From 28b41d925ded8f234ae0bd7bdb5bdc15a55b10d2 Mon Sep 17 00:00:00 2001 From: Charlie Nolan Date: Tue, 21 Jan 2025 20:09:14 -0800 Subject: [PATCH] SSair correctness improvments (#28057) --- code/controllers/subsystem/SSair.dm | 55 ++++++++----------- code/game/turfs/turf.dm | 10 ++-- .../environmental/LINDA_turf_tile.dm | 6 +- .../atmospherics/gasmixtures/gas_mixture.dm | 1 + .../unary_devices/heat_exchanger.dm | 6 +- 5 files changed, 35 insertions(+), 43 deletions(-) diff --git a/code/controllers/subsystem/SSair.dm b/code/controllers/subsystem/SSair.dm index 9e7735c0872..435c0766588 100644 --- a/code/controllers/subsystem/SSair.dm +++ b/code/controllers/subsystem/SSair.dm @@ -17,6 +17,10 @@ SUBSYSTEM_DEF(air) flags = SS_BACKGROUND | SS_TICKER /// How long we actually wait between ticks. Will round up to the next server tick. var/self_wait = 0.15 SECONDS + /// MC seems to not be good at tracking whether SSair pauses, so track that ourselves. + var/was_paused = FALSE + /// And that means we also nee a replacement for times_fired. + var/milla_tick = 0 runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME offline_implications = "Turfs will no longer process atmos, and all atmospheric machines (including cryotubes) will no longer function. Shuttle call recommended." cpu_display = SS_CPUDISPLAY_HIGH @@ -186,6 +190,10 @@ SUBSYSTEM_DEF(air) currentpart = SSair.currentpart milla_idle = SSair.milla_idle +/datum/controller/subsystem/air/pause() + was_paused = TRUE + return ..() + /datum/controller/subsystem/air/fire(resumed = 0) // All atmos stuff assumes MILLA is synchronous. Ensure it actually is. var/now = world.timeofday + (world.tick_lag * world.tick_usage) / 100 @@ -200,12 +208,13 @@ SUBSYSTEM_DEF(air) // Run the sleepless callbacks again in case more showed up since on_milla_tick_finished() run_sleepless_callbacks() - fire_sleepless(resumed) + fire_sleepless(resumed || was_paused) /datum/controller/subsystem/air/proc/fire_sleepless(resumed) // Any proc that wants MILLA to be synchronous should not sleep. SHOULD_NOT_SLEEP(TRUE) in_milla_safe_code = TRUE + was_paused = FALSE var/timer = TICK_USAGE_REAL @@ -317,6 +326,7 @@ SUBSYSTEM_DEF(air) timer = TICK_USAGE_REAL spawn_milla_tick_thread() + milla_tick++ milla_idle = FALSE cost_milla_tick = MC_AVERAGE(cost_milla_tick, get_milla_tick_time()) @@ -415,9 +425,9 @@ SUBSYSTEM_DEF(air) // Bind the MILLA tile we got, if needed. if(isnull(T.bound_air)) bind_turf(T, milla_tile) - else if(T.bound_air.lastread < times_fired) + else if(T.bound_air.lastread < milla_tick) T.bound_air.copy_from_milla(milla_tile) - T.bound_air.lastread = times_fired + T.bound_air.lastread = milla_tick T.bound_air.readonly = null T.bound_air.dirty = FALSE T.bound_air.synchronized = FALSE @@ -446,7 +456,7 @@ SUBSYSTEM_DEF(air) if(isnull(S.wind_tick)) // Didn't have wind before, add it. windy_tiles += S - S.wind_tick = times_fired + S.wind_tick = milla_tick S.wind_x = x_flow S.wind_y = y_flow T.high_pressure_movements(x_flow, y_flow) @@ -463,15 +473,17 @@ SUBSYSTEM_DEF(air) var/list/currentrun = src.currentrun while(length(currentrun)) var/turf/simulated/S = currentrun[length(currentrun)] - currentrun.len-- if(!istype(S)) + currentrun.len-- continue if(S.update_hotspot()) // Is still a hotspot, keep it. new_hotspots += S + currentrun.len-- + if(MC_TICK_CHECK) return @@ -627,33 +639,12 @@ SUBSYSTEM_DEF(air) /datum/controller/subsystem/air/proc/setup_turfs(turf/low_corner = locate(1, 1, 1), turf/high_corner = locate(world.maxx, world.maxy, world.maxz)) for(var/turf/T as anything in block(low_corner, high_corner)) - T.Initialize_Atmos(times_fired) + T.Initialize_Atmos(milla_tick) milla_load_turfs(low_corner, high_corner) for(var/turf/T as anything in block(low_corner, high_corner)) T.milla_data.len = 0 T.milla_data = null -/datum/controller/subsystem/air/proc/setup_write_to_milla() - var/watch = start_watch() - log_startup_progress("Writing tiles to MILLA...") - - //cache for sanic speed (lists are references anyways) - var/list/cache = bound_mixtures - var/count = length(cache) - while(length(cache)) - var/datum/gas_mixture/bound_to_turf/mixture = cache[length(cache)] - cache.len-- - if(mixture.dirty) - in_milla_safe_code = TRUE - // This is one of two places expected to call this otherwise-unsafe method. - mixture.private_unsafe_write() - in_milla_safe_code = FALSE - mixture.bound_turf.bound_air = null - mixture.bound_turf = null - CHECK_TICK - - log_startup_progress("Wrote [count] tiles in [stop_watch(watch)]s.") - /datum/controller/subsystem/air/proc/setup_atmos_machinery(list/machines_to_init) var/watch = start_watch() log_startup_progress("Initializing atmospherics machinery...") @@ -713,7 +704,7 @@ SUBSYSTEM_DEF(air) milla_tile = new/list(MILLA_TILE_SIZE) get_tile_atmos(T, milla_tile) B.copy_from_milla(milla_tile) - B.lastread = src.times_fired + B.lastread = src.milla_tick B.readonly = null B.dirty = FALSE B.synchronized = FALSE @@ -832,11 +823,11 @@ SUBSYSTEM_DEF(air) soft_assert_safe() // This is one of two intended places to call this otherwise-unsafe proc. var/datum/gas_mixture/bound_to_turf/air = T.private_unsafe_get_air() - if(air.lastread < SSair.times_fired) + if(air.lastread < SSair.milla_tick) var/list/milla_tile = new/list(MILLA_TILE_SIZE) get_tile_atmos(T, milla_tile) air.copy_from_milla(milla_tile) - air.lastread = SSair.times_fired + air.lastread = SSair.milla_tick air.readonly = null air.dirty = FALSE if(!air.synchronized) @@ -882,11 +873,11 @@ SUBSYSTEM_DEF(air) soft_assert_safe() // This is one of two intended places to call this otherwise-unsafe proc. var/datum/gas_mixture/bound_to_turf/air = T.private_unsafe_get_air() - if(air.lastread < SSair.times_fired) + if(air.lastread < SSair.milla_tick) var/list/milla_tile = new/list(MILLA_TILE_SIZE) get_tile_atmos(T, milla_tile) air.copy_from_milla(milla_tile) - air.lastread = SSair.times_fired + air.lastread = SSair.milla_tick air.readonly = null air.dirty = FALSE if(!air.synchronized) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 765a74fed91..b2c02b58364 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -641,11 +641,11 @@ RETURN_TYPE(/datum/gas_mixture) // This is one of two intended places to call this otherwise-unsafe proc. var/datum/gas_mixture/bound_to_turf/air = private_unsafe_get_air() - if(air.lastread < SSair.times_fired) + if(air.lastread < SSair.milla_tick) var/list/milla_tile = new/list(MILLA_TILE_SIZE) get_tile_atmos(src, milla_tile) air.copy_from_milla(milla_tile) - air.lastread = SSair.times_fired + air.lastread = SSair.milla_tick air.readonly = null air.dirty = FALSE air.synchronized = FALSE @@ -678,7 +678,7 @@ return FALSE // If it's old, delete it. - if(active_hotspot.death_timer < SSair.times_fired) + if(active_hotspot.death_timer < SSair.milla_tick) QDEL_NULL(active_hotspot) return FALSE else @@ -687,7 +687,7 @@ if(isnull(active_hotspot)) active_hotspot = new(src) - active_hotspot.death_timer = SSair.times_fired + 4 + active_hotspot.death_timer = SSair.milla_tick + 4 if(air.hotspot_volume() > 0) active_hotspot.temperature = air.hotspot_temperature() active_hotspot.volume = air.hotspot_volume() * CELL_VOLUME @@ -699,7 +699,7 @@ return TRUE /turf/simulated/proc/update_wind() - if(wind_tick != SSair.times_fired) + if(wind_tick != SSair.milla_tick) QDEL_NULL(wind_effect) wind_tick = null return FALSE diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index 88277271929..a6d3b1aafe5 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -129,9 +129,9 @@ if(direction == 0) return - if(last_high_pressure_movement_time >= SSair.times_fired - 3) + if(last_high_pressure_movement_time >= SSair.milla_tick - 3) return - last_high_pressure_movement_time = SSair.times_fired + last_high_pressure_movement_time = SSair.milla_tick air_push(direction, (force - force_needed) / force_needed) @@ -171,7 +171,7 @@ #define INDEX_SOUTH 3 #define INDEX_WEST 4 -/turf/proc/Initialize_Atmos(times_fired) +/turf/proc/Initialize_Atmos(milla_tick) // This is one of two places expected to call this otherwise-unsafe method. var/list/connectivity = private_unsafe_recalculate_atmos_connectivity() var/list/air = list(oxygen, carbon_dioxide, nitrogen, toxins, sleeping_agent, agent_b, temperature) diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index e14706d7b26..510b981fcee 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -762,6 +762,7 @@ What are the archived variables for? #undef QUANTIZE /datum/gas_mixture/bound_to_turf + synchronized = FALSE var/dirty = FALSE var/lastread = 0 var/turf/bound_turf = null diff --git a/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm b/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm index 60a7a1187a7..6ed29994f36 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm @@ -32,11 +32,11 @@ if(!partner) return 0 - if(!SSair || SSair.times_fired <= update_cycle) + if(!SSair || SSair.milla_tick <= update_cycle) return 0 - update_cycle = SSair.times_fired - partner.update_cycle = SSair.times_fired + update_cycle = SSair.milla_tick + partner.update_cycle = SSair.milla_tick var/air_heat_capacity = air_contents.heat_capacity() var/other_air_heat_capacity = partner.air_contents.heat_capacity()