mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-23 13:05:44 +01:00
Fix All Exoplanet Atmosphere Lag (#22924)
Y'know, probably. It certainly seems to work locally! changes: - code_imp: "Exoplanets now cache their main outdoor atmospheric region instead of trying to search their entire map once per second." - code_imp: "Exoplanet atmospheric calculations now run only when necessary using new update_revision counter." - code_imp: "Exoplanet atmospheres now wait until all random ruins have been placed before trying to resolve the air everywhere." - admin: "Adds new admin debug verb, 'Toggle Non-Horizon Temperature Graphics', which toggles all off-ship gas temp graphics to address lag in a pinch, if still necessary, without removing actual environmental hazard."
This commit is contained in:
+7
-1
@@ -6,7 +6,13 @@
|
||||
|
||||
/turf/simulated/proc/update_graphic(list/graphic_add = null, list/graphic_remove = null)
|
||||
if(graphic_add && LAZYLEN(graphic_add))
|
||||
add_vis_contents(graphic_add)
|
||||
if(SSair.suppress_nonhorizon_temperature_graphics && !is_station_level(z))
|
||||
for(var/obj/gas_overlay/graphic in graphic_add)
|
||||
if(graphic.gas_id == GAS_HEAT || graphic.gas_id == GAS_COLD)
|
||||
continue
|
||||
add_vis_contents(graphic)
|
||||
else
|
||||
add_vis_contents(graphic_add)
|
||||
if(graphic_remove && LAZYLEN(graphic_remove))
|
||||
remove_vis_contents(graphic_remove)
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ Class Vars:
|
||||
name - A name of the format "Zone [#]", used for debugging.
|
||||
invalid - True if the zone has been erased and is no longer eligible for processing.
|
||||
needs_update - True if the zone has been added to the update list.
|
||||
update_revision - Incremented when needs_update flips on, and retained after needs_update is cleared.
|
||||
edges - A list of edges that connect to this zone.
|
||||
air - The gas mixture that any turfs in this zone will return. Values are per-tile with a group multiplier.
|
||||
|
||||
@@ -47,6 +48,8 @@ Class Procs:
|
||||
var/list/fire_tiles
|
||||
|
||||
var/needs_update = 0
|
||||
/// Counter incremented when zone is dirtied for processing.
|
||||
var/update_revision = 0
|
||||
|
||||
var/list/connection_edge/edges
|
||||
|
||||
@@ -172,6 +175,7 @@ Class Procs:
|
||||
to_chat(M, "P: [XGM_PRESSURE(air)] kPa V: [air.volume]L T: [air.temperature]�K ([air.temperature - T0C]�C)")
|
||||
to_chat(M, "O2 per N2: [(air.gas[GAS_NITROGEN] ? air.gas[GAS_OXYGEN]/air.gas[GAS_NITROGEN] : "N/A")] Moles: [air.total_moles]")
|
||||
to_chat(M, "Simulated: [contents.len] ([air.group_multiplier])")
|
||||
to_chat(M, "Update Revision: [update_revision]")
|
||||
//to_chat(M, "Unsimulated: [unsimulated_contents.len]")
|
||||
//to_chat(M, "Edges: [LAZYLEN(edges)]")
|
||||
if(invalid) to_chat(M, "Invalid!")
|
||||
|
||||
@@ -88,6 +88,9 @@ SUBSYSTEM_DEF(air)
|
||||
var/active_zones = 0
|
||||
var/next_id = 1
|
||||
|
||||
/// Prevents gas temp graphics from being attached to turfs on non-Horizon z-levels.
|
||||
var/suppress_nonhorizon_temperature_graphics = FALSE
|
||||
|
||||
#ifdef ZASDBG
|
||||
var/updated = 0
|
||||
#endif
|
||||
@@ -297,6 +300,36 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
|
||||
if (processing_zones)
|
||||
processing_zones -= z
|
||||
|
||||
/// Suppresses or restores temperature graphics on every currently loaded non-station z-level.
|
||||
/datum/controller/subsystem/air/proc/set_nonhorizon_temperature_graphics_suppressed(suppress)
|
||||
suppress_nonhorizon_temperature_graphics = suppress
|
||||
. = 0
|
||||
|
||||
for(var/z_level in 1 to world.maxz)
|
||||
if(is_station_level(z_level))
|
||||
continue
|
||||
|
||||
for(var/turf/simulated/T in Z_TURFS(z_level))
|
||||
var/list/temperature_graphics
|
||||
|
||||
if(suppress)
|
||||
for(var/obj/gas_overlay/graphic in T.vis_contents)
|
||||
if(graphic.gas_id == GAS_HEAT || graphic.gas_id == GAS_COLD)
|
||||
LAZYADD(temperature_graphics, graphic)
|
||||
else if(TURF_HAS_VALID_ZONE(T))
|
||||
for(var/obj/gas_overlay/graphic in T.zone.air.graphic)
|
||||
if(graphic.gas_id == GAS_HEAT || graphic.gas_id == GAS_COLD)
|
||||
LAZYADD(temperature_graphics, graphic)
|
||||
|
||||
if(LAZYLEN(temperature_graphics))
|
||||
if(suppress)
|
||||
T.update_graphic(graphic_remove = temperature_graphics)
|
||||
else
|
||||
T.update_graphic(graphic_add = temperature_graphics)
|
||||
. += length(temperature_graphics)
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
/datum/controller/subsystem/air/proc/air_blocked(turf/A, turf/B)
|
||||
#ifdef ZASDBG
|
||||
ASSERT(isturf(A))
|
||||
@@ -386,6 +419,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
|
||||
return
|
||||
zones_to_update += Z
|
||||
Z.needs_update = 1
|
||||
Z.update_revision++
|
||||
|
||||
/datum/controller/subsystem/air/proc/mark_edge_sleeping(connection_edge/E)
|
||||
#ifdef ZASDBG
|
||||
|
||||
@@ -205,6 +205,7 @@ GLOBAL_LIST_INIT(admin_verbs_debug, list(
|
||||
/client/proc/cmd_admin_delete,
|
||||
/client/proc/cmd_debug_del_all,
|
||||
/client/proc/air_report,
|
||||
/client/proc/toggle_nonhorizon_temperature_graphics,
|
||||
/client/proc/reload_admins,
|
||||
/client/proc/print_random_map,
|
||||
/client/proc/create_random_map,
|
||||
|
||||
@@ -41,6 +41,24 @@
|
||||
|
||||
usr << browse(HTML_SKELETON(output), "window=airreport")
|
||||
|
||||
/client/proc/toggle_nonhorizon_temperature_graphics()
|
||||
set category = "Debug"
|
||||
set name = "Toggle Non-Horizon Temperature Graphics"
|
||||
set desc = "Toggle gas temperature graphics on all non-Horizon z-levels."
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
if(!SSair)
|
||||
to_chat(src, SPAN_WARNING("The air subsystem is unavailable."))
|
||||
return
|
||||
|
||||
var/suppress = !SSair.suppress_nonhorizon_temperature_graphics
|
||||
to_chat(src, SPAN_NOTICE("[suppress ? "Disabling" : "Re-enabling"] non-Horizon temperature graphics. This may take several ticks."))
|
||||
|
||||
var/updated_graphics = SSair.set_nonhorizon_temperature_graphics_suppressed(suppress)
|
||||
log_and_message_admins("has [suppress ? "disabled" : "enabled"] GAS_HEAT and GAS_COLD graphics on non-Horizon z-levels ([updated_graphics] graphic reference\s updated).")
|
||||
feedback_add_details("admin_verb", "TNTG")
|
||||
|
||||
/client/proc/fix_next_move()
|
||||
set category = "Debug"
|
||||
set name = "Unfreeze Everyone"
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
var/list/animals = list()
|
||||
var/max_animal_count
|
||||
var/datum/gas_mixture/atmosphere
|
||||
/// Cached main ZAS surface zone per generated z-level. Resolved lazily after ZAS finishes building.
|
||||
var/list/main_planetary_zones = list()
|
||||
/// Last ZAS update revision processed per generated z-level.
|
||||
var/list/main_planetary_zone_atmosphere_revisions = list()
|
||||
var/list/breathgas = list() //list of gases animals/plants require to survive
|
||||
var/badgas //id of gas that is toxic to life here
|
||||
|
||||
@@ -222,6 +226,7 @@
|
||||
generate_features()
|
||||
theme.after_map_generation(src)
|
||||
generate_landing(2)
|
||||
finalize_outdoor_atmosphere()
|
||||
update_biome()
|
||||
generate_planet_image()
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
@@ -272,17 +277,74 @@
|
||||
|
||||
if(!atmosphere)
|
||||
continue
|
||||
var/zone/Z
|
||||
for(var/i = 1 to maxx)
|
||||
var/turf/simulated/T = locate(i, 2, zlevel)
|
||||
if(istype(T) && T.zone && T.zone.contents.len > (maxx*maxy*0.25)) //if it's a zone quarter of zlevel, good enough odds it's planetary main one
|
||||
Z = T.zone
|
||||
break
|
||||
if(Z && !length(Z.fire_tiles) && !atmosphere.compare(Z.air)) //let fire die out first if there is one
|
||||
var/zone/Z = get_main_planetary_zone(zlevel)
|
||||
if(!Z)
|
||||
continue
|
||||
var/zlevel_key = "[zlevel]"
|
||||
var/last_atmosphere_revision = main_planetary_zone_atmosphere_revisions[zlevel_key]
|
||||
if(!isnull(last_atmosphere_revision) && last_atmosphere_revision == Z.update_revision)
|
||||
continue
|
||||
// Let ZAS settle and fire die out first if there is one
|
||||
if(Z.needs_update || length(Z.fire_tiles))
|
||||
continue
|
||||
if(!atmosphere.compare(Z.air))
|
||||
var/datum/gas_mixture/daddy = new() //make a fake 'planet' zone gas
|
||||
daddy.copy_from(atmosphere)
|
||||
daddy.group_multiplier = Z.air.group_multiplier
|
||||
Z.air.equalize(daddy)
|
||||
SSair.mark_zone_update(Z)
|
||||
main_planetary_zone_atmosphere_revisions[zlevel_key] = Z.update_revision
|
||||
|
||||
/// Attempts to not only identify the largest air zone, but also cache it for subsequent ticks.
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/get_main_planetary_zone(zlevel)
|
||||
var/zlevel_key = "[zlevel]"
|
||||
var/zone/cached_zone = main_planetary_zones[zlevel_key]
|
||||
// ZAS may invalidate and rebuild zones after terrain changes. Keep the cached zone only while it is still valid!
|
||||
if(cached_zone && !cached_zone.invalid)
|
||||
return cached_zone
|
||||
|
||||
main_planetary_zones -= zlevel_key
|
||||
main_planetary_zone_atmosphere_revisions -= zlevel_key
|
||||
|
||||
// Exoplanet transition edges are unsimulated, so only scan the generated interior when resolving the main surface zone.
|
||||
var/min_x = TRANSITIONEDGE + 1
|
||||
var/min_y = TRANSITIONEDGE + 1
|
||||
var/max_x = maxx - (TRANSITIONEDGE + 1)
|
||||
var/max_y = maxy - (TRANSITIONEDGE + 1)
|
||||
var/turf/lower_left = locate(min_x, min_y, zlevel)
|
||||
var/turf/upper_right = locate(max_x, max_y, zlevel)
|
||||
if(!lower_left || !upper_right)
|
||||
return null
|
||||
|
||||
// If it's a zone quarter of zlevel, good enough odds it's planetary main one.
|
||||
var/minimum_zone_size = maxx * maxy * 0.25
|
||||
var/zone/best_zone
|
||||
var/best_zone_size = 0
|
||||
var/list/checked_zones = list()
|
||||
var/zas_pending = FALSE
|
||||
for(var/turf/simulated/T in block(lower_left, upper_right))
|
||||
// Dynamic turf generation queues ZAS updates... Do not cache a main zone while the surface may still be settling!
|
||||
if(T.needs_air_update)
|
||||
zas_pending = TRUE
|
||||
continue
|
||||
if(!TURF_HAS_VALID_ZONE(T))
|
||||
continue
|
||||
var/zone/current_zone = T.zone
|
||||
if(current_zone in checked_zones)
|
||||
continue
|
||||
checked_zones += current_zone
|
||||
var/current_zone_size = current_zone.contents.len
|
||||
if(current_zone_size <= best_zone_size || current_zone_size <= minimum_zone_size)
|
||||
continue
|
||||
best_zone = current_zone
|
||||
best_zone_size = current_zone_size
|
||||
|
||||
// Try again on a later processing tick once ZAS has finished assigning/rebuilding the planet's surface zones
|
||||
if(zas_pending)
|
||||
return null
|
||||
if(best_zone)
|
||||
main_planetary_zones[zlevel_key] = best_zone
|
||||
return best_zone
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/remove_animal(mob/M)
|
||||
animals -= M
|
||||
@@ -318,6 +380,56 @@
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/generate_features()
|
||||
spawned_features = seedRuins(map_z, features_budget, possible_features, /area/exoplanet, maxx, maxy)
|
||||
|
||||
/**
|
||||
* Applies the generated planetary atmosphere AFTER terrain and ruins finish loading.
|
||||
*
|
||||
* Exoplanet turf subtypes initialize themselves with the planet's air, but ruins and
|
||||
* terrain generation may place ordinary simulated turfs which otherwise retain their
|
||||
* type's standard atmosphere. The area's mapped is_outside value is authoritative:
|
||||
* OUTSIDE_NO preserves sealed interiors, while every outdoor turf receives planetary air.
|
||||
*
|
||||
* Without this behavior, you see weird cross-contamination issues, especially in cases
|
||||
* where maps don't have their /areas configured properly.
|
||||
*/
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/finalize_outdoor_atmosphere()
|
||||
if(!atmosphere)
|
||||
return
|
||||
|
||||
var/list/outdoor_zones = list()
|
||||
for(var/zlevel in map_z)
|
||||
var/turf/lower_left = locate(TRANSITIONEDGE + 1, TRANSITIONEDGE + 1, zlevel)
|
||||
var/turf/upper_right = locate(maxx - (TRANSITIONEDGE + 1), maxy - (TRANSITIONEDGE + 1), zlevel)
|
||||
if(!lower_left || !upper_right)
|
||||
continue
|
||||
|
||||
for(var/turf/simulated/T in block(lower_left, upper_right))
|
||||
var/area/A = get_area(T)
|
||||
if(!A || A.is_outside == OUTSIDE_NO)
|
||||
continue
|
||||
|
||||
T.initial_gas = atmosphere.gas.Copy()
|
||||
T.temperature = atmosphere.temperature
|
||||
|
||||
// Dynamic z-levels are created after SSair initializes. Usually these turfs are
|
||||
// still unzoned... but if ZAS already found them, take care not to break them.
|
||||
if(TURF_HAS_VALID_ZONE(T))
|
||||
outdoor_zones |= T.zone
|
||||
else if(T.air)
|
||||
T.air.group_multiplier = 1
|
||||
T.air.copy_from(atmosphere)
|
||||
else
|
||||
T.make_air()
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
// A zone stores ONE shared mixture, so update it once rather than once per member turf.
|
||||
for(var/zone/Z as anything in outdoor_zones)
|
||||
if(Z.invalid)
|
||||
continue
|
||||
Z.air.copy_from(atmosphere)
|
||||
SSair.mark_zone_update(Z)
|
||||
CHECK_TICK
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/update_biome()
|
||||
for(var/datum/seed/S as anything in seeds)
|
||||
adapt_seed(S)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
author: Batrachophrenoboocosmomachia
|
||||
delete-after: True
|
||||
changes:
|
||||
- code_imp: "Exoplanets now cache their main outdoor atmospheric region instead of trying to search their entire map once per second."
|
||||
- code_imp: "Exoplanet atmospheric calculations now run only when necessary using new update_revision counter."
|
||||
- code_imp: "Exoplanet atmospheres now wait until all random ruins have been placed before trying to resolve the air everywhere."
|
||||
- admin: "Adds new admin debug verb, 'Toggle Non-Horizon Temperature Graphics', which toggles all off-ship gas temp graphics to address lag in a pinch, if still necessary, without removing actual environmental hazard."
|
||||
Reference in New Issue
Block a user