[MIRROR] Integrated circuits for modular computers (#26196)

Integrated circuits for modular computers (#80530)

This PR integrates circuits for modular computers and a good bits of
their programs.
The peculiarity here is that modular computers have no fixed amount of
unremovable components (except the base one with just a couple ports for
now), instead, they're added and removed along with programs. With a few
exceptions (such as the messenger and signaler), for these program
circuits to work, their associated program has to be either open or in
the background.

For a reason or another, not all programs have a circuit associated to
them, still, however the programs with a circuit are still a handful.
They are:
- Nanotrasen Pay System
- Notepad
- SiliConnect
- WireCarp
- MODsuit Control
- Spectre Meter
- Direct Messenger*
- LifeConnect
- Custodial Locator
- Fission360
- Camera
- Status Display
- SignalCommander

*By the by, sending messages has a cooldown, so it shouldn't be as
spammy. If it turns out to not be enough, I can make it so messages from
circuit will be ignored by other messenger circuits.

The PR is no longer WIP.

I believe modular computers could make for some interesting setups with
circuits, since they're fairly flexible and stocked with features unlike
many other appliances, therefore also a speck more abusable, though
limits, cooldowns, logging and sanitization have been implemented to
keep it in check.

🆑
add: Modular Computers now support integrated circuits. What can be done
with them depends on the programs installed and whether they're running
(open or background).
add: Modular Consoles (the machinery) now have a small backup cell they
draw power from if the power goes out.
/🆑

Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
This commit is contained in:
SkyratBot
2024-01-21 15:59:14 +01:00
committed by GitHub
parent ab5a4d0f99
commit fdcfabefd8
60 changed files with 1286 additions and 240 deletions
@@ -44,6 +44,40 @@
var/alert_pending = FALSE
/// How well this program will help combat detomatix viruses.
var/detomatix_resistance = NONE
/// Unremovable circuit componentn added to the physical computer while the program is installed
var/obj/item/circuit_component/mod_program/circuit_comp_type
/datum/computer_file/program/New()
..()
///We need to ensure that different programs (subtypes mostly) won't try to load in the same circuit comps into the shell or usb port of the modpc.
if(circuit_comp_type && initial(circuit_comp_type.associated_program) != type)
stack_trace("circuit comp type mismatch: [type] has circuit comp type \[[circuit_comp_type]\], while \[[circuit_comp_type]\] has associated program \[[initial(circuit_comp_type.associated_program)]\].")
/**
* Here we deal with peculiarity of adding unremovable components to the computer shell.
* It probably doesn't look badass, but it's a decent way of doing it without taining the component with
* oddities like this.
*/
/datum/computer_file/program/on_install(datum/computer_file/source, obj/item/modular_computer/computer_installing)
. = ..()
if(isnull(circuit_comp_type) || isnull(computer.shell))
return
if(!(locate(circuit_comp_type) in computer.shell.unremovable_circuit_components))
var/obj/item/circuit_component/mod_program/comp = new circuit_comp_type()
computer.shell.add_unremovable_circuit_component(comp)
if(computer.shell.attached_circuit)
comp.forceMove(computer.shell.attached_circuit)
computer.shell.attached_circuit.add_component(comp)
///Here we deal with killing the associated components instead.
/datum/computer_file/program/Destroy()
if(isnull(circuit_comp_type) || isnull(computer?.shell))
return ..()
for(var/obj/item/circuit_component/mod_program/comp in computer.shell.unremovable_circuit_components)
if(comp.associated_program == src)
computer.shell.unremovable_circuit_components -= comp
qdel(comp)
return ..()
/datum/computer_file/program/clone()
var/datum/computer_file/program/temp = ..()
@@ -67,10 +101,6 @@
/datum/computer_file/program/ui_interact(mob/user, datum/tgui/ui)
SHOULD_CALL_PARENT(FALSE)
///We are not calling parent as it's handled by the computer itself, this is only called after.
/datum/computer_file/program/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
SHOULD_CALL_PARENT(FALSE)
// Relays icon update to the computer.
/datum/computer_file/program/proc/update_computer_icon()
if(computer)
@@ -167,12 +197,13 @@
**/
/datum/computer_file/program/proc/on_start(mob/living/user)
SHOULD_CALL_PARENT(TRUE)
if(can_run(user, loud = TRUE))
if(program_flags & PROGRAM_REQUIRES_NTNET)
var/obj/item/card/id/ID = computer.computer_id_slot?.GetID()
generate_network_log("Connection opened -- Program ID:[filename] User:[ID?"[ID.registered_name]":"None"]")
return TRUE
return FALSE
if(!can_run(user, loud = TRUE))
return FALSE
if(program_flags & PROGRAM_REQUIRES_NTNET)
var/obj/item/card/id/ID = computer.computer_id_slot?.GetID()
generate_network_log("Connection opened -- Program ID:[filename] User:[ID?"[ID.registered_name]":"None"]")
SEND_SIGNAL(src, COMSIG_COMPUTER_PROGRAM_START, user)
return TRUE
/**
* Kills the running program
@@ -189,25 +220,29 @@
computer.active_program = null
if(!QDELETED(computer) && computer.enabled)
INVOKE_ASYNC(computer, TYPE_PROC_REF(/obj/item/modular_computer, update_tablet_open_uis), user)
if(src in computer.idle_threads)
else if(src in computer.idle_threads)
computer.idle_threads.Remove(src)
else //The program wasn't running to begin with.
return FALSE
if(program_flags & PROGRAM_REQUIRES_NTNET)
var/obj/item/card/id/ID = computer.computer_id_slot?.GetID()
generate_network_log("Connection closed -- Program ID: [filename] User:[ID ? "[ID.registered_name]" : "None"]")
computer.update_appearance(UPDATE_ICON)
SEND_SIGNAL(src, COMSIG_COMPUTER_PROGRAM_KILL, user)
return TRUE
///Sends the running program to the background/idle threads. Header programs can't be minimized and will kill instead.
/datum/computer_file/program/proc/background_program()
/datum/computer_file/program/proc/background_program(mob/user)
SHOULD_CALL_PARENT(TRUE)
if(program_flags & PROGRAM_HEADER)
if(program_flags & PROGRAM_HEADER || length(computer.idle_threads) > computer.max_idle_programs)
return kill_program()
computer.idle_threads.Add(src)
computer.active_program = null
computer.update_tablet_open_uis(usr)
if(user)
INVOKE_ASYNC(computer, TYPE_PROC_REF(/obj/item/modular_computer, update_tablet_open_uis), user)
computer.update_appearance(UPDATE_ICON)
return TRUE