mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
Backports several SSmapping improvements (#17208)
* Optimizes SSmapping * Turfs inside area are stored https://github.com/tgstation/tgstation/pull/70966 * Add async reserving of turfs * Fix bug * Fix shuttle init
This commit is contained in:
@@ -351,7 +351,6 @@ SUBSYSTEM_DEF(air)
|
||||
queued_for_activation.Cut()
|
||||
|
||||
/datum/controller/subsystem/air/proc/setup_allturfs()
|
||||
var/list/turfs_to_init = block(locate(1, 1, 1), locate(world.maxx, world.maxy, world.maxz))
|
||||
var/list/active_turfs = src.active_turfs
|
||||
var/times_fired = ++src.times_fired
|
||||
|
||||
@@ -359,7 +358,7 @@ SUBSYSTEM_DEF(air)
|
||||
// one-by-one, and Initalize_Atmos only ever adds `src` back in.
|
||||
active_turfs.Cut()
|
||||
|
||||
for(var/thing in turfs_to_init)
|
||||
for(var/thing in ALL_TURFS())
|
||||
var/turf/T = thing
|
||||
if (T.blocks_air)
|
||||
continue
|
||||
|
||||
55
code/controllers/subsystem/area_contents.dm
Normal file
55
code/controllers/subsystem/area_contents.dm
Normal file
@@ -0,0 +1,55 @@
|
||||
#define ALLOWED_LOOSE_TURFS 500
|
||||
/**
|
||||
* Responsible for managing the sizes of area.contained_turfs and area.turfs_to_uncontain
|
||||
* These lists do not check for duplicates, which is fine, but it also means they can balloon in size over time
|
||||
* as a consequence of repeated changes in area in a space
|
||||
* They additionally may not always resolve often enough to avoid memory leaks
|
||||
* This is annoying, so lets keep an eye on them and cut them down to size if needed
|
||||
*/
|
||||
SUBSYSTEM_DEF(area_contents)
|
||||
name = "Area Contents"
|
||||
flags = SS_NO_INIT
|
||||
runlevels = RUNLEVEL_LOBBY|RUNLEVELS_DEFAULT
|
||||
var/list/currentrun
|
||||
var/list/area/marked_for_clearing = list()
|
||||
|
||||
/datum/controller/subsystem/area_contents/stat_entry(msg)
|
||||
var/total_clearing_from = 0
|
||||
var/total_to_clear = 0
|
||||
for(var/area/to_clear as anything in marked_for_clearing)
|
||||
total_to_clear += length(to_clear.turfs_to_uncontain)
|
||||
total_clearing_from += length(to_clear.contained_turfs)
|
||||
msg = "A:[length(currentrun)] MR:[length(marked_for_clearing)] TC:[total_to_clear] CF:[total_clearing_from]"
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/controller/subsystem/area_contents/fire(resumed)
|
||||
if(!resumed)
|
||||
currentrun = GLOB.areas.Copy()
|
||||
|
||||
while(length(currentrun))
|
||||
var/area/test = currentrun[length(currentrun)]
|
||||
if(length(test.turfs_to_uncontain) > ALLOWED_LOOSE_TURFS)
|
||||
marked_for_clearing |= test
|
||||
currentrun.len--
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
// Alright, if we've done a scan on all our areas, it's time to knock the existing ones down to size
|
||||
while(length(marked_for_clearing))
|
||||
var/area/clear = marked_for_clearing[length(marked_for_clearing)]
|
||||
|
||||
// The operation of cutting large lists can be expensive
|
||||
// It scales almost directly with the size of the list we're cutting with
|
||||
// Because of this, we're gonna stick to cutting 1 entry at a time
|
||||
// There's no reason to batch it I promise, this is faster. No overtime too
|
||||
var/amount_cut = 0
|
||||
var/list/cut_from = clear.turfs_to_uncontain
|
||||
for(amount_cut in 1 to length(cut_from))
|
||||
clear.contained_turfs -= cut_from[amount_cut]
|
||||
if(MC_TICK_CHECK)
|
||||
cut_from.Cut(1, amount_cut + 1)
|
||||
return
|
||||
|
||||
clear.turfs_to_uncontain = list()
|
||||
marked_for_clearing.len--
|
||||
@@ -1,7 +1,7 @@
|
||||
SUBSYSTEM_DEF(mapping)
|
||||
name = "Mapping"
|
||||
init_order = INIT_ORDER_MAPPING
|
||||
flags = SS_NO_FIRE
|
||||
runlevels = ALL
|
||||
|
||||
loading_points = 11 SECONDS // Yogs -- loading times
|
||||
|
||||
@@ -32,6 +32,8 @@ SUBSYSTEM_DEF(mapping)
|
||||
var/list/turf/unused_turfs = list() //Not actually unused turfs they're unused but reserved for use for whatever requests them. "[zlevel_of_turf]" = list(turfs)
|
||||
var/list/datum/turf_reservations //list of turf reservations
|
||||
var/list/used_turfs = list() //list of turf = datum/turf_reservation
|
||||
/// List of lists of turfs to reserve
|
||||
var/list/lists_to_reserve = list()
|
||||
|
||||
var/clearing_reserved_turfs = FALSE
|
||||
|
||||
@@ -63,7 +65,7 @@ SUBSYSTEM_DEF(mapping)
|
||||
to_chat(world, span_boldannounce("Unable to load next or default map config, defaulting to Box Station"))
|
||||
config = old_config
|
||||
loadWorld()
|
||||
repopulate_sorted_areas()
|
||||
require_area_resort()
|
||||
process_teleport_locs() //Sets up the wizard teleport locations
|
||||
preloadTemplates()
|
||||
run_map_generation()
|
||||
@@ -91,20 +93,20 @@ SUBSYSTEM_DEF(mapping)
|
||||
loading_ruins = TRUE
|
||||
var/list/lava_ruins = levels_by_trait(ZTRAIT_LAVA_RUINS)
|
||||
if (lava_ruins.len)
|
||||
seedRuins(lava_ruins, CONFIG_GET(number/lavaland_budget), list(/area/lavaland/surface/outdoors/unexplored), lava_ruins_templates)
|
||||
seedRuins(lava_ruins, CONFIG_GET(number/lavaland_budget), list(/area/lavaland/surface/outdoors/unexplored), lava_ruins_templates, clear_below = TRUE)
|
||||
for (var/lava_z in lava_ruins)
|
||||
spawn_rivers(lava_z)
|
||||
|
||||
var/list/ice_ruins = levels_by_trait(ZTRAIT_ICE_RUINS)
|
||||
if (ice_ruins.len)
|
||||
// needs to be whitelisted for underground too so place_below ruins work
|
||||
seedRuins(ice_ruins, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/surface/outdoors/unexplored, /area/icemoon/underground/unexplored), ice_ruins_templates)
|
||||
seedRuins(ice_ruins, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/surface/outdoors/unexplored, /area/icemoon/underground/unexplored), ice_ruins_templates, clear_below = TRUE)
|
||||
for(var/ice_z in ice_ruins)
|
||||
spawn_rivers(ice_z, 4, /turf/open/openspace/icemoon, /area/icemoon/surface/outdoors/unexplored)
|
||||
|
||||
var/list/ice_ruins_underground = levels_by_trait(ZTRAIT_ICE_RUINS_UNDERGROUND)
|
||||
if (ice_ruins_underground.len)
|
||||
seedRuins(ice_ruins_underground, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/underground/unexplored), ice_ruins_underground_templates)
|
||||
seedRuins(ice_ruins_underground, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/underground/unexplored), ice_ruins_underground_templates, clear_below = TRUE)
|
||||
for(var/ice_z in ice_ruins_underground)
|
||||
spawn_rivers(ice_z, 4, /turf/open/lava/plasma/ice_moon, /area/icemoon/underground/unexplored)
|
||||
|
||||
@@ -134,7 +136,7 @@ SUBSYSTEM_DEF(mapping)
|
||||
PM.initTemplateBounds()
|
||||
// Add the transit level
|
||||
transit = add_new_zlevel("Transit/Reserved", list(ZTRAIT_RESERVED = TRUE))
|
||||
repopulate_sorted_areas()
|
||||
require_area_resort()
|
||||
// Set up Z-level transitions.
|
||||
setup_map_transitions()
|
||||
generate_station_area_list()
|
||||
@@ -143,6 +145,35 @@ SUBSYSTEM_DEF(mapping)
|
||||
build_minimaps()
|
||||
return SS_INIT_SUCCESS
|
||||
|
||||
/datum/controller/subsystem/mapping/fire(resumed)
|
||||
// Cache for sonic speed
|
||||
var/list/unused_turfs = src.unused_turfs
|
||||
var/list/world_contents = GLOB.areas_by_type[world.area].contents
|
||||
var/list/world_turf_contents = GLOB.areas_by_type[world.area].contained_turfs
|
||||
var/list/lists_to_reserve = src.lists_to_reserve
|
||||
var/index = 0
|
||||
while(index < length(lists_to_reserve))
|
||||
var/list/packet = lists_to_reserve[index + 1]
|
||||
var/packetlen = length(packet)
|
||||
while(packetlen)
|
||||
if(MC_TICK_CHECK)
|
||||
lists_to_reserve.Cut(1, index)
|
||||
return
|
||||
var/turf/T = packet[packetlen]
|
||||
T.empty(RESERVED_TURF_TYPE, RESERVED_TURF_TYPE, null, TRUE)
|
||||
LAZYINITLIST(unused_turfs["[T.z]"])
|
||||
unused_turfs["[T.z]"] |= T
|
||||
var/area/old_area = T.loc
|
||||
old_area.turfs_to_uncontain += T
|
||||
T.flags_1 |= UNUSED_RESERVATION_TURF_1
|
||||
world_contents += T
|
||||
world_turf_contents += T
|
||||
packet.len--
|
||||
packetlen = length(packet)
|
||||
|
||||
index++
|
||||
lists_to_reserve.Cut(1, index)
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/wipe_reservations(wipe_safety_delay = 100)
|
||||
if(clearing_reserved_turfs || !initialized) //in either case this is just not needed.
|
||||
return
|
||||
@@ -250,13 +281,13 @@ SUBSYSTEM_DEF(mapping)
|
||||
var/start_z = world.maxz + 1
|
||||
var/i = 0
|
||||
for (var/level in traits)
|
||||
add_new_zlevel("[name][i ? " [i + 1]" : ""]", level)
|
||||
add_new_zlevel("[name][i ? " [i + 1]" : ""]", level, contain_turfs = FALSE)
|
||||
++i
|
||||
|
||||
// load the maps
|
||||
for (var/P in parsed_maps)
|
||||
var/datum/parsed_map/pm = P
|
||||
if (!pm.load(1, 1, start_z + parsed_maps[P], no_changeturf = TRUE))
|
||||
if (!pm.load(1, 1, start_z + parsed_maps[P], no_changeturf = TRUE, new_z = TRUE))
|
||||
errorList |= pm.original_path
|
||||
if(!silent)
|
||||
INIT_ANNOUNCE("Loaded [name] in [(REALTIMEOFDAY - start_time)/10]s!")
|
||||
@@ -310,7 +341,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/generate_station_area_list()
|
||||
var/list/station_areas_blacklist = typecacheof(list(/area/space, /area/mine, /area/ruin, /area/asteroid/nearstation))
|
||||
for(var/area/A in world)
|
||||
for(var/area/A in GLOB.areas)
|
||||
if (is_type_in_typecache(A, station_areas_blacklist))
|
||||
continue
|
||||
if (!A.contents.len || !A.unique)
|
||||
@@ -323,7 +354,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
log_world("ERROR: Station areas list failed to generate!")
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/run_map_generation()
|
||||
for(var/area/A in world)
|
||||
for(var/area/A as anything in GLOB.areas)
|
||||
A.RunGeneration()
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/maprotate()
|
||||
@@ -549,15 +580,12 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
unused_turfs["[i]"] = block
|
||||
clearing_reserved_turfs = FALSE
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/reserve_turfs(list/turfs)
|
||||
for(var/i in turfs)
|
||||
var/turf/T = i
|
||||
T.empty(RESERVED_TURF_TYPE, RESERVED_TURF_TYPE, null, TRUE)
|
||||
LAZYINITLIST(unused_turfs["[T.z]"])
|
||||
unused_turfs["[T.z]"] |= T
|
||||
T.flags_1 |= UNUSED_RESERVATION_TURF_1
|
||||
GLOB.areas_by_type[world.area].contents += T
|
||||
CHECK_TICK
|
||||
/// Schedules a group of turfs to be handed back to the reservation system's control
|
||||
/// If await is true, will sleep until the turfs are finished work
|
||||
/datum/controller/subsystem/mapping/proc/reserve_turfs(list/turfs, await = FALSE)
|
||||
lists_to_reserve += list(turfs)
|
||||
if(await)
|
||||
UNTIL(!length(turfs))
|
||||
|
||||
//DO NOT CALL THIS PROC DIRECTLY, CALL wipe_reservations().
|
||||
/datum/controller/subsystem/mapping/proc/do_wipe_turf_reservations()
|
||||
@@ -575,7 +603,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
clearing |= used_turfs //used turfs is an associative list, BUT, reserve_turfs() can still handle it. If the code above works properly, this won't even be needed as the turfs would be freed already.
|
||||
unused_turfs.Cut()
|
||||
used_turfs.Cut()
|
||||
reserve_turfs(clearing)
|
||||
reserve_turfs(clearing, await = TRUE)
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/build_minimaps()
|
||||
to_chat(world, span_boldannounce("Building minimaps..."))
|
||||
@@ -586,3 +614,15 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
for(var/B in areas)
|
||||
var/area/A = B
|
||||
A.reg_in_areas_in_z()
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/build_area_turfs(z_level, space_guaranteed)
|
||||
// If we know this is filled with default tiles, we can use the default area
|
||||
// Faster
|
||||
if(space_guaranteed)
|
||||
var/area/global_area = GLOB.areas_by_type[world.area]
|
||||
global_area.contained_turfs += Z_TURFS(z_level)
|
||||
return
|
||||
|
||||
for(var/turf/to_contain as anything in Z_TURFS(z_level))
|
||||
var/area/our_area = to_contain.loc
|
||||
our_area.contained_turfs += to_contain
|
||||
|
||||
@@ -516,9 +516,12 @@ SUBSYSTEM_DEF(shuttle)
|
||||
var/turf/midpoint = locate(transit_x, transit_y, bottomleft.z)
|
||||
if(!midpoint)
|
||||
return FALSE
|
||||
var/area/old_area = midpoint.loc
|
||||
old_area.turfs_to_uncontain += proposal.reserved_turfs
|
||||
var/area/shuttle/transit/A = new()
|
||||
A.parallax_movedir = travel_dir
|
||||
A.contents = proposal.reserved_turfs
|
||||
A.contained_turfs = proposal.reserved_turfs
|
||||
var/obj/docking_port/stationary/transit/new_transit_dock = new(midpoint)
|
||||
new_transit_dock.reserved_area = proposal
|
||||
new_transit_dock.name = "Transit for [M.id]/[M.name]"
|
||||
|
||||
Reference in New Issue
Block a user