Replaced "area" shuttles with "landmark" shuttles.

Largely ported from the work done at Baystation in https://github.com/Baystation12/Baystation12/pull/17460 and later commits.

 - Shuttles no longer require a separate area for each location they jump to.
   Instead destinations are indicated by landmark objects, which are not necessarily exclusive to that shuttle.
   This means that more than one shuttle could use the same docking port (not at the same time of course).
 - Enhanced shuttle control computers to use nanoui if they didn't.
 - Organizes shuttle datum code a bit better so there is less re-inventing the wheel in subtypes.
 - Allows the possibility of shuttles (or destinations) that start on late-loaded maps.
 - Deprecate the "extra" shuttle areas that are no longer needed and update shuttle areas in unit tests

This all required a bit of infrastructure improvements.

 - ChangeArea proc, for changing the area of a turf.
 - Fixed lighting overlays actually being able to be destroyed.
 - Added a few utility macros and procs.
 - Added "turf translation" procs which are like move_contents_to but more flexible.
This commit is contained in:
Leshana
2020-02-28 16:23:51 -05:00
parent caeb0de720
commit c837078105
69 changed files with 2474 additions and 1451 deletions

View File

@@ -2,6 +2,7 @@
/obj/machinery/embedded_controller/radio/airlock
// Setup parameters only
radio_filter = RADIO_AIRLOCK
program = /datum/computer/file/embedded_program/airlock
var/tag_exterior_door
var/tag_interior_door
var/tag_airpump
@@ -11,11 +12,22 @@
var/tag_airlock_mech_sensor
var/tag_shuttle_mech_sensor
var/tag_secure = 0
var/list/dummy_terminals = list()
var/cycle_to_external_air = 0
/obj/machinery/embedded_controller/radio/airlock/Initialize()
. = ..()
program = new/datum/computer/file/embedded_program/airlock(src)
/obj/machinery/embedded_controller/radio/airlock/Destroy()
// TODO - Leshana - Implement dummy terminals
//for(var/thing in dummy_terminals)
// var/obj/machinery/dummy_airlock_controller/dummy = thing
// dummy.master_controller = null
//dummy_terminals.Cut()
return ..()
/obj/machinery/embedded_controller/radio/airlock/CanUseTopic(var/mob/user)
if(!allowed(user))
return min(STATUS_UPDATE, ..())
else
return ..()
//Advanced airlock controller for when you want a more versatile airlock controller - useful for turning simple access control rooms into airlocks
/obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller
@@ -37,43 +49,20 @@
if (!ui)
ui = new(user, src, ui_key, "advanced_airlock_console.tmpl", name, 470, 290)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller/Topic(href, href_list)
if(..())
if((. = ..()))
return
usr.set_machine(src)
src.add_fingerprint(usr)
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
if("cycle_ext")
clean = 1
if("cycle_int")
clean = 1
if("force_ext")
clean = 1
if("force_int")
clean = 1
if("abort")
clean = 1
if("purge")
clean = 1
if("secure")
clean = 1
if(clean)
program.receive_user_command(href_list["command"])
if("cycle_ext", "cycle_int", "force_ext", "force_int", "abort", "purge", "secure")
program.receive_user_command(href_list["command"])
return 1
//Airlock controller for airlock control - most airlocks on the station use this
/obj/machinery/embedded_controller/radio/airlock/airlock_controller
name = "Airlock Controller"
@@ -90,23 +79,16 @@
)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "simple_airlock_console.tmpl", name, 470, 290)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/airlock/airlock_controller/Topic(href, href_list)
if(..())
if((. = ..()))
return
usr.set_machine(src)
src.add_fingerprint(usr)
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
if("cycle_ext")
@@ -125,7 +107,6 @@
return 1
//Access controller for door control - used in virology and the like
/obj/machinery/embedded_controller/radio/airlock/access_controller
icon = 'icons/obj/airlock_machines.dmi'
@@ -154,23 +135,16 @@
)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "door_access_console.tmpl", name, 330, 220)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/airlock/access_controller/Topic(href, href_list)
if(..())
if((. = ..()))
return
usr.set_machine(src)
src.add_fingerprint(usr)
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
if("cycle_ext_door")

