Ports the Port of Circuits

Ports PsiOmegaDelta's port of integrated circuits, which has several improvements in code quality.
Ports a few small things like the weakref datum and some macros.
This commit is contained in:
Neerti
2016-09-24 18:06:11 -04:00
parent 57c5de6d1c
commit 801a162ba7
19 changed files with 884 additions and 1088 deletions
+148 -175
View File
@@ -1,3 +1,7 @@
#define IC_INPUT "input"
#define IC_OUTPUT "output"
#define IC_ACTIVATOR "activator"
#define DATA_CHANNEL "data channel"
#define PULSE_CHANNEL "pulse channel"
@@ -11,66 +15,37 @@
var/list/inputs = list()
var/list/outputs = list()
var/list/activators = list()
var/number_of_inputs = 0 //This is how many input pins are created
var/number_of_outputs = 0 //Likewise for output
var/number_of_activators = 0 //Guess
var/list/input_names = list()
var/list/output_names = list()
var/list/activator_names = list()
var/last_used = 0 //Uses world.time
var/next_use = 0 //Uses world.time
var/complexity = 1 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'.
var/cooldown_per_use = 2 SECONDS
var/cooldown_per_use = 1 SECOND
var/category = /obj/item/integrated_circuit // Used by the toolsets to filter out category types
/obj/item/integrated_circuit/examine(mob/user)
..()
user << "This board has [inputs.len] input [inputs.len != 1 ? "pins" : "pin"] and \
[outputs.len] output [outputs.len != 1 ? "pins" : "pin"]."
to_chat(user, "This board has [inputs.len] input pin\s and [outputs.len] output pin\s.")
for(var/datum/integrated_io/input/I in inputs)
if(I.linked.len)
user << "\The [I.name] is connected to [I.get_linked_to_desc()]."
to_chat(user, "The [I] is connected to [I.get_linked_to_desc()].")
for(var/datum/integrated_io/output/O in outputs)
if(O.linked.len)
user << "\The [O.name] is connected to [O.get_linked_to_desc()]."
to_chat(user, "The [O] is connected to [O.get_linked_to_desc()].")
for(var/datum/integrated_io/activate/A in activators)
if(A.linked.len)
user << "\The [A.name] is connected to [A.get_linked_to_desc()]."
to_chat(user, "The [A] is connected to [A.get_linked_to_desc()].")
interact(user)
/obj/item/integrated_circuit/New()
setup_io(inputs, /datum/integrated_io/input)
setup_io(outputs, /datum/integrated_io/output)
setup_io(activators, /datum/integrated_io/activate)
..()
var/i = 0
if(number_of_inputs)
for(i = number_of_inputs, i > 0, i--)
inputs.Add(new /datum/integrated_io/input(src))
if(number_of_outputs)
for(i = number_of_outputs, i > 0, i--)
outputs.Add(new /datum/integrated_io/output(src))
if(number_of_activators)
for(i = number_of_activators, i > 0, i--)
activators.Add(new /datum/integrated_io/activate(src))
apply_names_to_io()
/obj/item/integrated_circuit/proc/apply_names_to_io()
var/i = 1
if(input_names.len)
for(var/datum/integrated_io/input/I in inputs)
I.name = "[input_names[i]]"
i++
i = 1
if(output_names.len)
for(var/datum/integrated_io/output/O in outputs)
O.name = "[output_names[i]]"
i++
i = 1
if(activator_names.len)
for(var/datum/integrated_io/activate/A in activators)
A.name = "[activator_names[i]]"
i++
/obj/item/integrated_circuit/proc/setup_io(var/list/io_list, var/io_type)
var/list/names = io_list.Copy()
io_list.Cut()
for(var/name in names)
io_list.Add(new io_type(src, name))
/obj/item/integrated_circuit/proc/on_data_written() //Override this for special behaviour when new data gets pushed to the circuit.
return
@@ -82,7 +57,12 @@
qdel(O)
for(var/datum/integrated_io/A in activators)
qdel(A)
..()
. = ..()
/obj/item/integrated_circuit/nano_host()
if(istype(src.loc, /obj/item/device/electronic_assembly))
return loc
return ..()
/obj/item/integrated_circuit/emp_act(severity)
for(var/datum/integrated_io/io in inputs + outputs + activators)
@@ -94,42 +74,42 @@
set desc = "Rename your circuit, useful to stay organized."
var/mob/M = usr
if(!M.canmove || M.stat || M.restrained())
if(!CanInteract(M, physical_state))
return
var/input = sanitizeSafe(input("What do you want to name the circuit?", "Rename", src.name), MAX_NAME_LEN)
if(src && input)
M << "<span class='notice'>The circuit '[src.name]' is now labeled '[input]'.</span>"
var/input = sanitizeSafe(input("What do you want to name the circuit?", "Rename", src.name) as null|text, MAX_NAME_LEN)
if(src && input && CanInteract(M, physical_state))
to_chat(M, "<span class='notice'>The circuit '[src.name]' is now labeled '[input]'.</span>")
name = input
/obj/item/integrated_circuit/proc/get_pin_ref(var/pin_type, var/pin_number)
switch(pin_type)
if("input")
if(IC_INPUT)
if(pin_number > inputs.len)
return null
return inputs[pin_number]
if("output")
if(IC_OUTPUT)
if(pin_number > outputs.len)
return null
return outputs[pin_number]
if("activator")
if(IC_ACTIVATOR)
if(pin_number > activators.len)
return null
return activators[pin_number]
return null
/obj/item/integrated_circuit/interact(mob/user)
if(get_dist(get_turf(src), user) > 1)
user.unset_machine(src)
if(!CanInteract(user, physical_state))
return
var/HTML = "<html><head><title>[src.name]</title></head><body>"
var/HTML = list()
HTML += "<html><head><title>[src.name]</title></head><body>"
HTML += "<div align='center'>"
HTML += "<table border='1' style='undefined;table-layout: fixed; width: 424px'>"
HTML += "<br><a href='?src=\ref[src];user=\ref[user]'>\[Refresh\]</a> | "
HTML += "<a href='?src=\ref[src];user=\ref[user];rename=1'>\[Rename\]</a><br>"
HTML += "<br><a href='?src=\ref[src];'>\[Refresh\]</a> | "
HTML += "<a href='?src=\ref[src];rename=1'>\[Rename\]</a> | "
HTML += "<a href='?src=\ref[src];remove=1'>\[Remove\]</a><br>"
HTML += "<colgroup>"
HTML += "<col style='width: 121px'>"
@@ -139,80 +119,69 @@
var/column_width = 3
var/row_height = max(inputs.len, outputs.len, 1)
var/i
var/j
for(i = 1, i < row_height+1, i++)
for(var/i = 1 to row_height)
HTML += "<tr>"
for(j = 1, j < column_width+1, j++)
for(var/j = 1 to column_width)
var/datum/integrated_io/io = null
var/words = null
var/words = list()
var/height = 1
switch(j)
if(1)
io = get_pin_ref("input",i)
io = get_pin_ref(IC_INPUT, i)
if(io)
if(io.linked.len)
words = "<a href=?src=\ref[src];wire=1;user=\ref[user];pin=\ref[io]><b>[io.name] [io.display_data()]</b></a><br>"
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]><b>[io.name] [io.display_data()]</b></a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;user=\ref[user];pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;user=\ref[user]>[linked.holder]</a><br>"
else // "Click <a href=?src=\ref[src];action=start>here</a>!"
words = "<a href=?src=\ref[src];wire=1;user=\ref[user];pin=\ref[io]>[io.name] [io.display_data()]</a><br>"
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder]</a><br>"
else
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>[io.name] [io.display_data()]</a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;user=\ref[user];pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;user=\ref[user]>[linked.holder]</a><br>"
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder]</a><br>"
if(outputs.len > inputs.len)
// height = Floor(outputs.len / inputs.len)
height = 1 // Because of bugs, if there's more outputs than inputs, it causes the output side to be hidden.
//world << "I wrote [words] at ([i],[j]). Height = [height]."
height = 1
if(2)
if(i == 1)
words = "[src.name]<br><br>[src.desc]"
words += "[src.name]<br><br>[src.desc]"
height = row_height
//world << "I wrote the center piece because i was equal to 1, at ([i],[j]). Height = [height]."
else
continue
if(3)
io = get_pin_ref("output",i)
io = get_pin_ref(IC_OUTPUT, i)
if(io)
if(io.linked.len)
words = "<a href=?src=\ref[src];wire=1;user=\ref[user];pin=\ref[io]><b>[io.name] [io.display_data()]</b></a><br>"
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]><b>[io.name] [io.display_data()]</b></a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;user=\ref[user];pin=\ref[io]>\[[linked.name]\]</a> \
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;user=\ref[user]>[linked.holder]</a><br>"
else
words = "<a href=?src=\ref[src];wire=1;user=\ref[user];pin=\ref[io]>[io.name] [io.display_data()]</a><br>"
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>[io.name] [io.display_data()]</a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;user=\ref[user];pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;user=\ref[user]>[linked.holder]</a><br>"
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder]</a><br>"
if(inputs.len > outputs.len)
// height = Floor(inputs.len / outputs.len)
height = 1 // See above.
//world << "I wrote [words] at ([i],[j]). Height = [height]."
HTML += "<td align='center' rowspan='[height]'>[words]</td>"
//HTML += "<td align='center'>[words]</td>"
//world << "Writing to ([i],[j])."
height = 1
HTML += "<td align='center' rowspan='[height]'>[jointext(words, null)]</td>"
HTML += "</tr>"
if(activators.len)
for(i = 1, i < activators.len+1, i++)
var/datum/integrated_io/io = null
var/words = null
io = get_pin_ref("activator",i)
if(io)
if(io.linked.len)
words = "<a href=?src=\ref[src];wire=1;user=\ref[user];pin=\ref[io]><font color='FF0000'><b>[io.name]</b></font></a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;user=\ref[user];pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src[src];examine=1;user=\ref[user]>[linked.holder]</a><br>"
else // "Click <a href=?src=\ref[src];action=start>here</a>!"
words = "<a href=?src=\ref[src];wire=1;user=\ref[user];pin=\ref[io]><font color='FF0000'>[io.name]</font></a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;user=\ref[user];pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;user=\ref[user]>[linked.holder]</a><br>"
HTML += "<tr>"
HTML += "<td colspan='3' align='center'>[words]</td>"
HTML += "</tr>"
for(var/activator in activators)
var/datum/integrated_io/io = activator
var/words = list()
if(io.linked.len)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]><font color='FF0000'><b>[io.name]</b></font></a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src[src];examine=1;user=\ref[user]>[linked.holder]</a><br>"
else
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]><font color='FF0000'>[io.name]</font></a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder]</a><br>"
HTML += "<tr>"
HTML += "<td colspan='3' align='center'>[jointext(words, null)]</td>"
HTML += "</tr>"
HTML += "</table>"
HTML += "</div>"
@@ -221,56 +190,50 @@
HTML += "<br><font color='0000FF'>[extended_desc]</font>"
HTML += "</body></html>"
user << browse(HTML, "window=circuit-\ref[src];size=600x350;border=1;can_resize=1;can_close=1;can_minimize=1")
user << browse(jointext(HTML, null), "window=circuit-\ref[src];size=600x350;border=1;can_resize=1;can_close=1;can_minimize=1")
//user << sanitize(HTML, "window=debug;size=400x400;border=1;can_resize=1;can_close=1;can_minimize=1")
//world << sanitize(HTML)
user.set_machine(src)
onclose(user, "circuit-\ref[src]")
/obj/item/integrated_circuit/Topic(href, href_list[])
var/mob/living/user = locate(href_list["user"]) in mob_list
/obj/item/integrated_circuit/Topic(href, href_list, state = physical_state)
if(..())
return 1
var/pin = locate(href_list["pin"]) in inputs + outputs + activators
if(!user || !user.Adjacent(get_turf(src)) )
return 1
if(!user.canmove || user.stat || user.restrained())
return
var/obj/held_item = usr.get_active_hand()
if(href_list["wire"])
if(ishuman(user) && Adjacent(user))
var/mob/living/carbon/human/H = user
var/obj/held_item = H.get_active_hand()
if(istype(held_item, /obj/item/device/integrated_electronics/wirer))
var/obj/item/device/integrated_electronics/wirer/wirer = held_item
if(pin)
wirer.wire(pin, usr)
if(istype(held_item, /obj/item/device/integrated_electronics/wirer))
var/obj/item/device/integrated_electronics/wirer/wirer = held_item
if(pin)
wirer.wire(pin, user)
else if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/debugger = held_item
if(pin)
debugger.write_data(pin, user)
// if(istype(H.r_hand, /obj/item/device/integrated_electronics/wirer))
// wirer = H.r_hand
// else if(istype(H.l_hand, /obj/item/device/integrated_electronics/wirer))
// wirer = H.l_hand
// if(wirer && pin)
// wirer.wire(pin, user)
else
user << "<span class='warning'>You can't do a whole lot without tools.</span>"
else if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/debugger = held_item
if(pin)
debugger.write_data(pin, usr)
else
to_chat(usr, "<span class='warning'>You can't do a whole lot without the proper tools.</span>")
if(href_list["examine"])
examine(user)
examine(usr)
if(href_list["rename"])
rename_component(user)
rename_component(usr)
interact(user) // To refresh the UI.
if(href_list["remove"])
if(istype(held_item, /obj/item/weapon/screwdriver))
disconnect_all()
var/turf/T = get_turf(src)
forceMove(T)
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
to_chat(usr, "<span class='notice'>You pop \the [src] out of the case, and slide it out.</span>")
else
to_chat(usr, "<span class='warning'>You need a screwdriver to remove components.</span>")
var/obj/item/device/electronic_assembly/ea = loc
if(istype(ea))
ea.interact(usr)
return
interact(usr) // To refresh the UI.
/datum/integrated_io
var/name = "input/output"
@@ -287,8 +250,20 @@
/datum/integrated_io/Destroy()
disconnect()
data = null
holder = null
..()
. = ..()
/datum/integrated_io/nano_host()
return holder
/datum/integrated_io/proc/data_as_type(var/as_type)
if(!isweakref(data))
return
var/weakref/w = data
var/output = w.resolve()
return istype(output, as_type) ? output : null
/datum/integrated_io/proc/display_data()
if(isnull(data))
@@ -316,43 +291,38 @@
push_data()
/datum/integrated_io/proc/write_data_to_pin(var/new_data)
if(isnull(new_data) || isnum(new_data) || istext(new_data) || istype(new_data, /atom/) ) // Anything else is a type we don't want.
if(isnull(new_data) || isnum(new_data) || istext(new_data) || isweakref(new_data)) // Anything else is a type we don't want.
data = new_data
holder.on_data_written()
/datum/integrated_io/proc/push_data()
if(linked.len)
for(var/datum/integrated_io/io in linked)
io.write_data_to_pin(data)
for(var/datum/integrated_io/io in linked)
io.write_data_to_pin(data)
/datum/integrated_io/activate/push_data()
if(linked.len)
for(var/datum/integrated_io/io in linked)
io.holder.work()
for(var/datum/integrated_io/io in linked)
io.holder.check_then_do_work()
/datum/integrated_io/proc/pull_data()
if(linked.len)
for(var/datum/integrated_io/io in linked)
write_data_to_pin(io.data)
for(var/datum/integrated_io/io in linked)
write_data_to_pin(io.data)
/datum/integrated_io/proc/get_linked_to_desc()
if(linked.len)
var/result = english_list(linked)
return "the [result]"
return "the [english_list(linked)]"
return "nothing"
/datum/integrated_io/proc/disconnect()
if(linked.len)
//First we iterate over everything we are linked to.
for(var/datum/integrated_io/their_io in linked)
//While doing that, we iterate them as well, and disconnect ourselves from them.
for(var/datum/integrated_io/their_linked_io in their_io.linked)
if(their_linked_io == src)
their_io.linked.Remove(src)
else
continue
//Now that we're removed from them, we gotta remove them from us.
src.linked.Remove(their_io)
//First we iterate over everything we are linked to.
for(var/datum/integrated_io/their_io in linked)
//While doing that, we iterate them as well, and disconnect ourselves from them.
for(var/datum/integrated_io/their_linked_io in their_io.linked)
if(their_linked_io == src)
their_io.linked.Remove(src)
else
continue
//Now that we're removed from them, we gotta remove them from us.
src.linked.Remove(their_io)
/datum/integrated_io/input
name = "input pin"
@@ -372,11 +342,14 @@
for(var/datum/integrated_io/input/I in inputs)
I.push_data()
/obj/item/integrated_circuit/proc/work(var/datum/integrated_io/io)
if(last_used + cooldown_per_use > world.time) // All intergrated circuits have an internal cooldown, to protect from spam.
return 0
last_used = world.time
return 1
/obj/item/integrated_circuit/proc/check_then_do_work()
if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam.
return
next_use = world.time + cooldown_per_use
do_work()
/obj/item/integrated_circuit/proc/do_work()
return
/obj/item/integrated_circuit/proc/disconnect_all()
for(var/datum/integrated_io/input/I in inputs)