Files
Bubberstation/code/modules/modular_computers/file_system/program_circuit.dm
Ghom 3f1c159904 [NO GBP] Fixing issues with modular computer and circuits. (#81076)
## About The Pull Request
It turns out the messenger circuit wasn't working as intended, because
list components tend to convert datum keys into weakrefs, creating
incoherence between composite datum/atom and simple datum/atom
datatypes, which at least just spares us from the headache of clearing
the refs on del from lists too.

So, taking the shortest path, I decided to adapt the messenger to the
weak ref usage.

Another thing, instead of refusing altogether to send message that
trigger the pda filter regexes, the messenger circuit will instead
replace the matches with grawlix, since we have no way to inform
whoever's responsible for said message about the filters in an orthodox
way.

Beside that, I've noticed several of the circuits from my PR were
lacking trigger outputs or similar when needed, pretty making them only
as half as functional, at least to a noob like me.

And another small issue with missing ports from the status display
circuit.

One more suggestion from moocow is to add a cooldown to the ringtone
trigger for the messenger circuit, because he said it's pretty spammy
and some admins are fickle.

## Why It's Good For The Game
Bugfixing and improvements.

## Changelog

🆑
fix: Fixed the messenger circuit not sending messages.
fix: Added several ports to modpc circuits that were missing or needing
them.
fix: Fixes ever-expanding ports whenever circuits are re-inserted in a
modular computer.
/🆑
2024-01-25 09:11:45 -05:00

96 lines
4.1 KiB
Plaintext

/**
* Circuit components of modular programs are special.
* They're added to the unremovable components of the shell when the prog is installed and deleted if uninstalled.
* This means they don't work like normal unremovable comps that live and die along with their shell.
*/
/obj/item/circuit_component/mod_program
display_name = "Abstract Modular Program"
desc = "I've spent lot of time thinking how to get this to work. If you see this, I either failed or someone else did, so report it."
/**
* The program that installed us into the shell/usb_port comp. Needed to avoid having too many signals for every program.
* This is also the program we need to install on the modular computer if the circuit is admin-loaded.
* Just make sure each of these components is associated to one and only type of program, no subtypes of anything.
*/
var/datum/computer_file/program/associated_program
///Starts the program if possible, placing it in the background if another's active.
var/datum/port/input/start
///kills the program.
var/datum/port/input/kill
///binary for whether the program is running or not
var/datum/port/output/running
/obj/item/circuit_component/mod_program/Initialize(mapload)
if(associated_program)
display_name = initial(associated_program.filedesc)
desc = initial(associated_program.extended_desc)
return ..() // Set the name correctly
/obj/item/circuit_component/mod_program/register_shell(atom/movable/shell)
. = ..()
var/obj/item/modular_computer/computer
if(istype(shell, /obj/item/modular_computer))
computer = shell
else if(istype(shell, /obj/machinery/modular_computer))
var/obj/machinery/modular_computer/console = shell
computer = console.cpu
///Find the associated program in the computer's stored_files (install it otherwise) and store a reference to it.
var/datum/computer_file/program/found_program = locate(associated_program) in computer.stored_files
///The integrated circuit was loaded/duplicated
if(isnull(found_program))
associated_program = new associated_program()
computer.store_file(associated_program)
else
associated_program = found_program
RegisterSignal(associated_program, COMSIG_COMPUTER_PROGRAM_START, PROC_REF(on_start))
RegisterSignal(associated_program, COMSIG_COMPUTER_PROGRAM_KILL, PROC_REF(on_kill))
/obj/item/circuit_component/mod_program/unregister_shell()
UnregisterSignal(associated_program, list(COMSIG_COMPUTER_PROGRAM_START, COMSIG_COMPUTER_PROGRAM_KILL))
associated_program = initial(associated_program)
return ..()
/obj/item/circuit_component/mod_program/populate_ports()
. = ..()
SHOULD_CALL_PARENT(TRUE)
start = add_input_port("Start", PORT_TYPE_SIGNAL, trigger = PROC_REF(start_prog))
kill = add_input_port("Kill", PORT_TYPE_SIGNAL, trigger = PROC_REF(kill_prog))
running = add_output_port("Running", PORT_TYPE_NUMBER)
///For most programs, triggers only work if they're open (either active or idle).
/obj/item/circuit_component/mod_program/should_receive_input(datum/port/input/port)
. = ..()
if(!.)
return FALSE
if(isnull(associated_program))
return FALSE
if(!associated_program.computer.enabled)
return FALSE
if(associated_program.program_flags & PROGRAM_CIRCUITS_RUN_WHEN_CLOSED || COMPONENT_TRIGGERED_BY(start, port))
return TRUE
var/obj/item/modular_computer/computer = associated_program.computer
if(computer.active_program == associated_program || (associated_program in computer.idle_threads))
return TRUE
return FALSE
/obj/item/circuit_component/mod_program/proc/start_prog(datum/port/input/port)
associated_program.computer.open_program(program = associated_program)
/obj/item/circuit_component/mod_program/proc/on_start(mob/living/user)
SIGNAL_HANDLER
running.set_output(TRUE)
/obj/item/circuit_component/mod_program/proc/kill_prog(datum/port/input/port)
associated_program.kill_program()
/obj/item/circuit_component/mod_program/proc/on_kill(mob/living/user)
SIGNAL_HANDLER
running.set_output(FALSE)
/obj/item/circuit_component/mod_program/get_ui_notices()
. = ..()
if(!(associated_program.program_flags & PROGRAM_CIRCUITS_RUN_WHEN_CLOSED))
. += create_ui_notice("Requires open program for inputs", "purple")