View File

@@ -0,0 +1,51 @@
// Provides remote access to a controller (since they must be unique).
/obj/machinery/dummy_airlock_controller
name = "airlock control terminal"
icon = 'icons/obj/airlock_machines.dmi'
icon_state = "airlock_control_standby"
layer = ABOVE_OBJ_LAYER
var/id_tag
var/datum/topic_state/remote/remote_state
var/obj/machinery/embedded_controller/radio/airlock/master_controller
/obj/machinery/dummy_airlock_controller/process()
if(master_controller)
appearance = master_controller
. = ..()
/obj/machinery/dummy_airlock_controller/Initialize()
. = ..()
if(id_tag)
for(var/obj/machinery/embedded_controller/radio/airlock/_master in SSmachines.machinery)
if(_master.id_tag == id_tag)
master_controller = _master
master_controller.dummy_terminals += src
break
if(!master_controller)
qdel(src)
else
remote_state = new /datum/topic_state/remote(src, master_controller)
/obj/machinery/dummy_airlock_controller/Destroy()
if(master_controller)
master_controller.dummy_terminals -= src
if(remote_state)
qdel(remote_state)
remote_state = null
return ..()
/obj/machinery/dummy_airlock_controller/interface_interact(var/mob/user)
open_remote_ui(user)
return TRUE
/obj/machinery/dummy_airlock_controller/proc/open_remote_ui(var/mob/user)
if(master_controller)
appearance = master_controller
return master_controller.ui_interact(user, state = remote_state)
/obj/machinery/dummy_airlock_controller/powered(var/chan = -1, var/area/check_area = null)
if(master_controller)
var/area/A = get_area(master_controller)
return master_controller.powered(chan, A)
return ..()

View File

