mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-12 18:51:53 +00:00
Makes the code compatible with 515.1594+
Few simple changes and one very painful one.
Let's start with the easy:
* puts call behind `LIBCALL` define, so call_ext is properly used in 515
* Adds `NAMEOF_STATIC(_,X)` macro for nameof in static definitions since
src is now invalid there.
* Fixes tgui and devserver. From 515 onward the tmp3333{procid} cache
directory is not appened to base path in browser controls so we don't
check for it in base js and put the dev server dummy window file in
actual directory not the byond root.
* Renames the few things that had /final/ in typepath to ultimate since
final is a new keyword
And the very painful change:
`.proc/whatever` format is no longer valid, so we're replacing it with
new nameof() function. All this wrapped in three new macros.
`PROC_REF(X)`,`TYPE_PROC_REF(TYPE,X)`,`GLOBAL_PROC_REF(X)`. Global is
not actually necessary but if we get nameof that does not allow globals
it would be nice validation.
This is pretty unwieldy but there's no real alternative.
If you notice anything weird in the commits let me know because majority
was done with regex replace.
@tgstation/commit-access Since the .proc/stuff is pretty big change.
Co-authored-by: san7890 <the@san7890.com>
Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
230 lines
8.4 KiB
Plaintext
230 lines
8.4 KiB
Plaintext
#define COMP_SIGNAL_HANDLER_GLOBAL "Global"
|
|
#define COMP_SIGNAL_HANDLER_OBJECT "Object"
|
|
|
|
/**
|
|
* # Signal Handler Component
|
|
*
|
|
* A component that registers signals on events and listens for them.
|
|
*/
|
|
/obj/item/circuit_component/signal_handler
|
|
display_name = "Signal Handler"
|
|
desc = "A component that listens for signals on an object."
|
|
category = "Admin"
|
|
circuit_flags = CIRCUIT_FLAG_ADMIN|CIRCUIT_FLAG_INSTANT
|
|
|
|
/// Whether it is a global or object signal
|
|
var/datum/port/input/option/signal_handler_options
|
|
|
|
/// 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 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
|
|
/// The custom input from the current signal type.
|
|
var/list/datum/port/input/input_signal_ports = list()
|
|
/// The custom output from the current signal type.
|
|
var/list/datum/port/output/output_signal_ports = list()
|
|
|
|
/// The entity received from the event.
|
|
var/datum/port/output/entity
|
|
/// The event has been triggered
|
|
var/datum/port/output/event_triggered
|
|
|
|
/// The current entities that have the signal registered on it
|
|
var/list/datum/weakref/registered_entities = list()
|
|
/// The current registered signal
|
|
var/registered_signal
|
|
|
|
/// Whether it is a custom signal id or not.
|
|
var/custom_signal = FALSE
|
|
|
|
/obj/item/circuit_component/signal_handler/populate_options()
|
|
var/static/list/component_options = list(
|
|
COMP_SIGNAL_HANDLER_OBJECT,
|
|
COMP_SIGNAL_HANDLER_GLOBAL,
|
|
)
|
|
signal_handler_options = add_option_port("Signal Handler Options", component_options, trigger = null)
|
|
|
|
signal_id = add_option_port("Signal ID", GLOB.integrated_circuit_signal_ids, trigger = null)
|
|
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_REF(register_signals))
|
|
unregister = add_input_port("Unregister", PORT_TYPE_SIGNAL, order = 2, trigger = PROC_REF(unregister_signals))
|
|
unregister_all = add_input_port("Unregister All", PORT_TYPE_SIGNAL, order = 2, trigger = PROC_REF(unregister_signals_all))
|
|
|
|
add_source_entity()
|
|
event_triggered = add_output_port("Triggered", PORT_TYPE_INSTANT_SIGNAL, order = 2)
|
|
|
|
/obj/item/circuit_component/signal_handler/proc/add_source_entity()
|
|
if(target)
|
|
remove_input_port(target)
|
|
if(entity)
|
|
remove_output_port(entity)
|
|
|
|
target = add_input_port("Target", PORT_TYPE_DATUM, order = 1, trigger = null)
|
|
entity = add_output_port("Source Entity", PORT_TYPE_DATUM, order = 0)
|
|
|
|
/obj/item/circuit_component/signal_handler/save_data_to_list(list/component_data)
|
|
. = ..()
|
|
component_data["signal_id"] = signal_id.value
|
|
component_data["signal_port_data"] = signal_ports
|
|
|
|
/obj/item/circuit_component/signal_handler/load_data_from_list(list/component_data)
|
|
signal_id.set_value(component_data["signal_id"], force = TRUE)
|
|
registered_signal = signal_id.value
|
|
load_new_ports(component_data["signal_port_data"])
|
|
custom_signal = TRUE
|
|
return ..()
|
|
|
|
|
|
/obj/item/circuit_component/signal_handler/pre_input_received(datum/port/input/port)
|
|
if(signal_id.value != registered_signal)
|
|
custom_signal = FALSE
|
|
unregister_signals_all(port)
|
|
registered_signal = signal_id.value
|
|
var/list/data = signal_map[registered_signal]
|
|
if(data)
|
|
load_new_ports(data)
|
|
|
|
if(signal_handler_options == port)
|
|
set_signal_options(port)
|
|
|
|
/obj/item/circuit_component/signal_handler/proc/set_signal_options(datum/port/input/port)
|
|
CIRCUIT_TRIGGER
|
|
|
|
switch(signal_handler_options.value)
|
|
if(COMP_SIGNAL_HANDLER_GLOBAL)
|
|
signal_id.possible_options = GLOB.integrated_circuit_global_signal_ids
|
|
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
|
|
add_source_entity()
|
|
|
|
if(!custom_signal)
|
|
signal_id.set_value(null, TRUE)
|
|
unregister_signals_all(port)
|
|
|
|
/obj/item/circuit_component/signal_handler/proc/register_signals(datum/port/input/port)
|
|
CIRCUIT_TRIGGER
|
|
var/datum/target_datum = target?.value
|
|
if(signal_handler_options.value == COMP_SIGNAL_HANDLER_GLOBAL)
|
|
target_datum = SSdcs
|
|
|
|
if(target_datum)
|
|
log_admin_circuit("[parent.get_creator()] registered the signal '[registered_signal]' on [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_REF(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)
|
|
remove_input_port(input_port)
|
|
for(var/datum/port/output/output_port as anything in output_signal_ports)
|
|
remove_output_port(output_port)
|
|
input_signal_ports = list()
|
|
output_signal_ports = list()
|
|
|
|
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_SIGNAL, order = 3, trigger = PROC_REF(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 = target?.value
|
|
if(signal_handler_options.value == COMP_SIGNAL_HANDLER_GLOBAL)
|
|
registered_datum = SSdcs
|
|
|
|
if(!registered_datum)
|
|
return
|
|
|
|
UnregisterSignal(registered_datum, registered_signal)
|
|
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.
|
|
var/temp_usr = usr
|
|
usr = null
|
|
|
|
var/list/displayArgs = arguments.Copy()
|
|
log_admin_circuit("[parent.get_creator()] received a signal from [popleft(displayArgs)] ([registered_signal]) with the parameters \[[displayArgs.Join(", ")]]")
|
|
SScircuit_component.queue_instant_run()
|
|
run_ports_on_args(arguments)
|
|
var/list/output = SScircuit_component.execute_instant_run()
|
|
|
|
usr = temp_usr
|
|
|
|
if(!output)
|
|
message_admins("[parent.get_creator_admin()] took too much CPU time trying to handle a signal. Reduce the amount of circuit components attached to your [name] circuit component.")
|
|
return
|
|
|
|
return output["bitflag"] || NONE
|
|
|
|
/obj/item/circuit_component/signal_handler/proc/handle_bitflag_received(datum/port/input/port, list/return_values)
|
|
CIRCUIT_TRIGGER
|
|
if(!return_values)
|
|
return
|
|
|
|
if(!return_values["bitflag"])
|
|
return_values["bitflag"] = NONE
|
|
|
|
var/bitflag = input_signal_ports[port]
|
|
log_admin_circuit("[parent.get_creator()] received bitflag [bitflag] for '[registered_signal]'")
|
|
return_values["bitflag"] |= bitflag
|
|
|
|
#undef COMP_SIGNAL_HANDLER_GLOBAL
|
|
#undef COMP_SIGNAL_HANDLER_OBJECT
|