[MIRROR] Space/Changeturf fixes and optimizations [MDB IGNORE] (#19201)

Space/Changeturf fixes and optimizations

Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
Co-authored-by: GoldenAlpharex <jerego1234@hotmail.com>
Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com>
This commit is contained in:
SkyratBot
2023-02-28 21:23:35 +01:00
committed by GitHub
parent f558095a40
commit db33d75a5e
20 changed files with 231 additions and 120 deletions

View File

@@ -15,7 +15,7 @@
#define INIT_COST(costs, counting) \
var/list/_costs = costs; \
var/list/_counting = counting; \
var/usage = TICK_USAGE;
var/_usage = TICK_USAGE;
// STATIC cost tracking macro. Uses static lists instead of the normal global ones
// Good for debug stuff, and for running before globals init
@@ -31,16 +31,16 @@
costs = hidden_static_list_for_fun1; \
counting = hidden_static_list_for_fun2 ; \
} \
usage = TICK_USAGE;
_usage = TICK_USAGE;
#define SET_COST(category) \
do { \
var/cost = TICK_USAGE; \
_costs[category] += TICK_DELTA_TO_MS(cost - usage);\
var/_cost = TICK_USAGE; \
_costs[category] += TICK_DELTA_TO_MS(_cost - _usage);\
_counting[category] += 1; \
} while(FALSE); \
usage = TICK_USAGE;
_usage = TICK_USAGE;
#define SET_COST_LINE(...) SET_COST("[__LINE__]")
@@ -62,4 +62,5 @@
##proc(filename, costs, counts); \
} \
} \
} while (FALSE);
} while (FALSE); \
_usage = TICK_USAGE;

View File

@@ -348,19 +348,27 @@
///Returns the open turf next to the center in a specific direction
/proc/get_open_turf_in_dir(atom/center, dir)
var/turf/open/get_turf = get_ranged_target_turf(center, dir, 1)
var/turf/open/get_turf = get_step(center, dir)
if(istype(get_turf))
return get_turf
///Returns a list with all the adjacent open turfs. Clears the list of nulls in the end.
/proc/get_adjacent_open_turfs(atom/center)
. = list(
get_open_turf_in_dir(center, NORTH),
get_open_turf_in_dir(center, SOUTH),
get_open_turf_in_dir(center, EAST),
get_open_turf_in_dir(center, WEST)
)
list_clear_nulls(.)
var/list/hand_back = list()
// Inlined get_open_turf_in_dir, just to be fast
var/turf/open/new_turf = get_step(center, NORTH)
if(istype(new_turf))
hand_back += new_turf
new_turf = get_step(center, SOUTH)
if(istype(new_turf))
hand_back += new_turf
new_turf = get_step(center, EAST)
if(istype(new_turf))
hand_back += new_turf
new_turf = get_step(center, WEST)
if(istype(new_turf))
hand_back += new_turf
return hand_back
///Returns a list with all the adjacent areas by getting the adjacent open turfs
/proc/get_adjacent_open_areas(atom/center)

View File

