Fixes process_cell runtimes during lazyloading (#96367)

## About The Pull Request

I normally really don't like doing this but because this is so in the
weeds this is an alt pr.
Alt of #96366, I really don't want to add overhead to process_cell().

The issue here is when we request a reservation the turfs are empty()'d
which clears them out and places them in SSair's adjacent_turf recalc
queue (which will eventually cause an activation to clear out excited
groups).

We then immediately start maploading, which creates new, uninitialized
turfs (that remain in the queue because turf refs are based off position
instead of the actual datum). These unintialized turfs are able to
interact with the other, yet to be new()'d over turfs in the recalc
queue. This causes runtimes.

Later, while we initialize the turfs we loaded, we also have
interactions between initialized and uninitialized turfs, which also
causes runtimes.

The solution here is to prevent atmos processing in a loading template.
I do that here by first clearing out all relevant turfs from
atmos_adjacent_turf lists and deactivating them. We also have to clear
them from the recalc queue to prevent "fixing" this problem.

Then, after initialize is complete, we requeue them for recalcing, to
restore them to a workable state.

The underlying problem here is the logic of maploading is kind of
designed to run before everything else has initialized. It's something
we can dodge, but it will also show up in things that start processing
on initialize and expect their turf to immediately be ready for them. S
a bit of a mess.

Of note, it's technically possible for a turf to be initialized,
activate, and then attempt to process with an unitialized neighbor with
this solution. My gut fix for this would be using blocks_air to prevent
adjacent turfs from being recalculated until after InitializeAtoms is
finished, but that breaks turf/open/Initialize where we setup
gasmixtures, and I don't want to duplicate that code.

So we'll just bite the small risk of runtimes, they won't actually break
anything after all just make a bit of noise.
## Why It's Good For The Game

Closes #89649
This adds about 110ms of cost to loading the nukie station on my machine
(I used line by line macros around the two for loops), which is
significant but not huge, and it's cost that can be safely CHECK_TICK'd.
I think the cost of actually loading outweighs that significantly enough
(6.6s on my machine) that it's fine.

I prefer this solution to the alternative of adding guard checks to
process_cell because I do not want to add overhead to atmos code, and
also I don't like the idea that we cannot reliably prevent this (shuttle
code handles it effectively using blocks_air, as an example). Also, it
doesn't really resolve the uninitialized bit of this problem, which
isn't... good. Technically changes the math on share() too)
This commit is contained in:
LemonInTheDark
2026-06-08 03:36:44 +02:00
committed by GitHub
parent ce3a7c0756
commit 818008bca0
+15
View File
@@ -81,6 +81,17 @@
var/turf/bottom_left = reservation.bottom_left_turfs[z_idx]
var/turf/top_right = reservation.top_right_turfs[z_idx]
// Make our turfs dead to atmos
// Cache for sonic speed
var/list/to_rebuild = SSair.adjacent_rebuild
for(var/turf/contained_turf as anything in block(bottom_left, top_right))
SSair.remove_from_active(contained_turf)
to_rebuild -= contained_turf
for(var/turf/sub_turf as anything in contained_turf.atmos_adjacent_turfs)
sub_turf.atmos_adjacent_turfs?.Remove(contained_turf)
contained_turf.atmos_adjacent_turfs?.Cut()
CHECK_TICK
load_map(
file(load_path),
bottom_left.x,
@@ -104,6 +115,10 @@
loaded_atom_movables |= thing
SSatoms.InitializeAtoms(loaded_areas + loaded_atom_movables + loaded_turfs)
for(var/turf/turf as anything in loaded_turfs)
CALCULATE_ADJACENT_TURFS(turf, NORMAL_TURF)
CHECK_TICK
SSlighting.setup_static_lighting_if_needed(loaded_turfs)
SSmachines.setup_template_powernets(loaded_cables)
SSair.setup_template_machinery(loaded_atmospherics)