firsthit-lib_machines

This commit is contained in:
Letter N
2020-12-31 16:46:40 +08:00
parent 57f7b3948b
commit 56789c5924
18 changed files with 871 additions and 589 deletions
+133 -127
View File
@@ -25,12 +25,13 @@
var/title
var/category = "Any"
var/author
var/SQLquery
clockwork = TRUE //it'd look weird
var/search_page = 0
COOLDOWN_DECLARE(library_visitor_topic_cooldown)
clockwork = TRUE
/obj/machinery/computer/libraryconsole/ui_interact(mob/user)
. = ..()
var/dat = "" // <META HTTP-EQUIV='Refresh' CONTENT='10'>
var/list/dat = list() // <META HTTP-EQUIV='Refresh' CONTENT='10'>
switch(screenstate)
if(0)
dat += "<h2>Search Settings</h2><br>"
@@ -43,13 +44,48 @@
dat += "<font color=red><b>ERROR</b>: Unable to contact External Archive. Please contact your system administrator for assistance.</font><BR>"
else if(QDELETED(user))
return
else if(!SQLquery)
dat += "<font color=red><b>ERROR</b>: Malformed search request. Please contact your system administrator for assistance.</font><BR>"
else
dat += "<table>"
dat += "<tr><td>AUTHOR</td><td>TITLE</td><td>CATEGORY</td><td>SS<sup>13</sup>BN</td></tr>"
var/datum/DBQuery/query_library_list_books = SSdbcore.NewQuery(SQLquery)
var/SQLsearch = "isnull(deleted) AND "
if(category == "Any")
SQLsearch += "author LIKE '%[author]%' AND title LIKE '%[title]%'"
else
SQLsearch += "author LIKE '%[author]%' AND title LIKE '%[title]%' AND category='[category]'"
var/bookcount = 0
var/booksperpage = 20
var/datum/db_query/query_library_count_books = SSdbcore.NewQuery({"
SELECT COUNT(id) FROM [format_table_name("library")]
WHERE isnull(deleted)
AND author LIKE CONCAT('%',:author,'%')
AND title LIKE CONCAT('%',:title,'%')
AND (:category = 'Any' OR category = :category)
"}, list("author" = author, "title" = title, "category" = category))
if(!query_library_count_books.warn_execute())
qdel(query_library_count_books)
return
if(query_library_count_books.NextRow())
bookcount = text2num(query_library_count_books.item[1])
qdel(query_library_count_books)
if(bookcount > booksperpage)
dat += "<b>Page: </b>"
var/pagecount = 1
var/list/pagelist = list()
while(bookcount > 0)
pagelist += "<a href='?src=[REF(src)];bookpagecount=[pagecount - 1]'>[pagecount == search_page + 1 ? "<b>\[[pagecount]\]</b>" : "\[[pagecount]\]"]</a>"
bookcount -= booksperpage
pagecount++
dat += pagelist.Join(" | ")
search_page = text2num(search_page)
var/datum/db_query/query_library_list_books = SSdbcore.NewQuery({"
SELECT author, title, category, id
FROM [format_table_name("library")]
WHERE isnull(deleted)
AND author LIKE CONCAT('%',:author,'%')
AND title LIKE CONCAT('%',:title,'%')
AND (:category = 'Any' OR category = :category)
LIMIT :skip, :take
"}, list("author" = author, "title" = title, "category" = category, "skip" = booksperpage * search_page, "take" = booksperpage))
if(!query_library_list_books.Execute())
dat += "<font color=red><b>ERROR</b>: Unable to retrieve book listings. Please contact your system administrator for assistance.</font><BR>"
else
@@ -65,12 +101,15 @@
dat += "</table><BR>"
dat += "<A href='?src=[REF(src)];back=1'>\[Go Back\]</A><BR>"
var/datum/browser/popup = new(user, "publiclibrary", name, 600, 400)
popup.set_content(dat)
popup.set_content(jointext(dat, ""))
popup.open()
/obj/machinery/computer/libraryconsole/Topic(href, href_list)
if(!COOLDOWN_FINISHED(src, library_visitor_topic_cooldown))
return
COOLDOWN_START(src, library_visitor_topic_cooldown, 1 SECONDS)
. = ..()
if(..())
if(.)
usr << browse(null, "window=publiclibrary")
onclose(usr, "publiclibrary")
return
@@ -81,29 +120,24 @@
title = sanitize(newtitle)
else
title = null
title = sanitizeSQL(title)
if(href_list["setcategory"])
var/newcategory = input("Choose a category to search for:") in list("Any", "Fiction", "Non-Fiction", "Adult", "Reference", "Religion")
if(newcategory)
category = sanitize(newcategory)
else
category = "Any"
category = sanitizeSQL(category)
if(href_list["setauthor"])
var/newauthor = input("Enter an author to search for:") as text|null
if(newauthor)
author = sanitize(newauthor)
else
author = null
author = sanitizeSQL(author)
if(href_list["search"])
SQLquery = "SELECT author, title, category, id FROM [format_table_name("library")] WHERE isnull(deleted) AND "
if(category == "Any")
SQLquery += "author LIKE '%[author]%' AND title LIKE '%[title]%'"
else
SQLquery += "author LIKE '%[author]%' AND title LIKE '%[title]%' AND category='[category]'"
screenstate = 1
if(href_list["bookpagecount"])
search_page = text2num(href_list["bookpagecount"])
if(href_list["back"])
screenstate = 0
@@ -120,39 +154,6 @@
var/getdate
var/duedate
/*
* Cachedbook datum
*/
/datum/cachedbook // Datum used to cache the SQL DB books locally in order to achieve a performance gain.
var/id
var/title
var/author
var/category
GLOBAL_LIST(cachedbooks) // List of our cached book datums
/proc/load_library_db_to_cache()
if(GLOB.cachedbooks)
return
if(!SSdbcore.Connect())
return
GLOB.cachedbooks = list()
var/datum/DBQuery/query_library_cache = SSdbcore.NewQuery("SELECT id, author, title, category FROM [format_table_name("library")] WHERE isnull(deleted)")
if(!query_library_cache.Execute())
qdel(query_library_cache)
return
while(query_library_cache.NextRow())
var/datum/cachedbook/newbook = new()
newbook.id = query_library_cache.item[1]
newbook.author = query_library_cache.item[2]
newbook.title = query_library_cache.item[3]
newbook.category = query_library_cache.item[4]
GLOB.cachedbooks += newbook
qdel(query_library_cache)
#define PRINTER_COOLDOWN 60
/*
@@ -165,11 +166,15 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
/obj/machinery/computer/libraryconsole/bookmanagement
name = "book inventory management console"
desc = "Librarian's command station."
screenstate = 0 // 0 - Main Menu, 1 - Inventory, 2 - Checked Out, 3 - Check Out a Book
verb_say = "beeps"
verb_ask = "beeps"
verb_exclaim = "beeps"
pass_flags = PASSTABLE
circuit = /obj/item/circuitboard/computer/libraryconsole
var/screenstate = 0 // 0 - Main Menu, 1 - Inventory, 2 - Checked Out, 3 - Check Out a Book
var/arcanecheckout = 0
var/buffer_book
var/buffer_mob
@@ -178,33 +183,17 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
var/list/inventory = list()
var/checkoutperiod = 5 // In minutes
var/obj/machinery/libraryscanner/scanner // Book scanner that will be used when uploading books to the Archive
var/list/libcomp_menu
var/page = 1 //current page of the external archives
var/cooldown = 0
var/printer_cooldown = 0
COOLDOWN_DECLARE(library_console_topic_cooldown)
/obj/machinery/computer/libraryconsole/bookmanagement/proc/build_library_menu()
if(libcomp_menu)
return
load_library_db_to_cache()
if(!GLOB.cachedbooks)
return
libcomp_menu = list("")
for(var/i in 1 to GLOB.cachedbooks.len)
var/datum/cachedbook/C = GLOB.cachedbooks[i]
var/page = round(i/250)+1
if (libcomp_menu.len < page)
libcomp_menu.len = page
libcomp_menu[page] = ""
libcomp_menu[page] += "<tr><td>[C.author]</td><td>[C.title]</td><td>[C.category]</td><td><A href='?src=[REF(src)];targetid=[C.id]'>\[Order\]</A></td></tr>\n"
/obj/machinery/computer/libraryconsole/bookmanagement/Initialize()
/obj/machinery/computer/bookmanagement/Initialize()
. = ..()
if(circuit)
circuit.name = "Book Inventory Management Console (Machine Board)"
circuit.build_path = /obj/machinery/computer/libraryconsole/bookmanagement
circuit.build_path = /obj/machinery/computer/bookmanagement
/obj/machinery/computer/libraryconsole/bookmanagement/ui_interact(mob/user)
/obj/machinery/computer/bookmanagement/ui_interact(mob/user)
. = ..()
var/dat = "" // <META HTTP-EQUIV='Refresh' CONTENT='10'>
switch(screenstate)
@@ -258,17 +247,37 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
dat += "<A href='?src=[REF(src)];switchscreen=0'>(Return to main menu)</A><BR>"
if(4)
dat += "<h3>External Archive</h3>"
build_library_menu()
if(!GLOB.cachedbooks)
if(!SSdbcore.Connect())
dat += "<font color=red><b>ERROR</b>: Unable to contact External Archive. Please contact your system administrator for assistance.</font>"
else
var/booksperpage = 50
var/pagecount
var/datum/db_query/query_library_count_books = SSdbcore.NewQuery("SELECT COUNT(id) FROM [format_table_name("library")] WHERE isnull(deleted)")
if(!query_library_count_books.Execute())
qdel(query_library_count_books)
return
if(query_library_count_books.NextRow())
pagecount = CEILING(text2num(query_library_count_books.item[1]) / booksperpage, 1)
qdel(query_library_count_books)
var/list/booklist = list()
var/datum/db_query/query_library_get_books = SSdbcore.NewQuery({"
SELECT id, author, title, category
FROM [format_table_name("library")]
WHERE isnull(deleted)
LIMIT :skip, :take
"}, list("skip" = booksperpage * (page - 1), "take" = booksperpage))
if(!query_library_get_books.Execute())
qdel(query_library_get_books)
return
while(query_library_get_books.NextRow())
booklist += "<tr><td>[query_library_get_books.item[2]]</td><td>[query_library_get_books.item[3]]</td><td>[query_library_get_books.item[4]]</td><td><A href='?src=[REF(src)];targetid=[query_library_get_books.item[1]]'>\[Order\]</A></td></tr>\n"
dat += "<A href='?src=[REF(src)];orderbyid=1'>(Order book by SS<sup>13</sup>BN)</A><BR><BR>"
dat += "<table>"
dat += "<tr><td>AUTHOR</td><td>TITLE</td><td>CATEGORY</td><td></td></tr>"
dat += libcomp_menu[clamp(page,1,libcomp_menu.len)]
dat += "<tr><td><A href='?src=[REF(src)];page=[(max(1,page-1))]'>&lt;&lt;&lt;&lt;</A></td> <td></td> <td></td> <td><span style='text-align:right'><A href='?src=[REF(src)];page=[(min(libcomp_menu.len,page+1))]'>&gt;&gt;&gt;&gt;</A></span></td></tr>"
dat += jointext(booklist, "")
dat += "<tr><td><A href='?src=[REF(src)];page=[max(1,page-1)]'>&lt;&lt;&lt;&lt;</A></td> <td></td> <td></td> <td><span style='text-align:right'><A href='?src=[REF(src)];page=[min(pagecount,page+1)]'>&gt;&gt;&gt;&gt;</A></span></td></tr>"
dat += "</table>"
qdel(query_library_get_books)
dat += "<BR><A href='?src=[REF(src)];switchscreen=0'>(Return to main menu)</A><BR>"
if(5)
dat += "<H3>Upload a New Title</H3>"
@@ -315,39 +324,33 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
popup.set_content(dat)
popup.open()
/obj/machinery/computer/libraryconsole/bookmanagement/proc/findscanner(viewrange)
/obj/machinery/computer/bookmanagement/proc/findscanner(viewrange)
for(var/obj/machinery/libraryscanner/S in range(viewrange, get_turf(src)))
return S
return null
/obj/machinery/computer/libraryconsole/bookmanagement/proc/print_forbidden_lore(mob/user)
var/spook = pick("blood", "brass")
var/turf/T = get_turf(src)
if(spook == "blood")
new /obj/item/melee/cultblade/dagger(T)
else
new /obj/item/clockwork/slab(T)
/obj/machinery/computer/bookmanagement/proc/print_forbidden_lore(mob/user)
new /obj/item/melee/cultblade/dagger(get_turf(src))
to_chat(user, "<span class='warning'>Your sanity barely endures the seconds spent in the vault's browsing window. The only thing to remind you of this when you stop browsing is a sinister dagger sitting on the desk. You don't even remember where it came from...</span>")
user.visible_message("<span class='warning'>[user] stares at the blank screen for a few moments, [user.p_their()] expression frozen in fear. When [user.p_they()] finally awaken[user.p_s()] from it, [user.p_they()] look[user.p_s()] a lot older.</span>", 2)
to_chat(user, "<span class='warning'>Your sanity barely endures the seconds spent in the vault's browsing window. The only thing to remind you of this when you stop browsing is a [spook == "blood" ? "sinister dagger" : "strange metal tablet"] sitting on the desk. You don't even remember where it came from...</span>")
user.visible_message("[user] stares at the blank screen for a few moments, [user.p_their()] expression frozen in fear. When [user.p_they()] finally awaken[user.p_s()] from it, [user.p_they()] look[user.p_s()] a lot older.", 2)
/obj/machinery/computer/libraryconsole/bookmanagement/attackby(obj/item/W, mob/user, params)
/obj/machinery/computer/bookmanagement/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/barcodescanner))
var/obj/item/barcodescanner/scanner = W
scanner.computer = src
to_chat(user, "[scanner]'s associated machine has been set to [src].")
audible_message("[src] lets out a low, short blip.")
to_chat(user, "<span class='notice'>[scanner]'s associated machine has been set to [src].</span>")
audible_message("<span class='hear'>[src] lets out a low, short blip.</span>")
else
return ..()
/obj/machinery/computer/libraryconsole/bookmanagement/emag_act(mob/user)
. = ..()
if(!density || obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
return TRUE
/obj/machinery/computer/bookmanagement/emag_act(mob/user)
if(density && !(obj_flags & EMAGGED))
obj_flags |= EMAGGED
/obj/machinery/computer/libraryconsole/bookmanagement/Topic(href, href_list)
/obj/machinery/computer/bookmanagement/Topic(href, href_list)
if(!COOLDOWN_FINISHED(src, library_console_topic_cooldown))
return
COOLDOWN_START(src, library_console_topic_cooldown, 1 SECONDS)
if(..())
usr << browse(null, "window=library")
onclose(usr, "library")
@@ -385,7 +388,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
if(checkoutperiod < 1)
checkoutperiod = 1
if(href_list["editbook"])
buffer_book = stripped_input(usr, "Enter the book's title:")
buffer_book = stripped_input(usr, "Enter the book's title:", max_length = 45)
if(href_list["editmob"])
buffer_mob = stripped_input(usr, "Enter the recipient's name:", max_length = MAX_NAME_LEN)
if(href_list["checkout"])
@@ -404,7 +407,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
if(b && istype(b))
inventory.Remove(b)
if(href_list["setauthor"])
var/newauthor = stripped_input(usr, "Enter the author's name: ")
var/newauthor = stripped_input(usr, "Enter the author's name: ", max_length = 45)
if(newauthor)
scanner.cache.author = newauthor
if(href_list["setcategory"])
@@ -419,14 +422,11 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
if (!SSdbcore.Connect())
alert("Connection to Archive has been severed. Aborting.")
else
var/sqltitle = sanitizeSQL(scanner.cache.name)
var/sqlauthor = sanitizeSQL(scanner.cache.author)
var/sqlcontent = sanitizeSQL(scanner.cache.dat)
var/sqlcategory = sanitizeSQL(upload_category)
var/sqlckey = sanitizeSQL(usr.ckey)
var/msg = "[key_name(usr)] has uploaded the book titled [scanner.cache.name], [length(scanner.cache.dat)] signs"
var/datum/DBQuery/query_library_upload = SSdbcore.NewQuery("INSERT INTO [format_table_name("library")] (author, title, content, category, ckey, datetime, round_id_created) VALUES ('[sqlauthor]', '[sqltitle]', '[sqlcontent]', '[sqlcategory]', '[sqlckey]', Now(), '[GLOB.round_id]')")
var/datum/db_query/query_library_upload = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("library")] (author, title, content, category, ckey, datetime, round_id_created)
VALUES (:author, :title, :content, :category, :ckey, Now(), :round_id)
"}, list("title" = scanner.cache.name, "author" = scanner.cache.author, "content" = scanner.cache.dat, "category" = upload_category, "ckey" = usr.ckey, "round_id" = GLOB.round_id))
if(!query_library_upload.Execute())
qdel(query_library_upload)
alert("Database error encountered uploading to Archive")
@@ -439,7 +439,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
if(!GLOB.news_network)
alert("No news network found on station. Aborting.")
var/channelexists = 0
for(var/datum/news/feed_channel/FC in GLOB.news_network.network_channels)
for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels)
if(FC.channel_name == "Nanotrasen Book Club")
channelexists = 1
break
@@ -448,7 +448,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
GLOB.news_network.SubmitArticle(scanner.cache.dat, "[scanner.cache.name]", "Nanotrasen Book Club", null)
alert("Upload complete. Your uploaded title is now available on station newscasters.")
if(href_list["orderbyid"])
if(cooldown > world.time)
if(printer_cooldown > world.time)
say("Printer unavailable. Please allow a short time before attempting to print.")
else
var/orderid = input("Enter your order:") as num|null
@@ -457,14 +457,17 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
href_list["targetid"] = num2text(orderid)
if(href_list["targetid"])
var/sqlid = sanitizeSQL(href_list["targetid"])
var/id = href_list["targetid"]
if (!SSdbcore.Connect())
alert("Connection to Archive has been severed. Aborting.")
if(cooldown > world.time)
if(printer_cooldown > world.time)
say("Printer unavailable. Please allow a short time before attempting to print.")
else
cooldown = world.time + PRINTER_COOLDOWN
var/datum/DBQuery/query_library_print = SSdbcore.NewQuery("SELECT * FROM [format_table_name("library")] WHERE id=[sqlid] AND isnull(deleted)")
printer_cooldown = world.time + PRINTER_COOLDOWN
var/datum/db_query/query_library_print = SSdbcore.NewQuery(
"SELECT * FROM [format_table_name("library")] WHERE id=:id AND isnull(deleted)",
list("id" = id)
)
if(!query_library_print.Execute())
qdel(query_library_print)
say("PRINTER ERROR! Failed to print document (0x0000000F)")
@@ -480,24 +483,24 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
B.author = author
B.dat = content
B.icon_state = "book[rand(1,8)]"
visible_message("[src]'s printer hums as it produces a completely bound book. How did it do that?")
visible_message("<span class='notice'>[src]'s printer hums as it produces a completely bound book. How did it do that?</span>")
break
qdel(query_library_print)
if(href_list["printbible"])
if(cooldown < world.time)
if(printer_cooldown < world.time)
var/obj/item/storage/book/bible/B = new /obj/item/storage/book/bible(src.loc)
if(GLOB.bible_icon_state && GLOB.bible_item_state)
if(GLOB.bible_icon_state && GLOB.bible_inhand_icon_state)
B.icon_state = GLOB.bible_icon_state
B.item_state = GLOB.bible_item_state
B.inhand_icon_state = GLOB.bible_inhand_icon_state
B.name = GLOB.bible_name
B.deity_name = GLOB.deity
cooldown = world.time + PRINTER_COOLDOWN
printer_cooldown = world.time + PRINTER_COOLDOWN
else
say("Printer currently unavailable, please wait a moment.")
if(href_list["printposter"])
if(cooldown < world.time)
if(printer_cooldown < world.time)
new /obj/item/poster/random_official(src.loc)
cooldown = world.time + PRINTER_COOLDOWN
printer_cooldown = world.time + PRINTER_COOLDOWN
else
say("Printer currently unavailable, please wait a moment.")
add_fingerprint(usr)
@@ -521,7 +524,10 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
else
return ..()
/obj/machinery/libraryscanner/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/machinery/libraryscanner/attack_hand(mob/user)
. = ..()
if(.)
return
usr.set_machine(src)
var/dat = "" // <META HTTP-EQUIV='Refresh' CONTENT='10'>
if(cache)
@@ -577,21 +583,21 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
return ..()
/obj/machinery/bookbinder/proc/bind_book(mob/user, obj/item/paper/P)
if(stat)
if(machine_stat)
return
if(busy)
to_chat(user, "<span class='warning'>The book binder is busy. Please wait for completion of previous operation.</span>")
return
if(!user.transferItemToLoc(P, src))
return
user.visible_message("[user] loads some paper into [src].", "You load some paper into [src].")
audible_message("[src] begins to hum as it warms up its printing drums.")
user.visible_message("<span class='notice'>[user] loads some paper into [src].</span>", "<span class='notice'>You load some paper into [src].</span>")
audible_message("<span class='hear'>[src] begins to hum as it warms up its printing drums.</span>")
busy = TRUE
sleep(rand(200,400))
busy = FALSE
if(P)
if(!stat)
visible_message("[src] whirs as it prints and binds a new book.")
if(!machine_stat)
visible_message("<span class='notice'>[src] whirs as it prints and binds a new book.</span>")
var/obj/item/book/B = new(src.loc)
B.dat = P.info
B.name = "Print Job #" + "[rand(100, 999)]"