Initial Commit

This commit is contained in:
Tobba
2016-03-06 20:52:14 +01:00
commit b181d0b552
4325 changed files with 579453 additions and 0 deletions
+782
View File
@@ -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()
+291
View File
@@ -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
+317
View File
@@ -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
+291
View File
@@ -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
+213
View File
@@ -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 : "&lt;not set&gt;"]</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'>&lt;not set&gt;</a>"
dat += "<br>"
dat += "<b>Action:</b> <a href='?src=\ref[src];action=1'>[filter_action ? filter_action : "&lt;not set&gt;"]</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 : "&lt;not set&gt;"]</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 ("&#39;")
var/newString
while (command_stream.len)
if (command_stream[1] == "\'" || command_stream[1] == "&#39;")
command_stream.Cut(1,2)
break
else if (dd_hassuffix(command_stream[1], "&#39;"))
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
+712
View File
@@ -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>&emsp;[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>&emsp;[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
+898
View File
@@ -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>&emsp;[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>&emsp;[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
+162
View File
@@ -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
+574
View File
@@ -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
+342
View File
@@ -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.")
+512
View File
@@ -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