Updates Part Twelve

This commit is contained in:
Unknown
2019-04-14 14:38:30 -04:00
parent 042720823a
commit 7594c28f21
56 changed files with 1074 additions and 205 deletions
@@ -29,6 +29,8 @@
filedesc = "Camera Monitoring"
nanomodule_path = /datum/nano_module/camera_monitor
program_icon_state = "cameras"
program_key_state = "generic_key"
program_menu_icon = "search"
extended_desc = "This program allows remote access to the camera system. Some camera networks may have additional access requirements."
size = 12
available_on_ntnet = 1
@@ -7,6 +7,8 @@
filedesc = "Computer Configuration Tool"
extended_desc = "This program allows configuration of computer's hardware"
program_icon_state = "generic"
program_key_state = "generic_key"
program_menu_icon = "gear"
unsendable = 1
undeletable = 1
size = 4
@@ -3,6 +3,8 @@
filedesc = "Email Client"
extended_desc = "This program may be used to log in into your email account."
program_icon_state = "generic"
program_key_state = "generic_key"
program_menu_icon = "mail-closed"
size = 7
requires_ntnet = 1
available_on_ntnet = 1
@@ -1,10 +1,10 @@
#define MAX_TEXTFILE_LENGTH 128000 // 512GQ file
/datum/computer_file/program/filemanager
filename = "filemanager"
filedesc = "NTOS File Manager"
extended_desc = "This program allows management of files."
program_icon_state = "generic"
program_key_state = "generic_key"
program_menu_icon = "folder-collapsed"
size = 8
requires_ntnet = 0
available_on_ntnet = 0
@@ -89,9 +89,9 @@
return 1
var/oldtext = html_decode(F.stored_data)
oldtext = replacetext(oldtext, "\[editorbr\]", "\n")
oldtext = replacetext(oldtext, "\[br\]", "\n")
var/newtext = sanitize(replacetext(input(usr, "Editing file [open_file]. You may use most tags used in paper formatting:", "Text Editor", oldtext) as message|null, "\n", "\[editorbr\]"), MAX_TEXTFILE_LENGTH)
var/newtext = sanitize(replacetext(input(usr, "Editing file [open_file]. You may use most tags used in paper formatting:", "Text Editor", oldtext) as message|null, "\n", "\[br\]"), MAX_TEXTFILE_LENGTH)
if(!newtext)
return
@@ -204,5 +204,4 @@
ui = new(user, src, ui_key, "file_manager.tmpl", "NTOS File Manager", 575, 700, state = state)
ui.auto_update_layout = 1
ui.set_initial_data(data)
ui.open()
#undef MAX_TEXTFILE_LENGTH
ui.open()
@@ -6,6 +6,7 @@
filename = "arcadec" // File name, as shown in the file browser program.
filedesc = "Unknown Game" // User-Friendly name. In this case, we will generate a random name in constructor.
program_icon_state = "game" // Icon state of this program's screen.
program_menu_icon = "script"
extended_desc = "Fun for the whole family! Probably not an AAA title, but at least you can download it on the corporate network.." // A nice description.
size = 5 // Size in GQ. Integers only. Smaller sizes should be used for utility/low use programs (like this one), while large sizes are for important programs.
requires_ntnet = 0 // This particular program does not require NTNet network conectivity...
@@ -0,0 +1,191 @@
/*
In reply to this set of comments on lib_machines.dm:
// TODO: Make this an actual /obj/machinery/computer that can be crafted from circuit boards and such
// It is August 22nd, 2012... This TODO has already been here for months.. I wonder how long it'll last before someone does something about it.
The answer was five and a half years -ZeroBits
*/
/datum/computer_file/program/library
filename = "library"
filedesc = "Library"
extended_desc = "This program can be used to view e-books from an external archive."
program_icon_state = "word"
program_key_state = "atmos_key"
program_menu_icon = "note"
size = 6
requires_ntnet = 1
available_on_ntnet = 1
nanomodule_path = /datum/nano_module/library
/datum/nano_module/library
name = "Library"
var/error_message = ""
var/current_book
var/obj/machinery/libraryscanner/scanner
var/sort_by = "id"
/datum/nano_module/library/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
var/list/data = host.initial_data()
if(error_message)
data["error"] = error_message
else if(current_book)
data["current_book"] = current_book
else
var/list/all_entries[0]
establish_old_db_connection()
if(!dbcon_old.IsConnected())
error_message = "Unable to contact External Archive. Please contact your system administrator for assistance."
else
var/DBQuery/query = dbcon_old.NewQuery("SELECT id, author, title, category FROM library ORDER BY "+sanitizeSQL(sort_by))
query.Execute()
while(query.NextRow())
all_entries.Add(list(list(
"id" = query.item[1],
"author" = query.item[2],
"title" = query.item[3],
"category" = query.item[4]
)))
data["book_list"] = all_entries
data["scanner"] = istype(scanner)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "library.tmpl", "Library Program", 575, 700, state = state)
ui.auto_update_layout = 1
ui.set_initial_data(data)
ui.open()
/datum/nano_module/library/Topic(href, href_list)
if(..())
return 1
if(href_list["viewbook"])
view_book(href_list["viewbook"])
return 1
if(href_list["viewid"])
view_book(sanitizeSQL(input("Enter USBN:") as num|null))
return 1
if(href_list["closebook"])
current_book = null
return 1
if(href_list["connectscanner"])
if(!nano_host())
return 1
for(var/d in GLOB.cardinal)
var/obj/machinery/libraryscanner/scn = locate(/obj/machinery/libraryscanner, get_step(nano_host(), d))
if(scn && scn.anchored)
scanner = scn
return 1
if(href_list["uploadbook"])
if(!scanner || !scanner.anchored)
scanner = null
error_message = "Hardware Error: No scanner detected. Unable to access cache."
return 1
if(!scanner.cache)
error_message = "Interface Error: Scanner cache does not contain any data. Please scan a book."
return 1
var/obj/item/weapon/book/B = scanner.cache
if(B.unique)
error_message = "Interface Error: Cached book is copy-protected."
return 1
//B.SetName(input(usr, "Enter Book Title", "Title", B.name) as text|null)
B.author = input(usr, "Enter Author Name", "Author", B.author) as text|null
if(!B.author)
B.author = "Anonymous"
else if(lowertext(B.author) == "edgar allen poe" || lowertext(B.author) == "edgar allan poe")
error_message = "User Error: Upload something original."
return 1
if(!B.title)
B.title = "Untitled"
var/choice = input(usr, "Upload [B.name] by [B.author] to the External Archive?") in list("Yes", "No")
if(choice == "Yes")
establish_old_db_connection()
if(!dbcon_old.IsConnected())
error_message = "Network Error: Connection to the Archive has been severed."
return 1
var/upload_category = input(usr, "Upload to which category?") in list("Fiction", "Non-Fiction", "Reference", "Religion")
var/sqltitle = sanitizeSQL(B.name)
var/sqlauthor = sanitizeSQL(B.author)
var/sqlcontent = sanitizeSQL(B.dat)
var/sqlcategory = sanitizeSQL(upload_category)
var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO library (author, title, content, category) VALUES ('[sqlauthor]', '[sqltitle]', '[sqlcontent]', '[sqlcategory]')")
if(!query.Execute())
to_chat(usr, query.ErrorMsg())
error_message = "Network Error: Unable to upload to the Archive. Contact your system Administrator for assistance."
return 1
else
log_and_message_admins("has uploaded the book titled [B.name], [length(B.dat)] signs")
log_game("[usr.name]/[usr.key] has uploaded the book titled [B.name], [length(B.dat)] signs")
alert("Upload Complete.")
return 1
return 0
if(href_list["printbook"])
if(!current_book)
error_message = "Software Error: Unable to print; book not found."
return 1
//PRINT TO BINDER
if(!nano_host())
return 1
for(var/d in GLOB.cardinal)
var/obj/machinery/bookbinder/bndr = locate(/obj/machinery/bookbinder, get_step(nano_host(), d))
if(bndr && bndr.anchored)
var/obj/item/weapon/book/B = new(bndr.loc)
//B.SetName(current_book["title"])
B.title = current_book["title"]
B.author = current_book["author"]
B.dat = current_book["content"]
B.icon_state = "book[rand(1,7)]"
B.desc = current_book["author"]+", "+current_book["title"]+", "+"USBN "+current_book["id"]
bndr.visible_message("\The [bndr] whirs as it prints and binds a new book.")
return 1
//Regular printing
print_text("<i>Author: [current_book["author"]]<br>USBN: [current_book["id"]]</i><br><h3>[current_book["title"]]</h3><br>[current_book["content"]]", usr)
return 1
if(href_list["sortby"])
sort_by = href_list["sortby"]
return 1
if(href_list["reseterror"])
if(error_message)
current_book = null
scanner = null
sort_by = "id"
error_message = ""
return 1
/datum/nano_module/library/proc/view_book(var/id)
if(current_book || !id)
return 0
var/sqlid = sanitizeSQL(id)
establish_old_db_connection()
if(!dbcon_old.IsConnected())
error_message = "Network Error: Connection to the Archive has been severed."
return 1
var/DBQuery/query = dbcon_old.NewQuery("SELECT * FROM library WHERE id=[sqlid]")
query.Execute()
while(query.NextRow())
current_book = list(
"id" = query.item[1],
"author" = query.item[2],
"title" = query.item[3],
"content" = query.item[4]
)
break
return 1
@@ -3,6 +3,8 @@
filedesc = "NTNet/ExoNet News Browser"
extended_desc = "This program may be used to view and download news articles from the network."
program_icon_state = "generic"
program_key_state = "generic_key"
program_menu_icon = "contact"
size = 4
requires_ntnet = 1
available_on_ntnet = 1
@@ -2,6 +2,8 @@
filename = "ntndownloader"
filedesc = "NTNet Software Download Tool"
program_icon_state = "generic"
program_key_state = "generic_key"
program_menu_icon = "arrowthickstop-1-s"
extended_desc = "This program allows downloads of software from official NT repositories"
unsendable = 1
undeletable = 1
@@ -16,6 +18,7 @@
var/download_completion = 0 //GQ of downloaded data.
var/download_netspeed = 0
var/downloaderror = ""
var/list/downloads_queue[0]
/datum/computer_file/program/ntnetdownload/kill_program()
..()
@@ -25,20 +28,14 @@
downloaderror = ""
ui_header = "downloader_finished.gif"
/datum/computer_file/program/ntnetdownload/proc/begin_file_download(var/filename)
if(downloaded_file)
return 0
var/datum/computer_file/program/PRG = ntnet_global.find_ntnet_file_by_name(filename)
if(!PRG || !istype(PRG))
return 0
// Attempting to download antag only program, but without having emagged computer. No.
if(PRG.available_on_syndinet && !computer_emagged)
return 0
if(!computer || !computer.hard_drive || !computer.hard_drive.try_store_file(PRG))
if(!check_file_download(filename))
return 0
ui_header = "downloader_running.gif"
@@ -55,6 +52,22 @@
downloaded_file = PRG.clone()
/datum/computer_file/program/ntnetdownload/proc/check_file_download(var/filename)
//returns 1 if file can be downloaded, returns 0 if download prohibited
var/datum/computer_file/program/PRG = ntnet_global.find_ntnet_file_by_name(filename)
if(!PRG || !istype(PRG))
return 0
// Attempting to download antag only program, but without having emagged computer. No.
if(PRG.available_on_syndinet && !computer_emagged)
return 0
if(!computer || !computer.hard_drive || !computer.hard_drive.try_store_file(PRG))
return 0
return 1
/datum/computer_file/program/ntnetdownload/proc/abort_file_download()
if(!downloaded_file)
return
@@ -79,6 +92,10 @@
return
if(download_completion >= downloaded_file.size)
complete_file_download()
if(downloads_queue.len > 0)
begin_file_download(downloads_queue[1])
downloads_queue.Remove(downloads_queue[1])
// Download speed according to connectivity state. NTNet server is assumed to be on unlimited speed so we're limited by our local connectivity
download_netspeed = 0
// Speed defines are found in misc.dm
@@ -97,6 +114,11 @@
if(href_list["PRG_downloadfile"])
if(!downloaded_file)
begin_file_download(href_list["PRG_downloadfile"])
else if(check_file_download(href_list["PRG_downloadfile"]) && !downloads_queue.Find(href_list["PRG_downloadfile"]) && downloaded_file.filename != href_list["PRG_downloadfile"])
downloads_queue += href_list["PRG_downloadfile"]
return 1
if(href_list["PRG_removequeued"])
downloads_queue.Remove(href_list["PRG_removequeued"])
return 1
if(href_list["PRG_reseterror"])
if(downloaderror)
@@ -129,40 +151,46 @@
// This IF cuts on data transferred to client, so i guess it's worth it.
if(prog.downloaderror) // Download errored. Wait until user resets the program.
data["error"] = prog.downloaderror
else if(prog.downloaded_file) // Download running. Wait please..
if(prog.downloaded_file) // Download running. Wait please..
data["downloadname"] = prog.downloaded_file.filename
data["downloaddesc"] = prog.downloaded_file.filedesc
data["downloadsize"] = prog.downloaded_file.size
data["downloadspeed"] = prog.download_netspeed
data["downloadcompletion"] = round(prog.download_completion, 0.1)
else // No download running, pick file.
data["disk_size"] = my_computer.hard_drive.max_capacity
data["disk_used"] = my_computer.hard_drive.used_capacity
var/list/all_entries[0]
for(var/datum/computer_file/program/P in ntnet_global.available_station_software)
// Only those programs our user can run will show in the list
if(!P.can_run(user) && P.requires_access_to_download)
continue
all_entries.Add(list(list(
data["disk_size"] = my_computer.hard_drive.max_capacity
data["disk_used"] = my_computer.hard_drive.used_capacity
var/list/all_entries[0]
for(var/datum/computer_file/program/P in ntnet_global.available_station_software)
// Only those programs our user can run will show in the list
if(!P.can_run(user) && P.requires_access_to_download)
continue
all_entries.Add(list(list(
"filename" = P.filename,
"filedesc" = P.filedesc,
"fileinfo" = P.extended_desc,
"size" = P.size,
"icon" = P.program_menu_icon
)))
data["hackedavailable"] = 0
if(prog.computer_emagged) // If we are running on emagged computer we have access to some "bonus" software
var/list/hacked_programs[0]
for(var/datum/computer_file/program/P in ntnet_global.available_antag_software)
data["hackedavailable"] = 1
hacked_programs.Add(list(list(
"filename" = P.filename,
"filedesc" = P.filedesc,
"fileinfo" = P.extended_desc,
"size" = P.size
"size" = P.size,
"icon" = P.program_menu_icon
)))
data["hackedavailable"] = 0
if(prog.computer_emagged) // If we are running on emagged computer we have access to some "bonus" software
var/list/hacked_programs[0]
for(var/datum/computer_file/program/P in ntnet_global.available_antag_software)
data["hackedavailable"] = 1
hacked_programs.Add(list(list(
"filename" = P.filename,
"filedesc" = P.filedesc,
"fileinfo" = P.extended_desc,
"size" = P.size
)))
data["hacked_programs"] = hacked_programs
data["hacked_programs"] = hacked_programs
data["downloadable_programs"] = all_entries
if(prog.downloads_queue.len > 0)
data["downloads_queue"] = prog.downloads_queue
data["downloadable_programs"] = all_entries
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "ntnet_downloader.tmpl", "NTNet Download Program", 575, 700, state = state)
@@ -2,6 +2,8 @@
filename = "ntnrc_client"
filedesc = "NTNet Relay Chat Client"
program_icon_state = "command"
program_key_state = "med_key"
program_menu_icon = "comment"
extended_desc = "This program allows communication over NTNRC network"
size = 8
requires_ntnet = 1
@@ -5,6 +5,8 @@ var/global/nttransfer_uid = 0
filedesc = "NTNet P2P Transfer Client"
extended_desc = "This program allows for simple file transfer via direct peer to peer connection."
program_icon_state = "comm_logs"
program_key_state = "generic_key"
program_menu_icon = "transferthick-e-w"
size = 7
requires_ntnet = 1
requires_ntnet_feature = NTNET_PEERTOPEER
@@ -29,6 +31,7 @@ var/global/nttransfer_uid = 0
..()
/datum/computer_file/program/nttransfer/process_tick()
..()
// Server mode
if(provided_file)
for(var/datum/computer_file/program/nttransfer/C in connected_clients)
@@ -0,0 +1,236 @@
/datum/computer_file/program/wordprocessor
filename = "wordprocessor"
filedesc = "NanoWord"
extended_desc = "This program allows the editing and preview of text documents."
program_icon_state = "word"
program_key_state = "atmos_key"
size = 4
requires_ntnet = 0
available_on_ntnet = 1
nanomodule_path = /datum/nano_module/program/computer_wordprocessor/
var/browsing
var/open_file
var/loaded_data
var/error
var/is_edited
/datum/computer_file/program/wordprocessor/proc/get_file(var/filename)
var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive
if(!HDD)
return
var/datum/computer_file/data/F = HDD.find_file_by_name(filename)
if(!istype(F))
return
return F
/datum/computer_file/program/wordprocessor/proc/open_file(var/filename)
var/datum/computer_file/data/F = get_file(filename)
if(F)
open_file = F.filename
loaded_data = F.stored_data
return 1
/datum/computer_file/program/wordprocessor/proc/save_file(var/filename)
var/datum/computer_file/data/F = get_file(filename)
if(!F) //try to make one if it doesn't exist
F = create_file(filename, loaded_data)
return !isnull(F)
var/datum/computer_file/data/backup = F.clone()
var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive
if(!HDD)
return
HDD.remove_file(F)
F.stored_data = loaded_data
F.calculate_size()
if(!HDD.store_file(F))
HDD.store_file(backup)
return 0
is_edited = 0
return 1
/datum/computer_file/program/wordprocessor/proc/create_file(var/newname, var/data = "")
if(!newname)
return
var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive
if(!HDD)
return
if(get_file(newname))
return
var/datum/computer_file/data/F = new/datum/computer_file/data()
F.filename = newname
F.filetype = "TXT"
F.stored_data = data
F.calculate_size()
if(HDD.store_file(F))
return F
/datum/computer_file/program/wordprocessor/Topic(href, href_list)
if(..())
return 1
if(href_list["PRG_txtrpeview"])
show_browser(usr,"<HTML><HEAD><TITLE>[open_file]</TITLE></HEAD>[pencode2html(loaded_data)]</BODY></HTML>", "window=[open_file]")
return 1
if(href_list["PRG_taghelp"])
to_chat(usr, "<span class='notice'>The hologram of a googly-eyed paper clip helpfully tells you:</span>")
var/help = {"
\[br\] : Creates a linebreak.
\[center\] - \[/center\] : Centers the text.
\[h1\] - \[/h1\] : First level heading.
\[h2\] - \[/h2\] : Second level heading.
\[h3\] - \[/h3\] : Third level heading.
\[b\] - \[/b\] : Bold.
\[i\] - \[/i\] : Italic.
\[u\] - \[/u\] : Underlined.
\[small\] - \[/small\] : Decreases the size of the text.
\[large\] - \[/large\] : Increases the size of the text.
\[field\] : Inserts a blank text field, which can be filled later. Useful for forms.
\[date\] : Current station date.
\[time\] : Current station time.
\[list\] - \[/list\] : Begins and ends a list.
\[*\] : A list item.
\[hr\] : Horizontal rule.
\[table\] - \[/table\] : Creates table using \[row\] and \[cell\] tags.
\[grid\] - \[/grid\] : Table without visible borders, for layouts.
\[row\] - New table row.
\[cell\] - New table cell.
\[logo\] - Inserts NT logo image.
\[bluelogo\] - Inserts blue NT logo image.
\[solcrest\] - Inserts SCG crest image.
\[terraseal\] - Inserts TCC seal"}
to_chat(usr, help)
return 1
if(href_list["PRG_closebrowser"])
browsing = 0
return 1
if(href_list["PRG_backtomenu"])
error = null
return 1
if(href_list["PRG_loadmenu"])
browsing = 1
return 1
if(href_list["PRG_openfile"])
. = 1
if(is_edited)
if(alert("Would you like to save your changes first?",,"Yes","No") == "Yes")
save_file(open_file)
browsing = 0
if(!open_file(href_list["PRG_openfile"]))
error = "I/O error: Unable to open file '[href_list["PRG_openfile"]]'."
if(href_list["PRG_newfile"])
. = 1
if(is_edited)
if(alert("Would you like to save your changes first?",,"Yes","No") == "Yes")
save_file(open_file)
var/newname = sanitize(input(usr, "Enter file name:", "New File") as text|null)
if(!newname)
return 1
var/datum/computer_file/data/F = create_file(newname)
if(F)
open_file = F.filename
loaded_data = ""
return 1
else
error = "I/O error: Unable to create file '[href_list["PRG_saveasfile"]]'."
if(href_list["PRG_saveasfile"])
. = 1
var/newname = sanitize(input(usr, "Enter file name:", "Save As") as text|null)
if(!newname)
return 1
var/datum/computer_file/data/F = create_file(newname, loaded_data)
if(F)
open_file = F.filename
else
error = "I/O error: Unable to create file '[href_list["PRG_saveasfile"]]'."
return 1
if(href_list["PRG_savefile"])
. = 1
if(!open_file)
open_file = sanitize(input(usr, "Enter file name:", "Save As") as text|null)
if(!open_file)
return 0
if(!save_file(open_file))
error = "I/O error: Unable to save file '[open_file]'."
return 1
if(href_list["PRG_editfile"])
var/oldtext = html_decode(loaded_data)
oldtext = replacetext(oldtext, "\[br\]", "\n")
var/newtext = sanitize(replacetext(input(usr, "Editing file '[open_file]'. You may use most tags used in paper formatting:", "Text Editor", oldtext) as message|null, "\n", "\[br\]"), MAX_TEXTFILE_LENGTH)
if(!newtext)
return
loaded_data = newtext
is_edited = 1
return 1
if(href_list["PRG_printfile"])
. = 1
if(!computer.nano_printer)
error = "Missing Hardware: Your computer does not have the required hardware to complete this operation."
return 1
if(!computer.nano_printer.print_text(pencode2html(loaded_data)))
error = "Hardware error: Printer was unable to print the file. It may be out of paper."
return 1
/datum/nano_module/program/computer_wordprocessor
name = "Word Processor"
/datum/nano_module/program/computer_wordprocessor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
var/list/data = host.initial_data()
var/datum/computer_file/program/wordprocessor/PRG
PRG = program
var/obj/item/weapon/computer_hardware/hard_drive/HDD
var/obj/item/weapon/computer_hardware/hard_drive/portable/RHDD
if(PRG.error)
data["error"] = PRG.error
if(PRG.browsing)
data["browsing"] = PRG.browsing
if(!PRG.computer || !PRG.computer.hard_drive)
data["error"] = "I/O ERROR: Unable to access hard drive."
else
HDD = PRG.computer.hard_drive
var/list/files[0]
for(var/datum/computer_file/F in HDD.stored_files)
if(F.filetype == "TXT")
files.Add(list(list(
"name" = F.filename,
"size" = F.size
)))
data["files"] = files
RHDD = PRG.computer.portable_drive
if(RHDD)
data["usbconnected"] = 1
var/list/usbfiles[0]
for(var/datum/computer_file/F in RHDD.stored_files)
if(F.filetype == "TXT")
usbfiles.Add(list(list(
"name" = F.filename,
"size" = F.size,
)))
data["usbfiles"] = usbfiles
else if(PRG.open_file)
data["filedata"] = pencode2html(PRG.loaded_data)
data["filename"] = PRG.is_edited ? "[PRG.open_file]*" : PRG.open_file
else
data["filedata"] = pencode2html(PRG.loaded_data)
data["filename"] = "UNNAMED"
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "word_processor.tmpl", "Word Processor", 575, 700, state = state)
ui.auto_update_layout = 1
ui.set_initial_data(data)
ui.open()