mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2025-12-18 22:31:47 +00:00
* Removes comparisons to true and false * Update .github/CONTRIBUTING.md Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> --------- Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
598 lines
22 KiB
Plaintext
598 lines
22 KiB
Plaintext
///Defines how many player books appear on the player book archive TGUI tab
|
|
#define LIBRARY_BOOKS_PER_PAGE 25
|
|
///Login state for our computer, this state grants full access to functions
|
|
#define LOGIN_FULL 1
|
|
///Login state for our computer, this state grants basic access to functions
|
|
#define LOGIN_PUBLIC 2
|
|
///Wait time before printing another book, used to prevent spam
|
|
#define PRINTING_COOLDOWN (5 SECONDS)
|
|
|
|
/**
|
|
* # Library Computer
|
|
*
|
|
* This is the player facing machine that handles all library functions
|
|
*
|
|
* This holds all procs for handling book checkins/checkout, book fines, book obj creation/modification
|
|
* the object also holds static lists for book inventory and checkouts. NO SQL CALLS OR QUERIES ARE MADE HERE, all
|
|
* of those are handled by the global library catalog that we will reference, and it should stay that way :)
|
|
*/
|
|
/obj/machinery/computer/library
|
|
name = "Library Computer"
|
|
anchored = TRUE
|
|
density = TRUE
|
|
icon_keyboard = null
|
|
icon_screen = "computer_on"
|
|
icon = 'icons/obj/library.dmi'
|
|
icon_state = "computer"
|
|
|
|
//We define a required access only to lock library specific actions like ordering/managing books to librarian access+
|
|
req_one_access = list(ACCESS_LIBRARY)
|
|
///Page Number for going through player book archives
|
|
var/archive_page_num = 1
|
|
///report category_id we have selected
|
|
var/selected_report
|
|
///Total number of pages for the parameters have set for our booklist
|
|
var/num_pages = 0
|
|
///total inventoried books, used for setting book library IDs
|
|
var/total_books = 0
|
|
///list for storing player inputs and selections, helpful for cutting down on single variable declarations
|
|
var/datum/library_user_data/user_data = new()
|
|
///This list temporarily stores the player books we grab from the DB in datums, we only update it when we need to for performance reasons
|
|
var/list/cached_booklist = list()
|
|
///Static List of borrowbook datums, used to track book checkouts acrossed the library system
|
|
var/static/list/checkouts = list()
|
|
///Static List of book datums to track what books the librarian has added to the library inventory
|
|
var/static/list/inventory = list()
|
|
///How Long a book is allowed to be checked out for
|
|
var/checkoutperiod = 15 MINUTES
|
|
///Wait period for printing books
|
|
var/print_cooldown = 5 SECONDS
|
|
|
|
|
|
/obj/machinery/computer/library/Initialize(mapload)
|
|
. = ..()
|
|
populate_booklist(async = FALSE)
|
|
//since ui_data screws up when SQL calls are made inside it,
|
|
//we must populate our booklist before ui_act is called for the first time
|
|
|
|
/obj/machinery/computer/library/attack_ai(mob/user)
|
|
return attack_hand(user)
|
|
|
|
/obj/machinery/computer/library/attack_hand(mob/user)
|
|
if(..())
|
|
return
|
|
ui_interact(user)
|
|
|
|
/obj/machinery/computer/library/attack_ghost(mob/user)
|
|
ui_interact(user)
|
|
|
|
/obj/machinery/computer/library/attackby(obj/item/O, mob/user, params)
|
|
if(istype(O, /obj/item/book))
|
|
select_book(O)
|
|
return
|
|
if(istype(O, /obj/item/barcodescanner))
|
|
var/obj/item/barcodescanner/B = O
|
|
if(!B.connect(src))
|
|
playsound(src, 'sound/machines/synth_no.ogg', 15, TRUE)
|
|
to_chat(user, "<span class='warning'>ERROR: No Connection Established!</span>")
|
|
return
|
|
to_chat(user, "<span class='notice'>Barcode Scanner Successfully Connected to Computer.</span>")
|
|
audible_message("[src] lets out a low, short blip.", hearing_distance = 2)
|
|
playsound(B, 'sound/machines/terminal_select.ogg', 10, TRUE)
|
|
return
|
|
if(istype(O, /obj/item/card/id))
|
|
var/obj/item/card/id/ID = O //at some point, this should be moved over to its own proc (select_patron()???)
|
|
if(ID.registered_name)
|
|
user_data.patron_name = ID.registered_name
|
|
else
|
|
user_data.patron_name = null
|
|
user_data.patron_account = null //account number should reset every scan so we don't accidently have an account number but no name
|
|
playsound(src, 'sound/machines/synth_no.ogg', 15, TRUE)
|
|
to_chat(user, "<span class='notice'>ERROR: No name detected!</span>")
|
|
return //no point in continuing if the ID card has no associated name!
|
|
playsound(src, 'sound/items/scannerbeep.ogg', 15, TRUE)
|
|
if(ID.associated_account_number)
|
|
user_data.patron_account = ID.associated_account_number
|
|
else
|
|
user_data.patron_account = null
|
|
to_chat(user, "<span class='notice'>[src]'s screen flashes: 'WARNING! Patron without associated account number Selected'</span>")
|
|
return
|
|
|
|
if(default_unfasten_wrench(user, O, time = 60))
|
|
return
|
|
|
|
return ..()
|
|
|
|
/obj/machinery/computer/library/ui_state(mob/user)
|
|
return GLOB.default_state
|
|
|
|
/obj/machinery/computer/library/ui_interact(mob/user, datum/tgui/ui = null)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "LibraryComputer", name)
|
|
ui.open()
|
|
|
|
/*
|
|
* # UI Data for TGUI
|
|
*
|
|
* Hey friends, this proc is where we stuff our massive amounts of data into our data list to be sent to our TGUI
|
|
* a few things about the library UI in specific, under no circumstance can any proc be called in ui_data that causes
|
|
* our code to sleep or wait, this will crash our TGUI interface upon first opening. This means you cannot call any of our
|
|
* procs that call a library_catalog proc that makes an SQL Query.
|
|
*/
|
|
/obj/machinery/computer/library/ui_data(mob/user)
|
|
var/list/data = list()
|
|
|
|
data["archive_pagenumber"] = archive_page_num
|
|
data["num_pages"] = num_pages
|
|
var/selected_categories = list()
|
|
selected_categories = user_data.search_categories
|
|
|
|
data["login_state"] = allowed(user)
|
|
|
|
data["searchcontent"] = list(
|
|
"title" = user_data.search_title,
|
|
"author" = user_data.search_author,
|
|
"ratingmin" = user_data.search_rating["min"],
|
|
"ratingmax" = user_data.search_rating["max"],
|
|
"categories" = selected_categories,
|
|
"ckey" = user_data.search_ckey,
|
|
)
|
|
|
|
var/list/selected_book_data = list(
|
|
"title" = user_data.selected_book.title ? user_data.selected_book.title : "not specified",
|
|
"author" = user_data.selected_book.author ? user_data.selected_book.author : "not specified",
|
|
"summary" = user_data.selected_book.summary ? user_data.selected_book.summary : "no summary",
|
|
"copyright" = user_data.selected_book.copyright ? user_data.selected_book.copyright : FALSE,
|
|
"categories" = user_data.selected_book.categories ? user_data.selected_book.categories : list()
|
|
)
|
|
|
|
data["selectedbook"] = selected_book_data
|
|
|
|
//should only be generating the cached booklist when we absolutely need to
|
|
data["external_booklist"] = cached_booklist
|
|
data["checkout_data"] = list()
|
|
|
|
for(var/datum/borrowbook/b in checkouts)
|
|
var/remaining_time = (b.duedate - world.time) / 600
|
|
var/late = FALSE
|
|
if(remaining_time <= 0) //if remaining time is less than zero, you're late
|
|
late = TRUE
|
|
remaining_time = round(remaining_time)
|
|
|
|
var/list/checkout_data = list(
|
|
"timeleft" = remaining_time,
|
|
"islate" = late,
|
|
"title" = b.bookname,
|
|
"libraryid" = b.libraryid,
|
|
"patron_name" = b.patron_name
|
|
)
|
|
data["checkout_data"] += list(checkout_data)
|
|
|
|
data["inventory_list"] = list()
|
|
for(var/book in inventory)
|
|
var/checked_out = FALSE
|
|
var/datum/cachedbook/CB = book
|
|
for(var/datum/borrowbook/checkout in checkouts)
|
|
if(CB.libraryid == checkout.libraryid)
|
|
checked_out = TRUE
|
|
break
|
|
var/list/book_data = list(
|
|
"title" = CB.title ? CB.title : "not specified",
|
|
"author" = CB.author ? CB.author : "not specified",
|
|
"summary" = CB.summary ? CB.summary : "no summary",
|
|
"id" = CB.id,
|
|
"libraryid" = CB.libraryid,
|
|
"checked_out" = checked_out,
|
|
)
|
|
data["inventory_list"] += list(book_data)
|
|
data["user_ckey"] = user?.ckey
|
|
data["selected_report"] = selected_report
|
|
data["selected_rating"] = user_data.selected_rating
|
|
data["modal"] = ui_modal_data(src)
|
|
|
|
return data
|
|
|
|
/obj/machinery/computer/library/ui_static_data(mob/user)
|
|
var/list/static_data = list()
|
|
//Book Categories will never change within a round so they don't need to sent more than once
|
|
static_data["book_categories"] = list()
|
|
for(var/datum/library_category/category in GLOB.library_catalog.categories)
|
|
var/category_info = list(
|
|
"category_id" = category.category_id,
|
|
"description" = category.description,
|
|
)
|
|
static_data["book_categories"] += list(category_info)
|
|
|
|
//Report Categories will never change within a round so they don't need to sent more than once
|
|
static_data["report_categories"] = list()
|
|
for(var/r in GLOB.library_catalog.report_types)
|
|
var/datum/library_category/report = r
|
|
var/report_info = list(
|
|
"category_id" = report.category_id,
|
|
"description" = report.description,
|
|
)
|
|
static_data["report_categories"] += list(report_info)
|
|
|
|
static_data["programmatic_booklist"] = list()
|
|
for(var/book in GLOB.library_catalog.books)
|
|
var/datum/programmatic_book/PB = book
|
|
var/list/book_data = list(
|
|
"title" = PB.title ? PB.title : "not specified",
|
|
"author "= PB.author ? PB.author : "Nanotrasen",
|
|
"id" = PB.id,
|
|
)
|
|
static_data["programmatic_booklist"] += list(book_data)
|
|
|
|
return static_data
|
|
|
|
/obj/machinery/computer/library/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
|
if(..())
|
|
return
|
|
|
|
if(ui_act_modal(action, params))
|
|
return
|
|
|
|
add_fingerprint(usr)
|
|
|
|
switch(action)
|
|
//Page Switching
|
|
if("incrementpage")
|
|
archive_page_num = clamp(archive_page_num + 1, 1, num_pages)
|
|
populate_booklist()
|
|
if("incrementpagemax")
|
|
archive_page_num = num_pages
|
|
populate_booklist()
|
|
if("deincrementpage")
|
|
archive_page_num = clamp(archive_page_num - 1, 1, num_pages)
|
|
populate_booklist()
|
|
if("deincrementpagemax")
|
|
archive_page_num = 1
|
|
populate_booklist()
|
|
//Search Tools' Buttons
|
|
if("toggle_search_category")
|
|
var/category_id = text2num(params["category_id"])
|
|
if(category_id in user_data.search_categories)
|
|
user_data.search_categories -= category_id
|
|
populate_booklist()
|
|
else
|
|
user_data.search_categories += category_id
|
|
populate_booklist()
|
|
if("clear_search")
|
|
user_data.clear_search()
|
|
populate_booklist()
|
|
if("find_users_books")
|
|
user_data.clear_search() //we need to clear out other search params first
|
|
user_data.search_ckey = params["user_ckey"]
|
|
populate_booklist()
|
|
if("clear_ckey_search")
|
|
user_data.search_ckey = null
|
|
populate_booklist()
|
|
|
|
//Order Buttons
|
|
if("order_external_book")
|
|
var/datum/cachedbook/orderedbook = GLOB.library_catalog.get_book_by_id(params["bookid"])
|
|
if(orderedbook && print_cooldown <= world.time)
|
|
make_external_book(orderedbook)
|
|
print_cooldown = world.time + PRINTING_COOLDOWN
|
|
if("order_programmatic_book")
|
|
var/datum/programmatic_book/PB = GLOB.library_catalog.get_programmatic_book_by_id(params["bookid"])
|
|
if(PB && print_cooldown <= world.time)
|
|
make_programmatic_book(PB)
|
|
print_cooldown = world.time + PRINTING_COOLDOWN
|
|
//book author actions
|
|
if("delete_book")
|
|
if(params["bookid"])
|
|
var/datum/cachedbook/selectedbook = GLOB.library_catalog.get_book_by_id(params["bookid"])
|
|
if(!selectedbook)
|
|
playsound(src, 'sound/machines/synth_no.ogg', 15, TRUE)
|
|
atom_say("Deletion Failed!")
|
|
return
|
|
if(selectedbook.ckey != params["user_ckey"])
|
|
message_admins("[params["user_ckey"]] attempted to delete a book that wasn't theirs, this shouldn't happen, please investigate.")
|
|
return
|
|
if(GLOB.library_catalog.remove_book_by_id(params["bookid"])) //this doesn't need to be logged
|
|
playsound(loc, 'sound/machines/ping.ogg', 25, 0)
|
|
atom_say("Deletion Successful!")
|
|
return
|
|
playsound(src, 'sound/machines/synth_no.ogg', 15, TRUE)
|
|
atom_say("Deletion Failed!")
|
|
|
|
|
|
//rating acts
|
|
if("set_rating")
|
|
if(params["rating_value"])
|
|
user_data.selected_rating = text2num(params["rating_value"])
|
|
if("rate_book")
|
|
if(GLOB.library_catalog.rate_book(params["user_ckey"], params["bookid"], user_data.selected_rating))
|
|
playsound(loc, 'sound/machines/ping.ogg', 25, 0)
|
|
atom_say("Rating Successful!")
|
|
populate_booklist()
|
|
//Report Acts
|
|
if("submit_report")
|
|
if(GLOB.library_catalog.flag_book_by_id(params["user_ckey"], params["bookid"], selected_report))
|
|
playsound(loc, 'sound/machines/ping.ogg', 50, 0)
|
|
atom_say("Report Submitted!")
|
|
return
|
|
playsound(src, 'sound/machines/synth_no.ogg', 15, TRUE)
|
|
atom_say("Report Submission Failed!")
|
|
if("set_report")
|
|
selected_report = text2num(params["report_type"])
|
|
//Book Uploader
|
|
if("toggle_upload_category")
|
|
if(text2num(params["category_id"]) in user_data.selected_book.categories)
|
|
user_data.selected_book.categories -= text2num(params["category_id"])
|
|
populate_booklist()
|
|
else
|
|
if(length(user_data.selected_book.categories) >= 3)
|
|
playsound(src, 'sound/machines/synth_no.ogg', 15, TRUE)
|
|
return
|
|
user_data.selected_book.categories += text2num(params["category_id"])
|
|
populate_booklist()
|
|
if("uploadbook")
|
|
if(GLOB.library_catalog.upload_book(params["user_ckey"], user_data.selected_book))
|
|
playsound(src, 'sound/machines/ping.ogg', 50, 0)
|
|
atom_say("Book Uploaded!")
|
|
return
|
|
playsound(src, 'sound/machines/synth_no.ogg', 15, TRUE)
|
|
atom_say("Book Upload Failed!")
|
|
num_pages = getmaxpages()
|
|
if("reportlost")
|
|
inventoryRemove(text2num(params["libraryid"]))
|
|
for(var/datum/borrowbook/book in checkouts)
|
|
if(book.libraryid == text2num(params["libraryid"]))
|
|
checkouts -= book
|
|
|
|
|
|
/obj/machinery/computer/library/proc/ui_act_modal(action, list/params)
|
|
. = TRUE
|
|
var/id = params["id"] // The modal's ID
|
|
var/list/arguments = istext(params["arguments"]) ? json_decode(params["arguments"]) : params["arguments"]
|
|
switch(ui_modal_act(src, action, params))
|
|
if(UI_MODAL_OPEN)
|
|
switch(id)
|
|
if("setpagenumber")
|
|
ui_modal_input(src, id, "Please input a page number:", null, arguments, archive_page_num)
|
|
//search inputs
|
|
if("edit_search_title")
|
|
ui_modal_input(src, id, "Please input the new title:", null, arguments, user_data.search_title)
|
|
if("edit_search_author")
|
|
ui_modal_input(src, id, "Please input the new author:", null, arguments, user_data.search_author)
|
|
if("edit_search_ratingmax")
|
|
ui_modal_input(src, id, "Please input the new upper rating bound:", null, arguments, user_data.search_rating["max"])
|
|
if("edit_search_ratingmin")
|
|
ui_modal_input(src, id, "Please input the new lower rating bound:", null, arguments, user_data.search_rating["min"])
|
|
//book uploader inputs
|
|
if("edit_selected_title")
|
|
ui_modal_input(src, id, "Please input the new title:", null, arguments, user_data.selected_book.title)
|
|
if("edit_selected_author")
|
|
ui_modal_input(src, id, "Please input the new author:", null, arguments, user_data.selected_book.author)
|
|
if("edit_selected_summary")
|
|
ui_modal_input(src, id, "Please input the new summary:", null, arguments, user_data.selected_book.summary)
|
|
//book list buttons
|
|
if("expand_info")
|
|
var/datum/programmatic_book/PB = GLOB.library_catalog.get_programmatic_book_by_id(arguments["bookid"])
|
|
if(PB)
|
|
ui_modal_message(src, id, "", arguments = list(
|
|
"isProgrammatic" = TRUE,
|
|
"title" = PB.title,
|
|
"author" = PB.author,
|
|
"summary" = PB.summary ? PB.summary : "No Summary Provided",
|
|
"rating" = "N for Nanotrasen",
|
|
))
|
|
|
|
return //If we've succesfully opened the modal for our programmatic book, we don't need to do more logic
|
|
var/datum/cachedbook/CB = GLOB.library_catalog.get_book_by_id(arguments["bookid"])
|
|
if(CB)
|
|
var/category_names = list()
|
|
for(var/datum/library_category/category in CB.categories)
|
|
category_names += category.description
|
|
user_data.selected_report = null
|
|
user_data.selected_rating = 0
|
|
|
|
ui_modal_message(src, id, "", arguments = list(
|
|
"isProgrammatic" = FALSE,
|
|
"id" = CB.id,
|
|
"ckey" = CB.ckey,
|
|
"title" = CB.title,
|
|
"author" = CB.author,
|
|
"summary" = CB.summary ? CB.summary : "No Summary Provided",
|
|
"rating" = CB.rating ? CB.rating : 0,
|
|
"categories" = category_names,
|
|
))
|
|
if("report_book")
|
|
var/datum/cachedbook/CB = GLOB.library_catalog.get_book_by_id(arguments["bookid"])
|
|
ui_modal_message(src, id, "", arguments = list(
|
|
id = CB.id,
|
|
title = CB.title,
|
|
ckey = CB.ckey,
|
|
))
|
|
if("rate_info")
|
|
var/datum/cachedbook/CB = GLOB.library_catalog.get_book_by_id(arguments["bookid"])
|
|
var/list/book_ratings = GLOB.library_catalog.get_book_ratings(arguments["bookid"])
|
|
ui_modal_message(src, id, "", arguments = list(
|
|
"id" = CB.id,
|
|
"title" = CB.title,
|
|
"author" = CB.author,
|
|
"ckey" = CB.ckey,
|
|
"current_rating" = length(book_ratings) ? book_ratings[1] : 0,
|
|
"total_ratings" = length(book_ratings) ? length(book_ratings[2]) : 0,
|
|
))
|
|
else
|
|
return FALSE
|
|
if(UI_MODAL_ANSWER)
|
|
var/answer = sanitize(params["answer"]) //xss attacks bad
|
|
switch(id)
|
|
if("edit_search_title")
|
|
if(!length(answer))
|
|
user_data.search_title = null
|
|
populate_booklist()
|
|
return
|
|
if(length(answer) >= MAX_NAME_LEN)
|
|
return
|
|
user_data.search_title = answer
|
|
populate_booklist()
|
|
if("edit_search_author")
|
|
if(!length(answer))
|
|
user_data.search_author = null
|
|
populate_booklist()
|
|
return
|
|
if(length(answer) >= MAX_NAME_LEN)
|
|
return
|
|
user_data.search_author = answer
|
|
populate_booklist()
|
|
if("edit_search_ratingmax")
|
|
if(!text2num(answer))
|
|
return
|
|
user_data.search_rating["max"] = clamp(text2num(answer), user_data.search_rating["min"], 10)
|
|
populate_booklist()
|
|
if("edit_search_ratingmin")
|
|
if(isnull(text2num(answer)))
|
|
return
|
|
user_data.search_rating["min"] = clamp(text2num(answer), 0, user_data.search_rating["max"])
|
|
populate_booklist()
|
|
if("edit_selected_title")
|
|
if(length(answer) >= MAX_NAME_LEN)
|
|
return
|
|
user_data.selected_book.title = answer
|
|
if("edit_selected_author")
|
|
if(length(answer) >= MAX_NAME_LEN)
|
|
return
|
|
user_data.selected_book.author = answer
|
|
if("edit_selected_summary")
|
|
if(length(answer) >= MAX_SUMMARY_LEN)
|
|
return
|
|
user_data.selected_book.summary = answer
|
|
if("setpagenumber")
|
|
if(!text2num(answer))
|
|
return
|
|
populate_booklist()
|
|
archive_page_num = clamp(text2num(answer), 1, getmaxpages())
|
|
else
|
|
return FALSE
|
|
else
|
|
return FALSE
|
|
|
|
/obj/machinery/computer/library/proc/select_book(obj/item/book/B)
|
|
if(B.carved)
|
|
return
|
|
user_data.selected_book.title = B.title ? B.title : "No Title"
|
|
user_data.selected_book.author = B.author ? B.author : "No Author"
|
|
user_data.selected_book.summary = B.summary ? B.summary : "No Summary"
|
|
user_data.selected_book.copyright = B.copyright ? B.copyright : FALSE
|
|
user_data.selected_book.content = B.pages ? B.pages : list()
|
|
user_data.selected_book.categories = B.categories ? B.categories : list()
|
|
|
|
/obj/machinery/computer/library/proc/inventoryAdd(obj/item/book/B) //add book to library inventory
|
|
for(var/datum/cachedbook/I in inventory)
|
|
if(I.libraryid == B.libraryid)
|
|
return FALSE
|
|
if(!B.libraryid)
|
|
total_books++
|
|
B.libraryid = total_books
|
|
var/datum/cachedbook/CB = new()
|
|
CB.serialize_book(B)
|
|
if(!CB)
|
|
return
|
|
inventory.Add(CB)
|
|
return TRUE
|
|
|
|
/obj/machinery/computer/library/proc/inventoryRemove(libraryID) //remove book from library inventory
|
|
for(var/datum/cachedbook/O in inventory)
|
|
if(O.libraryid == libraryID)
|
|
inventory.Remove(O)
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/obj/machinery/computer/library/proc/checkout(obj/item/book/B) //checkout book
|
|
if(!B.libraryid || !user_data.patron_name) //If book isn't a library book or there isn't a selected patron: return
|
|
return FALSE
|
|
for(var/datum/borrowbook/O in checkouts) //is this book already checked out?
|
|
if(O.libraryid == B.libraryid)
|
|
return FALSE
|
|
var/datum/borrowbook/P = new /datum/borrowbook
|
|
P.bookname = sanitize(B.title)
|
|
P.libraryid = B.libraryid
|
|
P.patron_name = sanitize(user_data.patron_name)
|
|
P.patron_account = sanitize(user_data.patron_account)
|
|
P.duedate = world.time + (checkoutperiod)
|
|
checkouts.Add(P)
|
|
return TRUE
|
|
|
|
/obj/machinery/computer/library/proc/checkin(obj/item/book/B) //check back in a book
|
|
if(!B.libraryid)
|
|
return FALSE
|
|
for(var/datum/borrowbook/O in checkouts) //is this book checked out?
|
|
if(O.libraryid == B.libraryid)
|
|
checkouts.Remove(O)
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/*
|
|
* # populate_booklist
|
|
*
|
|
* internal proc that will refresh our cached booklist, it needs to be called everytime we are switching parameters
|
|
* that will affect what books will be displayed in our TGUI player book archive.
|
|
*/
|
|
/obj/machinery/computer/library/proc/populate_booklist(async = TRUE)
|
|
cached_booklist = list() //clear old list
|
|
var/starting_book = (archive_page_num - 1) * LIBRARY_BOOKS_PER_PAGE
|
|
var/range = LIBRARY_BOOKS_PER_PAGE
|
|
for(var/datum/cachedbook/CB in GLOB.library_catalog.get_book_by_range(starting_book, range, user_data, async))
|
|
//instead of just adding the datum to the cached_booklist, we want to make it an assoc list so we can just give it to the TGUI
|
|
|
|
var/list/book_data = list(
|
|
"id" = CB.id,
|
|
"title" = CB.title,
|
|
"author" = CB.author,
|
|
"rating" = CB.rating,
|
|
"summary" = CB.summary,
|
|
"ckey" = CB.ckey,
|
|
"reports" = CB.reports,
|
|
)
|
|
book_data["categories"] = list()
|
|
for(var/category in CB.categories)
|
|
var/datum/library_category/book_category = GLOB.library_catalog.get_book_category_by_id(category)
|
|
if(book_category)
|
|
book_data["categories"] += book_category.description //we're displaying the cats onlys, so we don't need the ids
|
|
|
|
cached_booklist += list(book_data)
|
|
num_pages = getmaxpages()
|
|
archive_page_num = clamp(archive_page_num, 1, num_pages)
|
|
|
|
///Returns the amount of pages we will need to hold all the book our DB has found
|
|
/obj/machinery/computer/library/proc/getmaxpages()
|
|
//if get_total_books doesn't return anything, just set pages to 1 so we don't break stuff
|
|
var/book_count = max(1, GLOB.library_catalog.get_total_books(user_data))
|
|
var/page_count = round(book_count / LIBRARY_BOOKS_PER_PAGE)
|
|
//Since 'round' gets the floor value it's likely there will be 1 page more than
|
|
//the page count amount (almost guaranteed), we check for a remainder because of this
|
|
if(book_count % LIBRARY_BOOKS_PER_PAGE)
|
|
page_count++
|
|
return page_count
|
|
|
|
/obj/machinery/computer/library/proc/make_external_book(datum/cachedbook/newbook)
|
|
if(!newbook?.id)
|
|
return
|
|
new /obj/item/book(loc, newbook, TRUE, FALSE)
|
|
visible_message("<span class='notice'>[src]'s printer hums as it produces a completely bound book. How did it do that?</span>")
|
|
|
|
/obj/machinery/computer/library/proc/make_programmatic_book(datum/programmatic_book/newbook)
|
|
if(!newbook?.book_type)
|
|
return
|
|
|
|
new newbook.book_type(loc)
|
|
visible_message("<span class='notice'>[src]'s printer hums as it produces a completely bound book. How did it do that?</span>")
|
|
|
|
/obj/machinery/computer/library/emag_act(mob/user)
|
|
if(print_cooldown <= world.time)
|
|
new /obj/item/storage/bible/syndi(loc)
|
|
visible_message("<span class='notice'>[src]'s printer ominously hums as it produces a completely bound book. How did it do that?</span>")
|
|
print_cooldown = world.time + PRINTING_COOLDOWN
|
|
return TRUE
|
|
|
|
#undef LIBRARY_BOOKS_PER_PAGE
|
|
#undef LOGIN_FULL
|
|
#undef LOGIN_PUBLIC
|
|
#undef PRINTING_COOLDOWN
|