@@ -1,8 +1,17 @@
/*
* NOTE - This file defines both these datums: Yes, you read that right. Its confusing. Lets try and break it down.
* /datum/computer/file/embedded_program/docking/airlock
* - A docking controller for an airlock based docking port
* /datum/computer/file/embedded_program/airlock/docking
* - An extension to the normal airlock program allows disabling of the regular airlock functions when docking
*/
//a docking port based on an airlock
/obj/machinery/embedded_controller/radio/airlock/docking_port
name = "docking port controller"
var/datum/computer/file/embedded_program/airlock/docking/airlock_program
var/datum/computer/file/embedded_program/docking/airlock/docking_program
var/display_name // For mappers to override docking_program.display_name (how would it show up on docking monitoring program)
tag_secure = 1
/obj/machinery/embedded_controller/radio/airlock/docking_port/Initialize()
@@ -10,9 +19,25 @@
airlock_program = new/datum/computer/file/embedded_program/airlock/docking(src)
docking_program = new/datum/computer/file/embedded_program/docking/airlock(src, airlock_program)
program = docking_program
if(display_name)
docking_program.display_name = display_name
/obj/machinery/embedded_controller/radio/airlock/docking_port/attackby(obj/item/W, mob/user)
if(istype(W,/obj/item/device/multitool)) //give them part of code, would take few tries to get full
var/datum/computer/file/embedded_program/docking/airlock/docking_program = program
var/code = docking_program.docking_codes
if(!code)
code = "N/A"
else
code = stars(code)
to_chat(user, "[W]'s screen displays '[code]'")
else
..()
/obj/machinery/embedded_controller/radio/airlock/docking_port/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/datum/computer/file/embedded_program/docking/airlock/docking_program = program
var/datum/computer/file/embedded_program/airlock/docking/airlock_program = docking_program.airlock_program
data = list(
"chamber_pressure" = round(airlock_program.memory["chamber_sensor_pressure"]),
@@ -22,6 +47,8 @@
"docking_status" = docking_program.get_docking_status(),
"airlock_disabled" = !(docking_program.undocked() || docking_program.override_enabled),
"override_enabled" = docking_program.override_enabled,
"docking_codes" = docking_program.docking_codes,
"name" = docking_program.get_name()
)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
@@ -33,12 +60,9 @@
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/airlock/docking_port/Topic(href, href_list)
if(..())
if((. = ..()))
return
usr.set_machine(src)
src.add_fingerprint(usr)
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
if("cycle_ext")
@@ -60,11 +84,13 @@
return 1
///////////////////////////////////////////////////////////////////////////////
//A docking controller for an airlock based docking port
//
/datum/computer/file/embedded_program/docking/airlock
var/datum/computer/file/embedded_program/airlock/docking/airlock_program
/datum/computer/file/embedded_program/docking/airlock/New(var/obj/machinery/embedded_controller/M, var/datum/computer/file/embedded_program/airlock/docking/A)
..(M)
airlock_program = A
@@ -76,10 +102,10 @@
disable_override()
else
enable_override()
return
return TRUE
..(command)
airlock_program.receive_user_command(command) //pass along to subprograms
. = ..(command)
. = airlock_program.receive_user_command(command) || . //pass along to subprograms; bypass shortcircuit
/datum/computer/file/embedded_program/docking/airlock/process()
airlock_program.process()
@@ -91,7 +117,7 @@
//tell the docking port to start getting ready for docking - e.g. pressurize
/datum/computer/file/embedded_program/docking/airlock/prepare_for_docking()
airlock_program.begin_cycle_in()
airlock_program.begin_dock_cycle()
//are we ready for docking?
/datum/computer/file/embedded_program/docking/airlock/ready_for_docking()
@@ -99,14 +125,14 @@
//we are docked, open the doors or whatever.
/datum/computer/file/embedded_program/docking/airlock/finish_docking()
airlock_program.enable_mech_regulators()
airlock_program.enable_mech_regulation()
airlock_program.open_doors()
//tell the docking port to start getting ready for undocking - e.g. close those doors.
/datum/computer/file/embedded_program/docking/airlock/prepare_for_undocking()
airlock_program.stop_cycling()
airlock_program.close_doors()
airlock_program.disable_mech_regulators()
airlock_program.disable_mech_regulation()
//are we ready for undocking?
/datum/computer/file/embedded_program/docking/airlock/ready_for_undocking()
@@ -114,20 +140,22 @@
var/int_closed = airlock_program.check_interior_door_secured()
return (ext_closed || int_closed)
///////////////////////////////////////////////////////////////////////////////
//An airlock controller to be used by the airlock-based docking port controller.
//Same as a regular airlock controller but allows disabling of the regular airlock functions when docking
//
/datum/computer/file/embedded_program/airlock/docking
var/datum/computer/file/embedded_program/docking/airlock/master_prog
/datum/computer/file/embedded_program/airlock/docking/Destroy()
if(master_prog)
master_prog.airlock_program = null
master_prog = null
return ..()
/datum/computer/file/embedded_program/airlock/docking/receive_user_command(command)
if (master_prog.undocked() || master_prog.override_enabled) //only allow the port to be used as an airlock if nothing is docked here or the override is enabled
..(command)
/datum/computer/file/embedded_program/airlock/docking/proc/enable_mech_regulators()
enable_mech_regulation()
/datum/computer/file/embedded_program/airlock/docking/proc/disable_mech_regulators()
disable_mech_regulation()
return ..(command)
/datum/computer/file/embedded_program/airlock/docking/proc/open_doors()
toggleDoor(memory["interior_status"], tag_interior_door, memory["secure"], "open")

View File