@@ -148,13 +148,13 @@ SUBSYSTEM_DEF(mapping)
#endif
// Run map generation after ruin generation to prevent issues
run_map_generation()
// Add the transit level
transit = add_new_zlevel("Transit/Reserved", list(ZTRAIT_RESERVED = TRUE))
// Add the first transit level
var/datum/space_level/base_transit = add_reservation_zlevel()
require_area_resort()
// Set up Z-level transitions.
setup_map_transitions()
generate_station_area_list()
initialize_reserved_level(transit.z_value)
initialize_reserved_level(base_transit.z_value)
calculate_default_z_level_gravities()
return SS_INIT_SUCCESS
@@ -171,6 +171,7 @@ SUBSYSTEM_DEF(mapping)
var/packetlen = length(packet)
while(packetlen)
if(MC_TICK_CHECK)
if(index)
lists_to_reserve.Cut(1, index)
return
var/turf/T = packet[packetlen]
@@ -328,7 +329,6 @@ Used by the AI doomsday and the self-destruct nuke.
turf_reservations = SSmapping.turf_reservations
used_turfs = SSmapping.used_turfs
holodeck_templates = SSmapping.holodeck_templates
transit = SSmapping.transit
areas_in_z = SSmapping.areas_in_z
config = SSmapping.config
@@ -663,6 +663,12 @@ GLOBAL_LIST_EMPTY(the_station_areas)
message_admins("Loading [away_name] failed!")
return
/// Adds a new reservation z level. A bit of space that can be handed out on request
/// Of note, reservations default to transit turfs, to make their most common use, shuttles, faster
/datum/controller/subsystem/mapping/proc/add_reservation_zlevel(for_shuttles)
num_of_res_levels++
return add_new_zlevel("Transit/Reserved #[num_of_res_levels]", list(ZTRAIT_RESERVED = TRUE))
/datum/controller/subsystem/mapping/proc/RequestBlockReservation(width, height, z, type = /datum/turf_reservation, turf_type_override)
UNTIL((!z || reservation_ready["[z]"]) && !clearing_reserved_turfs)
var/datum/turf_reservation/reserve = new type
@@ -673,8 +679,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
if(reserve.Reserve(width, height, i))
return reserve
//If we didn't return at this point, theres a good chance we ran out of room on the exisiting reserved z levels, so lets try a new one
num_of_res_levels += 1
var/datum/space_level/newReserved = add_new_zlevel("Transit/Reserved [num_of_res_levels]", list(ZTRAIT_RESERVED = TRUE))
var/datum/space_level/newReserved = add_reservation_zlevel()
initialize_reserved_level(newReserved.z_value)
if(reserve.Reserve(width, height, newReserved.z_value))
return reserve
@@ -687,7 +692,9 @@ GLOBAL_LIST_EMPTY(the_station_areas)
return reserve
QDEL_NULL(reserve)
//This is not for wiping reserved levels, use wipe_reservations() for that.
///Sets up a z level as reserved
///This is not for wiping reserved levels, use wipe_reservations() for that.
///If this is called after SSatom init, it will call Initialize on all turfs on the passed z, as its name promises
/datum/controller/subsystem/mapping/proc/initialize_reserved_level(z)
UNTIL(!clearing_reserved_turfs) //regardless, lets add a check just in case.
clearing_reserved_turfs = TRUE //This operation will likely clear any existing reservations, so lets make sure nothing tries to make one while we're doing it.
@@ -697,11 +704,15 @@ GLOBAL_LIST_EMPTY(the_station_areas)
var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,z))
var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,z))
var/block = block(A, B)
for(var/t in block)
// No need to empty() these, because it's world init and they're
// already /turf/open/space/basic.
var/turf/T = t
for(var/turf/T as anything in block)
// No need to empty() these, because they just got created and are already /turf/open/space/basic.
T.flags_1 |= UNUSED_RESERVATION_TURF
CHECK_TICK
// Gotta create these suckers if we've not done so already
if(SSatoms.initialized)
SSatoms.InitializeAtoms(Z_TURFS(z))
unused_turfs["[z]"] = block
reservation_ready["[z]"] = TRUE
clearing_reserved_turfs = FALSE

View File

