PCUs and SR Connected Computers (#4040)

* PCU and Connected Consoles

* Clean this up
This commit is contained in:
Zandario
2022-05-14 06:45:56 -07:00
committed by GitHub
parent 843e7e15fe
commit 03aacd017e
39 changed files with 617 additions and 462 deletions
@@ -1,13 +1,20 @@
var/global/file_uid = 0
/datum/computer_file/
var/filename = "NewFile" // Placeholder. No spacebars
var/filetype = "XXX" // File full names are [filename].[filetype] so like NewFile.XXX in this case
var/size = 1 // File size in GQ. Integers only!
var/obj/item/computer_hardware/hard_drive/holder // Holder that contains this file.
var/unsendable = 0 // Whether the file may be sent to someone via NTNet transfer or other means.
var/undeletable = 0 // Whether the file may be deleted. Setting to 1 prevents deletion/renaming/etc.
var/uid // UID of this file
/datum/computer_file
/// Placeholder. No spacebars
var/filename = "NewFile"
/// File full names are [filename].[filetype] so like NewFile.XXX in this case.
var/filetype = "XXX"
/// File size in GQ. Integers only!
var/size = 1
/// Holder that contains this file.
var/obj/item/computer_hardware/hard_drive/holder
/// Whether the file may be sent to someone via NTNet transfer or other means.
var/unsendable = FALSE
/// Whether the file may be deleted. Setting to 1 prevents deletion/renaming/etc.
var/undeletable = FALSE
/// UID of this file.
var/uid
/datum/computer_file/New()
..()
@@ -25,7 +32,7 @@ var/global/file_uid = 0
holder = null
..()
// Returns independent copy of this file.
/// Returns independent copy of this file.
/datum/computer_file/proc/clone(var/rename = 0)
var/datum/computer_file/temp = new type
temp.unsendable = unsendable
@@ -36,4 +43,4 @@ var/global/file_uid = 0
else
temp.filename = filename
temp.filetype = filetype
return temp
return temp
@@ -1,17 +1,22 @@
// /data/ files store data in string format.
// They don't contain other logic for now.
/**
* /data/ files store data in string format.
* They don't contain other logic for now.
*/
/datum/computer_file/data
var/stored_data = "" // Stored data in string format.
filetype = "DAT"
/// Whether the user will be reminded that the file probably shouldn't be edited.
var/do_not_edit = 0
/// Stored data in string format.
var/stored_data = ""
/// The file size of this bit of data.
var/block_size = 250
var/do_not_edit = 0 // Whether the user will be reminded that the file probably shouldn't be edited.
/datum/computer_file/data/clone()
var/datum/computer_file/data/temp = ..()
temp.stored_data = stored_data
return temp
// Calculates file size from amount of characters in saved string
/// Calculates file size from amount of characters in saved string
/datum/computer_file/data/proc/calculate_size()
size = max(1, round(length(stored_data) / block_size))
@@ -1,13 +1,20 @@
// /data/ files store data in string format.
// They don't contain other logic for now.
/**
* /data/ files store data in string format.
* They don't contain other logic for now.
*/
/datum/computer_file/data/news_article
filetype = "XNML"
filename = "Unknown News Entry"
block_size = 5000 // Results in smaller files
do_not_edit = 1 // Editing the file breaks most formatting due to some HTML tags not being accepted as input from average user.
var/server_file_path // File path to HTML file that will be loaded on server start. Example: '/news_articles/space_magazine_1.html'. Use the /news_articles/ folder!
var/archived // Set to 1 for older stuff
var/cover //filename of cover.
/// Results in smaller files.
block_size = 5000
/// Editing the file breaks most formatting due to some HTML tags not being accepted as input from average user.
do_not_edit = 1
/// File path to HTML file that will be loaded on server start. Example: '/news_articles/space_magazine_1.html'. Use the /news_articles/ folder!
var/server_file_path
/// Set to 1 for older stuff.
var/archived
/// Filename of cover.
var/cover
/datum/computer_file/data/news_article/New(var/load_from_file = 0)
..()
@@ -16,7 +23,7 @@
calculate_size()
// NEWS DEFINITIONS BELOW THIS LINE
//! ## NEWS DEFINITIONS BELOW THIS LINE
/* KEPT HERE AS AN EXAMPLE
/datum/computer_file/data/news_article/space/vol_one
filename = "SPACE Magazine vol. 1"
@@ -1,36 +1,64 @@
// /program/ files are executable programs that do things.
/datum/computer_file/program
filetype = "PRG"
filename = "UnknownProgram" // File name. FILE NAME MUST BE UNIQUE IF YOU WANT THE PROGRAM TO BE DOWNLOADABLE FROM NTNET!
var/required_access = null // List of required accesses to run/download the program.
var/requires_access_to_run = 1 // Whether the program checks for required_access when run.
var/requires_access_to_download = 1 // Whether the program checks for required_access when downloading.
//nanoui
var/datum/nano_module/NM = null // If the program uses NanoModule, put it here and it will be automagically opened. Otherwise implement nano_ui_interact.
var/nanomodule_path = null // Path to nanomodule, make sure to set this if implementing new program.
// t gui
var/datum/tgui_module/TM = null // If the program uses TGUIModule, put it here and it will be automagically opened. Otherwise implement ui_interact.
var/tguimodule_path = null // Path to tguimodule, make sure to set this if implementing new program.
// misc program stuff
var/program_state = PROGRAM_STATE_KILLED// PROGRAM_STATE_KILLED or PROGRAM_STATE_BACKGROUND or PROGRAM_STATE_ACTIVE - specifies whether this program is running.
var/obj/item/modular_computer/computer // Device that runs this program.
var/filedesc = "Unknown Program" // User-friendly name of this program.
var/extended_desc = "N/A" // Short description of this program's function.
var/program_icon_state = null // Program-specific screen icon state
var/program_key_state = "standby_key" // Program-specific keyboard icon state
var/program_menu_icon = "newwin" // Icon to use for program's link in main menu
var/requires_ntnet = 0 // Set to 1 for program to require nonstop NTNet connection to run. If NTNet connection is lost program crashes.
var/requires_ntnet_feature = 0 // Optional, if above is set to 1 checks for specific function of NTNet (currently NTNET_SOFTWAREDOWNLOAD, NTNET_PEERTOPEER, NTNET_SYSTEMCONTROL and NTNET_COMMUNICATION)
var/ntnet_status = 1 // NTNet status, updated every tick by computer running this program. Don't use this for checks if NTNet works, computers do that. Use this for calculations, etc.
var/usage_flags = PROGRAM_ALL // Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_TABLET combination) or PROGRAM_ALL
var/network_destination = null // Optional string that describes what NTNet server/system this program connects to. Used in default logging.
var/available_on_ntnet = 1 // Whether the program can be downloaded from NTNet. Set to 0 to disable.
var/available_on_syndinet = 0 // Whether the program can be downloaded from SyndiNet (accessible via emagging the computer). Set to 1 to enable.
var/computer_emagged = 0 // Set to 1 if computer that's running us was emagged. Computer updates this every Process() tick
var/ui_header = null // Example: "something.gif" - a header image that will be rendered in computer's UI when this program is running at background. Images are taken from /nano/images/status_icons. Be careful not to use too large images!
var/ntnet_speed = 0 // GQ/s - current network connectivity transfer rate
//! File name. FILE NAME MUST BE UNIQUE IF YOU WANT THE PROGRAM TO BE DOWNLOADABLE FROM NTNET!
filename = "UnknownProgram"
/// List of required accesses to run/download the program.
var/required_access = null
/// Whether the program checks for required_access when run.
var/requires_access_to_run = TRUE
/// Whether the program checks for required_access when downloading.
var/requires_access_to_download = TRUE
/datum/computer_file/program/New(var/obj/item/modular_computer/comp = null)
//! ## Nanoui
/// If the program uses NanoModule, put it here and it will be automagically opened. Otherwise implement nano_ui_interact.
var/datum/nano_module/NM = null
/// Path to nanomodule, make sure to set this if implementing new program.
var/nanomodule_path = null
//! ## TGUI
/// If the program uses TGUIModule, put it here and it will be automagically opened. Otherwise implement ui_interact.
var/datum/tgui_module/TM = null
/// Path to tguimodule, make sure to set this if implementing new program.
var/tguimodule_path = null
//! ## Misc Program Stuff
/// PROGRAM_STATE_KILLED or PROGRAM_STATE_BACKGROUND or PROGRAM_STATE_ACTIVE - specifies whether this program is running.
var/program_state = PROGRAM_STATE_KILLED
/// Device that runs this program.
var/obj/item/modular_computer/computer
/// User-friendly name of this program.
var/filedesc = "Unknown Program"
/// Short description of this program's function.
var/extended_desc = "N/A"
/// Program-specific screen icon state.
var/program_icon_state = null
/// Program-specific keyboard icon state.
var/program_key_state = "standby_key"
/// Icon to use for program's link in main menu.
var/program_menu_icon = "newwin"
/// Set to TRUE for program to require nonstop NTNet connection to run. If NTNet connection is lost program crashes.
var/requires_ntnet = FALSE
/// Optional, if above is set to TRUE checks for specific function of NTNet (currently NTNET_SOFTWAREDOWNLOAD, NTNET_PEERTOPEER, NTNET_SYSTEMCONTROL and NTNET_COMMUNICATION)
var/requires_ntnet_feature = FALSE
/// NTNet status, updated every tick by computer running this program. Don't use this for checks if NTNet works, computers do that. Use this for calculations, etc.
var/ntnet_status = 1
/// Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_TABLET combination) or PROGRAM_ALL
var/usage_flags = PROGRAM_ALL
/// Optional string that describes what NTNet server/system this program connects to. Used in default logging.
var/network_destination = null
/// Whether the program can be downloaded from NTNet. Set to FALSE to disable.
var/available_on_ntnet = TRUE
/// Whether the program can be downloaded from SyndiNet (accessible via emagging the computer). Set to TRUE to enable.
var/available_on_syndinet = FALSE
/// Set to TRUE if computer that's running us was emagged. Computer updates this every Process() tick
var/computer_emagged = FALSE
/// Example: "something.gif" - a header image that will be rendered in computer's UI when this program is running at background. Images are taken from /nano/images/status_icons. Be careful not to use too large images!
var/ui_header = null
/// GQ/s - current network connectivity transfer rate.
var/ntnet_speed = 0
/datum/computer_file/program/New(obj/item/modular_computer/comp = null)
..()
if(comp && istype(comp))
computer = comp
@@ -53,33 +81,33 @@
temp.usage_flags = usage_flags
return temp
// Relays icon update to the computer.
/// Relays icon update to the computer.
/datum/computer_file/program/proc/update_computer_icon()
if(computer)
computer.update_icon()
// Attempts to create a log in global ntnet datum. Returns 1 on success, 0 on fail.
/datum/computer_file/program/proc/generate_network_log(var/text)
/// Attempts to create a log in global ntnet datum. Returns TRUE on success, FALSE on fail.
/datum/computer_file/program/proc/generate_network_log(text)
if(computer)
return computer.add_log(text)
return 0
return FALSE
/datum/computer_file/program/proc/is_supported_by_hardware(var/hardware_flag = 0, var/loud = 0, var/mob/user = null)
/datum/computer_file/program/proc/is_supported_by_hardware(hardware_flag = 0, loud = FALSE, mob/user = null)
if(!(hardware_flag & usage_flags))
if(loud && computer && user)
to_chat(user, "<span class='warning'>\The [computer] flashes: \"Hardware Error - Incompatible software\".</span>")
return 0
return 1
to_chat(user, SPAN_WARNING("\The [computer] flashes: \"Hardware Error - Incompatible software\"."))
return FALSE
return TRUE
/datum/computer_file/program/proc/get_signal(var/specific_action = 0)
/datum/computer_file/program/proc/get_signal(specific_action = 0)
if(computer)
return computer.get_ntnet_status(specific_action)
return 0
return FALSE
// Called by Process() on device that runs us, once every tick.
/// Called by Process() on device that runs us, once every tick.
/datum/computer_file/program/proc/process_tick()
update_netspeed()
return 1
return TRUE
/datum/computer_file/program/proc/update_netspeed()
ntnet_speed = 0
@@ -91,44 +119,50 @@
if(3)
ntnet_speed = NTNETSPEED_ETHERNET
// Check if the user can run program. Only humans can operate computer. Automatically called in run_program()
// User has to wear their ID or have it inhand for ID Scan to work.
// Can also be called manually, with optional parameter being access_to_check to scan the user's ID
/datum/computer_file/program/proc/can_run(var/mob/living/user, var/loud = 0, var/access_to_check)
/**
* Check if the user can run program. Only humans can operate computer. Automatically called in run_program()
* User has to wear their ID or have it inhand for ID Scan to work.
* Can also be called manually, with optional parameter being access_to_check to scan the user's ID
*/
/datum/computer_file/program/proc/can_run(mob/living/user, loud = FALSE, access_to_check)
// Defaults to required_access
if(!access_to_check)
access_to_check = required_access
if(!access_to_check) // No required_access, allow it.
return 1
return TRUE
// Admin override - allows operation of any computer as aghosted admin, as if you had any required access.
if(istype(user, /mob/observer/dead) && check_rights(R_ADMIN, 0, user))
return 1
return TRUE
if(!istype(user))
return 0
return FALSE
var/obj/item/card/id/I = user.GetIdCard()
if(!I)
if(loud)
to_chat(user, "<span class='notice'>\The [computer] flashes an \"RFID Error - Unable to scan ID\" warning.</span>")
return 0
to_chat(user, SPAN_NOTICE("\The [computer] flashes an \"RFID Error - Unable to scan ID\" warning."))
return FALSE
if(access_to_check in I.access)
return 1
return TRUE
else if(loud)
to_chat(user, "<span class='notice'>\The [computer] flashes an \"Access Denied\" warning.</span>")
to_chat(user, SPAN_NOTICE("\The [computer] flashes an \"Access Denied\" warning."))
// This attempts to retrieve header data for NanoUIs. If implementing completely new device of different type than existing ones
// always include the device here in this proc. This proc basically relays the request to whatever is running the program.
/**
* This attempts to retrieve header data for NanoUIs. If implementing completely new device of different type than existing ones
* always include the device here in this proc. This proc basically relays the request to whatever is running the program.
*/
/datum/computer_file/program/proc/get_header_data()
if(computer)
return computer.get_header_data()
return list()
// This is performed on program startup. May be overriden to add extra logic. Remember to include ..() call. Return 1 on success, 0 on failure.
// When implementing new program based device, use this to run the program.
/datum/computer_file/program/proc/run_program(var/mob/living/user)
/**
* This is performed on program startup. May be overriden to add extra logic. Remember to include ..() call. Return 1 on success, 0 on failure.
* When implementing new program based device, use this to run the program.
*/
/datum/computer_file/program/proc/run_program(mob/living/user)
if(can_run(user, 1) || !requires_access_to_run)
computer.active_program = src
if(nanomodule_path)
@@ -141,11 +175,11 @@
if(requires_ntnet && network_destination)
generate_network_log("Connection opened to [network_destination].")
program_state = PROGRAM_STATE_ACTIVE
return 1
return 0
return TRUE
return FALSE
// Use this proc to kill the program. Designed to be implemented by each program if it requires on-quit logic, such as the NTNRC client.
/datum/computer_file/program/proc/kill_program(var/forced = 0)
/// Use this proc to kill the program. Designed to be implemented by each program if it requires on-quit logic, such as the NTNRC client.
/datum/computer_file/program/proc/kill_program(forced = FALSE)
program_state = PROGRAM_STATE_KILLED
if(network_destination)
generate_network_log("Connection to [network_destination] closed.")
@@ -154,37 +188,42 @@
SStgui.close_uis(TM)
qdel(TM)
TM = null
return 1
return TRUE
// This is called every tick when the program is enabled. Ensure you do parent call if you override it. If parent returns 1 continue with UI initialisation.
// It returns 0 if it can't run or if NanoModule was used instead. I suggest using NanoModules where applicable.
/datum/computer_file/program/nano_ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/**
* This is called every tick when the program is enabled. Ensure you do parent call if you override it. If parent returns TRUE continue with UI initialisation.
* It returns FALSE if it can't run or if NanoModule was used instead. I suggest using NanoModules where applicable.
*/
/datum/computer_file/program/nano_ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, force_open = TRUE)
if(program_state != PROGRAM_STATE_ACTIVE) // Our program was closed. Close the ui if it exists.
if(ui)
ui.close()
return computer.nano_ui_interact(user)
if(istype(NM))
NM.nano_ui_interact(user, ui_key, null, force_open)
return 0
return FALSE
if(istype(TM))
TM.ui_interact(user)
return 0
return 1
return FALSE
return TRUE
// CONVENTIONS, READ THIS WHEN CREATING NEW PROGRAM AND OVERRIDING THIS PROC:
// Topic calls are automagically forwarded from NanoModule this program contains.
// Calls beginning with "PRG_" are reserved for programs handling.
// Calls beginning with "PC_" are reserved for computer handling (by whatever runs the program)
// ALWAYS INCLUDE PARENT CALL ..() OR DIE IN FIRE.
/**
*! CONVENTIONS, READ THIS WHEN CREATING NEW PROGRAM AND OVERRIDING THIS PROC:
*
* Topic calls are automagically forwarded from NanoModule this program contains.
* Calls beginning with "PRG_" are reserved for programs handling.
* Calls beginning with "PC_" are reserved for computer handling (by whatever runs the program)
*
*! ALWAYS INCLUDE PARENT CALL ..() OR DIE IN FIRE.
*/
/datum/computer_file/program/Topic(href, href_list)
if(..())
return 1
if(computer)
return computer.Topic(href, href_list)
// Relays the call to nano module, if we have one
/datum/computer_file/program/proc/check_eye(var/mob/user)
/// Relays the call to nano module, if we have one
/datum/computer_file/program/proc/check_eye(mob/user)
if(NM)
return NM.check_eye(user)
else
@@ -197,25 +236,28 @@
return TRUE
/datum/nano_module/program
/// Program-Based computer program that runs this nano module. Defaults to null.
var/datum/computer_file/program/program = null
//available_to_ai = FALSE
var/datum/computer_file/program/program = null // Program-Based computer program that runs this nano module. Defaults to null.
/datum/nano_module/program/New(var/host, var/topic_manager, var/program)
/datum/nano_module/program/New(host, topic_manager, program)
..()
src.program = program
/datum/topic_manager/program
var/datum/program
/datum/topic_manager/program/New(var/datum/program)
/datum/topic_manager/program/New(datum/program)
..()
src.program = program
// Calls forwarded to PROGRAM itself should begin with "PRG_"
// Calls forwarded to COMPUTER running the program should begin with "PC_"
/**
* Calls forwarded to PROGRAM itself should begin with "PRG_"
* Calls forwarded to COMPUTER running the program should begin with "PC_"
*/
/datum/topic_manager/program/Topic(href, href_list)
return program && program.Topic(href, href_list)
/datum/computer_file/program/proc/relaymove(var/mob/M, direction)
/datum/computer_file/program/proc/relaymove(mob/M, direction)
if(NM)
return NM.relaymove(M, direction)
@@ -1,18 +1,20 @@
// Events are sent to the program by the computer.
// Always include a parent call when overriding an event.
/**
* Events are sent to the program by the computer.
* Always include a parent call when overriding an event.
*/
// Called when the ID card is removed from computer. ID is removed AFTER this proc.
/datum/computer_file/program/proc/event_idremoved(var/background)
/// Called when the ID card is removed from computer. ID is removed AFTER this proc.
/datum/computer_file/program/proc/event_idremoved(background)
return
// Called when the computer fails due to power loss. Override when program wants to specifically react to power loss.
/datum/computer_file/program/proc/event_powerfailure(var/background)
/// Called when the computer fails due to power loss. Override when program wants to specifically react to power loss.
/datum/computer_file/program/proc/event_powerfailure(background)
kill_program(1)
// Called when the network connectivity fails. Computer does necessary checks and only calls this when requires_ntnet_feature and similar variables are not met.
/datum/computer_file/program/proc/event_networkfailure(var/background)
/// Called when the network connectivity fails. Computer does necessary checks and only calls this when requires_ntnet_feature and similar variables are not met.
/datum/computer_file/program/proc/event_networkfailure(background)
kill_program(1)
if(background)
computer.visible_message("<span class='warning'>\The [computer]'s screen displays an error: \"Network connectivity lost - process [filename].[filetype] (PID [rand(100,999)]) terminated.\"</span>")
computer.visible_message(SPAN_WARNING("\The [computer]'s screen displays an error: \"Network connectivity lost - process [filename].[filetype] (PID [rand(100,999)]) terminated.\""))
else
computer.visible_message("<span class='warning'>\The [computer]'s screen briefly freezes and then shows: \"FATAL NETWORK ERROR - NTNet connection lost. Please try again later. If problem persists, please contact your system administrator.\"</span>")
computer.visible_message(SPAN_WARNING("\The [computer]'s screen briefly freezes and then shows: \"FATAL NETWORK ERROR - NTNet connection lost. Please try again later. If problem persists, please contact your system administrator.\""))