@@ -2,21 +2,15 @@
//this is the master controller, that things will try to dock with.
/obj/machinery/embedded_controller/radio/docking_port_multi
name = "docking port controller"
program = /datum/computer/file/embedded_program/docking/multi
var/child_tags_txt
var/child_names_txt
var/list/child_names = list()
var/datum/computer/file/embedded_program/docking/multi/docking_program
/obj/machinery/embedded_controller/radio/docking_port_multi/Initialize()
. = ..()
docking_program = new/datum/computer/file/embedded_program/docking/multi(src)
program = docking_program
var/list/names = splittext(child_names_txt, ";")
var/list/tags = splittext(child_tags_txt, ";")
if (names.len == tags.len)
for (var/i = 1; i <= tags.len; i++)
child_names[tags[i]] = names[i]
@@ -24,6 +18,7 @@
/obj/machinery/embedded_controller/radio/docking_port_multi/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/datum/computer/file/embedded_program/docking/multi/docking_program = program // Cast to proper type
var/list/airlocks[child_names.len]
var/i = 1
@@ -44,24 +39,21 @@
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/docking_port_multi/Topic(href, href_list)
return
return 1 // Apparently we swallow all input (this is corrected legacy code)
//a docking port based on an airlock
// This is the actual controller that will be commanded by the master defined above
/obj/machinery/embedded_controller/radio/airlock/docking_port_multi
name = "docking port controller"
program = /datum/computer/file/embedded_program/airlock/multi_docking
var/master_tag //for mapping
var/datum/computer/file/embedded_program/airlock/multi_docking/airlock_program
tag_secure = 1
/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/Initialize()
. = ..()
airlock_program = new/datum/computer/file/embedded_program/airlock/multi_docking(src)
program = airlock_program
/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/datum/computer/file/embedded_program/airlock/multi_docking/airlock_program // Cast to proper type
data = list(
"chamber_pressure" = round(airlock_program.memory["chamber_sensor_pressure"]),
@@ -82,12 +74,9 @@
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/Topic(href, href_list)
if(..())
if((. = ..()))
return
usr.set_machine(src)
src.add_fingerprint(usr)
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
if("cycle_ext")

View File

@@ -52,8 +52,8 @@
tag_interior_door = controller.tag_interior_door? controller.tag_interior_door : "[id_tag]_inner"
tag_airpump = controller.tag_airpump? controller.tag_airpump : "[id_tag]_pump"
tag_chamber_sensor = controller.tag_chamber_sensor? controller.tag_chamber_sensor : "[id_tag]_sensor"
tag_exterior_sensor = controller.tag_exterior_sensor
tag_interior_sensor = controller.tag_interior_sensor
tag_exterior_sensor = controller.tag_exterior_sensor || "[id_tag]_exterior_sensor"
tag_interior_sensor = controller.tag_interior_sensor || "[id_tag]_interior_sensor"
tag_airlock_mech_sensor = controller.tag_airlock_mech_sensor? controller.tag_airlock_mech_sensor : "[id_tag]_airlock_mech"
tag_shuttle_mech_sensor = controller.tag_shuttle_mech_sensor? controller.tag_shuttle_mech_sensor : "[id_tag]_shuttle_mech"
memory["secure"] = controller.tag_secure
@@ -117,6 +117,7 @@
/datum/computer/file/embedded_program/airlock/receive_user_command(command)
var/shutdown_pump = 0
. = TRUE
switch(command)
if("cycle_ext")
//If airlock is already cycled in this direction, just toggle the doors.
@@ -163,6 +164,8 @@
else
signalDoor(tag_interior_door, "unlock")
signalDoor(tag_exterior_door, "unlock")
else
. = FALSE
if(shutdown_pump)
signalPump(tag_airpump, 0) //send a signal to stop pressurizing
@@ -273,6 +276,9 @@
target_state = TARGET_INOPEN
memory["purge"] = cycle_to_external_air
/datum/computer/file/embedded_program/airlock/proc/begin_dock_cycle()
state = STATE_IDLE
target_state = TARGET_INOPEN
/datum/computer/file/embedded_program/airlock/proc/begin_cycle_out()
state = STATE_IDLE
target_state = TARGET_OUTOPEN

View File

@@ -12,51 +12,51 @@
/*
*** STATE TABLE ***
MODE_CLIENT|STATE_UNDOCKED sent a request for docking and now waiting for a reply.
MODE_CLIENT|STATE_DOCKING server told us they are OK to dock, waiting for our docking port to be ready.
MODE_CLIENT|STATE_DOCKED idle - docked as client.
MODE_CLIENT|STATE_UNDOCKING we are either waiting for our docking port to be ready or for the server to give us the OK to finish undocking.
MODE_SERVER|STATE_UNDOCKED should never happen.
MODE_SERVER|STATE_DOCKING someone requested docking, we are waiting for our docking port to be ready.
MODE_SERVER|STATE_DOCKED idle - docked as server
MODE_SERVER|STATE_UNDOCKING client requested undocking, we are waiting for our docking port to be ready.
MODE_NONE|STATE_UNDOCKED idle - not docked.
MODE_NONE|anything else should never happen.
*** Docking Signals ***
Docking
Client sends request_dock
Server sends confirm_dock to say that yes, we will serve your request
When client is ready, sends confirm_dock
Server sends confirm_dock back to indicate that docking is complete
Undocking
Client sends request_undock
When client is ready, sends confirm_undock
Server sends confirm_undock back to indicate that docking is complete
Note that in both cases each side exchanges confirm_dock before the docking operation is considered done.
The client first sends a confirm message to indicate it is ready, and then finally the server will send it's
The client first sends a confirm message to indicate it is ready, and then finally the server will send it's
confirm message to indicate that the operation is complete.
Note also that when docking, the server sends an additional confirm message. This is because before docking,
the server and client do not have a defined relationship. Before undocking, the server and client are already
related to each other, thus the extra confirm message is not needed.
*** Override, what is it? ***
The purpose of enabling the override is to prevent the docking program from automatically doing things with the docking port when docking or undocking.
Maybe the shuttle is full of plamsa/phoron for some reason, and you don't want the door to automatically open, or the airlock to cycle.
This means that the prepare_for_docking/undocking and finish_docking/undocking procs don't get called.
The docking controller will still check the state of the docking port, and thus prevent the shuttle from launching unless they force the launch (handling forced
launches is not the docking controller's responsibility). In this case it is up to the players to manually get the docking port into a good state to undock
launches is not the docking controller's responsibility). In this case it is up to the players to manually get the docking port into a good state to undock
(which usually just means closing and locking the doors).
In line with this, docking controllers should prevent players from manually doing things when the override is NOT enabled.
*/
@@ -67,27 +67,31 @@
var/control_mode = MODE_NONE
var/response_sent = 0 //so we don't spam confirmation messages
var/resend_counter = 0 //for periodically resending confirmation messages in case they are missed
var/override_enabled = 0 //when enabled, do not open/close doors or cycle airlocks and wait for the player to do it manually
var/received_confirm = 0 //for undocking, whether the server has recieved a confirmation from the client
var/docking_codes //would only allow docking when receiving signal with these, if set
var/display_name //Override the name shown on docking monitoring program; defaults to area name + coordinates if unset
/datum/computer/file/embedded_program/docking/New()
..()
var/datum/existing = locate(id_tag) //in case a datum already exists with our tag
if(existing)
existing.tag = null //take it from them
tag = id_tag //Greatly simplifies shuttle initialization
if(id_tag)
if(SSshuttles.docking_registry[id_tag])
crash_with("Docking controller tag [id_tag] had multiple associated programs.")
SSshuttles.docking_registry[id_tag] = src
/datum/computer/file/embedded_program/docking/Destroy()
SSshuttles.docking_registry -= id_tag
return ..()
/datum/computer/file/embedded_program/docking/receive_signal(datum/signal/signal, receive_method, receive_param)
var/receive_tag = signal.data["tag"] //for docking signals, this is the sender id
var/command = signal.data["command"]
var/recipient = signal.data["recipient"] //the intended recipient of the docking signal
if (recipient != id_tag)
return //this signal is not for us
switch (command)
if ("confirm_dock")
if (control_mode == MODE_CLIENT && dock_state == STATE_UNDOCKED && receive_tag == tag_target)
@@ -95,7 +99,7 @@
broadcast_docking_status()
if (!override_enabled)
prepare_for_docking()
else if (control_mode == MODE_CLIENT && dock_state == STATE_DOCKING && receive_tag == tag_target)
dock_state = STATE_DOCKED
broadcast_docking_status()
@@ -104,19 +108,27 @@
response_sent = 0
else if (control_mode == MODE_SERVER && dock_state == STATE_DOCKING && receive_tag == tag_target) //client just sent us the confirmation back, we're done with the docking process
received_confirm = 1
if ("request_dock")
if (control_mode == MODE_NONE && dock_state == STATE_UNDOCKED)
tag_target = receive_tag
if(docking_codes)
var/code = signal.data["code"]
if(code != docking_codes)
testing("Controller [id_tag] got request_dock but code:[code] != docking_codes:[docking_codes]")
return
control_mode = MODE_SERVER
dock_state = STATE_DOCKING
broadcast_docking_status()
tag_target = receive_tag
if (!override_enabled)
prepare_for_docking()
send_docking_command(tag_target, "confirm_dock") //acknowledge the request
if ("confirm_undock")
if (control_mode == MODE_CLIENT && dock_state == STATE_UNDOCKING && receive_tag == tag_target)
if (!override_enabled)
@@ -129,7 +141,7 @@
if (control_mode == MODE_SERVER && dock_state == STATE_DOCKED && receive_tag == tag_target)
dock_state = STATE_UNDOCKING
broadcast_docking_status()
if (!override_enabled)
prepare_for_undocking()
@@ -145,38 +157,38 @@
if (!response_sent)
send_docking_command(tag_target, "confirm_dock") //tell the server we're ready
response_sent = 1
else if (control_mode == MODE_SERVER && received_confirm)
send_docking_command(tag_target, "confirm_dock") //tell the client we are done docking.
dock_state = STATE_DOCKED
broadcast_docking_status()
if (!override_enabled)
finish_docking() //server done docking!
response_sent = 0
received_confirm = 0
if (STATE_UNDOCKING)
if (ready_for_undocking())
if (control_mode == MODE_CLIENT)
if (!response_sent)
send_docking_command(tag_target, "confirm_undock") //tell the server we are OK to undock.
response_sent = 1
else if (control_mode == MODE_SERVER && received_confirm)
send_docking_command(tag_target, "confirm_undock") //tell the client we are done undocking.
if (!override_enabled)
finish_undocking()
reset() //server is done undocking!
if (response_sent || resend_counter > 0)
resend_counter++
if (resend_counter >= MESSAGE_RESEND_TIME || (dock_state != STATE_DOCKING && dock_state != STATE_UNDOCKING))
response_sent = 0
resend_counter = 0
//handle invalid states
if (control_mode == MODE_NONE && dock_state != STATE_UNDOCKED)
if (tag_target)
@@ -189,22 +201,22 @@
/datum/computer/file/embedded_program/docking/proc/initiate_docking(var/target)
if (dock_state != STATE_UNDOCKED || control_mode == MODE_SERVER) //must be undocked and not serving another request to begin a new docking handshake
return
tag_target = target
control_mode = MODE_CLIENT
send_docking_command(tag_target, "request_dock")
/datum/computer/file/embedded_program/docking/proc/initiate_undocking()
if (dock_state != STATE_DOCKED || control_mode != MODE_CLIENT) //must be docked and must be client to start undocking
return
dock_state = STATE_UNDOCKING
broadcast_docking_status()
if (!override_enabled)
prepare_for_undocking()
send_docking_command(tag_target, "request_undock")
//tell the docking port to start getting ready for docking - e.g. pressurize
@@ -240,7 +252,7 @@
/datum/computer/file/embedded_program/docking/proc/reset()
dock_state = STATE_UNDOCKED
broadcast_docking_status()
control_mode = MODE_NONE
tag_target = null
response_sent = 0
@@ -267,6 +279,7 @@
signal.data["tag"] = id_tag
signal.data["command"] = command
signal.data["recipient"] = recipient
signal.data["code"] = docking_codes
post_signal(signal)
/datum/computer/file/embedded_program/docking/proc/broadcast_docking_status()
@@ -283,6 +296,8 @@
if (STATE_UNDOCKING) return "undocking"
if (STATE_DOCKED) return "docked"
/datum/computer/file/embedded_program/docking/proc/get_name()
return display_name ? display_name : "[get_area(master)] ([master.x], [master.y])"
#undef STATE_UNDOCKED
#undef STATE_DOCKING

View File

@@ -1,18 +1,20 @@
/obj/machinery/embedded_controller
var/datum/computer/file/embedded_program/program //the currently executing program
name = "Embedded Controller"
anchored = 1
use_power = 1
idle_power_usage = 10
var/datum/computer/file/embedded_program/program //the currently executing program
var/on = 1
obj/machinery/embedded_controller/radio/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
..()
/obj/machinery/embedded_controller/Initialize()
if(ispath(program))
program = new program(src)
return ..()
/obj/machinery/embedded_controller/Destroy()
if(istype(program))
qdel(program) // the program will clear the ref in its Destroy
return ..()
/obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line)
return 0
@@ -24,6 +26,17 @@ obj/machinery/embedded_controller/radio/Destroy()
program.receive_signal(signal, receive_method, receive_param)
//spawn(5) program.process() //no, program.process sends some signals and machines respond and we here again and we lag -rastaf0
/obj/machinery/embedded_controller/Topic(href, href_list)
if((. = ..()))
return
if(usr)
usr.set_machine(src)
src.add_fingerprint(usr)
// We would now pass it to the program, except that some of our embedded controller types want to block certain commands.
// Until/unless that is refactored differently, we rely on subtypes to pass it on.
//if(program)
// return program.receive_user_command(href_list["command"])
/obj/machinery/embedded_controller/process()
if(program)
program.process()
@@ -40,14 +53,16 @@ obj/machinery/embedded_controller/radio/Destroy()
src.ui_interact(user)
/obj/machinery/embedded_controller/ui_interact()
return
//
// Embedded controller with a radio! (Most things (All things?) use this)
//
/obj/machinery/embedded_controller/radio
icon = 'icons/obj/airlock_machines.dmi'
icon_state = "airlock_control_standby"
power_channel = ENVIRON
density = 0
unacidable = 1
var/id_tag
//var/radio_power_use = 50 //power used to xmit signals
@@ -55,11 +70,15 @@ obj/machinery/embedded_controller/radio/Destroy()
var/frequency = 1379
var/radio_filter = null
var/datum/radio_frequency/radio_connection
unacidable = 1
/obj/machinery/embedded_controller/radio/Initialize()
set_frequency(frequency) // Set it before parent instantiates program
. = ..()
set_frequency(frequency)
/obj/machinery/embedded_controller/radio/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
..()
/obj/machinery/embedded_controller/radio/update_icon()
if(on && program)