@@ -1,4 +1,10 @@
#define MAX_TRANSIT_REQUEST_RETRIES 10
/// How many turfs to allow before we stop blocking transit requests
#define MAX_TRANSIT_TILE_COUNT (150 ** 2)
/// How many turfs to allow before we start freeing up existing "soft reserved" transit docks
/// If we're under load we want to allow for cycling, but if not we want to preserve already generated docks for use
#define SOFT_TRANSIT_RESERVATION_THRESHOLD (100 ** 2)
SUBSYSTEM_DEF(shuttle)
name = "Shuttle"
@@ -25,6 +31,8 @@ SUBSYSTEM_DEF(shuttle)
var/list/transit_requesters = list()
/// An associative list of the mobile docking ports that have failed a transit request, with the amount of times they've actually failed that transit request, up to MAX_TRANSIT_REQUEST_RETRIES
var/list/transit_request_failures = list()
/// How many turfs our shuttles are currently utilizing in reservation space
var/transit_utilized = 0
/**
* Emergency shuttle stuff
@@ -192,6 +200,11 @@ SUBSYSTEM_DEF(shuttle)
// This next one removes transit docks/zones that aren't
// immediately being used. This will mean that the zone creation
// code will be running a lot.
// If we're below the soft reservation threshold, don't clear the old space
// We're better off holding onto it for now
if(transit_utilized < SOFT_TRANSIT_RESERVATION_THRESHOLD)
continue
var/obj/docking_port/mobile/owner = T.owner
if(owner)
var/idle = owner.mode == SHUTTLE_IDLE
@@ -204,7 +217,10 @@ SUBSYSTEM_DEF(shuttle)
if(!SSmapping.clearing_reserved_turfs)
while(transit_requesters.len)
var/requester = popleft(transit_requesters)
var/success = generate_transit_dock(requester)
var/success = null
// Do not try and generate any transit if we're using more then our max already
if(transit_utilized < MAX_TRANSIT_TILE_COUNT)
success = generate_transit_dock(requester)
if(!success) // BACK OF THE QUEUE
transit_request_failures[requester]++
if(transit_request_failures[requester] < MAX_TRANSIT_REQUEST_RETRIES)
@@ -619,6 +635,7 @@ SUBSYSTEM_DEF(shuttle)
var/turf/midpoint = locate(transit_x, transit_y, bottomleft.z)
if(!midpoint)
qdel(proposal)
return FALSE
var/area/old_area = midpoint.loc
old_area.turfs_to_uncontain += proposal.reserved_turfs
@@ -635,9 +652,18 @@ SUBSYSTEM_DEF(shuttle)
// Add 180, because ports point inwards, rather than outwards
new_transit_dock.setDir(angle2dir(dock_angle))
// Proposals use 2 extra hidden tiles of space, from the cordons that surround them
transit_utilized += (proposal.width + 2) * (proposal.height + 2)
M.assigned_transit = new_transit_dock
RegisterSignal(proposal, COMSIG_PARENT_QDELETING, PROC_REF(transit_space_clearing))
return new_transit_dock
/// Gotta manage our space brother
/datum/controller/subsystem/shuttle/proc/transit_space_clearing(datum/turf_reservation/source)
SIGNAL_HANDLER
transit_utilized -= (source.width + 2) * (source.height + 2)
/datum/controller/subsystem/shuttle/Recover()
initialized = SSshuttle.initialized
if (istype(SSshuttle.mobile_docking_ports))
@@ -856,7 +882,7 @@ SUBSYSTEM_DEF(shuttle)
/datum/controller/subsystem/shuttle/proc/load_template(datum/map_template/shuttle/loading_template)
. = FALSE
// Load shuttle template to a fresh block reservation.
preview_reservation = SSmapping.RequestBlockReservation(loading_template.width, loading_template.height, SSmapping.transit.z_value, /datum/turf_reservation/transit)
preview_reservation = SSmapping.RequestBlockReservation(loading_template.width, loading_template.height, type = /datum/turf_reservation/transit)
if(!preview_reservation)
CRASH("failed to reserve an area for shuttle template loading")
var/turf/bottom_left = TURF_FROM_COORDS_LIST(preview_reservation.bottom_left_coords)

View File

@@ -101,6 +101,7 @@
datum_flags &= ~DF_USE_TAG //In case something tries to REF us
weak_reference = null //ensure prompt GCing of weakref.
if(active_timers)
var/list/timers = active_timers
active_timers = null
for(var/datum/timedevent/timer as anything in timers)

View File

@@ -324,8 +324,9 @@
overlays.Cut()
LAZYNULL(managed_overlays)
if(ai_controller)
QDEL_NULL(ai_controller)
if(light)
QDEL_NULL(light)
if (length(light_sources))
light_sources.Cut()
@@ -1075,15 +1076,6 @@
/atom/proc/handle_atom_del(atom/deleting_atom)
SEND_SIGNAL(src, COMSIG_ATOM_CONTENTS_DEL, deleting_atom)
/**
* called when the turf the atom resides on is ChangeTurfed
*
* Default behaviour is to loop through atom contents and call their HandleTurfChange() proc
*/
/atom/proc/HandleTurfChange(turf/changing_turf)
for(var/atom/current_atom as anything in src)
current_atom.HandleTurfChange(changing_turf)
/**
* the vision impairment to give to the mob whose perspective is set to that atom
*

View File

@@ -244,11 +244,12 @@
if(!checked_turf)
continue
if(isclosedturf(checked_turf))
RegisterSignal(checked_turf, COMSIG_TURF_CHANGE, PROC_REF(adjacent_change))
RegisterSignal(checked_turf, COMSIG_TURF_EXPOSE, PROC_REF(process_results))
if(!isopenturf(checked_turf))
continue
process_results(checked_turf)
RegisterSignal(checked_turf, COMSIG_TURF_EXPOSE, PROC_REF(process_results))
/obj/machinery/door/firedoor/proc/unregister_adjacent_turfs(atom/old_loc)
if(!loc)
@@ -262,8 +263,14 @@
if(!checked_turf)
continue
UnregisterSignal(checked_turf, COMSIG_TURF_CHANGE)
UnregisterSignal(checked_turf, COMSIG_TURF_EXPOSE)
// If a turf adjacent to us changes, recalc our affecting areas when it's done yeah?
/obj/machinery/door/firedoor/proc/adjacent_change(turf/changed, path, list/new_baseturfs, flags, list/post_change_callbacks)
SIGNAL_HANDLER
post_change_callbacks += CALLBACK(src, PROC_REF(CalculateAffectingAreas))
/obj/machinery/door/firedoor/proc/check_atmos(turf/checked_turf)
var/datum/gas_mixture/environment = checked_turf.return_air()

View File

@@ -9,6 +9,10 @@
. = ..()
if(turf_loc_check && (!isturf(loc) || NeverShouldHaveComeHere(loc)))
return INITIALIZE_HINT_QDEL
var/static/list/loc_connections = list(
COMSIG_TURF_CHANGED = PROC_REF(handle_turf_change),
)
AddElement(/datum/element/connect_loc, loc_connections)
/obj/effect/decal/blob_act(obj/structure/blob/B)
if(B && B.loc == loc)
@@ -24,9 +28,12 @@
if(!(resistance_flags & FIRE_PROOF)) //non fire proof decal or being burned by lava
qdel(src)
/obj/effect/decal/HandleTurfChange(turf/T)
..()
if(T == loc && NeverShouldHaveComeHere(T))
/obj/effect/decal/proc/handle_turf_change(turf/source, path, list/new_baseturfs, flags, list/post_change_callbacks)
SIGNAL_HANDLER
post_change_callbacks += CALLBACK(src, PROC_REF(sanity_check_self))
/obj/effect/decal/proc/sanity_check_self(turf/changed)
if(changed == loc && NeverShouldHaveComeHere(changed))
qdel(src)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -82,8 +82,11 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
lgroup.remove_from_group(src)
//SKYRAT EDIT END
var/old_rcd_memory = rcd_memory
var/old_space_lit = space_lit
var/old_explosion_throw_details = explosion_throw_details
var/old_opacity = opacity
// I'm so sorry brother
// This is used for a starlight optimization
var/old_light_range = light_range
// We get just the bits of explosive_resistance that aren't the turf
var/old_explosive_resistance = explosive_resistance - get_explosive_block()
var/old_lattice_underneath = lattice_underneath
@@ -137,17 +140,13 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
lattice_underneath = old_lattice_underneath
var/area/our_area = new_turf.loc
if(new_turf.space_lit && !our_area.area_has_base_lighting)
// We are guarenteed to have these overlays because of how generation works
var/mutable_appearance/overlay = GLOB.fullbright_overlays[GET_TURF_PLANE_OFFSET(src) + 1]
new_turf.add_overlay(overlay)
else if (old_space_lit && !our_area.area_has_base_lighting)
var/mutable_appearance/overlay = GLOB.fullbright_overlays[GET_TURF_PLANE_OFFSET(src) + 1]
new_turf.cut_overlay(overlay)
if(SSlighting.initialized)
new_turf.lighting_object = old_lighting_object
// Space tiles should never have lighting objects
if(!space_lit)
// Should have a lighting object if we never had one
lighting_object = old_lighting_object || new /datum/lighting_object(src)
else if (old_lighting_object)
qdel(old_lighting_object, force = TRUE)
directional_opacity = old_directional_opacity
recalculate_directional_opacity()
@@ -155,8 +154,28 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
if(lighting_object && !lighting_object.needs_update)
lighting_object.update()
// If we're space, then we're either lit, or not, and impacting our neighbors, or not
if(isspaceturf(src) && CONFIG_GET(flag/starlight))
var/turf/open/space/lit_turf = src
// This also counts as a removal, so we need to do a full rebuild
if(!ispath(old_type, /turf/open/space))
lit_turf.update_starlight()
for(var/turf/open/space/space_tile in RANGE_TURFS(1, src) - src)
space_tile.update_starlight()
else if(old_light_range)
lit_turf.enable_starlight()
// If we're a cordon we count against a light, but also don't produce any ourselves
else if (istype(src, /turf/cordon) && CONFIG_GET(flag/starlight))
// This counts as removing a source of starlight, so we need to update the space tile to inform it
if(!ispath(old_type, /turf/open/space))
for(var/turf/open/space/space_tile in RANGE_TURFS(1, src))
space_tile.update_starlight()
// If we're not either, but were formerly a space turf, then we want light
else if(ispath(old_type, /turf/open/space) && CONFIG_GET(flag/starlight))
for(var/turf/open/space/space_tile in RANGE_TURFS(1, src))
space_tile.enable_starlight()
//SKYRAT EDIT ADDITION
if(old_liquids)
if(new_turf.liquids)
@@ -182,12 +201,17 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
qdel(old_liquids, TRUE)
//SKYRAT EDIT END
if(old_opacity != opacity && SSticker)
GLOB.cameranet.bareMajorChunkChange(src)
// We will only run this logic if the tile is not on the prime z layer, since we use area overlays to cover that
if(SSmapping.z_level_to_plane_offset[z])
var/area/our_area = new_turf.loc
if(our_area.lighting_effects)
new_turf.add_overlay(our_area.lighting_effects[SSmapping.z_level_to_plane_offset[z] + 1])
if(flags_1 & INITIALIZED_1) // only queue for smoothing if SSatom initialized us
// only queue for smoothing if SSatom initialized us, and we'd be changing smoothing state
if(flags_1 & INITIALIZED_1)
QUEUE_SMOOTH_NEIGHBORS(src)
QUEUE_SMOOTH(src)
@@ -224,6 +248,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
if(pollution)
qdel(pollution)
//SKYRAT EDIT END
if(excited || excited_group)
SSair.remove_from_active(src) //Clean up wall excitement, and refresh excited groups
if(ispath(path,/turf/closed) || ispath(path,/turf/cordon))
flags |= CHANGETURF_RECALC_ADJACENT
@@ -238,13 +263,6 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
SSair.add_to_active(src)
else //In effect, I want closed turfs to make their tile active when sheered, but we need to queue it since they have no adjacent turfs
CALCULATE_ADJACENT_TURFS(src, (!(ispath(oldType, /turf/closed) && isopenturf(src)) ? NORMAL_TURF : MAKE_ACTIVE))
//update firedoor adjacency
var/list/turfs_to_check = get_adjacent_open_turfs(src) | src
for(var/turf/check_turf in turfs_to_check)
for(var/obj/machinery/door/firedoor/FD in check_turf)
FD.CalculateAffectingAreas()
HandleTurfChange(src)
/turf/open/AfterChange(flags, oldType)
..()

View File

@@ -16,6 +16,8 @@
/turf/open/openspace/airless/planetary
planetary_atmos = TRUE
// Reminder, any behavior code written here needs to be duped to /turf/open/space/openspace
// I am so sorry
/turf/open/openspace/Initialize(mapload) // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
. = ..()
RegisterSignal(src, COMSIG_ATOM_INITIALIZED_ON, PROC_REF(on_atom_created))

View File

@@ -8,6 +8,7 @@
temperature = TCMB
thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
heat_capacity = 700000
var/starlight_source_count = 0
var/destination_z
var/destination_x
@@ -101,15 +102,23 @@
/turf/open/space/remove_air(amount)
return null
/// Updates starlight. Called when we're unsure of a turf's starlight state
/// Returns TRUE if we succeed, FALSE otherwise
/turf/open/space/proc/update_starlight()
if(CONFIG_GET(flag/starlight))
for(var/t in RANGE_TURFS(1,src)) //RANGE_TURFS is in code\__HELPERS\game.dm
if(isspaceturf(t))
// I've got a lot of cordons near spaceturfs, be good kids
if(isspaceturf(t) || istype(t, /turf/cordon))
//let's NOT update this that much pls
continue
set_light(2)
return
enable_starlight()
return TRUE
set_light(0)
return FALSE
/// Turns on the stars, if they aren't already
/turf/open/space/proc/enable_starlight()
if(!light_range)
set_light(2)
/turf/open/space/attack_paw(mob/user, list/modifiers)
return attack_hand(user, modifiers)
@@ -271,16 +280,25 @@
return TRUE
return FALSE
/turf/open/space/openspace/update_starlight()
if(!CONFIG_GET(flag/starlight))
return
/turf/open/space/openspace/enable_starlight()
var/turf/below = SSmapping.get_turf_below(src)
// Override = TRUE beacuse we could have our starlight updated many times without a failure, which'd trigger this
RegisterSignal(below, COMSIG_TURF_CHANGE, PROC_REF(on_below_change), override = TRUE)
if(!isspaceturf(below))
return
for(var/t in RANGE_TURFS(1,src)) //RANGE_TURFS is in code\__HELPERS\game.dm
if(isspaceturf(t))
//let's NOT update this that much pls
continue
set_light(2)
/turf/open/space/openspace/update_starlight()
. = ..()
if(.)
return
// If we're here, the starlight is not to be
var/turf/below = SSmapping.get_turf_below(src)
UnregisterSignal(below, COMSIG_TURF_CHANGE)
/turf/open/space/openspace/proc/on_below_change(turf/source, path, list/new_baseturfs, flags, list/post_change_callbacks)
SIGNAL_HANDLER
if(isspaceturf(source) && !ispath(path, /turf/open/space))
set_light(2)
else if(!isspaceturf(source) && ispath(path, /turf/open/space))
set_light(0)

View File

@@ -15,9 +15,10 @@
for(var/atom/movable/movable in src)
throw_atom(movable)
/turf/open/space/transit/clear_signal_refs()
/turf/open/space/transit/Destroy()
//Signals are NOT removed from turfs upon replacement, and we get replaced ALOT, so unregister our signal
UnregisterSignal(src, COMSIG_TURF_RESERVATION_RELEASED)
return ..()
/turf/open/space/transit/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
. = ..()

View File

@@ -147,10 +147,6 @@ GLOBAL_LIST_EMPTY(station_turfs)
if (smoothing_flags & (SMOOTH_CORNERS|SMOOTH_BITMASK))
QUEUE_SMOOTH(src)
// visibilityChanged() will never hit any path with side effects during mapload
if (!mapload)
visibilityChanged()
for(var/atom/movable/content as anything in src)
Entered(content, null)
@@ -186,6 +182,7 @@ GLOBAL_LIST_EMPTY(station_turfs)
if(!changing_turf)
stack_trace("Incorrect turf deletion")
changing_turf = FALSE
if(GET_LOWEST_STACK_OFFSET(z))
var/turf/T = SSmapping.get_turf_above(src)
if(T)
T.multiz_turf_del(src, DOWN)
@@ -199,7 +196,6 @@ GLOBAL_LIST_EMPTY(station_turfs)
for(var/A in B.contents)
qdel(A)
return
visibilityChanged()
QDEL_LIST(blueprint_data)
flags_1 &= ~INITIALIZED_1
requires_activation = FALSE

View File

@@ -28,9 +28,7 @@
/// Will update the light (duh).
/// Creates or destroys it if needed, makes it update values, makes sure it's got the correct source turf...
/atom/proc/update_light()
set waitfor = FALSE
if (QDELETED(src))
return
SHOULD_NOT_SLEEP(TRUE)
if(light_system != STATIC_LIGHT)
CRASH("update_light() for [src] with following light_system value: [light_system]")

View File

@@ -34,7 +34,7 @@ GLOBAL_LIST_EMPTY(default_lighting_underlays_by_z)
// Really this should be a global var or something, but lets not think about that yes?
if(CONFIG_GET(flag/starlight))
for(var/turf/open/space/space_tile in RANGE_TURFS(1, affected_turf))
space_tile.update_starlight()
space_tile.enable_starlight()
needs_update = TRUE
SSlighting.objects_queue += src

View File

@@ -7,6 +7,6 @@
for(var/turf/T as anything in A.get_contained_turfs())
if(T.space_lit)
continue
new/datum/lighting_object(T)
new /datum/lighting_object(T)
CHECK_TICK
CHECK_TICK

View File

@@ -14,7 +14,7 @@
if (lighting_object)
qdel(lighting_object, force=TRUE) //Shitty fix for lighting objects persisting after death
new/datum/lighting_object(src)
new /datum/lighting_object(src)
// Used to get a scaled lumcount.
/turf/proc/get_lumcount(minlum = 0, maxlum = 1)
@@ -81,6 +81,7 @@
reconsider_lights()
return
directional_opacity = NONE
if(opacity_sources)
for(var/atom/movable/opacity_source as anything in opacity_sources)
if(opacity_source.flags_1 & ON_BORDER_1)
directional_opacity |= opacity_source.dir
@@ -93,7 +94,7 @@
///Transfer the lighting of one area to another
/turf/proc/transfer_area_lighting(area/old_area, area/new_area)
if(SSlighting.initialized)
if(SSlighting.initialized && !space_lit)
if (new_area.static_lighting != old_area.static_lighting)
if (new_area.static_lighting)
lighting_build_overlay()
@@ -109,3 +110,7 @@
cut_overlay(old_area.lighting_effects[index])
if(new_area.lighting_effects)
add_overlay(new_area.lighting_effects[index])
// If we're changing into an area with no lighting, and we're lit, light ourselves
if(!new_area.lighting_effects && old_area.lighting_effects && space_lit)
overlays += GLOB.fullbright_overlays[GET_TURF_PLANE_OFFSET(src) + 1]

View File

@@ -800,11 +800,11 @@ GLOBAL_LIST_EMPTY(map_model_default)
//The next part of the code assumes there's ALWAYS an /area AND a /turf on a given tile
//first instance the /area and remove it from the members list
index = members.len
var/area/old_area
if(members[index] != /area/template_noop)
var/area/area_instance
if(members_attributes[index] != default_list)
world.preloader_setup(members_attributes[index], members[index])//preloader for assigning set variables on atom creation
area_instance = loaded_areas[members[index]]
var/area/area_instance = loaded_areas[members[index]]
if(!area_instance)
var/area_type = members[index]
// If this parsed map doesn't have that area already, we check the global cache
@@ -817,7 +817,7 @@ GLOBAL_LIST_EMPTY(map_model_default)
loaded_areas[area_type] = area_instance
if(!new_z)
var/area/old_area = crds.loc
old_area = crds.loc
old_area.turfs_to_uncontain += crds
area_instance.contained_turfs.Add(crds)
area_instance.contents.Add(crds)
@@ -845,6 +845,9 @@ GLOBAL_LIST_EMPTY(map_model_default)
if(GLOB.use_preloader && instance)//second preloader pass, for those atoms that don't ..() in New()
world.preloader_load(instance)
// If this isn't template work, we didn't change our turf and we changed area, then we've gotta handle area lighting transfer
else if(!no_changeturf && old_area)
crds.transfer_area_lighting(old_area, crds.loc)
MAPLOADING_CHECK_TICK
//finally instance all remainings objects/mobs

View File

@@ -19,6 +19,8 @@
manage_z_level(S, filled_with_space = FALSE)
generate_z_level_linkages() // Default Zs don't use add_new_zlevel() so they don't automatically generate z-linkages.
/// Generates a real, honest to god new z level. Will create the actual space, and also generate a datum that holds info about the new plot of land
/// Accepts the name, traits list, datum type, and if we should manage the turfs we create
/datum/controller/subsystem/mapping/proc/add_new_zlevel(name, traits = list(), z_type = /datum/space_level, contain_turfs = TRUE)
UNTIL(!adding_new_zlevel)
adding_new_zlevel = TRUE

View File

@@ -42,9 +42,12 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
/datum/cameranet/proc/chunkGenerated(x, y, z)
x = GET_CHUNK_COORD(x)
y = GET_CHUNK_COORD(y)
if(GET_LOWEST_STACK_OFFSET(z) != 0)
var/turf/lowest = get_lowest_turf(locate(x, y, z))
return chunks["[x],[y],[lowest.z]"]
return chunks["[x],[y],[z]"]
// Returns the chunk in the x, y, z.
// If there is no chunk, it creates a new chunk and returns that.
/datum/cameranet/proc/getCameraChunk(x, y, z)
@@ -150,6 +153,18 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
chunk.cameras["[T.z]"] |= c
chunk.hasChanged(update_delay_buffer = update_delay_buffer)
/// A faster, turf only version of [/datum/cameranet/proc/majorChunkChange]
/// For use in sensitive code, be careful with it
/datum/cameranet/proc/bareMajorChunkChange(turf/changed)
var/x1 = max(1, changed.x - (CHUNK_SIZE / 2))
var/y1 = max(1, changed.y - (CHUNK_SIZE / 2))
var/x2 = min(world.maxx, changed.x + (CHUNK_SIZE / 2))
var/y2 = min(world.maxy, changed.y + (CHUNK_SIZE / 2))
for(var/x = x1; x <= x2; x += CHUNK_SIZE)
for(var/y = y1; y <= y2; y += CHUNK_SIZE)
var/datum/camerachunk/chunk = chunkGenerated(x, y, changed.z)
chunk?.hasChanged()
/// Will check if a mob is on a viewable turf. Returns 1 if it is, otherwise returns 0.
/datum/cameranet/proc/checkCameraVis(mob/living/target)
var/turf/position = get_turf(target)