Files
Bubberstation/code/modules/wiremod/core/duplicator.dm
SpaceLoveSs13 a9ff046352 Administrator Cherrypick (#27405)
* Admin Verb Datums MkIII | Now with functional command bar (#82511)

* Modular stuffs

* Put some admin jump verbs back into the context menu | sorts area jump list again (#82647)

## About The Pull Request

See title.

## Why It's Good For The Game

Some admins wanted all the jump verbs back, aswell as making them not
AGhost you.
Also make the Jump To Area verb use a sorted list again

* Hey what if admins were allowed to use the player panel (#82682)

Re-adds the player panel verb to the verb panel.

* Controller Overview UI (#82739)

* Fixes a minor spelling mistake on the admin panel/verb list (#82747)

## About The Pull Request

Corrects `inisimin` to `invisimin`. This addresses #82728, but only
fixes one of the two issues mentioned

## Why It's Good For The Game

-1 spelling mistake

## Changelog
🆑
spellcheck: 'inisimin' verb corrected to 'invisimin'
/🆑

* Player Panel-age (#82757)

* Admin Forced Mob Rename and Preference Update (#82715)

---------

Co-authored-by: Zephyr <12817816+ZephyrTFA@users.noreply.github.com>
Co-authored-by: Useroth <37159550+Useroth@users.noreply.github.com>
Co-authored-by: chel <64568243+iliyaxox@users.noreply.github.com>
2024-04-23 20:43:45 +02:00

244 lines
9.5 KiB
Plaintext

#define LOG_ERROR(list, error) if(list) { list.Add(error) }
// Determines if a port can have a predefined input value if it is of this type.
GLOBAL_LIST_INIT(circuit_dupe_whitelisted_types, list(
PORT_TYPE_NUMBER,
PORT_TYPE_STRING,
PORT_TYPE_ANY,
PORT_TYPE_OPTION,
))
/// Loads a circuit based on json data at a location. Can also load usb connections, such as arrest consoles.
/obj/item/integrated_circuit/proc/load_circuit_data(json_data, list/errors)
var/list/general_data = json_decode(json_data)
if(!general_data)
LOG_ERROR(errors, "Invalid json format!")
return
var/list/variable_data = general_data["variables"]
for(var/list/variable as anything in variable_data)
var/variable_name = variable["name"]
var/datum/circuit_variable/variable_datum = new /datum/circuit_variable(variable_name, variable["datatype"])
circuit_variables[variable_name] = variable_datum
if(variable["is_assoc_list"])
assoc_list_variables[variable_name] = variable_datum
variable_datum.set_value(list())
else if(variable["is_list"])
list_variables[variable_name] = variable_datum
variable_datum.set_value(list())
else
modifiable_circuit_variables[variable_name] = variable_datum
admin_only = general_data["admin_only"]
if(general_data["display_name"])
set_display_name(general_data["display_name"])
var/list/circuit_data = general_data["components"]
var/list/identifiers_to_circuit = list()
for(var/identifier in circuit_data)
var/list/component_data = circuit_data[identifier]
var/type = text2path(component_data["type"])
if(!ispath(type, /obj/item/circuit_component))
LOG_ERROR(errors, "Invalid path for circuit component, expected [/obj/item/circuit_component], got [type]")
continue
var/obj/item/circuit_component/component = load_component(type)
identifiers_to_circuit[identifier] = component
component.load_data_from_list(component_data)
SEND_SIGNAL(component, COMSIG_CIRCUIT_COMPONENT_LOAD_DATA, component_data)
var/list/input_ports_data = component_data["input_ports_stored_data"]
for(var/port_name in input_ports_data)
var/datum/port/input/port
var/list/port_data = input_ports_data[port_name]
for(var/datum/port/input/port_to_check as anything in component.input_ports)
if(port_to_check.name == port_name)
port = port_to_check
break
if(!port)
LOG_ERROR(errors, "Port '[port_name]' not found on [component.type] when trying to set it to a value of [port_data["stored_data"]]!")
continue
port.set_input(port_data["stored_data"])
var/list/external_objects = general_data["external_objects"]
for(var/identifier in external_objects)
var/list/object_data = external_objects[identifier]
var/type = text2path(object_data["type"])
if(!ispath(type))
LOG_ERROR(errors, "Invalid path for external object, expected a path, got [type]")
continue
var/atom/movable/object = new type(drop_location())
var/list/connected_components = list()
for(var/component_id in object_data["connected_components"])
var/obj/item/circuit_component/component = identifiers_to_circuit[component_id]
if(!component)
continue
connected_components += component
SEND_SIGNAL(object, COMSIG_MOVABLE_CIRCUIT_LOADED, src, connected_components)
for(var/identifier in identifiers_to_circuit)
var/obj/item/circuit_component/component = identifiers_to_circuit[identifier]
var/list/component_data = circuit_data[identifier]
var/list/connections = component_data["connections"]
for(var/port_name in connections)
var/datum/port/input/port
var/list/connection_data = connections[port_name]
for(var/datum/port/input/port_to_check as anything in component.input_ports)
if(port_to_check.name == port_name)
port = port_to_check
break
if(!port)
LOG_ERROR(errors, "Port [port_name] not found for [component.type].")
continue
if(connection_data["stored_data"])
if(!(port.datatype in GLOB.circuit_dupe_whitelisted_types))
continue
port.set_input(connection_data["stored_data"])
continue
// The || list(connected_data) is for backwards compatibility with when inputs could only be connected to up to one output.
for(var/list/output_data in (connection_data["connected_ports"] || list(connection_data)))
var/obj/item/circuit_component/connected_component = identifiers_to_circuit[output_data["component_id"]]
if(!connected_component)
LOG_ERROR(errors, "No connected component found for [component.type] for port [connection_data["port_name"]]. (connected component identifier: [connection_data["component_id"]])")
continue
var/datum/port/output/output_port
var/output_port_name = output_data["port_name"]
for(var/datum/port/output/port_to_check as anything in connected_component.output_ports)
if(port_to_check.name == output_port_name)
output_port = port_to_check
break
if(!output_port)
LOG_ERROR(errors, "No output port found for [component.type] for port [output_port_name] on component [connected_component.type]")
continue
port.connect(output_port)
SEND_SIGNAL(src, COMSIG_CIRCUIT_POST_LOAD)
#undef LOG_ERROR
/// Converts a circuit into json.
/obj/item/integrated_circuit/proc/convert_to_json()
var/list/circuit_to_identifiers = list()
var/list/identifiers = list()
var/list/external_objects = list() // Objects that are connected to a component. These objects will be linked to the components.
for(var/obj/item/circuit_component/component as anything in attached_components)
var/identifier = "[component.type][length(identifiers)]"
identifiers += identifier
circuit_to_identifiers[component] = identifier
var/list/objects = list()
SEND_SIGNAL(component, COMSIG_CIRCUIT_COMPONENT_SAVE, objects)
for(var/atom/movable/object as anything in objects)
if(object in external_objects)
external_objects[object] += identifier
continue
external_objects[object] = list(identifier)
var/list/circuit_data = list()
for(var/obj/item/circuit_component/component as anything in circuit_to_identifiers)
var/identifier = circuit_to_identifiers[component]
var/list/component_data = list()
component_data["type"] = component.type
var/list/connections = list()
var/list/input_ports_stored_data = list()
for(var/datum/port/input/input as anything in component.input_ports)
var/list/connection_data = list()
if(!length(input.connected_ports))
if(isnull(input.value) || !(input.datatype in GLOB.circuit_dupe_whitelisted_types))
continue
connection_data["stored_data"] = input.value
input_ports_stored_data[input.name] = connection_data
continue
connection_data["connected_ports"] = list()
for(var/datum/port/output/output as anything in input.connected_ports)
connection_data["connected_ports"] += list(list(
"component_id" = circuit_to_identifiers[output.connected_component],
"port_name" = output.name,
))
connections[input.name] = connection_data
component_data["connections"] = connections
component_data["input_ports_stored_data"] = input_ports_stored_data
SEND_SIGNAL(component, COMSIG_CIRCUIT_COMPONENT_SAVE_DATA, component_data)
component.save_data_to_list(component_data)
circuit_data[identifier] = component_data
var/external_objects_key = list()
for(var/atom/movable/object as anything in external_objects)
var/list/new_data = list()
new_data["type"] = object.type
new_data["connected_components"] = external_objects[object]
external_objects_key["[object.type][length(external_objects_key)]"] = new_data
var/list/general_data = list()
general_data["components"] = circuit_data
general_data["external_objects"] = external_objects_key
general_data["display_name"] = display_name
general_data["admin_only"] = admin_only
var/list/variables = list()
for(var/variable_identifier in circuit_variables)
var/list/new_data = list()
var/datum/circuit_variable/variable = circuit_variables[variable_identifier]
new_data["name"] = variable.name
new_data["datatype"] = variable.datatype
if(variable_identifier in assoc_list_variables)
new_data["is_assoc_list"] = TRUE
else if(variable_identifier in list_variables)
new_data["is_list"] = TRUE
variables += list(new_data)
general_data["variables"] = variables
SEND_SIGNAL(src, COMSIG_CIRCUIT_PRE_SAVE_TO_JSON, general_data)
return json_encode(general_data)
/obj/item/integrated_circuit/proc/load_component(type)
var/obj/item/circuit_component/component = new type(src)
add_component(component)
return component
/// Saves data to a list. Shouldn't be used unless you are quite literally saving the data of a component to a list. Input value is the list to save the data to
/obj/item/circuit_component/proc/save_data_to_list(list/component_data)
component_data["rel_x"] = rel_x
component_data["rel_y"] = rel_y
/// Loads data from a list
/obj/item/circuit_component/proc/load_data_from_list(list/component_data)
rel_x = component_data["rel_x"]
rel_y = component_data["rel_y"]
ADMIN_VERB(load_circuit, R_VAREDIT, "Load Circuit", "Loads a circuit from a file or direct input.", ADMIN_CATEGORY_FUN)
var/list/errors = list()
var/option = alert(user, "Load by file or direct input?", "Load by file or string", "File", "Direct Input")
var/txt
switch(option)
if("File")
txt = file2text(input(user, "Input File") as null|file)
if("Direct Input")
txt = input(user, "Input JSON", "Input JSON") as text|null
if(!txt)
return
var/obj/item/integrated_circuit/loaded/circuit = new(user.mob.drop_location())
circuit.load_circuit_data(txt, errors)
if(length(errors))
to_chat(user, span_warning("The following errors were found whilst compiling the circuit data:"))
for(var/error in errors)
to_chat(user, span_warning(error))