View File

@@ -11,8 +11,15 @@
var/obj/machinery/embedded_controller/radio/R = M
id_tag = R.id_tag
/datum/computer/file/embedded_program/Destroy()
if(master)
master.program = null
master = null
return ..()
// Return TRUE if was a command for us, otherwise return FALSE (so controllers with multiple programs can try each in turn until one accepts)
/datum/computer/file/embedded_program/proc/receive_user_command(command)
return
return FALSE
/datum/computer/file/embedded_program/proc/receive_signal(datum/signal/signal, receive_method, receive_param)
return

View File

@@ -1,16 +1,12 @@
//a docking port that uses a single door
/obj/machinery/embedded_controller/radio/simple_docking_controller
name = "docking hatch controller"
program = /datum/computer/file/embedded_program/docking/simple
var/tag_door
var/datum/computer/file/embedded_program/docking/simple/docking_program
/obj/machinery/embedded_controller/radio/simple_docking_controller/Initialize()
. = ..()
docking_program = new/datum/computer/file/embedded_program/docking/simple(src)
program = docking_program
/obj/machinery/embedded_controller/radio/simple_docking_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/datum/computer/file/embedded_program/docking/simple/docking_program = program // Cast to proper type
data = list(
"docking_status" = docking_program.get_docking_status(),
@@ -28,11 +24,8 @@
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/simple_docking_controller/Topic(href, href_list)
if(..())
return 1
usr.set_machine(src)
src.add_fingerprint(usr)
if((. = ..()))
return
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
@@ -44,8 +37,7 @@
if(clean)
program.receive_user_command(href_list["command"])
return 0
return
//A docking controller program for a simple door based docking port
/datum/computer/file/embedded_program/docking/simple
@@ -76,6 +68,7 @@
..(signal, receive_method, receive_param)
/datum/computer/file/embedded_program/docking/simple/receive_user_command(command)
. = TRUE
switch(command)
if("force_door")
if (override_enabled)
@@ -88,7 +81,8 @@
disable_override()
else
enable_override()
else
. = FALSE
/datum/computer/file/embedded_program/docking/simple/proc/signal_door(var/command)
var/datum/signal/signal = new