mirror of
https://github.com/goonstation/goonstation-2016.git
synced 2026-07-15 02:52:18 +01:00
Initial Commit
This commit is contained in:
@@ -0,0 +1,782 @@
|
||||
/datum/computer/file/terminal_program/os/main_os/no_login
|
||||
setup_needs_authentication = 0
|
||||
|
||||
/datum/computer/file/terminal_program/os/main_os
|
||||
name = "ThinkDOS"
|
||||
size = 12
|
||||
var/tmp/datum/computer/folder/current_folder = null
|
||||
var/tmp/datum/computer/file/clipboard = null
|
||||
var/tmp/datum/computer/file/text/command_log = null
|
||||
var/tmp/datum/computer/file/record/help_lib = null
|
||||
var/tmp/datum/computer/file/user_data/active_account = null
|
||||
var/echo_input = 1
|
||||
var/log_errors = 1
|
||||
var/list/peripherals = list()
|
||||
var/authenticated = null //Is anyone logged in?
|
||||
|
||||
var/setup_version_name = "ThinkDOS 0.7.2"
|
||||
var/setup_needs_authentication = 1 //Do we need to present an ID to use this?
|
||||
//Setup for data logging
|
||||
#define SETUP_LOG_DIRECTORY "logs"
|
||||
#define SETUP_LOG_FILENAME "syslog"
|
||||
//Setup for help library
|
||||
#define SETUP_HELP_FILEPATH "/logs/helplib"
|
||||
//Where to put user account data.
|
||||
#define SETUP_ACC_DIRECTORY "logs"
|
||||
#define SETUP_ACC_FILENAME "sysusr"
|
||||
|
||||
disposing()
|
||||
peripherals = null
|
||||
current_folder = null
|
||||
clipboard = null
|
||||
command_log = null
|
||||
help_lib = null
|
||||
active_account = null
|
||||
|
||||
..()
|
||||
|
||||
input_text(text)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/list/command_list = parse_string(text)
|
||||
var/command = command_list[1]
|
||||
command_list -= command_list[1] //Remove the command we are now processing.
|
||||
|
||||
if(src.echo_input)
|
||||
src.print_text(strip_html(text))
|
||||
|
||||
print_to_log(text) //print to log strips html as it logs, no need to do it here!!
|
||||
|
||||
if(!current_folder)
|
||||
current_folder = src.holding_folder
|
||||
|
||||
if(!src.authenticated && src.setup_needs_authentication)
|
||||
switch(lowertext(command))
|
||||
if("login","logon")
|
||||
if (issilicon(usr) && !isghostdrone(usr))
|
||||
src.system_login("AIUSR","Station AI", null, 1)
|
||||
//src.print_text("Authorization Accepted.<br>Welcome, AIUSR!<br><b>Current Folder: [current_folder.name]</b>")
|
||||
//src.authenticated = "AI"
|
||||
//src.print_to_log("LOGIN: AIUSR | \[Station AI]")
|
||||
else
|
||||
var/obj/item/peripheral/scanner = find_peripheral("ID_SCANNER")
|
||||
if(!scanner)
|
||||
src.print_text("<b>Error:</b> No ID scanner detected.")
|
||||
return
|
||||
var/datum/signal/login_result = src.peripheral_command("scan_card", null, "\ref[scanner]")
|
||||
if(istype(login_result))
|
||||
system_login(login_result.data["registered"], login_result.data["assignment"], login_result.data["access"])
|
||||
else if(login_result == "nocard")
|
||||
src.print_text("<b>Error:</b> No ID card inserted.")
|
||||
|
||||
else
|
||||
src.print_text("Login required. Please use \"login\" command.")
|
||||
|
||||
else
|
||||
switch(lowertext(command))
|
||||
if("cls", "home") //Clear temp var of master computer3
|
||||
src.master.temp = null
|
||||
src.master.temp_add = "Screen cleared.<br>" //Okay perhaps not entirely clear.
|
||||
src.master.updateUsrDialog()
|
||||
|
||||
if("dir", "catalog", "ls") //Show contents of current folder
|
||||
|
||||
src.print_text("<b>Files on [current_folder.holder.title] - Used: \[[src.current_folder.holder.file_used]/[src.current_folder.holder.file_amount]\]</b>")
|
||||
src.print_text("<b>Current Folder: [current_folder.name]</b>")
|
||||
|
||||
var/dir_text = null
|
||||
for(var/datum/computer/P in current_folder.contents)
|
||||
if(P == src)
|
||||
dir_text += "[src.name] - SYSTEM - \[Size: [src.size]]<br>"
|
||||
continue
|
||||
|
||||
dir_text += "[P.name] - [(istype(P,/datum/computer/folder)) ? "FOLDER" : "[P:extension]"] - \[Size: [P.size]]<br>"
|
||||
|
||||
if(dir_text)
|
||||
src.print_text(dir_text)
|
||||
|
||||
if("cd", "chdir") //Attempts to set current folder to directory arg1
|
||||
var/dir_string = null
|
||||
if(command_list.len)
|
||||
dir_string = dd_list2text(command_list, " ")
|
||||
else
|
||||
src.print_text("<b>Syntax:</b> \"cd \[directory string]\" String is relative to current directory.")
|
||||
return
|
||||
|
||||
if(dir_string == "/") //If it is seriously just /, act like the root command
|
||||
src.current_folder = src.current_folder.holder.root
|
||||
src.print_text("<b>Current Directory is now [current_folder.name]</b>")
|
||||
return
|
||||
|
||||
var/datum/computer/folder/new_dir = parse_directory(dir_string, src.current_folder)
|
||||
if(!new_dir || !istype(new_dir))
|
||||
src.print_error_text("<b>Error:</b> Invalid directory or path.")
|
||||
return
|
||||
else
|
||||
src.current_folder = new_dir
|
||||
src.print_text("<b>Current Directory is now [new_dir.name]</b>")
|
||||
|
||||
if("root") //Sets current folder to root of current drive
|
||||
if(src.current_folder && src.current_folder.holder.root)
|
||||
src.current_folder = src.current_folder.holder.root
|
||||
src.print_text("<b>Current Directory is now [current_folder.name]</b>")
|
||||
|
||||
if("run") //Runs /datum/computer/file/terminal_program with name arg1
|
||||
var/prog_name = null
|
||||
if(command_list.len)
|
||||
prog_name = dd_list2text(command_list, " ")
|
||||
else
|
||||
src.print_text("<b>Syntax:</b> \"run \[program filepath].\" Path is relative to current directory.")
|
||||
return
|
||||
|
||||
var/datum/computer/file/terminal_program/to_run = src.parse_file_directory(prog_name, current_folder)
|
||||
|
||||
if(isnull(to_run) || !istype(to_run) || istype(to_run, /datum/computer/file/terminal_program/os))
|
||||
src.print_error_text("<b>Error:</b> Invalid file name or type.")
|
||||
else
|
||||
src.master.run_program(to_run)
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
|
||||
if("makedir","mkdir") //Creates folder in current directory with name arg1
|
||||
var/new_folder_name = strip_html(dd_list2text(command_list, " "))
|
||||
new_folder_name = copytext(new_folder_name, 1, 16)
|
||||
|
||||
if(!new_folder_name)
|
||||
src.print_text("<b>Syntax:</b> \"makedir \[new directory name]\"")
|
||||
return
|
||||
|
||||
if(src.get_computer_datum(new_folder_name, current_folder))
|
||||
src.print_error_text("<b>Error:</b> Directory name in use.")
|
||||
return
|
||||
|
||||
if(is_name_invalid(new_folder_name))
|
||||
src.print_error_text("<b>Error:</b> Invalid character in name.")
|
||||
return
|
||||
|
||||
var/datum/computer/F = new /datum/computer/folder
|
||||
F.name = new_folder_name
|
||||
if(!current_folder.add_file(F))
|
||||
src.print_error_text("<b>Error:</b> Unable to create new directory.")
|
||||
//qdel(F)
|
||||
F.dispose()
|
||||
else
|
||||
src.print_text("New directory created.")
|
||||
|
||||
if("rename","ren") //Sets name of file arg1 to arg2
|
||||
var/to_rename = null
|
||||
var/new_name = null
|
||||
if(command_list.len >= 2)
|
||||
to_rename = command_list[1]
|
||||
new_name = command_list[2]
|
||||
new_name = copytext(strip_html(new_name), 1, 16)
|
||||
|
||||
if(!to_rename || !new_name)
|
||||
src.print_text("<b>Syntax:</b> \"rename \[name of target] \[new name]\"")
|
||||
return
|
||||
|
||||
if(is_name_invalid(new_name))
|
||||
src.print_error_text("<b>Error:</b> Invalid character in name.")
|
||||
return
|
||||
|
||||
var/datum/computer/target = get_computer_datum(to_rename, current_folder)
|
||||
|
||||
if(!target || !istype(target))
|
||||
src.print_error_text("<b>Error:</b> File not found.")
|
||||
return
|
||||
|
||||
var/datum/computer/check_existing = get_computer_datum(new_name, src.current_folder)
|
||||
if(check_existing && check_existing != target )
|
||||
src.print_error_text("<b>Error:</b> Name in use.")
|
||||
return
|
||||
|
||||
target.name = new_name
|
||||
src.print_text("Done.")
|
||||
|
||||
if("title") //Set the title var of the current drive.
|
||||
var/new_name = null
|
||||
if(command_list.len)
|
||||
new_name = strip_html(dd_list2text(command_list, " "))
|
||||
new_name = copytext(new_name, 1, 16)
|
||||
else
|
||||
src.print_text("<b>Syntax:</b> \"title \[title name]\" Set name of active drive to given title.")
|
||||
return
|
||||
|
||||
if(src.current_folder.holder && !src.current_folder.holder.read_only)
|
||||
src.current_folder.holder.title = new_name
|
||||
src.print_text("Drive title set to <b>[new_name]</b>.")
|
||||
else
|
||||
src.print_error_text("<b>Error:</b> Unable to set title string.")
|
||||
|
||||
if("delete", "del","era","erase","rm") //Deletes file arg1
|
||||
var/file_name = null
|
||||
if(command_list.len)
|
||||
file_name = ckey(dd_list2text(command_list, " "))
|
||||
else
|
||||
src.print_text("<b>Syntax:</b> \"del \[file name].\" File must be in current directory.")
|
||||
return
|
||||
|
||||
var/datum/computer/target = get_computer_datum(file_name, current_folder)
|
||||
if(!target || !istype(target))
|
||||
src.print_error_text("<b>Error:</b> File not found.")
|
||||
return
|
||||
|
||||
if(target == src)
|
||||
src.print_error_text("<b>Error:</b> Access denied.")
|
||||
return
|
||||
|
||||
if(src.master.delete_file(target))
|
||||
src.print_text("File deleted.")
|
||||
else
|
||||
src.print_error_text("<b>Error:</b> Unable to delete file.")
|
||||
|
||||
if("copy","cp") //Sets file arg1 to be copied
|
||||
var/file_name = null
|
||||
if(command_list.len)
|
||||
file_name = ckey(dd_list2text(command_list, " "))
|
||||
else
|
||||
src.print_text("<b>Syntax:</b> \"copy \[file name].\" File must be in current directory.")
|
||||
return
|
||||
|
||||
var/datum/computer/target = get_file_name(file_name, current_folder)
|
||||
if(!target || !istype(target))
|
||||
src.print_error_text("<b>Error:</b> File not found.")
|
||||
return
|
||||
|
||||
src.clipboard = target
|
||||
src.print_text("File marked.")
|
||||
|
||||
if("paste","ps") //Pastes clipboard file with name arg1
|
||||
var/pasted_name = strip_html(dd_list2text(command_list, " "))
|
||||
pasted_name = copytext(pasted_name, 1, 16)
|
||||
|
||||
if(!pasted_name)
|
||||
src.print_text("<b>Syntax:</b> \"paste \[new file name].\" File is placed in current directory.")
|
||||
return
|
||||
|
||||
if(!src.clipboard || !src.clipboard.holder || !(src.clipboard.holder in src.master.contents))
|
||||
src.print_error_text("<b>Error:</b> Unable to locate marked file.")
|
||||
return
|
||||
|
||||
if(!istype(src.clipboard))
|
||||
src.print_error_text("<b>Error:</b> Invalid or corrupt file type.")
|
||||
return
|
||||
|
||||
if(get_computer_datum(pasted_name, src.current_folder))
|
||||
src.print_error_text("<b>Error:</b> Name in use.")
|
||||
return
|
||||
|
||||
if(is_name_invalid(pasted_name))
|
||||
src.print_error_text("<b>Error:</b> Invalid character in name.")
|
||||
return
|
||||
|
||||
if(src.clipboard.copy_file_to_folder(current_folder, pasted_name))
|
||||
src.print_text("Done")
|
||||
else
|
||||
src.print_error_text("<b>Error:</b> Unable to paste file (Drive is full?)")
|
||||
|
||||
if("drive","drv") //Sets current folder to root of drive arg1
|
||||
var/argument1 = null
|
||||
if(command_list.len)
|
||||
argument1 = command_list[1]
|
||||
|
||||
var/list/drives = src.get_loaded_drives()
|
||||
|
||||
if(!ckey(argument1))
|
||||
var/valid_string = english_list(drives, "None", " ")
|
||||
src.print_text("<b>Syntax:</b> \"drive \[drive id].\"<br><b>Valid IDs:</b> ([valid_string]).")
|
||||
return
|
||||
|
||||
var/obj/item/disk/data/to_load = drives[argument1]
|
||||
if(to_load && istype(to_load) && to_load.root)
|
||||
src.current_folder = to_load.root
|
||||
src.print_text("<b>Current Drive is now [current_folder.holder.title]</b>")
|
||||
else
|
||||
src.print_text("<b>Error:</b> Drive invalid.")
|
||||
|
||||
if("initlogs") //Restart logging if log file is deleted or otherwise lost.
|
||||
if(src.command_log)
|
||||
src.print_error_text("<b>Error:</b> Logging is already active.")
|
||||
else
|
||||
if(initialize_logs())
|
||||
src.print_text("Logging re-initialized.")
|
||||
else
|
||||
src.print_error_text("<b>Error:</b> Unable to re-initialize logging.")
|
||||
|
||||
if("help") //Allow access to "helplib" record datum. Should be kept tup to date with system commands, etc
|
||||
if(!src.help_lib || !istype(src.help_lib) || help_lib.disposed)
|
||||
help_lib = null
|
||||
src.print_error_text("<b>Error:</b> Help file missing or corrupt.")
|
||||
return
|
||||
else
|
||||
var/argument1 = "help"
|
||||
if(command_list.len)
|
||||
argument1 = lowertext(command_list[1])
|
||||
|
||||
var/help_string = src.help_lib.fields[argument1]
|
||||
if(help_string)
|
||||
src.print_text("<b>[capitalize(argument1)]</b><br>[help_string]")
|
||||
else
|
||||
src.print_error_text("<b>Error:</b> Invalid field.")
|
||||
|
||||
if("periph","p") //Allow some user interactions with peripheral cards.
|
||||
var/argument1 = null
|
||||
if(command_list.len)
|
||||
argument1 = command_list[1]
|
||||
|
||||
switch(argument1)
|
||||
if("view","v") //View installed cards.
|
||||
src.print_text("<b>Current active peripheral cards:</b>")
|
||||
if(!src.peripherals.len)
|
||||
src.print_text("<center>None loaded.</center>")
|
||||
else
|
||||
for(var/x = 1, x <= src.peripherals.len, x++)
|
||||
var/obj/item/peripheral/P = src.peripherals[x]
|
||||
if(istype(P))
|
||||
var/statdat = P.return_status_text()
|
||||
src.print_text("<b>ID: \[[x]] [P.func_tag]</b><br>Status: [statdat]")
|
||||
else
|
||||
src.peripherals -= P
|
||||
continue
|
||||
|
||||
if("command","c")
|
||||
var/id = 0
|
||||
var/pcommand = null
|
||||
var/sig_filename = null
|
||||
|
||||
if(command_list.len >= 3) //These two args are needed for this mode
|
||||
id = round(text2num(command_list[2]))
|
||||
pcommand = strip_html(command_list[3])
|
||||
|
||||
if(command_list.len >= 4) //Having a signal file is optional, however
|
||||
sig_filename = ckey(command_list[4])
|
||||
|
||||
if(!pcommand) //Check for command first, if they skip it they also don't get the id and it complains about that and aaaa
|
||||
src.print_error_text("Error: Command argument required.")
|
||||
return
|
||||
|
||||
if((!id) || (id > src.peripherals.len) || (id <= 0))
|
||||
src.print_error_text("Error: ID invalid or out of bounds.")
|
||||
return
|
||||
|
||||
var/datum/computer/file/signal/sig = null
|
||||
if(sig_filename)
|
||||
sig = get_file_name(sig_filename, src.current_folder)
|
||||
if(!sig || (!istype(sig) && !istype(sig, /datum/computer/file/record)))
|
||||
src.print_error_text("Error: Signal file missing or invalid.")
|
||||
return
|
||||
|
||||
src.print_text("Command: <b>ID:</b> [id] <b>COM:</b> [pcommand]")
|
||||
var/datum/signal/signal = get_free_signal()//new
|
||||
//signal.encryption = "\ref[src.peripherals[id]]"
|
||||
if(sig)
|
||||
if (istype(sig,/datum/computer/file/record))
|
||||
var/datum/computer/file/record/sigrec = sig
|
||||
for (var/entry in sigrec.fields)
|
||||
var/equalpos = findtext("=", entry)
|
||||
if (equalpos)
|
||||
signal.data["[copytext(entry, 1, equalpos)]"] = "[copytext(entry, equalpos)]"
|
||||
else
|
||||
if (!isnull(sigrec.fields[entry]))
|
||||
signal.data["[entry]"] = sigrec.fields[entry]
|
||||
else
|
||||
signal.data += entry
|
||||
|
||||
if (command_list.len > 4)
|
||||
signal.data_file = get_file_name(ckey(command_list[5]), src.current_folder)
|
||||
if (istype(signal.data_file, /datum/computer/file))
|
||||
signal.data_file = signal.data_file.copy_file()
|
||||
else
|
||||
signal.data_file = null
|
||||
|
||||
else
|
||||
signal.data = sig.data.Copy()
|
||||
if(sig.data_file) //For file transfers!
|
||||
var/datum/computer/file/tempfile = sig.data_file.copy_file()
|
||||
if(tempfile && istype(tempfile))
|
||||
signal.data_file = tempfile
|
||||
var/result = peripheral_command(pcommand, signal, "\ref[src.peripherals[id]]")
|
||||
if (result != 0)
|
||||
if (result == 1)
|
||||
src.print_text("Error: Command unsuccessful.")
|
||||
else if (istext(result))
|
||||
src.print_text("Response: [result]")
|
||||
|
||||
else
|
||||
src.print_text("Syntax: \"periph \[mode] \[ID] \[command] \[signal file]\"<br><b>Valid modes:</b> (view, command)")
|
||||
|
||||
if("backprog", "bp") //Allow the user to manage programs chilling in the background
|
||||
var/argument1 = null
|
||||
if(command_list.len)
|
||||
argument1 = command_list[1]
|
||||
|
||||
switch(argument1)
|
||||
if("view", "v") //View processing programs (other than us)
|
||||
src.print_text("<b>Current programs in memory:</b>")
|
||||
if(!src.master.processing_programs.len) //This should never happen as we should be in it.
|
||||
src.print_text("<center>None detected.</center>")
|
||||
else
|
||||
for(var/x = 1, x <= src.master.processing_programs.len, x++)
|
||||
var/datum/computer/file/terminal_program/T = src.master.processing_programs[x]
|
||||
if(istype(T))
|
||||
src.print_text("<b>ID: \[[x]]</b> [(T == src) ? "SYSTEM" : T.name]")
|
||||
|
||||
if("kill", "k") //Okay now that we know them it is time to BE RID OF THEM
|
||||
var/target_id = 0
|
||||
if(command_list.len >= 2)
|
||||
target_id = round(text2num(command_list[2]))
|
||||
else
|
||||
src.print_error_text("Target ID Required.")
|
||||
return
|
||||
|
||||
if((!target_id) || (target_id > src.master.processing_programs.len) || (target_id <= 0))
|
||||
src.print_error_text("<b>Error:</b> ID invalid or out of bounds.")
|
||||
return
|
||||
|
||||
var/datum/computer/file/terminal_program/target = src.master.processing_programs[target_id]
|
||||
if(!target || !istype(target) || target == src) //No terminating ourselves!!
|
||||
src.print_error_text("<b>Error:</b> Invalid Target.")
|
||||
return
|
||||
|
||||
src.master.unload_program(target)
|
||||
src.print_text("Program killed.")
|
||||
|
||||
if("switch", "s")
|
||||
var/target_id = 0
|
||||
if(command_list.len >= 2)
|
||||
target_id = round(text2num(command_list[2]))
|
||||
else
|
||||
src.print_error_text("Target ID Required.")
|
||||
return
|
||||
|
||||
if((!target_id) || (target_id > src.master.processing_programs.len) || (target_id <= 0))
|
||||
src.print_error_text("<b>Error:</b> ID invalid or out of bounds.")
|
||||
return
|
||||
|
||||
var/datum/computer/file/terminal_program/target = src.master.processing_programs[target_id]
|
||||
if(!target || !istype(target) || target == src || istype(target, /datum/computer/file/terminal_program/os)) //No re-running ourselves!!
|
||||
src.print_error_text("<b>Error:</b> Invalid Target.")
|
||||
return
|
||||
|
||||
src.print_text("Switching to target...")
|
||||
src.master.run_program(target)
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
|
||||
|
||||
else
|
||||
src.print_text("<b>Syntax:</b> \"backprog \[mode] \[ID]\"<br><b>Valid modes:</b> (view, kill, switch)")
|
||||
|
||||
|
||||
if("print") //Print text arg1 to screen.
|
||||
var/new_text = strip_html(dd_list2text(command_list, " "))
|
||||
if(new_text)
|
||||
src.print_text(new_text)
|
||||
else
|
||||
src.print_text("<b>Syntax:</b> \"print \[text to be printed]\"")
|
||||
|
||||
if("goonsay") //Display text arg1 along with goonsay ascii
|
||||
var/goon = {" __________<br>
|
||||
(--\[ .]-\[ .] /<br>
|
||||
(_______0__)<br>
|
||||
"}
|
||||
|
||||
var/anger_text = "A clown? On a space station? what"
|
||||
if(istype(command_list) && (command_list.len > 0))
|
||||
anger_text = strip_html(dd_list2text(command_list, " "))
|
||||
|
||||
src.print_text("<tt>[anger_text]<br>[goon]</tt>")
|
||||
|
||||
/*
|
||||
if("echo") //Determine if entered commands are printed to screen
|
||||
var/argument1 = null
|
||||
if(command_list.len)
|
||||
argument1 = command_list[1]
|
||||
|
||||
switch(argument1)
|
||||
if("on","ON")
|
||||
src.echo_input = 1
|
||||
|
||||
if("off","OFF")
|
||||
src.echo_input = 0
|
||||
|
||||
else
|
||||
src.echo_input = !src.echo_input
|
||||
|
||||
src.print_text("Input Echo is now <b>[src.echo_input ? "ON" : "OFF"]</b>")
|
||||
*/
|
||||
if("user") //Show current user identfication data
|
||||
if(!src.setup_needs_authentication)
|
||||
src.print_error_text("Account system inactive.")
|
||||
return
|
||||
|
||||
if(!src.active_account)
|
||||
src.print_error_text("<b>Error:</b> Unable to find account file.")
|
||||
return
|
||||
|
||||
src.print_text("Current User: [src.active_account.registered]<br>Rank: [src.active_account.assignment]")
|
||||
|
||||
if("logout","logoff") //Log out if we are currently logged in.
|
||||
if(!setup_needs_authentication || !src.authenticated)
|
||||
src.print_error_text("Account system inactive.")
|
||||
return
|
||||
else
|
||||
src.print_to_log("<b>LOGOUT:</b> [src.authenticated]",0)
|
||||
src.authenticated = null
|
||||
src.active_account = null
|
||||
src.master.temp = null
|
||||
src.echo_input = 1
|
||||
|
||||
//Kill off any background programs that may be running.
|
||||
for(var/datum/computer/file/terminal_program/T in src.master.processing_programs)
|
||||
if(T == src)
|
||||
continue
|
||||
|
||||
src.master.unload_program(T)
|
||||
|
||||
src.print_text("Logout complete. Have a secure day.<br><br>Authentication required.<br>Please insert card and \"Login.\"")
|
||||
|
||||
|
||||
if("read","type") //Display contents of text file arg1
|
||||
var/file_name = null
|
||||
if(command_list.len)
|
||||
file_name = ckey(dd_list2text(command_list, " "))
|
||||
else
|
||||
src.print_text("<b>Syntax:</b> \"read \[file name].\" Text file must be in current directory.")
|
||||
return
|
||||
|
||||
var/datum/computer/file/text/T = get_file_name(file_name, current_folder)
|
||||
|
||||
if(isnull(T) || !istype(T) || !T.data)
|
||||
if(istype(T, /datum/computer/file/record))
|
||||
var/print_buffer = null
|
||||
var/datum/computer/file/record/R = T
|
||||
for(var/i in R.fields)
|
||||
if (R.fields[i])
|
||||
print_buffer += "[i]: [R.fields[i]]<br>"
|
||||
else
|
||||
print_buffer += "[i]<br>"
|
||||
if(print_buffer)
|
||||
src.print_text(print_buffer)
|
||||
else
|
||||
src.print_error_text("<b>Error:</b> File is empty.")
|
||||
return
|
||||
|
||||
src.print_error_text("<b>Error:</b> Invalid or blank file.")
|
||||
else
|
||||
src.print_text(T.data)
|
||||
|
||||
if("version") //Show the version name. ~Flavortext~
|
||||
src.print_text("[src.setup_version_name]<br>Copyright 2047 Thinktronic Systems, LTD.")
|
||||
|
||||
if("time") //Hello my immersion needs to know the time
|
||||
src.print_text("System time: [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], 2053.")
|
||||
|
||||
else
|
||||
//Load the program if they just entered a path I guess
|
||||
var/prog_name = dd_list2text(command_list, " ")
|
||||
prog_name = command + prog_name
|
||||
|
||||
var/datum/computer/file/terminal_program/to_run = src.parse_file_directory(prog_name, current_folder)
|
||||
|
||||
if(isnull(to_run) || !istype(to_run) || istype(to_run, /datum/computer/file/terminal_program/os))
|
||||
src.print_text("Syntax Error.")
|
||||
else
|
||||
src.master.run_program(to_run)
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
initialize()
|
||||
src.print_text("Loading [src.setup_version_name]<br>Scanning for peripheral cards...")
|
||||
|
||||
src.peripherals = new //Figure out what cards are there now so we can address them later all easy-like
|
||||
for(var/obj/item/peripheral/P in src.master.peripherals)
|
||||
if(!(P in src.peripherals))
|
||||
src.peripherals += P
|
||||
|
||||
src.print_text("Preparing filesystem...")
|
||||
|
||||
src.command_log = null
|
||||
src.help_lib = null
|
||||
src.authenticated = null
|
||||
|
||||
src.current_folder = src.holder.root
|
||||
|
||||
if(src.initialize_logs()) //Get the logging file ready.
|
||||
print_text("<font color=red>Log system failure.</font>")
|
||||
|
||||
if(src.initialize_help()) //Find the help file so it can help people.
|
||||
print_text("<font color=red>Help library not found.</font>")
|
||||
|
||||
if(setup_needs_authentication && initialize_accounts())
|
||||
print_text("<font color=red>Unable to start account system.</font>")
|
||||
|
||||
if(src.setup_needs_authentication)
|
||||
src.print_text("Authentication required.<br>Please insert card and \"Login.\"")
|
||||
|
||||
else
|
||||
src.print_text("Ready.")
|
||||
|
||||
return
|
||||
|
||||
disk_ejected(var/obj/item/disk/data/thedisk)
|
||||
if(!thedisk)
|
||||
return
|
||||
|
||||
if(current_folder && (current_folder.holder == thedisk))
|
||||
current_folder = src.holding_folder
|
||||
|
||||
if(src.holder == thedisk)
|
||||
src.print_text("<font color=red><b>System Error:</b> Unable to read system file.</font>")
|
||||
src.master.active_program = null
|
||||
src.master.host_program = null
|
||||
return
|
||||
|
||||
return
|
||||
/*
|
||||
receive_command(obj/source, command, datum/signal/signal)
|
||||
if((..()))
|
||||
return
|
||||
|
||||
if((command == "card_authed") && signal && (!src.authenticated) && src.setup_needs_authentication)
|
||||
|
||||
system_login(signal.data["registered"], signal.data["assignment"], signal.data["access"])
|
||||
return
|
||||
|
||||
return
|
||||
*/
|
||||
|
||||
proc
|
||||
//Log this text in the ~system log~ as well as printing it.
|
||||
print_error_text(text)
|
||||
if(src.log_errors)
|
||||
src.print_to_log(text, 0)
|
||||
|
||||
return src.print_text(text)
|
||||
|
||||
initialize_logs() //Man we sure love logging things. Let's set up a log for our logging.
|
||||
var/datum/computer/folder/logdir = parse_directory(SETUP_LOG_DIRECTORY, src.holder.root)
|
||||
if(!logdir || !istype(logdir))
|
||||
logdir = new /datum/computer/folder
|
||||
if(src.holder.root.add_file(logdir))
|
||||
logdir.name = SETUP_LOG_DIRECTORY
|
||||
else
|
||||
return -1 //Must be read-only or something if we can't add a folder. Give up.
|
||||
|
||||
var/datum/computer/file/text/the_log = get_file_name(SETUP_LOG_FILENAME, logdir)
|
||||
if(the_log && istype(the_log))
|
||||
src.command_log = the_log
|
||||
|
||||
else
|
||||
the_log = new /datum/computer/file/text()
|
||||
if(logdir.add_file(the_log))
|
||||
src.command_log = the_log
|
||||
the_log.name = SETUP_LOG_FILENAME
|
||||
|
||||
else
|
||||
return -2
|
||||
|
||||
the_log.data += "<br><b>STARTUP:</b> [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], 2053"
|
||||
return 0
|
||||
|
||||
print_to_log(text, strip_input=1)
|
||||
if(!text)
|
||||
return 0
|
||||
if(!command_log || !istype(command_log) || !command_log.holder)
|
||||
return 0
|
||||
|
||||
if(!(command_log.holder in src.master.contents))
|
||||
return 0
|
||||
|
||||
if(strip_input)
|
||||
command_log.data += "<br>[strip_html(text)]"
|
||||
else
|
||||
command_log.data += "<br>[text]"
|
||||
|
||||
return 1
|
||||
|
||||
initialize_help() //It's pretty similar to initialize_logs(), but unable to recreate the file if missing.
|
||||
|
||||
var/datum/computer/file/record/target_rec = parse_file_directory(SETUP_HELP_FILEPATH)
|
||||
if(target_rec && istype(target_rec))
|
||||
src.help_lib = target_rec
|
||||
print_to_log("Help System Initialized.")
|
||||
return 0
|
||||
|
||||
return -1
|
||||
|
||||
initialize_accounts()
|
||||
var/datum/computer/folder/accdir = parse_directory(SETUP_ACC_DIRECTORY, src.holder.root)
|
||||
if(!accdir || !istype(accdir))
|
||||
accdir = new /datum/computer/folder
|
||||
if(src.holder.root.add_file(accdir))
|
||||
accdir.name = SETUP_ACC_DIRECTORY
|
||||
else
|
||||
return -1 //Oh welp read only
|
||||
|
||||
var/datum/computer/file/user_data/the_acc = get_file_name(SETUP_ACC_FILENAME, accdir)
|
||||
if(the_acc && istype(the_acc))
|
||||
src.active_account = the_acc
|
||||
|
||||
else
|
||||
the_acc = new /datum/computer/file/user_data()
|
||||
if(accdir.add_file(the_acc))
|
||||
src.active_account = the_acc
|
||||
the_acc.name = SETUP_ACC_FILENAME
|
||||
|
||||
else
|
||||
return -1
|
||||
|
||||
return 0
|
||||
|
||||
system_login(var/acc_name, var/acc_job, var/access_string, all_access=0)
|
||||
if(!acc_name || !acc_job)
|
||||
return
|
||||
|
||||
if(!src.active_account && !src.initialize_accounts()) //Oh welp we can't write it to file
|
||||
src.print_text("<b>Error:</b> Unable to write account file.")
|
||||
return -1
|
||||
|
||||
src.authenticated = acc_name
|
||||
src.active_account.access = list()
|
||||
src.active_account.registered = acc_name
|
||||
src.active_account.assignment = acc_job
|
||||
src.current_folder = src.holder.root
|
||||
|
||||
if(access_string && !all_access)
|
||||
var/list/decoding = dd_text2list(access_string, ";")
|
||||
for(var/x in decoding)
|
||||
src.active_account.access += text2num(x)
|
||||
|
||||
else if(all_access)
|
||||
src.active_account.access = get_all_accesses()
|
||||
|
||||
src.print_to_log("<b>LOGIN:</b> [acc_name] | \[[acc_job]]", 0)
|
||||
|
||||
src.print_text("Welcome, [acc_name]!<br><b>Current Folder: [current_folder.name]</b>")
|
||||
return 0
|
||||
|
||||
get_loaded_drives() //Return a list of the drives in the master computer3.
|
||||
var/list/drives = list()
|
||||
var/drive_num = 0
|
||||
if(src.master.hd)
|
||||
drives["hd0"] = src.master.hd
|
||||
if(src.master.diskette)
|
||||
drives["fd0"] = src.master.diskette
|
||||
|
||||
for(var/obj/item/disk/data/drive in src.master.contents)
|
||||
if(drive == src.master.hd || drive == src.master.diskette)
|
||||
continue
|
||||
drives["sd[drive_num]"] = drive
|
||||
drive_num++
|
||||
|
||||
return drives
|
||||
|
||||
#undef SETUP_LOG_DIRECTORY
|
||||
#undef SETUP_LOG_FILENAME
|
||||
#undef SETUP_HELP_FILEPATH
|
||||
#undef SETUP_ACC_DIRECTORY
|
||||
#undef SETUP_ACC_FILENAME
|
||||
@@ -0,0 +1,468 @@
|
||||
|
||||
|
||||
|
||||
/datum/computer/file/terminal_program
|
||||
name = "blank program"
|
||||
extension = "TPROG"
|
||||
//var/size = 4.0
|
||||
//var/obj/item/disk/data/holder = null
|
||||
var/obj/machinery/computer3/master = null
|
||||
//var/active_icon = null
|
||||
var/list/req_access = list()
|
||||
//var/id_tag = null
|
||||
var/executable = 1
|
||||
|
||||
os
|
||||
name = "blank system program"
|
||||
extension = "TSYS"
|
||||
executable = 0
|
||||
var/tmp/setup_string = null
|
||||
|
||||
os_call(var/list/call_list, var/datum/computer/file/terminal_program/caller, var/datum/computer/file/file)
|
||||
return (!master || master.stat & (NOPOWER|BROKEN) || !caller || !call_list)
|
||||
|
||||
termapp //Small applications for the "termos" computer3s.
|
||||
name = "blank terminal app"
|
||||
extension = "TAPP"
|
||||
executable = 0
|
||||
|
||||
New(obj/holding as obj)
|
||||
..()
|
||||
if(holding)
|
||||
src.holder = holding
|
||||
|
||||
if(istype(src.holder.loc,/obj/machinery/computer3))
|
||||
src.master = src.holder.loc
|
||||
|
||||
/* new disposing() pattern should handle this. -singh
|
||||
Del()
|
||||
if(master)
|
||||
master.processing_programs.Remove(src)
|
||||
..()
|
||||
*/
|
||||
|
||||
disposing()
|
||||
if (master)
|
||||
if (master.processing_programs)
|
||||
master.processing_programs.Remove(src)
|
||||
master = null
|
||||
|
||||
src.req_access = null
|
||||
..()
|
||||
|
||||
proc
|
||||
os_call(var/list/call_list, var/datum/computer/file/file)
|
||||
if(!master || master.stat & (NOPOWER|BROKEN))
|
||||
return null
|
||||
|
||||
if(master.host_program)
|
||||
return master.host_program.os_call(call_list, src, file)
|
||||
return null
|
||||
|
||||
print_text(var/text)
|
||||
if((!src.holder) || (!src.master) || !text)
|
||||
return 1
|
||||
|
||||
if((!istype(holder)) || (!istype(master)))
|
||||
return 1
|
||||
|
||||
if(master.stat & (NOPOWER|BROKEN))
|
||||
return 1
|
||||
|
||||
if(src != src.master.active_program)
|
||||
return 1
|
||||
|
||||
if(!(holder in src.master.contents))
|
||||
//boutput(world, "Holder [holder] not in [master] of prg:[src]")
|
||||
if(master.active_program == src)
|
||||
master.active_program = null
|
||||
return 1
|
||||
|
||||
if(!src.holder.root)
|
||||
src.holder.root = new /datum/computer/folder
|
||||
src.holder.root.holder = src
|
||||
src.holder.root.name = "root"
|
||||
|
||||
src.master.temp_add += "[text]<br>"
|
||||
src.master.updateUsrDialog()
|
||||
|
||||
return 0
|
||||
|
||||
input_text(var/text)
|
||||
if((!src.holder) || (!src.master) || !text)
|
||||
return 1
|
||||
|
||||
if((!istype(holder)) || (!istype(master)))
|
||||
return 1
|
||||
|
||||
if(master.stat & (NOPOWER|BROKEN))
|
||||
return 1
|
||||
|
||||
if(!(holder in src.master.contents))
|
||||
//boutput(world, "Holder [holder] not in [master] of prg:[src]")
|
||||
if(master.active_program == src)
|
||||
master.active_program = null
|
||||
return 1
|
||||
|
||||
if(!src.holder.root)
|
||||
src.holder.root = new /datum/computer/folder
|
||||
src.holder.root.holder = src
|
||||
src.holder.root.name = "root"
|
||||
|
||||
return 0
|
||||
|
||||
initialize() //Called when a program starts running.
|
||||
return
|
||||
|
||||
restart()
|
||||
return
|
||||
|
||||
process()
|
||||
if((!src.holder) || (!src.master))
|
||||
return 1
|
||||
|
||||
if((!istype(holder)) || (!istype(master)))
|
||||
return 1
|
||||
|
||||
if(!(holder in src.master.contents))
|
||||
if(master.active_program == src)
|
||||
master.active_program = null
|
||||
master.processing_programs.Remove(src)
|
||||
return 1
|
||||
|
||||
if(!src.holder.root)
|
||||
src.holder.root = new /datum/computer/folder
|
||||
src.holder.root.holder = src
|
||||
src.holder.root.name = "root"
|
||||
|
||||
return 0
|
||||
|
||||
receive_command(obj/source, command, datum/signal/signal)
|
||||
if((!src.holder) || (!src.master) || (!source) || (source != src.master))
|
||||
return 1
|
||||
|
||||
if((!istype(holder)) || (!istype(master)))
|
||||
return 1
|
||||
|
||||
if(master.stat & (NOPOWER|BROKEN))
|
||||
return 1
|
||||
|
||||
if(!(holder in src.master.contents))
|
||||
if(master.active_program == src)
|
||||
master.active_program = null
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
peripheral_command(command, datum/signal/signal, target_ref)
|
||||
if(master)
|
||||
return master.send_command(command, signal, target_ref)
|
||||
//else
|
||||
// qdel(signal)
|
||||
|
||||
return null
|
||||
|
||||
//Find a peripheral by func_tag
|
||||
find_peripheral(desired_tag)
|
||||
if(!src.master || !desired_tag) return
|
||||
|
||||
var/found = null
|
||||
for(var/obj/item/peripheral/P in src.master.peripherals)
|
||||
if(P.func_tag == desired_tag)
|
||||
found = P
|
||||
|
||||
return found
|
||||
|
||||
transfer_holder(obj/item/disk/data/newholder,datum/computer/folder/newfolder)
|
||||
|
||||
if((newholder.file_used + src.size) > newholder.file_amount)
|
||||
return 0
|
||||
|
||||
if(!newholder.root)
|
||||
newholder.root = new /datum/computer/folder
|
||||
newholder.root.holder = newholder
|
||||
newholder.root.name = "root"
|
||||
|
||||
if(!newfolder)
|
||||
newfolder = newholder.root
|
||||
|
||||
if((src.holder && src.holder.read_only) || newholder.read_only)
|
||||
return 0
|
||||
|
||||
if((src.holder) && (src.holder.root))
|
||||
src.holder.root.remove_file(src)
|
||||
|
||||
newfolder.add_file(src)
|
||||
|
||||
if(istype(newholder.loc,/obj/machinery/computer3))
|
||||
src.master = newholder.loc
|
||||
|
||||
//boutput(world, "Setting [src.holder] to [newholder]")
|
||||
src.holder = newholder
|
||||
return 1
|
||||
|
||||
parse_string(string)
|
||||
var/list/sorted = command2list(string, " ")
|
||||
if (!sorted.len) sorted.len++
|
||||
return sorted
|
||||
|
||||
//Command2list is a modified version of dd_text2list() designed to eat empty list entries generated by superfluous whitespace.
|
||||
//It was born in mainframe2. Do not forget your history.
|
||||
command2list(text, separator)
|
||||
var/textlength = length(text)
|
||||
var/separatorlength = length(separator)
|
||||
var/list/textList = new()
|
||||
var/searchPosition = 1
|
||||
var/findPosition = 1
|
||||
while(1)
|
||||
findPosition = findtext(text, separator, searchPosition, 0)
|
||||
var/buggyText = copytext(text, searchPosition, findPosition)
|
||||
if(buggyText)
|
||||
textList += "[buggyText]"
|
||||
if(!findPosition)
|
||||
return textList
|
||||
searchPosition = findPosition + separatorlength
|
||||
if(searchPosition > textlength)
|
||||
return textList
|
||||
return
|
||||
|
||||
parse_directory(string, var/datum/computer/folder/origin)
|
||||
if(!string)
|
||||
return null
|
||||
|
||||
//boutput(world, "[string]")
|
||||
var/datum/computer/folder/current = origin
|
||||
|
||||
if(!origin)
|
||||
origin = src.holding_folder
|
||||
|
||||
if(dd_hasprefix(string , "/")) //if it starts with a /
|
||||
current = origin.holder.root //Begin the search at root.of current drive
|
||||
string = copytext(string,2)
|
||||
//boutput(world, "string is now: [string]")
|
||||
|
||||
var/list/sort1 = dd_text2list(string,"/")
|
||||
if (sort1.len && copytext(sort1[1], 4, 5) == ":")
|
||||
. = lowertext( copytext(sort1[1], 1, 4) )
|
||||
if (length(sort1[1]) > 4)
|
||||
sort1[1] = copytext(sort1[1], 5)
|
||||
else
|
||||
sort1.Cut(1,2)
|
||||
switch (.)
|
||||
if ("hd0")
|
||||
if (master.hd)
|
||||
current = master.hd.root
|
||||
else
|
||||
return null
|
||||
|
||||
if ("fd0")
|
||||
if (master.diskette)
|
||||
current = master.diskette.root
|
||||
else
|
||||
return null
|
||||
|
||||
else
|
||||
if (cmptext(copytext(., 1, 3), "sd"))
|
||||
. = text2num(copytext(., 3))
|
||||
if (!isnum(.))
|
||||
return null
|
||||
|
||||
.++
|
||||
for (var/obj/item/disk/data/drive in master.contents)
|
||||
if (drive == master.hd || drive == master.diskette)
|
||||
continue
|
||||
|
||||
if (--. < 1)
|
||||
current = drive.root
|
||||
break
|
||||
|
||||
if (. > 0)
|
||||
return null
|
||||
|
||||
while(current)
|
||||
|
||||
if(!sort1.len)
|
||||
//boutput(world, "finished with [current.name]")
|
||||
return current
|
||||
|
||||
var/new_current = 0
|
||||
for(var/datum/computer/folder/F in current.contents)
|
||||
//boutput(world, "testing: [F.name] -- [sort1[1]] in folder [current]")
|
||||
if(ckey(F.name) == ckey(sort1[1]))
|
||||
//boutput(world, "matches: [F.name] -- [sort1[1]]")
|
||||
sort1 -= sort1[1]
|
||||
current = F
|
||||
new_current = 1
|
||||
break
|
||||
|
||||
if(!new_current)
|
||||
//boutput(world, "no new current")
|
||||
return null
|
||||
|
||||
return null
|
||||
|
||||
//Find a file at the end of a given dirstring.
|
||||
parse_file_directory(string, var/datum/computer/folder/origin)
|
||||
if(!string)
|
||||
return null
|
||||
|
||||
//boutput(world, "[string]")
|
||||
var/datum/computer/folder/current = origin
|
||||
|
||||
if(!origin)
|
||||
origin = src.holding_folder
|
||||
|
||||
if(dd_hasprefix(string , "/")) //if it starts with a /
|
||||
current = origin.holder.root //Begin the search at root.of current drive
|
||||
string = copytext(string,2)
|
||||
//boutput(world, "string is now: [string]")
|
||||
|
||||
var/list/sort1 = dd_text2list(string,"/")
|
||||
if (sort1.len && copytext(sort1[1], 4, 5) == ":")
|
||||
. = lowertext( copytext(sort1[1], 1, 4) )
|
||||
if (length(sort1[1]) > 4)
|
||||
sort1[1] = copytext(sort1[1], 5)
|
||||
else
|
||||
sort1.Cut(1,2)
|
||||
switch (.)
|
||||
if ("hd0")
|
||||
if (master.hd)
|
||||
current = master.hd.root
|
||||
else
|
||||
return null
|
||||
|
||||
if ("fd0")
|
||||
if (master.diskette)
|
||||
current = master.diskette.root
|
||||
else
|
||||
return null
|
||||
|
||||
else
|
||||
if (cmptext(copytext(., 1, 3), "sd"))
|
||||
. = text2num(copytext(., 3))
|
||||
if (!isnum(.))
|
||||
return null
|
||||
|
||||
.++
|
||||
for (var/obj/item/disk/data/drive in master.contents)
|
||||
if (drive == master.hd || drive == master.diskette)
|
||||
continue
|
||||
|
||||
if (--. < 1)
|
||||
current = drive.root
|
||||
break
|
||||
|
||||
if (. > 0)
|
||||
return null
|
||||
|
||||
var/file_name = sort1[sort1.len]
|
||||
if(!file_name)
|
||||
return null
|
||||
|
||||
sort1 -= sort1[sort1.len]
|
||||
|
||||
while(current)
|
||||
|
||||
if(!sort1.len)
|
||||
var/datum/computer/file/check = get_file_name(file_name, current)
|
||||
if(check && istype(check))
|
||||
return check
|
||||
else
|
||||
return null
|
||||
|
||||
var/new_current = 0
|
||||
for(var/datum/computer/folder/F in current.contents)
|
||||
//boutput(world, "testing: [F.name] -- [sort1[1]] in folder [current]")
|
||||
if(ckey(F.name) == ckey(sort1[1]))
|
||||
//boutput(world, "matches: [F.name] -- [sort1[1]]")
|
||||
sort1 -= sort1[1]
|
||||
current = F
|
||||
new_current = 1
|
||||
break
|
||||
|
||||
if(!new_current)
|
||||
//boutput(world, "no new current")
|
||||
return null
|
||||
|
||||
return null
|
||||
|
||||
disk_ejected(var/obj/item/disk/data/thedisk) //So we can switch out of the floppy if it's ejected or whatever.
|
||||
if(!thedisk)
|
||||
return
|
||||
|
||||
if(src.holder == thedisk)
|
||||
src.print_text("<font color=red>Fatal Error. Returning to system...</font>")
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
//Find a folder with a given name
|
||||
get_folder_name(string, var/datum/computer/folder/check_folder)
|
||||
if(!string || (!check_folder || !istype(check_folder)))
|
||||
return null
|
||||
|
||||
var/datum/computer/taken = null
|
||||
for(var/datum/computer/folder/F in check_folder.contents)
|
||||
if(ckey(string) == ckey(F.name))
|
||||
taken = F
|
||||
break
|
||||
|
||||
return taken
|
||||
|
||||
//Find a file with a given name
|
||||
get_file_name(string, var/datum/computer/folder/check_folder)
|
||||
if(!string || (!check_folder || !istype(check_folder)))
|
||||
return null
|
||||
|
||||
var/datum/computer/taken = null
|
||||
for(var/datum/computer/file/F in check_folder.contents)
|
||||
if(ckey(string) == ckey(F.name))
|
||||
taken = F
|
||||
break
|
||||
|
||||
return taken
|
||||
|
||||
//Just find any computer datum with this name, gosh
|
||||
get_computer_datum(string, var/datum/computer/folder/check_folder)
|
||||
if(!string || (!check_folder || !istype(check_folder)))
|
||||
return null
|
||||
|
||||
var/datum/computer/taken = null
|
||||
for(var/datum/computer/C in check_folder.contents)
|
||||
if(ckey(string) == ckey(C.name))
|
||||
taken = C
|
||||
break
|
||||
|
||||
return taken
|
||||
|
||||
is_name_invalid(string) //Check if a filename is invalid somehow
|
||||
if(!string)
|
||||
return 1
|
||||
|
||||
if(ckey(string) != dd_replacetext(lowertext(string), " ", null))
|
||||
return 1
|
||||
|
||||
if(findtext(string, "/"))
|
||||
src.print_text("<b>Error:</b> Invalid character in name.")
|
||||
return 1
|
||||
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
check_access(var/list/check_list)
|
||||
if(!src.req_access) //no requirements
|
||||
return 1
|
||||
if(!istype(src.req_access, /list)) //something's very wrong
|
||||
return 1
|
||||
|
||||
var/list/L = src.req_access
|
||||
if(!L.len) //still no requirements
|
||||
return 1
|
||||
if(!check_list || !istype(check_list, /list)) //invalid or no access
|
||||
return 0
|
||||
for(var/req in src.req_access)
|
||||
if(!(req in check_list)) //doesn't have this access
|
||||
return 0
|
||||
return 1
|
||||
@@ -0,0 +1,206 @@
|
||||
//Motherboard is just used in assembly/disassembly, doesn't exist in the actual computer object.
|
||||
/obj/item/motherboard
|
||||
name = "Computer mainboard"
|
||||
desc = "A computer motherboard."
|
||||
icon = 'icons/obj/module.dmi'
|
||||
inhand_image_icon = 'icons/mob/inhand/hand_tools.dmi'
|
||||
icon_state = "mainboard"
|
||||
item_state = "electronic"
|
||||
w_class = 2.0
|
||||
var/created_name = null //If defined, result computer will have this name.
|
||||
var/integrated_floppy = 1 //Does the resulting computer have a built-in disk drive?
|
||||
mats = 8
|
||||
|
||||
/obj/computer3frame
|
||||
density = 1
|
||||
anchored = 0
|
||||
name = "Computer-frame"
|
||||
icon = 'icons/obj/computer_frame.dmi'
|
||||
icon_state = "0"
|
||||
var/state = 0
|
||||
var/obj/item/motherboard/mainboard = null
|
||||
var/obj/item/disk/data/fixed_disk/hd = null
|
||||
var/max_peripherals = 3
|
||||
var/list/peripherals = list()
|
||||
var/created_icon_state = "computer_generic"
|
||||
var/glass_needed = 2 //How much glass does this need for a screen?
|
||||
var/metal_given = 5 //How much metal does this give when destroyed?
|
||||
|
||||
terminal //Light frame
|
||||
name = "Terminal-frame"
|
||||
desc = "A light micro-computer frame used for terminal systems."
|
||||
icon = 'icons/obj/terminal_frame.dmi'
|
||||
created_icon_state = "dterm"
|
||||
max_peripherals = 2
|
||||
metal_given = 3
|
||||
glass_needed = 1
|
||||
|
||||
desktop //Those old desktop computers
|
||||
name = "Desktop Computer-frame"
|
||||
icon = 'icons/obj/computer_frame_desk.dmi'
|
||||
created_icon_state = "old"
|
||||
max_peripherals = 3
|
||||
metal_given = 3
|
||||
glass_needed = 1
|
||||
|
||||
blob_act(var/power)
|
||||
if (prob(power * 2.5))
|
||||
qdel(src)
|
||||
|
||||
/obj/computer3frame/meteorhit(obj/O as obj)
|
||||
qdel(src)
|
||||
|
||||
/obj/computer3frame/attackby(obj/item/P as obj, mob/user as mob)
|
||||
switch(state)
|
||||
if(0)
|
||||
if(istype(P, /obj/item/wrench))
|
||||
playsound(src.loc, "sound/items/Ratchet.ogg", 50, 1)
|
||||
if(do_after(user, 20))
|
||||
boutput(user, "<span style=\"color:blue\">You wrench the frame into place.</span>")
|
||||
src.anchored = 1
|
||||
src.state = 1
|
||||
if(istype(P, /obj/item/weldingtool))
|
||||
playsound(src.loc, "sound/items/Welder.ogg", 50, 1)
|
||||
if(do_after(user, 20))
|
||||
boutput(user, "<span style=\"color:blue\">You deconstruct the frame.</span>")
|
||||
var/obj/item/sheet/A = new /obj/item/sheet( src.loc )
|
||||
if(src.material)
|
||||
A.setMaterial(src.material)
|
||||
else
|
||||
var/datum/material/M = getCachedMaterial("steel")
|
||||
A.setMaterial(M)
|
||||
A.amount = src.metal_given
|
||||
qdel(src)
|
||||
if(1)
|
||||
if(istype(P, /obj/item/wrench))
|
||||
playsound(src.loc, "sound/items/Ratchet.ogg", 50, 1)
|
||||
if(do_after(user, 20))
|
||||
boutput(user, "<span style=\"color:blue\">You unfasten the frame.</span>")
|
||||
src.anchored = 0
|
||||
src.state = 0
|
||||
if(istype(P, /obj/item/motherboard) && !mainboard)
|
||||
playsound(src.loc, "sound/items/Deconstruct.ogg", 50, 1)
|
||||
boutput(user, "<span style=\"color:blue\">You place the mainboard inside the frame.</span>")
|
||||
src.icon_state = "1"
|
||||
src.mainboard = P
|
||||
user.drop_item()
|
||||
P.set_loc(src)
|
||||
if(istype(P, /obj/item/screwdriver) && mainboard)
|
||||
playsound(src.loc, "sound/items/Screwdriver.ogg", 50, 1)
|
||||
boutput(user, "<span style=\"color:blue\">You screw the mainboard into place.</span>")
|
||||
src.state = 2
|
||||
src.icon_state = "2"
|
||||
if(istype(P, /obj/item/crowbar) && mainboard)
|
||||
playsound(src.loc, "sound/items/Crowbar.ogg", 50, 1)
|
||||
boutput(user, "<span style=\"color:blue\">You remove the mainboard.</span>")
|
||||
src.state = 1
|
||||
src.icon_state = "0"
|
||||
mainboard.set_loc(src.loc)
|
||||
src.mainboard = null
|
||||
if(istype(P, /obj/item/circuitboard))
|
||||
boutput(user, "<span style=\"color:red\">This is the wrong type of frame, it won't fit!</span>")
|
||||
|
||||
if(2)
|
||||
if(istype(P, /obj/item/screwdriver) && mainboard && (!peripherals.len))
|
||||
playsound(src.loc, "sound/items/Screwdriver.ogg", 50, 1)
|
||||
boutput(user, "<span style=\"color:blue\">You unfasten the mainboard.</span>")
|
||||
src.state = 1
|
||||
src.icon_state = "1"
|
||||
|
||||
if(istype(P, /obj/item/peripheral))
|
||||
if(src.peripherals.len < src.max_peripherals)
|
||||
user.drop_item()
|
||||
src.peripherals.Add(P)
|
||||
P.set_loc(src)
|
||||
boutput(user, "<span style=\"color:blue\">You add [P] to the frame.</span>")
|
||||
else
|
||||
boutput(user, "<span style=\"color:red\">There is no more room for peripheral cards.</span>")
|
||||
|
||||
if(istype(P, /obj/item/crowbar) && src.peripherals.len)
|
||||
playsound(src.loc, "sound/items/Crowbar.ogg", 50, 1)
|
||||
boutput(user, "<span style=\"color:blue\">You remove the peripheral boards.</span>")
|
||||
for(var/obj/item/peripheral/W in src.peripherals)
|
||||
W.set_loc(src.loc)
|
||||
src.peripherals.Remove(W)
|
||||
W.uninstalled()
|
||||
|
||||
if(istype(P, /obj/item/cable_coil))
|
||||
if(P:amount >= 5)
|
||||
playsound(src.loc, "sound/items/Deconstruct.ogg", 50, 1)
|
||||
if(do_after(user, 20))
|
||||
if (!P) //Wire: Fix for Cannot read null.amount
|
||||
return
|
||||
P:amount -= 5
|
||||
if(!P:amount) qdel(P)
|
||||
boutput(user, "<span style=\"color:blue\">You add cables to the frame.</span>")
|
||||
src.state = 3
|
||||
src.icon_state = "3"
|
||||
if(3)
|
||||
if(istype(P, /obj/item/wirecutters))
|
||||
playsound(src.loc, "sound/items/Wirecutter.ogg", 50, 1)
|
||||
boutput(user, "<span style=\"color:blue\">You remove the cables.</span>")
|
||||
src.state = 2
|
||||
src.icon_state = "2"
|
||||
var/obj/item/cable_coil/A = new /obj/item/cable_coil( src.loc )
|
||||
A.amount = 5
|
||||
if(src.hd)
|
||||
src.hd.set_loc(src.loc)
|
||||
src.hd = null
|
||||
|
||||
if(istype(P, /obj/item/disk/data/fixed_disk) && !src.hd)
|
||||
user.drop_item()
|
||||
src.hd = P
|
||||
P.set_loc(src)
|
||||
boutput(user, "<span style=\"color:blue\">You connect the drive to the cabling.</span>")
|
||||
|
||||
if(istype(P, /obj/item/crowbar) && src.hd)
|
||||
playsound(src.loc, "sound/items/Crowbar.ogg", 50, 1)
|
||||
boutput(user, "<span style=\"color:blue\">You remove the hard drive.</span>")
|
||||
src.hd.set_loc(src.loc)
|
||||
src.hd = null
|
||||
|
||||
if(istype(P, /obj/item/sheet))
|
||||
var/obj/item/sheet/S = P
|
||||
if (S.material && S.material.material_flags & MATERIAL_CRYSTAL)
|
||||
if (S.amount >= src.glass_needed)
|
||||
playsound(src.loc, "sound/items/Deconstruct.ogg", 50, 1)
|
||||
if(do_after(user, 20) && S)
|
||||
S.amount -= src.glass_needed
|
||||
if(S.amount < 1)
|
||||
qdel(S)
|
||||
boutput(user, "<span style=\"color:blue\">You put in the glass panel.</span>")
|
||||
src.state = 4
|
||||
src.icon_state = "4"
|
||||
else
|
||||
boutput(user, "<span style=\"color:red\">There's not enough sheets on the stack.</span>")
|
||||
else
|
||||
boutput(user, "<span style=\"color:red\">You need sheets of some kind of crystal or glass for this.</span>")
|
||||
if(4)
|
||||
if(istype(P, /obj/item/crowbar))
|
||||
playsound(src.loc, "sound/items/Crowbar.ogg", 50, 1)
|
||||
boutput(user, "<span style=\"color:blue\">You remove the glass panel.</span>")
|
||||
src.state = 3
|
||||
src.icon_state = "3"
|
||||
var/obj/item/sheet/glass/A = new /obj/item/sheet/glass(src.loc)
|
||||
A.amount = src.glass_needed
|
||||
|
||||
if(istype(P, /obj/item/screwdriver))
|
||||
playsound(src.loc, "sound/items/Screwdriver.ogg", 50, 1)
|
||||
boutput(user, "<span style=\"color:blue\">You connect the monitor.</span>")
|
||||
var/obj/machinery/computer3/C= new /obj/machinery/computer3( src.loc )
|
||||
if(src.material) C.setMaterial(src.material)
|
||||
C.setup_drive_size = 0
|
||||
C.icon_state = src.created_icon_state
|
||||
C.setup_frame_type = src.type
|
||||
if(mainboard.created_name) C.name = mainboard.created_name
|
||||
if(mainboard.integrated_floppy) C.setup_has_internal_disk = 1
|
||||
//qdel(mainboard)
|
||||
mainboard.dispose()
|
||||
if(hd)
|
||||
C.hd = hd
|
||||
hd.set_loc(C)
|
||||
for(var/obj/item/peripheral/W in src.peripherals)
|
||||
W.set_loc(C)
|
||||
W.installed(C) //Set C as their host, etc
|
||||
//dispose()
|
||||
src.dispose()
|
||||
@@ -0,0 +1,291 @@
|
||||
/obj/machinery/communications_dish
|
||||
name = "Communications dish"
|
||||
icon = 'icons/mob/hivebot.dmi'
|
||||
icon_state = "def_radar"
|
||||
anchored = 1
|
||||
density = 1
|
||||
var/list/messagetitle = list()
|
||||
var/list/messagetext = list()
|
||||
var/list/terminals = list() //list of netIDs of connected terminals.
|
||||
var/net_id = null
|
||||
var/obj/machinery/power/data_terminal/link = null
|
||||
//Radio inter-dish communications
|
||||
var/frequency = "0000"
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
mats = 25
|
||||
|
||||
New()
|
||||
..()
|
||||
spawn(6)
|
||||
if(!src.link)
|
||||
var/turf/T = get_turf(src)
|
||||
var/obj/machinery/power/data_terminal/test_link = locate() in T
|
||||
if(test_link && !test_link.is_valid_master(test_link.master))
|
||||
src.link = test_link
|
||||
src.link.master = src
|
||||
|
||||
if(radio_controller)
|
||||
initialize()
|
||||
src.net_id = generate_net_id(src)
|
||||
|
||||
initialize()
|
||||
radio_connection = radio_controller.add_object(src, "[frequency]")
|
||||
|
||||
proc
|
||||
add_centcom_report(var/title, var/message)
|
||||
if (!message)
|
||||
return
|
||||
|
||||
if (src.stat & (BROKEN|NOPOWER) )
|
||||
return
|
||||
|
||||
if (!title)
|
||||
title = "Cent. Com. Report"
|
||||
|
||||
messagetitle += title
|
||||
messagetext += message
|
||||
|
||||
if (!src.link)
|
||||
return
|
||||
|
||||
var/list/report_content = list(title) + dd_text2list(message, "<BR>")
|
||||
|
||||
for (var/listener_netid in src.terminals)
|
||||
var/datum/computer/file/record/report = new ()
|
||||
report.fields = report_content.Copy()
|
||||
report.name = "report[messagetext.len]"
|
||||
|
||||
var/datum/signal/signal = get_free_signal()
|
||||
signal.source = src
|
||||
signal.transmission_method = TRANSMISSION_WIRE
|
||||
signal.data["command"] = "term_file"
|
||||
signal.data["data"] = "command=add_report"
|
||||
signal.data_file = report
|
||||
|
||||
signal.data["address_1"] = listener_netid
|
||||
signal.data["sender"] = src.net_id
|
||||
|
||||
src.link.post_signal(src, signal)
|
||||
|
||||
|
||||
post_status(var/target_id, var/key, var/value, var/key2, var/value2, var/key3, var/value3)
|
||||
if(!src.link || !target_id)
|
||||
return
|
||||
|
||||
var/datum/signal/signal = get_free_signal()
|
||||
signal.source = src
|
||||
signal.transmission_method = TRANSMISSION_WIRE
|
||||
signal.data[key] = value
|
||||
if(key2)
|
||||
signal.data[key2] = value2
|
||||
if(key3)
|
||||
signal.data[key3] = value3
|
||||
|
||||
signal.data["address_1"] = target_id
|
||||
signal.data["sender"] = src.net_id
|
||||
|
||||
src.link.post_signal(src, signal)
|
||||
|
||||
post_reply(error_text, target_id)
|
||||
if(!error_text || !target_id)
|
||||
return
|
||||
spawn(3)
|
||||
src.post_status(target_id, "command", "device_reply", "status", error_text)
|
||||
return
|
||||
|
||||
parse_string(string) //Parse commands the same way a c3 does, for terminal control.
|
||||
var/list/sort1 = list()
|
||||
sort1 = dd_text2list(string,";")
|
||||
for(var/x in sort1)
|
||||
var/list/sorted = list()
|
||||
sorted = dd_text2list(x," ")
|
||||
return sorted
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if(stat & (NOPOWER|BROKEN) || !src.link)
|
||||
return
|
||||
if(!signal || !src.net_id || signal.encryption)
|
||||
return
|
||||
|
||||
if(signal.transmission_method != TRANSMISSION_WIRE) //No radio for us thanks
|
||||
return
|
||||
|
||||
var/target = signal.data["sender"]
|
||||
|
||||
//They don't need to target us specifically to ping us.
|
||||
//Otherwise, ff they aren't addressing us, ignore them
|
||||
if(signal.data["address_1"] != src.net_id)
|
||||
if((signal.data["address_1"] == "ping") && signal.data["sender"])
|
||||
spawn(5) //Send a reply for those curious jerks
|
||||
src.post_status(target, "command", "ping_reply", "device", "PNET_COM_ARRAY", "netid", src.net_id)
|
||||
|
||||
return
|
||||
|
||||
var/sigcommand = lowertext(signal.data["command"])
|
||||
if(!sigcommand || !signal.data["sender"])
|
||||
return
|
||||
|
||||
switch(sigcommand)
|
||||
if("call", "recall") //Time to call/cancel a shuttle!
|
||||
switch(signal.data["shuttle_id"])
|
||||
if("emergency")
|
||||
if(signal.data["acc_code"] != netpass_heads) //Cool dudes with head codes only thanks.
|
||||
return //Otherwise you have every jerk calling the shuttle from medbay or some shit.
|
||||
|
||||
if(emergency_shuttle.location!=0)
|
||||
src.post_reply("SHUTL_E_DIS", target)
|
||||
return
|
||||
|
||||
if(sigcommand == "call")
|
||||
//don't spam call it you buttes
|
||||
if(emergency_shuttle.online || call_shuttle_proc()) //Returns 1 on failure
|
||||
src.post_reply("SHUTL_E_DIS", target)
|
||||
return
|
||||
src.post_reply("SHUTL_E_SEN", target)
|
||||
else if(sigcommand == "recall")
|
||||
if(!emergency_shuttle.online || cancel_call_proc())
|
||||
src.post_reply("SHUTL_E_DIS", target)
|
||||
return
|
||||
src.post_reply("SHUTL_E_RET", target)
|
||||
else
|
||||
//to-do: error reply
|
||||
if("term_connect") //Terminal interface stuff.
|
||||
if(target in src.terminals)
|
||||
//something might be wrong here, disconnect them!
|
||||
src.terminals.Remove(target)
|
||||
spawn(3)
|
||||
src.post_status(target, "command","term_disconnect")
|
||||
return
|
||||
|
||||
src.terminals.Add(target) //Accept the connection!
|
||||
src.post_status(target, "command","term_connect","data","noreply","device","PNET_COM_ARRAY")
|
||||
src.updateUsrDialog()
|
||||
spawn(2) //Hello!
|
||||
src.post_status(target,"command","term_message","data","command=register")
|
||||
return
|
||||
|
||||
if("term_message")
|
||||
if(!(target in src.terminals)) //Ignore mystery jerks who aren't connected.
|
||||
return
|
||||
|
||||
var/list/commandList = params2list(signal.data["data"])
|
||||
if (!commandList || !commandList.len)
|
||||
return
|
||||
|
||||
switch (commandList["command"])
|
||||
if ("list")
|
||||
. = list()
|
||||
for(var/x, x <= src.messagetitle.len, x++)
|
||||
var/mtitle = src.messagetitle[x]
|
||||
if(isnull(mtitle)) continue
|
||||
|
||||
.["[add_zero("[x]",2)]"] = "[mtitle]"
|
||||
|
||||
spawn(3)
|
||||
src.post_status(target, "command","term_message","data",list2params(.),"render","multiline")
|
||||
return
|
||||
|
||||
if ("download")
|
||||
var/msg_id = round(text2num(commandList["message"]))
|
||||
|
||||
if(!msg_id || msg_id > src.messagetext.len)
|
||||
return
|
||||
|
||||
var/to_send = src.messagetext[msg_id]
|
||||
if(!to_send) return
|
||||
|
||||
//post status doesn't cover file attachments, so we do it here
|
||||
if(!src.link || !target)
|
||||
return
|
||||
|
||||
var/datum/computer/file/text/sendfile = new
|
||||
sendfile.name = "temp"
|
||||
sendfile.data = to_send
|
||||
|
||||
var/datum/signal/filesig = new()
|
||||
filesig.source = src
|
||||
filesig.transmission_method = TRANSMISSION_WIRE
|
||||
|
||||
filesig.data_file = sendfile
|
||||
filesig.data["command"] = "term_file"
|
||||
filesig.data["data"] = ""
|
||||
filesig.data["address_1"] = target
|
||||
filesig.data["sender"] = src.net_id
|
||||
|
||||
spawn(3)
|
||||
src.link.post_signal(src, filesig)
|
||||
|
||||
/*
|
||||
var/termcommand = lowertext(signal.data["data"])
|
||||
if(!termcommand) return
|
||||
var/list/termlist = parse_string(termcommand)
|
||||
termcommand = termlist[1]
|
||||
termlist -= termlist[1]
|
||||
|
||||
switch(termcommand)
|
||||
if("list")
|
||||
var/listdat = null
|
||||
for(var/x, x <= src.messagetitle.len, x++)
|
||||
var/mtitle = src.messagetitle[x]
|
||||
if(isnull(mtitle)) continue
|
||||
|
||||
listdat += "MSG:\[[add_zero("[x]",2)]] [mtitle]|n"
|
||||
|
||||
if(!listdat)
|
||||
listdat = "No messages available."
|
||||
|
||||
spawn(3)
|
||||
src.post_status(target, "command","term_message","data",listdat,"render","multiline")
|
||||
return
|
||||
|
||||
if("download")
|
||||
var/msg_id = 0
|
||||
if(termlist.len)
|
||||
msg_id = round(text2num(termlist[1]))
|
||||
|
||||
if(!msg_id || msg_id > src.messagetext.len)
|
||||
return
|
||||
|
||||
var/to_send = src.messagetext[msg_id]
|
||||
if(!to_send) return
|
||||
|
||||
//post status doesn't cover file attachments, so we do it here
|
||||
if(!src.link || !target)
|
||||
return
|
||||
|
||||
var/datum/computer/file/text/sendfile = new
|
||||
sendfile.name = "temp"
|
||||
sendfile.data = to_send
|
||||
|
||||
var/datum/signal/filesig = new()
|
||||
filesig.source = src
|
||||
filesig.transmission_method = TRANSMISSION_WIRE
|
||||
|
||||
filesig.data_file = sendfile
|
||||
filesig.data["command"] = "term_file"
|
||||
filesig.data["address_1"] = target
|
||||
filesig.data["sender"] = src.net_id
|
||||
|
||||
spawn(3)
|
||||
src.link.post_signal(src, filesig)
|
||||
*/
|
||||
return
|
||||
|
||||
if("term_ping")
|
||||
if(!(target in terminals))
|
||||
return
|
||||
if(signal.data["data"] == "reply")
|
||||
src.post_status(target, "command","term_ping")
|
||||
//src.timeout = initial(src.timeout)
|
||||
//src.timeout_alert = 0 //no really please stay zero
|
||||
return
|
||||
|
||||
if("term_disconnect")
|
||||
if(target in src.terminals)
|
||||
src.terminals -= target
|
||||
|
||||
return
|
||||
|
||||
|
||||
return
|
||||
@@ -0,0 +1,249 @@
|
||||
/datum/computer/file/terminal_program/communications
|
||||
name = "COMMaster"
|
||||
size = 16
|
||||
req_access = list(access_heads)
|
||||
var/tmp/authenticated = null //Are we currently logged in?
|
||||
var/datum/computer/file/user_data/account = null
|
||||
var/obj/item/peripheral/network/radio/radiocard = null
|
||||
var/obj/item/peripheral/network/powernet_card/pnet_card = null
|
||||
var/tmp/comm_net_id = null //The net id of our linked ~comm dish~
|
||||
var/tmp/reply_wait = -1 //How long do we wait for replies? -1 is not waiting.
|
||||
|
||||
var/setup_acc_filepath = "/logs/sysusr"//Where do we look for login data?
|
||||
|
||||
initialize()
|
||||
|
||||
src.authenticated = null
|
||||
src.master.temp = null
|
||||
if(!src.find_access_file()) //Find the account information, as it's essentially a ~digital ID card~
|
||||
src.print_text("<b>Error:</b> Cannot locate user file. Quitting...")
|
||||
src.master.unload_program(src) //Oh no, couldn't find the file.
|
||||
return
|
||||
|
||||
src.radiocard = locate() in src.master.peripherals
|
||||
if(!radiocard || !istype(src.radiocard))
|
||||
src.radiocard = null
|
||||
src.print_text("<b>Warning:</b> No radio module detected.")
|
||||
|
||||
src.pnet_card = locate() in src.master.peripherals
|
||||
if(!pnet_card || !istype(src.pnet_card))
|
||||
src.pnet_card = null
|
||||
src.print_text("<b>Warning:</b> No network adapter detected.")
|
||||
|
||||
if(!src.check_access(src.account.access))
|
||||
src.print_text("User [src.account.registered] does not have needed access credentials.<br>Quitting...")
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
|
||||
src.reply_wait = -1
|
||||
src.authenticated = src.account.registered
|
||||
|
||||
src.print_shuttle_status()
|
||||
var/intro_text = {"<br>Welcome to COMMaster!
|
||||
<br>InterStation Communication System.
|
||||
<br><b>Commands:</b>
|
||||
<br>(Status) to view current status.
|
||||
<br>(Link) to link with a comm array.
|
||||
<br>(Call) to call shuttle.
|
||||
<br>(Recall) to recall shuttle.
|
||||
<br>(Clear) to clear the screen.
|
||||
<br>(Quit) to exit COMMaster."}
|
||||
src.print_text(intro_text)
|
||||
|
||||
|
||||
input_text(text)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/list/command_list = parse_string(text)
|
||||
var/command = command_list[1]
|
||||
command_list -= command_list[1] //Remove the command we are now processing.
|
||||
|
||||
switch(lowertext(command))
|
||||
|
||||
if("status")
|
||||
src.print_shuttle_status()
|
||||
|
||||
if("link")
|
||||
if(!src.pnet_card) //can't do this ~fancy network stuff~ without a network card.
|
||||
src.print_text("<b>Error:</b> Network card required.")
|
||||
src.master.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
src.print_text("Now scanning for communications array...")
|
||||
src.detect_comm_dish()
|
||||
|
||||
if("call")
|
||||
if(!src.pnet_card)
|
||||
src.print_text("<b>Error:</b> Network card required.")
|
||||
src.master.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
if(!src.comm_net_id)
|
||||
src.detect_comm_dish()
|
||||
sleep(8)
|
||||
if (!src.comm_net_id)
|
||||
src.print_text("<b>Error:</b> Unable to detect comm dish. Please check network cabling.")
|
||||
return
|
||||
|
||||
if (solar_flare)
|
||||
src.print_text("Solar Flare activity is preventing contact with the Emergency Shuttle.")
|
||||
else
|
||||
src.print_text("Transmitting call request...")
|
||||
generate_signal(comm_net_id, "command", "call", "shuttle_id", "emergency", "acc_code", netpass_heads)
|
||||
|
||||
if("recall")
|
||||
if(!src.pnet_card)
|
||||
src.print_text("<b>Error:</b> Network card required.")
|
||||
src.master.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
if(istype(usr, /mob/living/silicon/ai) || src.authenticated == "AIUSR")
|
||||
src.print_text("<b>Error:</b> Shuttle recall from AIUSR blocked by Central Command.")
|
||||
return
|
||||
|
||||
if(!src.comm_net_id)
|
||||
src.detect_comm_dish()
|
||||
sleep(8)
|
||||
if (!src.comm_net_id)
|
||||
src.print_text("<b>Error:</b> Unable to detect comm dish. Please check network cabling.")
|
||||
return
|
||||
|
||||
if (solar_flare)
|
||||
src.print_text("Solar Flare activity is preventing contact with the Emergency Shuttle.")
|
||||
else
|
||||
src.print_text("Transmitting recall request...")
|
||||
generate_signal(comm_net_id, "command", "recall", "shuttle_id", "emergency", "acc_code", netpass_heads)
|
||||
|
||||
if("help")
|
||||
var/help_text = {"<b>Commands:</b>
|
||||
<br>(Status) to view current status.
|
||||
<br>(Link) to link with a comm array.
|
||||
<br>(Call) to call shuttle.
|
||||
<br>(Recall) to recall shuttle.
|
||||
<br>(Clear) to clear the screen.
|
||||
<br>(Quit) to exit COMMaster."}
|
||||
src.print_text(help_text)
|
||||
|
||||
if("clear")
|
||||
src.master.temp = null
|
||||
src.master.temp_add = "Workspace cleared.<br>"
|
||||
|
||||
if("quit")
|
||||
src.master.temp = ""
|
||||
print_text("Now quitting...")
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
|
||||
else
|
||||
print_text("Unknown command : \"[copytext(strip_html(command), 1, 16)]\"")
|
||||
|
||||
|
||||
src.master.add_fingerprint(usr)
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
|
||||
process()
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(src.reply_wait > 0)
|
||||
src.reply_wait--
|
||||
if(src.reply_wait == 0)
|
||||
src.print_text("Timed out on Dish. Please rescan and retry.")
|
||||
src.comm_net_id = null
|
||||
|
||||
receive_command(obj/source, command, datum/signal/signal)
|
||||
if((..()) || (!signal))
|
||||
return
|
||||
|
||||
//If we don't have a comm dish net_id to use, set one.
|
||||
switch(signal.data["command"])
|
||||
if("ping_reply")
|
||||
if(src.comm_net_id)
|
||||
return
|
||||
if((signal.data["device"] != "PNET_COM_ARRAY") || !signal.data["netid"])
|
||||
return
|
||||
|
||||
src.comm_net_id = signal.data["netid"]
|
||||
src.print_text("Communications array detected.")
|
||||
if("device_reply")
|
||||
if(!src.comm_net_id || signal.data["sender"] != src.comm_net_id)
|
||||
return
|
||||
|
||||
src.reply_wait = -1
|
||||
|
||||
switch(lowertext(signal.data["status"]))
|
||||
if("shutl_e_dis")
|
||||
src.print_text("<b>Alert:</b> Shuttle command request rejected!")
|
||||
|
||||
if("shutl_e_sen")
|
||||
src.print_text("<b>Alert:</b> The Emergency Shuttle has been called.")
|
||||
if(master && master.current_user)
|
||||
message_admins("<span style=\"color:blue\">[key_name(master.current_user)] called the Emergency Shuttle to the station</span>")
|
||||
logTheThing("station", null, null, "[key_name(master.current_user)] called the Emergency Shuttle to the station")
|
||||
|
||||
if("shutl_e_ret")
|
||||
src.print_text("<b>Alert:</b> The Emergency Shuttle has been recalled.")
|
||||
if(master && master.current_user)
|
||||
message_admins("<span style=\"color:blue\">[key_name(master.current_user)] recalled the Emergency Shuttle</span>")
|
||||
logTheThing("station", null, null, "[key_name(master.current_user)] recalled the Emergency Shuttle")
|
||||
|
||||
return
|
||||
|
||||
|
||||
return
|
||||
|
||||
proc
|
||||
find_access_file() //Look for the whimsical account_data file
|
||||
var/datum/computer/folder/accdir = src.holder.root
|
||||
if(src.master.host_program) //Check where the OS is, preferably.
|
||||
accdir = src.master.host_program.holder.root
|
||||
|
||||
var/datum/computer/file/user_data/target = parse_file_directory(setup_acc_filepath, accdir)
|
||||
if(target && istype(target))
|
||||
src.account = target
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
detect_comm_dish() //Send out a ping signal to find a comm dish.
|
||||
if(!src.pnet_card)
|
||||
return //The card is kinda crucial for this.
|
||||
|
||||
var/datum/signal/newsignal = get_free_signal()
|
||||
//newsignal.encryption = "\ref[src.pnet_card]"
|
||||
|
||||
src.comm_net_id = null
|
||||
src.reply_wait = -1
|
||||
src.peripheral_command("ping", newsignal, "\ref[src.pnet_card]")
|
||||
|
||||
generate_signal(var/target_id, var/key, var/value, var/key2, var/value2, var/key3, var/value3)
|
||||
if(!src.pnet_card || !comm_net_id)
|
||||
return
|
||||
|
||||
var/datum/signal/signal = get_free_signal()
|
||||
//signal.encryption = "\ref[src.pnet_card]"
|
||||
signal.data["address_1"] = target_id
|
||||
signal.data[key] = value
|
||||
if(key2)
|
||||
signal.data[key2] = value2
|
||||
if(key3)
|
||||
signal.data[key3] = value3
|
||||
|
||||
src.reply_wait = 5
|
||||
src.peripheral_command("transmit", signal, "\ref[src.pnet_card]")
|
||||
|
||||
|
||||
|
||||
print_shuttle_status()
|
||||
var/dat = "<b>Status</b>: "
|
||||
if (emergency_shuttle.online && emergency_shuttle.location==0)
|
||||
var/timeleft = emergency_shuttle.timeleft()
|
||||
dat += "<b>Emergency shuttle</b><br>ETA: [timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]"
|
||||
else
|
||||
dat += "No shuttles currently en route."
|
||||
|
||||
src.print_text(dat)
|
||||
|
||||
return
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,317 @@
|
||||
//CONTENTS
|
||||
//Base disk
|
||||
//Base fixed disk
|
||||
//Base memcard
|
||||
//Base tape reel (HEH)
|
||||
//Base "read only" floppy.
|
||||
//Computer3 boot floppy
|
||||
//Network tools floppy
|
||||
//Medical program floppy
|
||||
//Security program floppy
|
||||
//Research programs floppy
|
||||
//Computer3-formatted fixed disk.
|
||||
//Box of tapes
|
||||
|
||||
|
||||
/obj/item/disk/data
|
||||
name = "data disk"
|
||||
icon = 'icons/obj/cloning.dmi'
|
||||
icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk.
|
||||
item_state = "card-id"
|
||||
w_class = 1.0
|
||||
//DNA machine vars
|
||||
var/data = ""
|
||||
var/ue = 0
|
||||
var/data_type = "ui" //ui|se
|
||||
var/owner = "Farmer Jeff"
|
||||
var/read_only = 0 //Well,it's still a floppy disk
|
||||
//Filesystem vars
|
||||
var/datum/computer/folder/root = null
|
||||
var/file_amount = 32
|
||||
var/file_used = 0
|
||||
var/portable = 1
|
||||
var/title = "Data Disk"
|
||||
New()
|
||||
src.root = new /datum/computer/folder
|
||||
src.root.holder = src
|
||||
src.root.name = "root"
|
||||
|
||||
disposing()
|
||||
if (root)
|
||||
root.dispose()
|
||||
root = null
|
||||
|
||||
data = null
|
||||
..()
|
||||
|
||||
clone()
|
||||
var/obj/item/disk/data/D = ..()
|
||||
if (!D)
|
||||
return
|
||||
|
||||
D.data = src.data
|
||||
D.ue = src.ue
|
||||
D.data_type = src.data_type
|
||||
D.owner = src.owner
|
||||
D.read_only = src.read_only
|
||||
|
||||
D.title = src.title
|
||||
D.file_amount = src.file_amount
|
||||
if (src.root)
|
||||
D.root = src.root.copy_folder()
|
||||
D.root.holder = D
|
||||
|
||||
return D
|
||||
|
||||
/obj/item/disk/data/floppy
|
||||
var/random_color = 1
|
||||
|
||||
/obj/item/disk/data/floppy/New()
|
||||
..()
|
||||
if(random_color)
|
||||
var/diskcolor = pick(0,1,2)
|
||||
src.icon_state = "datadisk[diskcolor]"
|
||||
|
||||
/obj/item/disk/data/floppy/attack_self(mob/user as mob)
|
||||
src.read_only = !src.read_only
|
||||
boutput(user, "You flip the write-protect tab to [src.read_only ? "protected" : "unprotected"].")
|
||||
|
||||
/obj/item/disk/data/floppy/examine()
|
||||
set src in oview(5)
|
||||
..()
|
||||
boutput(usr, text("The write-protect tab is set to [src.read_only ? "protected" : "unprotected"]."))
|
||||
return
|
||||
|
||||
/obj/item/disk/data/floppy/demo
|
||||
name = "data disk - 'Farmer Jeff'"
|
||||
data = "0C80C80C80C80C80C8000000000000161FBDDEF"
|
||||
ue = 1
|
||||
read_only = 1
|
||||
|
||||
/obj/item/disk/data/floppy/monkey
|
||||
name = "data disk - 'Mr. Muggles'"
|
||||
data_type = "se"
|
||||
data = "0983E840344C39F4B059D5145FC5785DC6406A4FFF"
|
||||
read_only = 1
|
||||
|
||||
/obj/item/disk/data/fixed_disk
|
||||
name = "Storage Drive"
|
||||
icon_state = "harddisk"
|
||||
title = "Storage Drive"
|
||||
file_amount = 80
|
||||
portable = 0
|
||||
|
||||
/obj/item/disk/data/memcard
|
||||
name = "Memory Board"
|
||||
icon_state = "memcard"
|
||||
desc = "A large board of non-volatile memory."
|
||||
title = "MEMCORE"
|
||||
file_amount = 640
|
||||
portable = 0
|
||||
|
||||
attackby(obj/item/W as obj, mob/user as mob)
|
||||
if (istype(W, /obj/item/device/multitool))
|
||||
user.visible_message("<span style=\"color:red\"><b>[user] begins to clear the [src]!</b></span>","You begin to clear the [src].")
|
||||
if(do_after(user, 30))
|
||||
user.visible_message("<span style=\"color:red\"><b>[user] clears the [src]!</b></span>","You clear the [src].")
|
||||
//qdel(src.root)
|
||||
if (src.root)
|
||||
src.root.dispose()
|
||||
|
||||
src.root = new /datum/computer/folder
|
||||
src.root.holder = src
|
||||
src.root.name = "root"
|
||||
return
|
||||
|
||||
/obj/item/disk/data/tape
|
||||
name = "ThinkTape"
|
||||
desc = "A form of proprietary magnetic data tape used by Thinktronic Data Systems, LLC."
|
||||
title = "MAGTAPE"
|
||||
icon_state = "tape"
|
||||
item_state = "paper"
|
||||
file_amount = 128
|
||||
portable = 0
|
||||
|
||||
New()
|
||||
..()
|
||||
src.root.gen = 99 //No subfolders!!
|
||||
return
|
||||
|
||||
attackby(obj/item/W as obj, mob/user as mob)
|
||||
if (istype(W, /obj/item/pen))
|
||||
var/t = input(user, "Enter new tape label", src.name, null) as text
|
||||
t = copytext(strip_html(t), 1, 36)
|
||||
if (!in_range(src, usr) && src.loc != usr)
|
||||
return
|
||||
if (!t)
|
||||
src.name = "ThinkTape"
|
||||
return
|
||||
|
||||
src.name = "ThinkTape-'[t]'"
|
||||
else
|
||||
..()
|
||||
return
|
||||
|
||||
//Floppy disks that are read-only ONLY.
|
||||
//It's good to have a more permanent source of programs when somebody deletes everything (until they space all the disks)
|
||||
//Remember to actually set them as read only after adding files in New()
|
||||
/obj/item/disk/data/floppy/read_only
|
||||
name = "Permafloppy"
|
||||
|
||||
attack_self(mob/user as mob)
|
||||
boutput(user, "<span style=\"color:red\">You can't flip the write-protect tab, it's held in place with glue or something!</span>")
|
||||
return
|
||||
|
||||
/obj/item/disk/data/floppy/computer3boot
|
||||
name = "data disk-'ThinkDOS'"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/os/main_os(src))
|
||||
var/datum/computer/folder/newfolder = new /datum/computer/folder( )
|
||||
newfolder.name = "logs"
|
||||
src.root.add_file( newfolder )
|
||||
newfolder.add_file( new /datum/computer/file/record/c3help(src))
|
||||
newfolder = new /datum/computer/folder
|
||||
newfolder.name = "bin"
|
||||
src.root.add_file( newfolder )
|
||||
newfolder.add_file( new /datum/computer/file/terminal_program/writewizard(src))
|
||||
|
||||
/obj/item/disk/data/floppy/read_only/network_progs
|
||||
name = "data disk-'Network Tools'"
|
||||
desc = "A collection of network management tools."
|
||||
title = "Network Help"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/background/ping(src))
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/background/signal_catcher(src))
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/file_transfer(src))
|
||||
//src.root.add_file( new /datum/computer/file/terminal_program/sigcrafter(src))
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/sigpal(src))
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/email(src))
|
||||
src.read_only = 1
|
||||
|
||||
/obj/item/disk/data/floppy/read_only/medical_progs
|
||||
name = "data disk-'Med-Trak 4'"
|
||||
desc = "The future of professional medical record management"
|
||||
title = "Med-Trak 4"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/medical_records(src))
|
||||
src.read_only = 1
|
||||
|
||||
/obj/item/disk/data/floppy/read_only/security_progs
|
||||
name = "data disk-'SecMate 6'"
|
||||
desc = "It manages security records. It is the law."
|
||||
title = "SecMate 6"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/secure_records(src))
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/manifest(src))
|
||||
src.read_only = 1
|
||||
|
||||
/obj/item/disk/data/floppy/read_only/research_progs
|
||||
name = "data disk-'AutoMate'"
|
||||
desc = "A disk containing a popular robotics research application."
|
||||
title = "Research"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/robotics_research(src))
|
||||
src.read_only = 1
|
||||
|
||||
/obj/item/disk/data/floppy/read_only/ext_research_progs
|
||||
name = "data disk-'Research Suite'"
|
||||
desc = "A disk of research programs."
|
||||
title = "Research"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/artifact_research(src))
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/disease_research(src))
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/robotics_research(src))
|
||||
src.read_only = 1
|
||||
|
||||
/obj/item/disk/data/floppy/read_only/terminal_os
|
||||
name = "data disk-'TermOS B'"
|
||||
desc = "A boot-disk for terminal systems."
|
||||
title = "TermOS"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/os/terminal_os(src))
|
||||
src.read_only = 1
|
||||
|
||||
/obj/item/disk/data/floppy/read_only/communications
|
||||
name = "data disk-'COMMaster'"
|
||||
desc = "A disk for station communication programs."
|
||||
title = "COMMaster"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/communications(src))
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/manifest(src))
|
||||
src.read_only = 1
|
||||
#ifdef SINGULARITY_TIME
|
||||
/obj/item/disk/data/floppy/read_only/engine_prog
|
||||
name = "data disk-'EngineMaster'"
|
||||
desc = "A disk with an engine startup program."
|
||||
title = "EngineDisk"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/engine_control(src))
|
||||
src.read_only = 1
|
||||
#endif
|
||||
|
||||
/obj/item/disk/data/floppy/read_only/authentication
|
||||
name = "Authentication Disk"
|
||||
desc = "Capable of storing entire kilobytes of information, this disk carries activation codes for various secure things that aren't nuclear bombs."
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "nucleardisk"
|
||||
item_state = "card-id"
|
||||
w_class = 1.0
|
||||
mats = 15
|
||||
random_color = 0
|
||||
file_amount = 32.0
|
||||
|
||||
New()
|
||||
..()
|
||||
spawn (10) //Give time to actually generate network passes I guess.
|
||||
//src.root.add_file( new /datum/computer/file/nuclear_auth(src))
|
||||
var/datum/computer/file/record/authrec = new /datum/computer/file/record {name = "GENAUTH";} (src)
|
||||
authrec.fields = list("HEADS"="[netpass_heads]",
|
||||
"SEC"="[netpass_security]",
|
||||
"MED"="[netpass_medical]")
|
||||
|
||||
src.root.add_file( authrec )
|
||||
src.root.add_file( new /datum/computer/file/terminal_program/communications(src))
|
||||
src.read_only = 1
|
||||
|
||||
/obj/item/disk/data/floppy/devkit
|
||||
name = "data disk-'Development'"
|
||||
title = "T-DISK"
|
||||
|
||||
//A fixed disk with some structure already set up for the main os I guess
|
||||
/obj/item/disk/data/fixed_disk/computer3
|
||||
New()
|
||||
..()
|
||||
//First off, create the directory for logging stuff
|
||||
var/datum/computer/folder/newfolder = new /datum/computer/folder( )
|
||||
newfolder.name = "logs"
|
||||
src.root.add_file( newfolder )
|
||||
newfolder.add_file( new /datum/computer/file/record/c3help(src))
|
||||
//This is the bin folder. For various programs I guess sure why not.
|
||||
newfolder = new /datum/computer/folder
|
||||
newfolder.name = "bin"
|
||||
src.root.add_file( newfolder )
|
||||
//newfolder.add_file( new /datum/computer/file/terminal_program/sigcrafter(src))
|
||||
newfolder.add_file( new /datum/computer/file/terminal_program/sigpal(src))
|
||||
newfolder.add_file( new /datum/computer/file/terminal_program/background/signal_catcher(src))
|
||||
if (prob(75))
|
||||
newfolder.add_file( new /datum/computer/file/terminal_program/writewizard(src))
|
||||
else
|
||||
newfolder.add_file( new /datum/computer/file/terminal_program/file_transfer(src))
|
||||
@@ -0,0 +1,806 @@
|
||||
//CONTENTS
|
||||
//Email client!!
|
||||
|
||||
|
||||
#define MENU_MAIN 0 //Fun reminder that Byond does not have enums and probably never will.
|
||||
#define MENU_SETTINGS 1
|
||||
#define MENU_SETTING_INPUT 2
|
||||
#define MENU_MAIL_INDEX 3
|
||||
#define MENU_MAIL_SELECT 4
|
||||
#define MENU_MAIL_VIEW 5
|
||||
#define MENU_WAIT 6
|
||||
#define MENU_EDIT 7
|
||||
|
||||
#define MAIL_MODE_VIEW "V"
|
||||
#define MAIL_MODE_DELETE "D"
|
||||
#define MAIL_MODE_FORWARD "F"
|
||||
#define MAIL_MODE_REPLY "R"
|
||||
|
||||
#define EDIT_MODE_TARGET 1
|
||||
#define EDIT_MODE_SUBJ 2
|
||||
#define EDIT_MODE_BODY 3
|
||||
#define EDIT_MODE_REPLYBODY 4
|
||||
#define EDIT_MODE_FWD_TARGET 5
|
||||
|
||||
#define MAX_MAIL_TITLE_LEN 32
|
||||
|
||||
/datum/computer/file/terminal_program/email
|
||||
name = "ViewPoint"
|
||||
size = 4
|
||||
|
||||
var/tmp/obj/item/peripheral/network/netCard = null
|
||||
var/tmp/server_netid = null
|
||||
var/tmp/potential_server_netid = null
|
||||
var/tmp/connected = 0
|
||||
var/tmp/menu = MENU_MAIN
|
||||
var/tmp/list/mail_index = null
|
||||
var/tmp/list/mail_temp = null
|
||||
var/tmp/list/header_temp = null
|
||||
var/tmp/header_text = null
|
||||
var/tmp/setting_input = 0
|
||||
var/tmp/mail_mode = MAIL_MODE_VIEW
|
||||
var/tmp/edit_mode = EDIT_MODE_TARGET
|
||||
var/tmp/user_address = null
|
||||
|
||||
var/tmp/edit_mail_address = null
|
||||
var/tmp/edit_mail_subject = null
|
||||
var/tmp/edit_mail_group = null
|
||||
|
||||
var/max_lines = 16
|
||||
var/signature = null
|
||||
|
||||
var/setup_acc_filepath = "/logs/sysusr"//Where do we look for login data?
|
||||
var/defaultDomain = "NT13"
|
||||
|
||||
initialize()
|
||||
src.netCard = null
|
||||
src.menu = 0
|
||||
var/introdat = "ViewPoint Email Client V1.5<br>Copyright 2051 Thinktronic Systems, LTD.<br>"
|
||||
|
||||
src.netCard = find_peripheral("NET_ADAPTER")
|
||||
if (!src.netCard || !istype(src.netCard))
|
||||
src.netCard = null
|
||||
src.print_text("<b> Error:</b>No network card detected. Quitting...")
|
||||
|
||||
src.server_netid = null
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
|
||||
else
|
||||
introdat += mainmenu_text()
|
||||
|
||||
src.master.temp = null
|
||||
src.print_text(introdat)
|
||||
|
||||
return
|
||||
|
||||
input_text(text)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/list/command_list = parse_string(text)
|
||||
var/command = command_list[1]
|
||||
command_list -= command_list[1]
|
||||
|
||||
switch(menu)
|
||||
if (MENU_MAIN)
|
||||
switch (command)
|
||||
if ("0")
|
||||
src.print_text("Quitting...")
|
||||
if (connected)
|
||||
connected = 0
|
||||
disconnect_server()
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
if ("1") //(dis)connect
|
||||
if (connected)
|
||||
disconnect_server()
|
||||
src.connected = 0
|
||||
src.master.temp = null
|
||||
src.print_text(mainmenu_text(1))
|
||||
return
|
||||
else
|
||||
if (server_netid)
|
||||
//Attempt to connect to server
|
||||
src.menu = -1
|
||||
connect_server(server_netid, 1)
|
||||
if (connected)
|
||||
src.print_text("Connection established to \[[server_netid]]!<br>[mainmenu_text(0)]")
|
||||
src.menu = MENU_MAIN
|
||||
return
|
||||
|
||||
src.menu = MENU_MAIN
|
||||
src.print_text("Connection failed.")
|
||||
return
|
||||
else
|
||||
//Attempt to autodetect server & connect
|
||||
src.menu = -1
|
||||
src.print_text("Searching for mailserver...")
|
||||
if (ping_server(1))
|
||||
src.print_text("Unable to detect mailserver!")
|
||||
src.menu = MENU_MAIN
|
||||
return
|
||||
|
||||
src.print_text("Mailserver detected at \[[potential_server_netid]]<br>Connecting...")
|
||||
connect_server(potential_server_netid, 1)
|
||||
|
||||
src.menu = MENU_MAIN
|
||||
if (connected)
|
||||
src.print_text("Connection established to \[[server_netid]]!<br>[mainmenu_text(0)]")
|
||||
return
|
||||
|
||||
src.print_text("Connection failed.")
|
||||
return
|
||||
if ("2") //Settings
|
||||
//todo: List all settings
|
||||
src.master.temp = null
|
||||
var/menuText = "Options:<br><br> (1) Set Mailserver Address<br> (2) Set Max Printed Lines Before Prompt \[[max_lines]]<br> (3) Set signature<br> (0) Go Back."
|
||||
src.print_text(menuText)
|
||||
src.menu = MENU_SETTINGS
|
||||
return
|
||||
if ("3") //Receive mail
|
||||
message_server("command=mail&args=index")
|
||||
return
|
||||
|
||||
if ("4") //View mailbox
|
||||
|
||||
src.menu = MENU_MAIL_INDEX
|
||||
src.master.temp = null
|
||||
src.print_text(mailbox_text())
|
||||
return
|
||||
|
||||
if ("5") //Compose new email
|
||||
|
||||
src.menu = MENU_EDIT
|
||||
src.edit_mode = EDIT_MODE_TARGET
|
||||
src.print_text("Please enter target address. \"AddressName--MailGroup\" or 0 to return.")
|
||||
|
||||
return
|
||||
|
||||
if (MENU_SETTINGS)
|
||||
switch (command)
|
||||
if ("1")
|
||||
if (src.connected)
|
||||
src.print_text("This cannot be changed while connected.")
|
||||
return
|
||||
|
||||
src.print_text("Current value: [server_netid ? server_netid : "AUTO"]<br>Please enter new value.")
|
||||
src.setting_input = 1
|
||||
src.menu = MENU_SETTING_INPUT
|
||||
|
||||
if ("2")
|
||||
src.print_text("Please enter new value (1-64).")
|
||||
src.setting_input = 2
|
||||
src.menu = MENU_SETTING_INPUT
|
||||
|
||||
if ("3")
|
||||
src.print_text("Current value: [signature ? signature : "OFF"]<br>Please enter new value, *NONE to clear, or 0 to return.")
|
||||
src.setting_input = 3
|
||||
src.menu = MENU_SETTING_INPUT
|
||||
|
||||
if ("0")
|
||||
src.menu = MENU_MAIN
|
||||
src.master.temp = null
|
||||
src.print_text(mainmenu_text())
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
if (MENU_SETTING_INPUT)
|
||||
switch (setting_input)
|
||||
if (1)
|
||||
var/new_netid = ckey(command)
|
||||
if (new_netid == "auto")
|
||||
src.print_text("Automatic mailserver location enabled.")
|
||||
server_netid = null
|
||||
else if (!new_netid || !ishex(new_netid) || length(new_netid) != 8)
|
||||
src.print_text("Invalid value.")
|
||||
else
|
||||
server_netid = new_netid
|
||||
src.print_text("New mailserver address set.")
|
||||
|
||||
if (2)
|
||||
var/new_max_lines = round(text2num(command))
|
||||
if (new_max_lines < 1 || new_max_lines > 64)
|
||||
src.print_text("Invalid value.")
|
||||
else
|
||||
max_lines = new_max_lines
|
||||
src.print_text("New line maximum set.")
|
||||
|
||||
if (3)
|
||||
var/new_signature = copytext( strip_html(text), 1, 129 )
|
||||
if (new_signature != "0")
|
||||
if (ckey(new_signature) && lowertext(new_signature) != "*none")
|
||||
src.signature = new_signature
|
||||
|
||||
else
|
||||
src.signature = null
|
||||
|
||||
src.print_text("New signature set.")
|
||||
|
||||
src.menu = MENU_SETTINGS
|
||||
src.setting_input = 0
|
||||
return
|
||||
|
||||
if (MENU_MAIL_INDEX)
|
||||
switch (lowertext(command))
|
||||
if ("v")
|
||||
src.mail_mode = MAIL_MODE_VIEW
|
||||
src.print_text("Mode set to: View Mail Entry.")
|
||||
if ("d")
|
||||
src.mail_mode = MAIL_MODE_DELETE
|
||||
src.print_text("Mode set to: Delete Mail Entry.")
|
||||
if ("f")
|
||||
src.mail_mode = MAIL_MODE_FORWARD
|
||||
src.print_text("Mode set to: Forward Mail Entry.")
|
||||
if ("r")
|
||||
src.mail_mode = MAIL_MODE_REPLY
|
||||
src.print_text("Mode set to: Reply to Mail Entry.")
|
||||
|
||||
else
|
||||
var/index_number = round( max( text2num(command), 0) )
|
||||
if (index_number == 0)
|
||||
src.menu = MENU_MAIN
|
||||
src.master.temp = null
|
||||
src.print_text(mainmenu_text())
|
||||
return
|
||||
|
||||
if (!istype(mail_index) || index_number > mail_index.len)
|
||||
src.print_text("Invalid mail entry.")
|
||||
return
|
||||
|
||||
if (!connected)
|
||||
src.print_text("Not connected to mailserver.")
|
||||
return
|
||||
|
||||
switch (mail_mode)
|
||||
if (MAIL_MODE_VIEW)
|
||||
//steps: request mail from server -> load mail -> display in sections
|
||||
src.mail_temp = null
|
||||
src.header_temp = null
|
||||
message_server("command=mail&args=get [index_number]") //Request mail
|
||||
src.menu = -1
|
||||
sleep(8)
|
||||
if (istype(mail_temp))
|
||||
var/dat = ""
|
||||
var/end_max = max( min(mail_temp.len, max_lines) - 8, 0)
|
||||
for (var/i = 1, i <= end_max, i++)
|
||||
dat += "<br>[mail_temp[i]]"
|
||||
|
||||
src.master.temp = null
|
||||
if (end_max < mail_temp.len)
|
||||
print_text("[header_text][dat]<br> ([mail_temp.len-end_max]) lines remaining. Any key to show more, 0 to return.")
|
||||
src.menu = MENU_MAIL_VIEW
|
||||
src.mail_temp.Cut(1,end_max+1)
|
||||
return
|
||||
|
||||
print_text("[header_text][dat]<br>|---------| Press 0 to Return |---------|")
|
||||
src.menu = MENU_WAIT
|
||||
return
|
||||
|
||||
src.print_text("Error retrieving mail.")
|
||||
sleep(10)
|
||||
src.menu = MENU_MAIL_INDEX
|
||||
src.print_text(mainmenu_text())
|
||||
return
|
||||
if (MAIL_MODE_DELETE)
|
||||
src.menu = -1
|
||||
message_server("command=mail&args=delete [index_number]")
|
||||
|
||||
src.mail_index = null
|
||||
message_server("command=mail&args=index")
|
||||
sleep(8)
|
||||
if (istype(src.mail_index))
|
||||
src.master.temp = null
|
||||
src.print_text(mailbox_text())
|
||||
src.menu = MENU_MAIL_INDEX
|
||||
return
|
||||
|
||||
src.print_text("Unable to refresh mailbox.")
|
||||
sleep(10)
|
||||
src.menu = MENU_MAIL_INDEX
|
||||
src.print_text(mainmenu_text())
|
||||
return
|
||||
if (MAIL_MODE_FORWARD)
|
||||
//steps: request mail from server -> load mail -> request new target -> send to new target
|
||||
src.mail_temp = null
|
||||
message_server("command=mail&args=get [index_number]") //Request mail
|
||||
src.menu = -1
|
||||
sleep(8)
|
||||
if (istype(mail_temp))
|
||||
src.print_text("Please enter new target address. \"AddressName--MailGroup\"")
|
||||
src.menu = MENU_EDIT
|
||||
src.edit_mode = EDIT_MODE_FWD_TARGET
|
||||
return
|
||||
|
||||
src.print_text("Error retrieving mail.")
|
||||
sleep(10)
|
||||
src.menu = MENU_MAIL_INDEX
|
||||
src.print_text(mainmenu_text())
|
||||
return
|
||||
if (MAIL_MODE_REPLY)
|
||||
src.mail_temp = null
|
||||
message_server("command=mail&args=get [index_number]")
|
||||
src.menu = -1
|
||||
sleep(8)
|
||||
if (istype(mail_temp))
|
||||
src.print_text("Please enter body text, \"!send\" to send,<br>\"!del\" to remove last line or JUST 0 to return.")
|
||||
if (src.mail_temp)
|
||||
src.mail_temp.len = 0
|
||||
src.menu = MENU_EDIT
|
||||
src.edit_mode = EDIT_MODE_REPLYBODY
|
||||
return
|
||||
|
||||
src.print_text("Error retrieving mail.")
|
||||
sleep(10)
|
||||
src.menu = MENU_MAIL_INDEX
|
||||
src.print_text(mainmenu_text())
|
||||
return
|
||||
|
||||
if (MENU_MAIL_VIEW)
|
||||
if (command == "0" || (!src.mail_temp || !src.mail_temp.len))
|
||||
src.menu = MENU_MAIL_INDEX
|
||||
src.master.temp = null
|
||||
src.print_text(mailbox_text())
|
||||
return
|
||||
|
||||
if (istype(mail_temp))
|
||||
var/dat = ""
|
||||
var/end_max = min(mail_temp.len, max_lines)
|
||||
for (var/i = 1, i <= end_max, i++)
|
||||
dat += "<br>[mail_temp[i]]"
|
||||
|
||||
if (end_max < mail_temp.len)
|
||||
print_text("[dat]<br> ([mail_temp.len-end_max]) lines remaining. Any key to show more, 0 to return.")
|
||||
src.mail_temp.Cut(1,end_max+1)
|
||||
return
|
||||
|
||||
print_text("[dat]<br>|---------| Press 0 to Return |---------|")
|
||||
src.menu = MENU_WAIT
|
||||
return
|
||||
|
||||
if (MENU_WAIT)
|
||||
if (command == "0")
|
||||
src.menu = MENU_MAIL_INDEX
|
||||
src.master.temp = null
|
||||
src.print_text(mailbox_text())
|
||||
|
||||
return
|
||||
|
||||
if (MENU_EDIT)
|
||||
switch (edit_mode)
|
||||
if (EDIT_MODE_TARGET)
|
||||
if (command == "0")
|
||||
src.menu = MENU_MAIL_INDEX
|
||||
src.master.temp = null
|
||||
src.print_text(mailbox_text())
|
||||
return
|
||||
|
||||
var/attemptAddress = copytext( ckeyEx(uppertext(text)), 1, 33)
|
||||
if (!attemptAddress)
|
||||
return
|
||||
|
||||
var/mailgroupName = null
|
||||
var/mailgroupPoint = findtext(attemptAddress, "--")
|
||||
if (mailgroupPoint)
|
||||
mailgroupName = copytext(attemptAddress, mailgroupPoint+2)
|
||||
attemptAddress = copytext(attemptAddress, 1, mailgroupPoint)
|
||||
if (!attemptAddress && ckey(mailgroupName))
|
||||
attemptAddress = "GENERIC@[defaultDomain]"
|
||||
else if (!ckey(mailgroupName) || findtext(attemptAddress, "--"))
|
||||
src.print_text("Invalid mailgroup specification. Try \"Address--mailGroupName\"")
|
||||
return
|
||||
|
||||
if (!findtext(attemptAddress, "@"))
|
||||
attemptAddress += "@[defaultDomain]"
|
||||
|
||||
src.edit_mode = EDIT_MODE_SUBJ
|
||||
src.edit_mail_address = attemptAddress
|
||||
src.edit_mail_group = mailgroupName
|
||||
src.print_text("Target Address set to \"[edit_mail_address]\"[mailgroupName ? "<br>Target Mailgroup set to \"[mailgroupName]\"" : null]<br>Please enter subject line, or 0 to go back to address entry.")
|
||||
return
|
||||
|
||||
if (EDIT_MODE_SUBJ)
|
||||
if (command == "0")
|
||||
src.edit_mode = EDIT_MODE_TARGET
|
||||
src.print_text("Please enter new target address. \"AddressName--MailGroup\" or 0 to return.")
|
||||
return
|
||||
|
||||
var/attemptSubj = copytext( strip_html(text), 1, 33 )
|
||||
if (!ckey(attemptSubj))
|
||||
return
|
||||
|
||||
src.edit_mode = EDIT_MODE_BODY
|
||||
if (src.mail_temp)
|
||||
src.mail_temp.len = 0
|
||||
else
|
||||
src.mail_temp = list()
|
||||
|
||||
src.edit_mail_subject = attemptSubj
|
||||
src.print_text("Subject Line set to \"[edit_mail_subject]\"<br>Please enter body text, \"!send\" to send,<br>\"!del\" to remove last line or JUST 0 to go back to subject entry.")
|
||||
return
|
||||
|
||||
if (EDIT_MODE_BODY, EDIT_MODE_REPLYBODY)
|
||||
if (command == "0")
|
||||
if (edit_mode == EDIT_MODE_BODY)
|
||||
src.edit_mode = EDIT_MODE_SUBJ
|
||||
src.print_text("Please enter subject line, or 0 to go back.")
|
||||
|
||||
else
|
||||
src.menu = MENU_MAIL_INDEX
|
||||
src.master.temp = null
|
||||
src.print_text(mailbox_text())
|
||||
|
||||
return
|
||||
|
||||
else if (copytext(command,1,2) == "!")
|
||||
switch (lowertext(command))
|
||||
if ("!send")
|
||||
|
||||
src.menu = -1
|
||||
if (edit_mode == EDIT_MODE_REPLYBODY && header_temp)
|
||||
header_temp["subj"] = copytext("RE: [header_temp["subj"]]", 1, 33)
|
||||
src.edit_mail_group = "*NONE"
|
||||
else
|
||||
header_temp = list()
|
||||
header_temp["mailnet"] = "PUBLIC_NT"
|
||||
header_temp["priority"] = "STANDARD"
|
||||
header_temp["subj"] = src.edit_mail_subject
|
||||
header_temp["target"] =src.edit_mail_address
|
||||
header_temp["group"] = src.edit_mail_group ? uppertext(src.edit_mail_group) : "*NONE"
|
||||
header_temp["sender"] = user_address ? user_address : "???"
|
||||
mail_temp.Insert(1, list2params(header_temp))
|
||||
|
||||
if (src.signature)
|
||||
mail_temp += "-[src.signature]"
|
||||
|
||||
var/datum/computer/file/record/outgoingMail = new
|
||||
outgoingMail.name = "mail"
|
||||
outgoingMail.fields = mail_temp
|
||||
src.mail_temp = null
|
||||
header_temp = null
|
||||
message_server("command=mail&args=send", outgoingMail)
|
||||
src.print_text("Sending message...")
|
||||
|
||||
src.mail_index = null
|
||||
message_server("command=mail&args=index")
|
||||
sleep(8)
|
||||
if (istype(src.mail_index))
|
||||
src.master.temp = null
|
||||
src.print_text(mailbox_text())
|
||||
src.menu = MENU_MAIL_INDEX
|
||||
return
|
||||
|
||||
src.print_text("Unable to refresh mailbox.")
|
||||
sleep(10)
|
||||
src.menu = MENU_MAIL_INDEX
|
||||
src.print_text(mainmenu_text())
|
||||
return
|
||||
|
||||
if ("!del")
|
||||
if (!istype(src.mail_temp) || !src.mail_temp.len)
|
||||
return
|
||||
|
||||
src.mail_temp.len--
|
||||
src.print_text("Line removed.")
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
if (!src.mail_temp)
|
||||
src.mail_temp = list()
|
||||
|
||||
var/toAdd = copytext( strip_html(text), 1, MAX_MESSAGE_LEN)
|
||||
if (!ckeyEx(toAdd) || src.mail_temp.len >= 99)
|
||||
return
|
||||
|
||||
src.mail_temp += toAdd
|
||||
src.print_text("\[[add_zero("[src.mail_temp.len]", 2)]] [toAdd]")
|
||||
|
||||
return
|
||||
|
||||
if (EDIT_MODE_FWD_TARGET)
|
||||
if (command == "0" || !istype(mail_temp) || !mail_temp.len)
|
||||
src.menu = MENU_MAIL_INDEX
|
||||
src.master.temp = null
|
||||
src.print_text(mailbox_text())
|
||||
return
|
||||
|
||||
var/attemptAddress = copytext( ckeyEx(uppertext(text)), 1, 33)
|
||||
if (!attemptAddress)
|
||||
return
|
||||
|
||||
var/mailgroupName = null
|
||||
var/mailgroupPoint = findtext(attemptAddress, "--")
|
||||
if (mailgroupPoint)
|
||||
mailgroupName = copytext(attemptAddress, mailgroupPoint+2)
|
||||
attemptAddress = copytext(attemptAddress, 1, mailgroupPoint)
|
||||
if (!attemptAddress && ckey(mailgroupName))
|
||||
attemptAddress = "GENERIC@[defaultDomain]"
|
||||
else if (!ckey(mailgroupName) || findtext(attemptAddress, "--"))
|
||||
src.print_text("Invalid mailgroup specification. Try \"address--mailGroupName\"")
|
||||
return
|
||||
|
||||
if (!findtext(attemptAddress, "@"))
|
||||
attemptAddress += "@[defaultDomain]"
|
||||
|
||||
if (header_temp && header_temp.len) //email from grandma, FWD: RE: FWD: FWD: Space-President Jordan WQIT'XFWQ' Wilkins actually syndicate martian infiltrator!!
|
||||
src.menu = -1
|
||||
header_temp["subj"] = "FWD: [header_temp["subj"]]"
|
||||
header_temp["target"] = attemptAddress
|
||||
header_temp["group"] = mailgroupName ? uppertext(mailgroupName) : "*NONE"
|
||||
header_temp["sender"] = user_address ? user_address : "???"
|
||||
mail_temp.Insert(1, list2params(header_temp))
|
||||
|
||||
var/datum/computer/file/record/outgoingMail = new
|
||||
outgoingMail.name = "mail"
|
||||
outgoingMail.fields = mail_temp
|
||||
src.mail_temp = null
|
||||
header_temp = null
|
||||
message_server("command=mail&args=send", outgoingMail)
|
||||
src.print_text("Forwarding message...")
|
||||
|
||||
src.mail_index = null
|
||||
message_server("command=mail&args=index")
|
||||
sleep(8)
|
||||
if (istype(src.mail_index))
|
||||
src.master.temp = null
|
||||
src.print_text(mailbox_text())
|
||||
src.menu = MENU_MAIL_INDEX
|
||||
return
|
||||
|
||||
src.print_text("Unable to refresh mailbox.")
|
||||
sleep(10)
|
||||
src.menu = MENU_MAIL_INDEX
|
||||
src.print_text(mainmenu_text())
|
||||
return
|
||||
|
||||
receive_command(obj/source, command, datum/signal/signal)
|
||||
if ((..()) || (!signal))
|
||||
return
|
||||
|
||||
if (!connected)
|
||||
if (signal.data["command"] == "ping_reply" && !potential_server_netid)
|
||||
|
||||
if (signal.data["device"] == "PNET_MAINFRAME" && signal.data["sender"] && ishex(signal.data["sender"]))
|
||||
potential_server_netid = signal.data["sender"]
|
||||
return
|
||||
|
||||
else if (signal.data["command"] == "term_connect")
|
||||
server_netid = ckey(signal.data["sender"])
|
||||
connected = 1
|
||||
potential_server_netid = null
|
||||
if(signal.data["data"] != "noreply")
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
|
||||
termsignal.data["address_1"] = signal.data["sender"]
|
||||
termsignal.data["command"] = "term_connect"
|
||||
termsignal.data["device"] = "SRV_TERMINAL"
|
||||
termsignal.data["data"] = "noreply"
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netCard]")
|
||||
|
||||
return
|
||||
else
|
||||
if (signal.data["sender"] != server_netid)
|
||||
return
|
||||
|
||||
if (!server_netid)
|
||||
connected = 0
|
||||
return
|
||||
|
||||
switch(lowertext(signal.data["command"]))
|
||||
if ("term_message")
|
||||
var/list/data = params2list(signal.data["data"])
|
||||
if(!data || !data["command"])
|
||||
return
|
||||
|
||||
switch (lowertext(data["command"]))
|
||||
if ("mail_index")
|
||||
src.mail_index = null
|
||||
return
|
||||
//todo
|
||||
return
|
||||
|
||||
if ("term_file")
|
||||
var/list/data = params2list(signal.data["data"])
|
||||
if(!data || !data["command"])
|
||||
return
|
||||
|
||||
switch (lowertext(data["command"]))
|
||||
if ("mail_index")
|
||||
var/datum/computer/file/record/indexRecord = signal.data_file
|
||||
if (!istype(indexRecord))
|
||||
return
|
||||
|
||||
src.mail_index = indexRecord.fields.Copy()
|
||||
|
||||
if ("mail_entry")
|
||||
var/datum/computer/file/record/entryRecord = signal.data_file
|
||||
if (!istype(entryRecord))
|
||||
return
|
||||
|
||||
if (src.mail_temp)
|
||||
src.mail_temp = null
|
||||
|
||||
var/list/headerList = params2list(entryRecord.fields[1])
|
||||
if (!headerList || !headerList.len)
|
||||
return
|
||||
|
||||
src.header_temp = headerList
|
||||
entryRecord.fields.Cut(1,2)
|
||||
src.mail_temp = entryRecord.fields.Copy()
|
||||
if (!mail_temp)
|
||||
mail_temp = list("--No Message Body--")
|
||||
|
||||
header_text = {"-----------------|HEAD|-----------------<br>
|
||||
MAILNET: [ckeyEx(headerList["mailnet"]) ? copytext(uppertext(ckeyEx(headerList["mailnet"])), 1, 33) : "???"]<br>
|
||||
WORKGROUP: [ckeyEx(headerList["group"]) ? copytext(uppertext(headerList["group"]), 1, 33) : "???"]<br>
|
||||
FROM: [ckeyEx(headerList["sender"]) ? copytext(uppertext(headerList["sender"]), 1, 33) : "???"]<br>
|
||||
TO: [ckeyEx(headerList["target"]) ? copytext(uppertext(headerList["target"]), 1, 33) : "???"]<br>
|
||||
PRIORITY: [ckeyEx(headerList["priority"]) ? copytext(uppertext(ckeyEx(headerList["priority"])), 1, 9) : "???"]<br>
|
||||
SUBJECT: [ckeyEx(headerList["subj"]) ? copytext(uppertext(headerList["subj"]), 1, 33) : "???"]<br>
|
||||
----------------------------------------"}
|
||||
|
||||
return
|
||||
|
||||
if ("term_disconnect")
|
||||
src.connected = 0
|
||||
src.user_address = null
|
||||
src.print_text("Connection closed by mailserver.")
|
||||
|
||||
if("term_ping")
|
||||
if(signal.data["data"] == "reply")
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
|
||||
termsignal.data["address_1"] = signal.data["sender"]
|
||||
termsignal.data["command"] = "term_ping"
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netCard]")
|
||||
|
||||
|
||||
return
|
||||
|
||||
proc
|
||||
connect_server(var/attempted_netid, delayCaller=0)
|
||||
if (connected || !netCard)
|
||||
return 1
|
||||
|
||||
var/datum/signal/signal = get_free_signal()
|
||||
|
||||
signal.data["address_1"] = attempted_netid
|
||||
signal.data["command"] = "term_connect"
|
||||
signal.data["device"] = "SRV_TERMINAL"
|
||||
var/datum/computer/file/user_data/user_data = get_user_data()
|
||||
var/datum/computer/file/record/udat = null
|
||||
if (istype(user_data))
|
||||
udat = new
|
||||
|
||||
var/userid = format_username(user_data.registered)
|
||||
|
||||
udat.fields["userid"] = userid
|
||||
src.user_address = "[userid]@[defaultDomain]"
|
||||
//udat.fields["assignment"] = user_data.assignment
|
||||
udat.fields["access"] = list2params(user_data.access)
|
||||
if (!udat.fields["access"] || !udat.fields["userid"])
|
||||
//qdel(udat)
|
||||
udat.dispose()
|
||||
return 1
|
||||
|
||||
udat.fields["service"] = "mail"
|
||||
|
||||
if (udat)
|
||||
signal.data_file = udat
|
||||
|
||||
src.peripheral_command("transmit", signal, "\ref[netCard]")
|
||||
if (delayCaller)
|
||||
sleep(8)
|
||||
return 0
|
||||
|
||||
return 0
|
||||
|
||||
disconnect_server()
|
||||
if (!server_netid || !netCard)
|
||||
return 1
|
||||
|
||||
var/datum/signal/signal = get_free_signal()
|
||||
|
||||
signal.data["address_1"] = server_netid
|
||||
signal.data["command"] = "term_disconnect"
|
||||
|
||||
src.peripheral_command("transmit", signal, "\ref[netCard]")
|
||||
|
||||
return 0
|
||||
|
||||
message_server(var/message, var/datum/computer/file/toSend)
|
||||
if (!connected || !server_netid || !netCard || !message)
|
||||
return 1
|
||||
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
|
||||
termsignal.data["address_1"] = server_netid
|
||||
termsignal.data["data"] = message
|
||||
termsignal.data["command"] = "term_message"
|
||||
if (toSend)
|
||||
termsignal.data_file = toSend
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netCard]")
|
||||
return 0
|
||||
|
||||
ping_server(delayCaller=0)
|
||||
if (connected || !netCard)
|
||||
return 1
|
||||
|
||||
potential_server_netid = null
|
||||
src.peripheral_command("ping", null, "\ref[netCard]")
|
||||
|
||||
if (delayCaller)
|
||||
sleep(8)
|
||||
return (potential_server_netid == null)
|
||||
|
||||
return 0
|
||||
|
||||
get_user_data()
|
||||
var/datum/computer/folder/accdir = src.holder.root
|
||||
if(src.master.host_program) //Check where the OS is, preferably.
|
||||
accdir = src.master.host_program.holder.root
|
||||
|
||||
var/datum/computer/file/user_data/target = parse_file_directory(setup_acc_filepath, accdir)
|
||||
if(target && istype(target))
|
||||
return target
|
||||
|
||||
return null
|
||||
|
||||
mainmenu_text(display_server=1)
|
||||
. = null
|
||||
if (display_server)
|
||||
. = "<b>Mail Server</b>: "
|
||||
if (server_netid)
|
||||
. += "\[[server_netid]] ([connected ? null : "Not "]Connected)<br>Your address is: \[[user_address ? user_address : "???"]]<br><br>"
|
||||
else
|
||||
. += "None Set<br><br>"
|
||||
|
||||
. += "Please Select an Option:<br> (1) [connected ? "Disconnect from" : "Connect to"] Mailserver.<br> (2) Mailserver Settings."
|
||||
if (connected)
|
||||
. += "<br> (3) Receive Mail<br> (4) View Mailbox.<br> (5) Compose Mail."
|
||||
|
||||
. += "<br> (0) Quit"
|
||||
|
||||
|
||||
mailbox_text()
|
||||
. = "Message List:"
|
||||
if (istype(mail_index) && mail_index.len)
|
||||
var/leadingZeroCount = length("[mail_index.len]")
|
||||
for (var/i = 1, i <= mail_index.len, i++)
|
||||
var/iTitle = mail_index[i]
|
||||
if (length(iTitle) > MAX_MAIL_TITLE_LEN)
|
||||
iTitle = "[copytext(iTitle, 1,MAX_MAIL_TITLE_LEN+1)]..."
|
||||
|
||||
. += "<br> \[[add_zero("[i]", leadingZeroCount)]] [iTitle]"
|
||||
else
|
||||
. += "<br> No Messages."
|
||||
|
||||
. += "<br><br>Modes: (V) View (R) Reply (F) Forward (D) Delete<br>Current Mode: ([src.mail_mode])<br>Enter mail number or 0 to return."
|
||||
|
||||
|
||||
#undef MENU_MAIN
|
||||
#undef MENU_SETTINGS
|
||||
#undef MENU_SETTING_INPUT
|
||||
#undef MENU_MAIL_INDEX
|
||||
#undef MENU_MAIL_SELECT
|
||||
#undef MENU_MAIL_VIEW
|
||||
#undef MENU_WAIT
|
||||
#undef MENU_EDIT
|
||||
|
||||
#undef MAIL_MODE_VIEW
|
||||
#undef MAIL_MODE_DELETE
|
||||
#undef MAIL_MODE_FORWARD
|
||||
#undef MAIL_MODE_REPLY
|
||||
|
||||
#undef EDIT_MODE_TARGET
|
||||
#undef EDIT_MODE_SUBJ
|
||||
#undef EDIT_MODE_BODY
|
||||
#undef EDIT_MODE_REPLYBODY
|
||||
#undef EDIT_MODE_FWD_TARGET
|
||||
|
||||
#undef MAX_MAIL_TITLE_LEN
|
||||
@@ -0,0 +1,291 @@
|
||||
//Singularity engine control program
|
||||
#ifdef SINGULARITY_TIME
|
||||
/datum/computer/file/terminal_program/engine_control
|
||||
name = "EngineMaster"
|
||||
size = 10
|
||||
req_access = list(access_engineering_engine)
|
||||
var/tmp/authenticated = null //Are we currently logged in?
|
||||
var/datum/computer/file/user_data/account = null
|
||||
var/log_string = null
|
||||
var/obj/item/peripheral/network/powernet_card/netcard = null
|
||||
var/obj/item/peripheral/network/radio/radiocard = null
|
||||
var/tmp/task = null //What are we doing at the moment?
|
||||
var/tmp/startup_line = 1
|
||||
var/tmp/starting_up = 0 //Are we currently starting up?
|
||||
var/list/emitter_ids = list() //Net ids of located emitters.
|
||||
var/list/fieldgen_ids = list() //Net ids of located field generators.
|
||||
var/tmp/last_event_report = 0 //When did we last report an event?
|
||||
|
||||
var/setup_acc_filepath = "/logs/sysusr"//Where do we look for login data?
|
||||
var/setup_logdump_name = "englog"
|
||||
var/setup_mail_freq = 1149 //Which freq do we report to?
|
||||
var/setup_mailgroup = "engineer" //The PDA mailgroup used when alerting engineer pdas.
|
||||
|
||||
|
||||
initialize()
|
||||
|
||||
src.authenticated = null
|
||||
src.task = null
|
||||
src.master.temp = null
|
||||
src.startup_line = 1
|
||||
|
||||
if(!src.find_access_file()) //Find the account information, as it's essentially a ~digital ID card~
|
||||
src.print_text("<b>Error:</b> Cannot locate user file. Quitting...")
|
||||
src.master.unload_program(src) //Oh no, couldn't find the file.
|
||||
return
|
||||
if(!src.check_access(src.account.access))
|
||||
src.print_text("User [src.account.registered] does not have needed access credentials.<br>Quitting...")
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
|
||||
src.netcard = locate() in src.master.peripherals
|
||||
if(!src.netcard || !istype(src.netcard))
|
||||
src.print_text("<b>Error:</b> No network card detected.<br>Quitting...")
|
||||
src.log_string += "<br>Startup Failure: No network card."
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
|
||||
src.radiocard = locate() in src.master.peripherals
|
||||
if(!radiocard || !istype(src.radiocard))
|
||||
src.radiocard = null
|
||||
src.print_text("<b>Warning:</b> No radio module detected.")
|
||||
src.log_string += "<br>Startup Error: No radio."
|
||||
|
||||
src.authenticated = src.account.registered
|
||||
src.log_string += "<br><b>LOGIN:</b> [src.authenticated]"
|
||||
|
||||
src.ping_devices()
|
||||
|
||||
var/intro_text = {"<br>EngineMaster
|
||||
<br>Automated Engine Control System
|
||||
<br><b>Commands:</b>
|
||||
<br>(Startup) to activate engine systems.
|
||||
<br>(Abort) to abort startup procedure.
|
||||
<br>(Rescan) to rescan for engine devices.
|
||||
<br>(Clear) to clear the screen.
|
||||
<br>(Quit) to exit."}
|
||||
src.print_text(intro_text)
|
||||
|
||||
return
|
||||
|
||||
input_text(text)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/list/command_list = parse_string(text)
|
||||
var/command = command_list[1]
|
||||
command_list -= command_list[1]
|
||||
|
||||
src.print_text(strip_html(text))
|
||||
|
||||
switch(lowertext(command))
|
||||
|
||||
if("startup")
|
||||
//We're already starting, jeez give it some time
|
||||
if(src.starting_up)
|
||||
src.print_text("Startup already in progress.")
|
||||
src.master.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
if(!emitter_ids || emitter_ids.len <= 0)
|
||||
src.print_text("<b>Error:</b> Insufficient emitters detected.")
|
||||
src.master.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
if(!fieldgen_ids || fieldgen_ids.len < 4)
|
||||
src.print_text("<b>Error:</b> Insufficient field generators detected.")
|
||||
src.master.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
src.startup_line = 1
|
||||
src.starting_up = 1
|
||||
src.task = "startup-emit"
|
||||
src.log_string += "<br>Startup initiated."
|
||||
src.report_event("Engine starting up...")
|
||||
src.print_text("Startup procedure initiated.")
|
||||
|
||||
if("abort")
|
||||
if(!src.starting_up)
|
||||
src.print_text("No startup procedure in progress.")
|
||||
src.master.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
src.startup_line = 1
|
||||
src.task = null
|
||||
src.starting_up = 0
|
||||
src.log_string += "<br>Startup aborted."
|
||||
src.print_text("Startup procedure aborted.")
|
||||
|
||||
if("rescan")
|
||||
if((src.task && src.task != "scan") || src.starting_up)
|
||||
src.print_text("Unable to scan, system is busy.")
|
||||
return
|
||||
|
||||
src.ping_devices()
|
||||
|
||||
if("logdump")
|
||||
if(!src.log_string) //Something is wrong.
|
||||
src.print_text("<b>Error:</b> No log data to dump.")
|
||||
return
|
||||
|
||||
if(src.holder.read_only)
|
||||
src.print_text("<b>Error:</b> Destination drive is read-only.")
|
||||
return
|
||||
|
||||
var/datum/computer/file/text/logdump = get_file_name(setup_logdump_name, src.holding_folder)
|
||||
if(logdump && !istype(logdump) || get_folder_name(setup_logdump_name, src.holding_folder))
|
||||
src.print_text("<b>Error:</b> Name in use.")
|
||||
return
|
||||
|
||||
if(logdump && istype(logdump))
|
||||
logdump.data = src.log_string
|
||||
else
|
||||
logdump = new /datum/computer/file/text
|
||||
logdump.name = setup_logdump_name
|
||||
logdump.data = src.log_string
|
||||
if(!src.holding_folder.add_file(logdump))
|
||||
//qdel(logdump)
|
||||
logdump.dispose()
|
||||
src.print_text("<b>Error:</b> Cannot save to disk.")
|
||||
return
|
||||
|
||||
src.print_text("Log dumped to holding directory.")
|
||||
|
||||
if("clear")
|
||||
src.master.temp = null
|
||||
src.master.temp_add = "Workspace cleared.<br>"
|
||||
|
||||
if("quit")
|
||||
src.log_string += "<br><b>LOGOUT:</b> [src.authenticated]"
|
||||
src.print_text("Now quitting...")
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
|
||||
else
|
||||
src.print_text("Unknown command.")
|
||||
|
||||
src.master.add_fingerprint(usr)
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
|
||||
process()
|
||||
if(..() || !src.task)
|
||||
return
|
||||
|
||||
switch(src.task)
|
||||
if("startup-emit")
|
||||
if(startup_line > src.emitter_ids.len)
|
||||
src.task = "startup-field"
|
||||
src.startup_line = 1
|
||||
return
|
||||
|
||||
post_status(src.emitter_ids[src.startup_line], "command", "activate")
|
||||
src.startup_line++
|
||||
|
||||
if("startup-field")
|
||||
if(startup_line > src.fieldgen_ids.len)
|
||||
src.task = null
|
||||
src.startup_line = 1
|
||||
src.starting_up = 0
|
||||
src.print_text("Startup procedure complete.")
|
||||
return
|
||||
|
||||
post_status(src.fieldgen_ids[src.startup_line], "command", "activate")
|
||||
src.startup_line++
|
||||
|
||||
receive_command(obj/source, command, datum/signal/signal)
|
||||
if((..()) || !signal)
|
||||
return
|
||||
|
||||
//Time to populate our lists of components.
|
||||
if(signal.data["command"] == "ping_reply" && (src.task == "scan"))
|
||||
if(!signal.data["netid"])
|
||||
return
|
||||
|
||||
switch(signal.data["device"])
|
||||
if("PNET_ENG_EMITR") //Oh hey a new emitter.
|
||||
if(!(signal.data["netid"] in src.emitter_ids))
|
||||
src.emitter_ids += signal.data["netid"]
|
||||
if("PNET_ENG_FIELD")
|
||||
if(!(signal.data["netid"] in src.fieldgen_ids))
|
||||
src.fieldgen_ids += signal.data["netid"]
|
||||
else
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
proc
|
||||
ping_devices()
|
||||
if(!src.netcard)
|
||||
return
|
||||
src.task = "scan"
|
||||
src.emitter_ids = new
|
||||
src.fieldgen_ids = new
|
||||
|
||||
var/datum/signal/newsignal = get_free_signal()
|
||||
//newsignal.encryption = "\ref[src.netcard]"
|
||||
|
||||
src.log_string += "<br>Scanning for devices..."
|
||||
src.print_text("Scanning for devices...")
|
||||
src.peripheral_command("ping", newsignal, "\ref[src.netcard]")
|
||||
|
||||
return
|
||||
|
||||
post_status(var/target_id, var/key, var/value, var/key2, var/value2, var/key3, var/value3)
|
||||
if(!src.netcard)
|
||||
return
|
||||
|
||||
var/datum/signal/signal = get_free_signal()
|
||||
|
||||
//signal.encryption = "\ref[src.netcard]"
|
||||
signal.data[key] = value
|
||||
if(key2)
|
||||
signal.data[key2] = value2
|
||||
if(key3)
|
||||
signal.data[key3] = value3
|
||||
|
||||
signal.data["address_1"] = target_id
|
||||
src.peripheral_command("transmit", signal, "\ref[src.netcard]")
|
||||
|
||||
report_event(var/event_string)
|
||||
if(!event_string || !src.radiocard)
|
||||
return
|
||||
|
||||
//Unlikely that this would be a problem but OH WELL
|
||||
if(last_event_report && world.time < (last_event_report + 10))
|
||||
return
|
||||
|
||||
//Set card frequency if it isn't already.
|
||||
if(src.radiocard.frequency != src.setup_mail_freq && !src.radiocard.setup_freq_locked)
|
||||
var/datum/signal/freqsignal = get_free_signal()
|
||||
//freqsignal.encryption = "\ref[src.radiocard]"
|
||||
peripheral_command("[src.setup_mail_freq]", freqsignal,"\ref[src.radiocard]")
|
||||
src.log_string += "<br>Adjusting frequency... \[[src.setup_mail_freq]]."
|
||||
|
||||
var/datum/signal/signal = get_free_signal()
|
||||
//signal.encryption = "\ref[src.radiocard]"
|
||||
|
||||
//Create a PDA mass-message string.
|
||||
signal.data["address_1"] = "00000000"
|
||||
signal.data["command"] = "text_message"
|
||||
signal.data["sender_name"] = "ENGINE-MAILBOT"
|
||||
signal.data["group"] = src.setup_mailgroup //Only engineer PDAs should be informed.
|
||||
signal.data["message"] = "Notice: [event_string]"
|
||||
|
||||
src.log_string += "<br>Event notification sent."
|
||||
last_event_report = world.time
|
||||
peripheral_command("transmit", signal, "\ref[src.radiocard]")
|
||||
return
|
||||
|
||||
find_access_file() //Look for the whimsical account_data file
|
||||
var/datum/computer/folder/accdir = src.holder.root
|
||||
if(src.master.host_program) //Check where the OS is, preferably.
|
||||
accdir = src.master.host_program.holder.root
|
||||
|
||||
var/datum/computer/file/user_data/target = parse_file_directory(setup_acc_filepath, accdir)
|
||||
if(target && istype(target))
|
||||
src.account = target
|
||||
return 1
|
||||
|
||||
return 0
|
||||
#endif
|
||||
@@ -0,0 +1,213 @@
|
||||
#define HANGAR_AREATYPE "/area/hangar"
|
||||
/datum/computer/file/terminal_program/hangar_control
|
||||
name = "HangarControl"
|
||||
size = 16
|
||||
req_access = list(access_hangar)
|
||||
var/tmp/authenticated = null //Are we currently logged in?
|
||||
var/datum/computer/file/user_data/account = null
|
||||
var/tmp/reply_wait = -1 //How long do we wait for replies? -1 is not waiting.
|
||||
var/setup_acc_filepath = "/logs/sysusr"//Where do we look for login data?
|
||||
|
||||
initialize()
|
||||
|
||||
src.authenticated = null
|
||||
src.master.temp = null
|
||||
if(!src.find_access_file()) //Find the account information, as it's essentially a ~digital ID card~
|
||||
src.print_text("<b>Error:</b> Cannot locate user file. Quitting...")
|
||||
src.master.unload_program(src) //Oh no, couldn't find the file.
|
||||
return
|
||||
|
||||
if(!src.check_access(src.account.access))
|
||||
src.print_text("User [src.account.registered] does not have needed access credentials.<br>Quitting...")
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
|
||||
src.reply_wait = -1
|
||||
src.authenticated = src.account.registered
|
||||
var/intro_text = {"<br>Welcome to HangarControl!
|
||||
<br>Hangar Management System.
|
||||
<br><b>Commands:</b>
|
||||
<br>(Status) to view current status.
|
||||
<br>(ResetPass) to reset a hangar door's password.
|
||||
<br>(CloseAll) to close all hangar doors.
|
||||
<br>(Toggle) to toggle a hangar door.
|
||||
<br>(Clear) to clear the screen.
|
||||
<br>(Quit) to exit HangarControl."}
|
||||
src.print_text(intro_text)
|
||||
|
||||
input_text(text)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/list/command_list = parse_string(text)
|
||||
var/command = command_list[1]
|
||||
command_list -= command_list[1] //Remove the command we are now processing.
|
||||
|
||||
switch(lowertext(command))
|
||||
if("status")
|
||||
print_status()
|
||||
if("clear")
|
||||
src.master.temp = null
|
||||
src.master.temp_add = "Workspace cleared.<br>"
|
||||
if("closeall")
|
||||
close_all()
|
||||
if("toggle")
|
||||
var/door_name = ckey(dd_list2text(command_list, " "))
|
||||
if(!door_name)
|
||||
var/dat = "<b>Available Hangar Doors:</b><br>"
|
||||
for(var/turf/T in get_area_turfs(HANGAR_AREATYPE))
|
||||
for(var/obj/machinery/r_door_control/R in T)
|
||||
if(R.open)
|
||||
dat+="[R.name]<BR>"
|
||||
else
|
||||
dat+="[R.name]<BR>"
|
||||
src.print_text(dat)
|
||||
else
|
||||
for(var/turf/T in get_area_turfs(HANGAR_AREATYPE))
|
||||
for(var/obj/machinery/r_door_control/R in T)
|
||||
if(cmptext(door_name,R.id))
|
||||
if(R.open)
|
||||
src.print_text("Closing Door...")
|
||||
else
|
||||
src.print_text("Opening Door...")
|
||||
R.open_door()
|
||||
src.print_text("Done.<BR>")
|
||||
src.master.add_fingerprint(usr)
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
src.print_text("Invalid Hangar Door!<BR>")
|
||||
if("resetpass")
|
||||
var/door_name = ckey(dd_list2text(command_list, " "))
|
||||
if(!door_name)
|
||||
var/dat = "<b>Available Hangar Doors:</b><br>"
|
||||
for(var/turf/T in get_area_turfs(HANGAR_AREATYPE))
|
||||
for(var/obj/machinery/r_door_control/R in T)
|
||||
if(R.open)
|
||||
dat+="[R.name]<BR>"
|
||||
else
|
||||
dat+="[R.name]<BR>"
|
||||
src.print_text(dat)
|
||||
else
|
||||
for(var/turf/T in get_area_turfs(HANGAR_AREATYPE))
|
||||
for(var/obj/machinery/r_door_control/R in T)
|
||||
if(cmptext(door_name,R.id))
|
||||
R.pass = "[R.id]-[rand(100,999)]"
|
||||
src.print_text("[R.name] New Pass: [R.pass]")
|
||||
src.master.add_fingerprint(usr)
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
src.print_text("Invalid Hangar Door!<BR>")
|
||||
|
||||
if("help")
|
||||
var/intro_text = {"<br>Welcome to HangarControl!
|
||||
<br>Hangar Management System.
|
||||
<br><b>Commands:</b>
|
||||
<br>(Status) to view current status.
|
||||
<br>(ResetPass) to reset a hangar door's password.
|
||||
<br>(CloseAll) to close all hangar doors.
|
||||
<br>(Toggle) to toggle a hangar door.
|
||||
<br>(Clear) to clear the screen.
|
||||
<br>(Quit) to exit HangarControl."}
|
||||
src.print_text(intro_text)
|
||||
if("quit")
|
||||
src.master.temp = ""
|
||||
print_text("Now quitting...")
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
else
|
||||
print_text("Unknown command : \"[copytext(strip_html(command), 1, 16)]\"")
|
||||
|
||||
|
||||
src.master.add_fingerprint(usr)
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
|
||||
proc
|
||||
find_access_file() //Look for the whimsical account_data file
|
||||
var/datum/computer/folder/accdir = src.holder.root
|
||||
if(src.master.host_program) //Check where the OS is, preferably.
|
||||
accdir = src.master.host_program.holder.root
|
||||
|
||||
var/datum/computer/file/user_data/target = parse_file_directory(setup_acc_filepath, accdir)
|
||||
if(target && istype(target))
|
||||
src.account = target
|
||||
return 1
|
||||
|
||||
return 0
|
||||
print_status()
|
||||
var/dat="<b>Status</b>:<BR>"
|
||||
for(var/turf/T in get_area_turfs(HANGAR_AREATYPE))
|
||||
for(var/obj/machinery/r_door_control/R in T)
|
||||
if(R.open)
|
||||
dat+="[R.name] (Open): [R.pass]<BR>"
|
||||
else
|
||||
dat+="[R.name] (Closed): [R.pass]<BR>"
|
||||
src.print_text(dat)
|
||||
close_all()
|
||||
src.print_text("Closing All Doors...")
|
||||
for(var/turf/T in get_area_turfs(HANGAR_AREATYPE))
|
||||
for(var/obj/machinery/r_door_control/R in T)
|
||||
if(R.open)
|
||||
R.open_door()
|
||||
src.print_text("Done.<BR>")
|
||||
|
||||
/datum/computer/file/terminal_program/hangar_research
|
||||
name = "HangarHelper"
|
||||
size = 16
|
||||
req_access = list(access_hangar)
|
||||
var/tmp/authenticated = null //Are we currently logged in?
|
||||
var/datum/computer/file/user_data/account = null
|
||||
var/tmp/reply_wait = -1 //How long do we wait for replies? -1 is not waiting.
|
||||
var/setup_acc_filepath = "/logs/sysusr"//Where do we look for login data?
|
||||
|
||||
initialize()
|
||||
|
||||
src.authenticated = null
|
||||
src.master.temp = null
|
||||
if(!src.find_access_file()) //Find the account information, as it's essentially a ~digital ID card~
|
||||
src.print_text("<b>Error:</b> Cannot locate user file. Quitting...")
|
||||
src.master.unload_program(src) //Oh no, couldn't find the file.
|
||||
return
|
||||
|
||||
if(!src.check_access(src.account.access))
|
||||
src.print_text("User [src.account.registered] does not have needed access credentials.<br>Quitting...")
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
|
||||
src.reply_wait = -1
|
||||
src.authenticated = src.account.registered
|
||||
src.print_research_status()
|
||||
var/intro_text = {"<br>HangarHelper
|
||||
<br>Bringing You the Latest in Ship Technology!.
|
||||
<br><b>Commands:</b>
|
||||
<br>(Status) to view current progress.
|
||||
<br>(Research) to view research topics.
|
||||
<br>(Cancel) to halt current research.
|
||||
<br>(Complete) to view completed research.
|
||||
<br>(Clear) to clear the screen.
|
||||
<br>(Quit) to exit HangarHelper"}
|
||||
src.print_text(intro_text)
|
||||
|
||||
proc
|
||||
find_access_file() //Look for the whimsical account_data file
|
||||
var/datum/computer/folder/accdir = src.holder.root
|
||||
if(src.master.host_program) //Check where the OS is, preferably.
|
||||
accdir = src.master.host_program.holder.root
|
||||
|
||||
var/datum/computer/file/user_data/target = parse_file_directory(setup_acc_filepath, accdir)
|
||||
if(target && istype(target))
|
||||
src.account = target
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
print_research_status()
|
||||
var/dat = "<b>Tier [robotics_research.tier] Hangar Research</b><br>"
|
||||
if(robotics_research.is_researching)
|
||||
var/timeleft = robotics_research.get_research_timeleft()
|
||||
var/text = robotics_research.current_research
|
||||
dat += "Current Research: [text ? text : "None"]. ETA: [timeleft ? timeleft : "Completed"]."
|
||||
else
|
||||
dat += "Currently not researching."
|
||||
src.print_text(dat)
|
||||
return
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,655 @@
|
||||
//CONTENTS:
|
||||
//Mainframe program parent type
|
||||
//Mainframe user account datum
|
||||
|
||||
|
||||
/*
|
||||
* Mainframe Software
|
||||
*/
|
||||
|
||||
/datum/computer/file/mainframe_program
|
||||
name = "mainframe program"
|
||||
extension = "MPG"
|
||||
var/obj/machinery/networked/mainframe/master = null
|
||||
var/executable = 1
|
||||
var/needs_holder = 1
|
||||
var/tmp/datum/computer/file/mainframe_program/parent_task = null
|
||||
var/tmp/progid = 0
|
||||
var/tmp/initialized = 0
|
||||
var/tmp/datum/mainframe2_user_data/useracc = null
|
||||
|
||||
os
|
||||
name = "Base OS"
|
||||
size = 16
|
||||
extension = "SYS"
|
||||
executable = 0
|
||||
var/tmp/setup_string = null
|
||||
|
||||
proc
|
||||
//Called by the mainframe when a new terminal connection is made so as to alert the OS
|
||||
new_connection(datum/terminal_connection/conn)
|
||||
return
|
||||
|
||||
//Called by the mainframe upon termination of a connection, conn is deleted afterwards
|
||||
closed_connection(datum/terminal_connection/conn)
|
||||
return
|
||||
|
||||
//The data string (And, optionally, file) sent to us by a connected terminal (Identified by network ID in termid)
|
||||
//Note: The passed file will be completely temporary and is deleted after the function returns.
|
||||
term_input(var/data, var/termid, var/datum/computer/file/file)
|
||||
if(!src.master || !data || !termid)
|
||||
return 1
|
||||
|
||||
if(master.stat & (NOPOWER|BROKEN|MAINT))
|
||||
return 1
|
||||
|
||||
if(src.needs_holder)
|
||||
if(!(holder in src.master.contents))
|
||||
return 1
|
||||
|
||||
if(!src.holder.root)
|
||||
src.holder.root = new /datum/computer/folder
|
||||
src.holder.root.holder = src
|
||||
src.holder.root.name = "root"
|
||||
|
||||
return 0
|
||||
|
||||
//Called by the mainframe upon receipt of a ping_reply network signal. This does not a terminal_connection because we are not necessarily connected to the responding device.
|
||||
ping_reply(var/senderid,var/sendertype)
|
||||
return (!master || !senderid || !sendertype)
|
||||
|
||||
|
||||
//Send a message to a connected terminal device (Using term_message)
|
||||
message_term(var/message, var/termid, var/render=null)
|
||||
|
||||
if(!istype(master) || !message || !termid)
|
||||
return 1
|
||||
|
||||
if(master.stat & (NOPOWER|BROKEN|MAINT))
|
||||
return 1
|
||||
|
||||
if(src.needs_holder)
|
||||
if (!holder || !(holder in src.master.contents))
|
||||
return 1
|
||||
|
||||
if(!src.holder.root)
|
||||
src.holder.root = new /datum/computer/folder
|
||||
src.holder.root.holder = src
|
||||
src.holder.root.name = "root"
|
||||
|
||||
spawn(1)
|
||||
src.master.post_status(termid, "command", "term_message", "data", message, "render", render)
|
||||
return 0
|
||||
|
||||
//Send a file and message to a connected terminal device (Using term_file)
|
||||
file_term(var/datum/computer/file/file, var/termid, var/exdata)
|
||||
|
||||
|
||||
if(!istype(master) || !istype(file) || !termid)
|
||||
return 1
|
||||
|
||||
if(master.stat & (NOPOWER|BROKEN|MAINT))
|
||||
return 1
|
||||
|
||||
if(src.needs_holder)
|
||||
if (!holder || !(holder in src.master.contents))
|
||||
return 1
|
||||
|
||||
if(!src.holder.root)
|
||||
src.holder.root = new /datum/computer/folder
|
||||
src.holder.root.holder = src
|
||||
src.holder.root.name = "root"
|
||||
|
||||
spawn(1)
|
||||
src.master.post_file(termid, "data", exdata, file)
|
||||
return 0
|
||||
|
||||
/*
|
||||
* The parse_* functions parse the filesystem to locate a computer datum of some sort (Be it directory, file, or either)
|
||||
* with a supplied filepath string, origin point, and user. Create_if_missing determines whether intermediary folders in the path should be created if not present.
|
||||
* Notes: A '/' prefixing the filepath will cause the search to start at the origin point
|
||||
* '.' refers to the current folder in the search, while '..' refers to its parent folder
|
||||
* Results will be filtered based on the supplied user's permissions -- If they do not have permission to read a file, they will not find said file.
|
||||
* If a user datum is not supplied, it is assumed that the system made the call desiring full access.
|
||||
*/
|
||||
|
||||
parse_directory(string, var/datum/computer/folder/origin, var/create_if_missing, var/datum/mainframe2_user_data/user)
|
||||
if(!string)
|
||||
return null
|
||||
|
||||
var/datum/computer/folder/current = origin
|
||||
|
||||
if(!origin)
|
||||
origin = src.holder.root
|
||||
|
||||
if(dd_hasprefix(string , "/")) //if it starts with a /
|
||||
if (string == "/")
|
||||
return origin
|
||||
current = origin
|
||||
string = copytext(string,2)
|
||||
|
||||
var/list/sort1 = list()
|
||||
sort1 = dd_text2list(string,"/")
|
||||
if (sort1.len && !sort1[sort1.len])
|
||||
sort1.len--
|
||||
|
||||
while(current)
|
||||
|
||||
if(!sort1.len)
|
||||
return current
|
||||
|
||||
if(sort1[1] == "..")
|
||||
if (current == origin)
|
||||
return null
|
||||
current = current.holding_folder
|
||||
sort1 -= sort1[1]
|
||||
continue
|
||||
else if (sort1[1] == ".")
|
||||
sort1 -= sort1[1]
|
||||
continue
|
||||
|
||||
else if (!sort1[1] && !create_if_missing)
|
||||
return current
|
||||
|
||||
var/new_current = 0
|
||||
for(var/datum/computer/folder/F in current.contents)
|
||||
if(ckey(F.name) == ckey(sort1[1]) && (!user || check_read_permission(F, user)))
|
||||
sort1 -= sort1[1]
|
||||
current = F
|
||||
new_current = 1
|
||||
break
|
||||
|
||||
if(!new_current)
|
||||
if (!create_if_missing)
|
||||
return null
|
||||
|
||||
var/datum/computer/folder/F = new /datum/computer/folder( )
|
||||
F.name = sort1[1]
|
||||
|
||||
if (is_name_invalid(F.name))
|
||||
//qdel(F)
|
||||
F.dispose()
|
||||
return null
|
||||
|
||||
. = current.add_file(F)
|
||||
if (!.)
|
||||
if (F)
|
||||
F.dispose()
|
||||
return null
|
||||
|
||||
else if (istype(., /datum/computer/folder))
|
||||
F = .
|
||||
|
||||
sort1 -= sort1[1]
|
||||
current = F
|
||||
new_current = 1
|
||||
|
||||
return null
|
||||
|
||||
//Find a file at the end of a given dirstring.
|
||||
parse_file_directory(string, var/datum/computer/folder/origin, var/create_if_missing, var/datum/mainframe2_user_data/user)
|
||||
if(!string)
|
||||
return null
|
||||
|
||||
var/datum/computer/folder/current = origin
|
||||
|
||||
if(!origin)
|
||||
origin = src.holder.root
|
||||
|
||||
if(dd_hasprefix(string , "/")) //if it starts with a /
|
||||
current = origin
|
||||
string = copytext(string,2)
|
||||
|
||||
var/list/sort1 = list()
|
||||
sort1 = dd_text2list(string,"/")
|
||||
|
||||
var/file_name = sort1[sort1.len]
|
||||
if(!file_name)
|
||||
return null
|
||||
|
||||
sort1 -= sort1[sort1.len]
|
||||
|
||||
while(current)
|
||||
|
||||
if(!sort1.len)
|
||||
var/datum/computer/file/check = get_file_name(file_name, current, user)
|
||||
if(check && istype(check))
|
||||
return check
|
||||
else
|
||||
return null
|
||||
|
||||
if(sort1[1] == "..")
|
||||
if (current == origin)
|
||||
return null
|
||||
current = current.holding_folder
|
||||
sort1 -= sort1[1]
|
||||
continue
|
||||
else if (sort1[1] == ".")
|
||||
sort1 -= sort1[1]
|
||||
continue
|
||||
|
||||
var/new_current = 0
|
||||
for(var/datum/computer/folder/F in current.contents)
|
||||
if(ckey(F.name) == ckey(sort1[1]) && (!user || check_read_permission(F, user)))
|
||||
sort1 -= sort1[1]
|
||||
current = F
|
||||
new_current = 1
|
||||
break
|
||||
|
||||
if(!new_current)
|
||||
if (!create_if_missing)
|
||||
return null
|
||||
|
||||
var/datum/computer/folder/F = new /datum/computer/folder
|
||||
F.name = sort1[1]
|
||||
|
||||
if (is_name_invalid(F.name) || !current.add_file(F))
|
||||
//qdel(F)
|
||||
F.dispose()
|
||||
return null
|
||||
|
||||
sort1 -= sort1[1]
|
||||
current = F
|
||||
new_current = 1
|
||||
|
||||
return null
|
||||
|
||||
//If we are willing to accept either a file or folder as the return value.
|
||||
parse_datum_directory(string, var/datum/computer/folder/origin, var/create_if_missing, var/datum/mainframe2_user_data/user)
|
||||
if(!string)
|
||||
return null
|
||||
|
||||
var/datum/computer/folder/current = origin
|
||||
|
||||
if(!origin)
|
||||
origin = src.holder.root
|
||||
|
||||
if(dd_hasprefix(string , "/")) //if it starts with a /
|
||||
if (string == "/")
|
||||
return origin
|
||||
current = origin
|
||||
string = copytext(string,2)
|
||||
|
||||
var/list/sort1 = list()
|
||||
sort1 = dd_text2list(string,"/")
|
||||
|
||||
var/datum_name = sort1[sort1.len]
|
||||
if(!datum_name)
|
||||
//return null
|
||||
sort1.len--
|
||||
while (sort1.len)
|
||||
datum_name = sort1[sort1.len]
|
||||
if (!datum_name)
|
||||
sort1.len--
|
||||
continue
|
||||
break
|
||||
|
||||
sort1.len = max(0, sort1.len-1)
|
||||
|
||||
while(current)
|
||||
|
||||
if(!sort1.len)
|
||||
switch(datum_name)
|
||||
if ("..")
|
||||
if (current == origin)
|
||||
return null
|
||||
return current.holding_folder
|
||||
if (".")
|
||||
return current
|
||||
var/datum/computer/check = get_computer_datum(datum_name, current, user)
|
||||
if(check && istype(check))
|
||||
return check
|
||||
else
|
||||
return null
|
||||
|
||||
if(sort1[1] == "..")
|
||||
current = current.holding_folder
|
||||
sort1 -= sort1[1]
|
||||
continue
|
||||
else if (sort1[1] == ".")
|
||||
sort1 -= sort1[1]
|
||||
continue
|
||||
|
||||
var/new_current = 0
|
||||
for(var/datum/computer/folder/F in current.contents)
|
||||
if(ckey(F.name) == ckey(sort1[1]) && (!user || check_read_permission(F, user)))
|
||||
sort1 -= sort1[1]
|
||||
current = F
|
||||
new_current = 1
|
||||
break
|
||||
|
||||
if(!new_current)
|
||||
if (!create_if_missing)
|
||||
return null
|
||||
|
||||
var/datum/computer/folder/F = new /datum/computer/folder
|
||||
F.name = sort1[1]
|
||||
|
||||
if (is_name_invalid(F.name) || !current.add_file(F))
|
||||
//qdel(F)
|
||||
F.dispose()
|
||||
return null
|
||||
|
||||
sort1 -= sort1[1]
|
||||
current = F
|
||||
new_current = 1
|
||||
|
||||
return null
|
||||
|
||||
New(obj/holding as obj)
|
||||
if(holding)
|
||||
src.holder = holding
|
||||
|
||||
if(istype(src.holder.loc,/obj/machinery/networked/mainframe))
|
||||
src.master = src.holder.loc
|
||||
|
||||
disposing()
|
||||
if(master && (src in master.processing))
|
||||
master.processing[src] = null
|
||||
master = null
|
||||
..()
|
||||
|
||||
asText()
|
||||
return initialized ? "[progid]" : ..()
|
||||
|
||||
proc
|
||||
input_text(var/text)
|
||||
if(!istype(src.master) || !text || !useracc)
|
||||
return 1
|
||||
|
||||
if(src.needs_holder)
|
||||
if(!istype(holder))
|
||||
return 1
|
||||
|
||||
if(!(holder in src.master.contents))
|
||||
return 1
|
||||
|
||||
if(master.stat & (NOPOWER|BROKEN|MAINT))
|
||||
return 1
|
||||
|
||||
if(src.needs_holder && !src.holder.root)
|
||||
src.holder.root = new /datum/computer/folder
|
||||
src.holder.root.holder = src
|
||||
src.holder.root.name = "root"
|
||||
|
||||
return 0
|
||||
|
||||
initialize(var/initparams) //Called when a program starts running.
|
||||
if(src.initialized || !master)
|
||||
return 1
|
||||
|
||||
src.initialized = 1
|
||||
return 0
|
||||
|
||||
//Note: If you want your application to end inteionally, send the OS an "exit" signal.
|
||||
//Use the mainframe_prog_exit macro. The program will not exit otherwise, even if nothing bothers to send it more input
|
||||
handle_quit()
|
||||
if(src.master)
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
|
||||
process()
|
||||
if (!istype(master))
|
||||
return 1
|
||||
|
||||
if (src.needs_holder)
|
||||
if (!istype(holder))
|
||||
return 1
|
||||
|
||||
if(!(holder in src.master.contents))
|
||||
master.processing.Remove(src)
|
||||
return 1
|
||||
|
||||
if(!src.holder.root)
|
||||
src.holder.root = new /datum/computer/folder
|
||||
src.holder.root.holder = src
|
||||
src.holder.root.name = "root"
|
||||
|
||||
return 0
|
||||
|
||||
parse_string(string, var/list/replaceList = null)
|
||||
var/list/sorted = list()
|
||||
sorted = command2list(string, " ", replaceList)
|
||||
if (!sorted.len) sorted.len++
|
||||
return sorted
|
||||
|
||||
//Find a folder with a given name
|
||||
get_folder_name(string, var/datum/computer/folder/check_folder, var/datum/mainframe2_user_data/user)
|
||||
if(!string || !istype(check_folder))
|
||||
return null
|
||||
|
||||
var/datum/computer/taken = null
|
||||
for(var/datum/computer/folder/F in check_folder.contents)
|
||||
if(ckey(string) == ckey(F.name) && (!user || check_read_permission(F, user)))
|
||||
taken = F
|
||||
break
|
||||
|
||||
return taken
|
||||
|
||||
//Find a file with a given name
|
||||
get_file_name(string, var/datum/computer/folder/check_folder, var/datum/mainframe2_user_data/user)
|
||||
if(!string || !istype(check_folder))
|
||||
return null
|
||||
|
||||
var/datum/computer/taken = null
|
||||
for(var/datum/computer/file/F in check_folder.contents)
|
||||
if(ckey(string) == ckey(F.name) && (!user || check_read_permission(F, user)))
|
||||
taken = F
|
||||
break
|
||||
|
||||
return taken
|
||||
|
||||
//Just find any computer datum with this name, gosh
|
||||
get_computer_datum(string, var/datum/computer/folder/check_folder, var/datum/mainframe2_user_data/user)
|
||||
if(!string || !istype(check_folder))
|
||||
return null
|
||||
|
||||
var/datum/computer/taken = null
|
||||
for(var/datum/computer/C in check_folder.contents)
|
||||
if(ckey(string) == ckey(C.name) && (!user || check_read_permission(C, user)))
|
||||
taken = C
|
||||
break
|
||||
|
||||
return taken
|
||||
|
||||
is_name_invalid(string) //Check if a filename is invalid somehow
|
||||
if(!string)
|
||||
return 1
|
||||
//ckeyEx because it allows for - and _ and we love those!!
|
||||
if(lowertext(ckeyEx(string)) != dd_replacetext(lowertext(string), " ", null))
|
||||
return 1
|
||||
|
||||
if(findtext(string, "/"))
|
||||
return 1
|
||||
|
||||
|
||||
return 0
|
||||
|
||||
//Pass an output string to the user terminal, with optional render value.
|
||||
//Notes: The string is not immediately set to the user! It is instead passed by signal to the parent task of the program.
|
||||
//This allows for piping operations, etc. It is the duty of the OS to actually tranmit the information to the terminal.
|
||||
message_user(var/msg, var/render, var/file)
|
||||
if (!useracc)
|
||||
return ESIG_NOTARGET
|
||||
|
||||
if (parent_task)
|
||||
if (render)
|
||||
return signal_program(parent_task.progid, list("command"=DWAINE_COMMAND_MSG_TERM, "data" = msg, "term" = useracc.user_id, "render" = render), file )
|
||||
else
|
||||
return signal_program(parent_task.progid, list("command"=DWAINE_COMMAND_MSG_TERM, "data" = msg, "term" = useracc.user_id), file )
|
||||
|
||||
return ESIG_GENERIC
|
||||
|
||||
read_user_field(var/field)
|
||||
if (!useracc || (!istype(useracc.user_file) && !useracc.reload_user_file()))
|
||||
return null
|
||||
|
||||
return useracc.user_file.fields[field]
|
||||
|
||||
write_user_field(var/field, var/data)
|
||||
if (!useracc || !field || (!istype(useracc.user_file) && !useracc.reload_user_file()) || !useracc.user_file.fields)
|
||||
return 0
|
||||
|
||||
useracc.user_file.fields[field] = data
|
||||
return 1
|
||||
|
||||
signal_program(var/progid, var/list/data, var/datum/computer/file/file)
|
||||
if(!data || !master)
|
||||
return 1
|
||||
|
||||
if(useracc && useracc.user_file && ("id" in useracc.user_file.fields))
|
||||
data["user"] = useracc.user_file.fields["id"]
|
||||
|
||||
return master.relay_progsignal(src, progid, data, file)
|
||||
|
||||
receive_progsignal(var/sendid, var/list/data, var/datum/computer/file/file)
|
||||
return (!src.master || !(src in master.processing))
|
||||
|
||||
|
||||
unloaded()
|
||||
return
|
||||
|
||||
check_read_permission(var/datum/computer/cdatum, var/datum/mainframe2_user_data/usdat)
|
||||
if (!usdat)
|
||||
return 0
|
||||
|
||||
if (istype(cdatum, /datum/computer/folder/link) && cdatum:target)
|
||||
cdatum = cdatum:target
|
||||
|
||||
if (!istype(cdatum) || !cdatum.metadata)
|
||||
return 0
|
||||
|
||||
var/permissions = COMP_ALLACC
|
||||
if (isnum(cdatum.metadata["permission"]))
|
||||
permissions = cdatum.metadata["permission"]
|
||||
|
||||
if (istype(usdat.user_file) || usdat.reload_user_file())
|
||||
if (!usdat.user_file.fields)
|
||||
usdat.user_file.fields = list()
|
||||
|
||||
if (usdat.user_file.fields["group"] == 0) //Sysop usergroup
|
||||
return 1
|
||||
|
||||
if (cdatum.metadata["owner"] && (usdat.user_file.fields["name"] == cdatum.metadata["owner"]) && (permissions & COMP_ROWNER))
|
||||
return 1
|
||||
|
||||
if (cdatum.metadata["group"] && (usdat.user_file.fields["group"] == cdatum.metadata["group"]) && (permissions & COMP_RGROUP))
|
||||
return 1
|
||||
|
||||
return (permissions & COMP_ROTHER)
|
||||
|
||||
check_write_permission(var/datum/computer/cdatum, var/datum/mainframe2_user_data/usdat)
|
||||
if (!cdatum || !usdat)
|
||||
return 0
|
||||
|
||||
var/permissions = COMP_ALLACC
|
||||
|
||||
if (istype(cdatum, /datum/computer/folder/link) && cdatum:target)
|
||||
cdatum = cdatum:target
|
||||
|
||||
if (!istype(cdatum) || !cdatum.metadata)
|
||||
return 0
|
||||
|
||||
if (istype(cdatum.metadata, /list) && isnum(cdatum.metadata["permission"]))
|
||||
permissions = cdatum.metadata["permission"]
|
||||
|
||||
if (istype(usdat.user_file) || usdat.reload_user_file())
|
||||
|
||||
if (usdat.user_file.fields["group"] == 0) //Sysop usergroup can ~do anything~
|
||||
return 1
|
||||
|
||||
if (cdatum.metadata["owner"] && (usdat.user_file.fields["name"] == cdatum.metadata["owner"]) && (permissions & COMP_WOWNER))
|
||||
return 1
|
||||
|
||||
if (cdatum.metadata["group"] && (usdat.user_file.fields["group"] == cdatum.metadata["group"]) && (permissions & COMP_WGROUP))
|
||||
return 1
|
||||
|
||||
return (permissions & COMP_WOTHER)
|
||||
|
||||
return 0
|
||||
|
||||
check_mode_permission(var/datum/computer/cdatum, var/datum/mainframe2_user_data/usdat)
|
||||
if (!cdatum || !usdat)
|
||||
return 0
|
||||
|
||||
if (istype(cdatum, /datum/computer/folder/link) && cdatum:target)
|
||||
cdatum = cdatum:target
|
||||
|
||||
if (!istype(cdatum) || !cdatum.metadata)
|
||||
return 0
|
||||
|
||||
var/permissions = COMP_ALLACC
|
||||
if (istype(cdatum.metadata, /list) && isnum(cdatum.metadata["permission"]))
|
||||
permissions = cdatum.metadata["permission"]
|
||||
|
||||
if (istype(usdat.user_file) || usdat.reload_user_file())
|
||||
|
||||
if (usdat.user_file.fields["group"] == 0) //Sysop usergroup can ~do anything~
|
||||
return 1
|
||||
|
||||
if (cdatum.metadata["owner"] && (usdat.user_file.fields["name"] == cdatum.metadata["owner"]) && (permissions & COMP_DOWNER && permissions & COMP_WOWNER) )
|
||||
return 1
|
||||
|
||||
if (cdatum.metadata["group"] && (usdat.user_file.fields["group"] == cdatum.metadata["group"]) && (permissions & COMP_DGROUP && permissions & COMP_WGROUP) )
|
||||
return 1
|
||||
|
||||
return ((permissions & COMP_DOTHER) && (permissions & COMP_WOTHER))
|
||||
|
||||
return 0
|
||||
|
||||
//Command2list is a modified version of dd_text2list() designed to eat empty list entries generated by superfluous whitespace.
|
||||
//It also can insert shell alias/variables if provided with a replacement value list.
|
||||
#define QUOTE_SYMBOL "\""
|
||||
#define QUOTE_SYMBOL_LENGTH 1
|
||||
/proc/command2list(text, separator, list/replaceList, list/substitution_feedback_thing)
|
||||
var/textlength = length(text)
|
||||
var/separatorlength = length(separator)
|
||||
var/list/textList = new()
|
||||
var/searchPosition = 1
|
||||
var/findPosition = 1
|
||||
var/buggyText
|
||||
|
||||
|
||||
//substitution_feedback_thing = list() //debug
|
||||
while(1)
|
||||
findPosition = findtext(text, separator, searchPosition, 0)
|
||||
var/quotePoint = findtext(text, QUOTE_SYMBOL, searchPosition, findPosition)
|
||||
if (quotePoint)
|
||||
text = copytext(text, 1, quotePoint) + copytext(text, quotePoint + QUOTE_SYMBOL_LENGTH, 0)
|
||||
var/quotePointEnd = findtext(text, QUOTE_SYMBOL, quotePoint, 0)
|
||||
buggyText = copytext(text, searchPosition, quotePointEnd)
|
||||
findPosition = quotePointEnd+QUOTE_SYMBOL_LENGTH
|
||||
else
|
||||
var/subStartPoint = findtext(text, "$(", searchPosition, findPosition)
|
||||
if (substitution_feedback_thing && subStartPoint)
|
||||
var/subEndPoint = findtext(text, ")", subStartPoint)
|
||||
substitution_feedback_thing[++substitution_feedback_thing.len] = copytext(text, subStartPoint+2, subEndPoint)
|
||||
|
||||
text = copytext(text, 1, subStartPoint) + "_sub[substitution_feedback_thing.len]" + copytext(text, subEndPoint ? subEndPoint + 1 : 0)
|
||||
//boutput(world, "text changed to \"[text]\"")
|
||||
|
||||
//boutput(world, "added: \[[substitution_feedback_thing[substitution_feedback_thing.len]]]")
|
||||
|
||||
continue
|
||||
|
||||
else
|
||||
buggyText = trim(copytext(text, searchPosition, findPosition))
|
||||
|
||||
if(buggyText)
|
||||
|
||||
if (replaceList && dd_hasprefix(buggyText, "$") && (copytext(buggyText,2) in replaceList))
|
||||
textList += "[replaceList[copytext(buggyText, 2)]]"
|
||||
else
|
||||
textList += "[buggyText]"
|
||||
if(!findPosition)
|
||||
//boutput(world, english_list(textList))
|
||||
return textList
|
||||
searchPosition = findPosition + separatorlength
|
||||
if(searchPosition > textlength)
|
||||
//boutput(world, english_list(textList))
|
||||
return textList
|
||||
return
|
||||
|
||||
#undef QUOTE_SYMBOL
|
||||
#undef QUOTE_SYMBOL_LENGTH
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
//CONTENTS:
|
||||
//DWAINE system help file
|
||||
//Guardbot readme
|
||||
//Guardbot demo patrol script file
|
||||
//Guardbot demo bodyguard script file
|
||||
//Guardbot demo configuration file
|
||||
//Artifact research readme
|
||||
|
||||
|
||||
/*
|
||||
* Help record - Individual entries accessed by shell "help" command. "index" entry generated programmatically.
|
||||
*/
|
||||
/datum/computer/file/record/dwaine_help
|
||||
name = "help"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.fields["basics1"] = "DWAINE is a multi-user Unix-like operating system produced by Thinktronic Data Systems. The primary user interface is through a text-based terminal shell.|nApplications may be invoked simply by typing their filename, followed by a list of arguments if necessary. A set of primary commands, those covering basic system tasks (Such as ls and cd), are made available to all users regardless of location in the filesystem. Otherwise, applications must be in the user's current working directory to run."
|
||||
src.fields["basics2"] = "Directory navigation is accomplished primarily through the ls and cd commands.|nLS, an abbreviation of \"list\" will list the contents of the current directory. The argument -l will cause it to also display extended file information and hidden files.|nCD, or \"change directory\" will set the current directory to the provided path, if valid. A filepath takes a form such as \"/mnt/drive0\" Paths starting with / descend from the root directory \"..\" refers to the directory one level up from the current, while \".\" refers to the current directory.|nEx: \"cd ../hams\" would specify a directory named ham with the same parent as the current working one."
|
||||
src.fields["basics3"] = "DWAINE is, primarily, a networked system. All devices, from user terminals to lineprinters and tape drives, are connected remotely to the central mainframe. Devices that interact with files, such as drives or printers, may appear as part of the filesystem as a sub-directory of /mnt.|nFor example, the contents of tape databank \"Main\" would appear within /mnt/main and applications and other files could be accessed by setting it to your working directory with \"cd /mnt/main\""
|
||||
src.fields["basics4"] = "Application software is often bundled with a \"readme\" file of some sort, which can be viewed with the CAT command.|nEx: \"cat readme\" will view the contents of a readme file in the user's working directory."
|
||||
src.fields["ls"] = "View contents of a directory. If no filepath is supplied, the working directory will be listed.|nExpanded file information, as well as hidden files, may be viewed through use of the -l argument.|nUsage: ls \[-l] \[filepath]"
|
||||
src.fields["cd"] = "Change working directory to the filepath supplied as argument.|nUsage: cd \"filepath\""
|
||||
src.fields["cat"] = "Combine the contents of one or more data files and print result to current output (Default output would be the user terminal). Use with executable files is inadvisable.|nUsage: cat \"filepath\" \[filepath...]"
|
||||
src.fields["echo"] = "Print text to current stream. Stream defaults to standard output (User terminal screen) if not piping.|nIf piping, output is passed on. If the piping target is not an executable, an attempt will be made to write to that file.|nUsage: echo \"text\" OR echo \"text\" | pipe_file_name"
|
||||
src.fields["eval"] = "Evaluate an expression. Stack based with RPN input--the operation is expressed following the inputs, like \"1 2 +\" will result in 3.|nInput values are placed in order in a \"stack,\" with most recent input on top and first input on the bottom. Values are taken back off the stack from the top down. Operations act on the top 1 or 2 values on the stack, usually removing them and placing the result as the new top.|nValid operations are +, -, *, /, %, for arithmetic operations.|neq (equal), neq (not equal), gt (greater than), ge (greater or equal), lt (less than), le (less or equal) for comparison operations,|nAnd, Or, Not, and Xor for logical operations.|nThe operator DUP will copy the top value on the stack without removing anything from the stack.|nText surrounded by apostrophes will be interpreted as a string. Variables may be set by pushing the desired value to the stack and then using the TO operator and a variable name. For example, \"5 to HAMDAD\" would create a variable with the name HAMDAD and value 5.|nThere are also four file checking operators: d, e, f, and x. Each take a filepath string from the top of the stack and leave a boolean value in its place. d leaves a true if the path is to a folder, x is true if the path is to an executable, f is true if the path is to a file, and e is true if the path is to anything at all."
|
||||
src.fields["who"] = "Print list of current users to current output.|nUsage: who"
|
||||
src.fields["mesg"] = "Control acceptance of messages sent by other users.|nUsage mesg \"(y/n)\""
|
||||
src.fields["talk"] = "Send a message to another current user.|nUsage talk \"user name or user terminal ID\" \"message\""
|
||||
src.fields["cp"] = "Copy datafile to a new location. If new filepath specifies only a directory, the copy will retain original name.|nUsage: cp \"target filepath\" \"new filepath\""
|
||||
src.fields["mv"] = "Move datafile to a new location. If new filepath specifies only a directory, the file will retain original name.|nUsage: mv \"target filepath\" \"new filepath\""
|
||||
src.fields["rm"] = "Delete datafile or directory. Use of -r switch required for directory deletion. -i switch enables confirmation prompt, while -f suppresses this and error messages.|nUsage: rm \"target filepath\""
|
||||
src.fields["su"] = "Assume superuser status. An authorized ID must be provided.|nUsage: \"su\""
|
||||
src.fields["mkdir"] = "Create a directory or set of directories with the provided paths.|nUsage: mkdir \[filepath...]"
|
||||
src.fields["chmod"] = "Change the permissions of a file. File permissions take the form of three octal digits in the order of: owner, group, any user.|nBit one (The least significant bit) of each field controls modify access, bit two controls write access, and the third bit controls read access.|nUsage: chmod \"access value, i.e 777\" \"filename\""
|
||||
src.fields["chown"] = "Change the owner and/or group of a file. System operator status required to invoke.|nUsage: chown \[exact username]:\[group ID] \"filename\""
|
||||
src.fields["mount"] = "Mount device driver file space to filesystem. System operator status required to invoke.|nUsage: mount \"device net ID\" \"mountpoint name (Name for folder in /mnt)\""
|
||||
src.fields["scnt"] = "Scan network for unconnected peripheral devices, and then automatically connect to them. System operator status required to invoke.|nSpecific net IDs may be provided as arguments to connect to them directly. |nUsage: \"scnt\""
|
||||
src.fields["logoff"] = "Log out current user and ready system to accept new login.|nUsage: \"logoff\""
|
||||
|
||||
src.fields["index"] = "Usage: help \"topic\"|nValid Topics: [english_list(src.fields, "None")]"
|
||||
|
||||
/datum/computer/file/record/pr6_readme
|
||||
name = "readme"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.fields = list("Readme for PR-6 Control Interface",
|
||||
"Notice: Superuser access may be required to run prman application",
|
||||
"Please ready authorized heads ID and type \"su\"",
|
||||
"",
|
||||
"A series of demo files have been supplied, as well as PR-6 task packages.",
|
||||
"patrol_script takes one argument, the net id of the target bot. It may be invoked by \"patrol_script (bot id)\"",
|
||||
"guard_script takes two arguments, the net id of the target bot and the full name, with no spaces, of the person to protect.",
|
||||
"demo_conf is a demonstration configuration file to set bodyguard tasks to guard \"John Doe\"",
|
||||
"Valid PR-6 net ids may be listed via \"prman list\"",
|
||||
"PR-6 units may be recalled via \"prman recall (id)\" The id may either correspond to the actual PR-6 unit or its last used dock.",
|
||||
"If no arguments are supplied to prman, it will list valid commands.")
|
||||
|
||||
/datum/computer/file/record/patrol_script
|
||||
name = "patrol_script"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.fields = list("#!",
|
||||
"#demonstration patrol script",
|
||||
"#takes bot net id as argument",
|
||||
"if $argc 1 lt | echo Error: No Net ID specified! | break",
|
||||
"if $su 1 ne | echo Please authenticate (su) prior to invocation. | break",
|
||||
//FUN NOTE; Why do we use /conf instead of just the local directory?
|
||||
//"echo patrol=1|/conf/confpatrol",
|
||||
//Because this file is, by default, on a tape drive. The write time on secondary storage is such that
|
||||
//"prman upload $arg0 secure -f /conf/confpatrol",
|
||||
//by the time the file is visible, prman would've already looked and failed to find it.
|
||||
|
||||
"prman upload $arg0 secure patrol=1;",
|
||||
"prman wake $arg0")
|
||||
|
||||
/datum/computer/file/record/bodyguard_script
|
||||
name = "guard_script"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.fields = list("#!",
|
||||
"#simple bodyguard script",
|
||||
"#takes bot net id and spaceless target name as argument",
|
||||
"#ex: guard_script 02000050 johndoe",
|
||||
"if argc 2 lt | echo Error: No Net ID or target name specified! | break",
|
||||
"if su 1 ne | echo Please authenticate (su) prior to invocation. | break",
|
||||
//"echo name= | echo $arg1|/conf/confguard",
|
||||
//"prman upload $arg0 bodyguard -f /conf/confguard",
|
||||
"prman upload $arg0 bodyguard name= $arg1",
|
||||
"prman wake $arg0")
|
||||
|
||||
/datum/computer/file/record/roomguard_script
|
||||
name = "roomguard_script"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.fields = list("#!",
|
||||
"#Bot will only look for targets in the same area.",
|
||||
"#takes bot net id as argument",
|
||||
"if $argc 1 lt | echo Error: No Net ID specified! | break",
|
||||
"if $su 1 ne | echo Please authenticate (su) prior to invocation. | break",
|
||||
"prman upload $arg0 areaguard",
|
||||
"prman wake $arg0")
|
||||
|
||||
/datum/computer/file/record/bodyguard_conf
|
||||
name = "demo_conf"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.fields = list("#demonstration of configuration file",
|
||||
"#for bodyguard and secure tasks",
|
||||
"name=john doe",
|
||||
"#this is the name of the protected individual",
|
||||
"",
|
||||
"#this is for use with the secure task",
|
||||
"patrol=1",
|
||||
"",
|
||||
"#prman upload bot_id bodyguard patrol=1",
|
||||
"or",
|
||||
"#prman upload bot_id bodyguard -f demo_conf")
|
||||
|
||||
/*
|
||||
* Emails!!
|
||||
*/
|
||||
|
||||
/proc/get_random_email_list()
|
||||
return strings("mainframe/documents/randomEmail.txt", "availableMail")
|
||||
|
||||
/datum/computer/file/record/random_email
|
||||
|
||||
New(mailName as text)
|
||||
..()
|
||||
src.name = "[copytext("\ref[src]", 4, 12)]GENERIC"
|
||||
if (mailName)
|
||||
src.fields = strings("mainframe/documents/randomEmail.txt", mailName)
|
||||
@@ -0,0 +1,250 @@
|
||||
//CONTENTS
|
||||
//Email daemon thing
|
||||
|
||||
/datum/computer/file/mainframe_program/srv/email
|
||||
name = "mail"
|
||||
size = 1
|
||||
|
||||
var/setup_email_folder = "/etc/mail"
|
||||
var/setup_mailgroup_table = "groups"
|
||||
var/defaultDomain = "NT13"
|
||||
|
||||
initialize(var/initparams)
|
||||
if (..() || !useracc)
|
||||
mainframe_prog_exit
|
||||
return
|
||||
//todo: all of this. All of this forever.
|
||||
|
||||
//boutput(world, "[initparams]")
|
||||
|
||||
var/command = null
|
||||
var/list/initlist = dd_text2list(initparams, " ")
|
||||
if (!initparams || !initlist.len)
|
||||
command = "index"
|
||||
else
|
||||
command = ckey(initlist[1])
|
||||
|
||||
var/user_name = dd_hasprefix(useracc.user_name, "SRV") ? copytext(useracc.user_name, 4, length(useracc.user_name)) : copytext(useracc.user_name, 1, length(useracc.user_name))
|
||||
|
||||
//boutput(world, "Username: \"[useracc.user_name]\" -> \"[user_name]\"")
|
||||
|
||||
switch (command)
|
||||
if ("index")
|
||||
var/group = null
|
||||
if (initlist.len > 1)
|
||||
group = initlist[2]
|
||||
var/list/mail_subjects = list_mail_subjects(user_name, group)
|
||||
var/message = "mail_index"
|
||||
if (mail_subjects.len)
|
||||
message += "|n" + dd_list2text(mail_subjects, "|n")
|
||||
message_user(message, "record")
|
||||
|
||||
if ("get")
|
||||
var/index = 0
|
||||
var/group = null
|
||||
if (initlist.len > 1)
|
||||
index = max( round(text2num(initlist[2])), 1)
|
||||
|
||||
if (initlist.len > 2)
|
||||
group = initlist[3]
|
||||
|
||||
var/list/mailList = list_mail_for(user_name, group)
|
||||
if (!istype(mailList) || mailList.len < index)
|
||||
mainframe_prog_exit
|
||||
return
|
||||
|
||||
var/datum/computer/file/record/targetMail = mailList[index]
|
||||
if (istype(targetMail) && parent_task)
|
||||
targetMail = format_outgoing_mail(targetMail)
|
||||
message_user("mail_entry",null,targetMail)
|
||||
|
||||
if ("send")
|
||||
if (initlist.len > 1)
|
||||
var/sentMailPath = initlist[2]
|
||||
if (!dd_hasprefix(sentMailPath, "/"))
|
||||
sentMailPath = "/[sentMailPath]"
|
||||
|
||||
var/datum/computer/file/record/sentMail = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"="[sentMailPath]"))
|
||||
if (istype(sentMail))
|
||||
sentMail = sentMail.copy_file()
|
||||
sentMail.fields = sentMail.fields.Copy()
|
||||
if (send_mail_to(sentMail) == 0)
|
||||
message_user("ack")
|
||||
else
|
||||
message_user("nack")
|
||||
|
||||
if ("delete")
|
||||
var/index = 0
|
||||
var/group = null
|
||||
if (initlist.len > 1)
|
||||
index = max( round(text2num(initlist[2])), 1)
|
||||
|
||||
if (initlist.len > 2)
|
||||
group = initlist[3]
|
||||
|
||||
var/list/mailList = list_mail_for(user_name, group)
|
||||
if (!istype(mailList) || mailList.len < index)
|
||||
mainframe_prog_exit
|
||||
return
|
||||
|
||||
var/datum/computer/file/record/targetMail = mailList[index]
|
||||
if (istype(targetMail) && dd_hassuffix(targetMail.name, user_name))
|
||||
if (signal_program(1, list("command"=DWAINE_COMMAND_FKILL, "path"="[setup_email_folder]/[targetMail.name]")) == ESIG_SUCCESS)
|
||||
message_user("ack")
|
||||
else
|
||||
message_user("nack")
|
||||
else
|
||||
message_user("nack")
|
||||
|
||||
mainframe_prog_exit
|
||||
return
|
||||
|
||||
proc
|
||||
format_outgoing_mail(var/datum/computer/file/record/mail)
|
||||
if (!istype(mail) || !mail.fields || (mail.fields.len < 6))
|
||||
return null
|
||||
|
||||
var/datum/computer/file/record/newMail = mail.copy_file()
|
||||
newMail.fields = newMail.fields.Copy()
|
||||
var/compactHeader = "mailnet=[mail.fields[1] ? mail.fields[1] : "???"]&group=[mail.fields[2] ? mail.fields[2] : "???"]"
|
||||
compactHeader += "&sender=[mail.fields[3] ? mail.fields[3] : "???"]&target=[mail.fields[4] ? mail.fields[4] : "???"]"
|
||||
compactHeader += "&priority=[mail.fields[5] ? mail.fields[5] : "LOW"]&subj=[mail.fields[6] ? mail.fields[6] : "???"]"
|
||||
|
||||
newMail.fields[1] = compactHeader
|
||||
newMail.fields.Cut(2, 7)
|
||||
|
||||
return newMail
|
||||
|
||||
send_mail_to(var/datum/computer/file/record/mail)
|
||||
if (!istype(mail) || !mail.fields.len)
|
||||
return 1
|
||||
|
||||
var/list/mailHeader = params2list(mail.fields[1])
|
||||
if (!mailHeader)
|
||||
return 2
|
||||
|
||||
var/target = mailHeader["target"]
|
||||
var/target_name = target
|
||||
var/atLocation = findtext(target, "@")
|
||||
if (atLocation)
|
||||
target_name = copytext(target,1, atLocation)
|
||||
|
||||
var/mailgroup = ckey(mailHeader["group"]) ? mailHeader["group"] : "*NONE"
|
||||
|
||||
if (!target && !mailgroup)
|
||||
return 3
|
||||
|
||||
var/datum/computer/folder/mailgroupTable = null
|
||||
if (mailgroup && lowertext(mailgroup) != "*all" && lowertext(mailgroup) != "*none")
|
||||
mailgroupTable = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"="[setup_email_folder]/[setup_mailgroup_table]"))
|
||||
if (!istype(mailgroupTable))
|
||||
return 4
|
||||
|
||||
mail.fields.Cut(1,2)
|
||||
mail.name = "[copytext("\ref[mail]", 4, 12)][target_name ? lowertext(target_name) : "all"]"
|
||||
mail.fields.Insert(1, "PUBLIC_NT", "[uppertext(mailgroup)]","[ckeyEx(mailHeader["sender"]) ? copytext(uppertext(ckeyEx(mailHeader["sender"])), 1, 33) : "???"][dd_hassuffix(mailHeader["sender"], "@[defaultDomain]") ? null : "@[defaultDomain]"]",\
|
||||
"[target ? target : "ALL"]",\
|
||||
"[ckeyEx(mailHeader["priority"]) ? copytext(uppertext(ckeyEx(mailHeader["priority"])), 1, 9) : "LOW"]",\
|
||||
"[ckeyEx(mailHeader["subj"]) ? copytext(uppertext(mailHeader["subj"]), 1, 33) : "???"]")
|
||||
|
||||
if (signal_program(1, list("command"=DWAINE_COMMAND_FWRITE, "path"="[setup_email_folder]", "mkdir"=1), mail) == ESIG_SUCCESS)
|
||||
return 0
|
||||
|
||||
return 5
|
||||
|
||||
list_mail_for(var/target, var/mailgroup=null)//"*all")
|
||||
if (!target && !mailgroup)
|
||||
return
|
||||
|
||||
var/list/mailList = list()
|
||||
var/datum/computer/folder/mailFolder = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"="[setup_email_folder]"))
|
||||
if (!istype(mailFolder))
|
||||
return mailList
|
||||
|
||||
var/datum/computer/file/record/mailgroupTable = null
|
||||
var/list/groupTargets = null
|
||||
if (!(mailgroup && lowertext(mailgroup) != "*all"))
|
||||
groupTargets = list()
|
||||
mailgroupTable = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"="[setup_email_folder]/[setup_mailgroup_table]"))
|
||||
if (istype(mailgroupTable))
|
||||
for (var/groupDef in mailgroupTable.fields)
|
||||
if (findtext(groupDef, "[target],"))
|
||||
groupTargets += "[copytext(groupDef, 1, findtext(groupDef, ":"))]"
|
||||
break
|
||||
|
||||
for(var/datum/computer/file/record/emailRec in mailFolder.contents)
|
||||
if (!check_read_permission(emailRec, useracc))
|
||||
continue
|
||||
|
||||
if ((emailRec.fields.len >= 2) && lowertext(emailRec.fields[2]) == "*all")
|
||||
mailList += emailRec
|
||||
continue
|
||||
|
||||
if (groupTargets && groupTargets.len)
|
||||
var/success = 0
|
||||
for (var/groupMember in groupTargets)
|
||||
if (emailRec.fields.len >= 2 && (lowertext(groupMember) == lowertext(emailRec.fields[2])))
|
||||
mailList += emailRec
|
||||
success = 1
|
||||
break
|
||||
|
||||
if (success)
|
||||
continue
|
||||
|
||||
if (target && dd_hassuffix(emailRec.name, target))
|
||||
mailList += emailRec
|
||||
continue
|
||||
|
||||
return mailList
|
||||
|
||||
|
||||
list_mail_subjects(var/target, var/mailgroup=null)//"*all")
|
||||
if (!target && !mailgroup)
|
||||
return
|
||||
|
||||
var/list/mailSubjs = list()
|
||||
var/datum/computer/folder/mailFolder = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"="[setup_email_folder]"))
|
||||
if (!istype(mailFolder))
|
||||
return mailSubjs
|
||||
|
||||
var/datum/computer/file/record/mailgroupTable = null
|
||||
var/list/groupTargets = null
|
||||
if (!(mailgroup && lowertext(mailgroup) != "*all"))
|
||||
groupTargets = list()
|
||||
mailgroupTable = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"="[setup_email_folder]/[setup_mailgroup_table]"))
|
||||
if (istype(mailgroupTable))
|
||||
for (var/groupDef in mailgroupTable.fields)
|
||||
if (findtext(groupDef, "[target],"))
|
||||
groupTargets += "[copytext(groupDef, 1, findtext(groupDef, ":"))]"
|
||||
break
|
||||
|
||||
for(var/datum/computer/file/record/emailRec in mailFolder.contents)
|
||||
if (!check_read_permission(emailRec, useracc))
|
||||
continue
|
||||
|
||||
if (!emailRec.fields || emailRec.fields.len < 6)
|
||||
continue
|
||||
|
||||
if (lowertext(emailRec.fields[2]) == "*all")
|
||||
mailSubjs.len++
|
||||
mailSubjs[mailSubjs.len] = copytext(emailRec.fields[6], 1, 33)
|
||||
continue
|
||||
|
||||
if (groupTargets && groupTargets.len)
|
||||
var/success = 0
|
||||
for (var/groupMember in groupTargets)
|
||||
if (lowertext(groupMember) == lowertext(emailRec.fields[2]))
|
||||
mailSubjs.len++
|
||||
mailSubjs[mailSubjs.len] = copytext(emailRec.fields[6], 1, 33)
|
||||
success = 1
|
||||
break
|
||||
|
||||
if (success)
|
||||
continue
|
||||
|
||||
if (target && dd_hassuffix(emailRec.name, target))
|
||||
mailSubjs.len++
|
||||
mailSubjs[mailSubjs.len] = copytext(emailRec.fields[6], 1, 33)
|
||||
continue
|
||||
|
||||
return mailSubjs
|
||||
@@ -0,0 +1,67 @@
|
||||
|
||||
|
||||
//Filetype used to store information on current user
|
||||
/datum/computer/file/user_data
|
||||
name = "user account"
|
||||
extension = "USR"
|
||||
size = 1
|
||||
|
||||
//Store the data an ID card would.
|
||||
var/registered = null
|
||||
var/assignment = null
|
||||
var/list/access = list()
|
||||
//And some more
|
||||
var/net_id = null
|
||||
var/tmp/authlevel = 0
|
||||
var/tmp/datum/computer/file/mainframe_program/active_program = null
|
||||
var/tmp/datum/computer/folder/current_folder = null
|
||||
|
||||
disposing()
|
||||
active_program = null
|
||||
current_folder = null
|
||||
access = null
|
||||
|
||||
..()
|
||||
|
||||
/*
|
||||
* User Account Datum
|
||||
*/
|
||||
|
||||
/datum/mainframe2_user_data
|
||||
var/datum/computer/file/record/user_file = null
|
||||
var/datum/computer/folder/user_file_folder = null
|
||||
var/user_filename = null
|
||||
var/user_name = "GENERIC"
|
||||
var/user_id = null
|
||||
var/full_user = 0
|
||||
var/datum/computer/file/mainframe_program/current_prog = null
|
||||
|
||||
disposing()
|
||||
current_prog = null
|
||||
user_file = null
|
||||
user_file_folder = null
|
||||
|
||||
..()
|
||||
|
||||
proc/reload_user_file()
|
||||
if (!user_file_folder || !user_filename)
|
||||
return 0
|
||||
|
||||
for (var/datum/computer/file/record/potential in user_file_folder.contents)
|
||||
if (potential.name == user_filename)
|
||||
user_file = potential
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/datum/computer/file/document
|
||||
name = "Document"
|
||||
extension = "DOC"
|
||||
var/list/textlist = list() //Actual document text
|
||||
var/list/metalist = list() //Instructions on how to process each line.
|
||||
|
||||
disposing()
|
||||
textlist = null
|
||||
metalist = null
|
||||
|
||||
..()
|
||||
@@ -0,0 +1,754 @@
|
||||
#define ACCESSLOG_RECORDS_LIMIT 256
|
||||
#define DEFAULT_LOG_PATH "/var/log/door-access"
|
||||
#define MAINFRAME_ACCESSLOG_DRIVER_HACK
|
||||
|
||||
/datum/computer/file/record/accesslog_default_config
|
||||
name = "accesslog"
|
||||
New()
|
||||
..()
|
||||
fields = list("logdir" = DEFAULT_LOG_PATH)
|
||||
|
||||
/obj/machinery/networked/logreader
|
||||
icon = 'icons/obj/computer.dmi'
|
||||
icon_state = "computer_generic"
|
||||
name = "door access logs"
|
||||
density = 1
|
||||
anchored = 1
|
||||
device_tag = "PNET_LOGREADER"
|
||||
timeout = 10
|
||||
mats = 14
|
||||
power_usage = 100
|
||||
var/static/list/required_fields = list("card_name", "door_name", "time_t", "timestamp", "door_id", "action")
|
||||
var/filter_name = null
|
||||
var/ftb_min = null
|
||||
var/ftb_sec = null
|
||||
var/fte_min = null
|
||||
var/fte_sec = null
|
||||
var/filter_door_id = null
|
||||
var/filter_action = null
|
||||
var/machine_screen = 1
|
||||
var/list/records = list()
|
||||
var/refreshing = 0
|
||||
var/refresh_id = 0
|
||||
var/timed_out = 0
|
||||
var/spoofed = 0
|
||||
|
||||
New()
|
||||
..()
|
||||
spawn(5)
|
||||
src.net_id = generate_net_id(src)
|
||||
|
||||
if(!src.link)
|
||||
var/turf/T = get_turf(src)
|
||||
var/obj/machinery/power/data_terminal/test_link = locate() in T
|
||||
if(test_link && !test_link.is_valid_master(test_link.master))
|
||||
src.link = test_link
|
||||
src.link.master = src
|
||||
|
||||
attack_hand(var/mob/user)
|
||||
if(..() || (stat & (NOPOWER|BROKEN)))
|
||||
return
|
||||
|
||||
user.machine = src
|
||||
|
||||
var/dat = {"<html><head><title>Access Log Reader</title><style>
|
||||
.conn-box {
|
||||
float: right;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
display: block;
|
||||
display: inline-block;
|
||||
border: 1px solid #888888;
|
||||
}
|
||||
|
||||
.conn-ok {
|
||||
background-color: #33FF00;
|
||||
}
|
||||
|
||||
.conn-no {
|
||||
background-color: #F80000;
|
||||
}
|
||||
|
||||
.conn-error {
|
||||
background-color: #888888;
|
||||
}
|
||||
|
||||
</style></head><body>"}
|
||||
|
||||
|
||||
var/readout_class = "conn-error"
|
||||
var/readout = "ERROR"
|
||||
if(src.host_id)
|
||||
readout_class = "conn-ok"
|
||||
readout = "OK CONNECTION"
|
||||
else
|
||||
readout_class = "conn-no"
|
||||
readout = "NO CONNECTION"
|
||||
|
||||
dat += "<div class='conn-box [readout_class]'></div>"
|
||||
if (!refreshing)
|
||||
if (machine_screen == 1)
|
||||
dat += "<b>Connection</b> | <a href='?src=\ref[src];screen=2'>Data</a>"
|
||||
else if (machine_screen == 2)
|
||||
dat += "<a href='?src=\ref[src];screen=1'>Connection</a> | <b>Data</b>"
|
||||
else if (!refreshing)
|
||||
dat += "<a href='?src=\ref[src];screen=1'>Connection</a> | <a href='?src=\ref[src];screen=2'>Data</a>"
|
||||
|
||||
|
||||
dat += "<hr><br>"
|
||||
|
||||
|
||||
if (machine_screen == 1)
|
||||
dat += "<b>Host Connection:</b>"
|
||||
dat += "<table border='1' class='[readout_class]'><tr><td><font color=white>[readout]</font></td></tr></table><br>"
|
||||
dat += "<a href='?src=\ref[src];reset=1'>Reset Connection</a><br>"
|
||||
|
||||
if (src.panel_open)
|
||||
dat += net_switch_html()
|
||||
|
||||
else if (machine_screen == 2)
|
||||
dat += "<h3>Door access logs</h3>"
|
||||
if (spoofed)
|
||||
dat += "<i>Warning: could not verify authenticity of displayed data.</i><br>"
|
||||
if (timed_out)
|
||||
dat += "<i>Warning: last request to refresh records timed out with no response.</i><br>"
|
||||
if (spoofed || timed_out)
|
||||
dat += "<br>"
|
||||
dat += "<b>Filters</b><br>"
|
||||
dat += "<b>Card name (partial):</b> <a href='?src=\ref[src];card_name=1'>[filter_name ? filter_name : "<not set>"]</a>[filter_name ? " <a href='?src=\ref[src];card_name_clear=1'>\[X\]</a>" : null]<br>"
|
||||
dat += "<b>Time interval:</b> "
|
||||
if (ftb_min != null && ftb_sec != null && fte_min != null && fte_sec != null)
|
||||
dat += "<a href='?src=\ref[src];time_begin_min=1'>[ftb_min]</a>:"
|
||||
dat += "<a href='?src=\ref[src];time_begin_sec=1'>[ftb_sec]</a> - "
|
||||
dat += "<a href='?src=\ref[src];time_end_min=1'>[fte_min]</a>:"
|
||||
dat += "<a href='?src=\ref[src];time_end_sec=1'>[fte_sec]</a> "
|
||||
dat += "<a href='?src=\ref[src];time_clear=1'>\[X\]</a>"
|
||||
else
|
||||
dat += "<a href='?src=\ref[src];time=1'><not set></a>"
|
||||
dat += "<br>"
|
||||
dat += "<b>Action:</b> <a href='?src=\ref[src];action=1'>[filter_action ? filter_action : "<not set>"]</a>[filter_action ? " <a href='?src=\ref[src];action_clear=1'>\[X\]</a>" : null]<br>"
|
||||
dat += "<b>Door net ID:</b> <a href='?src=\ref[src];door_id=1'>[filter_door_id ? filter_door_id : "<not set>"]</a>[filter_door_id ? " <a href='?src=\ref[src];door_id_clear=1'>\[X\]</a>" : null]<br>"
|
||||
dat += "<a href='?src=\ref[src];refresh=1'>Refresh records</a><br><br>"
|
||||
|
||||
dat += "<b>Record listing: </b><br>"
|
||||
if (!records.len)
|
||||
dat += "<i>No records currently loaded. Refresh the records to load data.</i><br>"
|
||||
else
|
||||
for (var/rec in records)
|
||||
dat += "[rec]<br>"
|
||||
else if (refreshing)
|
||||
dat += "<i>Refreshing data, please wait...</i>"
|
||||
|
||||
user << browse(dat,"window=net_logreader;size=545x302")
|
||||
onclose(user,"net_logreader")
|
||||
return
|
||||
|
||||
Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if (!(usr in range(1)))
|
||||
return
|
||||
|
||||
usr.machine = src
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
if (href_list["reset"])
|
||||
if(last_reset && (last_reset + NETWORK_MACHINE_RESET_DELAY >= world.time))
|
||||
return
|
||||
|
||||
src.last_reset = world.time
|
||||
var/rem_host = src.host_id ? src.host_id : src.old_host_id
|
||||
src.host_id = null
|
||||
src.old_host_id = null
|
||||
src.post_status(rem_host, "command","term_disconnect")
|
||||
spawn(5)
|
||||
src.post_status(rem_host, "command","term_connect","device",src.device_tag)
|
||||
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
if (href_list["screen"])
|
||||
machine_screen = text2num(href_list["screen"])
|
||||
|
||||
if (href_list["card_name"])
|
||||
filter_name = input("Partial name of card holder", "Card holder name", filter_name) as text|null
|
||||
|
||||
if (href_list["card_name_clear"])
|
||||
filter_name = null
|
||||
|
||||
if (href_list["action"])
|
||||
filter_action = input("Door action", "Door action", filter_action) as null|anything in list("open","close","lock","unlock","reject")
|
||||
|
||||
if (href_list["action_clear"])
|
||||
filter_action = null
|
||||
|
||||
if (href_list["door_id"])
|
||||
filter_door_id = input("Net ID of door", "Door net ID", filter_door_id) as text|null
|
||||
|
||||
if (href_list["door_id_clear"])
|
||||
filter_door_id = null
|
||||
|
||||
if (href_list["time"])
|
||||
ftb_min = input("Filter start time: minutes", "Begin time minutes", 0) as num|null
|
||||
if (ftb_min == null)
|
||||
return
|
||||
ftb_sec = input("Filter start time: seconds", "Begin time seconds", 0) as num|null
|
||||
if (ftb_sec == null)
|
||||
ftb_min = null
|
||||
return
|
||||
fte_min = input("Filter end time: minutes", "End time minutes", 0) as num|null
|
||||
if (fte_min == null)
|
||||
ftb_min = null
|
||||
ftb_sec = null
|
||||
return
|
||||
fte_sec = input("Filter end time: seconds", "End time seconds", 0) as num|null
|
||||
if (fte_sec == null)
|
||||
ftb_min = null
|
||||
ftb_sec = null
|
||||
fte_min = null
|
||||
return
|
||||
|
||||
if (href_list["time_begin_min"])
|
||||
var/n_ftb_min = input("Filter start time: minutes", "Begin time minutes", ftb_min) as num|null
|
||||
if (n_ftb_min != null)
|
||||
ftb_min = n_ftb_min
|
||||
|
||||
if (href_list["time_begin_sec"])
|
||||
var/n_ftb_sec = input("Filter start time: seconds", "Begin time seconds", ftb_sec) as num|null
|
||||
if (n_ftb_sec != null)
|
||||
ftb_sec = n_ftb_sec
|
||||
|
||||
if (href_list["time_end_min"])
|
||||
var/n_fte_min = input("Filter end time: minutes", "End time minutes", fte_min) as num|null
|
||||
if (n_fte_min != null)
|
||||
fte_min = n_fte_min
|
||||
|
||||
if (href_list["time_end_sec"])
|
||||
var/n_fte_sec = input("Filter end time: seconds", "End time seconds", fte_sec) as num|null
|
||||
if (n_fte_sec != null)
|
||||
fte_sec = n_fte_sec
|
||||
|
||||
if (href_list["time_clear"])
|
||||
ftb_min = null
|
||||
ftb_sec = null
|
||||
fte_min = null
|
||||
fte_sec = null
|
||||
|
||||
if (href_list["refresh"])
|
||||
if (!src.host_id)
|
||||
return
|
||||
if (refreshing)
|
||||
return
|
||||
refreshing = 1
|
||||
refresh_id++
|
||||
var/my_refresh_id = refresh_id
|
||||
var/datum/signal/signal = get_free_signal()
|
||||
signal.source = src
|
||||
signal.transmission_method = TRANSMISSION_WIRE
|
||||
var/arguments = "-l 32 -f"
|
||||
if (ftb_min != null && ftb_sec != null && fte_min != null && fte_sec != null)
|
||||
var/st = ftb_min * 600 + ftb_sec * 10
|
||||
var/et = fte_min * 600 + fte_sec * 10
|
||||
arguments += " -t [st]:[et]"
|
||||
if (filter_action)
|
||||
arguments += " -m [filter_action]"
|
||||
if (filter_door_id)
|
||||
arguments += " -s [uppertext(ckey(filter_door_id))]"
|
||||
if (filter_name)
|
||||
arguments += " -- [bash_sanitize(filter_name)]"
|
||||
var/data = list2params(list("command"="record_query","query"="[arguments]"))
|
||||
src.post_status(src.host_id, "command", "term_message", "data", data, "netid", "[net_id]", "device", device_tag)
|
||||
spawn (300)
|
||||
if (refresh_id == my_refresh_id && refreshing)
|
||||
timed_out = 1
|
||||
refreshing = 0
|
||||
|
||||
attack_hand(usr)
|
||||
return
|
||||
|
||||
process()
|
||||
..()
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
use_power(100)
|
||||
|
||||
if(!host_id || !link)
|
||||
return
|
||||
|
||||
if(src.timeout == 0)
|
||||
src.post_status(host_id, "command","term_disconnect","data","timeout")
|
||||
src.host_id = null
|
||||
src.updateUsrDialog()
|
||||
src.timeout = initial(src.timeout)
|
||||
src.timeout_alert = 0
|
||||
else
|
||||
src.timeout--
|
||||
if(src.timeout <= 5 && !src.timeout_alert)
|
||||
src.timeout_alert = 1
|
||||
src.post_status(src.host_id, "command","term_ping","data","reply")
|
||||
|
||||
return
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if(stat & (NOPOWER) || !src.link)
|
||||
return
|
||||
if(!signal || !src.net_id || signal.encryption)
|
||||
return
|
||||
|
||||
var/target = signal.data["sender"] ? signal.data["sender"] : signal.data["netid"]
|
||||
if(!target)
|
||||
return
|
||||
|
||||
if(signal.data["target_device"] && signal.data["target_device"] != device_tag)
|
||||
return
|
||||
|
||||
//We care very deeply about address_1.
|
||||
if(lowertext(signal.data["address_1"]) != lowertext(src.net_id))
|
||||
if((signal.data["address_1"] == "ping") && ((signal.data["net"] == null) || ("[signal.data["net"]]" == "[src.net_number]")))
|
||||
spawn(5) //Send a reply for those curious jerks
|
||||
if (signal.transmission_method == TRANSMISSION_WIRE)
|
||||
src.post_status(target, "command", "ping_reply", "device", src.device_tag, "netid", src.net_id, "net", "[net_number]")
|
||||
// else ????
|
||||
return
|
||||
if (!signal.data["target_device"])
|
||||
return
|
||||
|
||||
var/sigcommand = lowertext(signal.data["command"])
|
||||
if(!sigcommand || !target)
|
||||
return
|
||||
|
||||
switch(sigcommand)
|
||||
if("term_connect") //Terminal interface stuff.
|
||||
if(target == src.host_id)
|
||||
src.host_id = null
|
||||
src.updateUsrDialog()
|
||||
spawn(3)
|
||||
src.post_status(target, "command","term_disconnect")
|
||||
return
|
||||
|
||||
if(src.host_id)
|
||||
return
|
||||
|
||||
src.timeout = initial(src.timeout)
|
||||
src.timeout_alert = 0
|
||||
src.host_id = target
|
||||
src.old_host_id = target
|
||||
if(signal.data["data"] != "noreply")
|
||||
src.post_status(target, "command","term_connect","data","noreply","device",src.device_tag)
|
||||
src.updateUsrDialog()
|
||||
spawn(2) //Sign up with the driver (if a mainframe contacted us)
|
||||
src.post_status(target,"command","term_message","data","command=register")
|
||||
return
|
||||
|
||||
if("term_message","term_file")
|
||||
if(target != src.host_id) //Huh, who is this?
|
||||
return
|
||||
var/data = signal.data["data"]
|
||||
if(!data || sigcommand == "term_message") // currently no action is taken without a file, so throw back term_message
|
||||
src.post_status(target,"command","term_message","data","command=status&status=failure")
|
||||
return
|
||||
|
||||
var/datum/computer/file/archive/archive = signal.data_file
|
||||
if (!istype(archive))
|
||||
src.post_status(target,"command","term_message","data","command=status&status=failure")
|
||||
return
|
||||
|
||||
records.len = 0
|
||||
for (var/datum/computer/file/record/R in archive.contained_files)
|
||||
var/bad = 0
|
||||
for (var/F in required_fields)
|
||||
if (!(F in R.fields))
|
||||
bad = 1
|
||||
break
|
||||
if (bad)
|
||||
continue
|
||||
records += accesslog_digest(R, 1)
|
||||
|
||||
if (data == "ack")
|
||||
spoofed = 0
|
||||
else
|
||||
spoofed = 1
|
||||
|
||||
timed_out = 0
|
||||
refreshing = 0
|
||||
|
||||
src.post_status(target,"command","term_message","data","command=status&status=success")
|
||||
for (var/mob/M in range(1))
|
||||
if (M.machine == src)
|
||||
attack_hand(M)
|
||||
return
|
||||
|
||||
if("term_ping")
|
||||
if(target != src.host_id)
|
||||
return
|
||||
if(signal.data["data"] == "reply")
|
||||
src.post_status(target, "command","term_ping")
|
||||
src.timeout = initial(src.timeout)
|
||||
src.timeout_alert = 0
|
||||
return
|
||||
|
||||
if("term_disconnect")
|
||||
if(target == src.host_id)
|
||||
src.host_id = null
|
||||
src.timeout = initial(src.timeout)
|
||||
src.timeout_alert = 0 //No need to be alerted about this anymore.
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
proc/accesslog_digest(var/datum/computer/file/record/R, formatted = 0)
|
||||
if (!istype(R))
|
||||
return "unknown type [R.name], possibly not a record"
|
||||
var/action = R.fields["action"]
|
||||
var/card_name = R.fields["card_name"]
|
||||
var/time_t = R.fields["time_t"]
|
||||
var/door_name = R.fields["door_name"]
|
||||
if (!action)
|
||||
return "corrupted record [R.name] missing action"
|
||||
if (!card_name)
|
||||
return "corrupted record [R.name] missing user ID"
|
||||
if (!time_t)
|
||||
return "corrupted record [R.name] missing human readable time"
|
||||
if (!door_name)
|
||||
return "corrupted record [R.name] missing door designated name"
|
||||
if (action != "reject")
|
||||
if (!formatted)
|
||||
return "[time_t] [card_name] [action]s [door_name]"
|
||||
else
|
||||
return "<b>[time_t]</b> [card_name] <b>[action]s</b> [door_name]"
|
||||
else
|
||||
if (!formatted)
|
||||
return "[time_t] [door_name] rejected entry for [card_name]"
|
||||
else
|
||||
return "<b>[time_t]</b> [door_name] <b>rejected entry for</b> [card_name]"
|
||||
|
||||
/datum/computer/file/mainframe_program/srv/accesslog
|
||||
name = "accesslog"
|
||||
size = 1
|
||||
var/static/nextlog = 1
|
||||
var/opt_data = null
|
||||
|
||||
receive_progsignal(var/sendid, var/list/data, var/datum/computer/file/file)
|
||||
. = ..()
|
||||
if (!.)
|
||||
if (data["command"] == DWAINE_COMMAND_REPLY)
|
||||
if (data["sender_tag"] == "getopt")
|
||||
opt_data = data["data"]
|
||||
return ESIG_USR4
|
||||
else
|
||||
return ESIG_GENERIC
|
||||
else if (data["command"] == DWAINE_COMMAND_MSG_TERM)
|
||||
message_user(data["data"])
|
||||
else
|
||||
return ESIG_GENERIC
|
||||
return ESIG_SUCCESS
|
||||
|
||||
proc/usage()
|
||||
message_user("Usage:")
|
||||
message_user("[name] -a -s DOOR_ID -m (open|close|lock|unlock|reject) -t TIME USER_ID")
|
||||
message_user("[name] -l COUNT \[-f\] \[-s DOOR_ID\] \[-m (open|close|lock|unlock|reject)\] \[-b TIME_START:TIME_END\] \[USER_ID_FRAGMENT \]")
|
||||
|
||||
proc/loglist(timestamp, action, door_id, card_name)
|
||||
var/list/ret = list()
|
||||
ret["action"] = action
|
||||
ret["door_id"] = door_id
|
||||
ret["card_name"] = card_name
|
||||
var/atom/door = locate("\[0x[door_id]\]")
|
||||
if (istype(door, /obj/machinery/door/airlock))
|
||||
ret["door_name"] = door.name
|
||||
else if (istype(door, /obj/machinery/networked))
|
||||
ret["door_name"] = "[door.name] (ALERT: network indicates this may not be door)"
|
||||
else
|
||||
ret["door_name"] = "Unknown device (0x[door_id])"
|
||||
var/time_n = istext(timestamp) ? text2num(timestamp) : timestamp
|
||||
ret["timestamp"] = time_n
|
||||
var/min = round(time_n / 600)
|
||||
var/sec = round(time_n / 10) - min * 60
|
||||
ret["time_t"] = "[min < 10 ? 0 : null][min]:[sec < 10 ? 0 : null][sec]"
|
||||
return ret
|
||||
|
||||
proc/message_reply_and_user(var/message)
|
||||
var/list/data = list("command"=DWAINE_COMMAND_REPLY, "data" = message, "sender_tag" = "accesslog")
|
||||
if (useracc)
|
||||
data["term"] = useracc.user_id
|
||||
var/sig = signal_program(parent_task.progid, data)
|
||||
if (sig != ESIG_USR4)
|
||||
message_user(message)
|
||||
|
||||
initialize(var/initparams)
|
||||
if (..())
|
||||
mainframe_prog_exit
|
||||
return
|
||||
|
||||
if (!initparams)
|
||||
usage()
|
||||
mainframe_prog_exit
|
||||
return
|
||||
|
||||
var/log_to = DEFAULT_LOG_PATH
|
||||
var/datum/computer/file/record/conf_file = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"="/etc/accesslog"))
|
||||
if (istype(conf_file))
|
||||
if (conf_file.fields["logdir"])
|
||||
log_to = conf_file.fields["logdir"]
|
||||
if (chs(log_to, 1) != "/")
|
||||
log_to = "/log_to"
|
||||
|
||||
opt_data = null
|
||||
var/status = signal_program(1, list("command"=DWAINE_COMMAND_TSPAWN, "passusr" = 1, "path" = "/bin/getopt", "args" = "afl:m:s:t: [initparams]"))
|
||||
if (status == ESIG_NOTARGET)
|
||||
message_user("getopt: command not found")
|
||||
mainframe_prog_exit
|
||||
return
|
||||
if (!opt_data)
|
||||
message_user("accesslog: No response from getopt.")
|
||||
mainframe_prog_exit
|
||||
return
|
||||
if (copytext(opt_data, 1, 7) == "getopt")
|
||||
message_user(opt_data)
|
||||
mainframe_prog_exit
|
||||
return
|
||||
var/list/l = optparse(opt_data)
|
||||
if (!istype(l))
|
||||
message_user("accesslog: Error parsing options: [opt_data].")
|
||||
mainframe_prog_exit
|
||||
return
|
||||
var/list/opts = l[1]
|
||||
var/list/params = l[2]
|
||||
if (opts["a"] && opts["l"])
|
||||
usage()
|
||||
mainframe_prog_exit
|
||||
return
|
||||
|
||||
if (opts["a"])
|
||||
if (opts["s"] && opts["t"] && opts["m"] && params.len)
|
||||
if (!(opts["m"] in list("open","close","lock","unlock","reject")))
|
||||
message_user("")
|
||||
var/mylog = nextlog
|
||||
nextlog++
|
||||
|
||||
var/datum/computer/file/record/logfile = new()
|
||||
var/fname = "access[mylog]"
|
||||
logfile.name = fname
|
||||
if (useracc)
|
||||
logfile.metadata["owner"] = read_user_field("name")
|
||||
logfile.metadata["permissions"] = COMP_ROWNER | COMP_RGROUP
|
||||
logfile.fields = loglist(opts["t"], opts["m"], opts["s"], dd_list2text(params, " "))
|
||||
var/datum/computer/folder/logs_dir = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"=log_to))
|
||||
if (istype(logs_dir))
|
||||
var/idx = 0
|
||||
while (logs_dir.contents.len >= ACCESSLOG_RECORDS_LIMIT)
|
||||
idx++
|
||||
if (idx > logs_dir.contents.len)
|
||||
message_user("Could not make space for new entry.")
|
||||
mainframe_prog_exit
|
||||
return
|
||||
var/datum/computer/to_delete = logs_dir.contents[idx]
|
||||
if (istype(to_delete, /datum/computer/file/record))
|
||||
logs_dir.remove_file(to_delete)
|
||||
if (to_delete)
|
||||
qdel(to_delete)
|
||||
idx--
|
||||
var/result = signal_program(1, list("command"=DWAINE_COMMAND_FWRITE, "path"=log_to,"replace"=1,"mkdir"=1), logfile)
|
||||
if (result == ESIG_SUCCESS)
|
||||
message_user("Data recorded.")
|
||||
else
|
||||
message_user("File system error occurred while recording data.")
|
||||
else
|
||||
usage()
|
||||
mainframe_prog_exit
|
||||
return
|
||||
else if (opts["l"])
|
||||
var/time_begin = null
|
||||
var/time_end = null
|
||||
if (opts["t"])
|
||||
var/time_filter = opts["t"]
|
||||
var/list/tf_list = dd_text2list(time_filter, ":")
|
||||
if (tf_list.len != 2)
|
||||
message_user("Invalid timestamp filter format [time_filter], usage: TIMESTAMP_BEGIN:TIMESTAMP_END.")
|
||||
mainframe_prog_exit
|
||||
return
|
||||
time_begin = text2num(tf_list[1])
|
||||
time_end = text2num(tf_list[2])
|
||||
if (!isnum(time_begin) || !isnum(time_end))
|
||||
message_user("Invalid timestamp filter [time_filter].")
|
||||
mainframe_prog_exit
|
||||
return
|
||||
var/datum/computer/folder/logs_folder = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"=log_to))
|
||||
if (logs_folder == ESIG_NOFILE)
|
||||
message_user("No recorded data.")
|
||||
mainframe_prog_exit
|
||||
return
|
||||
if (!istype(logs_folder))
|
||||
message_user("Error: cannot access logs directory. Please check your permissions and try again.")
|
||||
mainframe_prog_exit
|
||||
return
|
||||
var/count = text2num(opts["l"])
|
||||
if (!count)
|
||||
message_user("Invalid count: [opts["l"]]")
|
||||
mainframe_prog_exit
|
||||
return
|
||||
if (count < 0)
|
||||
message_user("Listing the last [count] records (do you honestly expect this to break anything?).")
|
||||
mainframe_prog_exit
|
||||
return
|
||||
if (count > 32)
|
||||
count = 32
|
||||
message_user("Listing the last [count] records:")
|
||||
var/paramsearch = null
|
||||
if (params.len)
|
||||
paramsearch = dd_list2text(params, " ")
|
||||
var/list/records = logs_folder.contents.Copy()
|
||||
if (!records.len)
|
||||
message_user("No recorded data.")
|
||||
else
|
||||
var/printed = 0
|
||||
var/now = ticker.round_elapsed_ticks
|
||||
var/max = -1
|
||||
var/datum/computer/file/record/C = null
|
||||
for (var/Q in records)
|
||||
if (!istype(Q, /datum/computer/file/record))
|
||||
records -= Q
|
||||
continue
|
||||
var/datum/computer/file/record/R = Q
|
||||
if (!R.fields["door_id"] || !R.fields["timestamp"] || !R.fields["card_name"] || !R.fields["action"] || !R.fields["time_t"] || !R.fields["door_name"])
|
||||
records -= Q
|
||||
var/TS = R.fields["timestamp"]
|
||||
if (!TS)
|
||||
records -= Q
|
||||
continue
|
||||
if (!isnum(TS))
|
||||
TS = text2num(TS)
|
||||
R.fields["timestamp"] = TS
|
||||
if (TS < 0)
|
||||
records -= Q
|
||||
continue
|
||||
if (opts["t"])
|
||||
if (TS < time_begin || TS > time_end)
|
||||
records -= Q
|
||||
continue
|
||||
if (opts["s"])
|
||||
if (R.fields["door_id"] != opts["s"])
|
||||
records -= Q
|
||||
continue
|
||||
if (opts["m"])
|
||||
if (R.fields["action"] != opts["m"])
|
||||
records -= Q
|
||||
continue
|
||||
if (params.len)
|
||||
if (!findtext(R.fields["card_name"], paramsearch))
|
||||
records -= Q
|
||||
continue
|
||||
|
||||
var/list/printing = list()
|
||||
while (printed < count && records.len)
|
||||
max = -1
|
||||
for (var/datum/computer/file/record/R in records)
|
||||
var/TS = R.fields["timestamp"]
|
||||
if (!isnum(TS))
|
||||
TS = text2num(TS)
|
||||
R.fields["timestamp"] = TS
|
||||
if (R.fields["timestamp"] > max && R.fields["timestamp"] < now - 300)
|
||||
max = R.fields["timestamp"]
|
||||
C = R
|
||||
if (C)
|
||||
printing += C
|
||||
records -= C
|
||||
printed++
|
||||
else
|
||||
break
|
||||
|
||||
for (var/i = printing.len, i >= 1, i--)
|
||||
var/datum/computer/file/record/R = printing[i]
|
||||
if (opts["f"])
|
||||
message_reply_and_user("[log_to]/[R.name]")
|
||||
else
|
||||
message_reply_and_user(accesslog_digest(R))
|
||||
|
||||
mainframe_prog_exit
|
||||
return
|
||||
|
||||
/datum/computer/file/mainframe_program/driver/mountable/logreader
|
||||
name = "logreader"
|
||||
setup_processes = 1
|
||||
var/tmp/list/records = list()
|
||||
var/tmp/archive_path = null
|
||||
|
||||
initialize(var/initparams)
|
||||
if (..())
|
||||
return
|
||||
|
||||
signal_program(1, list("command"=DWAINE_COMMAND_MOUNT, "id"=src.name, "link"="logreader"))
|
||||
return
|
||||
|
||||
process()
|
||||
return
|
||||
|
||||
receive_progsignal(var/sendid, var/list/data, var/datum/computer/file/file)
|
||||
. = ..()
|
||||
if (!.)
|
||||
if (data["command"] == DWAINE_COMMAND_REPLY)
|
||||
if (data["sender_tag"] == "accesslog")
|
||||
records += data["data"]
|
||||
return ESIG_USR4
|
||||
else if (data["sender_tag"] == "tar")
|
||||
archive_path = data["data"]
|
||||
return ESIG_USR4
|
||||
else
|
||||
return ESIG_GENERIC
|
||||
else if (data["command"] == DWAINE_COMMAND_MSG_TERM)
|
||||
message_user(data["data"])
|
||||
else
|
||||
return ESIG_GENERIC
|
||||
return ESIG_SUCCESS
|
||||
|
||||
terminal_input(var/data, var/datum/computer/file/theFile)
|
||||
if (..() || !data)
|
||||
return 1
|
||||
|
||||
|
||||
var/list/dataList = params2list(data)
|
||||
if (!dataList || !dataList.len)
|
||||
return 1
|
||||
|
||||
|
||||
switch (lowertext(dataList["command"]))
|
||||
if ("record_query")
|
||||
records.len = 0
|
||||
var/datum/computer/file/mainframe_program/P = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"="/sys/srv/accesslog"))
|
||||
if (istype(P))
|
||||
var/list/siglist = list("command"=DWAINE_COMMAND_TSPAWN, "passusr"=1, "path"="/sys/srv/accesslog", "args"=strip_html(dataList["query"]))
|
||||
signal_program(1, siglist)
|
||||
// see what i did here? heh? HEH?
|
||||
// doubly so, it almost sounds like tar gz
|
||||
var/targs = dd_list2text(records, " ")
|
||||
archive_path = null
|
||||
siglist = list("command"=DWAINE_COMMAND_TSPAWN, "passusr"=1, "path"="/bin/tar", "args"="-cqt -- [targs]")
|
||||
signal_program(1, siglist)
|
||||
if (!archive_path)
|
||||
return 1
|
||||
var/datum/computer/file/archive/archive = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"="[archive_path]"))
|
||||
if (!istype(archive))
|
||||
return 1
|
||||
message_device("ack", archive)
|
||||
//archive.dispose() // we don't need that tempfile anymore
|
||||
return 0
|
||||
|
||||
add_file(var/datum/computer/file/theFile)
|
||||
if (!initialized)
|
||||
return 0
|
||||
|
||||
if (istype(theFile, /datum/computer/file/archive))
|
||||
var/datum/computer/file/archive/R = theFile
|
||||
message_device("suppl", R)
|
||||
theFile.dispose()
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
change_metadata(var/datum/computer/file/file, var/field, var/newval)
|
||||
return 0
|
||||
|
||||
#undef DEFAULT_LOG_PATH
|
||||
#undef ACCESSLOG_RECORDS_LIMIT
|
||||
@@ -0,0 +1,949 @@
|
||||
|
||||
|
||||
/*
|
||||
* The Terminal Connection datum, used to keep track of, well, terminal connections.
|
||||
*/
|
||||
|
||||
/datum/terminal_connection
|
||||
var/obj/machinery/networked/master = null
|
||||
var/net_id = null //Network ID of connected device.
|
||||
var/term_type = null //Terminal type ID of connected device. i.e. PNET_MAINFRAME or HUI_TERMINAL
|
||||
|
||||
New(var/obj/machinery/networked/newmaster, var/new_id, var/newterm_type)
|
||||
..()
|
||||
if(istype(newmaster))
|
||||
src.master = newmaster
|
||||
|
||||
if(new_id)
|
||||
src.net_id = new_id
|
||||
|
||||
if(newterm_type)
|
||||
src.term_type = newterm_type
|
||||
return
|
||||
|
||||
disposing()
|
||||
master = null
|
||||
|
||||
..()
|
||||
|
||||
/*
|
||||
* The physical mainframe, communication through wired network.
|
||||
*/
|
||||
|
||||
/obj/machinery/networked/mainframe
|
||||
name = "Mainframe"
|
||||
desc = "A mainframe computer. It's pretty big!"
|
||||
density = 1
|
||||
anchored = 1
|
||||
icon_state = "dwaine"
|
||||
device_tag = "PNET_MAINFRAME"
|
||||
timeout = 30
|
||||
req_access = list(access_heads)
|
||||
var/list/terminals = list() //list of netIDs/terminal profiles of connected terminal devices.
|
||||
var/list/processing = list() //As the name implies, this is the list of programs that should be updated every process call on the mainframe object.
|
||||
var/list/timeout_list = list() //Terminals currently set to time out
|
||||
var/datum/computer/file/mainframe_program/os/os = null //Ref to current operating system program
|
||||
var/datum/computer/file/mainframe_program/os/bootstrap = null //Ref to bootloader program, instanciated when a main OS cannot be located on the memory card
|
||||
var/datum/computer/folder/runfolder = null //Storage folder for currently running programs.
|
||||
var/obj/item/disk/data/memcard/hd = null //Only internal storage for the mainframe--core memory, used as primary storage.
|
||||
|
||||
var/posted = 1 //Have we run through the POST sequence? Set to 1 initially so it doesn't freak out during map powernet generation.
|
||||
|
||||
var/setup_drive_size = 4096
|
||||
var/setup_drive_type = /obj/item/disk/data/memcard //Use this path for the hd
|
||||
var/setup_bootstrap_path = /datum/computer/file/mainframe_program/os/bootstrap //The bootstrapping system.
|
||||
var/setup_os_string = null
|
||||
power_usage = 500
|
||||
|
||||
zeta
|
||||
//setup_starting_os = /datum/computer/file/mainframe_program/os/main_os
|
||||
setup_drive_type = /obj/item/disk/data/memcard/main2
|
||||
|
||||
New()
|
||||
..()
|
||||
spawn(10)
|
||||
|
||||
src.net_id = generate_net_id(src)
|
||||
|
||||
if(!src.link)
|
||||
var/turf/T = get_turf(src)
|
||||
var/obj/machinery/power/data_terminal/test_link = locate() in T
|
||||
if(test_link && !test_link.is_valid_master(test_link.master))
|
||||
src.link = test_link
|
||||
src.link.master = src
|
||||
|
||||
if(!hd && (setup_drive_size > 0))
|
||||
if(src.setup_drive_type)
|
||||
src.hd = new src.setup_drive_type
|
||||
src.hd.set_loc(src)
|
||||
else
|
||||
src.hd = new /obj/item/disk/data/memcard(src)
|
||||
src.hd.file_amount = src.setup_drive_size
|
||||
|
||||
if(ispath(setup_bootstrap_path))
|
||||
src.bootstrap = new setup_bootstrap_path
|
||||
src.bootstrap.master = src
|
||||
|
||||
sleep(54)
|
||||
src.posted = 0
|
||||
src.post_system()
|
||||
|
||||
return
|
||||
|
||||
disposing()
|
||||
if (terminals)
|
||||
for (var/datum/conn in terminals)
|
||||
conn.dispose()
|
||||
|
||||
terminals.len = 0
|
||||
terminals = null
|
||||
|
||||
if (processing)
|
||||
processing.len = 0
|
||||
processing = null
|
||||
|
||||
if (timeout_list)
|
||||
timeout_list.len = 0
|
||||
timeout_list = null
|
||||
|
||||
if (os)
|
||||
os.dispose()
|
||||
os = null
|
||||
|
||||
if (bootstrap)
|
||||
bootstrap.dispose()
|
||||
bootstrap = null
|
||||
|
||||
if (runfolder)
|
||||
runfolder = null
|
||||
|
||||
if (hd)
|
||||
hd.dispose()
|
||||
hd = null
|
||||
|
||||
..()
|
||||
|
||||
attack_ai(mob/user as mob)
|
||||
return
|
||||
|
||||
attack_hand(mob/user as mob)
|
||||
if (user.stat || user.restrained())
|
||||
return
|
||||
|
||||
if(stat & BROKEN)
|
||||
if(!src.hd)
|
||||
return
|
||||
|
||||
boutput(user, "<span style=\"color:red\">The mainframe is trashed, but the memory core could probably salvaged.</span>")
|
||||
return
|
||||
|
||||
var/dat = "<html><head><title>Mainframe Access Panel</title></head><body><hr>"
|
||||
|
||||
dat += "<b>ACTIVE:</b> [src.os ? "YES" : "NO"]<br>"
|
||||
dat += "<b>BOOTING:</b> [(src.bootstrap && src.os && istype(src.os, src.bootstrap.type)) ? "YES" : "NO"]<br><br>"
|
||||
|
||||
if(stat & NOPOWER)
|
||||
|
||||
dat += "<b>Memory Core:</b> <a href='?src=\ref[src];core=1'>[src.hd ? "LOADED" : "---------"]</a><br>"
|
||||
dat += "Core Shield Maglock is <b>OFF</b><hr>[net_switch_html()]<hr>"
|
||||
else
|
||||
|
||||
dat += "<b>Memory Core:</b> [src.hd ? "LOADED" : "---------"]<br>"
|
||||
dat += "Core Shield Maglock is <b>ON</b><hr>"
|
||||
|
||||
|
||||
user << browse(dat, "window=mainframe;size=245x202")
|
||||
onclose(user, "mainframe")
|
||||
return
|
||||
|
||||
Topic(href, href_list)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
|
||||
if (istype(src.loc, /turf) && get_dist(src, usr) <= 1)
|
||||
if (usr.stat || usr.restrained())
|
||||
return
|
||||
|
||||
usr.machine = src
|
||||
|
||||
if(href_list["core"])
|
||||
|
||||
if(!(stat & NOPOWER))
|
||||
boutput(usr, "<span style=\"color:red\">The electromagnetic lock is still on!</span>")
|
||||
return
|
||||
|
||||
//Ai/cyborgs cannot physically remove a memory board from a room away.
|
||||
if(istype(usr,/mob/living/silicon) && get_dist(src, usr) > 1)
|
||||
boutput(usr, "<span style=\"color:red\">You cannot physically touch the board.</span>")
|
||||
return
|
||||
|
||||
if(src.hd)
|
||||
src.hd.set_loc(src.loc)
|
||||
boutput(usr, "You remove the memory core from the mainframe.")
|
||||
usr.unlock_medal("421", 1)
|
||||
stat |= MAINT
|
||||
src.unload_all()
|
||||
src.hd = null
|
||||
src.runfolder = null
|
||||
src.posted = 0
|
||||
|
||||
else
|
||||
var/obj/item/I = usr.equipped()
|
||||
if (istype(I, /obj/item/disk/data/memcard))
|
||||
usr.drop_item()
|
||||
I.set_loc(src)
|
||||
src.hd = I
|
||||
stat &= ~MAINT
|
||||
boutput(usr, "You insert [I].")
|
||||
|
||||
else if (href_list["dipsw"] && (stat & NOPOWER))
|
||||
var/switchNum = text2num(href_list["dipsw"])
|
||||
if (switchNum < 1 || switchNum > 8)
|
||||
return 1
|
||||
|
||||
switchNum = round(switchNum)
|
||||
if (net_number & switchNum)
|
||||
net_number &= ~switchNum
|
||||
else
|
||||
net_number |= switchNum
|
||||
|
||||
src.updateUsrDialog()
|
||||
src.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
attackby(obj/item/W as obj, mob/user as mob)
|
||||
if (istype(W, /obj/item/crowbar))
|
||||
if (!(stat & BROKEN))
|
||||
return
|
||||
|
||||
if (!src.hd)
|
||||
boutput(usr, "<span style=\"color:red\">The memory core has already been removed.</span>")
|
||||
return
|
||||
|
||||
stat |= MAINT
|
||||
src.unload_all()
|
||||
src.hd.set_loc(src.loc)
|
||||
src.hd = null
|
||||
src.posted = 0
|
||||
|
||||
boutput(usr, "You pry out the memory core.")
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
else
|
||||
..()
|
||||
|
||||
return
|
||||
|
||||
|
||||
process()
|
||||
..()
|
||||
if(stat & (NOPOWER|BROKEN|MAINT) || !processing)
|
||||
return
|
||||
use_power(500)
|
||||
if(prob(3))
|
||||
spawn(1)
|
||||
playsound(src.loc, pick(ambience_computer), 50, 1)
|
||||
|
||||
for (var/progIndex = 1, progIndex <= src.processing.len, progIndex++)
|
||||
var/datum/computer/file/mainframe_program/prog = src.processing[progIndex]
|
||||
if (prog)
|
||||
if (prog.disposed)
|
||||
src.processing[progIndex] = null
|
||||
continue
|
||||
|
||||
prog.process()
|
||||
/*
|
||||
for(var/datum/computer/file/mainframe_program/P in src.processing)
|
||||
if (P)
|
||||
P.process()
|
||||
*/
|
||||
if(src.timeout == 0)
|
||||
src.timeout = initial(src.timeout)
|
||||
src.timeout_alert = 0
|
||||
for(var/timed in timeout_list)
|
||||
var/datum/terminal_connection/conn = src.terminals[timed]
|
||||
src.terminals -= timed
|
||||
if(src.os && conn)
|
||||
src.os.closed_connection(conn)
|
||||
//qdel(conn)
|
||||
if (conn)
|
||||
conn.dispose()
|
||||
else
|
||||
src.timeout--
|
||||
if(src.timeout <= 5 && !src.timeout_alert)
|
||||
src.timeout_alert = 1
|
||||
src.timeout_list = src.terminals.Copy()
|
||||
for(var/id in timeout_list)
|
||||
src.post_status(id, "command","term_ping","data","reply")
|
||||
|
||||
return
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if(stat & (NOPOWER|BROKEN|MAINT) || !src.link)
|
||||
return
|
||||
if(!signal || !src.net_id || signal.encryption)
|
||||
return
|
||||
|
||||
if(signal.transmission_method != TRANSMISSION_WIRE) //No radio for us thanks
|
||||
return
|
||||
|
||||
var/target = signal.data["sender"]
|
||||
|
||||
//They don't need to target us specifically to ping us.
|
||||
//Otherwise, if they aren't addressing us, ignore them
|
||||
if(signal.data["address_1"] != src.net_id)
|
||||
if((signal.data["address_1"] == "ping") && ((signal.data["net"] == null) || ("[signal.data["net"]]" == "[src.net_number]")) && signal.data["sender"])
|
||||
spawn(5) //Send a reply for those curious jerks
|
||||
src.post_status(target, "command", "ping_reply", "device", src.device_tag, "netid", src.net_id)
|
||||
|
||||
return
|
||||
|
||||
var/sigcommand = lowertext(signal.data["command"])
|
||||
if(!sigcommand || !signal.data["sender"])
|
||||
return
|
||||
|
||||
switch(sigcommand)
|
||||
if("term_connect") //Terminal interface stuff.
|
||||
if(target in src.terminals)
|
||||
//something might be wrong here, disconnect them!
|
||||
var/datum/terminal_connection/conn = src.terminals[target]
|
||||
src.terminals.Remove(target)
|
||||
if(src.os)
|
||||
src.os.closed_connection(conn)
|
||||
//qdel(conn)
|
||||
if (conn)
|
||||
conn.dispose()
|
||||
spawn(3)
|
||||
src.post_status(target, "command","term_disconnect")
|
||||
return
|
||||
|
||||
var/devtype = signal.data["device"]
|
||||
if(!devtype) return
|
||||
var/datum/terminal_connection/newconn = new /datum/terminal_connection(src, target, devtype)
|
||||
src.terminals[target] = newconn //Accept the connection!
|
||||
if(signal.data["data"] != "noreply")
|
||||
src.post_status(target, "command","term_connect","data","noreply")
|
||||
//also say hi.
|
||||
if(src.os)
|
||||
var/datum/computer/theFile = null
|
||||
if (signal.data_file)
|
||||
theFile = signal.data_file.copy_file()
|
||||
src.os.new_connection(newconn, theFile)
|
||||
//qdel(file)
|
||||
if (theFile)
|
||||
theFile.dispose()
|
||||
return
|
||||
|
||||
if("term_message","term_file")
|
||||
if(!(target in src.terminals)) //Huh, who is this?
|
||||
return
|
||||
|
||||
//src.visible_message("[src] beeps.")
|
||||
var/data = signal.data["data"]
|
||||
var/file = null
|
||||
if(signal.data_file)
|
||||
file = signal.data_file.copy_file()
|
||||
if(src.os && data)
|
||||
src.os.term_input(data, target, file)
|
||||
//qdel(file)
|
||||
|
||||
return
|
||||
|
||||
if ("term_break")
|
||||
if (!(target in src.terminals))
|
||||
return
|
||||
|
||||
if (src.os)
|
||||
src.os.term_input(1, target, null, 1)
|
||||
|
||||
if("term_ping")
|
||||
if(!(target in src.terminals))
|
||||
spawn(3) //Go away!!
|
||||
src.post_status(target, "command","term_disconnect")
|
||||
return
|
||||
if(target in src.timeout_list)
|
||||
src.timeout_list -= target
|
||||
if(signal.data["data"] == "reply")
|
||||
src.post_status(target, "command","term_ping")
|
||||
return
|
||||
|
||||
if("term_disconnect")
|
||||
if(target in src.terminals)
|
||||
var/datum/terminal_connection/conn = src.terminals[target]
|
||||
if(src.os)
|
||||
src.os.closed_connection(conn)
|
||||
src.terminals -= target
|
||||
//qdel(conn)
|
||||
if (conn)
|
||||
conn.dispose()
|
||||
|
||||
return
|
||||
|
||||
if("ping_reply")
|
||||
if(src.os)
|
||||
os.ping_reply(signal.data["netid"],signal.data["device"])
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
power_change()
|
||||
if(stat & BROKEN)
|
||||
icon_state = initial(src.icon_state)
|
||||
src.icon_state += "b"
|
||||
return
|
||||
|
||||
else if(powered())
|
||||
icon_state = initial(src.icon_state)
|
||||
stat &= ~NOPOWER
|
||||
src.post_system() //Will simply return if POSTed already.
|
||||
else
|
||||
spawn(rand(0, 15))
|
||||
icon_state = initial(src.icon_state)
|
||||
src.icon_state += "0"
|
||||
stat |= NOPOWER
|
||||
src.posted = 0
|
||||
src.os = null
|
||||
|
||||
clone()
|
||||
var/obj/machinery/networked/mainframe/cloneframe = ..()
|
||||
if (!cloneframe)
|
||||
return
|
||||
|
||||
cloneframe.setup_bootstrap_path = src.setup_bootstrap_path
|
||||
cloneframe.setup_os_string = src.setup_os_string
|
||||
if (src.hd)
|
||||
cloneframe.hd = src.hd.clone()
|
||||
|
||||
return cloneframe
|
||||
|
||||
meteorhit(var/obj/O as obj)
|
||||
if(stat & BROKEN)
|
||||
//dispose()
|
||||
src.dispose()
|
||||
set_broken()
|
||||
var/datum/effects/system/harmless_smoke_spread/smoke = new /datum/effects/system/harmless_smoke_spread()
|
||||
smoke.set_up(5, 0, src)
|
||||
smoke.start()
|
||||
return
|
||||
|
||||
ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
//dispose()
|
||||
src.dispose()
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
set_broken()
|
||||
if(3.0)
|
||||
if (prob(25))
|
||||
set_broken()
|
||||
else
|
||||
return
|
||||
|
||||
blob_act(var/power)
|
||||
if (prob(power * 2.5))
|
||||
set_broken()
|
||||
src.density = 0
|
||||
|
||||
proc
|
||||
run_program(datum/computer/file/mainframe_program/program, var/datum/mainframe2_user_data/user, var/datum/computer/file/mainframe_program/caller, var/runparams)
|
||||
if(!hd || !program || (!program.holder && program.needs_holder))
|
||||
return 0
|
||||
|
||||
if(!runfolder)
|
||||
for (var/datum/computer/folder/F in src.hd.root.contents)
|
||||
if (F.name == "proc")
|
||||
runfolder = F
|
||||
runfolder.metadata["permission"] = COMP_HIDDEN
|
||||
break
|
||||
|
||||
if(!runfolder)
|
||||
runfolder = new /datum/computer/folder( )
|
||||
runfolder.name = "proc"
|
||||
runfolder.metadata["permission"] = COMP_HIDDEN
|
||||
if(!hd.root.add_file( runfolder ))
|
||||
//qdel(runfolder)
|
||||
runfolder.dispose()
|
||||
return 0
|
||||
if (!(program in src.processing))
|
||||
program = program.copy_file()
|
||||
if(!runfolder.add_file( program ))
|
||||
//qdel(program)
|
||||
program.dispose()
|
||||
return 0
|
||||
|
||||
if(program.master != src)
|
||||
program.master = src
|
||||
|
||||
if(istype(program, /datum/computer/file/mainframe_program/os))
|
||||
if (!src.os)
|
||||
src.os = program
|
||||
else
|
||||
//qdel(program)
|
||||
program.dispose()
|
||||
return 0
|
||||
|
||||
if(!(program in src.processing))
|
||||
if (src.os == program && src.processing.len)
|
||||
src.processing.len++
|
||||
for (var/x = src.processing.len, x > 0, x--)
|
||||
var/datum/computer/file/mainframe_program/P = src.processing[x]
|
||||
if (istype(P))
|
||||
P.progid = x+1
|
||||
if (src.processing.len == x)
|
||||
src.processing.len++
|
||||
src.processing[x+1] = P
|
||||
|
||||
src.processing[1] = src.os
|
||||
src.os.progid = 1
|
||||
|
||||
else
|
||||
var/success = 0
|
||||
for (var/x = 1, x <= src.processing.len, x++)
|
||||
if (!isnull(src.processing[x]))
|
||||
continue
|
||||
|
||||
src.processing[x] = program
|
||||
program.progid = x
|
||||
success = 1
|
||||
break
|
||||
|
||||
if (!success)
|
||||
src.processing += program
|
||||
program.progid = src.processing.len
|
||||
|
||||
if (user)
|
||||
program.useracc = user
|
||||
user.current_prog = program
|
||||
|
||||
if (caller)
|
||||
program.parent_task = caller
|
||||
|
||||
program.initialize(runparams)
|
||||
//program.initialized = 1
|
||||
return program
|
||||
|
||||
unload_program(datum/computer/file/mainframe_program/program)
|
||||
if(!program)
|
||||
return 0
|
||||
|
||||
if(program == src.os)
|
||||
return 0
|
||||
|
||||
if (src.processing[src.processing.len] == program)
|
||||
src.processing -= program
|
||||
else if (program.progid && program.progid <= src.processing.len)
|
||||
src.processing[program.progid] = null
|
||||
// if(src.active_program == program)
|
||||
// src.active_program = src.host_program
|
||||
program.initialized = 0
|
||||
program.unloaded()
|
||||
|
||||
if (program.holding_folder == src.runfolder)
|
||||
//qdel(program)
|
||||
program.dispose()
|
||||
|
||||
return 1
|
||||
|
||||
unload_all()
|
||||
src.os = null
|
||||
for(var/datum/computer/file/mainframe_program/M in src.processing)
|
||||
src.unload_program(M)
|
||||
|
||||
return
|
||||
|
||||
|
||||
delete_file(datum/computer/file/theFile)
|
||||
if((!theFile) || (!theFile.holder) || (theFile.holder.read_only))
|
||||
//boutput(world, "Cannot delete :(")
|
||||
return 0
|
||||
|
||||
//qdel(file)
|
||||
theFile.dispose()
|
||||
return 1
|
||||
|
||||
relay_progsignal(var/datum/computer/file/mainframe_program/caller, var/progid, var/list/data = null, var/datum/computer/file/file)
|
||||
if (progid < 1 || progid > src.processing.len || !caller)
|
||||
return ESIG_GENERIC
|
||||
|
||||
var/datum/computer/file/mainframe_program/P = src.processing[progid]
|
||||
if(!istype(P))
|
||||
return ESIG_GENERIC
|
||||
|
||||
var/callID = src.processing.Find(caller)
|
||||
return P.receive_progsignal(callID, data, file)
|
||||
|
||||
set_broken()
|
||||
icon_state = initial(src.icon_state)
|
||||
icon_state += "b"
|
||||
stat |= BROKEN
|
||||
|
||||
reconnect_all_devices()
|
||||
for (var/device_id in src.terminals)
|
||||
var/datum/terminal_connection/conn = src.terminals[device_id]
|
||||
if (istype(conn) && cmptext(conn.term_type, "hui_terminal"))
|
||||
continue
|
||||
|
||||
reconnect_device(device_id)
|
||||
|
||||
return ESIG_SUCCESS
|
||||
|
||||
reconnect_device(var/device_netid)
|
||||
if (!device_netid)
|
||||
return ESIG_GENERIC
|
||||
|
||||
device_netid = lowertext(device_netid)
|
||||
if (device_netid in src.terminals)
|
||||
var/datum/terminal_connection/conn = src.terminals[device_netid]
|
||||
if(src.os)
|
||||
src.os.closed_connection(conn)
|
||||
src.terminals -= device_netid
|
||||
//qdel(conn)
|
||||
if (conn)
|
||||
conn.dispose()
|
||||
|
||||
src.post_status(device_netid, "command", "term_connect", "device", src.device_tag)
|
||||
return ESIG_SUCCESS
|
||||
|
||||
/*
|
||||
* Overview of startup process:
|
||||
* If we already have an OS reference, initialize it and return.
|
||||
* If not, begin looking for an OS file in memory (Of type /datum/computer/file/mainframe_program/os)
|
||||
* Ideally, there is a folder named "sys" in the root directory to look in.
|
||||
* If we can't find the OS there, we pass control over the our bootstrapping program.
|
||||
*/
|
||||
|
||||
post_system()
|
||||
if(src.posted || !src.hd)
|
||||
return
|
||||
|
||||
src.posted = 1
|
||||
|
||||
if(src.os) //Let the starting programs set up vars or whatever
|
||||
src.os.initialize()
|
||||
|
||||
else
|
||||
|
||||
if (src.runfolder)
|
||||
//qdel(src.runfolder)
|
||||
src.runfolder.dispose()
|
||||
src.runfolder = null
|
||||
|
||||
if(src.hd && src.hd.root)
|
||||
var/datum/computer/folder/sysfolder = null
|
||||
for (var/datum/computer/folder/F in src.hd.root.contents)
|
||||
if (F.name == "sys")
|
||||
sysfolder = F
|
||||
break
|
||||
|
||||
if (sysfolder)
|
||||
var/datum/computer/file/mainframe_program/os/newos = locate(/datum/computer/file/mainframe_program/os) in sysfolder.contents
|
||||
if (istype(newos))
|
||||
src.visible_message("[src] beeps")
|
||||
newos.initialized = 0
|
||||
src.run_program(newos)
|
||||
return
|
||||
|
||||
if(!istype(src.bootstrap))
|
||||
src.bootstrap = new src.setup_bootstrap_path
|
||||
|
||||
//Run the bootstrapping code!
|
||||
if(bootstrap)
|
||||
src.run_program(bootstrap)
|
||||
|
||||
return
|
||||
|
||||
|
||||
/*
|
||||
* Bootstrapping System
|
||||
*/
|
||||
|
||||
/datum/computer/file/mainframe_program/os/bootstrap
|
||||
name = "NETBOOT"
|
||||
size = 4
|
||||
needs_holder = 0
|
||||
var/tmp/list/known_banks = list()
|
||||
var/tmp/current = null //Net ID of current bank.
|
||||
var/tmp/stage = 0
|
||||
var/tmp/ping_wait = 0
|
||||
var/tmp/stage_wait = 0
|
||||
var/tmp/rescan_wait = 0
|
||||
var/setup_system_directory = "/sys"
|
||||
var/setup_driver_directory = "/sys/drvr"
|
||||
var/setup_bin_directory = "/bin"
|
||||
|
||||
disposing()
|
||||
known_banks = null
|
||||
..()
|
||||
|
||||
initialize()
|
||||
if(..())
|
||||
return
|
||||
|
||||
src.known_banks.len = 0
|
||||
|
||||
src.clear_core()
|
||||
|
||||
src.find_existing_databanks()
|
||||
|
||||
src.stage_wait = 4
|
||||
src.stage = 1
|
||||
src.ping_wait = 4
|
||||
src.current = null
|
||||
spawn(1)
|
||||
src.master.post_status("ping","data","NETBOOT","net","[src.master.net_number]")
|
||||
return
|
||||
|
||||
process()
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(src.ping_wait)
|
||||
src.ping_wait--
|
||||
return
|
||||
|
||||
if(src.rescan_wait)
|
||||
if (--src.rescan_wait < 1)
|
||||
src.initialized = 0
|
||||
src.initialize()
|
||||
return
|
||||
|
||||
if(src.stage_wait)
|
||||
src.stage_wait--
|
||||
if(stage_wait <= 0)
|
||||
stage = 0
|
||||
|
||||
if(!stage)
|
||||
if(!known_banks.len)
|
||||
src.master.os = null
|
||||
src.handle_quit()
|
||||
//qdel (src)
|
||||
src.dispose()
|
||||
return
|
||||
|
||||
new_current()
|
||||
src.message_term("command=bootreq",current)
|
||||
return
|
||||
return
|
||||
|
||||
new_connection(datum/terminal_connection/conn)
|
||||
if(!istype(conn))
|
||||
return
|
||||
|
||||
if(conn.term_type == "PNET_DATA_BANK" && !(conn.net_id in known_banks) )
|
||||
known_banks += conn.net_id
|
||||
|
||||
return
|
||||
|
||||
closed_connection(datum/terminal_connection/conn)
|
||||
if(!istype(conn)) return
|
||||
var/del_netid = conn.net_id
|
||||
if(del_netid in src.known_banks)
|
||||
src.known_banks -= del_netid
|
||||
return
|
||||
|
||||
ping_reply(var/senderid,var/sendertype)
|
||||
if(..() || !ping_wait)
|
||||
return
|
||||
|
||||
if( !(senderid in master.terminals) && (sendertype == "PNET_DATA_BANK" || sendertype == "HUI_TERMINAL"))
|
||||
spawn(rand(1,4))
|
||||
src.master.post_status(senderid,"command","term_connect","device",master.device_tag)
|
||||
return
|
||||
|
||||
term_input(var/data, var/termid, var/datum/computer/file/the_file)
|
||||
if(..() || !stage)
|
||||
return
|
||||
|
||||
var/datum/terminal_connection/conn = master.terminals[termid]
|
||||
if(!conn || !conn.term_type)
|
||||
return
|
||||
var/device_type = conn.term_type
|
||||
if(device_type == "PNET_DATA_BANK")
|
||||
var/list/commandlist = params2list(data)
|
||||
if(!commandlist || !commandlist["command"])
|
||||
return
|
||||
var/command = lowertext(commandlist["command"])
|
||||
|
||||
//boutput(world, "\[[conn.net_id]]")
|
||||
|
||||
switch(command)
|
||||
if("register")
|
||||
return
|
||||
|
||||
if("file")
|
||||
//boutput(world, "FILE")
|
||||
if(!the_file)
|
||||
new_current()
|
||||
return
|
||||
|
||||
var/datum/computer/file/archive/arc = the_file.copy_file()
|
||||
if(!istype(arc))
|
||||
//qdel(arc)
|
||||
arc.dispose()
|
||||
new_current()
|
||||
return
|
||||
|
||||
var/datum/computer/file/mainframe_program/os/newos = locate() in arc.contained_files
|
||||
if(!istype(newos))
|
||||
//qdel(arc)
|
||||
arc.dispose()
|
||||
new_current()
|
||||
return
|
||||
|
||||
var/datum/computer/folder/sysdir = parse_directory(src.setup_system_directory, src.holder.root, 1)
|
||||
var/datum/computer/folder/drivedir = parse_directory(src.setup_driver_directory, src.holder.root, 1)
|
||||
var/datum/computer/folder/bindir = parse_directory(src.setup_bin_directory, src.holder.root, 1)
|
||||
var/datum/computer/folder/srvdir = parse_directory("srv", sysdir, 1)
|
||||
if(!sysdir || !drivedir || !bindir || !srvdir)
|
||||
master.visible_message("[master] boops")
|
||||
master.os = null
|
||||
src.handle_quit()
|
||||
//dispose()
|
||||
src.dispose()
|
||||
return
|
||||
|
||||
for(var/datum/computer/file/mainframe_program/MP in arc.contained_files)
|
||||
if (istype(MP, /datum/computer/file/mainframe_program/os))
|
||||
continue
|
||||
|
||||
var/datum/computer/file/mainframe_program/MP_copy = MP.copy_file()
|
||||
if (istype(MP_copy, /datum/computer/file/mainframe_program/driver))
|
||||
if(get_computer_datum(MP_copy.name, drivedir))
|
||||
continue
|
||||
if(!drivedir.add_file(MP_copy))
|
||||
//qdel(MP_copy)
|
||||
MP_copy.dispose()
|
||||
break
|
||||
|
||||
else if (istype(MP_copy, /datum/computer/file/mainframe_program/utility))
|
||||
if(get_computer_datum(MP_copy.name, bindir))
|
||||
continue
|
||||
if(!bindir.add_file(MP_copy))
|
||||
///qdel(MP_copy)
|
||||
MP_copy.dispose()
|
||||
break
|
||||
|
||||
else if (istype(MP_copy, /datum/computer/file/mainframe_program/srv))
|
||||
if(get_computer_datum(MP_copy.name, sysdir))
|
||||
continue
|
||||
|
||||
if(!srvdir.add_file(MP_copy))
|
||||
MP_copy.dispose()
|
||||
|
||||
else
|
||||
if(get_computer_datum(MP_copy.name, sysdir))
|
||||
continue
|
||||
if(!sysdir.add_file(MP_copy))
|
||||
//qdel(MP_copy)
|
||||
MP_copy.dispose()
|
||||
break
|
||||
|
||||
newos = newos.copy_file()
|
||||
if(sysdir.add_file(newos))
|
||||
master.os = null
|
||||
//qdel(arc)
|
||||
arc.dispose()
|
||||
master.visible_message("[master] beeps")
|
||||
master.run_program(newos)
|
||||
src.handle_quit()
|
||||
//dispose()
|
||||
src.dispose()
|
||||
return
|
||||
else
|
||||
//qdel(arc)
|
||||
//qdel(newos)
|
||||
if (arc)
|
||||
arc.dispose()
|
||||
if (newos)
|
||||
newos.dispose()
|
||||
/*
|
||||
src.quit()
|
||||
qdel(src)
|
||||
*/
|
||||
master.visible_message("[master] boops sadly.")
|
||||
src.rescan_wait = 20
|
||||
return
|
||||
|
||||
|
||||
if ("status")
|
||||
src.stage_wait = 1
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
proc
|
||||
new_current() //Move on to a new current in the list.
|
||||
if(src.current)
|
||||
src.known_banks.Cut(1,2)
|
||||
src.current = null
|
||||
|
||||
if(!known_banks.len)
|
||||
/*
|
||||
src.master.os = null
|
||||
src.quit()
|
||||
qdel(src)
|
||||
*/
|
||||
src.rescan_wait = 20
|
||||
return
|
||||
|
||||
stage_wait = 4
|
||||
stage = 1
|
||||
src.current = known_banks[1]
|
||||
return
|
||||
|
||||
clear_core() //Clear the core memory board.
|
||||
if(!src.holder || !src.holder.root)
|
||||
return 0
|
||||
|
||||
for(var/datum/computer/C in src.holder.root)
|
||||
if(C == src || C == src.holding_folder)
|
||||
continue
|
||||
|
||||
//qdel(C)
|
||||
C.dispose()
|
||||
|
||||
return 1
|
||||
|
||||
find_existing_databanks() //Find databank connections already in master.terminals
|
||||
if(!src.master)
|
||||
return
|
||||
|
||||
for(var/x in master.terminals)
|
||||
var/datum/terminal_connection/conn = master.terminals[x]
|
||||
if(!istype(conn))
|
||||
continue
|
||||
|
||||
master.terminals -= x
|
||||
//qdel(conn)
|
||||
conn.dispose()
|
||||
|
||||
var/tempx = x
|
||||
spawn(rand(1,4))
|
||||
src.master.post_status(tempx, "command", "term_disconnect")
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
/*
|
||||
* A little mass message proc for some SPOOKY ANTICS
|
||||
*/
|
||||
|
||||
/proc/send_spooky_mainframe_message(var/the_message, var/a_spooky_custom_name)
|
||||
if (!the_message)
|
||||
return 1
|
||||
|
||||
for (var/obj/machinery/networked/mainframe/aMainframe in world)
|
||||
if (aMainframe.z != 1)
|
||||
continue
|
||||
|
||||
if (!aMainframe.os || !hascall(aMainframe.os, "message_all_users"))
|
||||
continue
|
||||
|
||||
aMainframe.os:message_all_users(the_message, a_spooky_custom_name, 1)
|
||||
return 0
|
||||
|
||||
return 2
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,969 @@
|
||||
//CONTENTS
|
||||
//User shell
|
||||
|
||||
|
||||
//User shell program
|
||||
//Allows execution of various mainframe programs, as well as some scripting and a set of built-in commands.
|
||||
/datum/computer/file/mainframe_program/shell
|
||||
name = "Msh"
|
||||
size = 8
|
||||
executable = 0
|
||||
var/tmp/piping = 0
|
||||
var/tmp/pipetemp = ""
|
||||
|
||||
var/tmp/scriptline = 0
|
||||
var/tmp/list/shscript
|
||||
var/tmp/list/scriptvars
|
||||
var/tmp/scriptstat = 0
|
||||
var/tmp/script_iteration = 1
|
||||
|
||||
var/tmp/list/stack = list()
|
||||
var/tmp/list/previous_shscripts
|
||||
var/tmp/list/previous_scriptline
|
||||
var/tmp/previous_pipeout
|
||||
var/tmp/suppress_out = 0
|
||||
|
||||
var/setup_helprec_name = "help"
|
||||
var/setup_max_piped_commands = 16
|
||||
|
||||
#define SCRIPT_IF_TRUE 1
|
||||
#define SCRIPT_IN_LOOP 2
|
||||
#define MAX_SCRIPT_ITERATIONS 2048
|
||||
#define MAX_STACK_DEPTH 128
|
||||
|
||||
#define EVAL_BOOL_TRUE 1
|
||||
#define EVAL_BOOL_FALSE 0
|
||||
#define ERR_STACK_OVER -1
|
||||
#define ERR_STACK_UNDER -2
|
||||
#define ERR_UNDEFINED -3
|
||||
|
||||
initialize()
|
||||
if(..() || !useracc)
|
||||
return
|
||||
|
||||
previous_pipeout = null
|
||||
|
||||
piping = 0
|
||||
suppress_out = 0
|
||||
pipetemp = ""
|
||||
scriptline = 0
|
||||
script_iteration = 1
|
||||
scriptstat = 0
|
||||
scriptvars = list()
|
||||
shscript = list()
|
||||
previous_shscripts = list()
|
||||
previous_scriptline = list()
|
||||
|
||||
if (useracc.user_file)
|
||||
if(!read_user_field("name"))
|
||||
write_user_field("name", useracc.user_name)
|
||||
useracc.user_file.fields["curpath"] = "/home/usr[read_user_field("name")]"
|
||||
|
||||
message_user("[read_user_field("name")]@DWAINE - [time2text(world.realtime, "hh:mm MM/DD/53")]|nType \"help\" for command listing.", "multiline")
|
||||
return
|
||||
|
||||
process()
|
||||
if (..() || !useracc)
|
||||
return
|
||||
|
||||
script_process()
|
||||
return
|
||||
|
||||
|
||||
input_text(var/text, var/scripting = 0)
|
||||
//boutput(world, "input_text([text], [scripting])")
|
||||
if(..() || !useracc || ((scripting != 0) != (scriptline != 0)))
|
||||
return 1
|
||||
|
||||
var/list/subcommands = list()
|
||||
var/list/piped_list = command2list(text, "^", scriptvars, subcommands)//scripting ? scriptvars : null)
|
||||
piped_list.len = min(piped_list.len, setup_max_piped_commands)
|
||||
piping = piped_list.len
|
||||
pipetemp = ""
|
||||
var/script_counter = 0
|
||||
|
||||
while(piped_list.len && (script_counter < MAX_SCRIPT_ITERATIONS))
|
||||
script_counter++
|
||||
text = piped_list[1]
|
||||
piped_list -= piped_list[1]
|
||||
piping--
|
||||
|
||||
var/subPlace = findtext(text, "_sub")
|
||||
|
||||
while (subPlace)
|
||||
|
||||
var/subIndex = text2num( copytext( text, subPlace+4, subPlace+5) )
|
||||
|
||||
if (isnum(subIndex) && subIndex > 0 && subIndex <= subcommands.len)
|
||||
|
||||
previous_pipeout = ""
|
||||
suppress_out = 1
|
||||
if (!input_text(subcommands[subIndex], 0))
|
||||
|
||||
if (dd_hassuffix(previous_pipeout, "|n"))
|
||||
previous_pipeout = copytext(previous_pipeout, 1, -2)
|
||||
|
||||
text = "[copytext(text, 1, subPlace)][previous_pipeout][copytext(text, subPlace+5)]"
|
||||
//boutput(world, " --> \"[text]\"")
|
||||
suppress_out = 0
|
||||
|
||||
|
||||
else
|
||||
suppress_out = 0
|
||||
return 1
|
||||
|
||||
subPlace = findtext(text, "_sub")
|
||||
|
||||
var/list/command_list = parse_string(text, (scripting ? src.scriptvars : null))
|
||||
var/command = lowertext(command_list[1])
|
||||
command_list.Cut(1,2) //Remove the command that we are now processing.
|
||||
while (!command && command_list.len)
|
||||
command = command_list[1]
|
||||
command_list.Cut(1,2)
|
||||
|
||||
var/current = read_user_field("curpath")
|
||||
|
||||
if (!dd_hassuffix(current, "/") && current != "/")
|
||||
current = "[current]/"
|
||||
|
||||
if (execpath("/bin/[command]", current, command, command_list, scripting ? script_iteration : 0))
|
||||
continue
|
||||
|
||||
else
|
||||
switch(execpath("[current][dd_hasprefix(command,"/") ? copytext(command, 1) : command]", current, command, command_list, scripting ? script_iteration : 0))
|
||||
if (1)
|
||||
continue
|
||||
if (2)
|
||||
if (script_iteration < 2)
|
||||
script_process()
|
||||
return 0
|
||||
if (3)
|
||||
message_user("Error: Stack overflow.")
|
||||
return 1
|
||||
|
||||
switch(lowertext(command))
|
||||
if ("eval")
|
||||
var/result = null
|
||||
var/pipe_result = (command_list.len == 1)
|
||||
|
||||
if (!command_list.len)
|
||||
continue
|
||||
|
||||
if (stack)
|
||||
stack.len = 0
|
||||
else
|
||||
stack = list()
|
||||
|
||||
switch (script_evaluate2(command_list, 0))
|
||||
if (0,1)
|
||||
if (stack.len)
|
||||
result = stack[stack.len]
|
||||
else
|
||||
result = 0
|
||||
|
||||
|
||||
if (ERR_STACK_OVER)
|
||||
message_user("Error: Stack overflow.")
|
||||
return 1
|
||||
|
||||
if (ERR_STACK_UNDER)
|
||||
message_user("Error: Stack underflow.")
|
||||
return 1
|
||||
|
||||
if (ERR_UNDEFINED)
|
||||
message_user("Error: Undefined result.")
|
||||
|
||||
return 1
|
||||
|
||||
if (piping && pipe_result)
|
||||
pipetemp = "[result]"
|
||||
|
||||
else if (!scripting && !isnull(result))
|
||||
message_user("[result]")
|
||||
|
||||
continue
|
||||
|
||||
if ("goonsay")
|
||||
var/anger_text = null
|
||||
if (pipetemp)
|
||||
anger_text = pipetemp
|
||||
|
||||
if(istype(command_list) && (command_list.len > 0))
|
||||
anger_text += dd_list2text(command_list, " ")
|
||||
|
||||
if (piping && piped_list.len && (ckey(piped_list[1]) != "break") )
|
||||
pipetemp = anger_text
|
||||
else
|
||||
if (!anger_text)
|
||||
anger_text = "A clown? On a space station? what|n"
|
||||
else if (!dd_hassuffix(anger_text, "|n"))
|
||||
anger_text += "|n"
|
||||
message_user("[anger_text] __________|n(--\[ .]-\[ .] /|n(_______0__)", "multiline")
|
||||
continue
|
||||
|
||||
|
||||
if ("echo")
|
||||
var/echo_text = null
|
||||
if (pipetemp)
|
||||
echo_text = pipetemp
|
||||
|
||||
if(istype(command_list) && (command_list.len > 0))
|
||||
echo_text += dd_list2text(command_list, " ")
|
||||
|
||||
if (piping && piped_list.len && (ckey(piped_list[1]) != "break") )
|
||||
pipetemp = echo_text
|
||||
else
|
||||
if (echo_text && !dd_hassuffix(echo_text, "|n"))
|
||||
echo_text += "|n"
|
||||
message_user(echo_text, "multiline")
|
||||
|
||||
continue
|
||||
|
||||
//User identification & communication commands
|
||||
|
||||
if ("who")
|
||||
var/whotext = null
|
||||
var/list/wholist = signal_program(1, list("command"=DWAINE_COMMAND_ULIST))
|
||||
|
||||
if (istype(wholist))
|
||||
for (var/uid in wholist)
|
||||
whotext += "[uid]-[wholist[uid]]|n"
|
||||
else
|
||||
whotext = "Error: Unable to determine current users."
|
||||
|
||||
if (piping)
|
||||
pipetemp = whotext
|
||||
else
|
||||
if (!whotext)
|
||||
whotext = "Error: Unable to determine current users."
|
||||
|
||||
message_user(whotext, "multiline")
|
||||
continue
|
||||
|
||||
if ("mesg")
|
||||
var/input = (command_list.len ? command_list[1] : null)
|
||||
if (pipetemp)
|
||||
input = pipetemp
|
||||
|
||||
if (piping)
|
||||
if (input)
|
||||
switch (lowertext(input))
|
||||
if ("y")
|
||||
if (write_user_field("accept_msg","1"))
|
||||
pipetemp = "Now allowing messages."
|
||||
else
|
||||
pipetemp = "Error: Unable to write user configuration."
|
||||
if ("n")
|
||||
if (write_user_field("accept_msg","0"))
|
||||
pipetemp = "Now disallowing messages."
|
||||
else
|
||||
pipetemp = "Error: Unable to write user configuration."
|
||||
else
|
||||
pipetemp = "Error: Invalid argument for mesg (Must be \"y\" or \"n\")"
|
||||
else
|
||||
pipetemp = "is [read_user_field("accept_msg") == "1" ? "y" : "n"]"
|
||||
else
|
||||
if (input)
|
||||
switch (lowertext(input))
|
||||
if ("y")
|
||||
if (write_user_field("accept_msg","1"))
|
||||
message_user("Now allowing messages.")
|
||||
else
|
||||
message_user("Error: Unable to write user configuration.")
|
||||
if ("n")
|
||||
if (write_user_field("accept_msg","0"))
|
||||
message_user("Now disallowing messages.")
|
||||
else
|
||||
message_user("Error: Unable to write user configuration.")
|
||||
else
|
||||
message_user("Error: Invalid argument for mesg (Must be \"y\" or \"n\")")
|
||||
else
|
||||
message_user("is [read_user_field("accept_msg") == "1" ? "y" : "n"]")
|
||||
|
||||
continue
|
||||
|
||||
if ("talk")
|
||||
if (pipetemp)
|
||||
|
||||
if(istype(command_list))
|
||||
command_list += dd_text2list(pipetemp, " ")
|
||||
|
||||
if (command_list.len < 2)
|
||||
message_user("Error: Insufficient arguments for Talk (Requires Target ID and Message).")
|
||||
return 1
|
||||
|
||||
var/targetUser = lowertext(command_list[1])
|
||||
command_list.Cut(1,2)
|
||||
|
||||
switch (signal_program(1, list("command"=DWAINE_COMMAND_UMSG, "term"=targetUser, data=dd_list2text(command_list, " "))))
|
||||
if (ESIG_SUCCESS)
|
||||
continue
|
||||
if (ESIG_NOTARGET)
|
||||
message_user("Error: Invalid Target ID")
|
||||
return 1
|
||||
if (ESIG_IOERR)
|
||||
if (piping)
|
||||
pipetemp = "Error: Message refused by Target."
|
||||
else
|
||||
message_user("Error: Message refused by Target.")
|
||||
continue
|
||||
else
|
||||
message_user("Error: Unexpected response from kernel.")
|
||||
return 1
|
||||
|
||||
continue
|
||||
|
||||
|
||||
//SCRIPTING COMMANDS FOLLOW:
|
||||
//If - Evaluate an expression. If true, set SCRIPT_IF_TRUE in scriptstat and continue piping
|
||||
//if false, unset SCRIPT_IF_TRUE and continue to the next line
|
||||
//if null (From an evaluation error or invalid input), halt the script
|
||||
if ("if")
|
||||
|
||||
if (!command_list.len)
|
||||
return 1
|
||||
|
||||
switch (script_evaluate2(command_list, 1))
|
||||
if (1)
|
||||
pipetemp = null
|
||||
scriptstat |= SCRIPT_IF_TRUE
|
||||
var/elsePosition = piped_list.Find("else")
|
||||
if (elsePosition)
|
||||
piped_list.Cut(elsePosition)
|
||||
piping = piped_list.len
|
||||
continue //Continue processing any piped commands following this.
|
||||
if (0)
|
||||
scriptstat &= ~SCRIPT_IF_TRUE
|
||||
|
||||
var/elsePosition = piped_list.Find("else")
|
||||
if (elsePosition)
|
||||
piped_list.Cut(1,elsePosition+1)
|
||||
piping = piped_list.len
|
||||
pipetemp = null
|
||||
continue
|
||||
|
||||
return 0 //Move to the next line of the script, dropping any following commands on this line.
|
||||
if (null)
|
||||
return 1
|
||||
|
||||
if ("else")
|
||||
|
||||
if (scriptstat & SCRIPT_IF_TRUE)
|
||||
return 0
|
||||
|
||||
continue
|
||||
|
||||
if ("while")
|
||||
if (!command_list.len || (scriptstat & SCRIPT_IN_LOOP))
|
||||
return 1
|
||||
|
||||
switch (script_evaluate2(command_list, 1))
|
||||
if (1)
|
||||
scriptstat |= SCRIPT_IN_LOOP
|
||||
continue
|
||||
if (0)
|
||||
scriptstat &= ~SCRIPT_IN_LOOP
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
|
||||
if ("break")
|
||||
return 1
|
||||
|
||||
if ("sleep")
|
||||
if (!command_list.len)
|
||||
continue
|
||||
|
||||
. = text2num(command_list[1])
|
||||
if (!isnum(.) || . < 0)
|
||||
continue
|
||||
|
||||
sleep ( max(0, min(., 30)) )
|
||||
continue
|
||||
|
||||
if ("help", "man")
|
||||
var/datum/computer/file/record/helpRec = signal_program(1, list("command"=DWAINE_COMMAND_CONFGET,"fname"=setup_helprec_name))
|
||||
if (istype(helpRec))
|
||||
var/target_entry = "index"
|
||||
if (command_list.len && ckey(command_list[1]))
|
||||
target_entry = lowertext(command_list[1])
|
||||
|
||||
if (target_entry in helpRec.fields)
|
||||
message_user("[capitalize(target_entry)]: [helpRec.fields[target_entry]]", "multiline")
|
||||
else
|
||||
message_user("Error: Unknown topic.")
|
||||
else
|
||||
message_user("Error: Help library missing or invalid.")
|
||||
|
||||
continue
|
||||
|
||||
if ("logout","logoff")
|
||||
message_user("Thank you for using DWAINE!", "clear")
|
||||
mainframe_prog_exit
|
||||
return 1
|
||||
|
||||
else
|
||||
if (pipetemp)
|
||||
var/prefixroot = dd_hasprefix(command, "/")
|
||||
if (!prefixroot)
|
||||
command = "[current]" + ((dd_hassuffix(current, "/") || current == "/") ? null : "/") + command
|
||||
|
||||
var/list/templist = dd_text2list(command, "/")
|
||||
if (!templist.len)
|
||||
message_user("Syntax error.")
|
||||
break
|
||||
|
||||
var/recname = null
|
||||
recname = copytext(templist[templist.len], 1, 16)
|
||||
while (dd_hasprefix(recname, " "))
|
||||
recname = copytext(recname, 2)
|
||||
templist.len--
|
||||
command = dd_list2text(templist, "/")
|
||||
if (!recname)
|
||||
recname = "out"
|
||||
|
||||
if ((prefixroot || !command) && !dd_hasprefix(command, "/"))
|
||||
command = "/[command]"
|
||||
|
||||
//boutput(world, "here is the path: \"[command]\" and the name \"[recname]\"")
|
||||
var/datum/computer/file/record/rec = new /datum/computer/file/record( )
|
||||
rec.fields = dd_text2list(pipetemp, "|n")
|
||||
rec.name = recname
|
||||
rec.metadata["owner"] = read_user_field("name")
|
||||
rec.metadata["permission"] = COMP_ALLACC
|
||||
|
||||
if (signal_program(1, list("command"=DWAINE_COMMAND_FWRITE,"path"=command, "append"=1), rec) != ESIG_SUCCESS)
|
||||
message_user("Unable to pipe stream to file.")
|
||||
//qdel(rec)
|
||||
rec.dispose()
|
||||
break
|
||||
|
||||
continue
|
||||
|
||||
|
||||
message_user("Syntax error.")
|
||||
return 1
|
||||
|
||||
//message_user("[dirpath]$ " + text)
|
||||
previous_pipeout += pipetemp
|
||||
return 0
|
||||
|
||||
proc
|
||||
execpath(var/fpath, var/current, var/command, var/list/command_list, var/scripting=0)
|
||||
//boutput(world, "execpath([fpath], [current], [command], ,[scripting])")
|
||||
var/datum/computer/file/record/exec = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"=fpath))
|
||||
if (istype(exec, /datum/computer/file/mainframe_program))
|
||||
var/list/siglist = list("command"=DWAINE_COMMAND_TSPAWN, "passusr"=1, "path"=fpath)//"[current][command]")
|
||||
if (command_list.len)
|
||||
siglist["args"] = strip_html(dd_list2text(command_list, " ")) + (pipetemp ? " [pipetemp]" : null)
|
||||
else if (pipetemp)
|
||||
siglist["args"] = pipetemp
|
||||
|
||||
pipetemp = ""
|
||||
signal_program(1, siglist)
|
||||
//qdel(siglist)
|
||||
return 1
|
||||
|
||||
else if (istype(exec) && (!pipetemp || scripting) && exec.fields && (exec.fields.len > 1) && dd_hasprefix(exec.fields[1], "#!")) //Maybe it's a shell script?
|
||||
if (previous_shscripts.len + 1 > MAX_SCRIPT_ITERATIONS)
|
||||
//script_iteration = 1
|
||||
previous_shscripts.len = 0
|
||||
return 3
|
||||
previous_scriptline.Insert(1, scriptline)
|
||||
scriptline = 1
|
||||
//script_iteration++
|
||||
//scriptstat = 0
|
||||
|
||||
if (shscript.len)
|
||||
previous_shscripts.Insert(1, 0)
|
||||
previous_shscripts[1] = shscript
|
||||
shscript = script_format( exec.fields.Copy() )
|
||||
//shscript.Insert(2, script_format( exec.fields.Copy() ))
|
||||
else
|
||||
//script_iteration = 1
|
||||
//scriptline = 1
|
||||
stack.len = 0
|
||||
shscript = script_format( exec.fields.Copy() )
|
||||
scriptvars["su"] = (read_user_field("group") == 0)
|
||||
|
||||
command_list.len = min(command_list.len, 8)
|
||||
|
||||
. = ""
|
||||
for (var/i = 1, i <= command_list.len, i++)
|
||||
scriptvars["arg[i-1]"] = command_list[i]
|
||||
. += "[. ? " " : null][command_list[i]]"
|
||||
|
||||
|
||||
scriptvars["*"] = .
|
||||
scriptvars["argc"] = command_list.len
|
||||
scriptvars["$"] = src.progid
|
||||
|
||||
return 2
|
||||
|
||||
return 0
|
||||
|
||||
script_process()
|
||||
spawn(0)
|
||||
while (shscript.len)
|
||||
|
||||
for (var/i = 1, i <= 5, i++)
|
||||
if (!shscript.len)
|
||||
if (previous_shscripts.len && istype(previous_shscripts[1], /list))
|
||||
shscript = previous_shscripts[1]
|
||||
previous_shscripts.Cut(1,2)
|
||||
scriptline = previous_scriptline[1]
|
||||
previous_scriptline.Cut(1,2)
|
||||
break
|
||||
|
||||
//Input_text should return 1 on an error, so break if we get that, I guess.
|
||||
if (src.input_text(shscript[1], script_iteration+1))
|
||||
message_user("Break at line [scriptline+1]")
|
||||
shscript.len = 0
|
||||
scriptline = 0
|
||||
script_iteration = 1
|
||||
return
|
||||
|
||||
if (scriptstat & SCRIPT_IN_LOOP)
|
||||
scriptstat &= ~SCRIPT_IN_LOOP //Turn this back off now
|
||||
continue
|
||||
|
||||
if (shscript.len)
|
||||
shscript.Cut(1, 2)
|
||||
scriptline++
|
||||
|
||||
scriptline *= (shscript.len > 0)
|
||||
sleep(10)
|
||||
return
|
||||
|
||||
script_format(var/list/scriptlist)
|
||||
if (!scriptlist || scriptlist.len < 2)
|
||||
return list()
|
||||
|
||||
//The first line should just be #!, so...
|
||||
scriptlist.Cut(1,2) //Don't need to copy the whole shebang, ha ha get it??
|
||||
|
||||
for (var/i = 1, i <= scriptlist.len, i++)
|
||||
//Check if it's a comment line...
|
||||
if (dd_hasprefix(trim_left(scriptlist[i]), "#"))
|
||||
scriptlist.Cut(i, i+1)
|
||||
i--
|
||||
continue
|
||||
scriptlist[i] = dd_replacetext(scriptlist[i], "|", "^")
|
||||
|
||||
return scriptlist
|
||||
|
||||
//Something something immersion something something 32-bit signed someting fixed point something.
|
||||
script_clampvalue(var/clampnum)
|
||||
//return round( min( max(text2num(clampnum), -2147483647), 2147483648) )
|
||||
return round( min( max(clampnum, -2147483647), 2147483648), 0.01 )
|
||||
|
||||
script_isNumResult(var/current, var/result)
|
||||
|
||||
if (isnum(text2num(current)) && isnum(text2num(result)))
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
script_evaluate2(var/list/command_stream, return_bool)
|
||||
|
||||
stack.len = 0
|
||||
while (command_stream && command_stream.len)
|
||||
var/current_command = command_stream[1]
|
||||
//boutput(world, "current_command = \[[current_command]]")
|
||||
command_stream.Cut(1,2)
|
||||
|
||||
if (text2num(current_command) != null)
|
||||
if (stack.len > MAX_STACK_DEPTH)
|
||||
return ERR_STACK_OVER
|
||||
|
||||
stack += script_clampvalue( text2num(current_command) )
|
||||
continue
|
||||
|
||||
var/result = null
|
||||
switch ( lowertext(current_command) )
|
||||
if ("+") //(1X 2X -- (1X + 2X))
|
||||
if (stack.len < 2)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
if (script_isNumResult(stack[stack.len], stack[stack.len-1]))
|
||||
result = stack[stack.len] + stack[stack.len-1]
|
||||
stack[--stack.len] = script_clampvalue( result )
|
||||
|
||||
else
|
||||
result = "[stack[stack.len-1] ][ stack[stack.len] ]"
|
||||
stack[--stack.len] = result
|
||||
|
||||
if ("-") //(1X 2X -- (1X - 2X)
|
||||
if (stack.len < 2)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
if (script_isNumResult(stack[stack.len], stack[stack.len-1]))
|
||||
result = stack[stack.len-1] - stack[stack.len]
|
||||
stack[--stack.len] = script_clampvalue( result )
|
||||
|
||||
else if (istext(stack[stack.len-1]) && isnum(stack[stack.len]))
|
||||
result = copytext(stack[stack.len-1], 1, max( length(stack[stack.len-1]) - stack[stack.len], 1) )
|
||||
stack[--stack.len] = result
|
||||
|
||||
else
|
||||
return ERR_UNDEFINED
|
||||
|
||||
if ("*") //(1X 2X -- (1X * 2X))
|
||||
if (stack.len < 2)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
if (script_isNumResult(stack[stack.len], stack[stack.len-1]))
|
||||
result = stack[stack.len-1] * stack[stack.len]
|
||||
stack[--stack.len] = script_clampvalue( result )
|
||||
|
||||
else if (istext(stack[stack.len-1]) && isnum(stack[stack.len]))
|
||||
result = ""
|
||||
var/repeatCount = stack[stack.len]
|
||||
while (repeatCount-- > 0)
|
||||
result += "[stack[stack.len-1]]"
|
||||
|
||||
stack[--stack.len] = copytext(result, 1, MAX_MESSAGE_LEN)
|
||||
|
||||
else
|
||||
return ERR_UNDEFINED
|
||||
|
||||
if ("/") //(1X 2X -- (1X / 2X))
|
||||
if (stack.len < 2)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
if (script_isNumResult(stack[stack.len], stack[stack.len-1]))
|
||||
if (stack[stack.len] == 0)
|
||||
return ERR_UNDEFINED
|
||||
|
||||
result = stack[stack.len-1] / stack[stack.len]
|
||||
stack[--stack.len] = script_clampvalue( result )
|
||||
|
||||
else if (istext(stack[stack.len]) && istext(stack[stack.len-1]))
|
||||
var/list/explodedString = dd_text2list("[stack[stack.len-1]]", "[stack[stack.len]]")
|
||||
if (explodedString.len + stack.len > MAX_STACK_DEPTH)
|
||||
return ERR_STACK_OVER
|
||||
|
||||
// reverselist is getting removed because it didnt actually do anything other than copy the list, if this line actually intended to reverse it, use reverse_list
|
||||
//explodedString = reverselist(explodedString)
|
||||
|
||||
stack.len -= 2
|
||||
stack += explodedString
|
||||
|
||||
else
|
||||
return ERR_UNDEFINED
|
||||
|
||||
if ("%")
|
||||
if (stack.len < 2)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
if (script_isNumResult(stack[stack.len], stack[stack.len-1]))
|
||||
if (stack[stack.len] == 0)
|
||||
return ERR_UNDEFINED
|
||||
|
||||
result = stack[stack.len-1] % stack[stack.len]
|
||||
stack[--stack.len] = script_clampvalue( result )
|
||||
|
||||
else
|
||||
return ERR_UNDEFINED
|
||||
|
||||
if ("eq") //(1X 2X -- (1X == 2X))
|
||||
if (stack.len < 2)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
result = stack[stack.len-1] == stack[stack.len]
|
||||
stack[--stack.len] = result
|
||||
|
||||
if ("ne") //(1X 2X -- (1X != 2X))
|
||||
if (stack.len < 2)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
result = stack[stack.len-1] != stack[stack.len]
|
||||
stack[--stack.len] = result
|
||||
|
||||
if ("gt") //(1X 2X -- (1X > 2X))
|
||||
if (stack.len < 2)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
if (script_isNumResult(stack[stack.len], stack[stack.len-1]))
|
||||
result = stack[stack.len-1] > stack[stack.len]
|
||||
stack[--stack.len] = result
|
||||
|
||||
else if (istext(stack[stack.len-1]) && isnum(stack[stack.len]))
|
||||
result = length(stack[stack.len-1]) > stack[stack.len]
|
||||
stack[--stack.len] = result
|
||||
|
||||
else if (isnum(stack[stack.len-1]) && istext(stack[stack.len]))
|
||||
result = stack[stack.len-1] > length(stack[stack.len])
|
||||
stack[--stack.len] = result
|
||||
|
||||
else
|
||||
result = length(stack[stack.len-1]) > length(stack[stack.len])
|
||||
stack[--stack.len] = result
|
||||
|
||||
if ("ge") //(1X 2X -- (1X >= 2X))
|
||||
if (stack.len < 2)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
if (script_isNumResult(stack[stack.len], stack[stack.len-1]))
|
||||
result = stack[stack.len-1] >= stack[stack.len]
|
||||
stack[--stack.len] = result
|
||||
|
||||
else if (istext(stack[stack.len-1]) && isnum(stack[stack.len]))
|
||||
result = length(stack[stack.len-1]) >= stack[stack.len]
|
||||
stack[--stack.len] = result
|
||||
|
||||
else if (isnum(stack[stack.len-1]) && istext(stack[stack.len]))
|
||||
result = stack[stack.len-1] >= length(stack[stack.len])
|
||||
stack[--stack.len] = result
|
||||
|
||||
else
|
||||
result = length(stack[stack.len-1]) >= length(stack[stack.len])
|
||||
stack[--stack.len] = result
|
||||
|
||||
if ("lt") //(1X 2X -- (1X < 2X))
|
||||
if (stack.len < 2)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
if (script_isNumResult(stack[stack.len], stack[stack.len-1]))
|
||||
result = stack[stack.len-1] < stack[stack.len]
|
||||
stack[--stack.len] = result
|
||||
|
||||
else if (istext(stack[stack.len-1]) && isnum(stack[stack.len]))
|
||||
result = length(stack[stack.len-1]) < stack[stack.len]
|
||||
stack[--stack.len] = result
|
||||
|
||||
else if (isnum(stack[stack.len-1]) && istext(stack[stack.len]))
|
||||
result = stack[stack.len-1] < length(stack[stack.len])
|
||||
stack[--stack.len] = result
|
||||
|
||||
else
|
||||
result = length(stack[stack.len-1]) < length(stack[stack.len])
|
||||
stack[--stack.len] = result
|
||||
|
||||
if ("le") //(1X 2X -- (1X <= 2X))
|
||||
if (stack.len < 2)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
if (script_isNumResult(stack[stack.len], stack[stack.len-1]))
|
||||
result = stack[stack.len-1] <= stack[stack.len]
|
||||
stack[--stack.len] = result
|
||||
|
||||
else if (istext(stack[stack.len-1]) && isnum(stack[stack.len]))
|
||||
result = length(stack[stack.len-1]) <= stack[stack.len]
|
||||
stack[--stack.len] = result
|
||||
|
||||
else if (isnum(stack[stack.len-1]) && istext(stack[stack.len]))
|
||||
result = stack[stack.len-1] <= length(stack[stack.len])
|
||||
stack[--stack.len] = result
|
||||
|
||||
else
|
||||
result = length(stack[stack.len-1]) <= length(stack[stack.len])
|
||||
stack[--stack.len] = result
|
||||
|
||||
if ("and") //(1X 2X -- (1X && 2X))
|
||||
if (stack.len < 2)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
if (script_isNumResult(stack[stack.len], stack[stack.len-1]))
|
||||
result = script_clampvalue( stack[stack.len] & stack[stack.len-1] )
|
||||
|
||||
else
|
||||
result = stack[stack.len] && stack[stack.len-1]
|
||||
|
||||
stack[--stack.len] = result
|
||||
|
||||
if ("or") //(1X 2X -- (1X || 2X))
|
||||
if (stack.len < 2)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
if (script_isNumResult(stack[stack.len], stack[stack.len-1]))
|
||||
result = script_clampvalue( stack[stack.len] | stack[stack.len-1] )
|
||||
|
||||
else
|
||||
result = stack[stack.len] || stack[stack.len-1]
|
||||
|
||||
stack[--stack.len] = result
|
||||
|
||||
if ("not","!") //(1X -- (!1X))
|
||||
if (!stack.len)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
if (isnum(stack[stack.len]))
|
||||
stack[stack.len] = ~stack[stack.len]
|
||||
|
||||
else
|
||||
stack[stack.len] = !stack[stack.len]
|
||||
|
||||
if ("xor","eor") //(1X 2X -- (1X ^ 2X))
|
||||
if (stack.len < 2)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
if (script_isNumResult(stack[stack.len], stack[stack.len-1]))
|
||||
result = stack[stack.len-1] ^ stack[stack.len]
|
||||
stack[--stack.len] = result
|
||||
|
||||
else
|
||||
return ERR_UNDEFINED
|
||||
|
||||
if ("dup")
|
||||
if (stack.len)
|
||||
stack.len++
|
||||
stack[stack.len] = stack[stack.len-1]
|
||||
|
||||
if ("'")
|
||||
var/newString
|
||||
while (command_stream.len)
|
||||
if (command_stream[1] == "\'" || command_stream[1] == "'")
|
||||
command_stream.Cut(1,2)
|
||||
break
|
||||
else if (dd_hassuffix(command_stream[1], "'"))
|
||||
if (newString)
|
||||
newString += " [copytext( command_stream[1],1,length(command_stream[1]-5) )]"
|
||||
|
||||
else
|
||||
newString = "[copytext( command_stream[1],1,length(command_stream[1]-5) )]"
|
||||
|
||||
command_stream.Cut(1,2)
|
||||
break
|
||||
|
||||
else
|
||||
if (newString)
|
||||
newString += " [command_stream[1]]"
|
||||
|
||||
else
|
||||
newString = "[command_stream[1]]"
|
||||
|
||||
command_stream.Cut(1,2)
|
||||
|
||||
if (newString)
|
||||
stack += newString
|
||||
|
||||
if ("d","e","f","x")
|
||||
if (!stack.len)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
. = stack[stack.len]
|
||||
if (!istext(.))
|
||||
return ERR_UNDEFINED
|
||||
|
||||
. = signal_program(1, list("command"=DWAINE_COMMAND_FGET, "path"="[.]"))
|
||||
if (!istype(., /datum/computer))
|
||||
. = 0
|
||||
|
||||
else if (cmptext(current_command, "d"))
|
||||
. = istype(., /datum/computer/folder)
|
||||
|
||||
else if (cmptext(current_command, "x"))
|
||||
. = (istype(., /datum/computer/file/mainframe_program))// || (istype(., /datum/computer/file/record) && .:fields && .:fields[1] == "#!"))
|
||||
|
||||
else if (cmptext(current_command, "f"))
|
||||
. = istype(., /datum/computer/file)
|
||||
|
||||
else
|
||||
. = 1
|
||||
|
||||
|
||||
stack[stack.len] = .
|
||||
continue
|
||||
|
||||
if (":")
|
||||
//todo
|
||||
continue
|
||||
|
||||
if ("value", "to") //Define/Set a variable value.
|
||||
if (!stack.len)
|
||||
return ERR_STACK_UNDER
|
||||
|
||||
if (!command_stream.len)
|
||||
return ERR_UNDEFINED
|
||||
|
||||
var/valueName = lowertext(ckeyEx(command_stream[1]))
|
||||
if (!valueName)
|
||||
return ERR_UNDEFINED
|
||||
|
||||
scriptvars["[valueName]"] = stack[stack.len]
|
||||
stack.len--
|
||||
|
||||
else
|
||||
//boutput(world, "\[[lowertext(ckeyEx(current_command))]] in script vars?")
|
||||
if (lowertext(ckeyEx(current_command)) in scriptvars) //Lowertext(ckeyEx()) is equivalent to a ckey() that preserves underscores
|
||||
//boutput(world, "yes")
|
||||
result = scriptvars["[lowertext( ckeyEx(current_command) )]"]
|
||||
stack.len++
|
||||
stack[stack.len] = result
|
||||
|
||||
else if (istext(current_command))
|
||||
stack += "[current_command]"
|
||||
|
||||
//boutput(world, "STACK: [english_list(stack)]")
|
||||
if (return_bool)
|
||||
if (!stack.len)
|
||||
return EVAL_BOOL_FALSE
|
||||
return (stack[stack.len] ? EVAL_BOOL_TRUE : EVAL_BOOL_FALSE)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
receive_progsignal(var/sendid, var/list/data, var/datum/computer/file/theFile)
|
||||
if (..())
|
||||
return ESIG_GENERIC
|
||||
|
||||
if (!data["command"])
|
||||
return ESIG_GENERIC
|
||||
|
||||
switch (data["command"])
|
||||
if (DWAINE_COMMAND_MSG_TERM)
|
||||
if (piping)
|
||||
pipetemp += data["data"]
|
||||
else
|
||||
return message_user(data["data"], data["render"])
|
||||
|
||||
if (DWAINE_COMMAND_BREAK)
|
||||
if (shscript.len)
|
||||
message_user("Break at line [scriptline+1]")
|
||||
shscript.len = 0
|
||||
scriptline = 0
|
||||
script_iteration = 1
|
||||
return
|
||||
|
||||
|
||||
if (DWAINE_COMMAND_RECVFILE)
|
||||
//save to current dir.
|
||||
var/current_path = read_user_field("curpath")
|
||||
if (!current_path)
|
||||
return ESIG_GENERIC
|
||||
|
||||
if (!istype(theFile))
|
||||
return ESIG_NOFILE
|
||||
|
||||
return signal_program(1, list("command"=DWAINE_COMMAND_FWRITE, "path"=current_path,"replace"=1,"mkdir"=0), theFile)
|
||||
|
||||
return
|
||||
|
||||
message_user(var/msg, var/render=null)
|
||||
if (!useracc)
|
||||
return ESIG_NOTARGET
|
||||
|
||||
if (suppress_out)
|
||||
|
||||
if (dd_hassuffix(msg, "|n"))
|
||||
msg = copytext(msg, 1, -2)
|
||||
|
||||
previous_pipeout += dd_replacetext(msg, "|n", " ")
|
||||
|
||||
return ESIG_SUCCESS
|
||||
|
||||
previous_pipeout += msg
|
||||
if (render)
|
||||
return signal_program(parent_task.progid, list("command"=DWAINE_COMMAND_MSG_TERM, "data" = msg, "term" = useracc.user_id, "render" = render) )
|
||||
else
|
||||
return signal_program(parent_task.progid, list("command"=DWAINE_COMMAND_MSG_TERM, "data" = msg, "term" = useracc.user_id) )
|
||||
|
||||
|
||||
#undef SCRIPT_IF_TRUE
|
||||
#undef SCRIPT_IN_LOOP
|
||||
#undef MAX_SCRIPT_ITERATIONS
|
||||
#undef MAX_STACK_DEPTH
|
||||
#undef ERR_STACK_OVER
|
||||
#undef ERR_STACK_UNDER
|
||||
#undef ERR_UNDEFINED
|
||||
@@ -0,0 +1,257 @@
|
||||
//CONTENTS
|
||||
//Mainframe 2 memory core
|
||||
//Mainframe 2 master tape -- TODO
|
||||
//Mainframe 2 boot tape
|
||||
//Mainframe 2 artifact research tape.
|
||||
//Guardbot configuration tape.
|
||||
//Boot kit box
|
||||
|
||||
|
||||
/*
|
||||
* Mainframe 2 starting memory
|
||||
*/
|
||||
/obj/item/disk/data/memcard/main2
|
||||
file_amount = 4096
|
||||
|
||||
New()
|
||||
..()
|
||||
var/datum/computer/folder/newfolder = new /datum/computer/folder( )
|
||||
newfolder.name = "sys"
|
||||
newfolder.metadata["permission"] = COMP_HIDDEN
|
||||
src.root.add_file( newfolder )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/os/kernel(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/shell(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/login(src) )
|
||||
|
||||
var/datum/computer/folder/subfolder = new /datum/computer/folder
|
||||
subfolder.name = "drvr" //Driver prototypes.
|
||||
newfolder.add_file( subfolder )
|
||||
//subfolder.add_file ( new FILEPATH GOES HERE )
|
||||
subfolder.add_file( new /datum/computer/file/mainframe_program/driver/mountable/databank(src) )
|
||||
subfolder.add_file( new /datum/computer/file/mainframe_program/driver/mountable/printer(src) )
|
||||
subfolder.add_file( new /datum/computer/file/mainframe_program/driver/nuke(src) )
|
||||
subfolder.add_file( new /datum/computer/file/mainframe_program/driver/mountable/guard_dock(src) )
|
||||
subfolder.add_file( new /datum/computer/file/mainframe_program/driver/mountable/radio(src) )
|
||||
subfolder.add_file( new /datum/computer/file/mainframe_program/driver/test_apparatus(src) )
|
||||
subfolder.add_file( new /datum/computer/file/mainframe_program/driver/mountable/service_terminal(src) )
|
||||
subfolder.add_file( new /datum/computer/file/mainframe_program/driver/mountable/user_terminal(src) )
|
||||
subfolder.add_file( new /datum/computer/file/mainframe_program/driver/telepad(src) )
|
||||
subfolder.add_file( new /datum/computer/file/mainframe_program/driver/mountable/comm_dish(src) )
|
||||
subfolder.add_file( new /datum/computer/file/mainframe_program/driver/artifact_console(src) )
|
||||
//subfolder.add_file( new /datum/computer/file/mainframe_program/driver/mountable/logreader(src) )
|
||||
subfolder.add_file( new /datum/computer/file/mainframe_program/driver/apc(src) )
|
||||
|
||||
subfolder = new /datum/computer/folder
|
||||
subfolder.name = "srv"
|
||||
newfolder.add_file( subfolder )
|
||||
subfolder.add_file( new /datum/computer/file/mainframe_program/srv/email(src) )
|
||||
subfolder.add_file( new /datum/computer/file/mainframe_program/srv/print(src) )
|
||||
//subfolder.add_file( new /datum/computer/file/mainframe_program/srv/accesslog(src) )
|
||||
subfolder.add_file( new /datum/computer/file/mainframe_program/srv/telecontrol(src) )
|
||||
|
||||
newfolder = new /datum/computer/folder
|
||||
newfolder.name = "bin" //Applications available to all users.
|
||||
newfolder.metadata["permission"] = COMP_ROWNER|COMP_RGROUP|COMP_ROTHER
|
||||
src.root.add_file( newfolder )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/utility/cd(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/utility/ls(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/utility/rm(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/utility/cat(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/utility/mkdir(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/utility/ln(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/utility/chmod(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/utility/chown(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/utility/su(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/utility/cp(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/utility/mv(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/utility/mount(src) )
|
||||
//newfolder.add_file( new /datum/computer/file/mainframe_program/utility/grep(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/utility/scnt(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/utility/getopt(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/utility/date(src) )
|
||||
newfolder.add_file( new /datum/computer/file/mainframe_program/utility/tar(src) )
|
||||
|
||||
newfolder = new /datum/computer/folder
|
||||
newfolder.name = "var"
|
||||
newfolder.metadata["permission"] = COMP_ROWNER|COMP_RGROUP|COMP_ROTHER
|
||||
src.root.add_file( newfolder )
|
||||
|
||||
newfolder = new /datum/computer/folder
|
||||
newfolder.name = "tmp"
|
||||
newfolder.metadata["permission"] = COMP_ALLACC &~(COMP_DOTHER|COMP_DGROUP)
|
||||
src.root.add_file( newfolder )
|
||||
/*
|
||||
subfolder = new /datum/computer/folder
|
||||
subfolder.name = "log"
|
||||
subfolder.metadata["permission"] = COMP_ROWNER|COMP_RGROUP
|
||||
newfolder.add_file( subfolder )
|
||||
*/
|
||||
newfolder = new /datum/computer/folder
|
||||
newfolder.name = "etc"
|
||||
newfolder.metadata["permission"] = COMP_ROWNER|COMP_RGROUP|COMP_ROTHER
|
||||
src.root.add_file( newfolder )
|
||||
|
||||
subfolder = new /datum/computer/folder
|
||||
subfolder.name = "mail"
|
||||
newfolder.add_file( subfolder )
|
||||
|
||||
var/datum/computer/file/record/groupRec = new /datum/computer/file/record( )
|
||||
groupRec.name = "groups"
|
||||
subfolder.add_file( groupRec )
|
||||
|
||||
var/list/randomMails = get_random_email_list()
|
||||
var/typeCount = 5
|
||||
while (typeCount-- > 0 && randomMails.len)
|
||||
var/mailName = pick(randomMails)
|
||||
var/datum/computer/file/record/mailfile = new /datum/computer/file/record/random_email(mailName)
|
||||
subfolder.add_file(mailfile)
|
||||
randomMails -= mailName
|
||||
/* var/list/randomMailTypes = typesof(/datum/computer/file/record/random_email) - /datum/computer/file/record/random_email
|
||||
var/typeCount = 5
|
||||
while (typeCount-- > 0 && randomMailTypes.len)
|
||||
var/mailType = pick(randomMailTypes)
|
||||
var/datum/computer/file/record/mailfile = new mailType
|
||||
subfolder.add_file( mailfile )
|
||||
|
||||
randomMailTypes -= mailType*/
|
||||
|
||||
newfolder = new /datum/computer/folder
|
||||
newfolder.name = "mnt"
|
||||
newfolder.metadata["permission"] = COMP_ROWNER|COMP_RGROUP|COMP_ROTHER
|
||||
src.root.add_file( newfolder )
|
||||
|
||||
newfolder = new /datum/computer/folder
|
||||
newfolder.name = "conf"
|
||||
newfolder.metadata["permission"] = COMP_ROWNER|COMP_RGROUP|COMP_ROTHER
|
||||
src.root.add_file( newfolder )
|
||||
|
||||
var/datum/computer/file/record/testR = new
|
||||
testR.name = "motd"
|
||||
testR.fields += "Welcome to DWAINE System VI!"
|
||||
testR.fields += pick("Better than System V ever was.","GLUEEEE GLUEEEE GLUEEEEE","Only YOU can prevent lp0 fires!","Please try not to kill yourselves today.", "Please don't set the lab facilities on fire.")
|
||||
newfolder.add_file( testR )
|
||||
|
||||
newfolder.add_file( new /datum/computer/file/record/dwaine_help(src) )
|
||||
|
||||
return
|
||||
|
||||
/obj/item/disk/data/tape/master
|
||||
name = "ThinkTape-'Master Tape'"
|
||||
//Not sure what all to put here yet.
|
||||
|
||||
New()
|
||||
..()
|
||||
//First off, buddy stuff.
|
||||
src.root.add_file( new /datum/computer/file/guardbot_task/security(src) )
|
||||
src.root.add_file( new /datum/computer/file/guardbot_task/security/purge(src) )
|
||||
src.root.add_file( new /datum/computer/file/guardbot_task/bodyguard(src) )
|
||||
src.root.add_file( new /datum/computer/file/guardbot_task/security/area_guard(src) )
|
||||
src.root.add_file( new /datum/computer/file/guardbot_task/bodyguard/heckle(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/guardbot_interface(src))
|
||||
src.root.add_file( new /datum/computer/file/record/pr6_readme(src))
|
||||
src.root.add_file( new /datum/computer/file/record/patrol_script(src))
|
||||
src.root.add_file( new /datum/computer/file/record/bodyguard_script(src))
|
||||
src.root.add_file( new /datum/computer/file/record/roomguard_script(src))
|
||||
src.root.add_file( new /datum/computer/file/record/bodyguard_conf(src))
|
||||
|
||||
//Nuke interface, because sometimes the nuke is alround.
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/nuke_interface(src) )
|
||||
//src.root.add_file( new /datum/computer/file/mainframe_program/srv/telecontrol(src) )
|
||||
|
||||
for (var/datum/computer/file/F in src.root.contents)
|
||||
F.metadata["permission"] = COMP_ROWNER|COMP_RGROUP|COMP_ROTHER
|
||||
|
||||
readonly
|
||||
desc = "A reel of magnetic data tape. The casing has been modified so as to prevent write access."
|
||||
icon_state = "r_tape"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.read_only = 1
|
||||
|
||||
/obj/item/disk/data/tape/boot2
|
||||
name = "ThinkTape-'OS Backup'"
|
||||
desc = "A reel of magnetic data tape containing operating software. The casing has been modified so as to prevent write access."
|
||||
icon_state = "r_tape"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/os/kernel(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/shell(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/login(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/driver/mountable/databank(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/driver/mountable/printer(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/driver/nuke(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/driver/mountable/guard_dock(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/driver/mountable/radio(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/driver/test_apparatus(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/driver/mountable/service_terminal(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/driver/mountable/user_terminal(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/driver/telepad(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/driver/mountable/comm_dish(src) )
|
||||
//src.root.add_file( new /datum/computer/file/mainframe_program/driver/mountable/logreader(src) )
|
||||
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/utility/cd(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/utility/ls(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/utility/rm(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/utility/cat(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/utility/mkdir(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/utility/ln(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/utility/chmod(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/utility/chown(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/utility/su(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/utility/cp(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/utility/mv(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/utility/mount(src) )
|
||||
//src.root.add_file( new /datum/computer/file/mainframe_program/utility/grep(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/utility/scnt(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/utility/getopt(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/utility/date(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/utility/tar(src) )
|
||||
//src.root.add_file( new /datum/computer/file/mainframe_program/srv/accesslog(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/srv/telecontrol(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/srv/email(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/srv/print(src) )
|
||||
src.read_only = 1
|
||||
|
||||
/obj/item/disk/data/tape/test
|
||||
name = "ThinkTape-'Test'"
|
||||
desc = "A reel of magnetic data tape containing various test files."
|
||||
|
||||
New()
|
||||
..()
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/shell(src) )
|
||||
src.root.add_file( new /datum/computer/file/document(src) )
|
||||
src.root.add_file( new /datum/computer/file/record/c3help(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/nuke_interface(src) )
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/test_interface(src) )
|
||||
|
||||
/obj/item/disk/data/tape/guardbot_tools
|
||||
name = "ThinkTape-'PR-6S Config'"
|
||||
desc = "A reel of magnetic data tape containing configuration and support files for PR-6S Guardbuddies."
|
||||
|
||||
New()
|
||||
..()
|
||||
src.root.add_file( new /datum/computer/file/guardbot_task/security(src) )
|
||||
src.root.add_file( new /datum/computer/file/guardbot_task/security/purge(src) )
|
||||
src.root.add_file( new /datum/computer/file/guardbot_task/bodyguard(src) )
|
||||
src.root.add_file( new /datum/computer/file/guardbot_task/security/area_guard(src) )
|
||||
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/guardbot_interface(src))
|
||||
src.root.add_file( new /datum/computer/file/record/pr6_readme(src))
|
||||
src.root.add_file( new /datum/computer/file/record/patrol_script(src))
|
||||
src.root.add_file( new /datum/computer/file/record/bodyguard_script(src))
|
||||
src.root.add_file( new /datum/computer/file/record/bodyguard_conf(src))
|
||||
for (var/datum/computer/file/F in src.root.contents)
|
||||
F.metadata["permission"] = COMP_ROWNER|COMP_RGROUP|COMP_ROTHER
|
||||
|
||||
/obj/item/disk/data/tape/artifact_research
|
||||
name = "ThinkTape-'Artifact Research'"
|
||||
desc = "A reel of magnetic data tape containing modern research software."
|
||||
|
||||
New()
|
||||
..()
|
||||
src.root.add_file( new /datum/computer/file/mainframe_program/test_interface(src) )
|
||||
//src.root.add_file( new /datum/computer/file/mainframe_program/artifact_research(src) )
|
||||
for (var/datum/computer/file/F in src.root.contents)
|
||||
F.metadata["permission"] = COMP_ROWNER|COMP_RGROUP|COMP_ROTHER
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,712 @@
|
||||
|
||||
|
||||
|
||||
#define MENU_MAIN 0 //Byond. Enums. Lacks them. Etc
|
||||
#define MENU_INDEX 1
|
||||
#define MENU_IN_RECORD 2
|
||||
#define MENU_FIELD_INPUT 3
|
||||
#define MENU_SEARCH_INPUT 4
|
||||
#define MENU_VIRUS_INDEX 5
|
||||
#define MENU_VIRUS_RECORD 6
|
||||
|
||||
#define FIELDNUM_NAME 1
|
||||
#define FIELDNUM_SEX 2
|
||||
#define FIELDNUM_AGE 3
|
||||
#define FIELDNUM_PRINT 4
|
||||
#define FIELDNUM_DNA 5
|
||||
#define FIELDNUM_PSTAT 6
|
||||
#define FIELDNUM_MSTAT 7
|
||||
#define FIELDNUM_BLOODTYPE 8
|
||||
#define FIELDNUM_MINDIS 9
|
||||
#define FIELDNUM_MINDET 10
|
||||
#define FIELDNUM_MAJDIS 11
|
||||
#define FIELDNUM_MAJDET 12
|
||||
#define FIELDNUM_DISEASE 13
|
||||
#define FIELDNUM_DISDET 14
|
||||
|
||||
#define FIELDNUM_DELETE "d"
|
||||
#define FIELDNUM_NEWREC 99
|
||||
|
||||
/datum/computer/file/terminal_program/medical_records
|
||||
name = "MedTrak"
|
||||
size = 12
|
||||
req_access = list(access_medical)
|
||||
var/tmp/menu = MENU_MAIN
|
||||
var/tmp/field_input = 0
|
||||
var/tmp/authenticated = null //Are we currently logged in?
|
||||
var/datum/computer/file/user_data/account = null
|
||||
var/list/record_list = list() //List of records, for jumping direclty to a specific ID
|
||||
var/datum/data/record/active_general = null //General record
|
||||
var/datum/data/record/active_medical = null //Medical record
|
||||
var/log_string = null //Log usage of record system, can be dumped to a text file.
|
||||
|
||||
var/setup_acc_filepath = "/logs/sysusr"//Where do we look for login data?
|
||||
var/setup_logdump_name = "medlog" //What name do we give our logdump textfile?
|
||||
|
||||
initialize()
|
||||
/*
|
||||
var/title_art = {"<pre>
|
||||
__ __ _ _____ _
|
||||
| \\/ |___ __| |___|_ _|_ _ __ _| |__
|
||||
| |\\/| / -_) _` |___| | | | '_/ _` | / /
|
||||
|_| |_\\___\\__,_| |_| |_| \\__,_|_\\_\\</pre>"}
|
||||
*/
|
||||
src.authenticated = null
|
||||
src.record_list = data_core.general.Copy() //Initial setting of record list.
|
||||
src.master.temp = null
|
||||
src.menu = MENU_MAIN
|
||||
src.field_input = 0
|
||||
//src.print_text(" [title_art]")
|
||||
if(!src.find_access_file()) //Find the account information, as it's essentially a ~digital ID card~
|
||||
src.print_text("<b>Error:</b> Cannot locate user file. Quitting...")
|
||||
src.master.unload_program(src) //Oh no, couldn't find the file.
|
||||
return
|
||||
|
||||
if(!src.check_access(src.account.access))
|
||||
src.print_text("User [src.account.registered] does not have needed access credentials.<br>Quitting...")
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
|
||||
src.authenticated = src.account.registered
|
||||
src.log_string += "<br><b>LOGIN:</b> [src.authenticated]"
|
||||
|
||||
src.print_text(mainmenu_text())
|
||||
return
|
||||
|
||||
|
||||
input_text(text)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/list/command_list = parse_string(text)
|
||||
var/command = command_list[1]
|
||||
command_list -= command_list[1]
|
||||
|
||||
switch(menu)
|
||||
if (MENU_MAIN)
|
||||
switch (command)
|
||||
if ("0") //Exit program
|
||||
src.print_text("Quitting...")
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
|
||||
if ("1") //View records
|
||||
src.record_list = data_core.general
|
||||
|
||||
src.menu = MENU_INDEX
|
||||
src.print_index()
|
||||
|
||||
if ("2") //Search records
|
||||
src.print_text("Please enter target name, ID, DNA, or fingerprint.")
|
||||
|
||||
src.menu = MENU_SEARCH_INPUT
|
||||
return
|
||||
|
||||
if ("3") //Viral records.
|
||||
|
||||
src.master.temp = null
|
||||
src.print_text(virusmenu_text())
|
||||
|
||||
src.menu = MENU_VIRUS_INDEX
|
||||
return
|
||||
|
||||
if (MENU_INDEX)
|
||||
var/index_number = round( max( text2num(command), 0) )
|
||||
if (index_number == 0)
|
||||
src.menu = MENU_MAIN
|
||||
src.master.temp = null
|
||||
src.print_text(mainmenu_text())
|
||||
return
|
||||
|
||||
if (!istype(record_list) || index_number > record_list.len)
|
||||
src.print_text("Invalid record.")
|
||||
return
|
||||
|
||||
var/datum/data/record/check = src.record_list[index_number]
|
||||
if(!check || !istype(check))
|
||||
src.print_text("<b>Error:</b> Record Data Invalid.")
|
||||
return
|
||||
|
||||
src.active_general = check
|
||||
src.active_medical = null
|
||||
if (data_core.general.Find(check))
|
||||
for (var/datum/data/record/E in data_core.medical)
|
||||
if ((E.fields["name"] == src.active_general.fields["name"] || E.fields["id"] == src.active_general.fields["id"]))
|
||||
src.active_medical = E
|
||||
break
|
||||
|
||||
src.log_string += "<br>Log loaded: [src.active_general.fields["id"]]"
|
||||
|
||||
if (src.print_active_record())
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
if (MENU_IN_RECORD)
|
||||
switch(lowertext(command))
|
||||
if ("r")
|
||||
src.print_active_record()
|
||||
return
|
||||
if ("d")
|
||||
src.print_text("Are you sure? (Y/N)")
|
||||
src.field_input = FIELDNUM_DELETE
|
||||
src.menu = MENU_FIELD_INPUT
|
||||
return
|
||||
if ("p")
|
||||
var/obj/item/peripheral/printcard = find_peripheral("LAR_PRINTER")
|
||||
if(!printcard)
|
||||
src.print_text("<b>Error:</b> No printer detected.")
|
||||
return
|
||||
|
||||
//Okay, let's put together something to print.
|
||||
var/info = "<center><B>Medical Record</B></center><br>"
|
||||
if (istype(src.active_general, /datum/data/record) && data_core.general.Find(src.active_general))
|
||||
info += {"
|
||||
Name: [src.active_general.fields["name"]] ID: [src.active_general.fields["id"]]
|
||||
<br><br>Sex: [src.active_general.fields["sex"]]
|
||||
<br><br>Age: [src.active_general.fields["age"]]
|
||||
<br><br>Rank: [src.active_general.fields["rank"]]
|
||||
<br><br>Fingerprint: [src.active_general.fields["fingerprint"]]
|
||||
<br><br>DNA: [src.active_general.fields["dna"]]
|
||||
<br><br>Physical Status: [src.active_general.fields["p_stat"]]
|
||||
<br><br>Mental Status: [src.active_general.fields["m_stat"]]"}
|
||||
else
|
||||
info += "<b>General Record Lost!</b><br>"
|
||||
if ((istype(src.active_medical, /datum/data/record) && data_core.medical.Find(src.active_medical)))
|
||||
info += {"
|
||||
<br><br><center><b>Medical Data</b></center><br>
|
||||
<br><br>Current Health: [src.active_medical.fields["h_imp"]]
|
||||
<br>Blood Type: [src.active_medical.fields["bioHolder.bloodType"]]
|
||||
<br><br>Minor Disabilities: [src.active_medical.fields["mi_dis"]]
|
||||
<br><br>Details: [src.active_medical.fields["mi_dis_d"]]
|
||||
<br><br><br>Major Disabilities: [src.active_medical.fields["ma_dis"]]
|
||||
<br><br>Details: [src.active_medical.fields["ma_dis_d"]]
|
||||
<br><br><br>Current Diseases: [src.active_medical.fields["cdi"]] (per disease info placed in log/comment section)
|
||||
<br>Details: [src.active_medical.fields["cdi_d"]]<br><br><br>
|
||||
<br>Traits: [src.active_medical.fields["traits"]]<br><br><br>
|
||||
Important Notes:<br>
|
||||
<br> [src.active_medical.fields["notes"]]<br>"}
|
||||
|
||||
else
|
||||
info += "<br><center><b>Medical Record Lost!</b></center><br>"
|
||||
|
||||
var/datum/signal/signal = get_free_signal()
|
||||
signal.data["data"] = info
|
||||
signal.data["title"] = "Medical Record"
|
||||
src.peripheral_command("print",signal, "\ref[printcard]")
|
||||
|
||||
src.print_text("Printing...")
|
||||
return
|
||||
|
||||
var/field_number = round( max( text2num(command), 0) )
|
||||
if (field_number == 0)
|
||||
src.menu = MENU_INDEX
|
||||
src.print_index()
|
||||
return
|
||||
|
||||
src.field_input = field_number
|
||||
switch(field_number)
|
||||
if (FIELDNUM_SEX)
|
||||
src.print_text("Please select: (1) Female (2) Male (3) Other (0) Back")
|
||||
src.menu = MENU_FIELD_INPUT
|
||||
return
|
||||
|
||||
if (FIELDNUM_BLOODTYPE)
|
||||
src.print_text("Please select: (1) A+ (2) A- (3) B+ (4) B-<br> (5) AB+ (6) AB- (7) O+ (8) O- (0) Back")
|
||||
src.menu = MENU_FIELD_INPUT
|
||||
return
|
||||
|
||||
else
|
||||
src.print_text("Please enter new value.")
|
||||
src.menu = MENU_FIELD_INPUT
|
||||
return
|
||||
|
||||
if (MENU_FIELD_INPUT)
|
||||
if (!src.active_general)
|
||||
src.print_text("<b>Error:</b> Record invalid.")
|
||||
src.menu = MENU_INDEX
|
||||
return
|
||||
|
||||
var/inputText = strip_html(text)
|
||||
switch (field_input)
|
||||
if (FIELDNUM_NAME)
|
||||
if (ckey(inputText))
|
||||
src.active_general.fields["name"] = copytext(inputText, 1, 26)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_SEX)
|
||||
switch (round( max( text2num(command), 0) ))
|
||||
if (1)
|
||||
src.active_general.fields["sex"] = "Female"
|
||||
if (2)
|
||||
src.active_general.fields["sex"] = "Male"
|
||||
if (3)
|
||||
src.active_general.fields["sex"] = "Other"
|
||||
if (0)
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_AGE)
|
||||
var/newAge = round( min( text2num(command), 99) )
|
||||
if (newAge < 1)
|
||||
src.print_text("Invalid age value. Please re-enter.")
|
||||
return
|
||||
|
||||
src.active_general.fields["age"] = newAge
|
||||
return
|
||||
|
||||
if (FIELDNUM_PSTAT)
|
||||
if (ckey(inputText))
|
||||
src.active_general.fields["p_stat"] = copytext(inputText, 1, 33)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_MSTAT)
|
||||
if (ckey(inputText))
|
||||
src.active_general.fields["m_stat"] = copytext(inputText, 1, 33)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_PRINT)
|
||||
if (ckey(inputText))
|
||||
src.active_general.fields["fingerprint"] = copytext(inputText, 1, 33)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_DNA)
|
||||
if (ckey(inputText))
|
||||
src.active_general.fields["dna"] = copytext(inputText, 1, 40)
|
||||
else
|
||||
return
|
||||
|
||||
|
||||
if (FIELDNUM_BLOODTYPE)
|
||||
if (!src.active_medical)
|
||||
src.print_text("No medical record loaded!")
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
switch (round( max( text2num(command), 0) ))
|
||||
if (1)
|
||||
src.active_medical.fields["bioHolder.bloodType"] = "A+"
|
||||
if (2)
|
||||
src.active_medical.fields["bioHolder.bloodType"] = "A-"
|
||||
if (3)
|
||||
src.active_medical.fields["bioHolder.bloodType"] = "B+"
|
||||
if (4)
|
||||
src.active_medical.fields["bioHolder.bloodType"] = "B-"
|
||||
if (5)
|
||||
src.active_medical.fields["bioHolder.bloodType"] = "AB+"
|
||||
if (6)
|
||||
src.active_medical.fields["bioHolder.bloodType"] = "AB-"
|
||||
if (7)
|
||||
src.active_medical.fields["bioHolder.bloodType"] = "O+"
|
||||
if (8)
|
||||
src.active_medical.fields["bioHolder.bloodType"] = "O-"
|
||||
if (9)
|
||||
src.active_medical.fields["bioHolder.bloodType"] = "Zesty Ranch"
|
||||
if (0)
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_MINDIS)
|
||||
if (!src.active_medical)
|
||||
src.print_text("No medical record loaded!")
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
if (ckey(inputText))
|
||||
src.active_medical.fields["mi_dis"] = copytext(inputText, 1, MAX_MESSAGE_LEN)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_MINDET)
|
||||
if (!src.active_medical)
|
||||
src.print_text("No medical record loaded!")
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
if (ckey(inputText))
|
||||
src.active_medical.fields["mi_dis_d"] = copytext(inputText, 1, MAX_MESSAGE_LEN)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_MAJDIS)
|
||||
if (!src.active_medical)
|
||||
src.print_text("No medical record loaded!")
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
if (ckey(inputText))
|
||||
src.active_medical.fields["ma_dis"] = copytext(inputText, 1, MAX_MESSAGE_LEN)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_MAJDET)
|
||||
if (!src.active_medical)
|
||||
src.print_text("No medical record loaded!")
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
if (ckey(inputText))
|
||||
src.active_medical.fields["ma_dis_d"] = copytext(inputText, 1, MAX_MESSAGE_LEN)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_DISEASE)
|
||||
if (!src.active_medical)
|
||||
src.print_text("No medical record loaded!")
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
if (ckey(inputText))
|
||||
src.active_medical.fields["cdi"] = copytext(inputText, 1, MAX_MESSAGE_LEN)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_DISDET)
|
||||
if (!src.active_medical)
|
||||
src.print_text("No medical record loaded!")
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
if (ckey(inputText))
|
||||
src.active_medical.fields["cdi_d"] = copytext(inputText, 1, MAX_MESSAGE_LEN)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_DELETE)
|
||||
switch (ckey(inputText))
|
||||
if ("y")
|
||||
if (src.active_medical)
|
||||
src.log_string += "<br>M-Record [src.active_medical.fields["id"]] deleted."
|
||||
data_core.medical -= src.active_medical
|
||||
qdel(src.active_medical)
|
||||
src.print_active_record()
|
||||
src.menu = MENU_IN_RECORD
|
||||
|
||||
else if (src.active_general)
|
||||
data_core.general -= src.active_general
|
||||
|
||||
src.log_string += "<br>Record [src.active_general.fields["id"]] deleted."
|
||||
qdel(src.active_general)
|
||||
src.menu = MENU_INDEX
|
||||
src.print_index()
|
||||
|
||||
if ("n")
|
||||
src.menu = MENU_IN_RECORD
|
||||
src.print_text("Record preserved.")
|
||||
|
||||
return
|
||||
|
||||
|
||||
if (FIELDNUM_NEWREC)
|
||||
if (src.active_medical)
|
||||
return
|
||||
|
||||
var/datum/data/record/R = new /datum/data/record( )
|
||||
R.fields["name"] = src.active_general.fields["name"]
|
||||
R.fields["id"] = src.active_general.fields["id"]
|
||||
R.name = "Medical Record #[R.fields["id"]]"
|
||||
R.fields["bioHolder.bloodType"] = "Unknown"
|
||||
R.fields["mi_dis"] = "None"
|
||||
R.fields["mi_dis_d"] = "No minor disabilities have been declared."
|
||||
R.fields["ma_dis"] = "None"
|
||||
R.fields["ma_dis_d"] = "No major disabilities have been diagnosed."
|
||||
R.fields["alg"] = "None"
|
||||
R.fields["alg_d"] = "No allergies have been detected in this patient."
|
||||
R.fields["cdi"] = "None"
|
||||
R.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
|
||||
R.fields["notes"] = "No notes."
|
||||
R.fields["h_imp"] = "No health implant detected."
|
||||
R.fields["traits"] = "No known traits."
|
||||
data_core.medical += R
|
||||
src.active_medical = R
|
||||
|
||||
src.log_string += "<br>New medical record created."
|
||||
src.print_active_record()
|
||||
return
|
||||
src.print_text("Field updated.")
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
if (MENU_SEARCH_INPUT)
|
||||
var/searchText = ckey(strip_html(text))
|
||||
if (!searchText)
|
||||
return
|
||||
|
||||
var/datum/data/record/result = null
|
||||
for(var/datum/data/record/R in data_core.general)
|
||||
if((ckey(R.fields["name"]) == searchText) || (ckey(R.fields["dna"]) == searchText) || (ckey(R.fields["id"]) == searchText) || (ckey(R.fields["fingerprint"]) == searchText))
|
||||
result = R
|
||||
break
|
||||
|
||||
if(!result)
|
||||
src.print_text("No results found.")
|
||||
src.menu = MENU_MAIN
|
||||
return
|
||||
|
||||
src.active_general = result
|
||||
src.active_medical = null //Time to find the accompanying medical record, if it even exists.
|
||||
for (var/datum/data/record/E in data_core.medical)
|
||||
if ((E.fields["name"] == src.active_general.fields["name"] || E.fields["id"] == src.active_general.fields["id"]))
|
||||
src.active_medical = E
|
||||
break
|
||||
|
||||
src.menu = MENU_IN_RECORD
|
||||
src.print_active_record()
|
||||
return
|
||||
|
||||
if (MENU_VIRUS_INDEX)
|
||||
var/entrydat = null
|
||||
switch (copytext(text, 1,2))
|
||||
if ("0")
|
||||
src.menu = MENU_MAIN
|
||||
src.master.temp = null
|
||||
src.print_text(virusmenu_text())
|
||||
return
|
||||
if ("1")
|
||||
entrydat = {"<b>Name:</b> GBS
|
||||
<br><b>Number of stages:</b> 5
|
||||
<br><b>Spread:</b> Airborne Transmission
|
||||
<br><b>Possible Cure:</b> Spaceacillin
|
||||
<br><b>Affected Species:</b> Human
|
||||
<br>
|
||||
<br><b>Notes:</b> If left untreated death will occur.
|
||||
<br>
|
||||
<br><b>Severity:</b> Major"}
|
||||
if ("2")
|
||||
entrydat = {"<b>Name:</b> Common Cold
|
||||
<br><b>Number of stages:</b> 3
|
||||
<br><b>Spread:</b> Airborne Transmission
|
||||
<br><b>Possible Cure:</b> Rest
|
||||
<br><b>Affected Species:</b> Human
|
||||
<br>
|
||||
<br><b>Notes:</b> If left untreated the subject will contract the flu.
|
||||
<br>
|
||||
<br><b>Severity:</b> Minor"}
|
||||
if ("3")
|
||||
entrydat = {"<b>Name:</b> The Flu
|
||||
<br><b>Number of stages:</b> 3
|
||||
<br><b>Spread:</b> Airborne Transmission
|
||||
<br><b>Possible Cure:</b> Rest
|
||||
<br><b>Affected Species:</b> Human
|
||||
<br>
|
||||
<br><b>Notes:</b> If left untreated the subject will feel quite unwell.
|
||||
<br>
|
||||
<br><b>Severity:</b> Medium"}
|
||||
|
||||
if ("4")
|
||||
entrydat = {"<b>Name:</b> Jungle Fever
|
||||
<br><b>Number of stages:</b> 1
|
||||
<br><b>Spread:</b> Airborne Transmission
|
||||
<br><b>Possible Cure:</b> None
|
||||
<br><b>Affected Species:</b> Monkey
|
||||
<br>
|
||||
<br><b>Notes:</b> Monkies with this disease will bite humans, causing humans to spontaneously to mutate into a monkey.
|
||||
<br>
|
||||
<br><b>Severity:</b> Medium"}
|
||||
|
||||
if ("5")
|
||||
entrydat = {"<b>Name:</b> Clowning Around
|
||||
<br><b>Number of stages:</b> 4
|
||||
<br><b>Spread:</b> Contact Transmission
|
||||
<br><b>Possible Cure:</b> Spaceacillin
|
||||
<br><b>Affected Species:</b> Human
|
||||
<br>
|
||||
<br><b>Notes:</b> Subjects are affected by rampant honking and a fondness for shenanigans. They may also spontaneously phase through closed airlocks.
|
||||
<br>
|
||||
<br><b>Severity:</b> Laughable"}
|
||||
|
||||
if ("6")
|
||||
entrydat = {"<b>Name:</b> Space Rhinovirus
|
||||
<br><b>Number of stages:</b> 4
|
||||
<br><b>Spread:</b> Airborne Transmission
|
||||
<br><b>Possible Cure:</b> Spaceacillin
|
||||
<br><b>Affected Species:</b> Human
|
||||
<br>
|
||||
<br><b>Notes:</b> This disease transplants the genetic code of the intial vector into new hosts.
|
||||
<br>
|
||||
<br><b>Severity:</b> Medium"}
|
||||
|
||||
if ("7")
|
||||
entrydat = {"<b>Name:</b> Robot Transformation
|
||||
<br><b>Number of stages:</b> 5
|
||||
<br><b>Spread:</b> Infected food
|
||||
<br><b>Possible Cure:</b> Electric shock.
|
||||
<br><b>Affected Species:</b> Human
|
||||
<br>
|
||||
<br><b>Notes:</b> This disease, actually acute nanomachine infection, converts the victim into a cyborg.
|
||||
<br>
|
||||
<br><b>Severity:</b> Major"}
|
||||
|
||||
if ("8")
|
||||
entrydat = {"<b>Name:</b> Teleportitis
|
||||
<br><b>Number of stages:</b> 1
|
||||
<br><b>Spread:</b> Unknown
|
||||
<br><b>Possible Cure:</b> Unknown
|
||||
<br><b>Affected Species:</b> Human
|
||||
<br>
|
||||
<br><b>Notes:</b> Means of transmission are currently unknown,
|
||||
may be related to contents of teleporter emissions. Causes violent shifts
|
||||
in physical position of subject. Keep patients away from active engines.<br>
|
||||
<br><b>Severity:</b> Unknown"}
|
||||
|
||||
if ("9")
|
||||
entrydat = {"<b>Name:</b> Berserker
|
||||
<br><b>Number of stages:</b> 2
|
||||
<br><b>Spread:</b> Contact Transmission
|
||||
<br><b>Possible Cure:</b> Spaceacillin
|
||||
<br><b>Affected Species:</b> Human
|
||||
<br>
|
||||
<br><b>Notes:</b> This disease causes fits of extreme rage and violence in the victim.
|
||||
Due to its ability to spread, it is considered extremely dangerous.
|
||||
Do not attempt to reason with infected persons.<br>
|
||||
<br><b>Severity:</b> Major"}
|
||||
|
||||
else
|
||||
|
||||
return
|
||||
|
||||
src.master.temp = null
|
||||
src.print_text("[entrydat]<br>Enter 0 to return.")
|
||||
src.menu = MENU_VIRUS_RECORD
|
||||
|
||||
if (MENU_VIRUS_RECORD)
|
||||
if (copytext(text, 1,2) == "0")
|
||||
src.master.temp = null
|
||||
src.menu = MENU_MAIN
|
||||
src.print_text(mainmenu_text())
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
|
||||
proc
|
||||
mainmenu_text()
|
||||
var/dat = {"<center>M E D T R A K</center><br>
|
||||
Welcome to Medtrak 5.1<br>
|
||||
<b>Commands:</b>
|
||||
<br>(1) View medical records.
|
||||
<br>(2) Search for a record.
|
||||
<br>(3) View viral database.
|
||||
<br>(0) Quit."}
|
||||
|
||||
return dat
|
||||
|
||||
virusmenu_text()
|
||||
var/dat = {"<b>Known Diseases:</b><br>
|
||||
(01) GBS<br>
|
||||
(02) Common Cold<br>
|
||||
(03) Flu<br>
|
||||
(04) Jungle Fever<br>
|
||||
(05) Clowning Around<br>
|
||||
(06) Space Rhinovirus<br>
|
||||
(07) Robot Transformation<br>
|
||||
(08) Teleportitis<br>
|
||||
(09) Berserker<br>
|
||||
Enter virus number or 0 to return."}
|
||||
|
||||
return dat
|
||||
|
||||
print_active_record()
|
||||
if (!src.active_general)
|
||||
src.print_text("<b>Error:</b> General record data corrupt.")
|
||||
return 0
|
||||
src.master.temp = null
|
||||
|
||||
var/view_string = {"
|
||||
\[01]Name: [src.active_general.fields["name"]] ID: [src.active_general.fields["id"]]
|
||||
<br>\[02]<b>Sex:</b> [src.active_general.fields["sex"]]
|
||||
<br>\[03]<b>Age:</b> [src.active_general.fields["age"]]
|
||||
<br>\[__]<b>Rank:</b> [src.active_general.fields["rank"]]
|
||||
<br>\[04]<b>Fingerprint:</b> [src.active_general.fields["fingerprint"]]
|
||||
<br>\[05]<b>DNA:</b> [src.active_general.fields["dna"]]
|
||||
<br>\[06]Physical Status: [src.active_general.fields["p_stat"]]
|
||||
<br>\[07]Mental Status: [src.active_general.fields["m_stat"]]"}
|
||||
|
||||
if ((istype(src.active_medical, /datum/data/record) && data_core.medical.Find(src.active_medical)))
|
||||
view_string += {"<br><center><b>Medical Data:</b></center>
|
||||
<br>\[__]Current Health: [src.active_medical.fields["h_imp"]]
|
||||
<br>\[08]Blood Type: [src.active_medical.fields["bioHolder.bloodType"]]
|
||||
<br>\[09]Minor Disabilities: [src.active_medical.fields["mi_dis"]]
|
||||
<br>\[10]Details: [src.active_medical.fields["mi_dis_d"]]
|
||||
<br>\[11]<br>Major Disabilities: [src.active_medical.fields["ma_dis"]]
|
||||
<br>\[12]Details: [src.active_medical.fields["ma_dis_d"]]
|
||||
<br>\[13]<br>Current Diseases: [src.active_medical.fields["cdi"]] (per disease info placed in log/comment section)
|
||||
<br>\[14]Details: [src.active_medical.fields["cdi_d"]]
|
||||
<br>\[15]Traits: [src.active_medical.fields["traits"]]
|
||||
<br>Important Notes:
|
||||
<br> [src.active_medical.fields["notes"]]"}
|
||||
else
|
||||
view_string += "<br><br><b>Medical Record Lost!</b>"
|
||||
view_string += "<br>\[99] Create New Medical Record.<br>"
|
||||
|
||||
view_string += "<br>Enter field number to edit a field<br>(R) Redraw (D) Delete (P) Print (0) Return to index."
|
||||
|
||||
src.print_text("<b>Record Data:</b><br>[view_string]")
|
||||
return 1
|
||||
|
||||
print_index()
|
||||
src.master.temp = null
|
||||
var/dat = ""
|
||||
if(!src.record_list || !src.record_list.len)
|
||||
src.print_text("<b>Error:</b> No records found in database.")
|
||||
|
||||
else
|
||||
dat = "Please select a record:"
|
||||
var/leadingZeroCount = length("[src.record_list.len]")
|
||||
for(var/x = 1, x <= src.record_list.len, x++)
|
||||
var/datum/data/record/R = src.record_list[x]
|
||||
if(!R || !istype(R))
|
||||
dat += "<br><b>\[[add_zero("[x]",leadingZeroCount)]]</b><font color=red>ERR: REDACTED</font>"
|
||||
continue
|
||||
|
||||
dat += "<br><b>\[[add_zero("[x]",leadingZeroCount)]]</b>[R.fields["id"]]: [R.fields["name"]]"
|
||||
|
||||
dat += "<br><br>Enter record number, or 0 to return."
|
||||
|
||||
src.print_text(dat)
|
||||
return 1
|
||||
|
||||
find_access_file() //Look for the whimsical account_data file
|
||||
var/datum/computer/folder/accdir = src.holder.root
|
||||
if(src.master.host_program) //Check where the OS is, preferably.
|
||||
accdir = src.master.host_program.holder.root
|
||||
|
||||
var/datum/computer/file/user_data/target = parse_file_directory(setup_acc_filepath, accdir)
|
||||
if(target && istype(target))
|
||||
src.account = target
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
#undef MENU_MAIN
|
||||
#undef MENU_INDEX
|
||||
#undef MENU_IN_RECORD
|
||||
#undef MENU_FIELD_INPUT
|
||||
#undef MENU_SEARCH_INPUT
|
||||
#undef MENU_VIRUS_INDEX
|
||||
#undef MENU_VIRUS_RECORD
|
||||
|
||||
#undef FIELDNUM_NAME
|
||||
#undef FIELDNUM_SEX
|
||||
#undef FIELDNUM_AGE
|
||||
#undef FIELDNUM_PRINT
|
||||
#undef FIELDNUM_DNA
|
||||
#undef FIELDNUM_PSTAT
|
||||
#undef FIELDNUM_MSTAT
|
||||
#undef FIELDNUM_BLOODTYPE
|
||||
#undef FIELDNUM_MINDIS
|
||||
#undef FIELDNUM_MINDET
|
||||
#undef FIELDNUM_MAJDIS
|
||||
#undef FIELDNUM_MAJDET
|
||||
#undef FIELDNUM_DISEASE
|
||||
#undef FIELDNUM_DISDET
|
||||
|
||||
#undef FIELDNUM_DELETE
|
||||
#undef FIELDNUM_NEWREC
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,898 @@
|
||||
|
||||
|
||||
|
||||
#define MENU_MAIN 0 //Byond. Enums. Lacks them. Etc
|
||||
#define MENU_INDEX 1
|
||||
#define MENU_IN_RECORD 2
|
||||
#define MENU_FIELD_INPUT 3
|
||||
#define MENU_SEARCH_INPUT 4
|
||||
#define MENU_SETTINGS 5
|
||||
#define MENU_SELECT_PRINTER 6
|
||||
|
||||
#define FIELDNUM_NAME 1
|
||||
#define FIELDNUM_SEX 2
|
||||
#define FIELDNUM_AGE 3
|
||||
#define FIELDNUM_RANK 4
|
||||
#define FIELDNUM_PRINT 5
|
||||
#define FIELDNUM_CRIMSTAT 6
|
||||
#define FIELDNUM_MINCRIM 7
|
||||
#define FIELDNUM_MINDET 8
|
||||
#define FIELDNUM_MAJCRIM 9
|
||||
#define FIELDNUM_MAJDET 10
|
||||
|
||||
#define FIELDNUM_DELETE "d"
|
||||
#define FIELDNUM_NEWREC 99
|
||||
|
||||
/datum/computer/file/terminal_program/secure_records
|
||||
name = "SecMate"
|
||||
size = 12
|
||||
req_access = list(access_security)
|
||||
var/tmp/menu = MENU_MAIN
|
||||
var/tmp/field_input = 0
|
||||
var/tmp/authenticated = null //Are we currently logged in?
|
||||
var/tmp/datum/computer/file/user_data/account = null
|
||||
var/list/record_list = list() //List of records, for jumping direclty to a specific ID
|
||||
var/datum/data/record/active_general = null //General record
|
||||
var/datum/data/record/active_secure = null //Security record
|
||||
var/log_string = null //Log usage of record system, can be dumped to a text file.
|
||||
var/obj/item/peripheral/network/radio/radiocard = null
|
||||
var/tmp/last_arrest_report = 0 //When did we last report an arrest?
|
||||
|
||||
var/tmp/connected = 0
|
||||
var/tmp/server_netid = null
|
||||
var/tmp/potential_server_netid = null
|
||||
var/tmp/selected_printer = null
|
||||
var/tmp/list/known_printers = list()
|
||||
var/tmp/printer_status = "???"
|
||||
|
||||
var/setup_acc_filepath = "/logs/sysusr"//Where do we look for login data?
|
||||
var/setup_logdump_name = "seclog" //What name do we give our logdump textfile?
|
||||
var/setup_mailgroup = "security" //The PDA mailgroup used when alerting security pdas to an arrest set.
|
||||
var/setup_mail_freq = 1149 //Which frequency do we transmit PDA alerts on?
|
||||
|
||||
initialize() //Forms "SECMATE" ascii art. Oh boy.
|
||||
/*
|
||||
var/title_art = {"<pre> ____________________ _ __________________
|
||||
\\ ___\\ ___\\ ___\\ -./ \\ __ \\ _ _\\ ___\\
|
||||
\\ \\___ \\ __\\\\ \\___\\ \\-./\\ \\ __ \\/\\ \\ \\ __\\
|
||||
\\/\\_____\\_____\\_____\\ \\_\\ \\ \\ \\_\\ \\ \\ \\ \\_____\\
|
||||
\\/_____/_____/_____/_/ \\/_/_/\\/_/\\/_/\\/_____/ </pre>"}
|
||||
*/
|
||||
src.authenticated = null
|
||||
src.record_list = data_core.general.Copy() //Initial setting of record list.
|
||||
src.master.temp = null
|
||||
src.menu = MENU_MAIN
|
||||
src.field_input = 0
|
||||
//src.print_text(" [title_art]")
|
||||
if(!src.find_access_file()) //Find the account information, as it's essentially a ~digital ID card~
|
||||
src.print_text("<b>Error:</b> Cannot locate user file. Quitting...")
|
||||
src.master.unload_program(src) //Oh no, couldn't find the file.
|
||||
return
|
||||
|
||||
src.radiocard = locate() in src.master.peripherals
|
||||
if(!radiocard || !istype(src.radiocard))
|
||||
src.radiocard = null
|
||||
src.print_text("<b>Warning:</b> No radio module detected.")
|
||||
|
||||
if(!src.check_access(src.account.access))
|
||||
src.print_text("User [src.account.registered] does not have needed access credentials.<br>Quitting...")
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
|
||||
src.authenticated = src.account.registered
|
||||
src.log_string += "<br><b>LOGIN:</b> [src.authenticated]"
|
||||
|
||||
src.print_text(mainmenu_text())
|
||||
return
|
||||
|
||||
|
||||
input_text(text)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/list/command_list = parse_string(text)
|
||||
var/command = command_list[1]
|
||||
command_list -= command_list[1]
|
||||
|
||||
switch(menu)
|
||||
if (MENU_MAIN)
|
||||
switch (command)
|
||||
if ("0") //Exit program
|
||||
src.print_text("Quitting...")
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
|
||||
if ("1") //View records
|
||||
src.record_list = data_core.general
|
||||
|
||||
src.menu = MENU_INDEX
|
||||
src.print_index()
|
||||
|
||||
if ("2") //Search records
|
||||
src.print_text("Please enter target name, ID, DNA, or fingerprint.")
|
||||
|
||||
src.menu = MENU_SEARCH_INPUT
|
||||
return
|
||||
|
||||
if ("3")
|
||||
src.print_settings()
|
||||
|
||||
src.menu = MENU_SETTINGS
|
||||
return
|
||||
|
||||
if (MENU_SETTINGS)
|
||||
switch (command)
|
||||
if ("0")
|
||||
src.menu = MENU_MAIN
|
||||
src.master.temp = null
|
||||
src.print_text(mainmenu_text())
|
||||
return
|
||||
|
||||
if ("1")
|
||||
if (src.connected)
|
||||
disconnect_server()
|
||||
src.connected = 0
|
||||
src.master.temp = null
|
||||
src.print_settings()
|
||||
return
|
||||
else
|
||||
if (server_netid)
|
||||
//Attempt to connect to server
|
||||
src.menu = -1
|
||||
connect_printserver(server_netid, 1)
|
||||
if (connected)
|
||||
src.master.temp = null
|
||||
src.print_text("Connection established to \[[server_netid]]!")
|
||||
src.print_settings()
|
||||
src.menu = MENU_SETTINGS
|
||||
return
|
||||
|
||||
src.menu = MENU_SETTINGS
|
||||
src.print_text("Connection failed.")
|
||||
return
|
||||
else
|
||||
//Attempt to autodetect server & connect
|
||||
src.menu = -1
|
||||
src.print_text("Searching for printserver...")
|
||||
if (ping_server(1))
|
||||
src.print_text("Unable to detect printserver!")
|
||||
src.menu = MENU_SETTINGS
|
||||
return
|
||||
|
||||
src.print_text("Printserver detected at \[[potential_server_netid]]<br>Connecting...")
|
||||
connect_printserver(potential_server_netid, 1)
|
||||
|
||||
src.menu = MENU_SETTINGS
|
||||
if (connected)
|
||||
src.master.temp = null
|
||||
src.print_text("Connection established to \[[server_netid]]!")
|
||||
src.print_settings()
|
||||
return
|
||||
|
||||
src.print_text("Connection failed.")
|
||||
return
|
||||
|
||||
if ("2")
|
||||
src.menu = -1
|
||||
message_server("command=print&args=index")
|
||||
sleep(8)
|
||||
var/dat = "Known Printers:"
|
||||
if (!src.known_printers || !src.known_printers.len)
|
||||
dat += "<br> \[__] No printers known."
|
||||
|
||||
else
|
||||
var/leadingZeroCount = length("[src.known_printers.len]")
|
||||
for (var/kp_index=1, kp_index <= src.known_printers.len, kp_index++)
|
||||
dat += "<br> \[[add_zero("[kp_index]",leadingZeroCount)]] [src.known_printers[kp_index]]"
|
||||
|
||||
src.master.temp = null
|
||||
src.print_text("[dat]<br> (0) Return")
|
||||
src.menu = MENU_SELECT_PRINTER
|
||||
return
|
||||
|
||||
if (MENU_SELECT_PRINTER)
|
||||
var/printerNumber = round(text2num(command))
|
||||
if (printerNumber == 0)
|
||||
src.menu = MENU_SETTINGS
|
||||
src.master.temp = null
|
||||
src.print_settings()
|
||||
return
|
||||
|
||||
if (printerNumber < 1 || printerNumber > src.known_printers.len)
|
||||
return
|
||||
|
||||
src.selected_printer = src.known_printers[printerNumber]
|
||||
src.menu = MENU_SETTINGS
|
||||
src.master.temp = null
|
||||
src.print_text("Printer set.")
|
||||
src.print_settings()
|
||||
|
||||
|
||||
if (MENU_INDEX)
|
||||
var/index_number = round( max( text2num(command), 0) )
|
||||
if (index_number == 0)
|
||||
src.menu = MENU_MAIN
|
||||
src.master.temp = null
|
||||
src.print_text(mainmenu_text())
|
||||
return
|
||||
|
||||
else if (index_number == 99)
|
||||
var/datum/data/record/G = new /datum/data/record( )
|
||||
G.fields["name"] = "New Record"
|
||||
G.fields["id"] = "[add_zero(num2hex(rand(1, 1.6777215E7)), 6)]"
|
||||
G.fields["rank"] = "Unassigned"
|
||||
G.fields["sex"] = "Other"
|
||||
G.fields["age"] = "Unknown"
|
||||
G.fields["fingerprint"] = "Unknown"
|
||||
G.fields["p_stat"] = "Active"
|
||||
G.fields["m_stat"] = "Stable"
|
||||
src.active_general = G
|
||||
src.active_secure = null
|
||||
src.log_string += "<br>Log created: [G.fields["id"]]"
|
||||
|
||||
if (src.print_active_record())
|
||||
src.menu = MENU_IN_RECORD
|
||||
|
||||
return
|
||||
|
||||
if (!istype(record_list) || index_number > record_list.len)
|
||||
src.print_text("Invalid record.")
|
||||
return
|
||||
|
||||
var/datum/data/record/check = src.record_list[index_number]
|
||||
if(!check || !istype(check))
|
||||
src.print_text("<b>Error:</b> Record Data Invalid.")
|
||||
return
|
||||
|
||||
src.active_general = check
|
||||
src.active_secure = null
|
||||
if (data_core.general.Find(check))
|
||||
for (var/datum/data/record/E in data_core.security)
|
||||
if ((E.fields["name"] == src.active_general.fields["name"] || E.fields["id"] == src.active_general.fields["id"]))
|
||||
src.active_secure = E
|
||||
break
|
||||
|
||||
src.log_string += "<br>Log loaded: [src.active_general.fields["id"]]"
|
||||
|
||||
if (src.print_active_record())
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
if (MENU_IN_RECORD)
|
||||
switch(lowertext(command))
|
||||
if ("r")
|
||||
src.print_active_record()
|
||||
return
|
||||
if ("d")
|
||||
src.print_text("Are you sure? (Y/N)")
|
||||
src.field_input = FIELDNUM_DELETE
|
||||
src.menu = MENU_FIELD_INPUT
|
||||
return
|
||||
if ("p")
|
||||
|
||||
if ((src.connected && src.selected_printer) && !src.network_print())
|
||||
src.print_text("Print instruction sent.")
|
||||
else
|
||||
if (local_print())
|
||||
src.print_text("<b>Error:</b> No printer detected.")
|
||||
else
|
||||
src.print_text("Print instruction sent.")
|
||||
|
||||
return
|
||||
|
||||
var/field_number = round( max( text2num(command), 0) )
|
||||
if (field_number == 0)
|
||||
src.menu = MENU_INDEX
|
||||
src.print_index()
|
||||
return
|
||||
|
||||
src.field_input = field_number
|
||||
switch(field_number)
|
||||
if (FIELDNUM_NAME, FIELDNUM_AGE, FIELDNUM_RANK, FIELDNUM_PRINT, FIELDNUM_MINCRIM, FIELDNUM_MINDET, FIELDNUM_MAJCRIM, FIELDNUM_MAJDET)
|
||||
src.print_text("Please enter new value.")
|
||||
src.menu = MENU_FIELD_INPUT
|
||||
return
|
||||
|
||||
if (FIELDNUM_SEX)
|
||||
src.print_text("Please select: (1) Female (2) Male (3) Other (0) Back")
|
||||
src.menu = MENU_FIELD_INPUT
|
||||
return
|
||||
|
||||
if (FIELDNUM_CRIMSTAT)
|
||||
src.print_text("Please select: (1) Arrest (2) None (3) Incarcerated<br>(4) Parolled (5) Released (0) Back")
|
||||
src.menu = MENU_FIELD_INPUT
|
||||
return
|
||||
|
||||
if (FIELDNUM_NEWREC)
|
||||
if (src.active_secure)
|
||||
return
|
||||
|
||||
var/datum/data/record/R = new /datum/data/record( )
|
||||
R.fields["name"] = src.active_general.fields["name"]
|
||||
R.fields["id"] = src.active_general.fields["id"]
|
||||
R.name = "Security Record #[R.fields["id"]]"
|
||||
R.fields["criminal"] = "None"
|
||||
R.fields["mi_crim"] = "None"
|
||||
R.fields["mi_crim_d"] = "No minor crime convictions."
|
||||
R.fields["ma_crim"] = "None"
|
||||
R.fields["ma_crim_d"] = "No major crime convictions."
|
||||
R.fields["notes"] = "No notes."
|
||||
data_core.security += R
|
||||
src.active_secure = R
|
||||
|
||||
src.print_active_record()
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
if (MENU_FIELD_INPUT)
|
||||
if (!src.active_general)
|
||||
src.print_text("<b>Error:</b> Record invalid.")
|
||||
src.menu = MENU_INDEX
|
||||
return
|
||||
|
||||
var/inputText = strip_html(text)
|
||||
switch (field_input)
|
||||
if (FIELDNUM_NAME)
|
||||
if (ckey(inputText))
|
||||
src.active_general.fields["name"] = copytext(inputText, 1, 26)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_SEX)
|
||||
switch (round( max( text2num(command), 0) ))
|
||||
if (1)
|
||||
src.active_general.fields["sex"] = "Female"
|
||||
if (2)
|
||||
src.active_general.fields["sex"] = "Male"
|
||||
if (3)
|
||||
src.active_general.fields["sex"] = "Other"
|
||||
if (0)
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_AGE)
|
||||
var/newAge = round( min( text2num(command), 99) )
|
||||
if (newAge < 1)
|
||||
src.print_text("Invalid age value. Please re-enter.")
|
||||
return
|
||||
|
||||
src.active_general.fields["age"] = newAge
|
||||
|
||||
if (FIELDNUM_RANK)
|
||||
if (ckey(inputText))
|
||||
src.active_general.fields["rank"] = copytext(inputText, 1, 33)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_PRINT)
|
||||
if (ckey(inputText))
|
||||
src.active_general.fields["fingerprint"] = copytext(inputText, 1, 33)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_CRIMSTAT)
|
||||
if (!src.active_secure)
|
||||
src.print_text("No security record loaded!")
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
switch (round( max( text2num(command), 0) ))
|
||||
if (1)
|
||||
if (src.active_secure.fields["criminal"] != "*Arrest*")
|
||||
src.report_arrest(src.active_general.fields["name"])
|
||||
src.active_secure.fields["criminal"] = "*Arrest*"
|
||||
if (2)
|
||||
src.active_secure.fields["criminal"] = "None"
|
||||
if (3)
|
||||
src.active_secure.fields["criminal"] = "Incarcerated"
|
||||
if (4)
|
||||
src.active_secure.fields["criminal"] = "Parolled"
|
||||
if (5)
|
||||
src.active_secure.fields["criminal"] = "Released"
|
||||
if (0)
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_MINCRIM)
|
||||
if (!src.active_secure)
|
||||
src.print_text("No security record loaded!")
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
if (ckey(inputText))
|
||||
src.active_secure.fields["mi_crim"] = copytext(inputText, 1, MAX_MESSAGE_LEN)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_MINDET)
|
||||
if (!src.active_secure)
|
||||
src.print_text("No security record loaded!")
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
if (ckey(inputText))
|
||||
src.active_secure.fields["mi_crim_d"] = copytext(inputText, 1, MAX_MESSAGE_LEN)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_MAJCRIM)
|
||||
if (!src.active_secure)
|
||||
src.print_text("No security record loaded!")
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
if (ckey(inputText))
|
||||
src.active_secure.fields["ma_crim"] = copytext(inputText, 1, MAX_MESSAGE_LEN)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_MAJDET)
|
||||
if (!src.active_secure)
|
||||
src.print_text("No security record loaded!")
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
if (ckey(inputText))
|
||||
src.active_secure.fields["ma_crim_d"] = copytext(inputText, 1, MAX_MESSAGE_LEN)
|
||||
else
|
||||
return
|
||||
|
||||
if (FIELDNUM_DELETE)
|
||||
switch (ckey(inputText))
|
||||
if ("y")
|
||||
if (src.active_secure)
|
||||
src.log_string += "<br>S-Record [src.active_secure.fields["id"]] deleted."
|
||||
data_core.security -= src.active_secure
|
||||
qdel(src.active_secure)
|
||||
src.print_active_record()
|
||||
src.menu = MENU_IN_RECORD
|
||||
|
||||
else if (src.active_general)
|
||||
data_core.general -= src.active_general
|
||||
|
||||
src.log_string += "<br>Record [src.active_general.fields["id"]] deleted."
|
||||
qdel(src.active_general)
|
||||
src.menu = MENU_INDEX
|
||||
src.print_index()
|
||||
|
||||
if ("n")
|
||||
src.menu = MENU_IN_RECORD
|
||||
src.print_text("Record preserved.")
|
||||
|
||||
return
|
||||
|
||||
src.print_text("Field updated.")
|
||||
src.menu = MENU_IN_RECORD
|
||||
return
|
||||
|
||||
if (MENU_SEARCH_INPUT)
|
||||
var/searchText = ckey(strip_html(text))
|
||||
if (!searchText)
|
||||
return
|
||||
|
||||
var/datum/data/record/result = null
|
||||
for(var/datum/data/record/R in data_core.general)
|
||||
if((ckey(R.fields["name"]) == searchText) || (ckey(R.fields["dna"]) == searchText) || (ckey(R.fields["id"]) == searchText) || (ckey(R.fields["fingerprint"]) == searchText))
|
||||
result = R
|
||||
break
|
||||
|
||||
if(!result)
|
||||
src.print_text("No results found.")
|
||||
src.menu = MENU_MAIN
|
||||
return
|
||||
|
||||
src.active_general = result
|
||||
src.active_secure = null //Time to find the accompanying security record, if it even exists.
|
||||
for (var/datum/data/record/E in data_core.security)
|
||||
if ((E.fields["name"] == src.active_general.fields["name"] || E.fields["id"] == src.active_general.fields["id"]))
|
||||
src.active_secure = E
|
||||
break
|
||||
|
||||
src.menu = MENU_IN_RECORD
|
||||
src.print_active_record()
|
||||
return
|
||||
|
||||
|
||||
return
|
||||
|
||||
receive_command(obj/source, command, datum/signal/signal)
|
||||
if ((..()) || (!signal))
|
||||
return
|
||||
|
||||
if (!connected)
|
||||
if (signal.data["command"] == "ping_reply" && !potential_server_netid)
|
||||
|
||||
if (signal.data["device"] == "PNET_MAINFRAME" && signal.data["sender"] && ishex(signal.data["sender"]))
|
||||
potential_server_netid = signal.data["sender"]
|
||||
return
|
||||
|
||||
else if (signal.data["command"] == "term_connect")
|
||||
server_netid = ckey(signal.data["sender"])
|
||||
connected = 1
|
||||
potential_server_netid = null
|
||||
if(signal.data["data"] != "noreply")
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
|
||||
termsignal.data["address_1"] = signal.data["sender"]
|
||||
termsignal.data["command"] = "term_connect"
|
||||
termsignal.data["device"] = "SRV_TERMINAL"
|
||||
termsignal.data["data"] = "noreply"
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[find_peripheral("NET_ADAPTER")]")
|
||||
|
||||
return
|
||||
else
|
||||
if (signal.data["sender"] != server_netid)
|
||||
return
|
||||
|
||||
if (!server_netid)
|
||||
connected = 0
|
||||
return
|
||||
|
||||
switch(lowertext(signal.data["command"]))
|
||||
if ("term_message","term_file")
|
||||
var/list/data = params2list(signal.data["data"])
|
||||
if(!data || !data["command"])
|
||||
return
|
||||
|
||||
var/list/commandList = dd_text2list(data["command"], "|n")
|
||||
if (!commandList || !commandList.len)
|
||||
return
|
||||
|
||||
switch (commandList[1])
|
||||
if ("print_index")
|
||||
if (commandList.len > 1)
|
||||
known_printers = commandList.Copy(2)
|
||||
else
|
||||
known_printers = list()
|
||||
|
||||
if ("print_status")
|
||||
if (commandList.len > 1)
|
||||
printer_status = commandList[2]
|
||||
else
|
||||
printer_status = "???"
|
||||
return
|
||||
|
||||
if ("term_disconnect")
|
||||
src.connected = 0
|
||||
src.server_netid = null
|
||||
src.print_text("Connection closed by printserver.")
|
||||
|
||||
if("term_ping")
|
||||
if(signal.data["data"] == "reply")
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
|
||||
termsignal.data["address_1"] = signal.data["sender"]
|
||||
termsignal.data["command"] = "term_ping"
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[find_peripheral("NET_ADAPTER")]")
|
||||
|
||||
|
||||
return
|
||||
|
||||
proc
|
||||
mainmenu_text()
|
||||
var/dat = {"<center>S E C M A T E 7</center><br>
|
||||
Welcome to SecMate 7<br>
|
||||
<b>Commands:</b>
|
||||
<br>(1) View security records.
|
||||
<br>(2) Search for a record.
|
||||
<br>(3) Adjust settings.
|
||||
<br>(0) Quit."}
|
||||
|
||||
return dat
|
||||
|
||||
print_active_record()
|
||||
if (!src.active_general)
|
||||
src.print_text("<b>Error:</b> General record data corrupt.")
|
||||
return 0
|
||||
src.master.temp = null
|
||||
|
||||
var/view_string = {"
|
||||
\[01]Name: [src.active_general.fields["name"]] ID: [src.active_general.fields["id"]]
|
||||
<br>\[02]<b>Sex:</b> [src.active_general.fields["sex"]]
|
||||
<br>\[03]<b>Age:</b> [src.active_general.fields["age"]]
|
||||
<br>\[04]<b>Rank:</b> [src.active_general.fields["rank"]]
|
||||
<br>\[05]<b>Fingerprint:</b> [src.active_general.fields["fingerprint"]]
|
||||
<br>\[__]<b>DNA:</b> [src.active_general.fields["dna"]]
|
||||
<br>\[__]Physical Status: [src.active_general.fields["p_stat"]]
|
||||
<br>\[__]Mental Status: [src.active_general.fields["m_stat"]]"}
|
||||
|
||||
if ((istype(src.active_secure, /datum/data/record) && data_core.security.Find(src.active_secure)))
|
||||
view_string +={"
|
||||
<br><center><b>Security Data</b></center>
|
||||
<br>\[06]<b>Criminal Status:</b> [src.active_secure.fields["criminal"]]
|
||||
<br>\[07]<b>Minor Crimes:</b> [src.active_secure.fields["mi_crim"]]
|
||||
<br>\[08]<b>Details:</b> [src.active_secure.fields["mi_crim_d"]]
|
||||
<br>\[09]<b><br>Major Crimes:</b> [src.active_secure.fields["ma_crim"]]
|
||||
<br>\[10]<b>Details:</b> [src.active_secure.fields["ma_crim_d"]]
|
||||
<br>Important Notes:
|
||||
<br> [src.active_secure.fields["notes"]]<br>"}
|
||||
else
|
||||
view_string += "<br><br><b>Security Record Lost!</b>"
|
||||
view_string += "<br>\[99] Create New Security Record.<br>"
|
||||
|
||||
view_string += "<br>Enter field number to edit a field<br>(R) Redraw (D) Delete (P) Print (0) Return to index."
|
||||
|
||||
src.print_text("<b>Record Data:</b><br>[view_string]")
|
||||
return 1
|
||||
|
||||
print_index()
|
||||
src.master.temp = null
|
||||
var/dat = ""
|
||||
if(!src.record_list || !src.record_list.len)
|
||||
src.print_text("<b>Error:</b> No records found in database.")
|
||||
dat += "<br><b>\[99]</b> Create New Record.<br>"
|
||||
|
||||
else
|
||||
dat = "Please select a record:"
|
||||
var/leadingZeroCount = length("[src.record_list.len]")
|
||||
for(var/x = 1, x <= src.record_list.len, x++)
|
||||
var/datum/data/record/R = src.record_list[x]
|
||||
if(!R || !istype(R))
|
||||
dat += "<br><b>\[[add_zero("[x]",leadingZeroCount)]]</b><font color=red>ERR: REDACTED</font>"
|
||||
continue
|
||||
|
||||
dat += "<br><b>\[[add_zero("[x]",leadingZeroCount)]]</b>[R.fields["id"]]: [R.fields["name"]]"
|
||||
|
||||
dat += "<br><b>\[[add_zero("99",leadingZeroCount)]]</b> Create New Record.<br>"
|
||||
dat += "<br><br>Enter record number, or 0 to return."
|
||||
|
||||
src.print_text(dat)
|
||||
return 1
|
||||
|
||||
print_settings()
|
||||
var/dat = "Options:"
|
||||
|
||||
if (src.connected)
|
||||
dat += "<br>(1) Disconnect from print server."
|
||||
dat += "<br>(2) Select printer."
|
||||
|
||||
else
|
||||
dat += "<br>(1) Connect to print server."
|
||||
|
||||
dat += "<br>(0) Back."
|
||||
|
||||
src.print_text(dat)
|
||||
return 1
|
||||
|
||||
report_arrest(var/perp_name)
|
||||
if(!perp_name || !src.radiocard)
|
||||
return
|
||||
|
||||
if (usr)
|
||||
logTheThing("station", usr, null, "[perp_name] is set to arrest by [usr] (using the ID card of [src.authenticated]) [log_loc(src.master)]")
|
||||
|
||||
//Unlikely that this would be a problem but OH WELL
|
||||
if(last_arrest_report && world.time < (last_arrest_report + 10))
|
||||
return
|
||||
|
||||
//Set card frequency if it isn't already.
|
||||
if(src.radiocard.frequency != src.setup_mail_freq && !src.radiocard.setup_freq_locked)
|
||||
var/datum/signal/freqsignal = get_free_signal()
|
||||
//freqsignal.encryption = "\ref[src.radiocard]"
|
||||
peripheral_command("[src.setup_mail_freq]", freqsignal, "\ref[src.radiocard]")
|
||||
src.log_string += "<br>Adjusting frequency... \[[src.setup_mail_freq]]."
|
||||
|
||||
var/datum/signal/signal = get_free_signal()
|
||||
//signal.encryption = "\ref[src.radiocard]"
|
||||
|
||||
//Create a PDA mass-message string.
|
||||
signal.data["command"] = "text_message"
|
||||
signal.data["sender_name"] = "SEC-MAILBOT"
|
||||
signal.data["group"] = src.setup_mailgroup //Only security PDAs should be informed.
|
||||
signal.data["message"] = "Alert! Crewman \"[perp_name]\" has been flagged for arrest by [src.authenticated]!"
|
||||
|
||||
src.log_string += "<br>Arrest notification sent."
|
||||
last_arrest_report = world.time
|
||||
peripheral_command("transmit", signal, "\ref[src.radiocard]")
|
||||
return
|
||||
|
||||
find_access_file() //Look for the whimsical account_data file
|
||||
var/datum/computer/folder/accdir = src.holder.root
|
||||
if(src.master.host_program) //Check where the OS is, preferably.
|
||||
accdir = src.master.host_program.holder.root
|
||||
|
||||
var/datum/computer/file/user_data/target = parse_file_directory(setup_acc_filepath, accdir)
|
||||
if(target && istype(target))
|
||||
src.account = target
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
local_print()
|
||||
var/obj/item/peripheral/printcard = find_peripheral("LAR_PRINTER")
|
||||
if(!printcard)
|
||||
return 1
|
||||
|
||||
//Okay, let's put together something to print.
|
||||
var/info = "<center><B>Security Record</B></center><br>"
|
||||
if (istype(src.active_general, /datum/data/record) && data_core.general.Find(src.active_general))
|
||||
info += {"
|
||||
Name: [src.active_general.fields["name"]] ID: [src.active_general.fields["id"]]
|
||||
<br><br>Sex: [src.active_general.fields["sex"]]
|
||||
<br><br>Age: [src.active_general.fields["age"]]
|
||||
<br><br>Rank: [src.active_general.fields["rank"]]
|
||||
<br><br>Fingerprint: [src.active_general.fields["fingerprint"]]
|
||||
<br><br>DNA: [src.active_general.fields["dna"]]
|
||||
<br><br>Physical Status: [src.active_general.fields["p_stat"]]
|
||||
<br><br>Mental Status: [src.active_general.fields["m_stat"]]"}
|
||||
else
|
||||
info += "<b>General Record Lost!</b><br>"
|
||||
if ((istype(src.active_secure, /datum/data/record) && data_core.security.Find(src.active_secure)))
|
||||
info += {"
|
||||
<br><br><center><b>Security Data</b></center><br>
|
||||
<br>Criminal Status: [src.active_secure.fields["criminal"]]
|
||||
<br><br>Minor Crimes: [src.active_secure.fields["mi_crim"]]
|
||||
<br><br>Details: [src.active_secure.fields["mi_crim_d"]]
|
||||
<br><br><br>Major Crimes: [src.active_secure.fields["ma_crim"]]
|
||||
<br><br>Details: [src.active_secure.fields["ma_crim_d"]]
|
||||
Important Notes:<br>
|
||||
<br> [src.active_secure.fields["notes"]]<br>"}
|
||||
|
||||
else
|
||||
info += "<br><center><b>Security Record Lost!</b></center><br>"
|
||||
info += "</tt>"
|
||||
|
||||
var/datum/signal/signal = get_free_signal()
|
||||
signal.data["data"] = info
|
||||
signal.data["title"] = "Security Record"
|
||||
src.peripheral_command("print",signal, "\ref[printcard]")
|
||||
return 0
|
||||
|
||||
network_print()
|
||||
if (!connected || !selected_printer || !server_netid)
|
||||
return 1
|
||||
|
||||
var/datum/computer/file/record/printRecord = new
|
||||
printRecord.fields += "title=Security Record"
|
||||
printRecord.fields += "Security Record"
|
||||
if (istype(src.active_general, /datum/data/record) && data_core.general.Find(src.active_general))
|
||||
|
||||
printRecord.fields += "Name: [src.active_general.fields["name"]] ID: [src.active_general.fields["id"]]"
|
||||
printRecord.fields += "Sex: [src.active_general.fields["sex"]]"
|
||||
printRecord.fields += "Age: [src.active_general.fields["age"]]"
|
||||
printRecord.fields += "Rank: [src.active_general.fields["rank"]]"
|
||||
printRecord.fields += "Fingerprint: [src.active_general.fields["fingerprint"]]"
|
||||
printRecord.fields += "DNA: [src.active_general.fields["dna"]]"
|
||||
printRecord.fields += "Physical Status: [src.active_general.fields["p_stat"]]"
|
||||
printRecord.fields += "Mental Status: [src.active_general.fields["m_stat"]]"
|
||||
else
|
||||
printRecord.fields += "General Record Lost!"
|
||||
|
||||
if ((istype(src.active_secure, /datum/data/record) && data_core.security.Find(src.active_secure)))
|
||||
|
||||
printRecord.fields += "Security Data"
|
||||
printRecord.fields += "Criminal Status: [src.active_secure.fields["criminal"]]"
|
||||
printRecord.fields += "Minor Crimes: [src.active_secure.fields["mi_crim"]]"
|
||||
printRecord.fields += "Details: [src.active_secure.fields["mi_crim_d"]]"
|
||||
printRecord.fields += "Major Crimes: [src.active_secure.fields["ma_crim"]]"
|
||||
printRecord.fields += "Details: [src.active_secure.fields["ma_crim_d"]]"
|
||||
printRecord.fields += "Important Notes:"
|
||||
printRecord.fields += "[src.active_secure.fields["notes"]]"
|
||||
|
||||
else
|
||||
printRecord.fields += "Security Record Lost!"
|
||||
|
||||
printRecord.name = "printout"
|
||||
|
||||
message_server("command=print&args=print [selected_printer]", printRecord)
|
||||
return 0
|
||||
|
||||
message_server(var/message, var/datum/computer/file/toSend)
|
||||
if (!connected || !server_netid || !message)
|
||||
return 1
|
||||
|
||||
var/netCard = find_peripheral("NET_ADAPTER")
|
||||
if (!netCard)
|
||||
return 1
|
||||
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
|
||||
termsignal.data["address_1"] = server_netid
|
||||
termsignal.data["data"] = message
|
||||
termsignal.data["command"] = "term_message"
|
||||
if (toSend)
|
||||
termsignal.data_file = toSend
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netCard]")
|
||||
return 0
|
||||
|
||||
connect_printserver(var/address, delayCaller=0)
|
||||
if (connected)
|
||||
return 1
|
||||
|
||||
var/netCard = find_peripheral("NET_ADAPTER")
|
||||
if (!netCard)
|
||||
return 1
|
||||
|
||||
var/datum/signal/signal = get_free_signal()
|
||||
|
||||
signal.data["address_1"] = address
|
||||
signal.data["command"] = "term_connect"
|
||||
signal.data["device"] = "SRV_TERMINAL"
|
||||
var/datum/computer/file/user_data/user_data = account
|
||||
var/datum/computer/file/record/udat = null
|
||||
if (istype(user_data))
|
||||
udat = new
|
||||
|
||||
var/userid = format_username(user_data.registered)
|
||||
|
||||
udat.fields["userid"] = userid
|
||||
udat.fields["access"] = list2params(user_data.access)
|
||||
if (!udat.fields["access"] || !udat.fields["userid"])
|
||||
// qdel(udat)
|
||||
udat.dispose()
|
||||
return 1
|
||||
|
||||
udat.fields["service"] = "print"
|
||||
|
||||
if (udat)
|
||||
signal.data_file = udat
|
||||
|
||||
src.peripheral_command("transmit", signal, "\ref[netCard]")
|
||||
if (delayCaller)
|
||||
sleep(8)
|
||||
return 0
|
||||
|
||||
return 0
|
||||
|
||||
disconnect_server()
|
||||
if (!server_netid)
|
||||
return 1
|
||||
|
||||
var/netCard = find_peripheral("NET_ADAPTER")
|
||||
if (!netCard)
|
||||
return 1
|
||||
|
||||
var/datum/signal/signal = get_free_signal()
|
||||
|
||||
signal.data["address_1"] = server_netid
|
||||
signal.data["command"] = "term_disconnect"
|
||||
|
||||
src.peripheral_command("transmit", signal, "\ref[netCard]")
|
||||
|
||||
return 0
|
||||
|
||||
ping_server(delayCaller=0)
|
||||
if (connected)
|
||||
return 1
|
||||
|
||||
var/netCard = find_peripheral("NET_ADAPTER")
|
||||
if (!netCard)
|
||||
return 1
|
||||
|
||||
potential_server_netid = null
|
||||
src.peripheral_command("ping", null, "\ref[netCard]")
|
||||
|
||||
if (delayCaller)
|
||||
sleep(8)
|
||||
return (potential_server_netid == null)
|
||||
|
||||
return 0
|
||||
|
||||
#undef MENU_MAIN
|
||||
#undef MENU_INDEX
|
||||
#undef MENU_IN_RECORD
|
||||
#undef MENU_FIELD_INPUT
|
||||
#undef MENU_SEARCH_INPUT
|
||||
#undef MENU_SETTINGS
|
||||
#undef MENU_SELECT_PRINTER
|
||||
|
||||
#undef FIELDNUM_NAME
|
||||
#undef FIELDNUM_SEX
|
||||
#undef FIELDNUM_AGE
|
||||
#undef FIELDNUM_RANK
|
||||
#undef FIELDNUM_PRINT
|
||||
#undef FIELDNUM_CRIMSTAT
|
||||
#undef FIELDNUM_MINCRIM
|
||||
#undef FIELDNUM_MINDET
|
||||
#undef FIELDNUM_MAJCRIM
|
||||
#undef FIELDNUM_MAJDET
|
||||
|
||||
#undef FIELDNUM_DELETE
|
||||
#undef FIELDNUM_NEWREC
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,162 @@
|
||||
//A packet sniffer!!
|
||||
|
||||
/obj/item/device/net_sniffer
|
||||
name = "Packet Sniffer"
|
||||
desc = "An electronic device designed to intercept network transmissions."
|
||||
icon_state = "sniffer0"
|
||||
item_state = "electronic"
|
||||
w_class = 4.0
|
||||
rand_pos = 0
|
||||
var/mode = 0
|
||||
var/obj/machinery/power/data_terminal/link = null
|
||||
var/filter_id = null
|
||||
var/list/filters = list()
|
||||
var/last_intercept = 0
|
||||
var/list/packet_data = list()
|
||||
var/max_logs = 8
|
||||
|
||||
attack_ai()
|
||||
return
|
||||
|
||||
attack_hand(mob/user as mob)
|
||||
if(mode)
|
||||
src.interact(user)
|
||||
return
|
||||
|
||||
else
|
||||
..()
|
||||
|
||||
attackby(var/obj/item/I, var/mob/user)
|
||||
if(istype(I, /obj/item/screwdriver))
|
||||
if(!mode)
|
||||
var/turf/T = loc
|
||||
if(isturf(T) && !T.intact)
|
||||
var/obj/machinery/power/data_terminal/test_link = locate() in T
|
||||
if(test_link && !test_link.is_valid_master(test_link.master))
|
||||
src.link = test_link
|
||||
src.link.master = src
|
||||
|
||||
anchored = 1
|
||||
mode = 1
|
||||
user.visible_message("[user] attaches the [src] to the data terminal.","You attach the [src] to the data terminal.")
|
||||
|
||||
icon_state = "sniffer1"
|
||||
|
||||
else
|
||||
|
||||
boutput(user, "<span style=\"color:red\">The [src] couldn't be attached here!</span>")
|
||||
return
|
||||
|
||||
else
|
||||
boutput(user, "Device must be placed over a free data terminal to attach to it.")
|
||||
return
|
||||
else
|
||||
anchored = 0
|
||||
mode = 0
|
||||
user.visible_message("[user] detaches the [src] from the data terminal.","You detach the [src] from the data terminal.")
|
||||
icon_state = "sniffer0"
|
||||
if(src.link)
|
||||
src.link.master = null
|
||||
src.link = null
|
||||
return
|
||||
else
|
||||
..()
|
||||
|
||||
attack_self(mob/user as mob)
|
||||
return interact(user)
|
||||
|
||||
proc/interact(mob/user as mob)
|
||||
|
||||
var/dat = "<html><head><title>Packet Sniffer</title></head><body>"
|
||||
|
||||
dat += "Current sender filter: <a href='byond://?src=\ref[src];filtid=1'>[src.filter_id ? src.filter_id : "NONE"]</a><br>"
|
||||
|
||||
dat += "<hr><b>Packet log:</b><hr>"
|
||||
if(packet_data.len)
|
||||
for(var/a in packet_data)
|
||||
dat += "<tt>[a]</tt><br>"
|
||||
else
|
||||
dat += "<b>NONE</b>"
|
||||
|
||||
dat += "<hr>"
|
||||
user << browse(dat,"window=packets")
|
||||
onclose(user,"packets")
|
||||
return
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
|
||||
if (usr.contents.Find(src) || usr.contents.Find(src.master) || (istype(src.loc, /turf) && get_dist(src, usr) <= 1))
|
||||
if (usr.stat || usr.restrained())
|
||||
return
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
usr.machine = src
|
||||
|
||||
if(href_list["filtid"])
|
||||
var/t = input(usr, "Please enter new filter net id", src.name, src.filter_id) as text
|
||||
if (!t)
|
||||
src.filter_id = null
|
||||
src.updateIntDialog()
|
||||
return
|
||||
|
||||
if (!in_range(src, usr) || usr.stat || usr.restrained())
|
||||
return
|
||||
|
||||
if(length(t) != 8 || !ishex(t))
|
||||
src.filter_id = null
|
||||
src.updateIntDialog()
|
||||
return
|
||||
|
||||
src.filter_id = t
|
||||
|
||||
src.updateIntDialog()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
proc/updateIntDialog()
|
||||
if(mode)
|
||||
src.updateUsrDialog()
|
||||
else
|
||||
src.updateSelfDialog()
|
||||
return
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if(!mode || !src.link)
|
||||
return
|
||||
if(!signal || signal.encryption)
|
||||
return
|
||||
|
||||
if(signal.transmission_method != TRANSMISSION_WIRE) //No radio for us thanks
|
||||
return
|
||||
|
||||
var/target = signal.data["address_1"]
|
||||
if(src.filter_id && src.filter_id != target)
|
||||
return
|
||||
|
||||
var/badcheck = 0
|
||||
for(var/check in src.filters)
|
||||
if(!(check in signal.data) || signal.data[check] != src.filters[check])
|
||||
badcheck = 1
|
||||
break
|
||||
if(badcheck)
|
||||
return
|
||||
|
||||
if(!src.last_intercept || src.last_intercept + 40 <= world.time)
|
||||
playsound(src.loc, "sound/machines/twobeep.ogg", 25, 1)
|
||||
//src.packet_data = signal.data:Copy()
|
||||
var/newdat = "<b>\[[time2text(world.timeofday,"mm:ss")]:[(world.timeofday%10)]\]:</b>"
|
||||
for (var/i in signal.data)
|
||||
newdat += "[i][isnull(signal.data[i]) ? "; " : "=[signal.data[i]]; "]"
|
||||
|
||||
if (signal.data_file)
|
||||
. = signal.data_file.asText()
|
||||
newdat += "<br>Included file ([signal.data_file.name], [signal.data_file.extension]): [. ? . : "Not printable."]"
|
||||
|
||||
src.packet_data += newdat
|
||||
if (src.packet_data.len > src.max_logs)
|
||||
src.packet_data.Cut(1,2)
|
||||
src.last_intercept = world.time
|
||||
src.updateIntDialog()
|
||||
return
|
||||
@@ -0,0 +1,574 @@
|
||||
|
||||
|
||||
/datum/computer/file/terminal_program/os/terminal_os
|
||||
name = "TermOS B"
|
||||
size = 6
|
||||
var/datum/computer/folder/current_folder = null
|
||||
var/net_number = null
|
||||
var/tmp/serv_id = null //NetID of connected server
|
||||
var/tmp/attempt_id = null //Are we attempting to connect to something?
|
||||
var/tmp/last_serv_id = null //Last valid serv_id.
|
||||
var/obj/item/peripheral/network/netcard = null
|
||||
var/tmp/disconnect_wait = -1 //Are we waiting to disconnect?
|
||||
var/tmp/ping_wait = 0 //Are we waiting for a ping reply?
|
||||
var/tmp/datum/computer/file/temp_file = null //Temp folder from our server
|
||||
var/auto_accept = 1 //Do we automatically accept connection attempts?
|
||||
//var/tmp/service_mode = 0
|
||||
|
||||
input_text(text)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/list/command_list = parse_string(text)
|
||||
var/command = lowertext(command_list[1])
|
||||
command_list -= command_list[1] //Remove the command that we are now processing.
|
||||
|
||||
src.print_text(">[strip_html(text)]")
|
||||
|
||||
if(!current_folder)
|
||||
current_folder = src.holding_folder
|
||||
|
||||
if(disconnect_wait > 0)
|
||||
src.print_text("Alert: System busy, please hold.")
|
||||
return
|
||||
|
||||
if(command == "help" && !src.serv_id)
|
||||
var/help_message = {"<b>Terminal Commands:</b><br>
|
||||
term_status - View current status of terminal.<br>
|
||||
term_accept - Toggle connection auto-accept.<br>
|
||||
term_login - Transmit login file (ID Required)<br>
|
||||
term_ping - Scan network for terminal devices.<br>
|
||||
term_break - Send break signal to host.<br>
|
||||
<b>Connection Commands:</b><br>
|
||||
connect \[Net ID] - Connect to a specified device.<br>
|
||||
reconnect - Connect to last valid address<br>
|
||||
disconnect - Disconnect from current device.<br>
|
||||
<b>File Commands</b><br>
|
||||
file_status - View status of loaded file.<br>
|
||||
file_send - Transmit loaded file.<br>
|
||||
file_print - Print contents of file.<br>
|
||||
file_load - Load file from local disk.
|
||||
file_save - Save file to local disk."}
|
||||
src.print_text(help_message)
|
||||
return
|
||||
|
||||
switch(command)
|
||||
if("term_status")
|
||||
if(src.netcard)
|
||||
var/statdat = netcard.return_status_text()
|
||||
src.print_text("<b>[netcard.func_tag]</b><br>Status: [statdat]")
|
||||
else
|
||||
src.print_text("No network card detected.")
|
||||
|
||||
src.print_text("Current Server Address: [src.serv_id ? src.serv_id : "NONE"]<br>Auto-accept connections is <b>[src.auto_accept ? "ON" : "OFF"]</b><br>Toggle this with \"term_accept\"")//[src.service_mode ? "<br>Service mode active." : ""]")
|
||||
|
||||
if("term_accept")
|
||||
src.auto_accept = !src.auto_accept
|
||||
src.print_text("Auto-Accept is now <b>[src.auto_accept ? "ON" : "OFF"]</b>")
|
||||
|
||||
if ("term_break")
|
||||
if (!src.serv_id || !netcard)
|
||||
return
|
||||
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
//termsignal.encryption = "\ref[netcard]"
|
||||
termsignal.data["address_1"] = src.serv_id
|
||||
termsignal.data["command"] = "term_break"
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netcard]")
|
||||
|
||||
if("term_ping")
|
||||
if(src.serv_id)
|
||||
src.print_text("Alert: Cannot ping while connected.")
|
||||
return
|
||||
|
||||
if(!src.netcard)
|
||||
src.print_text("Alert: No network card detected.")
|
||||
return
|
||||
|
||||
if (command_list.len)
|
||||
if (ckey(command_list[1]) == "all")
|
||||
src.net_number = null
|
||||
else
|
||||
var/new_net_number = round( text2num(command_list[1]) )
|
||||
if (new_net_number != null && new_net_number >= 0 && new_net_number <= 16)
|
||||
src.net_number = new_net_number
|
||||
|
||||
src.peripheral_command("subnet[src.net_number]", null, "\ref[src.netcard]")
|
||||
|
||||
src.ping_wait = 4
|
||||
|
||||
src.print_text("Pinging [src.net_number == null ? "All Subnetworks" : "Subnetwork [src.net_number]"]...")
|
||||
src.peripheral_command("ping[src.net_number]", null, "\ref[src.netcard]")
|
||||
|
||||
if("term_login")
|
||||
var/obj/item/peripheral/scanner = find_peripheral("ID_SCANNER")
|
||||
if(!scanner)
|
||||
src.print_text("Error: No ID scanner detected.")
|
||||
return
|
||||
if(!src.netcard)
|
||||
src.print_text("Alert: No network card detected.")
|
||||
return
|
||||
if(!src.serv_id)
|
||||
src.print_text("Alert: Connection required.")
|
||||
return
|
||||
src.ping_wait = 2
|
||||
if (issilicon(usr))
|
||||
var/datum/signal/newsig = new
|
||||
newsig.data["registered"] = istype(usr, /mob/living/silicon/ai) ? "AI" : "CYBORG"
|
||||
newsig.data["assignment"] = "AI"
|
||||
newsig.data["access"] = "0"
|
||||
|
||||
spawn (4)
|
||||
switch( src.receive_command(src.master, "card_authed", newsig) )
|
||||
if ("nocard")
|
||||
src.print_text("Please insert a card first.")
|
||||
|
||||
if ("noreg")
|
||||
src.print_text("Notice: No name on card.")
|
||||
|
||||
if ("noassign")
|
||||
src.print_text("Notice: No assignment on card.")
|
||||
|
||||
return
|
||||
else
|
||||
src.peripheral_command("scan_card",null,"\ref[scanner]")
|
||||
/*
|
||||
if("term_service")
|
||||
if (src.serv_id)
|
||||
src.print_text("Alert: Cannot switch mode while connected.")
|
||||
return
|
||||
|
||||
src.service_mode = !src.service_mode
|
||||
src.print_text("Service mode [src.service_mode ? "" : "de"]activated.")
|
||||
*/
|
||||
if("connect")
|
||||
if(src.serv_id)
|
||||
src.print_text("Alert: Terminal is already connected.")
|
||||
return
|
||||
|
||||
if(src.attempt_id)
|
||||
src.print_text("Alert: Already attempting to connect.")
|
||||
return
|
||||
|
||||
var/argument1 = null
|
||||
if(command_list.len)
|
||||
argument1 = command_list[1]
|
||||
|
||||
argument1 = ckey(copytext(argument1, 1, 9))
|
||||
if(!argument1 || (length(argument1) != 8))
|
||||
src.print_text("Alert: Invalid ID. (Must be 8 characters.)")
|
||||
return
|
||||
|
||||
src.attempt_id = argument1
|
||||
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
//termsignal.encryption = "\ref[netcard]"
|
||||
termsignal.data["address_1"] = argument1
|
||||
termsignal.data["command"] = "term_connect"
|
||||
termsignal.data["device"] = "HUI_TERMINAL"
|
||||
//termsignal.data["device"] = "[src.service_mode ? "SRV" : "HUI"]_TERMINAL"
|
||||
src.disconnect_wait = 4
|
||||
|
||||
src.print_text("Attempting to connect...")
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netcard]")
|
||||
|
||||
if("reconnect")
|
||||
if (src.serv_id)
|
||||
src.print_text("Alert: Terminal is already connected.")
|
||||
return
|
||||
|
||||
if (src.attempt_id)
|
||||
src.print_text("Alert: Already attempting to connect.")
|
||||
return
|
||||
|
||||
if (!src.last_serv_id)
|
||||
src.print_text("Alert: No prior connection address in memory.")
|
||||
return
|
||||
|
||||
src.attempt_id = src.last_serv_id
|
||||
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
//termsignal.encryption = "\ref[netcard]"
|
||||
termsignal.data["address_1"] = src.attempt_id
|
||||
termsignal.data["command"] = "term_connect"
|
||||
termsignal.data["device"] = "HUI_TERMINAL"
|
||||
//termsignal.data["device"] = "[src.service_mode ? "SRV" : "HUI"]_TERMINAL"
|
||||
src.disconnect_wait = 4
|
||||
|
||||
src.print_text("Attempting to reconnect to \[[src.attempt_id]]...")
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netcard]")
|
||||
|
||||
|
||||
if("disconnect")
|
||||
if(src.serv_id)
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
//termsignal.encryption = "\ref[netcard]"
|
||||
termsignal.data["address_1"] = src.serv_id
|
||||
termsignal.data["command"] = "term_disconnect"
|
||||
src.serv_id = null
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netcard]")
|
||||
src.print_text("<b>Connection Closed.</b>")
|
||||
src.disconnect_wait = -1
|
||||
|
||||
//Tempfile usage commands.
|
||||
if("file_status")
|
||||
if(!src.temp_file || !istype(src.temp_file))
|
||||
src.print_text("Alert: No file loaded.")
|
||||
return
|
||||
|
||||
var/file_info = "[temp_file.name] - [temp_file.extension] - \[Size: [temp_file.size]]<br>Enter command \"file_save\" to save to external disk."
|
||||
if(istype(temp_file, /datum/computer/file/text))
|
||||
file_info += "<br>Enter command \"file_print\" to print."
|
||||
else if(istype(temp_file, /datum/computer/file/terminal_program/termapp))
|
||||
file_info += "<br>Enter command \"file_run\" to execute."
|
||||
else
|
||||
file_info += "<br>Unknown filetype."
|
||||
|
||||
src.print_text(file_info)
|
||||
|
||||
if("file_send")
|
||||
if (!istype(src.temp_file))
|
||||
src.print_text("Alert: No file loaded.")
|
||||
return
|
||||
|
||||
if(!src.serv_id)
|
||||
src.print_text("Alert: Connection required.")
|
||||
return
|
||||
|
||||
var/sendText = "login"
|
||||
if (command_list.len)
|
||||
sendText = dd_list2text(command_list, " ")
|
||||
|
||||
src.send_term_message(sendText, 1)
|
||||
src.print_text("File sent.")
|
||||
|
||||
/*
|
||||
if("file_read")
|
||||
if(!src.temp_file || !istype(temp_file, /datum/computer/file/text))
|
||||
src.print_text("Alert: File invalid or missing.")
|
||||
return
|
||||
|
||||
src.master.temp = "<b>File Contents:</b><br>"
|
||||
src.print_text(src.temp_file:data)
|
||||
*/
|
||||
if("file_load")
|
||||
var/toLoadName = "temp"
|
||||
if (command_list.len)
|
||||
toLoadName = dd_list2text(command_list, "")
|
||||
|
||||
var/datum/computer/file/loadedFile = null
|
||||
for (var/obj/item/disk/data/drive in src.master.contents)
|
||||
if (drive == src.holder)
|
||||
continue
|
||||
|
||||
loadedFile = get_file_name(toLoadName, drive.root)
|
||||
if (istype(loadedFile))
|
||||
src.print_text("File loaded.")
|
||||
src.temp_file = loadedFile
|
||||
return
|
||||
|
||||
continue
|
||||
|
||||
if (src.master.hd && src.master.hd.root)
|
||||
loadedFile = get_file_name(toLoadName, src.master.hd.root)
|
||||
|
||||
if (istype(loadedFile))
|
||||
src.print_text("File loaded.")
|
||||
src.temp_file = loadedFile
|
||||
return
|
||||
|
||||
src.print_text("Alert: File not found (or invalid).")
|
||||
return
|
||||
|
||||
if("file_save")
|
||||
if (!src.temp_file)
|
||||
src.print_text("Alert: No file to save.")
|
||||
return
|
||||
|
||||
var/toSaveName = "temp"
|
||||
if (command_list.len)
|
||||
toSaveName = dd_list2text(command_list, "")
|
||||
|
||||
for (var/obj/item/disk/data/drive in src.master.contents)
|
||||
if (drive == src.holder || !drive.root)
|
||||
continue
|
||||
|
||||
if (src.temp_file.holder == drive)
|
||||
src.print_text("Alert: File already saved to this drive.")
|
||||
return
|
||||
|
||||
var/datum/computer/file/oldFile = get_file_name(toSaveName, drive.root)
|
||||
if (oldFile)
|
||||
if (istype(oldFile, src.temp_file.type))
|
||||
oldFile.dispose()
|
||||
|
||||
else
|
||||
src.print_text("Alert: File name taken, unable to overwrite.")
|
||||
return
|
||||
|
||||
src.temp_file.name = toSaveName
|
||||
if (drive.root.add_file(src.temp_file.copy_file()))
|
||||
src.print_text("File saved.")
|
||||
return
|
||||
|
||||
src.print_text("Alert: Unable to write to disk.")
|
||||
return
|
||||
|
||||
src.print_text("Alert: No valid destination drive found.")
|
||||
return
|
||||
|
||||
if("file_print")
|
||||
if(!src.temp_file || (!istype(temp_file, /datum/computer/file/text) && !istype(temp_file, /datum/computer/file/record)))
|
||||
src.print_text("Alert: File invalid or missing.")
|
||||
return
|
||||
|
||||
var/to_print = null
|
||||
if(istype(temp_file, /datum/computer/file/record))
|
||||
for(var/a in temp_file:fields)
|
||||
if (temp_file:fields[a])
|
||||
to_print += "[a]=[temp_file:fields[a]]<br>"
|
||||
else
|
||||
to_print += "[a]<br>"
|
||||
else
|
||||
to_print = temp_file:data
|
||||
src.print_text("Sending print command...")
|
||||
var/datum/signal/printsig = new
|
||||
//printsig.encryption = "\ref[netcard]"
|
||||
printsig.data["data"] = to_print
|
||||
printsig.data["title"] = "Printout"
|
||||
|
||||
src.peripheral_command("print",printsig, "\ref[netcard]")
|
||||
|
||||
if("file_run") //to-do
|
||||
src.print_text("Command currently inoperative.")
|
||||
|
||||
else
|
||||
src.send_term_message(text)
|
||||
|
||||
return
|
||||
|
||||
initialize()
|
||||
//src.service_mode = 0
|
||||
src.print_text("Loading TermOS, Revision C<br>Copyright 2046-2053 Thinktronic Systems, LTD.")
|
||||
|
||||
if(src.serv_id) //I guess some jerk rebooted us
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
//termsignal.encryption = "\ref[netcard]"
|
||||
termsignal.data["address_1"] = src.serv_id
|
||||
termsignal.data["command"] = "term_disconnect"
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netcard]")
|
||||
|
||||
src.ping_wait = 0
|
||||
src.disconnect_wait = 0
|
||||
src.attempt_id = null
|
||||
src.serv_id = null
|
||||
src.netcard = find_peripheral("NET_ADAPTER")
|
||||
if(!src.netcard || !istype(src.netcard))
|
||||
src.netcard = find_peripheral("RAD_ADAPTER")
|
||||
if (istype(src.netcard))
|
||||
src.peripheral_command("mode_net", null, "\ref[netcard]")
|
||||
src.print_text("Network card detected.<br>Ready.")
|
||||
else
|
||||
src.netcard = null
|
||||
src.print_text("<font color=red>Error: No network card detected.</font><br>Ready.")
|
||||
else
|
||||
src.print_text("Network card detected.<br>Ready.")
|
||||
|
||||
src.current_folder = src.holder.root
|
||||
if(src.setup_string && src.netcard) //Use setup string as tag for startup server.
|
||||
var/target_tag = src.setup_string
|
||||
var/maybe_netnum = findtext(target_tag, "|")
|
||||
if (maybe_netnum)
|
||||
src.net_number = text2num( copytext(target_tag, maybe_netnum+1) )
|
||||
target_tag = copytext(target_tag, 1, maybe_netnum)
|
||||
src.peripheral_command("subnet[src.net_number]", null, "\ref[src.netcard]")
|
||||
|
||||
src.setup_string = null
|
||||
|
||||
var/obj/target_serv = locate(target_tag)
|
||||
if(istype(target_serv) && hasvar(target_serv,"net_id"))
|
||||
spawn(100)
|
||||
if (target_serv)
|
||||
src.input_text("connect [target_serv:net_id]")
|
||||
|
||||
return
|
||||
|
||||
disk_ejected(var/obj/item/disk/data/thedisk)
|
||||
if(!thedisk)
|
||||
return
|
||||
|
||||
if(current_folder && (current_folder.holder == thedisk))
|
||||
current_folder = src.holding_folder
|
||||
|
||||
if(src.holder == thedisk)
|
||||
src.print_text("<font color=red>System Error: Unable to read system file.</font>")
|
||||
src.master.active_program = null
|
||||
src.master.host_program = null
|
||||
return
|
||||
|
||||
if(src.temp_file && (src.temp_file.holder == thedisk))
|
||||
src.temp_file = null
|
||||
|
||||
return
|
||||
|
||||
proc/send_term_message(var/message, send_file=0)
|
||||
if(!message || !src.serv_id || !netcard)
|
||||
return
|
||||
|
||||
message = strip_html(message)
|
||||
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
//termsignal.encryption = "\ref[netcard]"
|
||||
termsignal.data["address_1"] = src.serv_id
|
||||
termsignal.data["data"] = message
|
||||
termsignal.data["command"] = "term_[send_file ? "file" : "message"]"
|
||||
if (send_file && src.temp_file)
|
||||
termsignal.data_file = src.temp_file.copy_file()
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netcard]")
|
||||
return
|
||||
|
||||
restart()
|
||||
attempt_id = null
|
||||
if(src.serv_id) //I guess some jerk rebooted us
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
//termsignal.encryption = "\ref[netcard]"
|
||||
termsignal.data["address_1"] = src.serv_id
|
||||
termsignal.data["command"] = "term_disconnect"
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netcard]")
|
||||
return
|
||||
|
||||
process()
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(src.ping_wait)
|
||||
src.ping_wait--
|
||||
|
||||
if(src.disconnect_wait > 0)
|
||||
src.disconnect_wait--
|
||||
if(src.disconnect_wait == 0)
|
||||
src.print_text("Timed out. Please retry.")
|
||||
src.serv_id = null
|
||||
src.attempt_id = null
|
||||
|
||||
receive_command(obj/source, command, datum/signal/signal)
|
||||
if((..()) || (!signal))
|
||||
return
|
||||
|
||||
if(command == "card_authed" && src.ping_wait && serv_id)
|
||||
|
||||
var/datum/computer/file/record/udat = new
|
||||
udat.fields["registered"] = signal.data["registered"]
|
||||
udat.fields["assignment"] = signal.data["assignment"]
|
||||
udat.fields["access"] = signal.data["access"]
|
||||
if (!udat.fields["access"] || !udat.fields["assignment"] || !udat.fields["access"])
|
||||
//qdel(udat)
|
||||
udat.dispose()
|
||||
return
|
||||
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
//termsignal.encryption = "\ref[netcard]"
|
||||
termsignal.data["address_1"] = serv_id
|
||||
termsignal.data["command"] = "term_file"
|
||||
termsignal.data["data"] = "login"
|
||||
termsignal.data_file = udat
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netcard]")
|
||||
return
|
||||
|
||||
|
||||
if(!serv_id || signal.data["sender"] != src.serv_id)
|
||||
if(signal.data["command"] == "ping_reply" && src.ping_wait)
|
||||
if(!signal.data["device"] || !signal.data["netid"])
|
||||
return
|
||||
|
||||
var/reply_device = signal.data["device"]
|
||||
var/reply_id = signal.data["netid"]
|
||||
|
||||
src.print_text("<b>P:</b> \[[reply_id]]-TYPE: [reply_device]")
|
||||
|
||||
//oh, somebody trying to connect!
|
||||
else if(signal.data["command"] == "term_connect" && !src.serv_id)
|
||||
if(!attempt_id && signal.data["sender"] && src.auto_accept)
|
||||
src.serv_id = signal.data["sender"]
|
||||
src.disconnect_wait = -1
|
||||
src.print_text("Connection established to [serv_id]!")
|
||||
//well okay but now they need to know we've accepted!
|
||||
if(signal.data["data"] != "noreply")
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
//termsignal.encryption = "\ref[netcard]"
|
||||
termsignal.data["address_1"] = signal.data["sender"]
|
||||
termsignal.data["command"] = "term_connect"
|
||||
termsignal.data["data"] = "noreply"
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netcard]")
|
||||
|
||||
|
||||
else if(signal.data["sender"] == attempt_id)
|
||||
src.attempt_id = null
|
||||
src.serv_id = signal.data["sender"]
|
||||
src.last_serv_id = src.serv_id
|
||||
src.disconnect_wait = -1
|
||||
src.print_text("Connection to [serv_id] successful.")
|
||||
|
||||
if(signal.data["sender"] == src.serv_id)
|
||||
switch(lowertext(signal.data["command"]))
|
||||
if("term_message")
|
||||
var/new_message = signal.data["data"]
|
||||
if(!new_message)
|
||||
return
|
||||
|
||||
switch(lowertext(signal.data["render"]))
|
||||
if("clear") //They want the screen clear before printing
|
||||
src.master.temp = null
|
||||
|
||||
if("multiline") //Oh, they want multiple lines of stuff.
|
||||
new_message = dd_replacetext(new_message, "|n", "<br>]")
|
||||
|
||||
if ("multiline|clear","clear|multiline") //Both of the above!
|
||||
src.master.temp = null
|
||||
new_message = dd_replacetext(new_message, "|n", "<br>]")
|
||||
|
||||
src.print_text("][new_message]")
|
||||
return
|
||||
|
||||
if("term_file") //oh boy, a file!
|
||||
if(!signal.data_file || !istype(signal.data_file))
|
||||
return //oh no the file is bad
|
||||
|
||||
//Will it fit? Check before clearing out our old temp file!
|
||||
if((holder.file_used + signal.data_file.size) > holder.file_amount)
|
||||
src.print_text("Alert: Unable to accept file transfer, disk is full!")
|
||||
return
|
||||
|
||||
if(src.temp_file)
|
||||
//qdel(temp_file) //Clear our old temp file!
|
||||
temp_file.dispose()
|
||||
|
||||
src.temp_file = signal.data_file.copy_file()
|
||||
src.temp_file.name = "temp"
|
||||
src.print_text("Alert: File received from remote host!<br>Valid commands: file_status, file_print")
|
||||
|
||||
if("term_ping")
|
||||
if(signal.data["data"] == "reply")
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
//termsignal.encryption = "\ref[netcard]"
|
||||
termsignal.data["address_1"] = signal.data["sender"]
|
||||
termsignal.data["command"] = "term_ping"
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netcard]")
|
||||
return
|
||||
|
||||
if("term_disconnect")
|
||||
src.serv_id = null
|
||||
src.attempt_id = null
|
||||
|
||||
src.print_text("<b>Connection closed by remote host.</b>")
|
||||
return
|
||||
|
||||
return
|
||||
@@ -0,0 +1,342 @@
|
||||
//CONTENTS
|
||||
//Computer3 Help Record
|
||||
//Computer3 Test script config file
|
||||
//Computer3 halloween event notes.
|
||||
//Robot Factory notes.
|
||||
//Old outpost notes.
|
||||
//Icemoon notes
|
||||
//Drone factory notes
|
||||
|
||||
|
||||
/datum/computer/file/record/c3help
|
||||
name = "helplib"
|
||||
size = 2
|
||||
|
||||
New()
|
||||
..()
|
||||
src.fields["topics"] = "General: cls, cd, dir, root, rename, copy, paste, makedir, title, delete, run, drive, read, print, login, logout, user, time<br>System Functions: help, logging, periph, backprog, accounts, version"
|
||||
src.fields["logging"] = "All console commands are logged in /logs/syslog.text by default. Initlogs re-activates logging if it has been disabled."
|
||||
src.fields["help"] = "Syntax: help \[topic]. Prints help message on topic, if possible.<br>Information stored on external helplib record file. <br> Getting Started: The DIR command will show you a list of files in your current directory. ROOT will return you to the root directory. CD / name will change to that directory (example: cd / bin). To run programs, use RUN filename (example: run commaster) or just type the filename. <br>Type \"help topics\" to see a listing of commands."
|
||||
src.fields["cls"] = "Clears the terminal screen."
|
||||
src.fields["initlogs"] = "Re-activates logging system if disabled."
|
||||
src.fields["dir"] = "Displays contents of current directory."
|
||||
src.fields["version"] = "Display OS version information."
|
||||
src.fields["read"] = "Syntax: \"read \[file name].\" Display contents of text file."
|
||||
src.fields["print"] = "Syntax: \"print \[text].\" Print text to screen."
|
||||
src.fields["rename"] = "Syntax: \"rename \[target file] \[new name].\"<br>Sets name of local file to the new name."
|
||||
src.fields["drive"] = "Syntax: \"drive \[drive id].\"<br>Common Valid IDs: (hd0, fd0).<br>Directory will be set to root of chosen drive"
|
||||
src.fields["root"] = "Sets working directory to root of current drive."
|
||||
src.fields["copy"] = "Syntax: \"copy \[file name].\" File must be in current directory.<br>Marks file for use with Paste command."
|
||||
src.fields["paste"] = "Syntax: \"paste \[new name].\"<br>Pastes copy of marked file, copy will have given name."
|
||||
src.fields["delete"] = "Syntax: \"delete \[file name].\" Deletes supplied file, if possible.<br>Alternative command: Del."
|
||||
src.fields["run"] = "Syntax: \"run \[program name].\" <br>If the string begins with a forward slash /, search will begin at root of current drive. Otherwise, it will begin within the current directory.<br>Valid executable type: .TPROG"
|
||||
src.fields["periph"] = "Syntax: \"periph \[mode] \[ID] \[command] \[signal file]\"<br>Valid modes: (view, command)<br>View or send commands to active peripheral cards."
|
||||
src.fields["cd"] = "Syntax: \"cd \[directory string]\"<br>If the string begins with a forward slash /, search will begin at root of current drive. Otherwise, it will begin within the current directory."
|
||||
src.fields["makedir"] = "Syntax: \"makedir \[new directory name]\"<br>Create a new directory with given name in working directory."
|
||||
src.fields["title"] = "Syntax: \"title \[title name]\"<br>Set name of active drive to given title."
|
||||
src.fields["accounts"] = "This system manages user accounts to support user accountability. Login to log in, logout to log out. A valid ID is required.<br>User data is stored in /logs/sysusr by default."
|
||||
src.fields["login"] = "Syntax: \"login\" Cannot be used with an account still active.<br>This will scan the card(s) in any active card scanner modules."
|
||||
src.fields["logout"] = "Syntax: \"logout\" This will clear the active account and place the system on standby."
|
||||
src.fields["backprog"] = "Syntax: \"backprog \[mode] \[ID]\"<br>Valid modes: (view, kill, switch)<br>Used to view, switch to, and terminate running programs in memory."
|
||||
src.fields["user"] = "Display current user account data, if applicable."
|
||||
src.fields["time"] = "Display current system time."
|
||||
|
||||
|
||||
//Halloween Notes:
|
||||
/datum/computer/file/text/hjam_rlog_1
|
||||
name = "Log 489-C"
|
||||
|
||||
data = {"Specimen ID: D078-48-E
|
||||
<br>File ID: 489-<u> C</u>
|
||||
<br>Researcher: Dr. Horace K Jam
|
||||
<br>Date: 11/14/2048
|
||||
<br>
|
||||
<br>Description: 078-48 is physically a small iron key of unknown
|
||||
origin, though dating tests place it as 75 to 100 years old. 078-48 was
|
||||
first discovered by a mining team in the vicinity of Nanotrasen Space
|
||||
Station #\[REDACTED]. Its anomalous nature was demonstrated upon
|
||||
collision with their mining vehicle, at which point it caused a major hull
|
||||
breach.
|
||||
<br>078-48 has the strange ability to "tunnel" a temporary door through
|
||||
the hulls of space vessels. Upon physical contact with such a structure, if
|
||||
used in the manner of an ordinary key being inserted into a lock, 078-48 will
|
||||
seem to phase into the solid material. Upon attempted removal, the structure
|
||||
will partially give way, acting as though it is a hinged door with 078-48 as
|
||||
its handle. Once 078-48 is removed and the door is closed, the structure will
|
||||
shift back to its initial state as though the door had never existed.
|
||||
<br>
|
||||
<br>Testing Log:
|
||||
<br>Test 01:
|
||||
<br>078-48 is given to Agent L. Wilson. Agent Wilson is instructed to press
|
||||
078-48 into a replica external hull module affixed to the center of test chamber
|
||||
A. 078-38 behaves as expected and the hull module functions as a door until
|
||||
removal.
|
||||
<br>Test 02:
|
||||
<br>078-48 is again given to Agent L. Wilson. Agent Wilson is instructed to press
|
||||
078-48 into a new replica hull module with the twice the thickness of a standard
|
||||
wall. 078-48 successfully creates a doorway, however it only pierces halfway through
|
||||
the wall structure, suggesting a range limit to 078-48's capabilities. Holding the initial
|
||||
door open, Agent Wilson is able to create a second doorway, fully extending the passage
|
||||
though the module. Upon closure of both doors, the hull module reintegrates as expected.
|
||||
<br>Test 03:
|
||||
<br>078-48 is given to Test Subject 0239F. 0239F is instructed to press
|
||||
078-48 into the surface of an iron sphere roughly ten feet in diameter.
|
||||
Upon use, 078-48 creates a rectangular doorway that does not fully pierce the
|
||||
sphere. 0239F is instructed to enter the doorway. After electro-coercion,
|
||||
0239F enters the sphere. 078-48 is then removed by Lab Attendant Moore and
|
||||
the doorway is closed. Upon the reapplication of 078-48, the sphere \[REDACTED].
|
||||
<br>
|
||||
<br>Addendum A:
|
||||
<p>After the events of Test 03, 078-48 has had its hazard rating incremented.
|
||||
All further tests of 078-48 are to be authorized by the Extradimensional Hazard Evaluation
|
||||
Board before proceeding.</p>
|
||||
-Dr. Jam<br>
|
||||
<br>Addendum B:
|
||||
<p>At the behest of the weapon research division, 078-48 has been
|
||||
scheduled for use in a test of the K25 experimental particle emitter.
|
||||
078-48 has been chosen due to interest in the effects such particles
|
||||
may have on its space-time warping abilities.</p>
|
||||
-Dr. Franklin<br>
|
||||
<br>Addendum C:
|
||||
<p>Since its exposure to the K25 emitter, 078-48 has not regained
|
||||
any of the anomalous characteristics warranting its inclusion in study.
|
||||
As such, 078-48 has been reclassified as Decommissioned and is to
|
||||
be disposed of in a manner befitting of an ordinary iron key. As an aside,
|
||||
Dr. Franklin's remaining limbs have not yet regained sensation or fine motor
|
||||
control. Please be more careful when testing E-level objects in the future.</p>
|
||||
-Dr. Jam"}
|
||||
|
||||
/datum/computer/file/text/hjam_rlog_2
|
||||
name = "Log 491-D"
|
||||
|
||||
data = {"Specimen ID: 081-48-K
|
||||
<br>File ID: 491-<u> D</u>
|
||||
<br>Researcher: Dr. Richard L. Northup
|
||||
<br>Date: 12/24/2048
|
||||
<br>
|
||||
<br>Description: 081-48 consists of a luminescent green liquid. 081-48 is extremely
|
||||
toxic if ingested but harmless if correct containment procedures are maintained.
|
||||
<br>Please contact <u> Dr. Northup </u> to requisition the use of 081-48 in a controlled test.
|
||||
<br>081-48 is remarkable for its effects on deceased biological matter.
|
||||
Upon sufficient contact or injection into such matter, 081-48 rapidly \[REDACTED].
|
||||
<br>081-48 and all chemical agents related to its creation should be kept in appropriate, clearly-labeled containers.
|
||||
CAUTION: Release of 081-48 is grounds for immediate scuttling of the research facility under Directive 7-12.
|
||||
<br>
|
||||
<br>Testing Log:
|
||||
<br>Test 01:
|
||||
<br>081-48 is given to Medical Technician F. Jackson. Technician Jackson is instructed to inject
|
||||
081-48 into Test Subject 1013B. Ten minutes after injection, Subject 1013B experiences servere convulsions, followed
|
||||
by clinical death twenty-one minutes later. 1013B's corpse is observered for a period of five hours, 22 minutes, 45 seconds.
|
||||
Test chamber purge systems are activated and the chamber is sterilized.
|
||||
<br>Test 02:
|
||||
<br>081-48 is given to Medical Technician K. Horvitz. Technician Horvitz is instructed to administer
|
||||
25ml of 081-48 solution to Donated Corpse 011-FJ. Technician Horvitz administers solution as expected and is then
|
||||
instructed to leave the chamber. He does not make to the internal airlock, however, as \[REDACTED].
|
||||
Test chamber purge systems are unable to be activated, as the damaged chamber windows could collapse fully.
|
||||
Containment team Gamma-11 is dispatched. Chamber sterilization proceeds as planned.
|
||||
<br>
|
||||
<br>Addendum A:
|
||||
<p>Due to the excessive damages incurred following the escape of 081-48-E-1 and its subsequent discovery of the
|
||||
station morgue, I have been forced to
|
||||
postpone all further tests of 081-48 indefinitely. Furthermore, 081-48's hazard rating has been elevated to
|
||||
the highest possible level.</p>
|
||||
-Dr. Northup<br>
|
||||
<br>Addendum B:
|
||||
<p>This is nothing more than an overreaction. 081-48's potential benefits outweigh its dangers
|
||||
by far. The Institute stands only to gain from this, your attempts at decommissioning such a sample
|
||||
have cost days of valuable research.</p>
|
||||
-Dr. Jam<br>
|
||||
<br>Addendum C:
|
||||
<p>Dr. Jam, the fallout of test 02 almost destroyed not only Outpost Gamma's funding,
|
||||
but almost the station itself. 081-48 is far too dangerous to retain, a release of even a single drop could
|
||||
cause an outbreak and potential EOW scenario. By the authorization of the council, 081-48 is to be decommissioned.</p>
|
||||
-Dr. Northup
|
||||
<br>Addendum D:
|
||||
<p>Despite the best efforts of the decommissioning teams, one container of 081-48 has not yet been located.
|
||||
All personnel are to remain on high alert, contact station HAZSEC teams immediately if 081-48 or its progeny are located.</p>
|
||||
-Dr. Northup"}
|
||||
|
||||
/datum/computer/file/text/hjam_rlog_3
|
||||
name = "Log 492-A"
|
||||
|
||||
data = {"Specimen ID: 082-48-E
|
||||
<br>File ID: 492-<u> A</u>
|
||||
<br>Researcher: Dr. Richard L. Northup
|
||||
<br>Date: 12/25/2048
|
||||
<br>
|
||||
<br>Description: 082-48 consists of a vintage jukebo3*#0()#($*
|
||||
<br><pre> 3893 *#(* $(09 #**** $&&NJFK ,,,11100f4//ief
|
||||
<br> 39jf 3kkk <NM<n fr930 f--j,vm +fpkeo ??Fje
|
||||
<br> #8r83T930___ro BU sT erS-3890-
|
||||
<br>39.,&&&390--,fe.289498fJAM IS R838f0UNNING-300SCARED</pre>
|
||||
<br>
|
||||
<br><center>File Corruption Detected</center>"}
|
||||
|
||||
/datum/computer/file/text/hjam_passlog
|
||||
name = "Passwords"
|
||||
|
||||
data = {"Note to self: Don't let anyone else see this file.
|
||||
<br>
|
||||
<br>Company Intranet:
|
||||
<br>1c3CR34m-1999
|
||||
<br>
|
||||
<br>Company Email:
|
||||
<br>hjam@ntmedrs.org
|
||||
<br>pass: eyEceCr34m
|
||||
<br>
|
||||
<br>Personal Email:
|
||||
<br>neowizrad1999@cheapnets.com
|
||||
<br>pass: icecream
|
||||
<br>
|
||||
<br>Company Gun Locker:
|
||||
<br>54321
|
||||
<br>
|
||||
<br>trying to pitch upgrade to 8 character model 51 alphanumeric locker."}
|
||||
|
||||
/datum/computer/file/text/outpost_rlog_1
|
||||
name = "Log 014"
|
||||
|
||||
data = {"File ID: 014-1-1
|
||||
Researcher: Dr. William K. Mutambara
|
||||
<br>Date: 08/16/2052
|
||||
<br>
|
||||
<br>Scenario: Test Subject 11F will be placed within VR simulation 3.2.5 and observed to determine
|
||||
competency under such extreme conditions. To maintain validity of subject reactions, 11F must not be informed of
|
||||
3.2.5's scenario parameters, instead being lead to believe that the tested disaster is a minor shuttle docking accident.
|
||||
<br>
|
||||
<br>Testing Log:
|
||||
<br>\[0:00:30] Subject 11F successfully virtualized, taking Head of Personnel role on Nanotrasen Installation 11.
|
||||
<br>\[0:08:11] Collision in shuttle bay. 11F moves to mobilize medical response and assess damage. Performance considered commendable.
|
||||
<br>\[0:17:48] Initial sighting of antagonist entities within damaged sector.
|
||||
<br>\[0:21:03] 11F receives reports of antagonist entities, but disregards them. His reaction is disappointing, but expected.
|
||||
<br>\[0:00:00] LOG ERR<pre>0102- A=82 X=5B Y=EF P=B4 S=83
|
||||
<br> *
|
||||
<br>39.,&&&390--,fe.28949IS R838f0U-300ED</pre>
|
||||
\[1:03:29] Simulation terminated due to death of subject.
|
||||
<br>\[1:04:55] Subject 11F not responsive to APA-mandated debriefing session."}
|
||||
|
||||
/datum/computer/file/text/outpost_rlog_2
|
||||
name = "Log 017"
|
||||
|
||||
data = {"File ID: 017-1-4
|
||||
<br>Researcher: Dr. William K. Mutambara
|
||||
<br>Date: 08/23/2052
|
||||
<br>
|
||||
<br>Scenario: Test Subject 19Q will be placed within VR simulation 3.2.7 and observed to determine
|
||||
effect of new revision on subject behavior. 19Q will have cognitive locks enabled to prevent motivation contamination by
|
||||
memories of previous run in simulation.
|
||||
<br>
|
||||
<br>Testing Log:
|
||||
<br>\[0:00:28] Subject virtualized successfully in role of Chief Engineer on Nanotrasen Installation 11.
|
||||
<br>\[0:04:39] 19Q trips while exiting office and impacts his head on a table, losing consciousness.
|
||||
<br>\[0:08:11] Collision in shuttle bay. 19Q fails to respond.
|
||||
<br>\[0:17:48] Initial sighting of antagonist entities within damaged sector.
|
||||
<br>\[0:35:02] Station cat begins to sleep on face of Subject 19Q.
|
||||
<br>\[1:40:21] Simulation terminated due to suffocation death of subject."}
|
||||
|
||||
|
||||
/datum/computer/file/text/icemoon_log1
|
||||
name = "Log 001"
|
||||
|
||||
data = {"File ID: THETA-001
|
||||
<br>User: *SYSTEM
|
||||
<br>Timestamp: 000001
|
||||
<br>
|
||||
<br>###########################
|
||||
<br>Systems diagnostic complete.
|
||||
<br>Computer system booted and ready for usage.
|
||||
<br>Network integrated successfully.
|
||||
<br>###########################
|
||||
<br>"}
|
||||
|
||||
/datum/computer/file/text/icemoon_log2
|
||||
name = "Log 002"
|
||||
|
||||
data = {"File ID: THETA-002
|
||||
<br>User: B.FREDRICKKSEN \[DIRECTOR]
|
||||
<br>Timestamp: 000006
|
||||
<br>
|
||||
<br>Looks like the engineering boys did a pretty good job setting this place up. I don't much care for the lack of decor, but it's not like we're on vacation.
|
||||
It's dark as hell out there from the cloud cover and the atmosphere isn't even breathable, not to mention the freezing temperatures and constant high winds.
|
||||
A wonder they ever managed to build this little piece of home in the first place.
|
||||
<br>
|
||||
<br>Tomorrow we'll begin taking ice core samples from the glacial interior. NT wants us to check out some sort of biological scans that their last probe picked up.
|
||||
<br>"}
|
||||
|
||||
/datum/computer/file/text/icemoon_log3
|
||||
name = "Log 003"
|
||||
|
||||
data = {"File ID: THETA-003
|
||||
<br>User: R.BROWN \[TECHNICIAN]
|
||||
<br>Timestamp: 000006
|
||||
<br>
|
||||
<br>god what a hellhole
|
||||
<br>stuck on this shitty little ice station with 4 other guys and no ladies for six months, oh well at least were being paid creds hand over fist for being here
|
||||
<br>plus i managed to smuggle some wiskey in hahaha gonna need it
|
||||
<br>"}
|
||||
|
||||
/datum/computer/file/text/icemoon_log4
|
||||
name = "Log 004"
|
||||
|
||||
data = {"File ID: THETA-004
|
||||
<br>User: B.FREDRICKKSEN \[DIRECTOR]
|
||||
<br>Timestamp: 000008
|
||||
<br>
|
||||
<br>We discovered some sort of indigenous arachnid lifeform today. Technician Brown's hazard suit is a total loss and he's sustained major frostbite around several puncture wounds,
|
||||
but we've managed to recover something that was caught in his suit. It looks to be a broken-off leg of whatever attacked him, some sort of spider-like creature.
|
||||
<br>
|
||||
<br>Microscopic analysis reveals a crystalline matrix of living cells, functioning together as a colony instead of a single organism. Not unlike a slime mold.
|
||||
<br>They are clearly adapted for living in this environment - they show an extreme tolerance for low temperature environments, though will recoil very quickly from any source of significant heat.
|
||||
The genetic structure of these cells is unlike anything we've ever seen before - we're still trying to figure out what exactly to call them.
|
||||
<br>Further tests will commence soon. We are planning to separate the cells into various cultures for further research."}
|
||||
|
||||
|
||||
/datum/computer/file/record/dronefact_log1
|
||||
name = "SR0210A"
|
||||
|
||||
New()
|
||||
..()
|
||||
|
||||
fields = list("Service Request #02-10A",
|
||||
"Problem description: DRONE WILL NOT STOP FIRING",
|
||||
"IT KEEPS FIRING INTO THE WALL AND IT'S GOING TO BREACH THIS WHOLE DAMN PLACE IF IT DOESN'T STOP",
|
||||
"I TRIED CUTTING THE POWER BUT IT'S STILL GOING",
|
||||
"IT ISN'T RESPONDING TO COMMANDS",
|
||||
"I THINK JENKINS IS DEAD",
|
||||
"Problem status: Resolved",
|
||||
"Technician notes: Maintenance bay evacuated and drone ejected into space.")
|
||||
|
||||
/datum/computer/file/record/dronefact_log2
|
||||
name = "SR0220C"
|
||||
|
||||
New()
|
||||
..()
|
||||
fields = list("Service Request #02-20C",
|
||||
"Problem description: Drone unable to identify targets.",
|
||||
"A more accurate description is that it is unable to identify enemy targets.",
|
||||
"All targets are being mistakenly identified as friendly, even those that",
|
||||
"are actively firing upon and damaging it.",
|
||||
"Problem status: Resolved (effectively)",
|
||||
"Technician notes: Attempts to repair IFF system resulted in all targets",
|
||||
"being mis-identified as threats. Drone destroyed before staff could be",
|
||||
"injured.")
|
||||
|
||||
/datum/computer/file/record/dronefact_log3
|
||||
name = "IRIDIUM"
|
||||
|
||||
New()
|
||||
..()
|
||||
fields = list(" *** CONFIDENTIAL DOCUMENT *** ",
|
||||
" ** TOP EYES ONLY, FOR REAL **",
|
||||
"Project IRIDUM is comprised of three core technologies, all of which",
|
||||
"have been developed from anomalous archeological findings on moon",
|
||||
"LV-0723 (As detailed in incident report 291.53). These technologies",
|
||||
"consist of a powerful projected energy weapon, manifesting as an orb",
|
||||
"of plasma which collapses in a threatening electromagnetic burst shortly",
|
||||
"after removal from a containment field; a range of advanced propulsion",
|
||||
"systems derived from that same form of plasmatic technology; and a",
|
||||
"coffee maker that uses an electrostatically-confined plasma field to",
|
||||
"successfully keep coffee warm without creating a burned flavor.",
|
||||
"",
|
||||
"Two of these technologies are utilized in a 'Y Drone' testbed project,",
|
||||
"built in the frame of the existing Omega-class superheavy drone.")
|
||||
@@ -0,0 +1,512 @@
|
||||
//CONTENTS
|
||||
//Writing/printing program
|
||||
|
||||
|
||||
#define MODE_EDIT 0
|
||||
#define MODE_CONFIG 1
|
||||
#define MODE_SELECT_PRINTER 2
|
||||
|
||||
//Text editor program
|
||||
/datum/computer/file/terminal_program/writewizard
|
||||
name = "WizWrite"
|
||||
size = 2
|
||||
var/tmp/mode = 0
|
||||
var/tmp/connected = 0
|
||||
var/tmp/server_netid = null
|
||||
var/tmp/potential_server_netid = null
|
||||
var/tmp/obj/item/peripheral/network/netCard = null
|
||||
var/list/notelist = list()
|
||||
var/tmp/working_line = 0
|
||||
var/tmp/selected_printer = null
|
||||
var/tmp/list/known_printers = list()
|
||||
var/tmp/printer_status = "???"
|
||||
|
||||
var/setup_acc_filepath = "/logs/sysusr"//Where do we look for login data?
|
||||
|
||||
initialize()
|
||||
src.print_text("WizWrite V3.0")
|
||||
src.connected = 0
|
||||
src.mode = 0
|
||||
src.server_netid = null
|
||||
src.netCard = find_peripheral("NET_ADAPTER")
|
||||
if (src.known_printers)
|
||||
src.known_printers.len = 0
|
||||
else
|
||||
src.known_printers = list()
|
||||
|
||||
//src.print_text("Commands: !view to view note, !new to start new note, !del to remove current line<br>!load to load file, !save to save file.<br>!\[line number] to set current line, !print to print. !quit to quit.<br>Anything else to type a line.")
|
||||
src.print_text(get_help_text())
|
||||
return
|
||||
|
||||
input_text(text)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/list/command_list = parse_string(text)
|
||||
var/command = command_list[1]
|
||||
command_list -= command_list[1]
|
||||
|
||||
if (src.mode != MODE_EDIT)
|
||||
switch(src.mode)
|
||||
if (MODE_CONFIG)
|
||||
switch(lowertext(copytext(command,1,2)))
|
||||
if ("0")
|
||||
src.mode = MODE_EDIT
|
||||
src.print_text("Now editing. !help to list commands.")
|
||||
if ("1")
|
||||
if (src.connected)
|
||||
disconnect_server()
|
||||
src.connected = 0
|
||||
src.master.temp = null
|
||||
src.print_text(get_config_menu())
|
||||
return
|
||||
else
|
||||
if (server_netid)
|
||||
//Attempt to connect to server
|
||||
src.mode = -1
|
||||
connect_printserver(server_netid, 1)
|
||||
if (connected)
|
||||
src.master.temp = null
|
||||
src.print_text("Connection established to \[[server_netid]]!<br>[get_config_menu()]")
|
||||
src.mode = MODE_CONFIG
|
||||
return
|
||||
|
||||
src.print_text("Connection failed.")
|
||||
return
|
||||
else
|
||||
//Attempt to autodetect server & connect
|
||||
src.mode = -1
|
||||
src.print_text("Searching for printserver...")
|
||||
if (ping_server(1))
|
||||
src.print_text("Unable to detect printserver!")
|
||||
src.mode = MODE_CONFIG
|
||||
return
|
||||
|
||||
src.print_text("Printserver detected at \[[potential_server_netid]]<br>Connecting...")
|
||||
connect_printserver(potential_server_netid, 1)
|
||||
|
||||
src.mode = MODE_CONFIG
|
||||
if (connected)
|
||||
src.master.temp = null
|
||||
src.print_text("Connection established to \[[server_netid]]!<br>[get_config_menu()]")
|
||||
return
|
||||
|
||||
src.print_text("Connection failed.")
|
||||
return
|
||||
if ("2")
|
||||
src.mode = -1
|
||||
message_server("command=print&args=index")
|
||||
sleep(8)
|
||||
var/dat = "Known Printers:"
|
||||
if (!src.known_printers || !src.known_printers.len)
|
||||
dat += "<br> \[__] No printers known."
|
||||
|
||||
else
|
||||
var/leadingZeroCount = length("[src.known_printers.len]")
|
||||
for (var/kp_index=1, kp_index <= src.known_printers.len, kp_index++)
|
||||
dat += "<br> \[[add_zero("[kp_index]",leadingZeroCount)]] [src.known_printers[kp_index]]"
|
||||
dat += "<br> \[A] Print to All."
|
||||
|
||||
src.master.temp = null
|
||||
src.print_text("[dat]<br> (0) Return")
|
||||
src.mode = MODE_SELECT_PRINTER
|
||||
return
|
||||
|
||||
if (MODE_SELECT_PRINTER)
|
||||
if (lowertext(command) == "a")
|
||||
src.selected_printer = "!all!"
|
||||
else
|
||||
var/printerNumber = round(text2num(command))
|
||||
if (printerNumber == 0)
|
||||
src.mode = MODE_CONFIG
|
||||
src.master.temp = null
|
||||
src.print_text(get_config_menu())
|
||||
return
|
||||
|
||||
if (printerNumber < 1 || printerNumber > src.known_printers.len)
|
||||
return
|
||||
|
||||
src.selected_printer = src.known_printers[printerNumber]
|
||||
|
||||
src.mode = MODE_CONFIG
|
||||
src.master.temp = null
|
||||
src.print_text("Printer set.<br>[get_config_menu()]")
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
if(dd_hasprefix(command, "!"))
|
||||
switch(lowertext(command))
|
||||
if ("!view","!v")
|
||||
if(src.notelist.len)
|
||||
var/to_print = null
|
||||
for(var/t=1, t <= notelist.len, t++)
|
||||
to_print += "\[[add_zero("[t]",3)]] [notelist[t]] [notelist[ notelist[t] ] ? "=[notelist[ notelist[t] ]]": null]<br>"
|
||||
src.print_text(to_print)
|
||||
else
|
||||
src.print_text("No document loaded.")
|
||||
if ("!new","!n")
|
||||
src.notelist = new
|
||||
src.print_text("Current note cleared")
|
||||
|
||||
if ("!del","!d")
|
||||
if(src.working_line && src.working_line < notelist.len)
|
||||
src.notelist.Cut(src.working_line,src.working_line+1)
|
||||
src.print_text("Line [src.working_line] removed.")
|
||||
else
|
||||
src.print_text("Line [src.notelist.len] removed.")
|
||||
src.notelist.len--
|
||||
src.working_line = 0
|
||||
|
||||
if ("!load","!l")
|
||||
var/file_name = ckey(dd_list2text(command_list, " "))
|
||||
|
||||
if (!file_name)
|
||||
src.print_text("Syntax: \"!load \[file name]\"")
|
||||
return
|
||||
|
||||
var/datum/computer/file/record/to_load = get_file_name(file_name, src.holding_folder)
|
||||
if(!to_load || (!istype(to_load) && !istype(to_load, /datum/computer/file/text)))
|
||||
src.print_text("Error: File not found (Or invalid).")
|
||||
return
|
||||
|
||||
if (istype(to_load, /datum/computer/file/text))
|
||||
var/datum/computer/file/text/loadText = to_load
|
||||
src.notelist = dd_text2list(loadText.data, "<br>")
|
||||
else
|
||||
src.notelist = to_load.fields.Copy()
|
||||
|
||||
src.print_text("Load successful.")
|
||||
|
||||
if ("!save", "!s")
|
||||
var/new_name = strip_html(dd_list2text(command_list, " "))
|
||||
new_name = copytext(new_name, 1, 16)
|
||||
|
||||
if(!new_name)
|
||||
src.print_text("Syntax: \"!save \[file name]\"")
|
||||
return
|
||||
|
||||
var/datum/computer/file/record/saved = get_file_name(new_name, src.holding_folder)
|
||||
if(saved && !istype(saved) || get_folder_name(new_name, src.holding_folder))
|
||||
src.print_text("Error: Name in use.")
|
||||
return
|
||||
|
||||
if(is_name_invalid(new_name))
|
||||
src.print_text("Error: Invalid character in name.")
|
||||
return
|
||||
|
||||
if(saved && istype(saved))
|
||||
saved.fields = src.notelist.Copy()
|
||||
else
|
||||
saved = new /datum/computer/file/record
|
||||
saved.name = new_name
|
||||
saved.fields = src.notelist.Copy()
|
||||
if(!src.holding_folder.add_file(saved))
|
||||
//qdel(saved)
|
||||
saved.dispose()
|
||||
src.print_text("Error: Cannot save to disk.")
|
||||
return
|
||||
|
||||
src.print_text("File saved.")
|
||||
|
||||
if ("!help", "!h")
|
||||
src.print_text(get_help_text())
|
||||
|
||||
if ("!print", "!p")
|
||||
var/print_name = strip_html(dd_list2text(command_list, " "))
|
||||
print_name = copytext(print_name, 1, 16)
|
||||
|
||||
var/networked = (src.connected && src.selected_printer)
|
||||
|
||||
if(!print_name && !networked)
|
||||
src.print_text("<b>Syntax:</b> \"!print \[title].\" Prints current loaded document")
|
||||
return
|
||||
|
||||
if(!notelist.len)
|
||||
src.print_text("<b>Error:</b> No document loaded.")
|
||||
|
||||
else
|
||||
if (networked && !src.network_print(print_name))
|
||||
src.print_text("Print instruction sent.")
|
||||
else
|
||||
if (local_print(print_name))
|
||||
src.print_text("<b>Error:</b> No printer detected.")
|
||||
else
|
||||
src.print_text("Print instruction sent.")
|
||||
|
||||
if ("!config","!c","!conf")
|
||||
src.mode = MODE_CONFIG
|
||||
src.master.temp = null
|
||||
src.print_text("[get_config_menu()]")
|
||||
|
||||
return
|
||||
|
||||
if ("!quit","!q")
|
||||
src.print_text("Quitting...")
|
||||
if (connected)
|
||||
connected = 0
|
||||
disconnect_server()
|
||||
src.master.unload_program(src)
|
||||
return
|
||||
|
||||
else
|
||||
var/line_num = round( text2num( copytext(command, 2) ) )
|
||||
if(isnull(line_num))
|
||||
src.print_text("Unknown command.")
|
||||
return
|
||||
if(line_num <= 0)
|
||||
src.working_line = 0
|
||||
src.print_text("Now working from end of document.")
|
||||
return
|
||||
|
||||
if(line_num > notelist.len)
|
||||
src.print_text("Line outside of document scope.")
|
||||
return
|
||||
|
||||
src.working_line = line_num
|
||||
src.print_text("\[[add_zero("[working_line]",3)]] [notelist[working_line]]")
|
||||
return
|
||||
|
||||
else
|
||||
var/adding = strip_html(text)
|
||||
var/adding_associative = null
|
||||
src.print_text("\[[add_zero("[working_line == 0 ? notelist.len+1 : working_line]",3)]] [adding]")
|
||||
//src.oldnote = src.note
|
||||
var/split_point = findtext(adding, "=")
|
||||
if (split_point)
|
||||
adding_associative = copytext(adding, split_point+1)
|
||||
adding = copytext(adding, 1, split_point)
|
||||
|
||||
adding = copytext(adding, 1, 256)
|
||||
if(src.working_line && src.working_line <= notelist.len)
|
||||
src.notelist[src.working_line] = "[adding]"
|
||||
if (adding_associative)
|
||||
src.notelist["[adding]"] = adding_associative
|
||||
src.working_line++
|
||||
if(src.working_line > notelist.len)
|
||||
src.working_line = 0
|
||||
else
|
||||
src.notelist += "[adding]"
|
||||
if (adding_associative)
|
||||
src.notelist["[adding]"] = adding_associative
|
||||
|
||||
src.master.add_fingerprint(usr)
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
|
||||
receive_command(obj/source, command, datum/signal/signal)
|
||||
if ((..()) || (!signal))
|
||||
return
|
||||
|
||||
if (!connected)
|
||||
if (signal.data["command"] == "ping_reply" && !potential_server_netid)
|
||||
|
||||
if (signal.data["device"] == "PNET_MAINFRAME" && signal.data["sender"] && ishex(signal.data["sender"]))
|
||||
potential_server_netid = signal.data["sender"]
|
||||
return
|
||||
|
||||
else if (signal.data["command"] == "term_connect")
|
||||
server_netid = ckey(signal.data["sender"])
|
||||
connected = 1
|
||||
potential_server_netid = null
|
||||
if(signal.data["data"] != "noreply")
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
|
||||
termsignal.data["address_1"] = signal.data["sender"]
|
||||
termsignal.data["command"] = "term_connect"
|
||||
termsignal.data["device"] = "SRV_TERMINAL"
|
||||
termsignal.data["data"] = "noreply"
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netCard]")
|
||||
|
||||
return
|
||||
else
|
||||
if (signal.data["sender"] != server_netid)
|
||||
return
|
||||
|
||||
if (!server_netid)
|
||||
connected = 0
|
||||
return
|
||||
|
||||
switch(lowertext(signal.data["command"]))
|
||||
if ("term_message","term_file")
|
||||
var/list/data = params2list(signal.data["data"])
|
||||
if(!data || !data["command"])
|
||||
return
|
||||
|
||||
var/list/commandList = dd_text2list(data["command"], "|n")
|
||||
if (!commandList || !commandList.len)
|
||||
return
|
||||
|
||||
switch (commandList[1])
|
||||
if ("print_index")
|
||||
if (commandList.len > 1)
|
||||
known_printers = commandList.Copy(2)
|
||||
else
|
||||
known_printers = list()
|
||||
|
||||
if ("print_status")
|
||||
if (commandList.len > 1)
|
||||
printer_status = commandList[2]
|
||||
else
|
||||
printer_status = "???"
|
||||
return
|
||||
|
||||
if ("term_disconnect")
|
||||
src.connected = 0
|
||||
src.server_netid = null
|
||||
src.print_text("Connection closed by printserver.")
|
||||
|
||||
if("term_ping")
|
||||
if(signal.data["data"] == "reply")
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
|
||||
termsignal.data["address_1"] = signal.data["sender"]
|
||||
termsignal.data["command"] = "term_ping"
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netCard]")
|
||||
|
||||
|
||||
return
|
||||
|
||||
proc
|
||||
connect_printserver(var/address, delayCaller=0)
|
||||
if (connected || !netCard)
|
||||
return 1
|
||||
|
||||
var/datum/signal/signal = get_free_signal()
|
||||
|
||||
signal.data["address_1"] = address
|
||||
signal.data["command"] = "term_connect"
|
||||
signal.data["device"] = "SRV_TERMINAL"
|
||||
var/datum/computer/file/user_data/user_data = get_user_data()
|
||||
var/datum/computer/file/record/udat = null
|
||||
if (istype(user_data))
|
||||
udat = new
|
||||
|
||||
var/userid = format_username(user_data.registered)
|
||||
|
||||
udat.fields["userid"] = userid
|
||||
udat.fields["access"] = list2params(user_data.access)
|
||||
if (!udat.fields["access"] || !udat.fields["userid"])
|
||||
// qdel(udat)
|
||||
udat.dispose()
|
||||
return 1
|
||||
|
||||
udat.fields["service"] = "print"
|
||||
|
||||
if (udat)
|
||||
signal.data_file = udat
|
||||
|
||||
src.peripheral_command("transmit", signal, "\ref[netCard]")
|
||||
if (delayCaller)
|
||||
sleep(8)
|
||||
return 0
|
||||
|
||||
return 0
|
||||
|
||||
disconnect_server()
|
||||
if (!server_netid || !netCard)
|
||||
return 1
|
||||
|
||||
var/datum/signal/signal = get_free_signal()
|
||||
|
||||
signal.data["address_1"] = server_netid
|
||||
signal.data["command"] = "term_disconnect"
|
||||
|
||||
src.peripheral_command("transmit", signal, "\ref[netCard]")
|
||||
|
||||
return 0
|
||||
|
||||
ping_server(delayCaller=0)
|
||||
if (connected || !netCard)
|
||||
return 1
|
||||
|
||||
potential_server_netid = null
|
||||
src.peripheral_command("ping", null, "\ref[netCard]")
|
||||
|
||||
if (delayCaller)
|
||||
sleep(8)
|
||||
return (potential_server_netid == null)
|
||||
|
||||
return 0
|
||||
|
||||
message_server(var/message, var/datum/computer/file/toSend)
|
||||
if (!connected || !server_netid || !netCard || !message)
|
||||
return 1
|
||||
|
||||
var/datum/signal/termsignal = get_free_signal()
|
||||
|
||||
termsignal.data["address_1"] = server_netid
|
||||
termsignal.data["data"] = message
|
||||
termsignal.data["command"] = "term_message"
|
||||
if (toSend)
|
||||
termsignal.data_file = toSend
|
||||
|
||||
src.peripheral_command("transmit", termsignal, "\ref[netCard]")
|
||||
return 0
|
||||
|
||||
network_print(var/print_title = "Printout")
|
||||
if (!connected || !netCard || !selected_printer || !server_netid || !src.notelist || !src.notelist.len)
|
||||
return 1
|
||||
|
||||
var/datum/computer/file/record/printRecord = new
|
||||
printRecord.fields = src.notelist.Copy()
|
||||
if (print_title)
|
||||
printRecord.fields.Insert(1, "title=[print_title]")
|
||||
printRecord.name = "printout"
|
||||
|
||||
if (selected_printer == "!all!")
|
||||
message_server("command=print&args=printall", printRecord)
|
||||
else
|
||||
message_server("command=print&args=print [selected_printer]", printRecord)
|
||||
return 0
|
||||
|
||||
local_print(var/print_title = "Printout")
|
||||
var/obj/item/peripheral/printcard = find_peripheral("LAR_PRINTER")
|
||||
if(!printcard || !src.notelist || !src.notelist.len)
|
||||
return 1
|
||||
|
||||
var/datum/signal/signal = get_free_signal()
|
||||
signal.data["data"] = dd_list2text(src.notelist, "<br>")
|
||||
signal.data["title"] = print_title
|
||||
src.peripheral_command("print",signal, "\ref[printcard]")
|
||||
return 0
|
||||
|
||||
get_user_data()
|
||||
var/datum/computer/folder/accdir = src.holder.root
|
||||
if(src.master.host_program) //Check where the OS is, preferably.
|
||||
accdir = src.master.host_program.holder.root
|
||||
|
||||
var/datum/computer/file/user_data/target = parse_file_directory(setup_acc_filepath, accdir)
|
||||
if(target && istype(target))
|
||||
return target
|
||||
|
||||
return null
|
||||
|
||||
get_config_menu()
|
||||
if (src.connected && src.server_netid)
|
||||
var/confText = "Currently connected to printserver \[[src.server_netid]]"
|
||||
confText += "<br> (1) Disconnect"
|
||||
confText += "<br> (2) Select Printer"
|
||||
confText += "<br> (0) Back"
|
||||
return confText
|
||||
|
||||
return "No printserver connection<br> (1) Connect<br> (0) Back"
|
||||
|
||||
get_help_text()
|
||||
|
||||
var/help_text = {"Commands:
|
||||
<br> \"!view\" to view note
|
||||
<br> \"!del\" to remove current line
|
||||
<br> \"!\[integer]" to set current line
|
||||
<br> \"!save \[name]\" to save note
|
||||
<br> \"!load \[name]\" to load note
|
||||
<br> \"!print\" to print current note.
|
||||
<br> \"!config\" to configure network printing.
|
||||
<br> Anything else to type."}
|
||||
return help_text
|
||||
|
||||
#undef MODE_EDIT
|
||||
#undef MODE_CONFIG
|
||||
#undef MODE_SELECT_PRINTER
|
||||
Reference in New Issue
Block a user