diff --git a/_maps/map_files/YogStation/YogStation.dmm b/_maps/map_files/YogStation/YogStation.dmm index b3bba9670734..4700ec1d0ae6 100644 --- a/_maps/map_files/YogStation/YogStation.dmm +++ b/_maps/map_files/YogStation/YogStation.dmm @@ -16303,12 +16303,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/security/prison) -"aVA" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos_distro) "aVB" = ( /obj/machinery/hydroponics/soil, /obj/effect/turf_decal/tile/green{ @@ -17043,12 +17037,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel/cafeteria, /area/security/prison) -"aYJ" = ( -/obj/machinery/atmospherics/pipe/manifold/supply/visible{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos_distro) "aYK" = ( /obj/machinery/door/window/westleft, /turf/open/floor/engine{ @@ -17456,17 +17444,6 @@ /obj/machinery/door/firedoor/border_only, /turf/open/floor/plasteel, /area/hydroponics) -"bao" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/components/binary/pump/on{ - dir = 1; - name = "Air to distro"; - target_pressure = 4500 - }, -/turf/open/floor/plasteel, -/area/engine/atmos_distro) "bap" = ( /obj/structure/table/reinforced, /obj/machinery/door/window/westright{ @@ -29541,18 +29518,6 @@ "bVJ" = ( /turf/closed/wall/r_wall, /area/tcommsat/computer) -"bVT" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/manifold/supply/visible{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos_distro) "bWr" = ( /turf/open/floor/plasteel, /area/science/misc_lab) @@ -34353,6 +34318,12 @@ /mob/living/simple_animal/pet/cat/Runtime, /turf/open/floor/plasteel/cafeteria, /area/crew_quarters/heads/cmo) +"dAR" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/engine/atmos_distro) "dBV" = ( /obj/machinery/camera{ c_tag = "Central Hallway West"; @@ -37251,6 +37222,19 @@ /obj/effect/landmark/stationroom/maint/threexfive, /turf/template_noop, /area/maintenance/port/aft) +"fBV" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/components/binary/pump/on{ + dir = 1; + name = "Air to Distro"; + target_pressure = 4500 + }, +/turf/open/floor/plasteel, +/area/engine/atmos_distro) "fCb" = ( /obj/structure/chair{ dir = 8 @@ -39027,6 +39011,15 @@ /obj/effect/spawner/lootdrop/techstorage/tcomms, /turf/open/floor/plasteel/white, /area/storage/tech) +"gRG" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 6 + }, +/turf/open/floor/plasteel, +/area/engine/atmos_distro) "gRQ" = ( /obj/effect/turf_decal/trimline/blue/filled/line, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ @@ -39077,14 +39070,6 @@ /obj/machinery/suit_storage_unit/atmos, /turf/open/floor/plasteel/dark, /area/engine/atmos) -"gWe" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, -/turf/open/floor/plasteel, -/area/engine/atmos_distro) "gWm" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -40158,6 +40143,14 @@ /obj/effect/decal/cleanable/blood, /turf/open/floor/plating, /area/maintenance/aft) +"hJt" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/manifold/supply{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/engine/atmos_distro) "hJu" = ( /obj/machinery/light, /obj/structure/sign/warning/electricshock{ @@ -44396,15 +44389,6 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) -"krs" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/engine/atmos_distro) "ksg" = ( /obj/structure/cable{ icon_state = "1-2" @@ -45452,6 +45436,18 @@ /mob/living/carbon/monkey, /turf/open/floor/grass, /area/medical/genetics) +"lfz" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/visible{ + dir = 5 + }, +/turf/open/floor/plasteel, +/area/engine/atmos_distro) "lfO" = ( /obj/machinery/atmospherics/pipe/simple/purple/visible{ dir = 4 @@ -46420,13 +46416,6 @@ }, /turf/open/floor/plating, /area/maintenance/starboard) -"lLZ" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, -/turf/open/floor/plasteel, -/area/engine/atmos_distro) "lMg" = ( /obj/effect/turf_decal/stripes/line{ dir = 5 @@ -46740,6 +46729,15 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) +"mde" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/engine/atmos_distro) "mdx" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, @@ -47857,6 +47855,15 @@ /obj/machinery/telecomms/hub/preset, /turf/open/floor/circuit/green/telecomms/mainframe, /area/tcommsat/server) +"mPY" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/engine/atmos_distro) "mRf" = ( /obj/structure/cable{ icon_state = "1-2" @@ -48116,6 +48123,12 @@ }, /turf/open/floor/plating, /area/hallway/secondary/exit) +"mXV" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel, +/area/engine/atmos_distro) "mZe" = ( /obj/item/twohanded/required/kirbyplants/random, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ @@ -49826,12 +49839,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/port) -"oaF" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/engine/atmos_distro) "ocv" = ( /obj/effect/landmark/stationroom/maint/fivexfour, /turf/template_noop, @@ -50191,6 +50198,13 @@ "omk" = ( /turf/template_noop, /area/maintenance/fore) +"omC" = ( +/obj/machinery/meter, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/manifold4w/cyan, +/turf/open/floor/plasteel, +/area/engine/atmos_distro) "omX" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -51049,15 +51063,6 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) -"oLx" = ( -/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ - dir = 1 - }, -/obj/machinery/meter, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, -/turf/open/floor/plasteel, -/area/engine/atmos_distro) "oLF" = ( /obj/machinery/atmospherics/components/unary/tank/air{ piping_layer = 2 @@ -52296,6 +52301,12 @@ /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4, /turf/open/floor/plasteel, /area/security/main) +"pEB" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/machinery/holopad, +/turf/open/floor/plasteel, +/area/engine/atmos_distro) "pEC" = ( /obj/machinery/door/firedoor/border_only{ dir = 8 @@ -55194,13 +55205,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/starboard) -"rCr" = ( -/obj/machinery/holopad, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos_distro) "rCG" = ( /obj/machinery/camera/motion{ c_tag = "AI Upload Chamber - Starboard"; @@ -56150,6 +56154,18 @@ /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/science/storage) +"shf" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/supply{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/engine/atmos_distro) "shz" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 1 @@ -58343,14 +58359,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) -"tKT" = ( -/obj/machinery/atmospherics/pipe/simple/supply/visible{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, -/turf/open/floor/plasteel, -/area/engine/atmos_distro) "tLe" = ( /obj/effect/turf_decal/tile/yellow{ dir = 1 @@ -59892,6 +59900,12 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) +"uMd" = ( +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/engine/atmos_distro) "uMh" = ( /obj/structure/window/reinforced{ dir = 8 @@ -61992,6 +62006,10 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /turf/open/floor/plating, /area/maintenance/starboard/aft) +"whe" = ( +/obj/machinery/holopad, +/turf/open/floor/plasteel, +/area/engine/atmos_distro) "whg" = ( /obj/machinery/camera{ c_tag = "Central Hallway South-East"; @@ -63765,18 +63783,6 @@ /obj/effect/mapping_helpers/teleport_anchor, /turf/open/floor/plasteel, /area/engine/engineering) -"xxQ" = ( -/obj/machinery/atmospherics/pipe/simple/supply/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos_distro) "xyU" = ( /obj/machinery/disposal/bin, /obj/structure/disposalpipe/trunk{ @@ -101140,10 +101146,10 @@ sCs axJ aFY vbA -bVT -aYJ -bao -bij +lfz +aSJ +mXV +uMd aSJ bAi bCP @@ -101397,10 +101403,10 @@ bIT avy clA iNp -xxQ -tKT -gWe -oLx +shf +hJt +fBV +omC wPn aME hRo @@ -101660,7 +101666,7 @@ kcl bqC bwW bAo -rCr +bCP cor qsa tLy @@ -101671,7 +101677,7 @@ iNp iNp iNp sXz -iNp +pEB iNp iNp oyd @@ -101911,8 +101917,8 @@ tHY aCV juh aSJ -oaF -krs +dAR +gRG bbK bqC bwW @@ -102168,8 +102174,8 @@ jyo axJ wqE aSY -aVA -lLZ +mde +mPY bej bre bxh @@ -102427,7 +102433,7 @@ aRF aTp aVD aZT -aSJ +whe bue bxI bBm diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm index 812ff5d9503d..f3fd23177efb 100644 --- a/code/__DEFINES/atmospherics.dm +++ b/code/__DEFINES/atmospherics.dm @@ -492,5 +492,11 @@ GLOBAL_LIST_INIT(pipe_paint_colors, list( "yellow" = rgb(255,198,0) )) +///ROT Miasma #define MIASMA_CORPSE_MOLES 0.02 #define MIASMA_GIBS_MOLES 0.005 + +//PIPENET UPDATE STATUS +#define PIPENET_UPDATE_STATUS_DORMANT 0 +#define PIPENET_UPDATE_STATUS_REACT_NEEDED 1 +#define PIPENET_UPDATE_STATUS_RECONCILE_NEEDED 2 diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index 3904143392f7..3c02852ada82 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -77,8 +77,9 @@ SUBSYSTEM_DEF(air) var/timer = TICK_USAGE_REAL if(currentpart == SSAIR_REBUILD_PIPENETS) var/list/pipenet_rebuilds = pipenets_needing_rebuilt - for(var/thing in pipenet_rebuilds) - var/obj/machinery/atmospherics/AT = thing + for(var/obj/machinery/atmospherics/AT as() in pipenet_rebuilds) + if(!AT) //If a null somehow shows up here, this next line runtimes and the subsystem dies + continue AT.build_network() cost_rebuilds = MC_AVERAGE(cost_rebuilds, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)) pipenets_needing_rebuilt.Cut() @@ -184,12 +185,13 @@ SUBSYSTEM_DEF(air) //cache for sanic speed (lists are references anyways) var/list/currentrun = src.currentrun while(currentrun.len) - var/datum/thing = currentrun[currentrun.len] + var/datum/pipeline/P = currentrun[currentrun.len] currentrun.len-- - if(thing) - thing.process() + if(P) + if(P.update) + P.update = P.reconcile_air() else - networks.Remove(thing) + networks.Remove(P) if(MC_TICK_CHECK) return diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm index 31c31f188b53..983a96a6d743 100644 --- a/code/game/objects/items/tanks/tanks.dm +++ b/code/game/objects/items/tanks/tanks.dm @@ -230,7 +230,7 @@ /obj/item/tank/process() //Allow for reactions - air_contents.react() + air_contents.react(src) check_status() /obj/item/tank/proc/check_status() diff --git a/code/modules/admin/verbs/atmosdebug.dm b/code/modules/admin/verbs/atmosdebug.dm index a8823ed9d698..051cdf760a29 100644 --- a/code/modules/admin/verbs/atmosdebug.dm +++ b/code/modules/admin/verbs/atmosdebug.dm @@ -20,6 +20,14 @@ for(var/obj/machinery/atmospherics/pipe/simple/pipe in GLOB.machines) if(pipe.z && (!pipe.nodes || !pipe.nodes.len || (null in pipe.nodes))) to_chat(usr, "Unconnected [pipe.name] located at [ADMIN_VERBOSEJMP(pipe)]", confidential=TRUE) + + //Erroneous Connections, e.g. duplicate pipes + //This uses pipeline_expansion(), so you can detect some atmos machineries causing problems at pipenet code. + for (var/obj/machinery/atmospherics/AM in GLOB.machines) + for (var/obj/machinery/atmospherics/AMT in AM.pipeline_expansion()) + if (!(AM in AMT.pipeline_expansion())) + to_chat(usr, "Errorneous connections around [AM.name]. Duplicate or rogue pipes suspected at or around [ADMIN_VERBOSEJMP(AM)]") + /client/proc/powerdebug() set category = "Misc.Server Debug" diff --git a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm index 9181b33d5709..0c454f078959 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm @@ -82,7 +82,7 @@ air_update_turf() var/datum/pipeline/parent1 = parents[1] - parent1.update = 1 + parent1.update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED else //external -> output @@ -103,7 +103,7 @@ air_update_turf() var/datum/pipeline/parent2 = parents[2] - parent2.update = 1 + parent2.update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED //Radio remote control diff --git a/code/modules/atmospherics/machinery/components/binary_devices/valve.dm b/code/modules/atmospherics/machinery/components/binary_devices/valve.dm index 1974d31816fd..96ed54e2331e 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/valve.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/valve.dm @@ -24,6 +24,16 @@ It's like a regular ol' straight pipe, but you can turn it on and off. var/switching = FALSE +/obj/machinery/atmospherics/components/binary/valve/Destroy() + //Should only happen on extreme circumstances + if(on) + //Let's give presumably now-severed pipenets a chance to scramble for what's happening at next SSair fire() + if(parents[1]) + parents[1].update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED + if(parents[2]) + parents[2].update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED + . = ..() + /obj/machinery/atmospherics/components/binary/valve/update_icon_nopipes(animation = FALSE) normalize_cardinal_directions() if(animation) @@ -44,6 +54,8 @@ It's like a regular ol' straight pipe, but you can turn it on and off. parent1.reconcile_air() investigate_log("was opened by [usr ? key_name(usr) : "a remote signal"]", INVESTIGATE_ATMOS) investigate_log("was opened by [usr ? key_name(usr) : "a remote signal"]", INVESTIGATE_SUPERMATTER) // yogs - Makes supermatter invest useful + update_icon_nopipes() + update_parents() /obj/machinery/atmospherics/components/binary/valve/interact(mob/user) add_fingerprint(usr) diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm index 3640947b0187..a01a693f3d26 100644 --- a/code/modules/atmospherics/machinery/components/components_base.dm +++ b/code/modules/atmospherics/machinery/components/components_base.dm @@ -71,7 +71,7 @@ /obj/machinery/atmospherics/components/build_network() for(var/i in 1 to device_type) - if(!parents[i]) + if(QDELETED(parents[i])) parents[i] = new /datum/pipeline() var/datum/pipeline/P = parents[i] P.build_pipeline(src) @@ -82,10 +82,27 @@ var/i = parents.Find(reference) reference.other_airs -= airs[i] reference.other_atmosmch -= src + /** + * We explicitly qdel pipeline when this particular pipeline + * is projected to have no member and cause GC problems. + * We have to do this because components don't qdel pipelines + * while pipes must and will happily wreck and rebuild everything again + * every time they are qdeleted. + */ + if(!(reference.other_atmosmch.len || reference.members.len)) + qdel(reference) parents[i] = null +// We should return every air sharing a parent /obj/machinery/atmospherics/components/returnPipenetAir(datum/pipeline/reference) - return airs[parents.Find(reference)] + for(var/i in 1 to device_type) + if(parents[i] == reference) + if(.) + if(!islist(.)) + . = list(.) + . += airs[i] + else + . = airs[i] /obj/machinery/atmospherics/components/pipeline_expansion(datum/pipeline/reference) if(reference) @@ -139,9 +156,10 @@ var/datum/pipeline/parent = parents[i] if(!parent) WARNING("Component is missing a pipenet! Rebuilding...") + //At pre-SSair_rebuild_pipenets times, not having a parent wasn't supposed to happen SSair.add_to_rebuild_queue(src) - else - parent.update = 1 + continue + parent.update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED /obj/machinery/atmospherics/components/returnPipenets() . = list() diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm index aaad250b2fc3..b33d0f56b2a9 100644 --- a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm +++ b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm @@ -111,16 +111,16 @@ var/datum/gas_mixture/removed1 = air1.remove(transfer_moles1) air3.merge(removed1) var/datum/pipeline/parent1 = parents[1] - parent1.update = TRUE + parent1.update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED if(transfer_moles2) var/datum/gas_mixture/removed2 = air2.remove(transfer_moles2) air3.merge(removed2) var/datum/pipeline/parent2 = parents[2] - parent2.update = TRUE + parent2.update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED var/datum/pipeline/parent3 = parents[3] - parent3.update = TRUE + parent3.update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED /obj/machinery/atmospherics/components/trinary/mixer/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm index 0d6cd38dd32b..c931f31dedd9 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm @@ -97,6 +97,7 @@ if(src in node.nodes) //Only if it's actually connected. On-pipe version would is one-sided. node.disconnect(src) nodes[1] = null + //Sometimes this gets called more than once per atmos tick; i.e. before the incoming build_network call by SSAIR_REBUILD_PIPENETS, so we check this here. if(parents[1]) nullifyPipenet(parents[1]) diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm index 06a0a275ff79..d9382ca0bf90 100644 --- a/code/modules/atmospherics/machinery/datum_pipeline.dm +++ b/code/modules/atmospherics/machinery/datum_pipeline.dm @@ -5,7 +5,7 @@ var/list/obj/machinery/atmospherics/pipe/members var/list/obj/machinery/atmospherics/components/other_atmosmch - var/update = TRUE + var/update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED /datum/pipeline/New() other_airs = list() @@ -23,62 +23,53 @@ C.nullifyPipenet(src) return ..() -/datum/pipeline/process() - if(update) - update = FALSE - reconcile_air() - update = air.react(src) - /datum/pipeline/proc/build_pipeline(obj/machinery/atmospherics/base) - var/volume = 0 - if(istype(base, /obj/machinery/atmospherics/pipe)) - var/obj/machinery/atmospherics/pipe/E = base - volume = E.volume - members += E - if(E.air_temporary) - air = E.air_temporary - E.air_temporary = null - else - addMachineryMember(base) - if(!air) - air = new - var/list/possible_expansions = list(base) - while(possible_expansions.len) - for(var/obj/machinery/atmospherics/borderline in possible_expansions) - var/list/result = borderline.pipeline_expansion(src) - if(result && result.len) - for(var/obj/machinery/atmospherics/P in result) - if(istype(P, /obj/machinery/atmospherics/pipe)) - var/obj/machinery/atmospherics/pipe/item = P - if(!members.Find(item)) - - if(item.parent) - var/static/pipenetwarnings = 100 - if(pipenetwarnings > 0) - log_mapping("build_pipeline(): [item.type] added to a pipenet while still having one. (pipes leading to the same spot stacking in one turf) around [AREACOORD(item)].") - pipenetwarnings-- - if(pipenetwarnings == 0) - log_mapping("build_pipeline(): further messages about pipenets will be suppressed") - members += item - possible_expansions += item - - volume += item.volume - item.parent = src - - if(item.air_temporary) - air.merge(item.air_temporary) - item.air_temporary = null - else - P.setPipenet(src, borderline) - addMachineryMember(P) - - possible_expansions -= borderline - - air.set_volume(volume) + if(!QDELETED(base)) + var/volume = 0 + if(istype(base, /obj/machinery/atmospherics/pipe)) + var/obj/machinery/atmospherics/pipe/E = base + volume = E.volume + members += E + if(E.air_temporary) + air = E.air_temporary + E.air_temporary = null + else + addMachineryMember(base) + if(!air) + air = new + var/list/possible_expansions = list(base) + while(possible_expansions.len) + for(var/obj/machinery/atmospherics/borderline in possible_expansions) + var/list/result = borderline.pipeline_expansion(src) + if(result && result.len) + for(var/obj/machinery/atmospherics/P in result) + if(istype(P, /obj/machinery/atmospherics/pipe)) + var/obj/machinery/atmospherics/pipe/item = P + if(!members.Find(item)) + if(item.parent) + var/static/pipenetwarnings = 10 + if(pipenetwarnings > 0) + log_mapping("build_pipeline(): [item.type] added to a pipenet while still having one. (pipes leading to the same spot stacking in one turf) around [AREACOORD(item)].") + pipenetwarnings-- + if(pipenetwarnings == 0) + log_mapping("build_pipeline(): further messages about pipenets will be suppressed") + members += item + possible_expansions += item + volume += item.volume + item.parent = src + if(item.air_temporary) + air.merge(item.air_temporary) + item.air_temporary = null + else if(!P.returnPipenet(borderline)) + P.setPipenet(src, borderline) + addMachineryMember(P) + possible_expansions -= borderline + air.set_volume(volume) /datum/pipeline/proc/addMachineryMember(obj/machinery/atmospherics/components/C) - other_atmosmch |= C - var/datum/gas_mixture/G = C.returnPipenetAir(src) + //Yes we are having duplicate references to components with multiple nodes sharing a parent + other_atmosmch += C + var/G = C.returnPipenetAir(src) if(!G) stack_trace("addMachineryMember: Null gasmix added to pipeline datum from [C] which is of type [C.type]. Nearby: ([C.x], [C.y], [C.z])") other_airs |= G @@ -116,7 +107,7 @@ other_airs.Add(E.other_airs) E.members.Cut() E.other_atmosmch.Cut() - update = TRUE + update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED qdel(E) /obj/machinery/atmospherics/proc/addMember(obj/machinery/atmospherics/A) @@ -198,7 +189,7 @@ (partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity)) air.set_temperature(air.return_temperature() - heat/total_heat_capacity) - update = TRUE + update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED /datum/pipeline/proc/return_air() . = other_airs + air @@ -215,8 +206,12 @@ var/datum/pipeline/P = PL[i] if(!P) continue - GL += P.other_airs - GL += P.air + GL += P.return_air() + if(P != src) + //If one of the reconciling pipenet requires full reconciliation, we have to comply + update = max(update, P.update) + //This prevents redundant reconciliations, highlander style: there can be only one (to reconcile) + P.update = PIPENET_UPDATE_STATUS_DORMANT for(var/atmosmch in P.other_atmosmch) if (istype(atmosmch, /obj/machinery/atmospherics/components/binary/valve)) var/obj/machinery/atmospherics/components/binary/valve/V = atmosmch @@ -228,6 +223,7 @@ if(C.connected_device) GL += C.connected_device.air_contents + //This builds total_gas_mixture, which is the *only* instance of complete total gas of a superpipnet. var/datum/gas_mixture/total_gas_mixture = new(0) var/total_volume = 0 @@ -235,6 +231,20 @@ var/datum/gas_mixture/G = i total_gas_mixture.merge(G) total_volume += G.return_volume() + + total_gas_mixture.set_volume(total_volume) + + //Decides what this pipeline should do next tick + //Pipenet air reacts here or your connected canisters won't react properly + if(total_gas_mixture.react(pick(PL))) + //Might need another reaction next time; immediately set this pipenet for next reconcile_air() + . = PIPENET_UPDATE_STATUS_REACT_NEEDED + else + . = PIPENET_UPDATE_STATUS_DORMANT + //Needs no update and didn't even react? This reconcile_air() can return early since no change was made. + //This can only be achieved with self-ending stream of reactions, i.e. pipeline fire that has come to an end. + if(update < PIPENET_UPDATE_STATUS_RECONCILE_NEEDED) + return if(total_volume > 0) //Update individual gas_mixtures by volume ratio diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm index 54d437274f81..128f374ac5bf 100644 --- a/code/modules/atmospherics/machinery/pipes/pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/pipes.dm @@ -12,6 +12,7 @@ can_buckle = 1 buckle_requires_restraints = 1 buckle_lying = -1 + FASTDMM_PROP(\ set_instance_vars(\ icon_state = INSTANCE_VAR_DEFAULT\ @@ -54,7 +55,12 @@ air_update_turf() /obj/machinery/atmospherics/pipe/return_air() - return parent.air + if(parent) + return parent.air + +/obj/machinery/atmospherics/pipe/return_analyzable_air() + if(parent) + return parent.air /obj/machinery/atmospherics/pipe/remove_air(amount) return parent.air.remove(amount) @@ -67,16 +73,9 @@ else return ..() -/obj/machinery/atmospherics/pipe/analyzer_act(mob/living/user, obj/item/I) - atmosanalyzer_scan(parent.air, user, src) - -/obj/machinery/atmospherics/pipe/examine(mob/dead/observer/user) - if(istype(user)) - analyzer_act(user, src) - return ..() - /obj/machinery/atmospherics/pipe/returnPipenet() - return parent + if(parent) + return parent.air /obj/machinery/atmospherics/pipe/setPipenet(datum/pipeline/P) parent = P diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm index 97c409de6e38..4a11613dc12b 100644 --- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm +++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm @@ -63,8 +63,7 @@ //Perform the connection connected_port = new_port connected_port.connected_device = src - var/datum/pipeline/connected_port_parent = connected_port.parents[1] - connected_port_parent.reconcile_air() + connected_port.parents[1].update = PIPENET_UPDATE_STATUS_RECONCILE_NEEDED anchored = TRUE //Prevent movement pixel_x = new_port.pixel_x