diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 0b1596e5694..b0e5ea8f412 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -1459,6 +1459,12 @@ /// Called in /obj/structure/moneybot/add_money(). (to_add) #define COMSIG_MONEYBOT_ADD_MONEY "moneybot_add_money" +/// Called in /obj/structure/dispenserbot/add_item(). (obj/item/to_add) +#define COMSIG_DISPENSERBOT_ADD_ITEM "moneybot_add_item" + +/// Called in /obj/structure/dispenserbot/remove_item(). (obj/item/to_remove) +#define COMSIG_DISPENSERBOT_REMOVE_ITEM "moneybot_remove_item" + /// Called when somebody passes through a scanner gate and it triggers #define COMSIG_SCANGATE_PASS_TRIGGER "scangate_pass_trigger" diff --git a/code/__DEFINES/wiremod.dm b/code/__DEFINES/wiremod.dm index 43038a63195..5ccc49b39ad 100644 --- a/code/__DEFINES/wiremod.dm +++ b/code/__DEFINES/wiremod.dm @@ -22,15 +22,20 @@ #define PORT_TYPE_NUMBER "number" /// Signal datatype #define PORT_TYPE_SIGNAL "signal" -/// List datatype -#define PORT_TYPE_LIST "list" -/// Associative List datatype. Derivative of list. -#define PORT_TYPE_ASSOC_LIST "assoc list" /// Table datatype. Derivative of list, contains other lists with matching columns. #define PORT_TYPE_TABLE "table" /// Options datatype. Derivative of string. #define PORT_TYPE_OPTION "option" +// Composite datatypes +#define PORT_COMPOSITE_TYPE_LIST "list" +/// List datatype +#define PORT_TYPE_LIST(datatype) SSwiremod_composite.composite_datatype(PORT_COMPOSITE_TYPE_LIST, datatype) + +#define PORT_COMPOSITE_TYPE_ASSOC_LIST "assoc list" +/// Associative List datatype. Derivative of list. +#define PORT_TYPE_ASSOC_LIST(key_datatype, datatype) SSwiremod_composite.composite_datatype(PORT_COMPOSITE_TYPE_ASSOC_LIST, key_datatype, datatype) + // Other datatypes /// Atom datatype #define PORT_TYPE_ATOM "entity" @@ -110,3 +115,5 @@ #define DATATYPE_FLAG_ALLOW_MANUAL_INPUT (1<<0) /// The datatype won't update the value when it is connected to the port #define DATATYPE_FLAG_AVOID_VALUE_UPDATE (1<<1) +/// The datatype has been generated and is an existing composite datatype +#define DATATYPE_FLAG_COMPOSITE (1<<2) diff --git a/code/_globalvars/lists/wiremod.dm b/code/_globalvars/lists/wiremod.dm index ea1349ee5a4..3737af99fe5 100644 --- a/code/_globalvars/lists/wiremod.dm +++ b/code/_globalvars/lists/wiremod.dm @@ -4,9 +4,7 @@ GLOBAL_LIST_INIT(wiremod_basic_types, list( PORT_TYPE_STRING, PORT_TYPE_NUMBER, PORT_TYPE_SIGNAL, - PORT_TYPE_LIST, PORT_TYPE_TABLE, - PORT_TYPE_ASSOC_LIST, PORT_TYPE_ATOM, )) @@ -16,7 +14,7 @@ GLOBAL_LIST_INIT(wiremod_fundamental_types, list( PORT_TYPE_NUMBER, PORT_TYPE_ATOM, PORT_TYPE_DATUM, + PORT_TYPE_LIST(PORT_TYPE_ANY), PORT_TYPE_STRING, - PORT_TYPE_LIST, - PORT_TYPE_ASSOC_LIST, + PORT_TYPE_ASSOC_LIST(PORT_TYPE_ANY, PORT_TYPE_ANY), )) diff --git a/code/controllers/subsystem/circuit_component.dm b/code/controllers/subsystem/circuit_component.dm index 0ee631071e9..544f141e65e 100644 --- a/code/controllers/subsystem/circuit_component.dm +++ b/code/controllers/subsystem/circuit_component.dm @@ -6,6 +6,8 @@ SUBSYSTEM_DEF(circuit_component) var/list/callbacks_to_invoke = list() var/list/currentrun = list() + var/list/instant_run_stack = list() + var/instant_run_tick = 0 var/instant_run_start_cpu_usage = 0 var/instant_run_max_cpu_usage = 10 @@ -45,9 +47,17 @@ SUBSYSTEM_DEF(circuit_component) callbacks_to_invoke += to_call /// Queues any callbacks to be executed instantly instead of using the subsystem. -/datum/controller/subsystem/circuit_component/proc/queue_instant_run() +/datum/controller/subsystem/circuit_component/proc/queue_instant_run(start_cpu_time) + if(instant_run_tick) + instant_run_stack += list(instant_run_callbacks_to_run) + // If we're already instantly executing, don't change the start_cpu_time. + start_cpu_time = instant_run_start_cpu_usage + + if(!start_cpu_time) + start_cpu_time = TICK_USAGE + instant_run_tick = world.time - instant_run_start_cpu_usage = TICK_USAGE + instant_run_start_cpu_usage = start_cpu_time instant_run_callbacks_to_run = list() /** @@ -67,7 +77,11 @@ SUBSYSTEM_DEF(circuit_component) to_call.InvokeAsync(received_inputs) qdel(to_call) - instant_run_tick = 0 + if(length(instant_run_stack)) + instant_run_callbacks_to_run = pop(instant_run_stack) + else + instant_run_tick = 0 + if((TICK_USAGE - instant_run_start_cpu_usage) < instant_run_max_cpu_usage) return received_inputs else diff --git a/code/controllers/subsystem/wiremod_composite.dm b/code/controllers/subsystem/wiremod_composite.dm new file mode 100644 index 00000000000..33863f073ea --- /dev/null +++ b/code/controllers/subsystem/wiremod_composite.dm @@ -0,0 +1,42 @@ +/** + * This subsystem is to handle creating and storing + * composite templates that are used to create composite datatypes + * for integrated circuits + * + * See: https://en.wikipedia.org/wiki/Composite_data_type + **/ +SUBSYSTEM_DEF(wiremod_composite) + name = "Wiremod Composite Templates" + flags = SS_NO_FIRE + /// The templates created and stored + var/list/templates = list() + +/datum/controller/subsystem/wiremod_composite/New() + . = ..() + // This needs to execute before global variables have initialized. + for(var/datum/circuit_composite_template/type as anything in subtypesof(/datum/circuit_composite_template)) + if(!initial(type.datatype)) + continue + templates[initial(type.datatype)] = new type() + +/datum/controller/subsystem/wiremod_composite/Initialize(start_timeofday) + . = ..() + for(var/type in templates) + var/datum/circuit_composite_template/template = templates[type] + template.Initialize() + +/** + * Used to produce a composite datatype using another datatype, or + * to get an already existing composite datatype. + */ +/datum/controller/subsystem/wiremod_composite/proc/composite_datatype(datatype, ...) + var/datum/circuit_composite_template/type = templates[datatype] + if(!type) + return + return type.generate_composite_type(args.Copy(2)) + +/datum/controller/subsystem/wiremod_composite/proc/get_composite_type(base_type, datatype) + var/datum/circuit_composite_template/template = templates[base_type] + if(!template) + return + return template.generated_types[datatype] diff --git a/code/datums/components/shell.dm b/code/datums/components/shell.dm index 9f519bcc259..037aaea617b 100644 --- a/code/datums/components/shell.dm +++ b/code/datums/components/shell.dm @@ -165,7 +165,7 @@ if(istype(item, /obj/item/circuit_component)) attached_circuit.add_component_manually(item, attacker) - return + return COMPONENT_NO_AFTERATTACK if(!istype(item, /obj/item/integrated_circuit)) return diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm index b19f518b733..c3f7d25c266 100644 --- a/code/game/machinery/computer/teleporter.dm +++ b/code/game/machinery/computer/teleporter.dm @@ -234,7 +234,7 @@ update_trigger = add_input_port("Update Targets", PORT_TYPE_SIGNAL) current_target = add_output_port("Current Target", PORT_TYPE_STRING) - possible_targets = add_output_port("Possible Targets", PORT_TYPE_LIST) + possible_targets = add_output_port("Possible Targets", PORT_TYPE_LIST(PORT_TYPE_ANY)) on_fail = add_output_port("Failed", PORT_TYPE_SIGNAL) /obj/item/circuit_component/teleporter_control_console/register_usb_parent(atom/movable/shell) diff --git a/code/modules/research/designs/wiremod_designs.dm b/code/modules/research/designs/wiremod_designs.dm index f2bb657aa8f..620882e14b1 100644 --- a/code/modules/research/designs/wiremod_designs.dm +++ b/code/modules/research/designs/wiremod_designs.dm @@ -73,6 +73,11 @@ id = "comp_index" build_path = /obj/item/circuit_component/index +/datum/design/component/index_assoc + name = "Index Associative List Component" + id = "comp_index_assoc" + build_path = /obj/item/circuit_component/index/assoc_string + /datum/design/component/length name = "Length Component" id = "comp_length" diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 704e46cb236..ffbdd0851d4 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -211,6 +211,7 @@ "comp_health", "comp_hear", "comp_index", + "comp_index_assoc", "comp_index_table", "comp_length", "comp_light", diff --git a/code/modules/wiremod/components/utility/getter.dm b/code/modules/wiremod/components/abstract/variable.dm similarity index 56% rename from code/modules/wiremod/components/utility/getter.dm rename to code/modules/wiremod/components/abstract/variable.dm index 399a2969164..d8070b70876 100644 --- a/code/modules/wiremod/components/utility/getter.dm +++ b/code/modules/wiremod/components/abstract/variable.dm @@ -1,63 +1,53 @@ /** - * # Getter Component + * # Variable Component * - * Gets the current value from a variable. + * Abstract component for handling variables */ -/obj/item/circuit_component/getter +/obj/item/circuit_component/variable display_name = "Variable Getter" desc = "A component that gets a variable globally on the circuit." /// Variable name var/datum/port/input/option/variable_name - /// The value of the variable - var/datum/port/output/value - var/datum/circuit_variable/current_variable - circuit_size = 0 -/obj/item/circuit_component/getter/populate_options() +/obj/item/circuit_component/variable/populate_options() variable_name = add_option_port("Variable", null) -/obj/item/circuit_component/getter/add_to(obj/item/integrated_circuit/added_to) +/obj/item/circuit_component/variable/add_to(obj/item/integrated_circuit/added_to) . = ..() variable_name.possible_options = added_to.circuit_variables -/obj/item/circuit_component/getter/removed_from(obj/item/integrated_circuit/removed_from) +/obj/item/circuit_component/variable/removed_from(obj/item/integrated_circuit/removed_from) variable_name.possible_options = null return ..() -/obj/item/circuit_component/getter/populate_ports() - value = add_output_port("Value", PORT_TYPE_ANY) - -/obj/item/circuit_component/getter/pre_input_received(datum/port/input/port) +/obj/item/circuit_component/variable/pre_input_received(datum/port/input/port) if(!parent) return var/variable_string = variable_name.value if(!variable_string) remove_current_variable() - value.set_output(null) return var/datum/circuit_variable/variable = parent.circuit_variables[variable_string] if(!variable) remove_current_variable() - value.set_output(null) return set_current_variable(variable) - value.set_output(variable.value) -/obj/item/circuit_component/getter/proc/remove_current_variable() +/obj/item/circuit_component/variable/proc/remove_current_variable() SIGNAL_HANDLER if(current_variable) current_variable.remove_listener(src) UnregisterSignal(current_variable, COMSIG_PARENT_QDELETING) current_variable = null -/obj/item/circuit_component/getter/proc/set_current_variable(datum/circuit_variable/variable) +/obj/item/circuit_component/variable/proc/set_current_variable(datum/circuit_variable/variable) if(variable == current_variable) return @@ -65,4 +55,3 @@ current_variable = variable current_variable.add_listener(src) RegisterSignal(current_variable, COMSIG_PARENT_QDELETING, .proc/remove_current_variable) - value.set_datatype(variable.datatype) diff --git a/code/modules/wiremod/components/admin/animate.dm b/code/modules/wiremod/components/admin/animate.dm index 8166f4f8dd8..3f9c633cb90 100644 --- a/code/modules/wiremod/components/admin/animate.dm +++ b/code/modules/wiremod/components/admin/animate.dm @@ -74,7 +74,7 @@ atom_or_filter = add_option_port("Target", component_options) /obj/item/circuit_component/animation_step/populate_ports() - animation_variables = add_input_port("Variables", PORT_TYPE_ASSOC_LIST, order = 1.66) + animation_variables = add_input_port("Variables", PORT_TYPE_ASSOC_LIST(PORT_TYPE_STRING, PORT_TYPE_ANY), order = 1.66) animation_time = add_input_port("Time", PORT_TYPE_NUMBER, order = 1.66) animation_easing = add_input_port("Easing", PORT_TYPE_NUMBER, order = 1.66) animation_flags = add_input_port("Flags", PORT_TYPE_NUMBER, order = 1.66) diff --git a/code/modules/wiremod/components/admin/filter.dm b/code/modules/wiremod/components/admin/filter.dm index e7a3854a9b0..c901086e842 100644 --- a/code/modules/wiremod/components/admin/filter.dm +++ b/code/modules/wiremod/components/admin/filter.dm @@ -12,7 +12,7 @@ GLOBAL_LIST_INIT(wiremod_filter_info, list( "size" = PORT_TYPE_NUMBER, ), "color" = list( - "color" = PORT_TYPE_LIST, + "color" = PORT_TYPE_LIST(PORT_TYPE_ANY), "space" = PORT_TYPE_NUMBER, ), "displace" = list( @@ -39,7 +39,7 @@ GLOBAL_LIST_INIT(wiremod_filter_info, list( "render_source" = PORT_TYPE_STRING, "flags" = PORT_TYPE_NUMBER, "color" = PORT_TYPE_STRING, - "transform" = PORT_TYPE_LIST, + "transform" = PORT_TYPE_LIST(PORT_TYPE_ANY), "blend_mode" = PORT_TYPE_NUMBER, ), "motion_blur" = list( @@ -162,7 +162,7 @@ GLOBAL_LIST_INIT(wiremod_flag_info, list( /obj/item/circuit_component/filter_helper/populate_ports() current_filter_type = filter_type_port.value - output_params = add_output_port("Parameters", PORT_TYPE_ASSOC_LIST) + output_params = add_output_port("Parameters", PORT_TYPE_ASSOC_LIST(PORT_TYPE_STRING, PORT_TYPE_ANY)) handle_filter_type_changed() /obj/item/circuit_component/filter_helper/pre_input_received(datum/port/input/port) diff --git a/code/modules/wiremod/components/admin/input_request.dm b/code/modules/wiremod/components/admin/input_request.dm index 133a66ee1c7..e39857cdf17 100644 --- a/code/modules/wiremod/components/admin/input_request.dm +++ b/code/modules/wiremod/components/admin/input_request.dm @@ -93,7 +93,7 @@ if(COMP_INPUT_NUMBER) input_response.set_datatype(PORT_TYPE_NUMBER) if(COMP_INPUT_LIST) - parameter = add_input_port("Options List", PORT_TYPE_LIST) + parameter = add_input_port("Options List", PORT_TYPE_LIST(PORT_TYPE_ANY)) input_response.set_datatype(PORT_TYPE_STRING) #undef COMP_INPUT_STRING diff --git a/code/modules/wiremod/components/admin/proccall.dm b/code/modules/wiremod/components/admin/proccall.dm index 87e6c1369af..19408e89886 100644 --- a/code/modules/wiremod/components/admin/proccall.dm +++ b/code/modules/wiremod/components/admin/proccall.dm @@ -42,7 +42,7 @@ /obj/item/circuit_component/proccall/populate_ports() entity = add_input_port("Target", PORT_TYPE_DATUM) proc_name = add_input_port("Proc Name", PORT_TYPE_STRING) - arguments = add_input_port("Arguments", PORT_TYPE_LIST) + arguments = add_input_port("Arguments", PORT_TYPE_LIST(PORT_TYPE_ANY)) output_value = add_output_port("Output Value", PORT_TYPE_ANY) diff --git a/code/modules/wiremod/components/admin/sdql.dm b/code/modules/wiremod/components/admin/sdql.dm index d65bed83cbd..febfa165003 100644 --- a/code/modules/wiremod/components/admin/sdql.dm +++ b/code/modules/wiremod/components/admin/sdql.dm @@ -16,7 +16,7 @@ /obj/item/circuit_component/sdql_operation/populate_ports() sdql_operation = add_input_port("SDQL String", PORT_TYPE_STRING) - results = add_output_port("Result", PORT_TYPE_LIST) + results = add_output_port("Result", PORT_TYPE_LIST(PORT_TYPE_STRING)) /obj/item/circuit_component/sdql_operation/input_received(datum/port/input/port) if(GLOB.AdminProcCaller) diff --git a/code/modules/wiremod/components/admin/spawn.dm b/code/modules/wiremod/components/admin/spawn.dm index 3a4d07a7201..06d6fe231e4 100644 --- a/code/modules/wiremod/components/admin/spawn.dm +++ b/code/modules/wiremod/components/admin/spawn.dm @@ -23,7 +23,7 @@ /obj/item/circuit_component/spawn_atom/populate_ports() input_path = add_input_port("Type", PORT_TYPE_ANY) spawn_at = add_input_port("Spawn At", PORT_TYPE_ATOM) - parameters = add_input_port("Parameters", PORT_TYPE_LIST) + parameters = add_input_port("Parameters", PORT_TYPE_LIST(PORT_TYPE_ANY)) spawned_atom = add_output_port("Spawned Atom", PORT_TYPE_ATOM) diff --git a/code/modules/wiremod/components/list/assoc_literal.dm b/code/modules/wiremod/components/list/assoc_literal.dm index 2977f362f12..7f0db7fdfd7 100644 --- a/code/modules/wiremod/components/list/assoc_literal.dm +++ b/code/modules/wiremod/components/list/assoc_literal.dm @@ -3,87 +3,57 @@ * * Return an associative list literal. */ -/obj/item/circuit_component/assoc_literal +/obj/item/circuit_component/list_literal/assoc_literal display_name = "Associative List Literal" - desc = "A component that returns an associative list consisting of the inputs. Attack in hand to increase list size, right click to decrease table size." + desc = "A component that returns an associative list consisting of the inputs." circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL /// The inputs used to create the list var/list/datum/port/input/key_ports = list() - var/list/datum/port/input/value_ports = list() - /// The result from the output - var/datum/port/output/list_output - var/length = 0 +/obj/item/circuit_component/list_literal/assoc_literal/clear_lists() + for(var/datum/port/input/port as anything in key_ports) + remove_input_port(port) + for(var/datum/port/input/port as anything in entry_ports) + remove_input_port(port) + key_ports = list() + entry_ports = list() + length = 0 - var/default_list_size = 2 +/obj/item/circuit_component/list_literal/assoc_literal/remove_one_entry() + var/index = length(entry_ports) + var/key_port = key_ports[index] + key_ports -= key_port + remove_input_port(key_port) + var/value_port = entry_ports[index] + entry_ports -= value_port + remove_input_port(value_port) + length-- - var/min_size = 1 - var/max_size = 20 +/obj/item/circuit_component/list_literal/assoc_literal/pre_input_received(datum/port/input/port) + if(port == list_options) + var/new_datatype = list_options.value + list_output.set_datatype(PORT_TYPE_ASSOC_LIST(PORT_TYPE_STRING, new_datatype)) + for(var/datum/port/input/port_to_set as anything in entry_ports) + port_to_set.set_datatype(new_datatype) - ui_buttons = list( - "plus" = "increase", - "minus" = "decrease" - ) +/obj/item/circuit_component/list_literal/assoc_literal/add_one_entry() + length++ + key_ports += add_input_port("Key [length]", PORT_TYPE_STRING) + entry_ports += add_input_port("Index [length]", PORT_TYPE_ANY) -/obj/item/circuit_component/assoc_literal/save_data_to_list(list/component_data) - . = ..() - component_data["length"] = length - -/obj/item/circuit_component/assoc_literal/load_data_from_list(list/component_data) - set_list_size(component_data["length"]) - - return ..() - -/obj/item/circuit_component/assoc_literal/proc/set_list_size(new_size) - if(new_size <= 0) - for(var/datum/port/input/port as anything in key_ports) - remove_input_port(port) - for(var/datum/port/input/port as anything in value_ports) - remove_input_port(port) - key_ports = list() - value_ports = list() - length = 0 - return - - while(length > new_size) - var/index = length(value_ports) - var/key_port = key_ports[index] - key_ports -= key_port - remove_input_port(key_port) - var/value_port = value_ports[index] - value_ports -= value_port - remove_input_port(value_port) - length-- - - while(length < new_size) - length++ - var/index = length(input_ports) - if(trigger_input) - index -= 1 - key_ports += add_input_port("Key [index+1]", PORT_TYPE_STRING) - value_ports += add_input_port("Index [index+1]", PORT_TYPE_ANY) - -/obj/item/circuit_component/assoc_literal/populate_ports() +/obj/item/circuit_component/list_literal/assoc_literal/populate_ports() set_list_size(default_list_size) - list_output = add_output_port("Value", PORT_TYPE_ASSOC_LIST) - -/obj/item/circuit_component/assoc_literal/Destroy() - list_output = null - return ..() - -/obj/item/circuit_component/assoc_literal/ui_perform_action(mob/user, action) - switch(action) - if("increase") - set_list_size(min(length + 1, max_size)) - if("decrease") - set_list_size(max(length - 1, min_size)) - -/obj/item/circuit_component/assoc_literal/input_received(datum/port/input/port) + list_output = add_output_port("Value", PORT_TYPE_ASSOC_LIST(PORT_TYPE_STRING, PORT_TYPE_ANY)) +/obj/item/circuit_component/list_literal/assoc_literal/input_received(datum/port/input/port) var/list/new_literal = list() for(var/index in 1 to length) - new_literal += list(key_ports[index].value = value_ports[index].value) + // To prevent people from infinitely making lists to crash the server + if(islist(entry_ports[index].value) && get_list_count(entry_ports[index].value, max_list_count) >= max_list_count) + visible_message("[src] begins to overheat!") + return + new_literal += list(key_ports[index].value = entry_ports[index].value) list_output.set_output(new_literal) diff --git a/code/modules/wiremod/components/list/concat.dm b/code/modules/wiremod/components/list/concat.dm index 9ab4e290a53..950fdf8073a 100644 --- a/code/modules/wiremod/components/list/concat.dm +++ b/code/modules/wiremod/components/list/concat.dm @@ -18,7 +18,7 @@ circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL /obj/item/circuit_component/concat_list/populate_ports() - list_port = add_input_port("List", PORT_TYPE_LIST) + list_port = add_input_port("List", PORT_TYPE_LIST(PORT_TYPE_ANY)) separator = add_input_port("Seperator", PORT_TYPE_STRING) output = add_output_port("Output", PORT_TYPE_STRING) diff --git a/code/modules/wiremod/components/list/filter.dm b/code/modules/wiremod/components/list/filter.dm new file mode 100644 index 00000000000..a59ec5578f8 --- /dev/null +++ b/code/modules/wiremod/components/list/filter.dm @@ -0,0 +1,85 @@ +/** + * # For Each Component + * + * Filters + */ +/obj/item/circuit_component/filter_list + display_name = "Filter" + desc = "A component that loops through each element in a list and filters them." + circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_INSTANT + + /// The list type + var/datum/port/input/option/list_options + + /// Adds the list to the result + var/datum/port/input/accept_entry + /// The list to filter over + var/datum/port/input/list_to_filter + + /// The current element from the list + var/datum/port/output/element + /// The current index from the list + var/datum/port/output/current_index + /// A signal that is sent when the list has moved onto the next index. + var/datum/port/output/on_next_index + /// The finished list + var/datum/port/output/finished_list + /// A signal that is sent when the filtering has finished + var/datum/port/output/on_finished + /// A signal that is sent when the filtering has failed + var/datum/port/output/on_failed + + ui_buttons = list( + "plus" = "increase", + ) + + /// The limit of iterations before it breaks. Used to prevent from someone iterating a massive list constantly + var/limit = 300 + +/obj/item/circuit_component/filter_list/populate_options() + list_options = add_option_port("List Type", GLOB.wiremod_basic_types) + +/obj/item/circuit_component/filter_list/pre_input_received(datum/port/input/port) + if(port == list_options) + var/new_datatype = list_options.value + list_to_filter.set_datatype(PORT_TYPE_LIST(new_datatype)) + finished_list.set_datatype(PORT_TYPE_LIST(new_datatype)) + element.set_datatype(new_datatype) + +/obj/item/circuit_component/filter_list/populate_ports() + list_to_filter = add_input_port("List Input", PORT_TYPE_LIST(PORT_TYPE_ANY)) + accept_entry = add_input_port("Accept Entry", PORT_TYPE_SIGNAL, trigger = .proc/accept_entry_port) + + element = add_output_port("Element", PORT_TYPE_ANY) + current_index = add_output_port("Index", PORT_TYPE_NUMBER) + on_next_index = add_output_port("Next Index", PORT_TYPE_SIGNAL) + finished_list = add_output_port("Filtered List", PORT_TYPE_LIST(PORT_TYPE_ANY)) + on_finished = add_output_port("On Finished", PORT_TYPE_SIGNAL) + on_failed = add_output_port("On Failed", PORT_TYPE_SIGNAL) + +/obj/item/circuit_component/filter_list/proc/accept_entry_port(datum/port/input/port, list/return_values) + CIRCUIT_TRIGGER + if(return_values) + return_values["accept_entry"] = TRUE + +/obj/item/circuit_component/filter_list/input_received(datum/port/input/port) + var/index = 1 + var/start_tick_usage = TICK_USAGE + var/list/filtered_list = list() + for(var/element_in_list in list_to_filter.value) + if(index > limit && !parent.admin_only) + break + SScircuit_component.queue_instant_run(start_tick_usage) + element.set_output(element_in_list) + current_index.set_output(index) + on_next_index.set_output(COMPONENT_SIGNAL) + index += 1 + var/list/result = SScircuit_component.execute_instant_run() + if(!result) + visible_message("[src] starts to overheat!") + on_failed.set_output(COMPONENT_SIGNAL) + return + if(result["accept_entry"]) + filtered_list += list(element_in_list) + finished_list.set_output(filtered_list) + on_finished.set_output(COMPONENT_SIGNAL) diff --git a/code/modules/wiremod/components/list/foreach.dm b/code/modules/wiremod/components/list/foreach.dm new file mode 100644 index 00000000000..c7536c67ca7 --- /dev/null +++ b/code/modules/wiremod/components/list/foreach.dm @@ -0,0 +1,55 @@ +/** + * # For Each Component + * + * Sends a signal for each item in a list + */ +/obj/item/circuit_component/foreach + display_name = "For Each" + desc = "A component that loops through each element in a list." + circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL + + /// The list type + var/datum/port/input/option/list_options + + /// The list to iterate over + var/datum/port/input/list_to_iterate + + /// The current element from the list + var/datum/port/output/element + /// The current index from the list + var/datum/port/output/current_index + /// A signal that is sent when the list has moved onto the next index. + var/datum/port/output/on_next_index + /// A signal that is sent when the list has finished iterating + var/datum/port/output/on_finished + + /// The limit of iterations before it breaks. Used to prevent from someone iterating a massive list constantly + var/limit = 300 + +/obj/item/circuit_component/foreach/populate_options() + list_options = add_option_port("List Type", GLOB.wiremod_basic_types) + +/obj/item/circuit_component/foreach/pre_input_received(datum/port/input/port) + if(port == list_options) + var/new_datatype = list_options.value + list_to_iterate.set_datatype(PORT_TYPE_LIST(new_datatype)) + element.set_datatype(new_datatype) + +/obj/item/circuit_component/foreach/populate_ports() + list_to_iterate = add_input_port("List Input", PORT_TYPE_LIST(PORT_TYPE_ANY)) + + element = add_output_port("Element", PORT_TYPE_ANY) + current_index = add_output_port("Index", PORT_TYPE_NUMBER) + on_next_index = add_output_port("Next Index", PORT_TYPE_SIGNAL) + on_finished = add_output_port("On Finished", PORT_TYPE_SIGNAL) + +/obj/item/circuit_component/foreach/input_received(datum/port/input/port) + var/index = 1 + for(var/element_in_list in list_to_iterate.value) + if(index > limit && !parent.admin_only) + break + element.set_output(element_in_list) + current_index.set_output(index) + on_next_index.set_output(COMPONENT_SIGNAL) + index += 1 + on_finished.set_output(COMPONENT_SIGNAL) diff --git a/code/modules/wiremod/components/list/get_column.dm b/code/modules/wiremod/components/list/get_column.dm index 8e7d5ef0364..38684307021 100644 --- a/code/modules/wiremod/components/list/get_column.dm +++ b/code/modules/wiremod/components/list/get_column.dm @@ -20,7 +20,7 @@ /obj/item/circuit_component/get_column/populate_ports() received_table = add_input_port("Input", PORT_TYPE_TABLE) column_name = add_input_port("Column Name", PORT_TYPE_STRING) - output_list = add_output_port("Output", PORT_TYPE_LIST) + output_list = add_output_port("Output", PORT_TYPE_LIST(PORT_TYPE_ANY)) /obj/item/circuit_component/get_column/input_received(datum/port/input/port) diff --git a/code/modules/wiremod/components/list/index.dm b/code/modules/wiremod/components/list/index.dm index fda850f852b..45b162fcd02 100644 --- a/code/modules/wiremod/components/list/index.dm +++ b/code/modules/wiremod/components/list/index.dm @@ -7,6 +7,9 @@ display_name = "Index List" desc = "A component that returns the value of a list at a given index." + /// The list type + var/datum/port/input/option/list_options + /// The input port var/datum/port/input/list_port var/datum/port/input/index_port @@ -15,12 +18,26 @@ var/datum/port/output/output circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL + var/index_type = PORT_TYPE_NUMBER + +/obj/item/circuit_component/index/populate_options() + list_options = add_option_port("List Type", GLOB.wiremod_basic_types) + +/obj/item/circuit_component/index/proc/make_list_port() + list_port = add_input_port("List", PORT_TYPE_LIST(PORT_TYPE_ANY)) + /obj/item/circuit_component/index/populate_ports() - index_port = add_input_port("Index", PORT_TYPE_ANY) - list_port = add_input_port("List", PORT_TYPE_LIST) + index_port = add_input_port("Index", index_type) + make_list_port() output = add_output_port("Value", PORT_TYPE_ANY) +/obj/item/circuit_component/index/pre_input_received(datum/port/input/port) + if(port == list_options) + var/new_type = list_options.value + list_port.set_datatype(PORT_TYPE_LIST(new_type)) + output.set_datatype(new_type) + /obj/item/circuit_component/index/input_received(datum/port/input/port) var/index = index_port.value @@ -36,3 +53,17 @@ output.set_output(list_input[index]) +/obj/item/circuit_component/index/assoc_string + display_name = "Index Associative List" + desc = "A component that is commonly used to access a row from a table. Accesses data from a key, value list." + + index_type = PORT_TYPE_STRING + +/obj/item/circuit_component/index/assoc_string/make_list_port() + list_port = add_input_port("List", PORT_TYPE_ASSOC_LIST(PORT_TYPE_STRING, PORT_TYPE_ANY)) + +/obj/item/circuit_component/index/assoc_string/pre_input_received(datum/port/input/port) + if(port == list_options) + var/new_type = list_options.value + list_port.set_datatype(PORT_TYPE_ASSOC_LIST(PORT_TYPE_STRING, new_type)) + output.set_datatype(new_type) diff --git a/code/modules/wiremod/components/list/index_table.dm b/code/modules/wiremod/components/list/index_table.dm index eb9a10f45cc..69cc57fe9d2 100644 --- a/code/modules/wiremod/components/list/index_table.dm +++ b/code/modules/wiremod/components/list/index_table.dm @@ -21,7 +21,7 @@ received_table = add_input_port("Input", PORT_TYPE_TABLE) target_index = add_input_port("Index", PORT_TYPE_NUMBER) - output_list = add_output_port("Output", PORT_TYPE_LIST) + output_list = add_output_port("Output", PORT_TYPE_ASSOC_LIST(PORT_TYPE_STRING, PORT_TYPE_ANY)) /obj/item/circuit_component/index_table/input_received(datum/port/input/port) diff --git a/code/modules/wiremod/components/list/list_literal.dm b/code/modules/wiremod/components/list/list_literal.dm index 01db810ac1d..69b6441fc01 100644 --- a/code/modules/wiremod/components/list/list_literal.dm +++ b/code/modules/wiremod/components/list/list_literal.dm @@ -5,9 +5,12 @@ */ /obj/item/circuit_component/list_literal display_name = "List Literal" - desc = "A component that returns the value of a list at a given index. Attack in hand to increase list size, right click to decrease list size." + desc = "A component that creates a list from whatever input you give it." circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL + /// The list type + var/datum/port/input/option/list_options + /// The inputs used to create the list var/list/datum/port/input/entry_ports = list() /// The result from the output @@ -25,6 +28,11 @@ "minus" = "decrease" ) + var/max_list_count = 100 + +/obj/item/circuit_component/list_literal/populate_options() + list_options = add_option_port("List Type", GLOB.wiremod_basic_types) + /obj/item/circuit_component/list_literal/save_data_to_list(list/component_data) . = ..() component_data["length"] = length @@ -34,31 +42,44 @@ return ..() +/obj/item/circuit_component/list_literal/proc/clear_lists() + for(var/datum/port/input/port as anything in entry_ports) + remove_input_port(port) + entry_ports.Cut() + length = 0 + +/obj/item/circuit_component/list_literal/proc/remove_one_entry() + var/index = length(entry_ports) + var/entry_port = entry_ports[index] + entry_ports -= entry_port + remove_input_port(entry_port) + length-- + +/obj/item/circuit_component/list_literal/proc/add_one_entry() + length++ + entry_ports += add_input_port("Index [length]", list_options.value || PORT_TYPE_ANY) + /obj/item/circuit_component/list_literal/proc/set_list_size(new_size) if(new_size <= 0) - for(var/datum/port/input/port in entry_ports) - remove_input_port(port) - entry_ports = list() - length = 0 + clear_lists() return while(length > new_size) - var/index = length(entry_ports) - var/entry_port = entry_ports[index] - entry_ports -= entry_port - remove_input_port(entry_port) - length-- + remove_one_entry() while(length < new_size) - length++ - var/index = length(input_ports) - if(trigger_input) - index -= 1 - entry_ports += add_input_port("Index [index+1]", PORT_TYPE_ANY) + add_one_entry() + +/obj/item/circuit_component/list_literal/pre_input_received(datum/port/input/port) + if(port == list_options) + var/new_datatype = list_options.value + list_output.set_datatype(PORT_TYPE_LIST(new_datatype)) + for(var/datum/port/input/port_to_set as anything in entry_ports) + port_to_set.set_datatype(new_datatype) /obj/item/circuit_component/list_literal/populate_ports() set_list_size(default_list_size) - list_output = add_output_port("Value", PORT_TYPE_LIST) + list_output = add_output_port("Value", PORT_TYPE_LIST(PORT_TYPE_ANY)) /obj/item/circuit_component/list_literal/Destroy() list_output = null @@ -76,8 +97,25 @@ var/list/new_literal = list() for(var/datum/port/input/entry_port as anything in entry_ports) - // Prevents lists from merging together - new_literal += list(entry_port.value) + var/value = entry_port.value + // To prevent people from infinitely making lists to crash the server + if(islist(value) && get_list_count(value, max_list_count) >= max_list_count) + visible_message("[src] begins to overheat!") + return + new_literal += list(value) list_output.set_output(new_literal) +/proc/get_list_count(list/value, max_list_count) + var/list/lists_to_check = list() + lists_to_check += list(value) + var/lists = 1 + while(length(lists_to_check)) + var/list/list_to_iterate = lists_to_check[length(lists_to_check)] + for(var/list/list_data in list_to_iterate) + lists_to_check += list(list_data) + lists += 1 + lists_to_check.len-- + if(lists > max_list_count) + return lists + return lists diff --git a/code/modules/wiremod/components/list/split.dm b/code/modules/wiremod/components/list/split.dm index c3d870e4514..994fcd7cfb7 100644 --- a/code/modules/wiremod/components/list/split.dm +++ b/code/modules/wiremod/components/list/split.dm @@ -21,7 +21,7 @@ /obj/item/circuit_component/split/populate_ports() input_port = add_input_port("Input", PORT_TYPE_STRING) separator = add_input_port("Seperator", PORT_TYPE_STRING) - output = add_output_port("Output", PORT_TYPE_LIST) + output = add_output_port("Output", PORT_TYPE_LIST(PORT_TYPE_STRING)) /obj/item/circuit_component/split/input_received(datum/port/input/port) diff --git a/code/modules/wiremod/components/ntnet/ntnet_receive.dm b/code/modules/wiremod/components/ntnet/ntnet_receive.dm index fc97adbf7d0..a2a67d5d563 100644 --- a/code/modules/wiremod/components/ntnet/ntnet_receive.dm +++ b/code/modules/wiremod/components/ntnet/ntnet_receive.dm @@ -11,22 +11,43 @@ network_id = __NETWORK_CIRCUITS + /// The list type + var/datum/port/input/option/list_options + /// Data being received var/datum/port/output/data_package /// Encryption key var/datum/port/input/enc_key +/obj/item/circuit_component/ntnet_receive/populate_options() + list_options = add_option_port("List Type", GLOB.wiremod_basic_types) + /obj/item/circuit_component/ntnet_receive/populate_ports() - data_package = add_output_port("Data Package", PORT_TYPE_ANY) + data_package = add_output_port("Data Package", PORT_TYPE_LIST(PORT_TYPE_ANY)) enc_key = add_input_port("Encryption Key", PORT_TYPE_STRING) RegisterSignal(src, COMSIG_COMPONENT_NTNET_RECEIVE, .proc/ntnet_receive) +/obj/item/circuit_component/ntnet_receive/pre_input_received(datum/port/input/port) + if(port == list_options) + var/new_datatype = list_options.value + data_package.set_datatype(PORT_TYPE_LIST(new_datatype)) + + /obj/item/circuit_component/ntnet_receive/proc/ntnet_receive(datum/source, datum/netdata/data) SIGNAL_HANDLER if(data.data["enc_key"] != enc_key.value) return + var/datum/weakref/ref = data.data["port"] + var/datum/port/input/port = ref?.resolve() + if(!port) + return + + var/datum/circuit_datatype/datatype_handler = data_package.datatype_handler + if(!datatype_handler?.can_receive_from_datatype(port.datatype)) + return + data_package.set_output(data.data["data"]) trigger_output.set_output(COMPONENT_SIGNAL) diff --git a/code/modules/wiremod/components/ntnet/ntnet_send.dm b/code/modules/wiremod/components/ntnet/ntnet_send.dm index 0479ab0b1b6..64a1b1e089a 100644 --- a/code/modules/wiremod/components/ntnet/ntnet_send.dm +++ b/code/modules/wiremod/components/ntnet/ntnet_send.dm @@ -12,15 +12,26 @@ network_id = __NETWORK_CIRCUITS + /// The list type + var/datum/port/input/option/list_options + /// Data being sent var/datum/port/input/data_package /// Encryption key var/datum/port/input/enc_key +/obj/item/circuit_component/ntnet_send/populate_options() + list_options = add_option_port("List Type", GLOB.wiremod_basic_types) + /obj/item/circuit_component/ntnet_send/populate_ports() - data_package = add_input_port("Data Package", PORT_TYPE_ANY) + data_package = add_input_port("Data Package", PORT_TYPE_LIST(PORT_TYPE_ANY)) enc_key = add_input_port("Encryption Key", PORT_TYPE_STRING) +/obj/item/circuit_component/ntnet_send/pre_input_received(datum/port/input/port) + if(port == list_options) + var/new_datatype = list_options.value + data_package.set_datatype(PORT_TYPE_LIST(new_datatype)) + /obj/item/circuit_component/ntnet_send/input_received(datum/port/input/port) - ntnet_send(list("data" = data_package.value, "enc_key" = enc_key.value)) + ntnet_send(list("data" = data_package.value, "enc_key" = enc_key.value, "port" = WEAKREF(data_package))) diff --git a/code/modules/wiremod/components/string/tostring.dm b/code/modules/wiremod/components/string/tostring.dm index 9ceeeef03db..0cc96a3aeb4 100644 --- a/code/modules/wiremod/components/string/tostring.dm +++ b/code/modules/wiremod/components/string/tostring.dm @@ -26,8 +26,8 @@ var/value = input_port.value if(isatom(value)) var/turf/location = get_turf(src) - var/atom/object = value - if(object.z != location.z || get_dist(location, object) > max_range) + var/turf/target_location = get_turf(value) + if(target_location.z != location.z || get_dist(location, target_location) > max_range) output.set_output(PORT_TYPE_ATOM) return diff --git a/code/modules/wiremod/components/utility/router.dm b/code/modules/wiremod/components/utility/router.dm index bcfc61be225..ddfd1b45a0f 100644 --- a/code/modules/wiremod/components/utility/router.dm +++ b/code/modules/wiremod/components/utility/router.dm @@ -26,14 +26,7 @@ var/list/datum/port/output/outs /obj/item/circuit_component/router/populate_options() - var/static/component_options = list( - PORT_TYPE_ANY, - PORT_TYPE_STRING, - PORT_TYPE_NUMBER, - PORT_TYPE_LIST, - PORT_TYPE_ATOM, - ) - router_options = add_option_port("Router Options", component_options) + router_options = add_option_port("Router Options", GLOB.wiremod_basic_types) /obj/item/circuit_component/router/populate_ports() current_type = router_options.value diff --git a/code/modules/wiremod/components/utility/setter.dm b/code/modules/wiremod/components/utility/setter.dm deleted file mode 100644 index b5026c1207b..00000000000 --- a/code/modules/wiremod/components/utility/setter.dm +++ /dev/null @@ -1,70 +0,0 @@ -/** - * # Setter Component - * - * Stores the current input when triggered into a variable. - */ -/obj/item/circuit_component/setter - display_name = "Variable Setter" - desc = "A component that sets a variable globally on the circuit." - - circuit_flags = CIRCUIT_FLAG_OUTPUT_SIGNAL - - /// Variable name - var/datum/port/input/option/variable_name - - /// The input to store - var/datum/port/input/input_port - /// The trigger to store the current value of the input - var/datum/port/input/trigger - - var/current_type - - circuit_size = 0 - -/obj/item/circuit_component/setter/populate_options() - variable_name = add_option_port("Variable", null) - -/obj/item/circuit_component/setter/add_to(obj/item/integrated_circuit/added_to) - . = ..() - variable_name.possible_options = added_to.circuit_variables - -/obj/item/circuit_component/setter/removed_from(obj/item/integrated_circuit/removed_from) - variable_name.possible_options = null - return ..() - -/obj/item/circuit_component/setter/populate_ports() - input_port = add_input_port("Input", PORT_TYPE_ANY) - trigger = add_input_port("Store", PORT_TYPE_SIGNAL) - -/obj/item/circuit_component/setter/pre_input_received(datum/port/input/port) - var/datum/circuit_variable/variable = get_variable() - if(!variable) - return - - if(variable.datatype != current_type) - current_type = variable.datatype - input_port.set_datatype(current_type) - -/obj/item/circuit_component/setter/should_receive_input(datum/port/input/port) - if(!COMPONENT_TRIGGERED_BY(trigger, port)) - return FALSE - return ..() - - -/obj/item/circuit_component/setter/input_received(datum/port/input/port) - var/datum/circuit_variable/variable = get_variable() - if(!variable) - return - - variable.set_value(input_port.value) - -/obj/item/circuit_component/setter/proc/get_variable() - var/variable_string = variable_name.value - if(!variable_string) - return - - var/datum/circuit_variable/variable = parent.circuit_variables[variable_string] - if(!variable) - return - - return variable diff --git a/code/modules/wiremod/components/utility/typecast.dm b/code/modules/wiremod/components/utility/typecast.dm index 79be018e111..ac9b1ce3813 100644 --- a/code/modules/wiremod/components/utility/typecast.dm +++ b/code/modules/wiremod/components/utility/typecast.dm @@ -25,7 +25,7 @@ var/static/list/component_options = list( PORT_TYPE_STRING, PORT_TYPE_NUMBER, - PORT_TYPE_LIST, + PORT_COMPOSITE_TYPE_LIST, PORT_TYPE_ATOM, ) typecast_options = add_option_port("Typecast Options", component_options) @@ -48,7 +48,7 @@ if(PORT_TYPE_NUMBER) if(isnum(value)) value_to_set = value - if(PORT_TYPE_LIST) + if(PORT_COMPOSITE_TYPE_LIST) if(islist(value)) value_to_set = value if(PORT_TYPE_ATOM) diff --git a/code/modules/wiremod/components/utility/typecheck.dm b/code/modules/wiremod/components/utility/typecheck.dm index 8caa009fd85..f27360ccc5e 100644 --- a/code/modules/wiremod/components/utility/typecheck.dm +++ b/code/modules/wiremod/components/utility/typecheck.dm @@ -17,7 +17,7 @@ var/static/component_options = list( PORT_TYPE_STRING, PORT_TYPE_NUMBER, - PORT_TYPE_LIST, + PORT_COMPOSITE_TYPE_LIST, PORT_TYPE_ATOM, COMP_TYPECHECK_MOB, COMP_TYPECHECK_HUMAN, @@ -37,7 +37,7 @@ return istext(input_val) if(PORT_TYPE_NUMBER) return isnum(input_val) - if(PORT_TYPE_LIST) + if(PORT_COMPOSITE_TYPE_LIST) return islist(input_val) if(PORT_TYPE_ATOM) return isatom(input_val) diff --git a/code/modules/wiremod/components/variables/getter.dm b/code/modules/wiremod/components/variables/getter.dm new file mode 100644 index 00000000000..8e065743cca --- /dev/null +++ b/code/modules/wiremod/components/variables/getter.dm @@ -0,0 +1,22 @@ +/** + * # Getter Component + * + * Gets the current value from a variable. + */ +/obj/item/circuit_component/variable/getter + display_name = "Variable Getter" + desc = "A component that gets a variable globally on the circuit." + + /// The value of the variable + var/datum/port/output/value + + circuit_size = 0 + +/obj/item/circuit_component/variable/getter/populate_ports() + value = add_output_port("Value", PORT_TYPE_ANY) + +/obj/item/circuit_component/variable/getter/pre_input_received(datum/port/input/port) + . = ..() + if(current_variable) + value.set_datatype(current_variable.datatype) + value.set_value(current_variable.value) diff --git a/code/modules/wiremod/components/variables/setter.dm b/code/modules/wiremod/components/variables/setter.dm new file mode 100644 index 00000000000..296fd5bfc08 --- /dev/null +++ b/code/modules/wiremod/components/variables/setter.dm @@ -0,0 +1,30 @@ +/** + * # Setter Component + * + * Stores the current input when triggered into a variable. + */ +/obj/item/circuit_component/variable/setter + display_name = "Variable Setter" + desc = "A component that sets a variable globally on the circuit." + + circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL + + /// The input to store + var/datum/port/input/input_port + + circuit_size = 0 + +/obj/item/circuit_component/variable/setter/populate_ports() + input_port = add_input_port("Input", PORT_TYPE_ANY) + trigger_input = add_input_port("Store", PORT_TYPE_SIGNAL) + +/obj/item/circuit_component/variable/setter/pre_input_received(datum/port/input/port) + . = ..() + if(port == variable_name) + input_port.set_datatype(current_variable.datatype) + +/obj/item/circuit_component/variable/setter/input_received(datum/port/input/port) + if(!current_variable) + return + current_variable.set_value(input_port.value) + diff --git a/code/modules/wiremod/core/component.dm b/code/modules/wiremod/core/component.dm index 8368f6ae4f3..5a6ac5ecc6e 100644 --- a/code/modules/wiremod/core/component.dm +++ b/code/modules/wiremod/core/component.dm @@ -75,9 +75,9 @@ name = "[lowertext(display_name)] [COMPONENT_DEFAULT_NAME]" populate_options() populate_ports() - if(circuit_flags & CIRCUIT_FLAG_INPUT_SIGNAL) + if((circuit_flags & CIRCUIT_FLAG_INPUT_SIGNAL) && !trigger_input) trigger_input = add_input_port("Trigger", PORT_TYPE_SIGNAL, order = 2) - if(circuit_flags & CIRCUIT_FLAG_OUTPUT_SIGNAL) + if((circuit_flags & CIRCUIT_FLAG_OUTPUT_SIGNAL) && !trigger_output) trigger_output = add_output_port("Triggered", PORT_TYPE_SIGNAL, order = 2) if(circuit_flags & CIRCUIT_FLAG_INSTANT) ui_color = "orange" @@ -252,7 +252,7 @@ if(!cell?.use(power_usage_per_input)) return FALSE - if((circuit_flags & CIRCUIT_FLAG_INPUT_SIGNAL) && !COMPONENT_TRIGGERED_BY(trigger_input, port)) + if((!port || port.trigger == .proc/input_received) && (circuit_flags & CIRCUIT_FLAG_INPUT_SIGNAL) && !COMPONENT_TRIGGERED_BY(trigger_input, port)) return FALSE return TRUE diff --git a/code/modules/wiremod/core/datatypes.dm b/code/modules/wiremod/core/datatypes.dm index 048e7c23802..098f4fb644f 100644 --- a/code/modules/wiremod/core/datatypes.dm +++ b/code/modules/wiremod/core/datatypes.dm @@ -1,10 +1,10 @@ // An assoc list of all the possible datatypes. -GLOBAL_LIST_INIT(circuit_datatypes, generate_circuit_datatypes()) +GLOBAL_LIST_INIT_TYPED(circuit_datatypes, /datum/circuit_datatype, generate_circuit_datatypes()) /proc/generate_circuit_datatypes() var/list/datatypes_by_key = list() for(var/datum/circuit_datatype/type as anything in subtypesof(/datum/circuit_datatype)) - if(!initial(type.datatype)) + if(!initial(type.datatype) || initial(type.abstract)) continue datatypes_by_key[initial(type.datatype)] = new type() return datatypes_by_key @@ -22,6 +22,9 @@ GLOBAL_LIST_INIT(circuit_datatypes, generate_circuit_datatypes()) /// The flags of the circuit datatype var/datatype_flags = 0 + /// Whether this datatype should be loaded into the global circuit_datatypes list. + var/abstract = FALSE + /** * Returns the value to be set for the port * @@ -89,3 +92,9 @@ GLOBAL_LIST_INIT(circuit_datatypes, generate_circuit_datatypes()) */ /datum/circuit_datatype/proc/handle_manual_input(datum/port/input/port, mob/user, user_input) return user_input + +/** + * Used by composite datatypes. Returns all the datatypes that build this datatype up. + */ +/datum/circuit_datatype/proc/get_datatypes() + return list() diff --git a/code/modules/wiremod/core/duplicator.dm b/code/modules/wiremod/core/duplicator.dm index 9d68b353c7c..332310e3429 100644 --- a/code/modules/wiremod/core/duplicator.dm +++ b/code/modules/wiremod/core/duplicator.dm @@ -4,7 +4,6 @@ GLOBAL_LIST_INIT(circuit_dupe_whitelisted_types, list( PORT_TYPE_NUMBER, PORT_TYPE_STRING, - PORT_TYPE_LIST, PORT_TYPE_ANY, PORT_TYPE_OPTION, )) diff --git a/code/modules/wiremod/core/integrated_circuit.dm b/code/modules/wiremod/core/integrated_circuit.dm index 6ec768cc735..116d3015879 100644 --- a/code/modules/wiremod/core/integrated_circuit.dm +++ b/code/modules/wiremod/core/integrated_circuit.dm @@ -314,6 +314,7 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit) "type" = port.datatype, "ref" = REF(port), "color" = port.color, + "datatype_data" = port.datatype_ui_data(user) )) component_data["name"] = component.display_name @@ -551,7 +552,8 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit) var/variable_datatype = params["variable_datatype"] if(!(variable_datatype in GLOB.wiremod_basic_types)) return - + if(params["is_list"]) + variable_datatype = PORT_TYPE_LIST(variable_datatype) circuit_variables[variable_identifier] = new /datum/circuit_variable(variable_identifier, variable_datatype) . = TRUE if("remove_variable") @@ -568,19 +570,14 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit) if(setter_and_getter_count >= max_setters_and_getters) balloon_alert(usr, "setter and getter count at maximum capacity") return - var/designated_type = /obj/item/circuit_component/getter + var/designated_type = /obj/item/circuit_component/variable/getter if(params["is_setter"]) - designated_type = /obj/item/circuit_component/setter - var/obj/item/circuit_component/component = new designated_type(src) + designated_type = /obj/item/circuit_component/variable/setter + var/obj/item/circuit_component/variable/component = new designated_type(src) if(!add_component(component, usr)) qdel(component) return - if(params["is_setter"]) - var/obj/item/circuit_component/setter/setter = component - setter.variable_name.set_input(params["variable"]) - else - var/obj/item/circuit_component/getter/getter = component - getter.variable_name.set_input(params["variable"]) + component.variable_name.set_input(params["variable"]) component.rel_x = text2num(params["rel_x"]) component.rel_y = text2num(params["rel_y"]) RegisterSignal(component, COMSIG_CIRCUIT_COMPONENT_REMOVED, .proc/clear_setter_or_getter) diff --git a/code/modules/wiremod/core/port.dm b/code/modules/wiremod/core/port.dm index 61058bd5dab..ca668bc6842 100644 --- a/code/modules/wiremod/core/port.dm +++ b/code/modules/wiremod/core/port.dm @@ -92,7 +92,7 @@ datatype_handler = handler color = datatype_handler.color datatype_handler.on_gain(src) - src.value = datatype_handler.convert_value(src, value) + src.value = null SEND_SIGNAL(src, COMSIG_PORT_SET_TYPE, type_to_set) if(connected_component?.parent) SStgui.update_uis(connected_component.parent) @@ -124,6 +124,7 @@ * an integrated circuit */ /datum/port/proc/disconnect_all() + value = null SEND_SIGNAL(src, COMSIG_PORT_DISCONNECT) /datum/port/input/disconnect_all() @@ -184,6 +185,11 @@ if(!(datatype_handler.datatype_flags & DATATYPE_FLAG_AVOID_VALUE_UPDATE)) set_input(output.value) +/datum/port/input/set_datatype(new_type) + . = ..() + for(var/datum/port/output/port as anything in connected_ports) + check_type(port) + /** * Determines if a datatype is compatible with another port of a different type. * diff --git a/code/modules/wiremod/core/variable.dm b/code/modules/wiremod/core/variable.dm index 03fac9ac457..2153688d7bf 100644 --- a/code/modules/wiremod/core/variable.dm +++ b/code/modules/wiremod/core/variable.dm @@ -10,6 +10,9 @@ /// The datatype of the circuit variable. Used by the setter and getter circuit components var/datatype + /// The datatype handler for the circuit variable. + var/datum/circuit_datatype/datatype_handler + /// The colour that appears in the UI. The value is set to the datatype's matching colour var/color @@ -24,16 +27,11 @@ src.name = name src.datatype = datatype - var/datum/circuit_datatype/circuit_datatype = GLOB.circuit_datatypes[datatype] - + src.datatype_handler = GLOB.circuit_datatypes[datatype] src.listeners = list() - src.color = circuit_datatype.color + src.color = datatype_handler.color -/datum/circuit_variable/Destroy(force, ...) - listeners = null - return ..() - /// Sets the value of the circuit component and triggers the appropriate listeners /datum/circuit_variable/proc/set_value(new_value) value = new_value diff --git a/code/modules/wiremod/datatypes/basic.dm b/code/modules/wiremod/datatypes/basic.dm index b567c9d9ee0..feada123ae6 100644 --- a/code/modules/wiremod/datatypes/basic.dm +++ b/code/modules/wiremod/datatypes/basic.dm @@ -3,7 +3,3 @@ /datum/circuit_datatype/table datatype = PORT_TYPE_TABLE color = "grey" - -/datum/circuit_datatype/assoc_list - datatype = PORT_TYPE_ASSOC_LIST - color = "label" diff --git a/code/modules/wiremod/datatypes/composite/assoc_list.dm b/code/modules/wiremod/datatypes/composite/assoc_list.dm new file mode 100644 index 00000000000..238dac88087 --- /dev/null +++ b/code/modules/wiremod/datatypes/composite/assoc_list.dm @@ -0,0 +1,20 @@ +/datum/circuit_composite_template/assoc_list + datatype = PORT_COMPOSITE_TYPE_ASSOC_LIST + composite_datatype_path = /datum/circuit_datatype/composite_instance/assoc_list + expected_types = 2 + +/datum/circuit_composite_template/assoc_list/generate_name(list/composite_datatypes) + return "[composite_datatypes[1]], [composite_datatypes[2]] list" + +/datum/circuit_datatype/composite_instance/assoc_list + color = "white" + datatype_flags = DATATYPE_FLAG_COMPOSITE + +/datum/circuit_datatype/composite_instance/assoc_list/convert_value(datum/port/port, value_to_convert, force) + var/datum/circuit_datatype/key_handler = GLOB.circuit_datatypes[composite_datatypes[1]] + var/datum/circuit_datatype/value_handler = GLOB.circuit_datatypes[composite_datatypes[2]] + + var/list/converted_list = list() + for(var/data in value_to_convert) + converted_list[key_handler.convert_value(port, data)] = value_handler.convert_value(port, value_to_convert[data]) + return converted_list diff --git a/code/modules/wiremod/datatypes/composite/composite.dm b/code/modules/wiremod/datatypes/composite/composite.dm new file mode 100644 index 00000000000..b9116b3954f --- /dev/null +++ b/code/modules/wiremod/datatypes/composite/composite.dm @@ -0,0 +1,110 @@ +/// A template used to make composite datatypes for circuits. +/// Used so that we don't have to generate every single possible combination of types +/datum/circuit_composite_template + /// The datatype this composite template is of. + var/datatype + /// The path to the composite type + var/composite_datatype_path + /// The amount of composite datatypes needed to generate a datatype from this template + var/expected_types = 1 + + /// Types to generate during initialization + var/list/types_to_generate = list() + + var/list/datum/circuit_datatype/composite_instance/generated_types = list() + +/** + * Generates a name for the datatype using the unique list of composite datatypes. + * This should always generate a constant value for the input given as it is used as + * the unique identifier + **/ +/datum/circuit_composite_template/proc/generate_name(list/composite_datatypes) + SHOULD_BE_PURE(TRUE) + return "[datatype]<[composite_datatypes.Join(", ")]>" + +/** + * Generates a composite type using this template. Not recommended to use directly, use a define instead. + * + * Arguments: + * * composite_datatypes - The list of composite datatypes to use to generate this type. + **/ +/datum/circuit_composite_template/proc/generate_composite_type(list/composite_datatypes) + var/new_datatype = generate_name(composite_datatypes) + + if(!GLOB.circuit_datatypes) + types_to_generate += list(composite_datatypes) + return new_datatype + + if(expected_types != length(composite_datatypes)) + CRASH("Invalid amount of composite datatypes passed to [type]. Expected [expected_types], got [length(composite_datatypes)] arguments.") + + if(GLOB.circuit_datatypes[new_datatype]) + return new_datatype + for(var/datatype_to_check in composite_datatypes) + if(!GLOB.circuit_datatypes[datatype_to_check]) + CRASH("Attempted to form an invalid composite datatype using datatypes that don't exist! (got [datatype_to_check], expected a valid datatype)") + var/datum/circuit_datatype/composite_instance/generated_type = new composite_datatype_path(new_datatype, datatype, composite_datatypes) + GLOB.circuit_datatypes[new_datatype] = generated_type + generated_types[new_datatype] = generated_type + return new_datatype + +/** + * Used to generate composite types from anything that was generated + * before global variables were all initialized. + * Used for when composite datatypes are used in globally defined lists, before GLOB.circuit_datatypes is available. + **/ +/datum/circuit_composite_template/proc/Initialize() + if(types_to_generate) + for(var/list/data as anything in types_to_generate) + generate_composite_type(data) + +/// A composite instance generated by a template +/datum/circuit_datatype/composite_instance + datatype_flags = DATATYPE_FLAG_COMPOSITE + abstract = TRUE + + /// The base datatype, used for comparisons + var/base_datatype + + /// The composite datatypes that make this datatype up + var/list/composite_datatypes + + /// A list composed of the composite datatypes sent to the UI. + var/list/composite_datatypes_style + +/datum/circuit_datatype/composite_instance/New(datatype, base_datatype, list/composite_datatypes) + . = ..() + if(!datatype || !composite_datatypes) + return + + src.datatype = datatype + src.base_datatype = base_datatype + src.composite_datatypes = composite_datatypes + abstract = FALSE + + composite_datatypes_style += list() + for(var/datatype_to_check in composite_datatypes) + composite_datatypes_style += GLOB.circuit_datatypes[datatype_to_check].color + +/datum/circuit_datatype/composite_instance/can_receive_from_datatype(datatype_to_check) + . = ..() + if(.) + return + + var/datum/circuit_datatype/composite_instance/datatype_handler = SSwiremod_composite.get_composite_type(base_datatype, datatype_to_check) + if(!datatype_handler || length(datatype_handler.composite_datatypes) != length(composite_datatypes)) + return FALSE + + for(var/index in 1 to length(composite_datatypes)) + if(!GLOB.circuit_datatypes[composite_datatypes[index]].can_receive_from_datatype(datatype_handler.composite_datatypes[index])) + return FALSE + return TRUE + +/datum/circuit_datatype/composite_instance/datatype_ui_data(datum/port/port) + var/list/ui_data = list() + + ui_data["composite_types"] = composite_datatypes_style + return ui_data + +/datum/circuit_datatype/composite_instance/get_datatypes() + return composite_datatypes diff --git a/code/modules/wiremod/datatypes/composite/list.dm b/code/modules/wiremod/datatypes/composite/list.dm new file mode 100644 index 00000000000..c78f097b8d2 --- /dev/null +++ b/code/modules/wiremod/datatypes/composite/list.dm @@ -0,0 +1,19 @@ +/datum/circuit_composite_template/list + datatype = PORT_COMPOSITE_TYPE_LIST + composite_datatype_path = /datum/circuit_datatype/composite_instance/list + expected_types = 1 + +/datum/circuit_composite_template/list/generate_name(list/composite_datatypes) + return "[composite_datatypes[1]] [datatype]" + +/datum/circuit_datatype/composite_instance/list + color = "white" + datatype_flags = DATATYPE_FLAG_COMPOSITE + +/datum/circuit_datatype/composite_instance/list/convert_value(datum/port/port, value_to_convert, force) + var/datum/circuit_datatype/datatype_handler = GLOB.circuit_datatypes[composite_datatypes[1]] + + var/list/converted_list = list() + for(var/data in value_to_convert) + converted_list += list(datatype_handler.convert_value(port, data)) + return converted_list diff --git a/code/modules/wiremod/datatypes/list.dm b/code/modules/wiremod/datatypes/list.dm deleted file mode 100644 index e3042a444b8..00000000000 --- a/code/modules/wiremod/datatypes/list.dm +++ /dev/null @@ -1,10 +0,0 @@ -/datum/circuit_datatype/list_type - datatype = PORT_TYPE_LIST - color = "white" - -/datum/circuit_datatype/list_type/can_receive_from_datatype(datatype_to_check) - . = ..() - if(.) - return - - return datatype_to_check == PORT_TYPE_ASSOC_LIST diff --git a/code/modules/wiremod/shell/dispenser.dm b/code/modules/wiremod/shell/dispenser.dm new file mode 100644 index 00000000000..6c41cff47cd --- /dev/null +++ b/code/modules/wiremod/shell/dispenser.dm @@ -0,0 +1,203 @@ +/** + * # Dispenser + * + * Immobile (but not dense) shell that can receive and dispense items. + */ +/obj/structure/dispenser_bot + name = "dispenser" + icon = 'icons/obj/wiremod.dmi' + icon_state = "setup_large" + + density = FALSE + light_system = MOVABLE_LIGHT + light_on = FALSE + + var/max_weight = WEIGHT_CLASS_NORMAL + var/capacity = 20 + + var/list/obj/item/stored_items = list() + var/locked = FALSE + +/obj/structure/dispenser_bot/deconstruct(disassembled) + for(var/obj/item/stored_item as anything in stored_items) + remove_item(stored_item) + return ..() + +/obj/structure/dispenser_bot/Destroy() + QDEL_LIST(stored_items) + return ..() + + +/obj/structure/dispenser_bot/proc/add_item(obj/item/to_add) + stored_items += to_add + to_add.forceMove(src) + RegisterSignal(to_add, COMSIG_MOVABLE_MOVED, .proc/handle_stored_item_moved) + RegisterSignal(to_add, COMSIG_PARENT_QDELETING, .proc/handle_stored_item_deleted) + SEND_SIGNAL(src, COMSIG_DISPENSERBOT_ADD_ITEM, to_add) + +/obj/structure/dispenser_bot/proc/handle_stored_item_moved(obj/item/moving_item, atom/location) + SIGNAL_HANDLER + if(location != src) + remove_item(moving_item) + +/obj/structure/dispenser_bot/proc/handle_stored_item_deleted(obj/item/deleting_item) + SIGNAL_HANDLER + remove_item(deleting_item) + +/obj/structure/dispenser_bot/proc/remove_item(obj/item/to_remove) + UnregisterSignal(to_remove, list( + COMSIG_MOVABLE_MOVED, + COMSIG_PARENT_QDELETING, + )) + to_remove.forceMove(drop_location()) + stored_items -= to_remove + SEND_SIGNAL(src, COMSIG_DISPENSERBOT_REMOVE_ITEM, to_remove) + + +/obj/structure/dispenser_bot/Initialize(mapload) + . = ..() + AddComponent(/datum/component/shell, list( + new /obj/item/circuit_component/dispenser_bot() + ), SHELL_CAPACITY_LARGE) + +/obj/structure/dispenser_bot/attackby(obj/item/item, mob/living/user, params) + . = ..() + if(user.combat_mode || .) + return + + if(item.w_class > max_weight) + balloon_alert(user, "item too big!") + return + + if(length(stored_items) >= capacity) + balloon_alert(user, "at maximum capacity!") + return + + add_item(item) + + +/obj/structure/dispenser_bot/wrench_act(mob/living/user, obj/item/tool) + if(locked) + return + set_anchored(!anchored) + tool.play_tool_sound(src) + balloon_alert(user, "You [anchored?"secure":"unsecure"] [src].") + return TRUE + +/obj/item/circuit_component/dispenser_bot + display_name = "Dispenser" + desc = "A dispenser bot that can dispense items " + + /// The list of items + var/datum/port/output/item_list + /// The item that was added/removed. + var/datum/port/output/item + /// Called when an item is added. + var/datum/port/output/on_item_added + /// Called when an item is removed. + var/datum/port/output/on_item_removed + + ui_buttons = list( + "plus" = "add_vend_component", + ) + + /// Vendor components attached to this dispenser bot + var/list/obj/item/circuit_component/vendor_component/vendor_components = list() + + var/max_vendor_components = 20 + + +/obj/item/circuit_component/dispenser_bot/populate_ports() + item_list = add_output_port("Items", PORT_TYPE_LIST(PORT_TYPE_ATOM)) + + item = add_output_port("Item", PORT_TYPE_ATOM) + on_item_added = add_output_port("On Item Added", PORT_TYPE_SIGNAL) + on_item_removed = add_output_port("On Item Removed", PORT_TYPE_SIGNAL) + +/obj/item/circuit_component/dispenser_bot/register_shell(atom/movable/shell) + . = ..() + RegisterSignal(shell, COMSIG_DISPENSERBOT_ADD_ITEM, .proc/on_shell_add_item) + RegisterSignal(shell, COMSIG_DISPENSERBOT_REMOVE_ITEM, .proc/on_shell_remove_item) + +/obj/item/circuit_component/dispenser_bot/unregister_shell(atom/movable/shell) + UnregisterSignal(shell, list( + COMSIG_DISPENSERBOT_ADD_ITEM, + COMSIG_DISPENSERBOT_REMOVE_ITEM, + )) + return ..() + +/obj/item/circuit_component/dispenser_bot/proc/on_shell_add_item(obj/structure/dispenser_bot/source, obj/item/added_item) + SIGNAL_HANDLER + item.set_output(added_item) + item_list.set_output(source.stored_items) + on_item_added.set_output(COMPONENT_SIGNAL) + +/obj/item/circuit_component/dispenser_bot/proc/on_shell_remove_item(obj/structure/dispenser_bot/source, obj/item/added_item) + SIGNAL_HANDLER + item.set_output(added_item) + item_list.set_output(source.stored_items) + on_item_added.set_output(COMPONENT_SIGNAL) + +/obj/item/circuit_component/dispenser_bot/proc/remove_vendor_component(obj/item/circuit_component/vendor_component/vendor_component) + SIGNAL_HANDLER + UnregisterSignal(vendor_component, list( + COMSIG_PARENT_QDELETING, + COMSIG_CIRCUIT_COMPONENT_REMOVED, + )) + if(!QDELING(vendor_component)) + qdel(vendor_component) + vendor_components -= vendor_component + +/obj/item/circuit_component/dispenser_bot/ui_perform_action(mob/user, action) + switch(action) + if("add_vend_component") + if(length(vendor_components) >= max_vendor_components) + balloon_alert(user, "you have hit vendor component limit!") + return + var/obj/item/circuit_component/vendor_component/vendor_component = new(parent) + parent.add_component(vendor_component, user) + vendor_components += vendor_component + RegisterSignal(vendor_component, list( + COMSIG_PARENT_QDELETING, + COMSIG_CIRCUIT_COMPONENT_REMOVED, + ), .proc/remove_vendor_component) + +/obj/item/circuit_component/vendor_component + display_name = "Vend" + desc = "A component used to vend out specific objects from the dispenser bot." + + circuit_flags = CIRCUIT_FLAG_OUTPUT_SIGNAL + + var/obj/structure/dispenser_bot/attached_bot + + /// The item this vendor component should vend + var/datum/port/input/item_to_vend + /// Used to vend the item + var/datum/port/input/vend_item + + circuit_size = 0 + +/obj/item/circuit_component/vendor_component/register_shell(atom/movable/shell) + . = ..() + if(istype(shell, /obj/structure/dispenser_bot)) + attached_bot = shell + +/obj/item/circuit_component/vendor_component/unregister_shell(atom/movable/shell) + attached_bot = null + return ..() + +/obj/item/circuit_component/vendor_component/populate_ports() + item_to_vend = add_input_port("Item", PORT_TYPE_ATOM, trigger = null) + vend_item = add_input_port("Vend Item", PORT_TYPE_SIGNAL, trigger = .proc/vend_item) + +/obj/item/circuit_component/vendor_component/proc/vend_item(datum/port/input/port, list/return_values) + CIRCUIT_TRIGGER + if(!attached_bot) + return + + var/obj/item/vending_item = locate(item_to_vend.value) in attached_bot.stored_items + + if(!vending_item) + return + + attached_bot.remove_item(vending_item) diff --git a/tgstation.dme b/tgstation.dme index 41339570c44..5e35e5d0643 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -409,6 +409,7 @@ #include "code\controllers\subsystem\vis_overlays.dm" #include "code\controllers\subsystem\vote.dm" #include "code\controllers\subsystem\weather.dm" +#include "code\controllers\subsystem\wiremod_composite.dm" #include "code\controllers\subsystem\processing\acid.dm" #include "code\controllers\subsystem\processing\ai_basic_avoidance.dm" #include "code\controllers\subsystem\processing\ai_behaviors.dm" @@ -3855,6 +3856,7 @@ #include "code\modules\vending\youtool.dm" #include "code\modules\wiremod\components\abstract\compare.dm" #include "code\modules\wiremod\components\abstract\module.dm" +#include "code\modules\wiremod\components\abstract\variable.dm" #include "code\modules\wiremod\components\action\light.dm" #include "code\modules\wiremod\components\action\mmi.dm" #include "code\modules\wiremod\components\action\pathfind.dm" @@ -3887,6 +3889,8 @@ #include "code\modules\wiremod\components\bci\hud\target_intercept.dm" #include "code\modules\wiremod\components\list\assoc_literal.dm" #include "code\modules\wiremod\components\list\concat.dm" +#include "code\modules\wiremod\components\list\filter.dm" +#include "code\modules\wiremod\components\list\foreach.dm" #include "code\modules\wiremod\components\list\get_column.dm" #include "code\modules\wiremod\components\list\index.dm" #include "code\modules\wiremod\components\list\index_table.dm" @@ -3910,11 +3914,11 @@ #include "code\modules\wiremod\components\string\tostring.dm" #include "code\modules\wiremod\components\utility\clock.dm" #include "code\modules\wiremod\components\utility\delay.dm" -#include "code\modules\wiremod\components\utility\getter.dm" #include "code\modules\wiremod\components\utility\router.dm" -#include "code\modules\wiremod\components\utility\setter.dm" #include "code\modules\wiremod\components\utility\typecast.dm" #include "code\modules\wiremod\components\utility\typecheck.dm" +#include "code\modules\wiremod\components\variables\getter.dm" +#include "code\modules\wiremod\components\variables\setter.dm" #include "code\modules\wiremod\core\admin_panel.dm" #include "code\modules\wiremod\core\component.dm" #include "code\modules\wiremod\core\component_printer.dm" @@ -3929,11 +3933,13 @@ #include "code\modules\wiremod\datatypes\basic.dm" #include "code\modules\wiremod\datatypes\datum.dm" #include "code\modules\wiremod\datatypes\entity.dm" -#include "code\modules\wiremod\datatypes\list.dm" #include "code\modules\wiremod\datatypes\number.dm" #include "code\modules\wiremod\datatypes\option.dm" #include "code\modules\wiremod\datatypes\signal.dm" #include "code\modules\wiremod\datatypes\string.dm" +#include "code\modules\wiremod\datatypes\composite\assoc_list.dm" +#include "code\modules\wiremod\datatypes\composite\composite.dm" +#include "code\modules\wiremod\datatypes\composite\list.dm" #include "code\modules\wiremod\preset\hello_world.dm" #include "code\modules\wiremod\preset\speech_relay.dm" #include "code\modules\wiremod\shell\airlock.dm" @@ -3941,6 +3947,7 @@ #include "code\modules\wiremod\shell\brain_computer_interface.dm" #include "code\modules\wiremod\shell\compact_remote.dm" #include "code\modules\wiremod\shell\controller.dm" +#include "code\modules\wiremod\shell\dispenser.dm" #include "code\modules\wiremod\shell\drone.dm" #include "code\modules\wiremod\shell\gun.dm" #include "code\modules\wiremod\shell\moneybot.dm" diff --git a/tgui/packages/tgui/interfaces/IntegratedCircuit/DisplayName.js b/tgui/packages/tgui/interfaces/IntegratedCircuit/DisplayName.js index 5bebe9762ff..b7842eb50af 100644 --- a/tgui/packages/tgui/interfaces/IntegratedCircuit/DisplayName.js +++ b/tgui/packages/tgui/interfaces/IntegratedCircuit/DisplayName.js @@ -18,7 +18,7 @@ export const DisplayName = (props, context) => { return ( - + {(hasInput && ( diff --git a/tgui/packages/tgui/interfaces/IntegratedCircuit/Port.js b/tgui/packages/tgui/interfaces/IntegratedCircuit/Port.js index 305a3c30d0d..377b608a60a 100644 --- a/tgui/packages/tgui/interfaces/IntegratedCircuit/Port.js +++ b/tgui/packages/tgui/interfaces/IntegratedCircuit/Port.js @@ -1,10 +1,10 @@ import { Stack, - Icon, + Box, } from '../../components'; import { Component, createRef } from 'inferno'; import { DisplayName } from "./DisplayName"; - +import { classes } from 'common/react'; export class Port extends Component { constructor() { @@ -64,47 +64,89 @@ export class Port extends Component { } } - render() { + renderDisplayName() { const { port, portIndex, componentId, isOutput, - ...rest } = this.props; return ( - - {!!isOutput && ( - - - - )} + + + + ); + } + + render() { + const { + port, + isOutput, + ...rest + } = this.props; + + + let composite_types = []; + if (port.datatype_data?.composite_types) { + composite_types = port.datatype_data.composite_types; + } + + return ( + + {!!isOutput && this.renderDisplayName()} - + + {composite_types.map((compositeColor, index) => { + const radians = (2*Math.PI)/composite_types.length; + const arcLength = radians*50; + return ( + + ); + })} + + - + - {!isOutput && ( - - - - )} + {!isOutput && this.renderDisplayName()} ); } diff --git a/tgui/packages/tgui/interfaces/IntegratedCircuit/VariableMenu.js b/tgui/packages/tgui/interfaces/IntegratedCircuit/VariableMenu.js index f76efc68292..c62a9104ff3 100644 --- a/tgui/packages/tgui/interfaces/IntegratedCircuit/VariableMenu.js +++ b/tgui/packages/tgui/interfaces/IntegratedCircuit/VariableMenu.js @@ -99,7 +99,7 @@ export class VariableMenu extends Component { Drag me onto the circuit's grid to make a setter for this variable` } - icon="hammer" + icon="pen" /> @@ -113,7 +113,7 @@ export class VariableMenu extends Component { color={val.color} onMouseDown={(e) => handleMouseDownGetter(e, val.name)} - icon="eye" + icon="book-open" /> @@ -162,10 +162,21 @@ export class VariableMenu extends Component { height="100%" color="green" onClick={(e) => - onAddVariable(variable_name, variable_type, e)} + onAddVariable(variable_name, variable_type, false, e)} fluid > - + + + + + @@ -179,12 +190,12 @@ export class VariableMenu extends Component { } } -const PlusIconButton = (props, context) => { +const IconButton = (props, context) => { return ( - + this.setState({ menuOpen: false })} - onAddVariable={(name, type, event) => act("add_variable", { + onAddVariable={(name, type, asList, event) => act("add_variable", { variable_name: name, variable_datatype: type, + is_list: asList, })} onRemoveVariable={(name, event) => act("remove_variable", { variable_name: name, diff --git a/tgui/packages/tgui/styles/interfaces/IntegratedCircuit.scss b/tgui/packages/tgui/styles/interfaces/IntegratedCircuit.scss index 6d66e8582d2..bc0fc4fd506 100644 --- a/tgui/packages/tgui/styles/interfaces/IntegratedCircuit.scss +++ b/tgui/packages/tgui/styles/interfaces/IntegratedCircuit.scss @@ -1,10 +1,10 @@ @use '../colors.scss'; @use '../base.scss'; -$bg-map: colors.$bg-map !default; +$fg-map: colors.$fg-map !default; .CircuitInfo__Examined { - background-color:rgba(0, 0, 0, 1); + background-color: rgba(0, 0, 0, 1); padding: 8px; border-radius: 5px; @@ -30,6 +30,12 @@ $bg-map: colors.$bg-map !default; user-select: none; } +.ObjectComponent__Port { + position: relative; + width: 13px; + height: 13px; +} + .ObjectComponent__PortPos { position: absolute; top: 0; @@ -38,10 +44,14 @@ $bg-map: colors.$bg-map !default; bottom: 0; } -@each $color-name, $color-value in $bg-map { +@each $color-name, $color-value in $fg-map { .color-stroke-#{$color-name} { stroke: $color-value !important; } + + .color-fill-#{$color-name} { + fill: $color-value !important; + } } $border-color: #88bfff !default;