diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 2557d35a31a..d711303368b 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -1536,3 +1536,9 @@ ///Sent from /datum/biological_sample/proc/reset_sample #define COMSIG_SAMPLE_GROWTH_COMPLETED "sample_growth_completed" #define SPARE_SAMPLE (1<<0) + +/// Called when a techweb design is researched (datum/design/researched_design, custom) +#define COMSIG_TECHWEB_ADD_DESIGN "techweb_add_design" + +/// Called when a techweb design is removed (datum/design/removed_design, custom) +#define COMSIG_TECHWEB_REMOVE_DESIGN "techweb_remove_design" diff --git a/code/__DEFINES/wiremod.dm b/code/__DEFINES/wiremod.dm index 78447d1a73d..c93e263cbcc 100644 --- a/code/__DEFINES/wiremod.dm +++ b/code/__DEFINES/wiremod.dm @@ -52,6 +52,8 @@ #define COMPONENT_DEFAULT_NAME "component" +#define COMPONENT_DEFAULT_CATEGORY "Unassigned" + /// The minimum position of the x and y co-ordinates of the component in the UI #define COMPONENT_MIN_RANDOM_POS 200 /// The maximum position of the x and y co-ordinates of the component in the UI diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm index 75360a20db1..351e26b980a 100644 --- a/code/modules/research/techweb/_techweb.dm +++ b/code/modules/research/techweb/_techweb.dm @@ -199,6 +199,7 @@ /datum/techweb/proc/add_design(datum/design/design, custom = FALSE) if(!istype(design)) return FALSE + SEND_SIGNAL(src, COMSIG_TECHWEB_ADD_DESIGN, design, custom) researched_designs[design.id] = TRUE if(custom) custom_designs[design.id] = TRUE @@ -212,6 +213,7 @@ return FALSE if(custom_designs[design.id] && !custom) return FALSE + SEND_SIGNAL(src, COMSIG_TECHWEB_REMOVE_DESIGN, design, custom) custom_designs -= design.id researched_designs -= design.id return TRUE diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 9ef101e0dd0..1c31a3553ea 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -51,6 +51,7 @@ #include "card_mismatch.dm" #include "chain_pull_through_space.dm" #include "chat_filter.dm" +#include "circuit_component_category.dm" #include "closets.dm" #include "combat.dm" #include "component_tests.dm" diff --git a/code/modules/unit_tests/circuit_component_category.dm b/code/modules/unit_tests/circuit_component_category.dm new file mode 100644 index 00000000000..72995a2ac4a --- /dev/null +++ b/code/modules/unit_tests/circuit_component_category.dm @@ -0,0 +1,11 @@ +/// Tests to make sure each circuit component that could potentially be available to a player has a category +/datum/unit_test/circuit_component_category + +/datum/unit_test/circuit_component_category/Run() + for(var/datum/design/design in subtypesof(/datum/design/component)) + var/obj/item/circuit_component/path = initial(design.build_path) + if(!path) + continue + + if(initial(path.category) == COMPONENT_DEFAULT_CATEGORY) + Fail("[path] has a category of '[COMPONENT_DEFAULT_CATEGORY]' when it has a research design that players can potentially access!") diff --git a/code/modules/wiremod/components/abstract/module.dm b/code/modules/wiremod/components/abstract/module.dm index 3566d619c9f..ff89f8b0e4a 100644 --- a/code/modules/wiremod/components/abstract/module.dm +++ b/code/modules/wiremod/components/abstract/module.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/module display_name = "Module" desc = "A component that has other components within it, acting like a function. Use it in your hand to control the amount of input and output ports it has, as well as being able to access the integrated circuit contained inside." + category = "Abstract" var/obj/item/integrated_circuit/module/internal_circuit diff --git a/code/modules/wiremod/components/abstract/variable.dm b/code/modules/wiremod/components/abstract/variable.dm index d8070b70876..2130231c332 100644 --- a/code/modules/wiremod/components/abstract/variable.dm +++ b/code/modules/wiremod/components/abstract/variable.dm @@ -4,8 +4,8 @@ * Abstract component for handling variables */ /obj/item/circuit_component/variable - display_name = "Variable Getter" - desc = "A component that gets a variable globally on the circuit." + display_name = "Abstract Variable Component" + desc = "You shouldn't be seeing this." /// Variable name var/datum/port/input/option/variable_name diff --git a/code/modules/wiremod/components/action/light.dm b/code/modules/wiremod/components/action/light.dm index e6ffa5b2a76..61c1f65ef5c 100644 --- a/code/modules/wiremod/components/action/light.dm +++ b/code/modules/wiremod/components/action/light.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/light display_name = "Light" desc = "A component that emits a light of a specific brightness and colour. Requires a shell." + category = "Action" /// The colours of the light var/datum/port/input/red diff --git a/code/modules/wiremod/components/action/mmi.dm b/code/modules/wiremod/components/action/mmi.dm index 932e4a9cce7..3e3c3ef7414 100644 --- a/code/modules/wiremod/components/action/mmi.dm +++ b/code/modules/wiremod/components/action/mmi.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/mmi display_name = "Man-Machine Interface" desc = "A component that allows MMI to enter shells to send output signals." + category = "Action" circuit_flags = CIRCUIT_FLAG_REFUSE_MODULE /// The message to send to the MMI in the shell. diff --git a/code/modules/wiremod/components/action/pathfind.dm b/code/modules/wiremod/components/action/pathfind.dm index 2928dd06e02..eac9633ed24 100644 --- a/code/modules/wiremod/components/action/pathfind.dm +++ b/code/modules/wiremod/components/action/pathfind.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/pathfind display_name = "Pathfinder" desc = "When triggered, the next step to the target's location as an entity. This can be used with the direction component and the drone shell to make it move on its own. The Id Card input port is for considering ID access when pathing, it does not give the shell actual access." + category = "Action" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL var/datum/port/input/input_X diff --git a/code/modules/wiremod/components/action/printer.dm b/code/modules/wiremod/components/action/printer.dm index e6052d2a5cf..4ef07c1d253 100644 --- a/code/modules/wiremod/components/action/printer.dm +++ b/code/modules/wiremod/components/action/printer.dm @@ -7,6 +7,7 @@ display_name = "Printer" desc = "A component that prints a string input on a paper. Requires a shell and paper. \ Attack with paper to load them in the circuit. Use in hand to dump the bottom-most paper." + category = "Action" circuit_flags = CIRCUIT_FLAG_REFUSE_MODULE /// Prints stuff on the leftmost paper in the loaded_papers list. diff --git a/code/modules/wiremod/components/action/pull.dm b/code/modules/wiremod/components/action/pull.dm index 9e59f63e1cd..9b6f2e3e7f4 100644 --- a/code/modules/wiremod/components/action/pull.dm +++ b/code/modules/wiremod/components/action/pull.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/pull display_name = "Start Pulling" desc = "A component that can force the shell to pull entities. Only works for drone shells." + category = "Action" /// Frequency input var/datum/port/input/target diff --git a/code/modules/wiremod/components/action/radio.dm b/code/modules/wiremod/components/action/radio.dm index 4c693277951..76c81b3d38b 100644 --- a/code/modules/wiremod/components/action/radio.dm +++ b/code/modules/wiremod/components/action/radio.dm @@ -9,6 +9,7 @@ /obj/item/circuit_component/radio display_name = "Radio" desc = "A component that can listen and send frequencies. If set to private, the component will only receive signals from other components attached to circuitboards with the same owner id." + category = "Action" /// The publicity options. Controls whether it's public or private. var/datum/port/input/option/public_options diff --git a/code/modules/wiremod/components/action/soundemitter.dm b/code/modules/wiremod/components/action/soundemitter.dm index c586d7777e3..c7dc3e194c2 100644 --- a/code/modules/wiremod/components/action/soundemitter.dm +++ b/code/modules/wiremod/components/action/soundemitter.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/soundemitter display_name = "Sound Emitter" desc = "A component that emits a sound when it receives an input. The frequency is a multiplier which determines the speed at which the sound is played" + category = "Action" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL /// Sound to play diff --git a/code/modules/wiremod/components/action/speech.dm b/code/modules/wiremod/components/action/speech.dm index 7a307527a25..315ba450273 100644 --- a/code/modules/wiremod/components/action/speech.dm +++ b/code/modules/wiremod/components/action/speech.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/speech display_name = "Speech" desc = "A component that sends a message. Requires a shell." + category = "Action" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL /// The message to send diff --git a/code/modules/wiremod/components/admin/animate.dm b/code/modules/wiremod/components/admin/animate.dm index 921cc8ff6de..825eba83b77 100644 --- a/code/modules/wiremod/components/admin/animate.dm +++ b/code/modules/wiremod/components/admin/animate.dm @@ -4,6 +4,7 @@ /obj/item/circuit_component/begin_animation display_name = "Begin Animation" desc = "Begins an animation on the target. Create animation steps by chaining \"Animation Step\" components off of the \"Perform Animation\" port." + category = "Admin" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL|CIRCUIT_FLAG_INSTANT|CIRCUIT_FLAG_ADMIN /// Whether we are animating an atom or a filter on the atom @@ -95,6 +96,7 @@ /obj/item/circuit_component/animation_step display_name = "Animation Step" desc = "Perform a single animation step. The input of this component should be connected, directly or indirectly, to the \"Perform Animation\" port of a \"Begin Animation\" component." + category = "Admin" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL|CIRCUIT_FLAG_ADMIN diff --git a/code/modules/wiremod/components/admin/filter.dm b/code/modules/wiremod/components/admin/filter.dm index 3bab5e7a7d7..4a2ae1113ac 100644 --- a/code/modules/wiremod/components/admin/filter.dm +++ b/code/modules/wiremod/components/admin/filter.dm @@ -144,6 +144,7 @@ GLOBAL_LIST_INIT(wiremod_flag_info, list( /obj/item/circuit_component/filter_helper display_name = "Filter Parameter Helper" desc = "Constructs a list of filter parameters from the inputs." + category = "Admin" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL|CIRCUIT_FLAG_ADMIN var/datum/port/input/option/filter_type_port @@ -187,6 +188,7 @@ GLOBAL_LIST_INIT(wiremod_flag_info, list( /obj/item/circuit_component/filter_adder display_name = "Add Filter" desc = "Adds a filter to the target atom." + category = "Admin" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL|CIRCUIT_FLAG_ADMIN var/datum/port/input/target_port @@ -238,6 +240,7 @@ GLOBAL_LIST_INIT(wiremod_flag_info, list( /obj/item/circuit_component/filter_remover display_name = "Filter Remover" desc = "Removes the specified filter from the target." + category = "Admin" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL|CIRCUIT_FLAG_ADMIN var/datum/port/input/target_port @@ -256,6 +259,7 @@ GLOBAL_LIST_INIT(wiremod_flag_info, list( /obj/item/circuit_component/bitflag_helper display_name = "Animation & Filter Bitflag Helper" + category = "Admin" desc = "Allows you to construct bitflags for BYOND animation and filter parameters without having to manually search for the corresponding values." circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL|CIRCUIT_FLAG_ADMIN diff --git a/code/modules/wiremod/components/admin/getvar.dm b/code/modules/wiremod/components/admin/getvar.dm index c742dbe89ef..87690b79148 100644 --- a/code/modules/wiremod/components/admin/getvar.dm +++ b/code/modules/wiremod/components/admin/getvar.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/get_variable display_name = "Get Variable" desc = "A component that gets a variable on an object." + category = "Admin" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL|CIRCUIT_FLAG_ADMIN /// Whether to grab a global variable or a variable from this entity. diff --git a/code/modules/wiremod/components/admin/input_request.dm b/code/modules/wiremod/components/admin/input_request.dm index e39857cdf17..0b078080550 100644 --- a/code/modules/wiremod/components/admin/input_request.dm +++ b/code/modules/wiremod/components/admin/input_request.dm @@ -10,6 +10,7 @@ /obj/item/circuit_component/input_request display_name = "Input Request" desc = "Converts a string into a typepath. Useful for adding components." + category = "Admin" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_ADMIN /// Options for input requests diff --git a/code/modules/wiremod/components/admin/proccall.dm b/code/modules/wiremod/components/admin/proccall.dm index baa10aa4698..11475ebba67 100644 --- a/code/modules/wiremod/components/admin/proccall.dm +++ b/code/modules/wiremod/components/admin/proccall.dm @@ -10,6 +10,7 @@ /obj/item/circuit_component/proccall display_name = "Proc Call" desc = "A component that calls a proc on an object." + category = "Admin" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL|CIRCUIT_FLAG_ADMIN var/datum/port/input/option/proccall_options diff --git a/code/modules/wiremod/components/admin/save_shell.dm b/code/modules/wiremod/components/admin/save_shell.dm index b60e32e4b83..b940d1b2280 100644 --- a/code/modules/wiremod/components/admin/save_shell.dm +++ b/code/modules/wiremod/components/admin/save_shell.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/save_shell display_name = "Save Shell" desc = "A component that saves a shell." + category = "Admin" circuit_flags = CIRCUIT_FLAG_ADMIN /// Returns the output from the proccall diff --git a/code/modules/wiremod/components/admin/sdql.dm b/code/modules/wiremod/components/admin/sdql.dm index febfa165003..1da54d96926 100644 --- a/code/modules/wiremod/components/admin/sdql.dm +++ b/code/modules/wiremod/components/admin/sdql.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/sdql_operation display_name = "SDQL Operation" desc = "A component that performs an SDQL operation when invoked." + category = "Admin" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL|CIRCUIT_FLAG_ADMIN /// SDQL Operation to invoke diff --git a/code/modules/wiremod/components/admin/setvar.dm b/code/modules/wiremod/components/admin/setvar.dm index 58381e2a240..07a05d4ba27 100644 --- a/code/modules/wiremod/components/admin/setvar.dm +++ b/code/modules/wiremod/components/admin/setvar.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/set_variable display_name = "Set Variable" desc = "A component that sets a variable on an object." + category = "Admin" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL|CIRCUIT_FLAG_ADMIN /// Entity to set variable of diff --git a/code/modules/wiremod/components/admin/signal_handler/signal_handler.dm b/code/modules/wiremod/components/admin/signal_handler/signal_handler.dm index 3ba404ca6ac..4d374b5c2b8 100644 --- a/code/modules/wiremod/components/admin/signal_handler/signal_handler.dm +++ b/code/modules/wiremod/components/admin/signal_handler/signal_handler.dm @@ -9,6 +9,7 @@ /obj/item/circuit_component/signal_handler display_name = "Signal Handler" desc = "A component that listens for signals on an object." + category = "Admin" circuit_flags = CIRCUIT_FLAG_ADMIN|CIRCUIT_FLAG_INSTANT /// Whether it is a global or object signal diff --git a/code/modules/wiremod/components/admin/spawn.dm b/code/modules/wiremod/components/admin/spawn.dm index c18f8501b1f..9690b04a8ef 100644 --- a/code/modules/wiremod/components/admin/spawn.dm +++ b/code/modules/wiremod/components/admin/spawn.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/spawn_atom display_name = "Spawn Atom" desc = "Spawns an atom at a desired location" + category = "Admin" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL|CIRCUIT_FLAG_ADMIN /// The input path to convert into a typepath diff --git a/code/modules/wiremod/components/admin/to_type.dm b/code/modules/wiremod/components/admin/to_type.dm index 913588e730f..845ec88b137 100644 --- a/code/modules/wiremod/components/admin/to_type.dm +++ b/code/modules/wiremod/components/admin/to_type.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/to_type display_name = "String To Type" desc = "Converts a string into a typepath. Useful for adding components." + category = "Admin" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL|CIRCUIT_FLAG_ADMIN /// The input path to convert into a typepath diff --git a/code/modules/wiremod/components/atom/direction.dm b/code/modules/wiremod/components/atom/direction.dm index 75e5394982f..67e9b6ff496 100644 --- a/code/modules/wiremod/components/atom/direction.dm +++ b/code/modules/wiremod/components/atom/direction.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/direction display_name = "Get Direction" desc = "A component that returns the direction of itself and an entity." + category = "Entity" /// The input port var/datum/port/input/input_port diff --git a/code/modules/wiremod/components/atom/gps.dm b/code/modules/wiremod/components/atom/gps.dm index 941046a9cb3..c9ede5ef01f 100644 --- a/code/modules/wiremod/components/atom/gps.dm +++ b/code/modules/wiremod/components/atom/gps.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/gps display_name = "Internal GPS" desc = "A component that returns the xyz co-ordinates of itself." + category = "Entity" /// The result from the output var/datum/port/output/x_pos diff --git a/code/modules/wiremod/components/atom/health.dm b/code/modules/wiremod/components/atom/health.dm index 5802d6d8b61..637a032815c 100644 --- a/code/modules/wiremod/components/atom/health.dm +++ b/code/modules/wiremod/components/atom/health.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/health display_name = "Get Health" desc = "A component that returns the health of an organism." + category = "Entity" /// The input port var/datum/port/input/input_port diff --git a/code/modules/wiremod/components/atom/hear.dm b/code/modules/wiremod/components/atom/hear.dm index cc38667c9ce..6832ecca291 100644 --- a/code/modules/wiremod/components/atom/hear.dm +++ b/code/modules/wiremod/components/atom/hear.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/hear display_name = "Voice Activator" desc = "A component that listens for messages. Requires a shell." + category = "Entity" /// The message heard var/datum/port/output/message_port diff --git a/code/modules/wiremod/components/atom/pinpointer.dm b/code/modules/wiremod/components/atom/pinpointer.dm index 57a4f3e327b..0b6e59c5837 100644 --- a/code/modules/wiremod/components/atom/pinpointer.dm +++ b/code/modules/wiremod/components/atom/pinpointer.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/pinpointer display_name = "Proximity Pinpointer" desc = "A component that returns the xyz co-ordinates of its entity input, as long as its in view." + category = "Entity" var/datum/port/input/target diff --git a/code/modules/wiremod/components/atom/self.dm b/code/modules/wiremod/components/atom/self.dm index f6f88a80ae3..4e2693bfa3d 100644 --- a/code/modules/wiremod/components/atom/self.dm +++ b/code/modules/wiremod/components/atom/self.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/self display_name = "Self" desc = "A component that returns the current shell." + category = "Entity" /// The shell this component is attached to. var/datum/port/output/output diff --git a/code/modules/wiremod/components/atom/species.dm b/code/modules/wiremod/components/atom/species.dm index 4160e6bf8b5..24e5a41fd09 100644 --- a/code/modules/wiremod/components/atom/species.dm +++ b/code/modules/wiremod/components/atom/species.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/species display_name = "Get Species" desc = "A component that returns the species of its input." + category = "Entity" /// The input port var/datum/port/input/input_port diff --git a/code/modules/wiremod/components/bci/hud/bar_overlay.dm b/code/modules/wiremod/components/bci/hud/bar_overlay.dm index 4826d33d9b4..cc6add65ea5 100644 --- a/code/modules/wiremod/components/bci/hud/bar_overlay.dm +++ b/code/modules/wiremod/components/bci/hud/bar_overlay.dm @@ -11,6 +11,7 @@ /obj/item/circuit_component/object_overlay/bar display_name = "Bar Overlay" desc = "Requires a BCI shell. A component that shows a bar overlay ontop of an object from a range of 0 to 100." + category = "BCI" var/datum/port/input/option/bar_overlay_options var/datum/port/input/bar_number diff --git a/code/modules/wiremod/components/bci/hud/counter_overlay.dm b/code/modules/wiremod/components/bci/hud/counter_overlay.dm index babd6d8e8f3..973f4f9be01 100644 --- a/code/modules/wiremod/components/bci/hud/counter_overlay.dm +++ b/code/modules/wiremod/components/bci/hud/counter_overlay.dm @@ -8,6 +8,7 @@ /obj/item/circuit_component/counter_overlay display_name = "Counter Overlay" desc = "A component that shows an three digit counter. Requires a BCI shell." + category = "BCI" required_shells = list(/obj/item/organ/cyberimp/bci) diff --git a/code/modules/wiremod/components/bci/hud/object_overlay.dm b/code/modules/wiremod/components/bci/hud/object_overlay.dm index 1023cf72bc8..7822b465869 100644 --- a/code/modules/wiremod/components/bci/hud/object_overlay.dm +++ b/code/modules/wiremod/components/bci/hud/object_overlay.dm @@ -10,6 +10,7 @@ /obj/item/circuit_component/object_overlay display_name = "Object Overlay" desc = "Requires a BCI shell. A component that shows an overlay on top of an object." + category = "BCI" required_shells = list(/obj/item/organ/cyberimp/bci) diff --git a/code/modules/wiremod/components/bci/hud/target_intercept.dm b/code/modules/wiremod/components/bci/hud/target_intercept.dm index b84de0b7c43..fea25a3599b 100644 --- a/code/modules/wiremod/components/bci/hud/target_intercept.dm +++ b/code/modules/wiremod/components/bci/hud/target_intercept.dm @@ -8,6 +8,7 @@ /obj/item/circuit_component/target_intercept display_name = "Target Intercept" desc = "Requires a BCI shell. When activated, this component will allow user to target an object using their brain and will output the reference to said object." + category = "BCI" required_shells = list(/obj/item/organ/cyberimp/bci) diff --git a/code/modules/wiremod/components/list/assoc_literal.dm b/code/modules/wiremod/components/list/assoc_literal.dm index dc92c5cce65..251c1078c60 100644 --- a/code/modules/wiremod/components/list/assoc_literal.dm +++ b/code/modules/wiremod/components/list/assoc_literal.dm @@ -6,6 +6,7 @@ /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." + category = "List" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL /// The inputs used to create the list diff --git a/code/modules/wiremod/components/list/concat.dm b/code/modules/wiremod/components/list/concat.dm index 950fdf8073a..038f2bf95bc 100644 --- a/code/modules/wiremod/components/list/concat.dm +++ b/code/modules/wiremod/components/list/concat.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/concat_list display_name = "Concatenate List" desc = "A component that joins up a list with a separator into a single string." + category = "List" /// The input port var/datum/port/input/list_port diff --git a/code/modules/wiremod/components/list/filter.dm b/code/modules/wiremod/components/list/filter.dm index a59ec5578f8..f7eb4bb56c8 100644 --- a/code/modules/wiremod/components/list/filter.dm +++ b/code/modules/wiremod/components/list/filter.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/filter_list display_name = "Filter" desc = "A component that loops through each element in a list and filters them." + category = "List" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_INSTANT /// The list type diff --git a/code/modules/wiremod/components/list/foreach.dm b/code/modules/wiremod/components/list/foreach.dm index c7536c67ca7..08d0f6e96ec 100644 --- a/code/modules/wiremod/components/list/foreach.dm +++ b/code/modules/wiremod/components/list/foreach.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/foreach display_name = "For Each" desc = "A component that loops through each element in a list." + category = "List" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL /// The list type diff --git a/code/modules/wiremod/components/list/get_column.dm b/code/modules/wiremod/components/list/get_column.dm index 38684307021..d549b25b681 100644 --- a/code/modules/wiremod/components/list/get_column.dm +++ b/code/modules/wiremod/components/list/get_column.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/get_column display_name = "Get Column" desc = "Gets the column of a table and returns it as a regular list." + category = "List" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL /// The list to perform the filter on diff --git a/code/modules/wiremod/components/list/index.dm b/code/modules/wiremod/components/list/index.dm index 45b162fcd02..9eda4905907 100644 --- a/code/modules/wiremod/components/list/index.dm +++ b/code/modules/wiremod/components/list/index.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/index display_name = "Index List" desc = "A component that returns the value of a list at a given index." + category = "List" /// The list type var/datum/port/input/option/list_options diff --git a/code/modules/wiremod/components/list/index_table.dm b/code/modules/wiremod/components/list/index_table.dm index 69cc57fe9d2..66d8968b339 100644 --- a/code/modules/wiremod/components/list/index_table.dm +++ b/code/modules/wiremod/components/list/index_table.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/index_table display_name = "Index Table" 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." + category = "List" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL /// The list to perform the filter on diff --git a/code/modules/wiremod/components/list/list_literal.dm b/code/modules/wiremod/components/list/list_literal.dm index 20566fa0668..8810d63b770 100644 --- a/code/modules/wiremod/components/list/list_literal.dm +++ b/code/modules/wiremod/components/list/list_literal.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/list_literal display_name = "List Literal" desc = "A component that creates a list from whatever input you give it." + category = "List" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL /// The list type diff --git a/code/modules/wiremod/components/list/select.dm b/code/modules/wiremod/components/list/select.dm index 0f0bd534945..9b8167e358b 100644 --- a/code/modules/wiremod/components/list/select.dm +++ b/code/modules/wiremod/components/list/select.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/select display_name = "Select Query" 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." + category = "List" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL var/datum/port/input/option/comparison_options diff --git a/code/modules/wiremod/components/list/split.dm b/code/modules/wiremod/components/list/split.dm index 994fcd7cfb7..c15e9b272a1 100644 --- a/code/modules/wiremod/components/list/split.dm +++ b/code/modules/wiremod/components/list/split.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/split display_name = "Split" desc = "Splits a string by the separator, turning it into a list" + category = "List" /// The input port var/datum/port/input/input_port diff --git a/code/modules/wiremod/components/math/arithmetic.dm b/code/modules/wiremod/components/math/arithmetic.dm index ab742af33cb..621e2a14a38 100644 --- a/code/modules/wiremod/components/math/arithmetic.dm +++ b/code/modules/wiremod/components/math/arithmetic.dm @@ -14,6 +14,7 @@ /obj/item/circuit_component/arithmetic display_name = "Arithmetic" desc = "General arithmetic component with arithmetic capabilities." + category = "Math" /// The amount of input ports to have var/input_port_amount = 4 diff --git a/code/modules/wiremod/components/math/binary_conversion.dm b/code/modules/wiremod/components/math/binary_conversion.dm index e991499df60..d4c142bdde3 100644 --- a/code/modules/wiremod/components/math/binary_conversion.dm +++ b/code/modules/wiremod/components/math/binary_conversion.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/binary_decimal/binary_conversion display_name = "Binary Conversion" desc = "Splits a decimal number into an array of binary digits, or bits, represented as 1 or 0 and often used in boolean or binary operations like AND, OR and XOR." + category = "Math" /obj/item/circuit_component/binary_decimal/binary_conversion/populate_ports() . = ..() diff --git a/code/modules/wiremod/components/math/comparison.dm b/code/modules/wiremod/components/math/comparison.dm index 4ae23452858..10efc6c6b76 100644 --- a/code/modules/wiremod/components/math/comparison.dm +++ b/code/modules/wiremod/components/math/comparison.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/compare/comparison display_name = "Comparison" desc = "A component that compares two objects." + category = "Math" var/datum/port/input/option/comparison_option diff --git a/code/modules/wiremod/components/math/decimal_conversion.dm b/code/modules/wiremod/components/math/decimal_conversion.dm index 6e35d66e105..520747b70aa 100644 --- a/code/modules/wiremod/components/math/decimal_conversion.dm +++ b/code/modules/wiremod/components/math/decimal_conversion.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/binary_decimal/decimal_conversion display_name = "Decimal Conversion" desc = "Merges an array of binary digits, or bits, represented as 1 or 0 and often used in boolean or binary operations, into a decimal number." + category = "Math" /obj/item/circuit_component/binary_decimal/decimal_conversion/populate_ports() . = ..() diff --git a/code/modules/wiremod/components/math/length.dm b/code/modules/wiremod/components/math/length.dm index 019e040358a..2ccee90f7c4 100644 --- a/code/modules/wiremod/components/math/length.dm +++ b/code/modules/wiremod/components/math/length.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/length display_name = "Length" desc = "A component that returns the length of its input." + category = "Math" /// The input port var/datum/port/input/input_port diff --git a/code/modules/wiremod/components/math/logic.dm b/code/modules/wiremod/components/math/logic.dm index 9f632a92421..4a758f7b314 100644 --- a/code/modules/wiremod/components/math/logic.dm +++ b/code/modules/wiremod/components/math/logic.dm @@ -10,6 +10,7 @@ /obj/item/circuit_component/compare/logic display_name = "Logic" desc = "A component with 'and' and 'or' capabilities." + category = "Math" var/datum/port/input/option/logic_options diff --git a/code/modules/wiremod/components/math/not.dm b/code/modules/wiremod/components/math/not.dm index 92862fba423..f530c9edefc 100644 --- a/code/modules/wiremod/components/math/not.dm +++ b/code/modules/wiremod/components/math/not.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/not display_name = "Not" desc = "A component that inverts its input." + category = "Math" /// The input port var/datum/port/input/input_port diff --git a/code/modules/wiremod/components/math/random.dm b/code/modules/wiremod/components/math/random.dm index 9838e6d41b6..64ed9686126 100644 --- a/code/modules/wiremod/components/math/random.dm +++ b/code/modules/wiremod/components/math/random.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/random display_name = "Random" desc = "A component that returns random values." + category = "Math" /// The minimum value that the random number can be var/datum/port/input/minimum diff --git a/code/modules/wiremod/components/math/trigonometry.dm b/code/modules/wiremod/components/math/trigonometry.dm index d27978f22f6..735045844c3 100644 --- a/code/modules/wiremod/components/math/trigonometry.dm +++ b/code/modules/wiremod/components/math/trigonometry.dm @@ -15,6 +15,7 @@ /obj/item/circuit_component/trigonometry display_name = "Trigonometry" desc = "General trigonometry component with main and inverse trigonometry functions." + category = "Math" var/datum/port/input/option/trigonometric_function diff --git a/code/modules/wiremod/components/ntnet/ntnet_receive.dm b/code/modules/wiremod/components/ntnet/ntnet_receive.dm index a2a67d5d563..dae0c668682 100644 --- a/code/modules/wiremod/components/ntnet/ntnet_receive.dm +++ b/code/modules/wiremod/components/ntnet/ntnet_receive.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/ntnet_receive display_name = "NTNet Receiver" desc = "Receives data packages through NTNet. If Encryption Key is set then only signals with the same Encryption Key will be received." + category = "NTNet" circuit_flags = CIRCUIT_FLAG_OUTPUT_SIGNAL //trigger_output diff --git a/code/modules/wiremod/components/ntnet/ntnet_send.dm b/code/modules/wiremod/components/ntnet/ntnet_send.dm index 64a1b1e089a..f5f544c767f 100644 --- a/code/modules/wiremod/components/ntnet/ntnet_send.dm +++ b/code/modules/wiremod/components/ntnet/ntnet_send.dm @@ -7,6 +7,7 @@ /obj/item/circuit_component/ntnet_send display_name = "NTNet Transmitter" desc = "Sends a data package through NTNet. If Encryption Key is set then transmitted data will be only picked up by receivers with the same Encryption Key." + category = "NTNet" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL diff --git a/code/modules/wiremod/components/sensors/pressuresensor.dm b/code/modules/wiremod/components/sensors/pressuresensor.dm index 615f0b2bade..3914f4460fb 100644 --- a/code/modules/wiremod/components/sensors/pressuresensor.dm +++ b/code/modules/wiremod/components/sensors/pressuresensor.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/pressuresensor display_name = "Pressure Sensor" desc = "Outputs the current pressure of the tile" + category = "Sensor" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL diff --git a/code/modules/wiremod/components/sensors/tempsensor.dm b/code/modules/wiremod/components/sensors/tempsensor.dm index 9de9a7b6adf..0c7fd03321b 100644 --- a/code/modules/wiremod/components/sensors/tempsensor.dm +++ b/code/modules/wiremod/components/sensors/tempsensor.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/tempsensor display_name = "Temperature Sensor" desc = "Outputs the current temperature of the tile" + category = "Sensor" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL diff --git a/code/modules/wiremod/components/string/concat.dm b/code/modules/wiremod/components/string/concat.dm index 8b7db5fbf15..1b0a977233e 100644 --- a/code/modules/wiremod/components/string/concat.dm +++ b/code/modules/wiremod/components/string/concat.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/concat display_name = "Concatenate" desc = "A component that combines strings." + category = "String" /// The amount of input ports to have var/input_port_amount = 4 diff --git a/code/modules/wiremod/components/string/contains.dm b/code/modules/wiremod/components/string/contains.dm index ea08db73c4d..69f6d0602f1 100644 --- a/code/modules/wiremod/components/string/contains.dm +++ b/code/modules/wiremod/components/string/contains.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/compare/contains display_name = "String Contains" desc = "Checks if a string contains a word/letter" + category = "String" input_port_amount = 0 diff --git a/code/modules/wiremod/components/string/textcase.dm b/code/modules/wiremod/components/string/textcase.dm index 14434c08bab..ac289654236 100644 --- a/code/modules/wiremod/components/string/textcase.dm +++ b/code/modules/wiremod/components/string/textcase.dm @@ -9,6 +9,7 @@ /obj/item/circuit_component/textcase display_name = "Text Case" desc = "A component that makes its input uppercase or lowercase." + category = "String" var/datum/port/input/option/textcase_options diff --git a/code/modules/wiremod/components/string/tonumber.dm b/code/modules/wiremod/components/string/tonumber.dm index 4a27aec001a..4ff0900fc48 100644 --- a/code/modules/wiremod/components/string/tonumber.dm +++ b/code/modules/wiremod/components/string/tonumber.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/tonumber display_name = "To Number" desc = "A component that converts its input (a string) to a number. If there's text in the input, it'll only consider it if it starts with a number. It will take that number and ignore the rest." + category = "String" /// The input port var/datum/port/input/input_port diff --git a/code/modules/wiremod/components/string/tostring.dm b/code/modules/wiremod/components/string/tostring.dm index 0cc96a3aeb4..9847fca1cf0 100644 --- a/code/modules/wiremod/components/string/tostring.dm +++ b/code/modules/wiremod/components/string/tostring.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/tostring display_name = "To String" desc = "A component that converts its input to text." + category = "String" /// The input port var/datum/port/input/input_port diff --git a/code/modules/wiremod/components/utility/clock.dm b/code/modules/wiremod/components/utility/clock.dm index a876f09d043..af11c4a00dc 100644 --- a/code/modules/wiremod/components/utility/clock.dm +++ b/code/modules/wiremod/components/utility/clock.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/clock display_name = "Clock" desc = "A component that repeatedly fires." + category = "Utility" /// Whether the clock is on or not var/datum/port/input/on diff --git a/code/modules/wiremod/components/utility/delay.dm b/code/modules/wiremod/components/utility/delay.dm index 05e0c75ca0b..5db2f327365 100644 --- a/code/modules/wiremod/components/utility/delay.dm +++ b/code/modules/wiremod/components/utility/delay.dm @@ -9,6 +9,7 @@ /obj/item/circuit_component/delay display_name = "Delay" desc = "A component that delays a signal by a specified duration. Timer gets reset when triggered again." + category = "Utility" /// Amount to delay by var/datum/port/input/delay_amount diff --git a/code/modules/wiremod/components/utility/router.dm b/code/modules/wiremod/components/utility/router.dm index ddfd1b45a0f..c942853f982 100644 --- a/code/modules/wiremod/components/utility/router.dm +++ b/code/modules/wiremod/components/utility/router.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/router display_name = "Router" desc = "Copies the input chosen by \"Input Selector\" to the output chosen by \"Output Selector\"." + category = "Utility" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL var/datum/port/input/option/router_options diff --git a/code/modules/wiremod/components/utility/timepiece.dm b/code/modules/wiremod/components/utility/timepiece.dm index 6bc89faff0d..fa675bfa1b9 100644 --- a/code/modules/wiremod/components/utility/timepiece.dm +++ b/code/modules/wiremod/components/utility/timepiece.dm @@ -12,6 +12,7 @@ /obj/item/circuit_component/timepiece display_name = "Timepiece" desc = "A component that outputs the current station time. The text output port is used for time formats while the numerical output port is used for units of time." + category = "Utility" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL /// The time format of the text output diff --git a/code/modules/wiremod/components/utility/typecast.dm b/code/modules/wiremod/components/utility/typecast.dm index ac9b1ce3813..9dac9efe98a 100644 --- a/code/modules/wiremod/components/utility/typecast.dm +++ b/code/modules/wiremod/components/utility/typecast.dm @@ -6,6 +6,7 @@ /obj/item/circuit_component/typecast display_name = "Typecast" desc = "A component that casts a value to a type if it matches or outputs null." + category = "Utility" circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL var/datum/port/input/option/typecast_options diff --git a/code/modules/wiremod/components/utility/typecheck.dm b/code/modules/wiremod/components/utility/typecheck.dm index f27360ccc5e..fbd1692cacf 100644 --- a/code/modules/wiremod/components/utility/typecheck.dm +++ b/code/modules/wiremod/components/utility/typecheck.dm @@ -9,6 +9,7 @@ /obj/item/circuit_component/compare/typecheck display_name = "Typecheck" desc = "A component that checks the type of its input." + category = "Utility" input_port_amount = 1 var/datum/port/input/option/typecheck_options diff --git a/code/modules/wiremod/core/assets.dm b/code/modules/wiremod/core/assets.dm new file mode 100644 index 00000000000..d77c571f317 --- /dev/null +++ b/code/modules/wiremod/core/assets.dm @@ -0,0 +1,40 @@ +/datum/asset/json/circuit_components + name = "circuit_components" + +/datum/asset/json/circuit_components/generate() + var/list/circuit_data = list() + + for (var/component_type in subtypesof(/obj/item/circuit_component)) + var/obj/item/circuit_component/circuit_info = new component_type() + var/list/component_data = list() + + var/list/input_info = list() + for(var/datum/port/input/port as anything in circuit_info.input_ports) + input_info += list(list( + "name" = port.name, + "type" = port.datatype, + "color" = port.color, + "datatype_data" = port.datatype_ui_data(), + )) + var/list/output_info = list() + for(var/datum/port/output/port as anything in circuit_info.output_ports) + output_info += list(list( + "name" = port.name, + "type" = port.datatype, + "color" = port.color, + "datatype_data" = port.datatype_ui_data(), + )) + + component_data["name"] = circuit_info.display_name + component_data["description"] = circuit_info.desc + component_data["category"] = circuit_info.category + component_data["color"] = circuit_info.ui_color + component_data["type"] = component_type + + component_data["input_ports"] = input_info + component_data["output_ports"] = output_info + + circuit_data += list(component_data) + qdel(circuit_info) + + return circuit_data diff --git a/code/modules/wiremod/core/component.dm b/code/modules/wiremod/core/component.dm index 357858be7a7..76d8e75936c 100644 --- a/code/modules/wiremod/core/component.dm +++ b/code/modules/wiremod/core/component.dm @@ -16,6 +16,9 @@ /// The name of the component shown on the UI var/display_name = "Generic" + /// The category of the component in the UI + var/category = COMPONENT_DEFAULT_CATEGORY + /// The colour this circuit component appears in the UI var/ui_color = "blue" diff --git a/code/modules/wiremod/core/component_printer.dm b/code/modules/wiremod/core/component_printer.dm index 948ea080e73..0369dc309a5 100644 --- a/code/modules/wiremod/core/component_printer.dm +++ b/code/modules/wiremod/core/component_printer.dm @@ -14,11 +14,24 @@ /// The techweb the printer will get researched designs from var/datum/techweb/techweb + /// The current unlocked circuit component designs. Used by integrated circuits to print off circuit components remotely. + var/list/current_unlocked_designs = list() + /obj/machinery/component_printer/Initialize(mapload) . = ..() techweb = SSresearch.science_tech + for (var/researched_design_id in techweb.researched_designs) + var/datum/design/design = SSresearch.techweb_design_by_id(researched_design_id) + if (!(design.build_type & COMPONENT_PRINTER) || !ispath(design.build_path, /obj/item/circuit_component)) + continue + + current_unlocked_designs[design.build_path] = design.id + + RegisterSignal(techweb, COMSIG_TECHWEB_ADD_DESIGN, .proc/on_research) + RegisterSignal(techweb, COMSIG_TECHWEB_REMOVE_DESIGN, .proc/on_removed) + materials = AddComponent( \ /datum/component/remote_materials, \ "component_printer", \ @@ -26,6 +39,19 @@ mat_container_flags = BREAKDOWN_FLAGS_LATHE, \ ) +/obj/machinery/component_printer/proc/on_research(datum/source, datum/design/added_design, custom) + SIGNAL_HANDLER + if (!(added_design.build_type & COMPONENT_PRINTER) || !ispath(added_design.build_path, /obj/item/circuit_component)) + return + current_unlocked_designs[added_design.build_path] = added_design.id + +/obj/machinery/component_printer/proc/on_removed(datum/source, datum/design/added_design, custom) + SIGNAL_HANDLER + if (!(added_design.build_type & COMPONENT_PRINTER) || !ispath(added_design.build_path, /obj/item/circuit_component)) + return + current_unlocked_designs -= added_design.build_path + + /obj/machinery/component_printer/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) @@ -37,6 +63,23 @@ get_asset_datum(/datum/asset/spritesheet/sheetmaterials) ) +/obj/machinery/component_printer/proc/print_component(typepath) + var/design_id = current_unlocked_designs[typepath] + + var/datum/design/design = SSresearch.techweb_design_by_id(design_id) + if (!(design.build_type & COMPONENT_PRINTER)) + return + + if (materials.on_hold()) + return + + if (!materials.mat_container?.has_materials(design.materials)) + return + + materials.mat_container.use_materials(design.materials) + materials.silo_log(src, "printed", -1, design.name, design.materials) + return new design.build_path(drop_location()) + /obj/machinery/component_printer/ui_act(action, list/params) . = ..() if (.) @@ -105,6 +148,14 @@ return data +/obj/machinery/component_printer/attackby(obj/item/weapon, mob/living/user, params) + if(istype(weapon, /obj/item/integrated_circuit) && !user.combat_mode) + var/obj/item/integrated_circuit/circuit = weapon + circuit.linked_component_printer = WEAKREF(src) + balloon_alert(user, "successfully linked to the integrated circuit") + return + return ..() + /obj/machinery/component_printer/crowbar_act(mob/living/user, obj/item/tool) if(..()) return TRUE diff --git a/code/modules/wiremod/core/integrated_circuit.dm b/code/modules/wiremod/core/integrated_circuit.dm index 85026b42bf7..0859c80242b 100644 --- a/code/modules/wiremod/core/integrated_circuit.dm +++ b/code/modules/wiremod/core/integrated_circuit.dm @@ -72,6 +72,9 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit) /// The current size of the circuit. var/current_size = 0 + /// The current linked component printer. Lets you remotely print off circuit components and places them in the integrated circuit. + var/datum/weakref/linked_component_printer + /obj/item/integrated_circuit/Initialize(mapload) . = ..() @@ -272,7 +275,8 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit) /obj/item/integrated_circuit/ui_assets(mob/user) return list( - get_asset_datum(/datum/asset/simple/circuit_assets) + get_asset_datum(/datum/asset/simple/circuit_assets), + get_asset_datum(/datum/asset/json/circuit_components) ) /obj/item/integrated_circuit/ui_static_data(mob/user) @@ -281,6 +285,11 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit) .["screen_x"] = screen_x .["screen_y"] = screen_y + var/obj/machinery/component_printer/printer = linked_component_printer?.resolve() + if(!printer) + return + .["stored_designs"] = printer.current_unlocked_designs + /obj/item/integrated_circuit/ui_data(mob/user) . = list() .["components"] = list() @@ -592,7 +601,28 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit) return var/obj/item/circuit_component/component = attached_components[component_id] component.ui_perform_action(ui.user, params["action_name"]) - + if("print_component") + var/component_path = text2path(params["component_to_print"]) + var/obj/item/circuit_component/component + if(!check_rights_for(ui.user.client, R_SPAWN)) + var/obj/machinery/component_printer/printer = linked_component_printer?.resolve() + if(!printer) + balloon_alert(ui.user, "linked printer not found!") + return + component = printer.print_component(component_path) + if(!component) + balloon_alert(ui.user, "failed to make the component!") + return + else + if(!ispath(component_path, /obj/item/circuit_component)) + return + component = new component_path(drop_location()) + component.datum_flags |= DF_VAR_EDITED + if(!add_component(component)) + return + component.rel_x = text2num(params["rel_x"]) + component.rel_y = text2num(params["rel_y"]) + return TRUE #undef WITHIN_RANGE diff --git a/code/modules/wiremod/core/port.dm b/code/modules/wiremod/core/port.dm index b0facee8fdd..4604ca77bbc 100644 --- a/code/modules/wiremod/core/port.dm +++ b/code/modules/wiremod/core/port.dm @@ -109,7 +109,7 @@ /** * Returns the data from the datatype */ -/datum/port/proc/datatype_ui_data() +/datum/port/proc/datatype_ui_data(mob/user) return datatype_handler.datatype_ui_data(src) /** diff --git a/tgstation.dme b/tgstation.dme index f29c2ace7e9..f0a269bee14 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3935,6 +3935,7 @@ #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\assets.dm" #include "code\modules\wiremod\core\component.dm" #include "code\modules\wiremod\core\component_printer.dm" #include "code\modules\wiremod\core\datatypes.dm" diff --git a/tgui/packages/tgui/interfaces/IntegratedCircuit/ComponentMenu.js b/tgui/packages/tgui/interfaces/IntegratedCircuit/ComponentMenu.js new file mode 100644 index 00000000000..8dd554d8eb3 --- /dev/null +++ b/tgui/packages/tgui/interfaces/IntegratedCircuit/ComponentMenu.js @@ -0,0 +1,225 @@ +import { + Section, + Button, + Dropdown, + Stack, + Box, + Input, +} from '../../components'; +import { Component } from 'inferno'; +import { shallowDiffers } from 'common/react'; +import { fetchRetry } from "../../http"; +import { resolveAsset } from '../../assets'; +import { Port } from './Port'; +import { DEFAULT_COMPONENT_MENU_LIMIT, noop } from './constants'; + +// Cache response so it's only sent once +let fetchServerData; + +export class ComponentMenu extends Component { + constructor() { + super(); + this.state = { + selectedTab: "All", + currentLimit: DEFAULT_COMPONENT_MENU_LIMIT, + currentSearch: "", + }; + } + + componentDidMount() { + this.populateServerData(); + } + + async populateServerData() { + if (!fetchServerData) { + fetchServerData = fetchRetry(resolveAsset("circuit_components.json")) + .then(response => response.json()); + } + + const circuitData = await fetchServerData; + + this.setState({ + componentData: circuitData.sort((a, b) => + a.name.toLowerCase() < b.name.toLowerCase()), + }); + } + + shouldComponentUpdate(nextProps, nextState) { + if (shallowDiffers(this.state, nextState)) { + return true; + } + if (shallowDiffers(this.props.components, nextProps.components)) { + return true; + } + return false; + } + + render() { + const { + components = [], + showAll = false, + onMouseDownComponent, + onClose, + ...rest + } = this.props; + const { + selectedTab, + componentData = [], + currentLimit, + currentSearch, + } = this.state; + + const tabs = ["All"]; + let shownComponents = componentData.filter(val => { + let shouldShow = showAll || components.includes(val.type); + if (shouldShow) { + if (!tabs.includes(val.category)) { + tabs.push(val.category); + } + if (currentSearch !== "") { + const result + = val.name.toLowerCase().search(currentSearch.toLowerCase()); + return result !== -1; + } + return selectedTab === "All" || selectedTab === val.category; + } + return false; + }); + + const trueLength = shownComponents.length; + + // Limit the maximum amount of shown components to prevent a lagspike + // when you open the menu + shownComponents.length = currentLimit; + + return ( +
+ } + onMouseUp={(event) => { + event.preventDefault(); + }} + scrollable + > + + + this.setState({ + selectedTab: value, + currentSearch: "", + currentLimit: DEFAULT_COMPONENT_MENU_LIMIT, + })} + displayText={`Category: ${selectedTab}`} + color="transparent" + className="IntegratedCircuit__BlueBorder" + /> + + + this.setState({ + currentSearch: val, + selectedTab: "All", + currentLimit: DEFAULT_COMPONENT_MENU_LIMIT, + })} + /> + + + + {shownComponents.map(val => ( + onMouseDownComponent(e, val)} + > + + + + {val.name} + + +
+ ); + } +} diff --git a/tgui/packages/tgui/interfaces/IntegratedCircuit/DisplayName.js b/tgui/packages/tgui/interfaces/IntegratedCircuit/DisplayName.js index b7842eb50af..c3db5e75573 100644 --- a/tgui/packages/tgui/interfaces/IntegratedCircuit/DisplayName.js +++ b/tgui/packages/tgui/interfaces/IntegratedCircuit/DisplayName.js @@ -1,16 +1,15 @@ -import { useBackend } from '../../backend'; import { Box, Button, Flex } from '../../components'; import { FUNDAMENTAL_DATA_TYPES, DATATYPE_DISPLAY_HANDLERS } from './FundamentalTypes'; export const DisplayName = (props, context) => { - const { act } = useBackend(context); - const { port, isOutput, componentId, portIndex, ...rest } = props; + const { port, isOutput, componentId, portIndex, act, ...rest } = props; const InputComponent = FUNDAMENTAL_DATA_TYPES[port.type || 'unknown']; const TypeDisplayHandler = DATATYPE_DISPLAY_HANDLERS[port.type || 'unknown']; const hasInput = !isOutput && !port.connected_to?.length + && (componentId || port.type === "option") && InputComponent; const displayType = TypeDisplayHandler? TypeDisplayHandler(port) : port.type; diff --git a/tgui/packages/tgui/interfaces/IntegratedCircuit/FundamentalTypes.js b/tgui/packages/tgui/interfaces/IntegratedCircuit/FundamentalTypes.js index 0f433d552c2..2a421610435 100644 --- a/tgui/packages/tgui/interfaces/IntegratedCircuit/FundamentalTypes.js +++ b/tgui/packages/tgui/interfaces/IntegratedCircuit/FundamentalTypes.js @@ -69,8 +69,12 @@ export const FUNDAMENTAL_DATA_TYPES = { ); }, 'option': (props, context) => { - const { value, setValue, extraData } = props; + const { + value, + setValue, + } = props; let large = false; + const extraData = props.extraData || []; const data = Array.isArray(extraData) ? extraData : Object.keys(extraData); @@ -83,7 +87,7 @@ export const FUNDAMENTAL_DATA_TYPES = { return ( _ } = this.props; if (dragPos) { act('set_component_coordinates', { component_id: index, @@ -98,14 +96,14 @@ export class ObjectComponent extends Component { removable, ui_buttons, locations, - onPortUpdated, - onPortLoaded, - onPortMouseDown, - onPortRightClick, - onPortMouseUp, + onPortUpdated = noop, + onPortLoaded = noop, + onPortMouseDown = noop, + onPortRightClick = noop, + onPortMouseUp = noop, + act = noop, ...rest } = this.props; - const { act } = useBackend(this.context); const { startPos, dragPos } = this.state; let [x_pos, y_pos] = [x, y]; @@ -125,13 +123,14 @@ export class ObjectComponent extends Component { return ( + onComponentWillUnmount={this.handleDrag} + {...rest} + > @@ -201,6 +201,7 @@ export class ObjectComponent extends Component { {output_ports.map((port, portIndex) => ( {}; diff --git a/tgui/packages/tgui/interfaces/IntegratedCircuit/index.js b/tgui/packages/tgui/interfaces/IntegratedCircuit/index.js index 4b1591dc2e3..cc4c2c6a6c7 100644 --- a/tgui/packages/tgui/interfaces/IntegratedCircuit/index.js +++ b/tgui/packages/tgui/interfaces/IntegratedCircuit/index.js @@ -14,6 +14,7 @@ import { ABSOLUTE_Y_OFFSET, MOUSE_BUTTON_LEFT, TIME_UNTIL_PORT_RELEASE_WORKS } f import { Connections } from './Connections'; import { ObjectComponent } from './ObjectComponent'; import { VariableMenu } from './VariableMenu'; +import { ComponentMenu } from './ComponentMenu'; export class IntegratedCircuit extends Component { constructor() { @@ -26,7 +27,8 @@ export class IntegratedCircuit extends Component { zoom: 1, backgroundX: 0, backgroundY: 0, - menuOpen: false, + variableMenuOpen: false, + componentMenuOpen: false, }; this.handlePortLocation = this.handlePortLocation.bind(this); this.handleMouseDown = this.handleMouseDown.bind(this); @@ -43,6 +45,9 @@ export class IntegratedCircuit extends Component { this.onVarClickedSetter = this.onVarClickedSetter.bind(this); this.onVarClickedGetter = this.onVarClickedGetter.bind(this); this.handleVarDropped = this.handleVarDropped.bind(this); + + this.handleMouseDownComponent = this.handleMouseDownComponent.bind(this); + this.handleComponentDropped = this.handleComponentDropped.bind(this); } // Helper function to get an element's exact position @@ -301,6 +306,48 @@ export class IntegratedCircuit extends Component { window.removeEventListener('mouseup', this.handleVarDropped); } + + handleMouseDownComponent(event, component) { + this.setState({ + draggingComponent: component.type, + }); + + window.addEventListener('mouseup', this.handleComponentDropped); + } + + handleComponentDropped(event) { + const { data, act } = useBackend(this.context); + const { + draggingComponent, + backgroundX, + backgroundY, + zoom, + } = this.state; + const { + screen_x, + screen_y, + } = data; + + this.setState({ + draggingComponent: null, + }); + + window.removeEventListener('mouseup', this.handleComponentDropped); + + if (event.defaultPrevented) { + return; + } + + const xPos = (event.clientX - (backgroundX || screen_x)); + const yPos = (event.clientY - (backgroundY || screen_y)); + + act("print_component", { + component_to_print: draggingComponent, + rel_x: xPos*Math.pow(zoom, -1), + rel_y: (yPos + ABSOLUTE_Y_OFFSET)*Math.pow(zoom, -1), + }); + } + render() { const { act, data } = useBackend(this.context); const { @@ -316,8 +363,14 @@ export class IntegratedCircuit extends Component { is_admin, variables, global_basic_types, + stored_designs, } = data; - const { locations, selectedPort, menuOpen } = this.state; + const { + locations, + selectedPort, + variableMenuOpen, + componentMenuOpen, + } = this.state; const connections = []; for (const comp of components) { @@ -367,7 +420,7 @@ export class IntegratedCircuit extends Component { act("set_display_name", { display_name: value })} /> @@ -378,9 +431,21 @@ export class IntegratedCircuit extends Component { top={0} color="transparent" icon="cog" - selected={menuOpen} + selected={variableMenuOpen} onClick={() => this.setState((state) => ({ - menuOpen: !state.menuOpen, + variableMenuOpen: !state.variableMenuOpen, + }))} + /> + + +