Atmos Control Console Refactor (and syndiebase atmos tidyup) (#65372)

Main Takeaways For Mappers:

Use monitored pathed atmos devices very carefully. Also dont put atmos_sensors willy nilly. They are used to hook to atmos control monitors.

We want to keep at most one device broadcasting for each of the atmos sensor, inlets, and outlets. Run the mapping verb Check Atmos Chamber Devices to be sure, though this might not catch everything.

Some of the warning are pretty harmless. For example if you have reconnected the "station atmos monitor" and you get no listener for distro/waste loop warning, it's safe to ignore.

I don't know what the maptainer policy is on making new subtypes for offstation content, but if you do please branch off the general ones instead of the specific gas ones. If you aren't making a new subtype, varedit the general ones too.

About The Pull Request:

Need Would prefer this to be merged before #65271 (In game atmos guide).
Not strictly necessary, just makes me sleep better knowing the handbook wont die alongside the rest of the UI.

Fixes #36668 (Atmos Monitoring Consoles don't update it's sensors to the new tank after reconnect())
Fixes #32122 (Mix console fucked after reconnecting it)

Also made the distro meter thing broadcast more info instead of just the pressure, because I'm sure nobody would care and it would make my life easier.

A small high-level overview in case this breaks again in the future:

A signal datum (not DCS) is sent by the atmospheric devices (injectors and vents) and will be received by the atmos computers. The data is then stored at the monitor object and then passed to the UI. This initial signal is sent by `broadcast_signal()`, called by `atmos_init()`.

New sensors/vents (if you can actually get them in game, still only adminspawn/wrenchables afaik) will also initiate the conversation if atmos_init() is called, so it works fine. This means you need to unwrench and re-wrench the devices if you adminspawn them though, ugh.

In case of a newly built computer, it needs to be the one that prompt the data to the devices, so we send a request signal. This is a bit inefficient since it doesnt work off of callbacks and assocs like DCS, but won't really matter since we're doing this rarely.

We only talk with the injectors and vents when necessary here, while sensors and meters keep beeping with every process_atmos() tick so they rarely break.


Why It's Good For The Game:

Messy code gone (debatable).


Refactored the atmos control console devices. The ones that hook to the big turf chambers.
Distro meter now broadcast the whole gasmix info instead of just pressure to the monitors.
Lavaland syndie's atmos chamber vents are now actually configurable. Moved a few things around to accomodate this.
Lavalannd syndie chambers hooked to distro and moved distro pipe to layer2
atmos monitors can detect reactions now.
Some minor code changes to how anomaly refinery and implosion compressor show the gas info. No changes expected, report if bug.
recoded checks for atmos chamber abnormalities in debug verbs.
This commit is contained in:
vincentiusvin
2022-03-24 02:12:14 -07:00
committed by GitHub
parent 33fc723c93
commit 55336d1e53
37 changed files with 34907 additions and 34810 deletions
-36
View File
@@ -206,42 +206,6 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
log_admin("[key_name(usr)] gave away direct control of [M] to [newkey].")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Give Direct Control") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_test_atmos_controllers()
set category = "Mapping"
set name = "Test Atmos Monitoring Consoles"
var/list/dat = list()
if(SSticker.current_state == GAME_STATE_STARTUP)
to_chat(usr, "Game still loading, please hold!", confidential = TRUE)
return
message_admins(span_adminnotice("[key_name_admin(usr)] used the Test Atmos Monitor debug command."))
log_admin("[key_name(usr)] used the Test Atmos Monitor debug command.")
var/bad_shit = 0
for(var/obj/machinery/computer/atmos_control/tank/console in GLOB.atmos_air_controllers)
dat += "<h1>[console] at [AREACOORD(console)]:</h1><br>"
if(console.input_tag == console.output_tag)
dat += "Error: input_tag is the same as the output_tag, \"[console.input_tag]\"!<br>"
bad_shit++
if(!LAZYLEN(console.input_info))
dat += "Failed to find a valid outlet injector as an input with the tag [console.input_tag].<br>"
bad_shit++
if(!LAZYLEN(console.output_info))
dat += "Failed to find a valid siphon pump as an outlet with the tag [console.output_tag].<br>"
bad_shit++
if(!bad_shit)
dat += "<B>STATUS:</B> NORMAL"
else
bad_shit = 0
dat += "<br>"
CHECK_TICK
var/datum/browser/popup = new(usr, "testatmoscontroller", "Test Atmos Monitoring Consoles", 500, 750)
popup.set_content(dat.Join())
popup.open()
/client/proc/cmd_admin_areatest(on_station)
set category = "Mapping"
set name = "Test Areas"
+95 -1
View File
@@ -38,7 +38,6 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
#ifdef TESTING
/client/proc/see_dirty_varedits,
#endif
/client/proc/cmd_admin_test_atmos_controllers,
/client/proc/cmd_admin_rejuvenate,
/datum/admins/proc/show_traitor_panel,
/client/proc/disable_communication,
@@ -54,6 +53,7 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
/client/proc/place_ruin,
/client/proc/station_food_debug,
/client/proc/station_stack_debug,
/client/proc/check_atmos_controls,
))
GLOBAL_PROTECT(admin_verbs_debug_mapping)
@@ -422,3 +422,97 @@ GLOBAL_VAR_INIT(say_disabled, FALSE)
popup.set_content(page_contents)
popup.open()
/// Checks the atmos monitor, sensors, meters, vents, and injectors, and makes sure they dont overlap or do nothing.
/client/proc/check_atmos_controls()
set name = "Check Atmos Chamber Devices"
set category = "Mapping"
if(SSticker.current_state == GAME_STATE_STARTUP)
to_chat(usr, "Game still loading, please run this again later!", confidential = TRUE)
return
message_admins(span_adminnotice("[key_name_admin(usr)] used the Test Atmos Controls debug command."))
log_admin("[key_name(usr)] used the Test Atmos Controls debug command.")
var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_ATMOS_STORAGE)
/// broadcaster[id_tag] = machine
var/list/broadcasters = list()
/// listened_to[atmos_chamber_entry] = bool
/// TRUE means we have the corresponding id_tag being listened to by an atmos control computer.
var/list/listened_to = list()
/// broadcasted_to[id_tag[1]] = bool
/// TRUE means we have the corresponding id_tag being broadcasted to by a device, be it meter, sensors, etc.
var/list/broadcasted_to = list()
/// How many things dont fit the recognized subtypes.
var/invalid_machine = 0
/// How many things have invalid (messes with our delimiter) tags.
var/invalid_tag = 0
/// How many things have empty tags, invalids but much worse.
var/tagless = 0
/// How many things have duped id_tag.
var/duplicate_tag = 0
/// How many things are broadcasting without an atmos computer listening
var/not_heard = 0
/// How many atmos computers are listening to an empty tag.
var/not_told = 0
var/list/valid_device_types = typecacheof(list(
/obj/machinery/computer/atmos_control,
/obj/machinery/air_sensor,
/obj/machinery/atmospherics/components/unary/outlet_injector/monitored,
/obj/machinery/meter/monitored,
/obj/machinery/atmospherics/components/unary/vent_pump/siphon/monitored,
/obj/machinery/atmospherics/components/unary/vent_pump/high_volume/siphon/monitored
))
var/list/valid_tag_endings = list("sensor", "in", "out")
for (var/datum/weakref/device_ref as anything in frequency.devices[RADIO_ATMOSIA])
var/obj/machinery/machine = device_ref.resolve()
if(!machine)
continue
if(!valid_device_types[machine.type])
to_chat(usr, "Unrecognized machine [ADMIN_VERBOSEJMP(machine)] under type [machine.type] in FREQ_ATMOS_STORAGE ([FREQ_ATMOS_STORAGE]) frequency.", confidential=TRUE)
invalid_machine += 1
continue
if(istype(machine,/obj/machinery/computer/atmos_control))
var/obj/machinery/computer/atmos_control/atmos_comp = machine
for(var/listened_tags in atmos_comp.atmos_chambers)
LAZYINITLIST(listened_to[listened_tags])
listened_to[listened_tags] += atmos_comp
continue
// Code below is for valid machineries that are not atmos control.
var/list/tags = splittext(machine.id_tag, "_")
if(tags.len == 0 || length(tags[1]) == 0)
to_chat(usr, "Machine [ADMIN_VERBOSEJMP(machine)] under type [machine.type] does not have a tag or have an empty identifier tag: [machine.id_tag]", confidential=TRUE)
tagless += 1
continue
if(tags.len != 2 || !(tags[2] in valid_tag_endings))
to_chat(usr, "Invalid tag for machine [ADMIN_VERBOSEJMP(machine)] under type [machine.type]. Tag = [machine.id_tag]", confidential=TRUE)
invalid_tag += 1
continue
if(broadcasters[machine.id_tag])
var/obj/original_machine = broadcasters[machine.id_tag]
to_chat(usr, "Duplicate machine id_tag ([machine.id_tag]) detected. Implicated machineries: [ADMIN_VERBOSEJMP(machine)] under [machine.type] and [ADMIN_VERBOSEJMP(original_machine)] under [original_machine.type]", confidential=TRUE)
duplicate_tag += 1
continue
broadcasters[machine.id_tag] = machine
LAZYINITLIST(broadcasted_to[tags[1]])
broadcasted_to[tags[1]] += machine
for (var/tag in listened_to)
if(!broadcasted_to[tag])
for (var/obj/computer in listened_to[tag])
to_chat(usr, "A computer [ADMIN_VERBOSEJMP(computer)] is listening to tag: [tag] yet it no devices is broadcasting there.", confidential=TRUE)
not_told += 1
for (var/tag in broadcasted_to)
if(!listened_to[tag])
for (var/obj/machine in broadcasted_to[tag])
to_chat(usr, "A machinery [ADMIN_VERBOSEJMP(machine)] is broadcasting in tag: [tag] yet there are no listeners. Are you sure you want to use a monitored atmos device?", confidential=TRUE)
not_heard += 1
if(!(invalid_machine || invalid_tag || tagless || duplicate_tag || not_heard || not_told))
to_chat(usr, "Atmos control frequency check passed without encountering problems.", confidential=TRUE)
else
to_chat(usr, "Total errors: [invalid_machine + invalid_tag + tagless + duplicate_tag + not_heard + not_told]", confidential=TRUE)