mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
Preliminary implementation of ZAS as a StonedMC subsystem.
* Creates the SSair subsystem which replaces the Setup, Start(), and Tick() procs of air_master. * It may be best to have SSair completely replace air_master, but for now we are having them work together. It does completely replace the old processScheduer air ticker however. * Remove the obsolete Setup and Tick procs. * Adjust admin and debug verbs that dealt with some ZAS internals to work with the new implementation.
This commit is contained in:
@@ -80,166 +80,9 @@ Class Procs:
|
||||
/datum/controller/air_system/var/active_zones = 0
|
||||
|
||||
/datum/controller/air_system/var/current_cycle = 0
|
||||
/datum/controller/air_system/var/update_delay = 5 //How long between check should it try to process atmos again.
|
||||
/datum/controller/air_system/var/failed_ticks = 0 //How many ticks have runtimed?
|
||||
|
||||
/datum/controller/air_system/var/tick_progress = 0
|
||||
|
||||
/datum/controller/air_system/var/next_id = 1 //Used to keep track of zone UIDs.
|
||||
|
||||
/datum/controller/air_system/proc/Setup()
|
||||
//Purpose: Call this at the start to setup air groups geometry
|
||||
// (Warning: Very processor intensive but only must be done once per round)
|
||||
//Called by: Gameticker/Master controller
|
||||
//Inputs: None.
|
||||
//Outputs: None.
|
||||
|
||||
#ifndef ZASDBG
|
||||
set background = 1
|
||||
#endif
|
||||
|
||||
admin_notice("<span class='danger'>Processing Geometry...</span>", R_DEBUG)
|
||||
sleep(-1)
|
||||
|
||||
var/start_time = world.timeofday
|
||||
|
||||
var/simulated_turf_count = 0
|
||||
|
||||
for(var/turf/simulated/S in world)
|
||||
simulated_turf_count++
|
||||
S.update_air_properties()
|
||||
|
||||
admin_notice({"<span class='danger'>Geometry initialized in [round(0.1*(world.timeofday-start_time),0.1)] seconds.</span>
|
||||
<span class='info'>
|
||||
Total Simulated Turfs: [simulated_turf_count]
|
||||
Total Zones: [zones.len]
|
||||
Total Edges: [edges.len]
|
||||
Total Active Edges: [active_edges.len ? "<span class='danger'>[active_edges.len]</span>" : "None"]
|
||||
Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_count]
|
||||
</span>"}, R_DEBUG)
|
||||
|
||||
// Uncomment this if you're having problems finding where active edges are.
|
||||
/*
|
||||
for(var/connection_edge/E in active_edges)
|
||||
world << "Edge became active: [E]."
|
||||
var/i = 1
|
||||
for(var/turf/T in E.connecting_turfs)
|
||||
world << "[i] [T]:[T.x],[T.y],[T.z]"
|
||||
i++
|
||||
*/
|
||||
|
||||
|
||||
// spawn Start()
|
||||
|
||||
|
||||
/datum/controller/air_system/proc/Start()
|
||||
//Purpose: This is kicked off by the master controller, and controls the processing of all atmosphere.
|
||||
//Called by: Master controller
|
||||
//Inputs: None.
|
||||
//Outputs: None.
|
||||
|
||||
#ifndef ZASDBG
|
||||
set background = 1
|
||||
#endif
|
||||
|
||||
while(1)
|
||||
Tick()
|
||||
sleep(max(5,update_delay*tick_multiplier))
|
||||
|
||||
|
||||
/datum/controller/air_system/proc/Tick()
|
||||
. = 1 //Set the default return value, for runtime detection.
|
||||
|
||||
current_cycle++
|
||||
|
||||
//If there are tiles to update, do so.
|
||||
tick_progress = "updating turf properties"
|
||||
|
||||
var/list/updating
|
||||
|
||||
if(tiles_to_update.len)
|
||||
updating = tiles_to_update
|
||||
tiles_to_update = list()
|
||||
|
||||
#ifdef ZASDBG
|
||||
var/updated = 0
|
||||
#endif
|
||||
|
||||
//defer updating of self-zone-blocked turfs until after all other turfs have been updated.
|
||||
//this hopefully ensures that non-self-zone-blocked turfs adjacent to self-zone-blocked ones
|
||||
//have valid zones when the self-zone-blocked turfs update.
|
||||
|
||||
//This ensures that doorways don't form their own single-turf zones, since doorways are self-zone-blocked and
|
||||
//can merge with an adjacent zone, whereas zones that are formed on adjacent turfs cannot merge with the doorway.
|
||||
var/list/deferred = list()
|
||||
|
||||
for(var/turf/T in updating)
|
||||
//check if the turf is self-zone-blocked
|
||||
if(T.c_airblock(T) & ZONE_BLOCKED)
|
||||
deferred += T
|
||||
continue
|
||||
|
||||
T.update_air_properties()
|
||||
T.post_update_air_properties()
|
||||
T.needs_air_update = 0
|
||||
#ifdef ZASDBG
|
||||
T.overlays -= mark
|
||||
updated++
|
||||
#endif
|
||||
//sleep(1)
|
||||
|
||||
for(var/turf/T in deferred)
|
||||
T.update_air_properties()
|
||||
T.post_update_air_properties()
|
||||
T.needs_air_update = 0
|
||||
#ifdef ZASDBG
|
||||
T.overlays -= mark
|
||||
updated++
|
||||
#endif
|
||||
|
||||
#ifdef ZASDBG
|
||||
if(updated != updating.len)
|
||||
tick_progress = "[updating.len - updated] tiles left unupdated."
|
||||
world << "<span class='danger'>[tick_progress]</span>"
|
||||
. = 0
|
||||
#endif
|
||||
|
||||
//Where gas exchange happens.
|
||||
if(.)
|
||||
tick_progress = "processing edges"
|
||||
|
||||
for(var/connection_edge/edge in active_edges)
|
||||
edge.tick()
|
||||
|
||||
//Process fire zones.
|
||||
if(.)
|
||||
tick_progress = "processing fire zones"
|
||||
|
||||
for(var/zone/Z in active_fire_zones)
|
||||
Z.process_fire()
|
||||
|
||||
//Process hotspots.
|
||||
if(.)
|
||||
tick_progress = "processing hotspots"
|
||||
|
||||
for(var/obj/fire/fire in active_hotspots)
|
||||
fire.process()
|
||||
|
||||
//Process zones.
|
||||
if(.)
|
||||
tick_progress = "updating zones"
|
||||
|
||||
active_zones = zones_to_update.len
|
||||
if(zones_to_update.len)
|
||||
updating = zones_to_update
|
||||
zones_to_update = list()
|
||||
for(var/zone/zone in updating)
|
||||
zone.tick()
|
||||
zone.needs_update = 0
|
||||
|
||||
if(.)
|
||||
tick_progress = "success"
|
||||
|
||||
/datum/controller/air_system/proc/add_zone(zone/z)
|
||||
zones.Add(z)
|
||||
z.name = "Zone [next_id++]"
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
client/proc/ZoneTick()
|
||||
set category = "Debug"
|
||||
set name = "Process Atmos"
|
||||
set desc = "Manually run a single tick of the air subsystem"
|
||||
|
||||
// TODO - This might be a useful diagnostic tool. However its complicated to do with StonedMC
|
||||
// Therefore it is left unimplemented for now until its use actually becomes required. ~Leshana
|
||||
/*
|
||||
if(!check_rights(R_DEBUG)) return
|
||||
|
||||
var/result = air_master.Tick()
|
||||
if(result)
|
||||
@@ -8,7 +14,7 @@ client/proc/ZoneTick()
|
||||
|
||||
else
|
||||
src << "Failed to process! ([air_master.tick_progress])"
|
||||
|
||||
*/
|
||||
|
||||
client/proc/Zone_Info(turf/T as null|turf)
|
||||
set category = "Debug"
|
||||
|
||||
@@ -26,11 +26,3 @@ Notes for people who used ZAS before:
|
||||
var/zone/connected_zone = edge.get_connected_zone(zone)
|
||||
|
||||
*/
|
||||
|
||||
//#define ZASDBG
|
||||
#define MULTIZAS
|
||||
#define AIR_BLOCKED 1
|
||||
#define ZONE_BLOCKED 2
|
||||
#define BLOCKED 3
|
||||
|
||||
#define ZONE_MIN_SIZE 14 //zones with less than this many turfs will always merge, even if the connection is not direct
|
||||
|
||||
6
code/__defines/ZAS.dm
Normal file
6
code/__defines/ZAS.dm
Normal file
@@ -0,0 +1,6 @@
|
||||
// Bitflag values for c_airblock()
|
||||
#define AIR_BLOCKED 1 // Blocked
|
||||
#define ZONE_BLOCKED 2 // Not blocked, but zone boundaries will not cross.
|
||||
#define BLOCKED 3 // Blocked, zone boundaries will not cross even if opened.
|
||||
|
||||
#define ZONE_MIN_SIZE 14 // Zones with less than this many turfs will always merge, even if the connection is not direct
|
||||
@@ -7,6 +7,10 @@
|
||||
2 for preloading absolutely everything;
|
||||
*/
|
||||
|
||||
// ZAS Compile Options
|
||||
//#define ZASDBG // Uncomment to turn on super detailed ZAS debugging that probably won't even compile.
|
||||
#define MULTIZAS // Uncomment to turn on Multi-Z ZAS Support!
|
||||
|
||||
// If we are doing the map test build, do not include the main maps, only the submaps.
|
||||
#if MAP_TEST
|
||||
#define USING_MAP_DATUM /datum/map
|
||||
|
||||
@@ -17,3 +17,4 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
|
||||
// The numbers just define the ordering, they are meaningless otherwise.
|
||||
#define INIT_ORDER_MACHINES 10
|
||||
#define INIT_ORDER_LIGHTING 0
|
||||
#define INIT_ORDER_AIR -1
|
||||
|
||||
@@ -88,6 +88,10 @@
|
||||
/proc/log_unit_test(text)
|
||||
world.log << "## UNIT_TEST: [text]"
|
||||
|
||||
/proc/report_progress(var/progress_message)
|
||||
admin_notice("<span class='boldannounce'>[progress_message]</span>", R_DEBUG)
|
||||
to_world_log(progress_message)
|
||||
|
||||
//pretty print a direction bitflag, can be useful for debugging.
|
||||
/proc/print_dir(var/dir)
|
||||
var/list/comps = list()
|
||||
|
||||
@@ -573,14 +573,11 @@ var/datum/controller/master/Master = new()
|
||||
var/datum/controller/subsystem/SS = S
|
||||
SS.StartLoadingMap()
|
||||
|
||||
// ZAS might displace objects as the map loads if an air tick is processed mid-load.
|
||||
air_processing_killed = TRUE
|
||||
map_loading = TRUE
|
||||
|
||||
/datum/controller/master/StopLoadingMap(var/quiet = TRUE)
|
||||
if(!quiet)
|
||||
admin_notice("<span class='danger'>Map is finished. Unlocking.</span>", R_DEBUG)
|
||||
air_processing_killed = FALSE
|
||||
map_loading = FALSE
|
||||
for(var/S in subsystems)
|
||||
var/datum/controller/subsystem/SS = S
|
||||
|
||||
@@ -11,7 +11,6 @@ var/global/datum/controller/game_controller/master_controller //Set in world.New
|
||||
var/global/controller_iteration = 0
|
||||
var/global/last_tick_duration = 0
|
||||
|
||||
var/global/air_processing_killed = 0
|
||||
var/global/pipe_processing_killed = 0
|
||||
|
||||
datum/controller/game_controller
|
||||
|
||||
278
code/controllers/subsystems/air.dm
Normal file
278
code/controllers/subsystems/air.dm
Normal file
@@ -0,0 +1,278 @@
|
||||
// Air update stages
|
||||
#define SSAIR_TURFS 1
|
||||
#define SSAIR_EDGES 2
|
||||
#define SSAIR_FIREZONES 3
|
||||
#define SSAIR_HOTSPOTS 4
|
||||
#define SSAIR_ZONES 5
|
||||
#define SSAIR_DONE 6
|
||||
|
||||
SUBSYSTEM_DEF(air)
|
||||
name = "Air"
|
||||
init_order = INIT_ORDER_AIR
|
||||
priority = 20
|
||||
wait = 2 SECONDS // seconds (We probably can speed this up actually)
|
||||
flags = SS_BACKGROUND // TODO - Should this really be background? It might be important.
|
||||
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
|
||||
var/static/list/part_names = list("turfs", "edges", "fire zones", "hotspots", "zones")
|
||||
|
||||
var/cost_turfs = 0
|
||||
var/cost_edges = 0
|
||||
var/cost_firezones = 0
|
||||
var/cost_hotspots = 0
|
||||
var/cost_zones = 0
|
||||
|
||||
var/list/currentrun = null
|
||||
var/current_step = null
|
||||
|
||||
// Updating zone tiles requires temporary storage location of self-zone-blocked turfs across resumes. Used only by process_tiles_to_update.
|
||||
var/list/selfblock_deferred = null
|
||||
|
||||
/datum/controller/subsystem/air/PreInit()
|
||||
// Initialize the singleton /datum/controller/air_system
|
||||
// TODO - We could actually incorporate that into this subsystem! But in the spirit of not fucking with ZAS more than necessary, lets not for now. ~Leshana
|
||||
air_master = new()
|
||||
|
||||
/datum/controller/subsystem/air/Initialize(timeofday)
|
||||
report_progress("Processing Geometry...")
|
||||
|
||||
var/simulated_turf_count = 0
|
||||
for(var/turf/simulated/S in world)
|
||||
simulated_turf_count++
|
||||
S.update_air_properties()
|
||||
CHECK_TICK
|
||||
|
||||
admin_notice({"<span class='danger'>Geometry initialized in [round(0.1*(REALTIMEOFDAY-timeofday),0.1)] seconds.</span>
|
||||
<span class='info'>
|
||||
Total Simulated Turfs: [simulated_turf_count]
|
||||
Total Zones: [air_master.zones.len]
|
||||
Total Edges: [air_master.edges.len]
|
||||
Total Active Edges: [air_master.active_edges.len ? "<span class='danger'>[air_master.active_edges.len]</span>" : "None"]
|
||||
Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_count]
|
||||
</span>"}, R_DEBUG)
|
||||
|
||||
// Note - Baystation settles the air by running for one tick. We prefer to not have active edges.
|
||||
// Maps should not have active edges on boot. If we've got some, log it so it can get fixed.
|
||||
if(air_master.active_edges.len)
|
||||
var/list/edge_log = list()
|
||||
for(var/connection_edge/E in air_master.active_edges)
|
||||
edge_log += "Active Edge [E] ([E.type])"
|
||||
for(var/turf/T in E.connecting_turfs)
|
||||
edge_log += "+--- Connecting Turf [T] @ [T.x], [T.y], [T.z]"
|
||||
log_debug("Active Edges on ZAS Startup\n" + edge_log.Join("\n"))
|
||||
|
||||
..()
|
||||
|
||||
/datum/controller/subsystem/air/fire(resumed = 0)
|
||||
var/timer
|
||||
if(!resumed)
|
||||
ASSERT(LAZYLEN(currentrun) == 0) // Santity checks to make sure we don't somehow have items left over from last cycle
|
||||
ASSERT(current_step == null) // Or somehow didn't finish all the steps from last cycle
|
||||
air_master.current_cycle++ // Begin a new air_master cycle!
|
||||
current_step = SSAIR_TURFS // Start with Step 1 of course
|
||||
|
||||
INTERNAL_PROCESS_STEP(SSAIR_TURFS, TRUE, process_tiles_to_update, cost_turfs, SSAIR_EDGES)
|
||||
INTERNAL_PROCESS_STEP(SSAIR_EDGES, FALSE, process_active_edges, cost_edges, SSAIR_FIREZONES)
|
||||
INTERNAL_PROCESS_STEP(SSAIR_FIREZONES, FALSE, process_active_fire_zones, cost_firezones, SSAIR_HOTSPOTS)
|
||||
INTERNAL_PROCESS_STEP(SSAIR_HOTSPOTS, FALSE, process_active_hotspots, cost_hotspots, SSAIR_ZONES)
|
||||
INTERNAL_PROCESS_STEP(SSAIR_ZONES, FALSE, process_zones_to_update, cost_zones, SSAIR_DONE)
|
||||
|
||||
// Okay, we're done! Woo! Got thru a whole air_master cycle!
|
||||
ASSERT(LAZYLEN(currentrun) == 0) // Sanity checks to make sure there are really none left
|
||||
ASSERT(current_step == SSAIR_DONE) // And that we didn't somehow skip past the last step
|
||||
currentrun = null
|
||||
current_step = null
|
||||
|
||||
/datum/controller/subsystem/air/proc/process_tiles_to_update(resumed = 0)
|
||||
if (!resumed)
|
||||
// NOT a copy, because we are supposed to drain active turfs each cycle anyway, so just replace with empty list.
|
||||
// We still use a separate list tho, to ensure we don't process a turf twice during a single cycle!
|
||||
src.currentrun = air_master.tiles_to_update
|
||||
air_master.tiles_to_update = list()
|
||||
|
||||
//defer updating of self-zone-blocked turfs until after all other turfs have been updated.
|
||||
//this hopefully ensures that non-self-zone-blocked turfs adjacent to self-zone-blocked ones
|
||||
//have valid zones when the self-zone-blocked turfs update.
|
||||
//This ensures that doorways don't form their own single-turf zones, since doorways are self-zone-blocked and
|
||||
//can merge with an adjacent zone, whereas zones that are formed on adjacent turfs cannot merge with the doorway.
|
||||
ASSERT(src.selfblock_deferred == null) // Sanity check to make sure it was not remaining from last cycle somehow.
|
||||
src.selfblock_deferred = list()
|
||||
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
var/list/selfblock_deferred = src.selfblock_deferred
|
||||
|
||||
// Run thru the list, processing non-self-zone-blocked and deferring self-zone-blocked
|
||||
while(currentrun.len)
|
||||
var/turf/T = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
//check if the turf is self-zone-blocked
|
||||
if(T.c_airblock(T) & ZONE_BLOCKED)
|
||||
selfblock_deferred += T
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
else
|
||||
continue
|
||||
T.update_air_properties()
|
||||
T.post_update_air_properties()
|
||||
T.needs_air_update = 0
|
||||
#ifdef ZASDBG
|
||||
T.overlays -= mark
|
||||
#endif
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
ASSERT(LAZYLEN(currentrun) == 0)
|
||||
|
||||
// Run thru the deferred list and processing them
|
||||
while(selfblock_deferred.len)
|
||||
var/turf/T = selfblock_deferred[selfblock_deferred.len]
|
||||
selfblock_deferred.len--
|
||||
T.update_air_properties()
|
||||
T.post_update_air_properties()
|
||||
T.needs_air_update = 0
|
||||
#ifdef ZASDBG
|
||||
T.overlays -= mark
|
||||
#endif
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
ASSERT(LAZYLEN(selfblock_deferred) == 0)
|
||||
src.selfblock_deferred = null
|
||||
|
||||
/datum/controller/subsystem/air/proc/process_active_edges(resumed = 0)
|
||||
if (!resumed)
|
||||
src.currentrun = air_master.active_edges.Copy()
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
while(currentrun.len)
|
||||
var/connection_edge/edge = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if(edge) // TODO - Do we need to check this? Old one didn't, but old one was single-threaded.
|
||||
edge.tick()
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
/datum/controller/subsystem/air/proc/process_active_fire_zones(resumed = 0)
|
||||
if (!resumed)
|
||||
src.currentrun = air_master.active_fire_zones.Copy()
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
while(currentrun.len)
|
||||
var/zone/Z = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if(Z) // TODO - Do we need to check this? Old one didn't, but old one was single-threaded.
|
||||
Z.process_fire()
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
/datum/controller/subsystem/air/proc/process_active_hotspots(resumed = 0)
|
||||
if (!resumed)
|
||||
src.currentrun = air_master.active_hotspots.Copy()
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
while(currentrun.len)
|
||||
var/obj/fire/fire = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if(fire) // TODO - Do we need to check this? Old one didn't, but old one was single-threaded.
|
||||
fire.process()
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
/datum/controller/subsystem/air/proc/process_zones_to_update(resumed = 0)
|
||||
if (!resumed)
|
||||
air_master.active_zones = air_master.zones_to_update.len // Save how many zones there were to update this cycle (used by some debugging stuff)
|
||||
if(!air_master.zones_to_update.len)
|
||||
return // Nothing to do here this cycle!
|
||||
// NOT a copy, because we are supposed to drain active turfs each cycle anyway, so just replace with empty list.
|
||||
// Blanking the public list means we actually are removing processed ones from the list! Maybe we could we use zones_for_update directly?
|
||||
// But if we dom any zones added to zones_to_update DURING this step will get processed again during this step.
|
||||
// I don't know if that actually happens? But if it does, it could lead to an infinate loop. Better preserve original semantics.
|
||||
src.currentrun = air_master.zones_to_update
|
||||
air_master.zones_to_update = list()
|
||||
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
while(currentrun.len)
|
||||
var/zone/zone = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if(zone) // TODO - Do we need to check this? Old one didn't, but old one was single-threaded.
|
||||
zone.tick()
|
||||
zone.needs_update = 0
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
/datum/controller/subsystem/air/stat_entry(msg_prefix)
|
||||
var/list/msg = list(msg_prefix)
|
||||
msg += "S:[current_step ? part_names[current_step] : ""] "
|
||||
msg += "C:{"
|
||||
msg += "T [round(cost_turfs, 1)] | "
|
||||
msg += "E [round(cost_edges, 1)] | "
|
||||
msg += "F [round(cost_firezones, 1)] | "
|
||||
msg += "H [round(cost_hotspots, 1)] | "
|
||||
msg += "Z [round(cost_zones, 1)] "
|
||||
msg += "}"
|
||||
if(air_master)
|
||||
msg += "T:[round((cost ? air_master.tiles_to_update.len/cost : 0), 0.1)]"
|
||||
..(msg.Join())
|
||||
if(air_master)
|
||||
air_master.stat_entry()
|
||||
|
||||
|
||||
// Since air_master is still a separate controller from SSAir (Wait, why is that again? Get on that...)
|
||||
// I want it showing up in the statpanel too. We'll just hack it in as a separate line for now.
|
||||
/datum/controller/air_system/stat_entry()
|
||||
if(!statclick)
|
||||
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
|
||||
|
||||
var/title = " air_master"
|
||||
var/list/msg = list()
|
||||
msg += "Zones: [zones.len] "
|
||||
msg += "Edges: [edges.len] "
|
||||
msg += "Cycle: [current_cycle] {"
|
||||
msg += "T [tiles_to_update.len] | "
|
||||
msg += "E [active_edges.len] | "
|
||||
msg += "F [active_fire_zones.len] | "
|
||||
msg += "H [active_hotspots.len] | "
|
||||
msg += "Z [zones_to_update.len] "
|
||||
msg += "}"
|
||||
|
||||
stat(title, statclick.update(msg.Join()))
|
||||
|
||||
// ZAS might displace objects as the map loads if an air tick is processed mid-load.
|
||||
/datum/controller/subsystem/air/StartLoadingMap(var/quiet = TRUE)
|
||||
can_fire = FALSE
|
||||
. = ..()
|
||||
|
||||
/datum/controller/subsystem/air/StopLoadingMap(var/quiet = TRUE)
|
||||
can_fire = TRUE
|
||||
. = ..()
|
||||
|
||||
// Reboot the air master. A bit hacky right now, but sometimes necessary still.
|
||||
// TODO - Make this better by SSair and air_master together, then just reboot SSair
|
||||
/datum/controller/subsystem/air/proc/RebootZAS()
|
||||
can_fire = FALSE // Pause processing while we reboot
|
||||
// If we should happen to be in the middle of processing... wait until that finishes.
|
||||
if (state != SS_IDLE)
|
||||
report_progress("ZAS Rebuild initiated. Waiting for current air tick to complete before continuing.")
|
||||
while (state != SS_IDLE)
|
||||
stoplag()
|
||||
|
||||
var/datum/controller/air_system/old_air = global.air_master
|
||||
// Invalidate all zones
|
||||
for(var/zone/zone in old_air.zones)
|
||||
zone.c_invalidate()
|
||||
// Destroy the air_master and create a new one.
|
||||
qdel(old_air)
|
||||
global.air_master = new
|
||||
Initialize(REALTIMEOFDAY)
|
||||
|
||||
// Update next_fire so the MC doesn't try to make up for missed ticks.
|
||||
next_fire = world.time + wait
|
||||
can_fire = TRUE // Unpause
|
||||
|
||||
#undef SSAIR_TURFS
|
||||
#undef SSAIR_EDGES
|
||||
#undef SSAIR_FIREZONES
|
||||
#undef SSAIR_HOTSPOTS
|
||||
#undef SSAIR_ZONES
|
||||
#undef SSAIR_DONE
|
||||
@@ -779,11 +779,11 @@ var/list/admin_verbs_event_manager = list(
|
||||
set category = "Debug"
|
||||
set name = "Kill Air"
|
||||
set desc = "Toggle Air Processing"
|
||||
if(air_processing_killed)
|
||||
air_processing_killed = 0
|
||||
if(!SSair.can_fire)
|
||||
SSair.can_fire = TRUE
|
||||
usr << "<b>Enabled air processing.</b>"
|
||||
else
|
||||
air_processing_killed = 1
|
||||
SSair.can_fire = FALSE
|
||||
usr << "<b>Disabled air processing.</b>"
|
||||
feedback_add_details("admin_verb","KA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
log_admin("[key_name(usr)] used 'kill air'.")
|
||||
|
||||
@@ -45,10 +45,7 @@
|
||||
|
||||
usr << "\[4/5\] - All turfs reset to roundstart values."
|
||||
|
||||
qdel(air_master)
|
||||
air_master = new
|
||||
air_master.Setup()
|
||||
spawn air_master.Start()
|
||||
SSair.RebootZAS()
|
||||
|
||||
usr << "\[5/5\] - ZAS Rebooted"
|
||||
world << "<span class = 'danger'>Atmosphere restart completed in <b>[(world.timeofday - current_time)/10]</b> seconds.</span>"
|
||||
@@ -274,14 +274,7 @@ var/list/debug_verbs = list (
|
||||
set name = "Reboot ZAS"
|
||||
|
||||
if(alert("This will destroy and remake all zone geometry on the whole map.","Reboot ZAS","Reboot ZAS","Nevermind") == "Reboot ZAS")
|
||||
var/datum/controller/air_system/old_air = air_master
|
||||
for(var/zone/zone in old_air.zones)
|
||||
zone.c_invalidate()
|
||||
qdel(old_air)
|
||||
air_master = new
|
||||
air_master.Setup()
|
||||
spawn air_master.Start()
|
||||
|
||||
SSair.RebootZAS()
|
||||
|
||||
/client/proc/count_objects_on_z_level()
|
||||
set category = "Mapping"
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "code\__defines\turfs.dm"
|
||||
#include "code\__defines\unit_tests.dm"
|
||||
#include "code\__defines\xenoarcheaology.dm"
|
||||
#include "code\__defines\ZAS.dm"
|
||||
#include "code\_compatibility\509\_JSON.dm"
|
||||
#include "code\_compatibility\509\JSON Reader.dm"
|
||||
#include "code\_compatibility\509\JSON Writer.dm"
|
||||
@@ -151,7 +152,6 @@
|
||||
#include "code\controllers\verbs.dm"
|
||||
#include "code\controllers\voting.dm"
|
||||
#include "code\controllers\observer_listener\atom\observer.dm"
|
||||
#include "code\controllers\Processes\air.dm"
|
||||
#include "code\controllers\Processes\alarm.dm"
|
||||
#include "code\controllers\Processes\chemistry.dm"
|
||||
#include "code\controllers\Processes\emergencyShuttle.dm"
|
||||
@@ -172,6 +172,7 @@
|
||||
#include "code\controllers\Processes\vote.dm"
|
||||
#include "code\controllers\ProcessScheduler\core\process.dm"
|
||||
#include "code\controllers\ProcessScheduler\core\processScheduler.dm"
|
||||
#include "code\controllers\subsystems\air.dm"
|
||||
#include "code\controllers\subsystems\creation.dm"
|
||||
#include "code\controllers\subsystems\garbage.dm"
|
||||
#include "code\controllers\subsystems\lighting.dm"
|
||||
@@ -2376,7 +2377,6 @@
|
||||
#include "code\unit_tests\integrated_circuits\converter.dm"
|
||||
#include "code\unit_tests\integrated_circuits\logic.dm"
|
||||
#include "code\unit_tests\integrated_circuits\trig.dm"
|
||||
#include "code\ZAS\_docs.dm"
|
||||
#include "code\ZAS\Airflow.dm"
|
||||
#include "code\ZAS\Atom.dm"
|
||||
#include "code\ZAS\Connection.dm"
|
||||
|
||||
Reference in New Issue
Block a user