mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-31 12:01:47 +00:00
## About The Pull Request Converts all logging, excluding perf and investigate, to json. I focused on making the system as easy to use and as easy to add new categories as possible. Due to issues related to logging to world at global creation logger is now a byond real, which is created directly before Master Log categories support versioning, secret flagging, and sub-category filtering. Although all of this is entirely optional for coders. If you ever want to add a new category and use it, all you need to do is make the barebones category datum and the define. I've kept existing procs such as log_game, and simply turned them into a wrapper for Logger.Log(xxx, ...) ## Why It's Good For The Game Makes processing and filtering logs much easier in the future, while only minimally downgrading log crawling experience. I am also working on a log viewer frontend for admin usage however that will take a little bit longer to finish up. Also makes special logging and data tracking much easier thanks to a data list processing implementation and handling ## Changelog 🆑 server: All logs are now formatted in json, excluding perf and investigations /🆑 --------- Signed-off-by: GitHub <noreply@github.com> Co-authored-by: tattle <66640614+dragomagol@users.noreply.github.com> Co-authored-by: Kyle Spier-Swenson <kyleshome@gmail.com> Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com>
127 lines
4.9 KiB
Plaintext
127 lines
4.9 KiB
Plaintext
/**
|
|
* A savefile implementation that handles all data using json.
|
|
* Also saves it using JSON too, fancy.
|
|
* If you pass in a null path, it simply acts as a memory tree instead, and cannot be saved.
|
|
*/
|
|
/datum/json_savefile
|
|
var/path = ""
|
|
VAR_PRIVATE/list/tree
|
|
/// If this is set to true, calling set_entry or remove_entry will automatically call save(), this does not catch modifying a sub-tree, nor do I know how to do that
|
|
var/auto_save = FALSE
|
|
/// Cooldown that tracks the time between attempts to download the savefile.
|
|
COOLDOWN_DECLARE(download_cooldown)
|
|
|
|
GENERAL_PROTECT_DATUM(/datum/json_savefile)
|
|
|
|
/datum/json_savefile/New(path)
|
|
src.path = path
|
|
tree = list()
|
|
if(path && fexists(path))
|
|
load()
|
|
|
|
/**
|
|
* Gets an entry from the json tree, with an optional default value.
|
|
* If no key is specified it throws the entire tree at you instead
|
|
*/
|
|
/datum/json_savefile/proc/get_entry(key, default_value)
|
|
if(!key)
|
|
return tree
|
|
return (key in tree) ? tree[key] : default_value
|
|
|
|
/// Sets an entry in the tree to the given value
|
|
/datum/json_savefile/proc/set_entry(key, value)
|
|
tree[key] = value
|
|
if(auto_save)
|
|
save()
|
|
|
|
/// Removes the given key from the tree
|
|
/datum/json_savefile/proc/remove_entry(key)
|
|
if(key)
|
|
tree -= key
|
|
if(auto_save)
|
|
save()
|
|
|
|
/// Wipes the entire tree
|
|
/datum/json_savefile/proc/wipe()
|
|
tree?.Cut()
|
|
|
|
/datum/json_savefile/proc/load()
|
|
if(!path || !fexists(path))
|
|
return FALSE
|
|
try
|
|
tree = json_decode(rustg_file_read(path))
|
|
return TRUE
|
|
catch(var/exception/err)
|
|
stack_trace("failed to load json savefile at '[path]': [err]")
|
|
return FALSE
|
|
|
|
/datum/json_savefile/proc/save()
|
|
if(path)
|
|
rustg_file_write(json_encode(tree), path)
|
|
|
|
/datum/json_savefile/serialize_list(list/options, list/semvers)
|
|
SHOULD_CALL_PARENT(FALSE)
|
|
SET_SERIALIZATION_SEMVER(semvers, "1.0.0")
|
|
return tree.Copy()
|
|
|
|
/// Traverses the entire dir tree of the given savefile and dynamically assembles the tree from it
|
|
/datum/json_savefile/proc/import_byond_savefile(savefile/savefile)
|
|
tree.Cut()
|
|
var/list/dirs_to_go = list("/" = tree)
|
|
while(length(dirs_to_go))
|
|
var/dir = dirs_to_go[1]
|
|
var/list/region = dirs_to_go[dir]
|
|
dirs_to_go.Cut(1, 2)
|
|
savefile.cd = dir
|
|
for(var/entry in savefile.dir)
|
|
var/entry_value
|
|
savefile.cd = "[dir]/[entry]"
|
|
//eof refers to the path you are cd'ed into, not the savefile as a whole. being false right after cding into an entry means this entry has no buffer, which only happens with nested save file directories
|
|
if (savefile.eof)
|
|
region[entry] = list()
|
|
dirs_to_go["[dir]/[entry]"] = region[entry]
|
|
continue
|
|
READ_FILE(savefile, entry_value) //we are cd'ed to the entry, so we don't need to specify a path to read from
|
|
region[entry] = entry_value
|
|
|
|
/// Proc that handles generating a JSON file (prettified if 515 and over!) of a user's preferences and showing it to them.
|
|
/// Requester is passed in to the ftp() and tgui_alert() procs, and account_name is just used to generate the filename.
|
|
/// We don't _need_ to pass in account_name since this is reliant on the json_savefile datum already knowing what we correspond to, but it's here to help people keep track of their stuff.
|
|
/datum/json_savefile/proc/export_json_to_client(mob/requester, account_name)
|
|
if(!istype(requester) || !path)
|
|
return
|
|
|
|
if(!json_export_checks(requester))
|
|
return
|
|
|
|
COOLDOWN_START(src, download_cooldown, (CONFIG_GET(number/seconds_cooldown_for_preferences_export) * (1 SECONDS)))
|
|
var/file_name = "[account_name ? "[account_name]_" : ""]preferences_[time2text(world.timeofday, "MMM_DD_YYYY_hh-mm-ss")].json"
|
|
var/temporary_file_storage = "data/preferences_export_working_directory/[file_name]"
|
|
|
|
#if DM_VERSION >= 515
|
|
if(!text2file(json_encode(tree, JSON_PRETTY_PRINT), temporary_file_storage))
|
|
tgui_alert(requester, "Failed to export preferences to JSON! You might need to try again later.", "Export Preferences JSON")
|
|
return
|
|
#else
|
|
if(!text2file(json_encode(tree), temporary_file_storage))
|
|
tgui_alert(requester, "Failed to export preferences to JSON! You might need to try again later.", "Export Preferences JSON")
|
|
return
|
|
#endif
|
|
|
|
var/exportable_json = file(temporary_file_storage)
|
|
|
|
DIRECT_OUTPUT(requester, ftp(exportable_json, file_name))
|
|
fdel(temporary_file_storage)
|
|
|
|
/// Proc that just handles all of the checks for exporting a preferences file, returns TRUE if all checks are passed, FALSE otherwise.
|
|
/// Just done like this to make the code in the export_json_to_client() proc a bit cleaner.
|
|
/datum/json_savefile/proc/json_export_checks(mob/requester)
|
|
if(!COOLDOWN_FINISHED(src, download_cooldown))
|
|
tgui_alert(requester, "You must wait [DisplayTimeText(COOLDOWN_TIMELEFT(src, download_cooldown))] before exporting your preferences again!", "Export Preferences JSON")
|
|
return FALSE
|
|
|
|
if(tgui_alert(requester, "Are you sure you want to export your preferences as a JSON file? This will save to a file on your computer.", "Export Preferences JSON", list("Cancel", "Yes")) == "Yes")
|
|
return TRUE
|
|
|
|
return FALSE
|