Fixes bugs with admin circuits, expands upon some admin circuit components and fixes duplicator runtiming when a port doesn't exist. (#61948)

Co-authored-by: Watermelon914 <3052169-Watermelon914@users.noreply.gitlab.com>
This commit is contained in:
Watermelon914
2021-10-10 11:36:25 +01:00
committed by GitHub
parent 9211ddbe31
commit 0ebf4891ad
5 changed files with 90 additions and 44 deletions

View File

@@ -8,7 +8,7 @@
*/
/obj/item/circuit_component/signal_handler
display_name = "Signal Handler"
desc = "A component that listens for signals on an object. Registering a new object will automatically unregister the old."
desc = "A component that listens for signals on an object."
circuit_flags = CIRCUIT_FLAG_ADMIN|CIRCUIT_FLAG_INSTANT
/// Whether it is a global or object signal
@@ -17,14 +17,19 @@
/// The list of signal IDs that can be selected as an option.
var/datum/port/input/option/signal_id
/// Whether this executes instantly or not. If set to 0, this will not execute instantly.
var/datum/port/input/instant
var/list/signal_map
/// Entity to register the signal on
var/datum/port/input/target
/// Registers the signal
var/datum/port/input/register
/// Unregisters the signal from the current registered entity.
/// Unregisters the signal on the target.
var/datum/port/input/unregister
/// Unregisters the signal from everyone.
var/datum/port/input/unregister_all
/// The custom signal ports from the current signal type. Used for saving and loading.
var/list/signal_ports
@@ -38,8 +43,8 @@
/// The event has been triggered
var/datum/port/output/event_triggered
/// The current entity that has the signal registered on it
var/datum/weakref/current_registered_entity
/// The current entities that have the signal registered on it
var/list/datum/weakref/registered_entities = list()
/// The current registered signal
var/registered_signal
@@ -57,8 +62,10 @@
signal_map = GLOB.integrated_circuit_signal_ids
/obj/item/circuit_component/signal_handler/populate_ports()
instant = add_input_port("Instant", PORT_TYPE_NUMBER, order = 0.5, trigger = null, default = 1)
register = add_input_port("Register", PORT_TYPE_SIGNAL, order = 2, trigger = .proc/register_signals)
unregister = add_input_port("Unregister Current", PORT_TYPE_SIGNAL, order = 2, trigger = .proc/unregister_signals)
unregister = add_input_port("Unregister", PORT_TYPE_SIGNAL, order = 2, trigger = .proc/unregister_signals)
unregister_all = add_input_port("Unregister All", PORT_TYPE_SIGNAL, order = 2, trigger = .proc/unregister_signals_all)
add_source_entity()
event_triggered = add_output_port("Triggered", PORT_TYPE_INSTANT_SIGNAL, order = 2)
@@ -86,19 +93,13 @@
/obj/item/circuit_component/signal_handler/pre_input_received(datum/port/input/port)
if(signal_id == port)
if(signal_id.value != registered_signal)
custom_signal = FALSE
if(current_registered_entity)
unregister_signals(port)
var/last_registered_signal = registered_signal
unregister_signals_all(port)
registered_signal = signal_id.value
if(registered_signal != last_registered_signal)
var/list/data = signal_map[registered_signal]
if(data)
load_new_ports(data)
unregister_signals(port)
var/list/data = signal_map[registered_signal]
if(data)
load_new_ports(data)
if(signal_handler_options == port)
set_signal_options(port)
@@ -112,6 +113,8 @@
signal_map = GLOB.integrated_circuit_global_signal_ids
remove_output_port(entity)
remove_input_port(target)
target = null
entity = null
if(COMP_SIGNAL_HANDLER_OBJECT)
signal_id.possible_options = GLOB.integrated_circuit_signal_ids
signal_map = GLOB.integrated_circuit_signal_ids
@@ -119,20 +122,18 @@
if(!custom_signal)
signal_id.set_value(null, TRUE)
unregister_signals()
unregister_signals_all(port)
/obj/item/circuit_component/signal_handler/proc/register_signals(datum/port/input/port)
CIRCUIT_TRIGGER
if(current_registered_entity)
unregister_signals(port)
var/datum/target_datum = target.value
var/datum/target_datum = target?.value
if(signal_handler_options.value == COMP_SIGNAL_HANDLER_GLOBAL)
target_datum = SSdcs
if(target_datum)
RegisterSignal(target_datum, registered_signal, .proc/handle_signal_received)
current_registered_entity = WEAKREF(target_datum)
// We override because an admin may try registering a signal on the same object/datum again, so this prevents any runtimes from occuring
RegisterSignal(target_datum, registered_signal, .proc/handle_signal_received, override = TRUE)
registered_entities |= WEAKREF(target_datum)
/obj/item/circuit_component/signal_handler/proc/load_new_ports(list/ports_to_load)
for(var/datum/port/input/input_port as anything in input_signal_ports)
@@ -145,26 +146,51 @@
signal_ports = ports_to_load
for(var/list/data in signal_ports)
if(data["is_response"])
var/datum/port/input/bitflag_input = add_input_port(data["name"], PORT_TYPE_RESPONSE_SIGNAL, order = 1, trigger = .proc/handle_bitflag_received)
var/datum/port/input/bitflag_input = add_input_port(data["name"], PORT_TYPE_SIGNAL, order = 3, trigger = .proc/handle_bitflag_received)
input_signal_ports[bitflag_input] = data["bitflag"]
else
output_signal_ports += add_output_port(data["name"], data["type"], order = 1)
/obj/item/circuit_component/signal_handler/proc/unregister_signals_all(datum/port/input/port)
CIRCUIT_TRIGGER
for(var/datum/weakref/weakref_of_object as anything in registered_entities)
var/datum/datum_to_unregister = weakref_of_object.resolve()
if(!datum_to_unregister)
continue
UnregisterSignal(datum_to_unregister, registered_signal)
registered_entities.Cut()
/obj/item/circuit_component/signal_handler/proc/unregister_signals(datum/port/input/port)
CIRCUIT_TRIGGER
var/datum/registered_datum = current_registered_entity?.resolve()
var/datum/registered_datum = target?.value
if(signal_handler_options.value == COMP_SIGNAL_HANDLER_GLOBAL)
registered_datum = SSdcs
if(!registered_datum)
return
UnregisterSignal(registered_datum, registered_signal)
current_registered_entity = null
registered_entities -= WEAKREF(registered_datum)
/obj/item/circuit_component/signal_handler/proc/run_ports_on_args(list/arguments)
var/first_arg = popleft(arguments)
if(entity)
entity.set_output(first_arg)
for(var/datum/port/output/port as anything in output_signal_ports)
port.set_output(popleft(arguments))
event_triggered.set_output(COMPONENT_SIGNAL)
/obj/item/circuit_component/signal_handler/proc/handle_signal_received(...)
SIGNAL_HANDLER
var/list/arguments = args.Copy()
if(!instant.value)
run_ports_on_args(arguments)
return
// usr is not supposed to be defined whilst these execute, which it can be for some signal IDs.
// Especially if you try to proccall something - it'll fail because of this reason.
// No other way to solve this problem without refactoring proccall code, but it's admin tooling so it's whatever.
@@ -172,13 +198,7 @@
usr = null
SScircuit_component.queue_instant_run()
var/first_arg = popleft(arguments)
if(entity)
entity.set_output(first_arg)
for(var/datum/port/output/port as anything in output_signal_ports)
port.set_output(popleft(arguments))
event_triggered.set_output(COMPONENT_SIGNAL)
run_ports_on_args(arguments)
var/list/output = SScircuit_component.execute_instant_run()
usr = temp_usr