Input ports now connect to multiple output ports. Remove combiner. (#60494)

* tgui bsod

* debug disconnections

* prelim

* recomment

* set_value -> put ._.

* DAMN IT

* reinsert subsystem

* prepare

* unditch signals

* remove combiner

* remove combiner some more

* how did router.dm get here? deleting.

* These two COMSIGS should be one.

* critical typo

* inline cast

* have your signals

* Have your set_input & set_output.

* make compile

* upgrade save/load to n-to-n-wires

* have your documentation

* have your unsafe proc

* pay no attention to the compile errors

* unlist the ref

* paste my for block back in ._.

* fix manual input

* oops pushed too soon

* Have your !port.connected_to?.length

Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com>

Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com>
This commit is contained in:
Gurkenglas
2021-08-11 17:48:29 +02:00
committed by GitHub
parent e64b101750
commit e0fad671fd
66 changed files with 280 additions and 386 deletions
+2 -2
View File
@@ -112,10 +112,10 @@
*/
/obj/item/circuit_component/proc/disconnect()
for(var/datum/port/output/port_to_disconnect as anything in output_ports)
port_to_disconnect.disconnect()
port_to_disconnect.disconnect_all()
for(var/datum/port/input/port_to_disconnect as anything in input_ports)
port_to_disconnect.disconnect()
port_to_disconnect.disconnect_all()
/**
* Adds an input port and returns it
@@ -77,7 +77,7 @@
if(!port_to_update)
CRASH("[port.type] doesn't have a linked port in [type]!")
port_to_update.set_output(port.input_value)
port_to_update.set_output(port.value)
/obj/item/circuit_component/module/input_received(datum/port/input/port)
. = ..()
@@ -87,7 +87,7 @@
if(!port_to_update)
CRASH("[port.type] doesn't have a linked port in [type]!")
port_to_update.set_output(port.input_value)
port_to_update.set_output(port.value)
/obj/item/circuit_component/module_output/Destroy()
attached_module = null
@@ -45,11 +45,11 @@
/obj/item/circuit_component/light/input_received(datum/port/input/port)
. = ..()
brightness.set_input(clamp(brightness.input_value || 0, 0, max_power), FALSE)
red.set_input(clamp(red.input_value, 0, 255), FALSE)
blue.set_input(clamp(blue.input_value, 0, 255), FALSE)
green.set_input(clamp(green.input_value, 0, 255), FALSE)
var/list/hsl = rgb2hsl(red.input_value || 0, green.input_value || 0, blue.input_value || 0)
brightness.set_input(clamp(brightness.value || 0, 0, max_power))
red.set_input(clamp(red.value, 0, 255))
blue.set_input(clamp(blue.value, 0, 255))
green.set_input(clamp(green.value, 0, 255))
var/list/hsl = rgb2hsl(red.value || 0, green.value || 0, blue.value || 0)
var/list/light_col = hsl2rgb(hsl[1], hsl[2], max(min_lightness, hsl[3]))
shell_light_color = rgb(light_col[1], light_col[2], light_col[3])
if(.)
@@ -60,9 +60,9 @@
/obj/item/circuit_component/light/proc/set_atom_light(atom/movable/target_atom)
// Clamp anyways just for safety
var/bright_val = min(max(brightness.input_value || 0, 0), max_power)
var/bright_val = min(max(brightness.value || 0, 0), max_power)
target_atom.set_light_power(bright_val)
target_atom.set_light_range(bright_val)
target_atom.set_light_color(shell_light_color)
target_atom.set_light_on(!!on.input_value)
target_atom.set_light_on(!!on.value)
@@ -66,10 +66,10 @@
if(COMPONENT_TRIGGERED_BY(eject, port))
remove_current_brain()
if(COMPONENT_TRIGGERED_BY(send, port))
if(!message.input_value)
if(!message.value)
return
var/msg_str = copytext(html_encode(message.input_value), 1, max_length)
var/msg_str = copytext(html_encode(message.value), 1, max_length)
var/mob/living/target = brain.brainmob
if(!target)
@@ -49,15 +49,15 @@
if(.)
return
var/target_X = input_X.input_value
var/target_X = input_X.value
if(isnull(target_X))
return
var/target_Y = input_Y.input_value
var/target_Y = input_Y.value
if(isnull(target_Y))
return
var/atom/path_id = id_card.input_value
var/atom/path_id = id_card.value
if(path_id && !istype(path_id, /obj/item/card/id))
path_id = null
failed.set_output(COMPONENT_SIGNAL)
@@ -20,7 +20,7 @@
if(.)
return
var/atom/target_atom = target.input_value
var/atom/target_atom = target.value
if(!target_atom)
return
@@ -45,27 +45,27 @@
/obj/item/circuit_component/radio/input_received(datum/port/input/port)
. = ..()
freq.set_input(sanitize_frequency(freq.input_value, TRUE), FALSE)
freq.set_input(sanitize_frequency(freq.value, TRUE))
if(.)
return
var/frequency = freq.input_value
var/frequency = freq.value
SSradio.remove_object(src, current_freq)
radio_connection = SSradio.add_object(src, frequency, RADIO_SIGNALER)
current_freq = frequency
if(COMPONENT_TRIGGERED_BY(trigger_input, port))
var/datum/signal/signal = new(list("code" = round(code.input_value) || 0, "key" = parent?.owner_id))
var/datum/signal/signal = new(list("code" = round(code.value) || 0, "key" = parent?.owner_id))
radio_connection.post_signal(src, signal)
/obj/item/circuit_component/radio/receive_signal(datum/signal/signal)
. = FALSE
if(!signal)
return
if(signal.data["code"] != round(code.input_value || 0))
if(signal.data["code"] != round(code.value || 0))
return
if(public_options.input_value == COMP_RADIO_PRIVATE && parent?.owner_id != signal.data["key"])
if(public_options.value == COMP_RADIO_PRIVATE && parent?.owner_id != signal.data["key"])
return
trigger_output.set_output(COMPONENT_SIGNAL)
@@ -49,18 +49,18 @@
/obj/item/circuit_component/soundemitter/input_received(datum/port/input/port)
. = ..()
volume.set_input(clamp(volume.input_value, 0, 100), FALSE)
frequency.set_input(clamp(frequency.input_value, -100, 100), FALSE)
volume.set_input(clamp(volume.value, 0, 100))
frequency.set_input(clamp(frequency.value, -100, 100))
if(.)
return
if(TIMER_COOLDOWN_CHECK(parent, COOLDOWN_CIRCUIT_SOUNDEMITTER))
return
var/sound_to_play = options_map[sound_file.input_value]
var/sound_to_play = options_map[sound_file.value]
if(!sound_to_play)
return
playsound(src, sound_to_play, volume.input_value, frequency != 0, frequency = frequency.input_value)
playsound(src, sound_to_play, volume.value, frequency != 0, frequency = frequency.value)
TIMER_COOLDOWN_START(parent, COOLDOWN_CIRCUIT_SOUNDEMITTER, sound_cooldown)
@@ -30,11 +30,11 @@
if(TIMER_COOLDOWN_CHECK(parent, COOLDOWN_CIRCUIT_SPEECH))
return
if(message.input_value)
if(message.value)
var/atom/movable/shell = parent.shell
// Prevents appear as the individual component if there is a shell.
if(shell)
shell.say(message.input_value)
shell.say(message.value)
else
say(message.input_value)
say(message.value)
TIMER_COOLDOWN_START(parent, COOLDOWN_CIRCUIT_SPEECH, speech_cooldown)
@@ -29,8 +29,8 @@
. = ..()
if(.)
return
var/atom/object = entity.input_value
var/var_name = variable_name.input_value
var/atom/object = entity.value
var/var_name = variable_name.value
if(!var_name || !object)
output_value.set_output(null)
return
@@ -48,16 +48,16 @@
return
var/called_on
if(proccall_options.input_value == COMP_PROC_OBJECT)
called_on = entity.input_value
if(proccall_options.value == COMP_PROC_OBJECT)
called_on = entity.value
else
called_on = GLOBAL_PROC
if(!called_on)
return
var/to_invoke = proc_name.input_value
var/params = arguments.input_value || list()
var/to_invoke = proc_name.value
var/params = arguments.value || list()
if(!to_invoke)
return
@@ -24,7 +24,7 @@
if(.)
return
var/operation = sdql_operation.input_value
var/operation = sdql_operation.value
if(GLOB.AdminProcCaller || !operation)
return TRUE
@@ -28,9 +28,9 @@
. = ..()
if(.)
return
var/atom/object = entity.input_value
var/var_name = variable_name.input_value
var/atom/object = entity.value
var/var_name = variable_name.value
if(!var_name || !object)
return
object.vv_edit_var(var_name, new_value.input_value)
object.vv_edit_var(var_name, new_value.value)
@@ -33,15 +33,15 @@
if(.)
return
var/typepath = input_path.input_value
var/typepath = input_path.value
if(!ispath(typepath, /atom))
return
var/list/params = parameters.input_value
var/list/params = parameters.value
if(!params)
params = list()
params.Insert(1, spawn_at.input_value)
params.Insert(1, spawn_at.value)
spawned_atom.set_output(new typepath(arglist(params)))
@@ -24,5 +24,5 @@
if(.)
return
type_output.set_output(text2path(input_path.input_value))
type_output.set_output(text2path(input_path.value))
@@ -44,7 +44,7 @@
if(.)
return
var/atom/object = input_port.input_value
var/atom/object = input_port.value
if(!object)
return
var/turf/location = get_turf(src)
@@ -44,7 +44,7 @@
if(.)
return
var/mob/living/organism = input_port.input_value
var/mob/living/organism = input_port.value
var/turf/current_turf = get_turf(src)
if(!istype(organism) || get_dist(current_turf, organism) > max_range || current_turf.z != organism.z)
brute.set_output(null)
@@ -26,7 +26,7 @@
if(.)
return
var/mob/living/carbon/human/human = input_port.input_value
var/mob/living/carbon/human/human = input_port.value
if(!istype(human) || !human.has_dna())
output.set_output(null)
return
@@ -33,23 +33,23 @@
if(LAZYLEN(active_overlays) >= overlay_limit)
return
var/current_option = bar_overlay_options.input_value
var/current_option = bar_overlay_options.value
if(active_overlays[target_atom])
QDEL_NULL(active_overlays[target_atom])
var/number_clear = clamp(bar_number.input_value, 0, 100)
var/number_clear = clamp(bar_number.value, 0, 100)
if(current_option == COMP_BAR_OVERLAY_HORIZONTAL)
number_clear = round(number_clear / 6.25) * 6.25
else if(current_option == COMP_BAR_OVERLAY_VERTICAL)
number_clear = round(number_clear / 10) * 10
var/image/cool_overlay = image(icon = 'icons/hud/screen_bci.dmi', loc = target_atom, icon_state = "[options_map[current_option]][number_clear]", layer = RIPPLE_LAYER)
if(image_pixel_x.input_value)
cool_overlay.pixel_x = image_pixel_x.input_value
if(image_pixel_x.value)
cool_overlay.pixel_x = image_pixel_x.value
if(image_pixel_y.input_value)
cool_overlay.pixel_y = image_pixel_y.input_value
if(image_pixel_y.value)
cool_overlay.pixel_y = image_pixel_y.value
active_overlays[target_atom] = WEAKREF(target_atom.add_alt_appearance(
/datum/atom_hud/alternate_appearance/basic/one_person,
@@ -60,10 +60,10 @@
QDEL_NULL(counter_appearance)
var/image/counter = image(icon = 'icons/hud/screen_bci.dmi', icon_state = "hud_numbers", loc = owner)
if(image_pixel_x.input_value)
counter.pixel_x = image_pixel_x.input_value
if(image_pixel_y.input_value)
counter.pixel_y = image_pixel_y.input_value
if(image_pixel_x.value)
counter.pixel_x = image_pixel_x.value
if(image_pixel_y.value)
counter.pixel_y = image_pixel_y.value
counter_appearance = WEAKREF(owner.add_alt_appearance(
/datum/atom_hud/alternate_appearance/basic/one_person,
@@ -72,16 +72,16 @@
owner,
))
var/cleared_number = clamp(round(counter_number.input_value), 0, 999)
var/cleared_number = clamp(round(counter_number.value), 0, 999)
for(var/i = 1 to 3)
var/cur_num = round(cleared_number / (10 ** (3 - i))) % 10
var/image/number = image(icon = 'icons/hud/screen_bci.dmi', icon_state = "hud_number_[cur_num]", loc = owner)
if(image_pixel_x.input_value)
number.pixel_x = image_pixel_x.input_value + (i - 1) * 9
if(image_pixel_y.input_value)
number.pixel_y = image_pixel_y.input_value
if(image_pixel_x.value)
number.pixel_x = image_pixel_x.value + (i - 1) * 9
if(image_pixel_y.value)
number.pixel_y = image_pixel_y.value
numbers.Add(WEAKREF(owner.add_alt_appearance(
/datum/atom_hud/alternate_appearance/basic/one_person,
@@ -76,7 +76,7 @@
return
var/mob/living/owner = bci.owner
var/atom/target_atom = target.input_value
var/atom/target_atom = target.value
if(!owner || !istype(owner) || !owner.client || !target_atom)
return
@@ -95,13 +95,13 @@
if(active_overlays[target_atom])
QDEL_NULL(active_overlays[target_atom])
var/image/cool_overlay = image(icon = 'icons/hud/screen_bci.dmi', loc = target_atom, icon_state = options_map[object_overlay_options.input_value], layer = RIPPLE_LAYER)
var/image/cool_overlay = image(icon = 'icons/hud/screen_bci.dmi', loc = target_atom, icon_state = options_map[object_overlay_options.value], layer = RIPPLE_LAYER)
if(image_pixel_x.input_value)
cool_overlay.pixel_x = image_pixel_x.input_value
if(image_pixel_x.value)
cool_overlay.pixel_x = image_pixel_x.value
if(image_pixel_y.input_value)
cool_overlay.pixel_y = image_pixel_y.input_value
if(image_pixel_y.value)
cool_overlay.pixel_y = image_pixel_y.value
var/alt_appearance = WEAKREF(target_atom.add_alt_appearance(
/datum/atom_hud/alternate_appearance/basic/one_person,
@@ -29,11 +29,11 @@
if(.)
return
var/seperator = separator.input_value
var/seperator = separator.value
if(!seperator)
return
var/list/list_input = list_port.input_value
var/list/list_input = list_port.value
if(!list_input)
return
@@ -28,13 +28,13 @@
if(.)
return
var/list/input_list = received_table.input_value
if(!islist(input_list) || isnum(column_name.input_value))
var/list/input_list = received_table.value
if(!islist(input_list) || isnum(column_name.value))
return
var/list/new_list = list()
for(var/list/entry in input_list)
var/anything = entry[column_name.input_value]
var/anything = entry[column_name.value]
if(islist(anything))
continue
new_list += anything
@@ -27,8 +27,8 @@
if(.)
return
var/index = index_port.input_value
var/list/list_input = list_port.input_value
var/index = index_port.value
var/list/list_input = list_port.value
if(!islist(list_input) || !index)
output.set_output(null)
@@ -29,12 +29,12 @@
if(.)
return
var/list/target_list = received_table.input_value
var/list/target_list = received_table.value
if(!islist(target_list) || !length(target_list))
output_list.set_output(null)
return
var/index = target_index.input_value
var/index = target_index.value
if(index < 1 || index > length(target_list))
output_list.set_output(null)
return
@@ -80,7 +80,7 @@
var/list/new_literal = list()
for(var/datum/port/input/entry_port as anything in entry_ports)
// Prevents lists from merging together
new_literal += list(entry_port.input_value)
new_literal += list(entry_port.value)
list_output.set_output(new_literal)
@@ -45,7 +45,7 @@
/obj/item/circuit_component/select/input_received(datum/port/input/port)
. = ..()
var/current_option = comparison_options.input_value
var/current_option = comparison_options.value
switch(current_option)
if(COMP_COMPARISON_EQUAL, COMP_COMPARISON_NOT_EQUAL)
@@ -60,14 +60,14 @@
if(.)
return
var/list/input_list = received_table.input_value
if(!islist(input_list) || isnum(column_name.input_value))
var/list/input_list = received_table.value
if(!islist(input_list) || isnum(column_name.value))
return
var/comparison_value = comparison_input.input_value
var/comparison_value = comparison_input.value
var/list/new_list = list()
for(var/list/entry in input_list)
var/anything = entry[column_name.input_value]
var/anything = entry[column_name.value]
if(islist(anything))
continue
if(current_option != COMP_COMPARISON_EQUAL && current_option != COMP_COMPARISON_NOT_EQUAL && !isnum(anything))
@@ -29,11 +29,11 @@
if(.)
return
var/separator_value = separator.input_value
var/separator_value = separator.value
if(isnull(separator_value))
return
var/value = input_port.input_value
var/value = input_port.value
if(isnull(value))
return
@@ -53,14 +53,14 @@
var/list/ports = arithmetic_ports.Copy()
var/datum/port/input/first_port = popleft(ports)
var/result = first_port.input_value
var/result = first_port.value
for(var/datum/port/input/input_port as anything in ports)
var/value = input_port.input_value
var/value = input_port.value
if(isnull(value))
continue
switch(arithmetic_option.input_value)
switch(arithmetic_option.value)
if(COMP_ARITHMETIC_ADD)
result += value
if(COMP_ARITHMETIC_SUBTRACT)
@@ -24,7 +24,7 @@
comparison_option = add_option_port("Comparison Option", component_options)
/obj/item/circuit_component/compare/comparison/input_received(datum/port/input/port)
switch(comparison_option.input_value)
switch(comparison_option.value)
if(COMP_COMPARISON_EQUAL, COMP_COMPARISON_NOT_EQUAL)
if(current_type != PORT_TYPE_ANY)
current_type = PORT_TYPE_ANY
@@ -43,9 +43,9 @@
return FALSE
// Comparison component only compares the first two ports
var/input1 = compare_ports[1].input_value
var/input2 = compare_ports[2].input_value
var/current_option = comparison_option.input_value
var/input1 = compare_ports[1].value
var/input2 = compare_ports[2].value
var/current_option = comparison_option.value
switch(current_option)
if(COMP_COMPARISON_EQUAL)
@@ -25,5 +25,5 @@
if(.)
return
output.set_output(length(input_port.input_value))
output.set_output(length(input_port.value))
@@ -23,26 +23,26 @@
/obj/item/circuit_component/compare/logic/do_comparisons(list/ports)
. = FALSE
var/current_option = logic_options.input_value
var/current_option = logic_options.value
// Used by XOR
var/total_ports = 0
var/total_true_ports = 0
for(var/datum/port/input/port as anything in ports)
if(isnull(port.input_value) && isnull(port.connected_port))
if(isnull(port.value) && length(port.connected_ports) == 0)
continue
total_ports += 1
switch(current_option)
if(COMP_LOGIC_AND)
if(!port.input_value)
if(!port.value)
return FALSE
. = TRUE
if(COMP_LOGIC_OR)
if(port.input_value)
if(port.value)
return TRUE
if(COMP_LOGIC_XOR)
if(port.input_value)
if(port.value)
. = TRUE
total_true_ports += 1
+1 -1
View File
@@ -25,5 +25,5 @@
if(.)
return
result.set_output(!input_port.input_value)
result.set_output(!input_port.value)
@@ -29,8 +29,8 @@
if(.)
return
var/min_val = minimum.input_value || 0
var/max_val = maximum.input_value || 0
var/min_val = minimum.value || 0
var/max_val = maximum.value || 0
if(max_val < min_val)
output.set_output(0)
@@ -32,7 +32,7 @@
ports -= trigger_input
for(var/datum/port/input/input_port as anything in ports)
var/value = input_port.input_value
var/value = input_port.value
if(isnull(value))
continue
@@ -26,8 +26,8 @@
if(length(ports) < input_port_amount)
return
var/to_find = needle.input_value
var/to_search = haystack.input_value
var/to_find = needle.value
var/to_search = haystack.value
if(!to_find || !to_search)
return
@@ -37,12 +37,12 @@
if(.)
return
var/value = input_port.input_value
var/value = input_port.value
if(isnull(value))
return
var/result
switch(textcase_options.input_value)
switch(textcase_options.value)
if(COMP_TEXT_LOWER)
result = lowertext(value)
if(COMP_TEXT_UPPER)
@@ -26,4 +26,4 @@
if(.)
return
output.set_output(text2num(input_port.input_value))
output.set_output(text2num(input_port.value))
@@ -28,13 +28,13 @@
if(.)
return
var/input_value = input_port.input_value
if(isatom(input_value))
var/value = input_port.value
if(isatom(value))
var/turf/location = get_turf(src)
var/atom/object = input_value
var/atom/object = value
if(object.z != location.z || get_dist(location, object) > max_range)
output.set_output(PORT_TYPE_ATOM)
return
output.set_output("[input_value]")
output.set_output("[value]")
@@ -28,7 +28,7 @@
if(.)
return
if(on.input_value)
if(on.value)
start_process()
else
stop_process()
@@ -1,48 +0,0 @@
/**
* # Combiner Component
*
* Combines multiple inputs into 1 output port.
*/
/obj/item/circuit_component/combiner
display_name = "Combiner"
desc = "A component that combines multiple inputs to provide 1 output."
/// The amount of input ports to have
var/input_port_amount = 4
var/datum/port/input/option/combiner_options
var/datum/port/output/output_port
var/list/combiner_ports = list()
var/current_type
/obj/item/circuit_component/combiner/populate_options()
var/static/component_options = list(
PORT_TYPE_ANY,
PORT_TYPE_STRING,
PORT_TYPE_NUMBER,
PORT_TYPE_LIST,
PORT_TYPE_ATOM,
PORT_TYPE_SIGNAL,
)
combiner_options = add_option_port("Combiner Options", component_options)
/obj/item/circuit_component/combiner/Initialize()
. = ..()
current_type = combiner_options.input_value
for(var/port_id in 1 to input_port_amount)
var/letter = ascii2text(text2ascii("A") + (port_id-1))
combiner_ports += add_input_port(letter, current_type)
output_port = add_output_port("Output", current_type)
/obj/item/circuit_component/combiner/input_received(datum/port/input/port)
. = ..()
if(current_type != combiner_options.input_value)
current_type = combiner_options.input_value
for(var/datum/port/input/input_port as anything in combiner_ports)
input_port.set_datatype(current_type)
output_port.set_datatype(current_type)
if(. || !port)
return TRUE
output_port.set_output(port.input_value)
@@ -33,11 +33,11 @@
if(!COMPONENT_TRIGGERED_BY(trigger, port))
return
var/delay = delay_amount.input_value
var/delay = delay_amount.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)
addtimer(CALLBACK(output, /datum/port/output.proc/set_output, trigger.value), delay*10)
else
output.set_output(trigger.input_value)
output.set_output(trigger.value)
#undef COMP_DELAY_MIN_VALUE
@@ -52,8 +52,8 @@
/obj/item/circuit_component/ram/input_received(datum/port/input/port)
. = ..()
if(current_type != ram_options.input_value)
current_type = ram_options.input_value
if(current_type != ram_options.value)
current_type = ram_options.value
input_port.set_datatype(current_type)
output.set_datatype(current_type)
@@ -67,6 +67,6 @@
if(!COMPONENT_TRIGGERED_BY(trigger, port))
return TRUE
var/input_val = input_port.input_value
var/input_val = input_port.value
output.set_output(input_val)
@@ -37,7 +37,7 @@
/obj/item/circuit_component/router/Initialize()
. = ..()
current_type = router_options.input_value
current_type = router_options.value
if(input_port_amount > 1)
input_selector = add_input_port("Input Selector", PORT_TYPE_NUMBER, default = 1)
if(output_port_amount > 1)
@@ -63,7 +63,7 @@
#define WRAPACCESS(L, I) L[(((I||1)-1)%length(L)+length(L))%length(L)+1]
/obj/item/circuit_component/router/input_received(datum/port/input/port)
. = ..()
var/current_option = router_options.input_value
var/current_option = router_options.value
if(current_type != current_option)
current_type = current_option
for(var/datum/port/input/input as anything in ins)
@@ -72,9 +72,9 @@
output.set_datatype(current_type)
if(.)
return
var/datum/port/input/input = WRAPACCESS(ins, input_selector ? input_selector.input_value : 1)
var/datum/port/output/output = WRAPACCESS(outs, output_selector ? output_selector.input_value : 1)
output.set_output(input.input_value)
var/datum/port/input/input = WRAPACCESS(ins, input_selector ? input_selector.value : 1)
var/datum/port/output/output = WRAPACCESS(outs, output_selector ? output_selector.value : 1)
output.set_output(input.value)
/obj/item/circuit_component/router/multiplexer
display_name = "Multiplexer"
@@ -18,7 +18,7 @@
/obj/item/circuit_component/typecast/Initialize()
. = ..()
current_type = typecast_options.input_value
current_type = typecast_options.value
input_value = add_input_port("Input", PORT_TYPE_ANY)
output_value = add_output_port("Output", current_type)
@@ -33,7 +33,7 @@
/obj/item/circuit_component/typecast/input_received(datum/port/input/port)
. = ..()
var/current_option = typecast_options.input_value
var/current_option = typecast_options.value
if(current_type != current_option)
current_type = current_option
output_value.set_datatype(current_type)
@@ -41,7 +41,7 @@
if(.)
return
var/value = input_value.input_value
var/value = input_value.value
var/value_to_set = null
switch(current_option)
if(PORT_TYPE_STRING)
@@ -31,8 +31,8 @@
// We're only comparing the first port/value. There shouldn't be any more.
var/datum/port/input/input_port = ports[1]
var/input_val = input_port.input_value
switch(typecheck_options.input_value)
var/input_val = input_port.value
switch(typecheck_options.value)
if(PORT_TYPE_STRING)
return istext(input_val)
if(PORT_TYPE_NUMBER)
+1 -1
View File
@@ -49,7 +49,7 @@ GLOBAL_LIST_INIT(circuit_datatypes, generate_circuit_datatypes())
* * gained_port - The gained port.
*/
/datum/circuit_datatype/proc/on_gain(datum/port/gained_port)
gained_port.disconnect()
return
/**
* Called when the datatype is removed from a port.
+27 -25
View File
@@ -84,23 +84,25 @@ GLOBAL_LIST_INIT(circuit_dupe_whitelisted_types, list(
port.set_input(connection_data["stored_data"])
continue
var/obj/item/circuit_component/connected_component = identifiers_to_circuit[connection_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
// 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 = connection_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
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
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.register_output_port(output_port)
port.connect(output_port)
#undef LOG_ERROR
@@ -131,18 +133,18 @@ GLOBAL_LIST_INIT(circuit_dupe_whitelisted_types, list(
var/list/connections = list()
var/list/input_ports_stored_data = list()
for(var/datum/port/input/port as anything in component.input_ports)
for(var/datum/port/input/input as anything in component.input_ports)
var/list/connection_data = list()
var/datum/port/output/output_port = port.connected_port
if(!output_port)
if(isnull(port.input_value) || !(port.datatype in GLOB.circuit_dupe_whitelisted_types))
continue
connection_data["stored_data"] = port.input_value
input_ports_stored_data[port.name] = connection_data
continue
connection_data["component_id"] = circuit_to_identifiers[output_port.connected_component]
connection_data["port_name"] = output_port.name
connections[port.name] = connection_data
if(!isnull(input.value) && (input.datatype in GLOB.circuit_dupe_whitelisted_types))
connection_data["stored_data"] = input.value
input_ports_stored_data[input.name] = connection_data
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
+9 -10
View File
@@ -242,14 +242,17 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit)
var/list/component_data = list()
component_data["input_ports"] = list()
for(var/datum/port/input/port as anything in component.input_ports)
var/current_data = port.input_value
var/current_data = port.value
if(isatom(current_data)) // Prevent passing the name of the atom.
current_data = null
var/list/connected_to = list()
for(var/datum/port/output/output as anything in port.connected_ports)
connected_to += REF(output)
component_data["input_ports"] += list(list(
"name" = port.name,
"type" = port.datatype,
"ref" = REF(port), // The ref is the identifier to work out what it is connected to
"connected_to" = REF(port.connected_port),
"connected_to" = connected_to,
"color" = port.color,
"current_data" = current_data,
"datatype_data" = port.datatype_ui_data(user),
@@ -344,8 +347,7 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit)
if(!input_port.can_receive_from_datatype(output_port.datatype))
return
input_port.register_output_port(output_port)
input_port.connect(output_port)
. = TRUE
if("remove_connection")
var/component_id = text2num(params["component_id"])
@@ -366,7 +368,7 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit)
return
var/datum/port/port = port_table[port_id]
port.disconnect()
port.disconnect_all()
. = TRUE
if("detach_component")
var/component_id = text2num(params["component_id"])
@@ -398,9 +400,6 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit)
return
var/datum/port/input/port = component.input_ports[port_id]
if(port.connected_port)
return
if(params["set_null"])
port.set_input(null)
return TRUE
@@ -442,9 +441,9 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit)
return
var/datum/port/output/port = component.output_ports[port_id]
var/value = port.output_value
var/value = port.value
if(isatom(value))
value = port.convert_value(port.output_value)
value = PORT_TYPE_ATOM
else if(isnull(value))
value = "null"
var/string_form = copytext("[value]", 1, PORT_MAX_STRING_DISPLAY)
+82 -134
View File
@@ -1,9 +1,7 @@
/**
* # Component Port
*
* A base type port used by a component
*
* Connects to other ports. This is an abstract type that should not be instanciated
* A port used by a component. Connects to other ports.
*/
/datum/port
/// The component this port is attached to
@@ -15,6 +13,9 @@
/// The port type. Ports can only connect to each other if the type matches
var/datatype
/// The value that's currently in the port. It's of the above type.
var/value
/// The default port type. Stores the original datatype of the port set on Initialize.
var/datum/circuit_datatype/datatype_handler
@@ -26,31 +27,45 @@
qdel(src)
return
. = ..()
// Don't need to do src.connected_component here, but it looks inline
// with the other variable declarations
src.connected_component = to_connect
connected_component = to_connect
src.name = name
set_datatype(datatype)
/datum/port/Destroy(force)
disconnect_all()
connected_component = null
datatype_handler = null
return ..()
/**
* Returns the value to be set for the port
*
* Used for implicit conversions between outputs and inputs (e.g. number -> string)
* and applying/removing signals on inputs
* Sets the port's value to value.
* Casts to the port's datatype (e.g. number -> string), and assumes this can be done.
*/
/datum/port/proc/convert_value(value_to_convert)
return datatype_handler.convert_value(src, value_to_convert)
/datum/port/proc/set_value(value)
if(src.value != value)
if(isatom(value))
UnregisterSignal(value, COMSIG_PARENT_QDELETING)
src.value = datatype_handler.convert_value(src, value)
if(isatom(value))
RegisterSignal(value, COMSIG_PARENT_QDELETING, .proc/null_value)
SEND_SIGNAL(src, COMSIG_PORT_SET_VALUE, value)
/**
* Updates the value of the input and calls input_received on the connected component
*/
/datum/port/input/proc/set_input(value)
set_value(value)
if(trigger)
TRIGGER_CIRCUIT_COMPONENT(connected_component, src)
/datum/port/output/proc/set_output(value)
set_value(value)
/**
* Sets the datatype of the port.
*
* Arguments:
* * type_to_set - The type this port is set to.
* * new_type - The type this port is to be set to.
*/
/datum/port/proc/set_datatype(type_to_set)
if(type_to_set == datatype)
@@ -71,26 +86,22 @@
datatype_handler = handler
color = datatype_handler.color
datatype_handler.on_gain(src)
src.value = datatype_handler.convert_value(src, value)
SEND_SIGNAL(src, COMSIG_PORT_SET_TYPE, type_to_set)
if(connected_component?.parent)
SStgui.update_uis(connected_component.parent)
/datum/port/input/set_datatype(new_type)
for(var/datum/port/output/output as anything in connected_ports)
check_type(output)
..()
/**
* Returns the data from the datatype
*/
/datum/port/proc/datatype_ui_data()
return datatype_handler.datatype_ui_data(src)
/**
* Disconnects a port from all other ports
*
* Called by [/obj/item/circuit_component] whenever it is disconnected from
* an integrated circuit
*/
/datum/port/proc/disconnect()
SHOULD_CALL_PARENT(TRUE)
SEND_SIGNAL(src, COMSIG_PORT_DISCONNECT)
/**
* # Output Port
*
@@ -99,90 +110,67 @@
* Sends a signal whenever the output value is changed
*/
/datum/port/output
/// The output value of the port
var/output_value
/datum/port/output/disconnect()
set_output(null)
return ..()
/datum/port/output/Destroy(force)
output_value = null
return ..()
/**
* Sets the output value of the port
* Disconnects a port from all other ports.
*
* Arguments:
* * value - The value to set it to
* Called by [/obj/item/circuit_component] whenever it is disconnected from
* an integrated circuit
*/
/datum/port/output/proc/set_output(value)
if(isatom(output_value))
UnregisterSignal(output_value, COMSIG_PARENT_QDELETING)
output_value = convert_value(value)
if(isatom(output_value))
RegisterSignal(output_value, COMSIG_PARENT_QDELETING, .proc/null_output)
/datum/port/proc/disconnect_all()
SEND_SIGNAL(src, COMSIG_PORT_DISCONNECT)
SEND_SIGNAL(src, COMSIG_PORT_SET_OUTPUT, output_value)
/datum/port/input/disconnect_all()
..()
for(var/datum/port/output/output as anything in connected_ports)
disconnect(output)
/// Signal handler proc to null the output if an atom is deleted. An update is not sent because this was not set.
/datum/port/output/proc/null_output(datum/source)
/datum/port/input/proc/disconnect(datum/port/output/output)
connected_ports -= output
UnregisterSignal(output, COMSIG_PORT_SET_VALUE)
UnregisterSignal(output, COMSIG_PORT_SET_TYPE)
UnregisterSignal(output, COMSIG_PORT_DISCONNECT)
/// Do our part in setting all source references anywhere to null.
/datum/port/proc/on_value_qdeleting(datum/source)
SIGNAL_HANDLER
if(output_value == source)
output_value = null
/datum/port/output/set_datatype(type_to_set)
. = ..()
set_output(null)
if(value == source)
value = null
else
stack_trace("Impossible? [src] should only receive COMSIG_PARENT_QDELETING from an atom currently in the port, not [source].")
/**
* # Input Port
*
* An input port that can only be connected to 1 output port
* An input port remembers connected output ports.
*
* Registers a signal on the target output port to listen out for any output
* so that an update can be sent to the attached component
* Registers the PORT_SET_VALUE signal on each connected port,
* and keeps its value equal to the last such signal received.
*/
/datum/port/input
/// The output value of the port
var/input_value
/// The connected output port
var/datum/port/output/connected_port
/// Whether this port triggers an update whenever an output is received.
var/trigger = FALSE
/// The default value of this input
var/default
/// The ports this port is wired to.
var/list/datum/port/output/connected_ports
/datum/port/input/New(obj/item/circuit_component/to_connect, name, datatype, trigger, default)
. = ..()
set_input(default)
src.trigger = trigger
src.default = default
set_input(default, FALSE)
src.connected_ports = list()
/**
* Connects the input port to the output port
*
* Sets the input_value and registers a signal to receive future updates.
* Arguments:
* * port_to_register - The port to connect the input port to
* Introduces two ports to one another.
*/
/datum/port/input/proc/register_output_port(datum/port/output/port_to_register)
unregister_output_port()
RegisterSignal(port_to_register, COMSIG_PORT_SET_OUTPUT, .proc/receive_output)
RegisterSignal(port_to_register, list(
COMSIG_PORT_DISCONNECT,
COMSIG_PARENT_QDELETING
), .proc/unregister_output_port)
connected_port = port_to_register
SEND_SIGNAL(connected_port, COMSIG_PORT_OUTPUT_CONNECT, src)
/datum/port/input/proc/connect(datum/port/output/output)
connected_ports |= output
RegisterSignal(output, COMSIG_PORT_SET_VALUE, .proc/receive_value)
RegisterSignal(output, COMSIG_PORT_SET_TYPE, .proc/check_type)
RegisterSignal(output, COMSIG_PORT_DISCONNECT, .proc/disconnect)
// For signals, we don't update the input to prevent sending a signal when connecting ports.
if(!(datatype_handler.datatype_flags & DATATYPE_FLAG_AVOID_VALUE_UPDATE))
set_input(connected_port.output_value)
set_input(output.value)
/**
* Determines if a datatype is compatible with another port of a different type.
@@ -205,62 +193,22 @@
return null
/**
* Sets a timer depending on the value of the input_receive_delay
*
* The timer will call a proc that updates the value.
* Arguments:
* * connected_port - The connected output port
* * new_value - The new value received from the output port
* Mirror value updates from connected output ports after an input_receive_delay.
*/
/datum/port/input/proc/receive_output(datum/port/output/connected_port, new_value)
/datum/port/input/proc/receive_value(datum/port/output/output, value)
SIGNAL_HANDLER
SScircuit_component.add_callback(CALLBACK(src, .proc/set_input, new_value))
/**
* Updates the value of the input
*
* It updates the value of the input and calls input_received on the connected component
* Arguments:
* * port_to_register - The port to connect the input port to
*/
/datum/port/input/proc/set_input(new_value, send_update = TRUE)
if(isatom(input_value))
UnregisterSignal(input_value, COMSIG_PARENT_QDELETING)
input_value = convert_value(new_value)
if(isatom(input_value))
RegisterSignal(input_value, COMSIG_PARENT_QDELETING, .proc/null_output)
SEND_SIGNAL(src, COMSIG_PORT_SET_INPUT, input_value)
if(connected_component && trigger && send_update)
TRIGGER_CIRCUIT_COMPONENT(connected_component, src)
SScircuit_component.add_callback(CALLBACK(src, .proc/set_input, value))
/// Signal handler proc to null the input if an atom is deleted. An update is not sent because this was not set by anything.
/datum/port/input/proc/null_output(datum/source)
/datum/port/proc/null_value(datum/source)
SIGNAL_HANDLER
if(input_value == source)
input_value = null
if(value == source)
value = null
/datum/port/input/disconnect()
unregister_output_port()
return ..()
/datum/port/input/set_datatype(type_to_set)
. = ..()
set_input(default)
/datum/port/input/proc/unregister_output_port()
/**
* Handle type updates from connected output ports, breaking uncastable connections.
*/
/datum/port/input/proc/check_type(datum/port/output/output)
SIGNAL_HANDLER
if(!connected_port)
return
UnregisterSignal(connected_port, list(
COMSIG_PARENT_QDELETING,
COMSIG_PORT_SET_OUTPUT,
COMSIG_PORT_DISCONNECT
))
connected_port = null
set_input(default)
/datum/port/input/Destroy()
unregister_output_port()
connected_port = null
return ..()
if(!can_receive_from_datatype(output.datatype))
disconnect(output)
+1 -1
View File
@@ -17,4 +17,4 @@
speech.rel_x = 400
speech.rel_y = 200
speech.message.register_output_port(hear.message_port)
speech.message.connect(hear.message_port)
@@ -128,8 +128,8 @@
update_action()
/obj/item/circuit_component/bci_action/proc/update_action()
bci_action.name = button_name.input_value
bci_action.button_icon_state = "bci_[replacetextEx(lowertext(icon_options.input_value), " ", "_")]"
bci_action.name = button_name.value
bci_action.button_icon_state = "bci_[replacetextEx(lowertext(icon_options.value), " ", "_")]"
/datum/action/innate/bci_action
name = "Action"
@@ -205,7 +205,7 @@
return .
if (COMPONENT_TRIGGERED_BY(send_message_signal, port))
var/sent_message = trim(message.input_value)
var/sent_message = trim(message.value)
if (!sent_message)
return
+1 -1
View File
@@ -71,7 +71,7 @@
if(!attached_bot)
return
var/to_dispense = clamp(dispense_amount.input_value, 0, attached_bot.stored_money)
var/to_dispense = clamp(dispense_amount.value, 0, attached_bot.stored_money)
if(!to_dispense)
on_fail.set_output(COMPONENT_SIGNAL)
return