From 7e9e2df721898bf92d1e9a42823e8bc4370b7fdd Mon Sep 17 00:00:00 2001 From: Watermelon914 <37270891+Watermelon914@users.noreply.github.com> Date: Tue, 29 Jun 2021 21:23:14 +0100 Subject: [PATCH] Adds USB to arrest consoles. Adds list circuit components. (#59850) Co-authored-by: Watermelon914 <3052169-Watermelon914@users.noreply.gitlab.com> Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com> --- code/__DEFINES/wiremod.dm | 13 +- code/controllers/subsystem/delay_component.dm | 33 +++- code/datums/components/shell.dm | 1 + code/game/machinery/computer/security.dm | 174 ++++++++++++++++++ .../research/designs/wiremod_designs.dm | 20 ++ code/modules/research/techweb/all_nodes.dm | 4 + code/modules/wiremod/component.dm | 42 ++++- .../wiremod/components/action/light.dm | 6 +- .../wiremod/components/action/speech.dm | 6 +- .../wiremod/components/atom/direction.dm | 6 +- .../modules/wiremod/components/atom/health.dm | 6 +- .../modules/wiremod/components/list/concat.dm | 54 ++++++ .../wiremod/components/list/get_column.dm | 48 +++++ .../components/{math => list}/index.dm | 0 .../wiremod/components/list/index_table.dm | 48 +++++ .../modules/wiremod/components/list/select.dm | 96 ++++++++++ .../wiremod/components/utility/clock.dm | 6 +- .../wiremod/components/utility/delay.dm | 2 +- code/modules/wiremod/integrated_circuit.dm | 23 +++ code/modules/wiremod/port.dm | 15 +- code/modules/wiremod/shell/drone.dm | 2 +- tgstation.dme | 6 +- 22 files changed, 560 insertions(+), 51 deletions(-) create mode 100644 code/modules/wiremod/components/list/concat.dm create mode 100644 code/modules/wiremod/components/list/get_column.dm rename code/modules/wiremod/components/{math => list}/index.dm (100%) create mode 100644 code/modules/wiremod/components/list/index_table.dm create mode 100644 code/modules/wiremod/components/list/select.dm diff --git a/code/__DEFINES/wiremod.dm b/code/__DEFINES/wiremod.dm index e912af0ebaa..e15c2c010e2 100644 --- a/code/__DEFINES/wiremod.dm +++ b/code/__DEFINES/wiremod.dm @@ -1,5 +1,3 @@ -#define PORT_INPUT_RECEIVE_DELAY 0.2 SECONDS - /// Helper define that can only be used in /obj/item/circuit_component/input_received() #define COMPONENT_TRIGGERED_BY(trigger, port) (trigger.input_value && trigger == port) @@ -21,6 +19,8 @@ #define PORT_TYPE_SIGNAL "signal" /// List datatype #define PORT_TYPE_LIST "list" +/// Table datatype. Derivative of list, contains other lists with matching columns. +#define PORT_TYPE_TABLE "table" // Other datatypes /// Atom datatype @@ -88,6 +88,15 @@ #define COMP_RADIO_PUBLIC "public" #define COMP_RADIO_PRIVATE "private" +// Security Arrest Console +#define COMP_STATE_ARREST "*Arrest*" +#define COMP_STATE_PRISONER "Incarcerated" +#define COMP_STATE_PAROL "Paroled" +#define COMP_STATE_DISCHARGED "Discharged" +#define COMP_STATE_NONE "None" + +#define COMP_SECURITY_ARREST_AMOUNT_TO_FLAG 10 + // Shells /// Whether a circuit is stuck on a shell and cannot be removed (by a user) diff --git a/code/controllers/subsystem/delay_component.dm b/code/controllers/subsystem/delay_component.dm index 098dd8c65cc..3e549ae7963 100644 --- a/code/controllers/subsystem/delay_component.dm +++ b/code/controllers/subsystem/delay_component.dm @@ -1,3 +1,34 @@ -TIMER_SUBSYSTEM_DEF(circuit_component) +SUBSYSTEM_DEF(circuit_component) name = "Circuit Components" + wait = 0.1 SECONDS priority = FIRE_PRIORITY_DEFAULT + + var/list/callbacks_to_invoke = list() + var/list/currentrun = list() + +/datum/controller/subsystem/circuit_component/fire(resumed) + if(!resumed) + currentrun = callbacks_to_invoke.Copy() + callbacks_to_invoke.Cut() + + while(length(currentrun)) + var/datum/callback/to_call = currentrun[1] + currentrun.Cut(1,2) + + if(QDELETED(to_call)) + continue + + to_call.InvokeAsync() + qdel(to_call) + + if(MC_TICK_CHECK) + return + +/** + * Adds a callback to be invoked when the next fire() is done. Used by the integrated circuit system. + * + * Prevents race conditions as it acts like a queue system. + * Those that registered first will be executed first and those registered last will be executed last. + */ +/datum/controller/subsystem/circuit_component/proc/add_callback(datum/callback/to_call) + callbacks_to_invoke += to_call diff --git a/code/datums/components/shell.dm b/code/datums/components/shell.dm index 37381848252..38415bff80b 100644 --- a/code/datums/components/shell.dm +++ b/code/datums/components/shell.dm @@ -125,6 +125,7 @@ source.balloon_alert(attacker, "this is too large to fit into [parent]!") return + logic_board.inserter_mind = WEAKREF(attacker.mind) attach_circuit(logic_board, attacker) /datum/component/shell/proc/on_multitool_act(atom/source, mob/user, obj/item/tool) diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 8b0915afe02..ecb83690f93 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -19,6 +19,180 @@ var/sortBy = "name" var/order = 1 // -1 = Descending - 1 = Ascending +/obj/machinery/computer/secure_data/Initialize(mapload, obj/item/circuitboard/C) + . = ..() + AddComponent(/datum/component/usb_port, list( + /obj/item/circuit_component/arrest_console_data, + /obj/item/circuit_component/arrest_console_arrest, + )) + +/obj/item/circuit_component/arrest_console_data + display_name = "Security Records Data" + display_desc = "Outputs the security records data, where it can then be filtered with a Select Query component" + circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL + + /// The records retrieved + var/datum/port/output/records + + /// Sends a signal on failure + var/datum/port/output/on_fail + + var/obj/machinery/computer/secure_data/attached_console + +/obj/item/circuit_component/arrest_console_data/Initialize() + . = ..() + records = add_output_port("Security Records", PORT_TYPE_TABLE) + on_fail = add_output_port("Failed", PORT_TYPE_SIGNAL) + +/obj/item/circuit_component/arrest_console_data/Destroy() + records = null + on_fail = null + return ..() + + +/obj/item/circuit_component/arrest_console_data/register_usb_parent(atom/movable/parent) + . = ..() + if(istype(parent, /obj/machinery/computer/secure_data)) + attached_console = parent + +/obj/item/circuit_component/arrest_console_data/unregister_usb_parent(atom/movable/parent) + attached_console = null + return ..() + +/obj/item/circuit_component/arrest_console_data/get_ui_notices() + . = ..() + . += create_table_notices(list( + "name", + "id", + "rank", + "arrest_status", + "gender", + "age", + "species", + "fingerprint", + )) + + +/obj/item/circuit_component/arrest_console_data/input_received(datum/port/input/port) + . = ..() + if(.) + return + + if(!attached_console || !attached_console.authenticated) + on_fail.set_output(COMPONENT_SIGNAL) + return + + if(isnull(GLOB.data_core.general)) + on_fail.set_output(COMPONENT_SIGNAL) + return + + var/list/new_table = list() + for(var/datum/data/record/player_record as anything in GLOB.data_core.general) + var/list/entry = list() + var/datum/data/record/player_security_record = find_record("id", player_record.fields["id"], GLOB.data_core.security) + if(player_security_record) + entry["arrest_status"] = player_security_record.fields["criminal"] + entry["security_record"] = player_security_record + entry["name"] = player_record.fields["name"] + entry["id"] = player_record.fields["id"] + entry["rank"] = player_record.fields["rank"] + entry["gender"] = player_record.fields["gender"] + entry["age"] = player_record.fields["age"] + entry["species"] = player_record.fields["species"] + entry["fingerprint"] = player_record.fields["fingerprint"] + + new_table += list(entry) + + records.set_output(new_table) + +/obj/item/circuit_component/arrest_console_arrest + display_name = "Security Records Set Status" + display_desc = "Receives a table to use to set people's arrest status. Table should be from the security records data component. If New Status port isn't set, the status will be decided by the options." + circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL + + /// The targets to set the status of. + var/datum/port/input/targets + + /// Sets the new status of the targets. If set to null, the status is taken from the options. + var/datum/port/input/new_status + + /// Returns the new status set once the setting is complete. Good for locating errors. + var/datum/port/output/new_status_set + + /// Sends a signal on failure + var/datum/port/output/on_fail + + var/obj/machinery/computer/secure_data/attached_console + +/obj/item/circuit_component/arrest_console_arrest/register_usb_parent(atom/movable/parent) + . = ..() + if(istype(parent, /obj/machinery/computer/secure_data)) + attached_console = parent + +/obj/item/circuit_component/arrest_console_arrest/unregister_usb_parent(atom/movable/parent) + attached_console = null + return ..() + +/obj/item/circuit_component/arrest_console_arrest/populate_options() + var/static/list/component_options = list( + COMP_STATE_ARREST, + COMP_STATE_PRISONER, + COMP_STATE_PAROL, + COMP_STATE_DISCHARGED, + COMP_STATE_NONE, + ) + options = component_options + +/obj/item/circuit_component/arrest_console_arrest/Initialize() + . = ..() + targets = add_input_port("Targets", PORT_TYPE_TABLE) + new_status = add_input_port("New Status", PORT_TYPE_STRING) + new_status_set = add_output_port("Set Status", PORT_TYPE_STRING) + on_fail = add_output_port("Failed", PORT_TYPE_SIGNAL) + +/obj/item/circuit_component/arrest_console_arrest/Destroy() + targets = null + new_status = null + new_status_set = null + on_fail = null + return ..() + +/obj/item/circuit_component/arrest_console_arrest/input_received(datum/port/input/port) + . = ..() + if(.) + return + + if(!attached_console || !attached_console.authenticated) + on_fail.set_output(COMPONENT_SIGNAL) + return + + var/status_to_set = new_status.input_value + if(!status_to_set || !(status_to_set in options)) + status_to_set = current_option + + new_status_set.set_output(status_to_set) + var/list/target_table = targets.input_value + if(!target_table) + on_fail.set_output(COMPONENT_SIGNAL) + return + + var/successful_set = 0 + var/list/names_of_entries = list() + for(var/list/target in target_table) + var/datum/data/record/sec_record = target["security_record"] + if(!sec_record) + continue + + successful_set++ + sec_record.fields["criminal"] = status_to_set + names_of_entries += target["name"] + + if(successful_set > 0) + investigate_log("[names_of_entries.Join(", ")] have been set to [status_to_set] by [parent.get_creator()].", INVESTIGATE_RECORDS) + if(successful_set > COMP_SECURITY_ARREST_AMOUNT_TO_FLAG) + message_admins("[successful_set] security entries have been set to [status_to_set] by [parent.get_creator_admin()]. [ADMIN_COORDJMP(src)]") + for(var/mob/living/carbon/human/human as anything in GLOB.human_list) + human.sec_hud_set_security_status() /obj/machinery/computer/secure_data/syndie icon_keyboard = "syndie_key" diff --git a/code/modules/research/designs/wiremod_designs.dm b/code/modules/research/designs/wiremod_designs.dm index 25aa7f227fa..14c15a26d5d 100644 --- a/code/modules/research/designs/wiremod_designs.dm +++ b/code/modules/research/designs/wiremod_designs.dm @@ -183,6 +183,26 @@ id = "comp_multiplexer" build_path = /obj/item/circuit_component/multiplexer +/datum/design/component/get_column + name = "Get Column Component" + id = "comp_get_column" + build_path = /obj/item/circuit_component/get_column + +/datum/design/component/index_table + name = "Index Table Component" + id = "comp_index_table" + build_path = /obj/item/circuit_component/index_table + +/datum/design/component/concat_list + name = "Concatenate List Component" + id = "comp_concat_list" + build_path = /obj/item/circuit_component/concat_list + +/datum/design/component/select_query + name = "Select Query Component" + id = "comp_select_query" + build_path = /obj/item/circuit_component/select + /datum/design/compact_remote_shell name = "Compact Remote Shell" desc = "A handheld shell with one big button." diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index addf254bf73..3daf00032db 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -199,12 +199,15 @@ "comp_combiner", "comp_comparison", "comp_concat", + "comp_concat_list", "comp_delay", "comp_direction", + "comp_get_column", "comp_gps", "comp_health", "comp_hear", "comp_index", + "comp_index_table", "comp_length", "comp_light", "comp_logic", @@ -214,6 +217,7 @@ "comp_radio", "comp_ram", "comp_random", + "comp_select_query", "comp_self", "comp_species", "comp_speech", diff --git a/code/modules/wiremod/component.dm b/code/modules/wiremod/component.dm index 0dcfd6358db..9ed55616bb6 100644 --- a/code/modules/wiremod/component.dm +++ b/code/modules/wiremod/component.dm @@ -218,19 +218,41 @@ . = list() if(!removable) - . += list(list( - "icon" = "lock", - "content" = "Unremovable", - "color" = "red" - )) + . += create_ui_notice("Unremovable", "red", "lock") if(length(input_ports)) - . += list(list( - "icon" = "bolt", - "content" = "Power Usage Per Input: [power_usage_per_input]", - "color" = "orange", - )) + . += create_ui_notice("Power Usage Per Input: [power_usage_per_input]", "orange", "bolt") + +/** + * Creates a UI notice entry to be used in get_ui_notices() + * + * Returns a list that can then be added to the return list in get_ui_notices() + */ +/obj/item/circuit_component/proc/create_ui_notice(content, color, icon) + SHOULD_BE_PURE(TRUE) + SHOULD_NOT_OVERRIDE(TRUE) + return list(list( + "icon" = icon, + "content" = content, + "color" = color, + )) + +/** + * Creates a table UI notice entry to be used in get_ui_notices() + * + * Returns a list that can then be added to the return list in get_ui_notices() + * Used by components to list their available columns. Recommended to use at the end of get_ui_notices() + */ +/obj/item/circuit_component/proc/create_table_notices(list/entries) + SHOULD_BE_PURE(TRUE) + SHOULD_NOT_OVERRIDE(TRUE) + . = list() + . += create_ui_notice("Available Columns:", "grey", "question-circle") + + + for(var/entry in entries) + . += create_ui_notice("Column Name: '[entry]'", "grey", "columns") /obj/item/circuit_component/proc/register_usb_parent(atom/movable/parent) return diff --git a/code/modules/wiremod/components/action/light.dm b/code/modules/wiremod/components/action/light.dm index f398ac9dafd..bf3d62aca65 100644 --- a/code/modules/wiremod/components/action/light.dm +++ b/code/modules/wiremod/components/action/light.dm @@ -24,11 +24,7 @@ /obj/item/circuit_component/light/get_ui_notices() . = ..() - . += list(list( - "icon" = "lightbulb", - "content" = "Maximum Brightness: [max_power]", - "color" = "orange" - )) + . += create_ui_notice("Maximum Brightness: [max_power]", "orange", "lightbulb") /obj/item/circuit_component/light/Initialize() . = ..() diff --git a/code/modules/wiremod/components/action/speech.dm b/code/modules/wiremod/components/action/speech.dm index 8b0084fa522..41dd3d2f31c 100644 --- a/code/modules/wiremod/components/action/speech.dm +++ b/code/modules/wiremod/components/action/speech.dm @@ -19,11 +19,7 @@ /obj/item/circuit_component/speech/get_ui_notices() . = ..() - . += list(list( - "icon" = "stopwatch", - "content" = "Speech Cooldown: [DisplayTimeText(speech_cooldown)]", - "color" = "orange", - )) + . += create_ui_notice("Speech Cooldown: [DisplayTimeText(speech_cooldown)]", "orange", "stopwatch") /obj/item/circuit_component/speech/Initialize() . = ..() diff --git a/code/modules/wiremod/components/atom/direction.dm b/code/modules/wiremod/components/atom/direction.dm index 872076af7f2..c283b70ca99 100644 --- a/code/modules/wiremod/components/atom/direction.dm +++ b/code/modules/wiremod/components/atom/direction.dm @@ -26,11 +26,7 @@ /obj/item/circuit_component/direction/get_ui_notices() . = ..() - . += list(list( - "icon" = "info", - "content" = "Maximum Range: [max_range] tiles", - "color" = "orange", - )) + . += create_ui_notice("Maximum Range: [max_range] tiles", "orange", "info") /obj/item/circuit_component/direction/Initialize() . = ..() diff --git a/code/modules/wiremod/components/atom/health.dm b/code/modules/wiremod/components/atom/health.dm index af8afcb3167..e3a49502b0f 100644 --- a/code/modules/wiremod/components/atom/health.dm +++ b/code/modules/wiremod/components/atom/health.dm @@ -27,11 +27,7 @@ /obj/item/circuit_component/health/get_ui_notices() . = ..() - . += list(list( - "icon" = "info", - "content" = "Maximum Range: [max_range] tiles", - "color" = "orange", - )) + . += create_ui_notice("Maximum Range: [max_range] tiles", "orange", "info") /obj/item/circuit_component/health/Initialize() . = ..() diff --git a/code/modules/wiremod/components/list/concat.dm b/code/modules/wiremod/components/list/concat.dm new file mode 100644 index 00000000000..f800a4a70e7 --- /dev/null +++ b/code/modules/wiremod/components/list/concat.dm @@ -0,0 +1,54 @@ +/** + * # Concat List Component + * + * Concatenates a list with a separator + */ +/obj/item/circuit_component/concat_list + display_name = "Concatenate List" + display_desc = "A component that joins up a list with a separator into a single string." + + /// The input port + var/datum/port/input/list_port + + /// The seperator + var/datum/port/input/separator + + /// The result from the output + var/datum/port/output/output + circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL + +/obj/item/circuit_component/concat_list/Initialize() + . = ..() + list_port = add_input_port("List", PORT_TYPE_LIST) + separator = add_input_port("Seperator", PORT_TYPE_STRING) + + output = add_output_port("Output", PORT_TYPE_STRING) + +/obj/item/circuit_component/concat_list/Destroy() + list_port = null + separator = null + output = null + return ..() + +/obj/item/circuit_component/concat_list/input_received(datum/port/input/port) + . = ..() + if(.) + return + + var/seperator = separator.input_value + if(!seperator) + return + + var/list/list_input = list_port.input_value + if(!list_input) + return + + var/list/text_list = list() + for(var/entry in list_input) + if(isatom(entry)) + text_list += PORT_TYPE_ATOM + else + text_list += "[entry]" + + output.set_output(text_list.Join(seperator)) + diff --git a/code/modules/wiremod/components/list/get_column.dm b/code/modules/wiremod/components/list/get_column.dm new file mode 100644 index 00000000000..fac219ab249 --- /dev/null +++ b/code/modules/wiremod/components/list/get_column.dm @@ -0,0 +1,48 @@ +/** + * # Get Column Component + * + * Gets the column of a table and returns it as a regular list. + */ +/obj/item/circuit_component/get_column + display_name = "Get Column" + display_desc = "Gets the column of a table and returns it as a regular list." + circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL + + /// The list to perform the filter on + var/datum/port/input/received_table + + /// The name of the column to check + var/datum/port/input/column_name + + /// The filtered list + var/datum/port/output/output_list + +/obj/item/circuit_component/get_column/Initialize() + . = ..() + 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) + +/obj/item/circuit_component/get_column/Destroy() + received_table = null + column_name = null + output_list = null + return ..() + +/obj/item/circuit_component/get_column/input_received(datum/port/input/port) + . = ..() + if(.) + return + + var/list/input_list = received_table.input_value + if(!islist(input_list) || isnum(column_name.input_value)) + return + + var/list/new_list = list() + for(var/list/entry in input_list) + var/anything = entry[column_name.input_value] + if(islist(anything)) + continue + new_list += anything + + output_list.set_output(new_list) diff --git a/code/modules/wiremod/components/math/index.dm b/code/modules/wiremod/components/list/index.dm similarity index 100% rename from code/modules/wiremod/components/math/index.dm rename to code/modules/wiremod/components/list/index.dm diff --git a/code/modules/wiremod/components/list/index_table.dm b/code/modules/wiremod/components/list/index_table.dm new file mode 100644 index 00000000000..9bfe8b70945 --- /dev/null +++ b/code/modules/wiremod/components/list/index_table.dm @@ -0,0 +1,48 @@ +/** + * # Index Table Component + * + * Gets the row of a table using the index inputted. Will return no value if the index is invalid or a proper table is not returned. + */ +/obj/item/circuit_component/index_table + display_name = "Index Table" + display_desc = "Gets the row of a table using the index inputted. Will return no value if the index is invalid or a proper table is not returned." + circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL + + /// The list to perform the filter on + var/datum/port/input/received_table + + /// The target index + var/datum/port/input/target_index + + /// The filtered list + var/datum/port/output/output_list + +/obj/item/circuit_component/index_table/Initialize() + . = ..() + 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_TABLE) + +/obj/item/circuit_component/index_table/Destroy() + received_table = null + target_index = null + output_list = null + return ..() + +/obj/item/circuit_component/index_table/input_received(datum/port/input/port) + . = ..() + if(.) + return + + var/list/target_list = received_table.input_value + if(!islist(target_list) || !length(target_list)) + output_list.set_output(null) + return + + var/index = target_index.input_value + if(index < 1 || index > length(target_list)) + output_list.set_output(null) + return + + output_list.set_output(target_list[index]) diff --git a/code/modules/wiremod/components/list/select.dm b/code/modules/wiremod/components/list/select.dm new file mode 100644 index 00000000000..76eaf67b408 --- /dev/null +++ b/code/modules/wiremod/components/list/select.dm @@ -0,0 +1,96 @@ +/** + * # Select Component + * + * Selects a list from a list of lists by a specific column. Used only by USBs for communications to and from computers with lists of varying sizes. + */ +/obj/item/circuit_component/select + display_name = "Select Query" + display_desc = "A component used with USB cables that can perform select queries on a list based on the column name selected. The values are then compared with the comparison input." + circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL + + /// The list to perform the filter on + var/datum/port/input/received_table + + /// The name of the column to check + var/datum/port/input/column_name + + /// The input to compare with + var/datum/port/input/comparison_input + + /// The filtered list + var/datum/port/output/filtered_table + + var/current_type = PORT_TYPE_ANY + +/obj/item/circuit_component/select/populate_options() + var/static/component_options = list( + COMP_COMPARISON_EQUAL, + COMP_COMPARISON_NOT_EQUAL, + COMP_COMPARISON_GREATER_THAN, + COMP_COMPARISON_LESS_THAN, + COMP_COMPARISON_GREATER_THAN_OR_EQUAL, + COMP_COMPARISON_LESS_THAN_OR_EQUAL, + ) + options = component_options + +/obj/item/circuit_component/select/Initialize() + . = ..() + received_table = add_input_port("Input", PORT_TYPE_TABLE) + column_name = add_input_port("Column Name", PORT_TYPE_STRING) + comparison_input = add_input_port("Comparison Input", PORT_TYPE_ANY) + + filtered_table = add_output_port("Output", PORT_TYPE_TABLE) + +/obj/item/circuit_component/select/Destroy() + received_table = null + column_name = null + comparison_input = null + filtered_table = null + return ..() + +/obj/item/circuit_component/select/input_received(datum/port/input/port) + . = ..() + switch(current_option) + if(COMP_COMPARISON_EQUAL, COMP_COMPARISON_NOT_EQUAL) + if(current_type != PORT_TYPE_ANY) + current_type = PORT_TYPE_ANY + comparison_input.set_datatype(PORT_TYPE_ANY) + else + if(current_type != PORT_TYPE_NUMBER) + current_type = PORT_TYPE_NUMBER + comparison_input.set_datatype(PORT_TYPE_NUMBER) + + if(.) + return + + var/list/input_list = received_table.input_value + if(!islist(input_list) || isnum(column_name.input_value)) + return + + var/comparison_value = comparison_input.input_value + var/list/new_list = list() + for(var/list/entry in input_list) + var/anything = entry[column_name.input_value] + if(islist(anything)) + continue + if(current_option != COMP_COMPARISON_EQUAL && current_option != COMP_COMPARISON_NOT_EQUAL && !isnum(anything)) + continue + var/add_to_list = FALSE + switch(current_option) + if(COMP_COMPARISON_EQUAL) + add_to_list = anything == comparison_value + if(COMP_COMPARISON_NOT_EQUAL) + add_to_list = anything != comparison_value + if(COMP_COMPARISON_GREATER_THAN) + add_to_list = anything > comparison_value + if(COMP_COMPARISON_GREATER_THAN_OR_EQUAL) + add_to_list = anything >= comparison_value + if(COMP_COMPARISON_LESS_THAN) + add_to_list = anything < comparison_value + if(COMP_COMPARISON_LESS_THAN_OR_EQUAL) + add_to_list = anything <= comparison_value + + if(add_to_list) + new_list += list(entry) + + filtered_table.set_output(new_list) diff --git a/code/modules/wiremod/components/utility/clock.dm b/code/modules/wiremod/components/utility/clock.dm index 91b3a0db4b3..e856b1ee4d0 100644 --- a/code/modules/wiremod/components/utility/clock.dm +++ b/code/modules/wiremod/components/utility/clock.dm @@ -15,11 +15,7 @@ /obj/item/circuit_component/clock/get_ui_notices() . = ..() - . += list(list( - "icon" = "clock", - "content" = "Clock Interval: [DisplayTimeText(COMP_CLOCK_DELAY)]", - "color" = "orange", - )) + . += create_ui_notice("Clock Interval: [DisplayTimeText(COMP_CLOCK_DELAY)]", "orange", "clock") /obj/item/circuit_component/clock/Initialize() . = ..() diff --git a/code/modules/wiremod/components/utility/delay.dm b/code/modules/wiremod/components/utility/delay.dm index 7403bb41321..a7e43f56090 100644 --- a/code/modules/wiremod/components/utility/delay.dm +++ b/code/modules/wiremod/components/utility/delay.dm @@ -39,6 +39,6 @@ var/delay = delay_amount.input_value if(delay > COMP_DELAY_MIN_VALUE) // Convert delay into deciseconds - addtimer(CALLBACK(output, /datum/port/output.proc/set_output, trigger.input_value), delay*10, timer_subsystem =SScircuit_component) + addtimer(CALLBACK(output, /datum/port/output.proc/set_output, trigger.input_value), delay*10) else output.set_output(trigger.input_value) diff --git a/code/modules/wiremod/integrated_circuit.dm b/code/modules/wiremod/integrated_circuit.dm index 71f57062b7c..a9060673b3e 100644 --- a/code/modules/wiremod/integrated_circuit.dm +++ b/code/modules/wiremod/integrated_circuit.dm @@ -35,6 +35,9 @@ /// The current examined component. Used in IntegratedCircuit UI var/datum/weakref/examined_component + /// Set by the shell. Holds the reference to the owner who inserted the component into the shell. + var/datum/weakref/inserter_mind + /// X position of the examined_component var/examined_rel_x = 0 @@ -444,3 +447,23 @@ return COMSIG_CANCEL_USB_CABLE_ATTACK #undef WITHIN_RANGE + +/** + * Returns the creator of the integrated circuit. Used in admin messages and other related things. + */ +/obj/item/integrated_circuit/proc/get_creator_admin() + return get_creator(include_link = TRUE) + +/** + * Returns the creator of the integrated circuit. Used in admin logs and other related things. + */ +/obj/item/integrated_circuit/proc/get_creator(include_link = FALSE) + var/datum/mind/inserter + if(inserter_mind) + inserter = inserter_mind.resolve() + + var/obj/item/card/id/id_card + if(owner_id) + id_card = owner_id.resolve() + + return "(Shell: [shell || "*null*"], Inserter: [key_name(inserter, include_link)], Owner ID: [id_card?.name || "*null*"])" diff --git a/code/modules/wiremod/port.dm b/code/modules/wiremod/port.dm index 38a3282d25d..a3fb7c1f193 100644 --- a/code/modules/wiremod/port.dm +++ b/code/modules/wiremod/port.dm @@ -48,6 +48,8 @@ return "white" if(PORT_TYPE_SIGNAL) return "teal" + if(PORT_TYPE_TABLE) + return "grey" /datum/port/Destroy(force) if(!force && !QDELETED(connected_component)) @@ -94,8 +96,8 @@ datatype = type_to_set color = datatype_to_color() disconnect() - if(connected_component) - SStgui.update_uis(connected_component) + if(connected_component?.parent) + SStgui.update_uis(connected_component.parent) /** * Disconnects a port from all other ports @@ -187,10 +189,6 @@ /// The connected output port var/datum/port/output/connected_port - /// The delay before updating the input value whenever a modification is made. - /// This does not apply when when the output port is registered - var/input_receive_delay = PORT_INPUT_RECEIVE_DELAY - /// Whether this port triggers an update whenever an output is received. var/trigger = FALSE @@ -236,10 +234,7 @@ */ /datum/port/input/proc/receive_output(datum/port/output/connected_port, new_value) SIGNAL_HANDLER - if(input_receive_delay) - addtimer(CALLBACK(src, .proc/set_input, new_value), input_receive_delay, timer_subsystem = SScircuit_component) - else - set_input(new_value) + SScircuit_component.add_callback(CALLBACK(src, .proc/set_input, new_value)) /** * Updates the value of the input diff --git a/code/modules/wiremod/shell/drone.dm b/code/modules/wiremod/shell/drone.dm index 5944b662302..73312bebd6f 100644 --- a/code/modules/wiremod/shell/drone.dm +++ b/code/modules/wiremod/shell/drone.dm @@ -42,7 +42,7 @@ COOLDOWN_DECLARE(west_delay) /// Delay between each movement - var/move_delay = PORT_INPUT_RECEIVE_DELAY + var/move_delay = 0.2 SECONDS /obj/item/circuit_component/bot_circuit/Initialize() . = ..() diff --git a/tgstation.dme b/tgstation.dme index 4eb7a5f4138..1cc75080094 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3584,9 +3584,13 @@ #include "code\modules\wiremod\components\atom\hear.dm" #include "code\modules\wiremod\components\atom\self.dm" #include "code\modules\wiremod\components\atom\species.dm" +#include "code\modules\wiremod\components\list\concat.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" +#include "code\modules\wiremod\components\list\select.dm" #include "code\modules\wiremod\components\math\arithmetic.dm" #include "code\modules\wiremod\components\math\comparison.dm" -#include "code\modules\wiremod\components\math\index.dm" #include "code\modules\wiremod\components\math\length.dm" #include "code\modules\wiremod\components\math\logic.dm" #include "code\modules\wiremod\components\math\not.dm"