mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-17 10:03:50 +01:00
Ports rust_g -> rustlibs: logging, toml, dmi, json, and noisegen (#28858)
* Rustlibs logging, toml, dmi, and dbpnoise * missed one * Hopefully fix logging utf-8 decode errors * Fuck * Build Rust library * ports rust_g json validator * rustlibs_file clippy lint * Build Rust library * fix merge conflict --------- Co-authored-by: paradisess13[bot] <165046124+paradisess13[bot]@users.noreply.github.com>
This commit is contained in:
@@ -131,6 +131,47 @@
|
||||
/proc/mapmanip_read_dmm(mapname)
|
||||
return RUSTLIB_CALL(mapmanip_read_dmm_file, mapname)
|
||||
|
||||
// MARK: TOML
|
||||
/proc/rustlibs_read_toml_file(path)
|
||||
var/list/output = json_decode(RUSTLIB_CALL(toml_file_to_json, path) || "null")
|
||||
if(output["success"])
|
||||
return json_decode(output["content"])
|
||||
else
|
||||
CRASH(output["content"])
|
||||
|
||||
// MARK: Logging
|
||||
/proc/rustlibs_log_write(fname, text)
|
||||
return RUSTLIB_CALL(log_write, fname, text)
|
||||
|
||||
/proc/rustlibs_log_close_all()
|
||||
return RUSTLIB_CALL(log_close_all)
|
||||
|
||||
// MARK: DMI
|
||||
/proc/rustlibs_dmi_strip_metadata(fname)
|
||||
return RUSTLIB_CALL(dmi_strip_metadata, fname)
|
||||
|
||||
// MARK: JSON
|
||||
/proc/rustlibs_json_is_valid(text)
|
||||
return (RUSTLIB_CALL(json_is_valid, text) == "true")
|
||||
|
||||
|
||||
// MARK: Grid Perlin Noise
|
||||
/**
|
||||
* This proc generates a grid of perlin-like noise
|
||||
*
|
||||
* Returns a single string that goes row by row, with values of 1 representing an turned on cell, and a value of 0 representing a turned off cell.
|
||||
*
|
||||
* Arguments:
|
||||
* * seed: seed for the function
|
||||
* * accuracy: how close this is to the original perlin noise, as accuracy approaches infinity, the noise becomes more and more perlin-like
|
||||
* * stamp_size: Size of a singular stamp used by the algorithm, think of this as the same stuff as frequency in perlin noise
|
||||
* * world_size: size of the returned grid.
|
||||
* * lower_range: lower bound of values selected for. (inclusive)
|
||||
* * upper_range: upper bound of values selected for. (exclusive)
|
||||
*/
|
||||
/proc/rustlibs_dbp_generate(seed, accuracy, stamp_size, world_size, lower_range, upper_range)
|
||||
return RUSTLIB_CALL(dbp_generate, seed, accuracy, stamp_size, world_size, lower_range, upper_range)
|
||||
|
||||
// MARK: Redis
|
||||
#define RUSTLIBS_REDIS_ERROR_CHANNEL "RUSTG_REDIS_ERROR_CHANNEL"
|
||||
|
||||
|
||||
@@ -48,29 +48,6 @@
|
||||
/// Gets the version of rust_g
|
||||
/proc/rustg_get_version() return RUSTG_CALL(RUST_G, "get_version")()
|
||||
|
||||
// Grid Perlin Noise //
|
||||
|
||||
/**
|
||||
* This proc generates a grid of perlin-like noise
|
||||
*
|
||||
* Returns a single string that goes row by row, with values of 1 representing an turned on cell, and a value of 0 representing a turned off cell.
|
||||
*
|
||||
* Arguments:
|
||||
* * seed: seed for the function
|
||||
* * accuracy: how close this is to the original perlin noise, as accuracy approaches infinity, the noise becomes more and more perlin-like
|
||||
* * stamp_size: Size of a singular stamp used by the algorithm, think of this as the same stuff as frequency in perlin noise
|
||||
* * world_size: size of the returned grid.
|
||||
* * lower_range: lower bound of values selected for. (inclusive)
|
||||
* * upper_range: upper bound of values selected for. (exclusive)
|
||||
*/
|
||||
#define rustg_dbp_generate(seed, accuracy, stamp_size, world_size, lower_range, upper_range) \
|
||||
RUSTG_CALL(RUST_G, "dbp_generate")(seed, accuracy, stamp_size, world_size, lower_range, upper_range)
|
||||
|
||||
// DMI Operations //
|
||||
|
||||
#define rustg_dmi_strip_metadata(fname) RUSTG_CALL(RUST_G, "dmi_strip_metadata")(fname)
|
||||
|
||||
|
||||
// Git Operations //
|
||||
|
||||
/// Returns the git hash of the given revision, ex. "HEAD".
|
||||
@@ -111,15 +88,6 @@
|
||||
#define RUSTG_JOB_NO_SUCH_JOB "NO SUCH JOB"
|
||||
#define RUSTG_JOB_ERROR "JOB PANICKED"
|
||||
|
||||
// JSON Operations //
|
||||
|
||||
#define rustg_json_is_valid(text) (RUSTG_CALL(RUST_G, "json_is_valid")(text) == "true")
|
||||
|
||||
// Logging Operations //
|
||||
|
||||
#define rustg_log_write(fname, text) RUSTG_CALL(RUST_G, "log_write")(fname, text)
|
||||
/proc/rustg_log_close_all() return RUSTG_CALL(RUST_G, "log_close_all")()
|
||||
|
||||
// SQL Operations //
|
||||
|
||||
#define rustg_sql_connect_pool(options) RUSTG_CALL(RUST_G, "sql_connect_pool")(options)
|
||||
@@ -132,14 +100,3 @@
|
||||
// Toast Operations //
|
||||
|
||||
#define rustg_create_toast(title, body) RUSTG_CALL(RUST_G, "create_toast")(title, body)
|
||||
|
||||
// TOML Operations //
|
||||
|
||||
#define rustg_raw_read_toml_file(path) json_decode(RUSTG_CALL(RUST_G, "toml_file_to_json")(path) || "null")
|
||||
|
||||
/proc/rustg_read_toml_file(path)
|
||||
var/list/output = rustg_raw_read_toml_file(path)
|
||||
if(output["success"])
|
||||
return json_decode(output["content"])
|
||||
else
|
||||
CRASH(output["content"])
|
||||
|
||||
+37
-37
@@ -32,12 +32,12 @@ GLOBAL_PROTECT(log_end)
|
||||
if(!skip_glob)
|
||||
GLOB.admin_log.Add(text)
|
||||
if(GLOB.configuration.logging.admin_logging)
|
||||
rustg_log_write(GLOB.world_game_log, "ADMIN: [text][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "ADMIN: [text][GLOB.log_end]")
|
||||
|
||||
/proc/log_debug(text)
|
||||
// This has presence checks as this may be called before GLOB has loaded
|
||||
if(GLOB?.configuration?.logging.debug_logging)
|
||||
rustg_log_write(GLOB.world_game_log, "DEBUG: [text][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "DEBUG: [text][GLOB.log_end]")
|
||||
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(check_rights(R_DEBUG | R_VIEWRUNTIMES, FALSE, C.mob) && (C.prefs.toggles & PREFTOGGLE_CHAT_DEBUGLOGS))
|
||||
@@ -45,65 +45,65 @@ GLOBAL_PROTECT(log_end)
|
||||
|
||||
/proc/log_game(text)
|
||||
if(GLOB.configuration.logging.game_logging)
|
||||
rustg_log_write(GLOB.world_game_log, "GAME: [text][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "GAME: [text][GLOB.log_end]")
|
||||
|
||||
/proc/log_vote(text)
|
||||
if(GLOB.configuration.logging.vote_logging)
|
||||
rustg_log_write(GLOB.world_game_log, "VOTE: [text][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "VOTE: [text][GLOB.log_end]")
|
||||
|
||||
/proc/log_if_mismatch(mob/who, message, automatic = FALSE)
|
||||
if(istype(usr, /mob) && istype(who) && usr.last_known_ckey != who.last_known_ckey)
|
||||
if(automatic)
|
||||
rustg_log_write(GLOB.world_game_log, "AUTOMATIC ([usr.last_known_ckey]): [message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "AUTOMATIC ([usr.last_known_ckey]): [message][GLOB.log_end]")
|
||||
else
|
||||
rustg_log_write(GLOB.world_game_log, "LOG USER MISMATCH: [usr.simple_info_line()] was usr for [message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "LOG USER MISMATCH: [usr.simple_info_line()] was usr for [message][GLOB.log_end]")
|
||||
|
||||
/proc/log_access_in(client/new_client)
|
||||
if(GLOB.configuration.logging.access_logging)
|
||||
var/message = "ACCESS IN: [key_name(new_client)] - IP:[new_client.address] - CID:[new_client.computer_id] - BYOND v[new_client.byond_version].[new_client.byond_build]"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(new_client.mob, message)
|
||||
|
||||
/proc/log_access_out(mob/last_mob)
|
||||
if(GLOB.configuration.logging.access_logging)
|
||||
var/message = "ACCESS OUT: [key_name(last_mob)] - IP:[last_mob.lastKnownIP] - CID:[last_mob.computer_id] - BYOND Logged Out"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(last_mob, message)
|
||||
|
||||
/proc/log_say(text, mob/speaker, automatic = FALSE)
|
||||
if(GLOB.configuration.logging.say_logging)
|
||||
var/message = "SAY: [speaker.simple_info_line()]: [html_decode(text)]"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(speaker, message, automatic)
|
||||
|
||||
/proc/log_whisper(text, mob/speaker)
|
||||
if(GLOB.configuration.logging.whisper_logging)
|
||||
var/message = "WHISPER: [speaker.simple_info_line()]: [html_decode(text)]"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(speaker, message)
|
||||
|
||||
/proc/log_ooc(text, client/user)
|
||||
if(GLOB.configuration.logging.ooc_logging)
|
||||
var/message = "OOC: [user.simple_info_line()]: [html_decode(text)]"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(user, message)
|
||||
|
||||
/proc/log_aooc(text, client/user)
|
||||
if(GLOB.configuration.logging.ooc_logging)
|
||||
var/message = "AOOC: [user.simple_info_line()]: [html_decode(text)]"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(user, message)
|
||||
|
||||
/proc/log_looc(text, client/user)
|
||||
if(GLOB.configuration.logging.ooc_logging)
|
||||
var/message = "LOOC: [user.simple_info_line()]: [html_decode(text)]"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(user, message)
|
||||
|
||||
/proc/log_emote(text, mob/speaker)
|
||||
if(GLOB.configuration.logging.emote_logging)
|
||||
var/message = "EMOTE: [speaker.simple_info_line()]: [html_decode(text)]"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(speaker, message)
|
||||
|
||||
/proc/log_attack(mob/attacker, defender_str, attack_message)
|
||||
@@ -112,89 +112,89 @@ GLOBAL_PROTECT(log_end)
|
||||
if(istype(attacker))
|
||||
attacker_str = attacker.simple_info_line()
|
||||
var/message = "ATTACK: [attacker_str] against [defender_str]: [attack_message]"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(attacker, message)
|
||||
|
||||
/proc/log_adminsay(text, mob/speaker)
|
||||
if(GLOB.configuration.logging.adminchat_logging)
|
||||
var/message = "ADMINSAY: [speaker.simple_info_line()]: [html_decode(text)]"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(speaker, message)
|
||||
|
||||
/proc/log_ping_all_admins(text, mob/speaker)
|
||||
if(GLOB.configuration.logging.adminchat_logging)
|
||||
var/message = "ALL ADMIN PING: [speaker.simple_info_line()]: [html_decode(text)]"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(speaker, message)
|
||||
|
||||
/proc/log_qdel(text)
|
||||
rustg_log_write(GLOB.world_qdel_log, "QDEL: [text][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_qdel_log, "QDEL: [text][GLOB.log_end]")
|
||||
|
||||
/proc/log_mentorsay(text, mob/speaker)
|
||||
if(GLOB.configuration.logging.adminchat_logging)
|
||||
var/message = "MENTORSAY: [speaker.simple_info_line()]: [html_decode(text)]"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(speaker, message)
|
||||
|
||||
/proc/log_devsay(text, mob/speaker)
|
||||
if(GLOB.configuration.logging.adminchat_logging)
|
||||
var/message = "DEVSAY: [speaker.simple_info_line()]: [html_decode(text)]"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(speaker, message)
|
||||
|
||||
/proc/log_ghostsay(text, mob/speaker)
|
||||
if(GLOB.configuration.logging.say_logging)
|
||||
var/message = "DEADCHAT: [speaker.simple_info_line()]: [html_decode(text)]"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(speaker, message)
|
||||
|
||||
/proc/log_ghostemote(text, mob/speaker)
|
||||
if(GLOB.configuration.logging.emote_logging)
|
||||
var/message = "DEADEMOTE: [speaker.simple_info_line()]: [html_decode(text)]"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(speaker, message)
|
||||
|
||||
/proc/log_adminwarn(text)
|
||||
if(GLOB.configuration.logging.admin_warning_logging)
|
||||
rustg_log_write(GLOB.world_game_log, "ADMINWARN: [html_decode(text)][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "ADMINWARN: [html_decode(text)][GLOB.log_end]")
|
||||
|
||||
/proc/log_pda(text, mob/speaker)
|
||||
if(GLOB.configuration.logging.pda_logging)
|
||||
var/message = "PDA: [speaker.simple_info_line()]: [html_decode(text)]"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(speaker, message)
|
||||
|
||||
/proc/log_chat(text, mob/speaker)
|
||||
if(GLOB.configuration.logging.pda_logging)
|
||||
var/message = "CHAT: [speaker.simple_info_line()] [html_decode(text)]"
|
||||
rustg_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "[message][GLOB.log_end]")
|
||||
log_if_mismatch(speaker, message)
|
||||
|
||||
/proc/log_tgs(text, level)
|
||||
GLOB.tgs_log += "\[[time_stamp()]] \[[level]] [text]"
|
||||
rustg_log_write(GLOB.world_game_log, "TGS: [level]: [text][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "TGS: [level]: [text][GLOB.log_end]")
|
||||
|
||||
/proc/log_misc(text)
|
||||
rustg_log_write(GLOB.world_game_log, "MISC: [text][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "MISC: [text][GLOB.log_end]")
|
||||
|
||||
/proc/log_world(text)
|
||||
SEND_TEXT(world.log, text)
|
||||
// This has to be presence checked as log_world() is used before world/New().
|
||||
if(GLOB?.configuration?.logging.world_logging)
|
||||
rustg_log_write(GLOB.world_game_log, "WORLD: [html_decode(text)][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_game_log, "WORLD: [html_decode(text)][GLOB.log_end]")
|
||||
|
||||
/proc/log_runtime_txt(text) // different from /tg/'s log_runtime because our error handler has a log_runtime proc already that does other stuff
|
||||
rustg_log_write(GLOB.world_runtime_log, "[text][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_runtime_log, "[text][GLOB.log_end]")
|
||||
|
||||
/proc/log_config(text)
|
||||
rustg_log_write(GLOB.config_error_log, "[text][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.config_error_log, "[text][GLOB.log_end]")
|
||||
SEND_TEXT(world.log, text)
|
||||
|
||||
/proc/log_href(text)
|
||||
rustg_log_write(GLOB.world_href_log, "HREF: [html_decode(text)][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.world_href_log, "HREF: [html_decode(text)][GLOB.log_end]")
|
||||
|
||||
/proc/log_runtime_summary(text)
|
||||
rustg_log_write(GLOB.runtime_summary_log, "[text][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.runtime_summary_log, "[text][GLOB.log_end]")
|
||||
|
||||
/proc/log_tgui(user_or_client, text)
|
||||
var/list/messages = list()
|
||||
@@ -208,22 +208,22 @@ GLOBAL_PROTECT(log_end)
|
||||
messages.Add("[client.ckey]")
|
||||
messages.Add(": [text]")
|
||||
messages.Add("[GLOB.log_end]")
|
||||
rustg_log_write(GLOB.tgui_log, messages.Join())
|
||||
rustlibs_log_write(GLOB.tgui_log, messages.Join())
|
||||
|
||||
#ifdef REFERENCE_TRACKING
|
||||
/proc/log_gc(text)
|
||||
rustg_log_write(GLOB.gc_log, "[text][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.gc_log, "[text][GLOB.log_end]")
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(check_rights(R_DEBUG | R_VIEWRUNTIMES, FALSE, C.mob) && (C.prefs.toggles & PREFTOGGLE_CHAT_DEBUGLOGS))
|
||||
to_chat(C, "GC DEBUG: [text]")
|
||||
#endif
|
||||
|
||||
/proc/log_sql(text)
|
||||
rustg_log_write(GLOB.sql_log, "[text][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.sql_log, "[text][GLOB.log_end]")
|
||||
SEND_TEXT(world.log, text) // Redirect it to DD too
|
||||
|
||||
/proc/log_chat_debug(text)
|
||||
rustg_log_write(GLOB.chat_debug_log, "[text][GLOB.log_end]")
|
||||
rustlibs_log_write(GLOB.chat_debug_log, "[text][GLOB.log_end]")
|
||||
|
||||
// A logging proc that only outputs after setup is done, to
|
||||
// help devs test initialization stuff that happens a lot
|
||||
@@ -234,7 +234,7 @@ GLOBAL_PROTECT(log_end)
|
||||
|
||||
/* For logging round startup. */
|
||||
/proc/start_log(log)
|
||||
rustg_log_write(log, "Starting up. Round ID is [GLOB.round_id ? GLOB.round_id : "NULL"]\n-------------------------[GLOB.log_end]")
|
||||
rustlibs_log_write(log, "Starting up. Round ID is [GLOB.round_id ? GLOB.round_id : "NULL"]\n-------------------------[GLOB.log_end]")
|
||||
|
||||
// Helper procs for building detailed log lines
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ GLOBAL_DATUM_INIT(configuration, /datum/server_configuration, new())
|
||||
var/config_file = "config/config.toml"
|
||||
if(!fexists(config_file))
|
||||
config_file = "config/example/config.toml" // Fallback to example if user hasnt setup config properly
|
||||
raw_data = rustg_read_toml_file(config_file)
|
||||
raw_data = rustlibs_read_toml_file(config_file)
|
||||
|
||||
// Now pass through all our stuff
|
||||
load_all_sections()
|
||||
@@ -147,7 +147,7 @@ GLOBAL_DATUM_INIT(configuration, /datum/server_configuration, new())
|
||||
DIRECT_OUTPUT(world.log, "Override file [override_file] found. Loading.")
|
||||
var/start = start_watch() // Time tracking
|
||||
|
||||
raw_data = rustg_read_toml_file(override_file)
|
||||
raw_data = rustlibs_read_toml_file(override_file)
|
||||
|
||||
// Now safely load our overrides.
|
||||
// Due to the nature of config wrappers, only vars that exist in the config file are applied to the config datums.
|
||||
|
||||
@@ -45,7 +45,7 @@ SUBSYSTEM_DEF(http)
|
||||
log_data += "\tResponse body: [res.body]"
|
||||
log_data += "\tResponse headers: [json_encode(res.headers)]"
|
||||
log_data += "END ASYNC RESPONSE (ID: [req.id])"
|
||||
rustg_log_write(GLOB.http_log, log_data.Join("\n[GLOB.log_end]"))
|
||||
rustlibs_log_write(GLOB.http_log, log_data.Join("\n[GLOB.log_end]"))
|
||||
|
||||
/**
|
||||
* Async request creator
|
||||
@@ -74,7 +74,7 @@ SUBSYSTEM_DEF(http)
|
||||
log_data += "END ASYNC REQUEST (ID: [req.id])"
|
||||
|
||||
// Write the log data
|
||||
rustg_log_write(GLOB.http_log, log_data.Join("\n[GLOB.log_end]"))
|
||||
rustlibs_log_write(GLOB.http_log, log_data.Join("\n[GLOB.log_end]"))
|
||||
|
||||
/**
|
||||
* Blocking request creator
|
||||
@@ -106,7 +106,7 @@ SUBSYSTEM_DEF(http)
|
||||
log_data += "END BLOCKING REQUEST"
|
||||
|
||||
// Write the log data
|
||||
rustg_log_write(GLOB.http_log, log_data.Join("\n[GLOB.log_end]"))
|
||||
rustlibs_log_write(GLOB.http_log, log_data.Join("\n[GLOB.log_end]"))
|
||||
|
||||
return res
|
||||
*/
|
||||
|
||||
+3
-3
@@ -131,7 +131,7 @@ GLOBAL_LIST_EMPTY(world_topic_handlers)
|
||||
message_admins("[key_name_admin(usr)] has requested an immediate world restart via client side debugging tools")
|
||||
log_admin("[key_name(usr)] has requested an immediate world restart via client side debugging tools")
|
||||
to_chat(world, "<span class='boldannounceooc'>Rebooting world immediately due to host request</span>")
|
||||
rustg_log_close_all() // Past this point, no logging procs can be used, at risk of data loss.
|
||||
rustlibs_log_close_all() // Past this point, no logging procs can be used, at risk of data loss.
|
||||
// Now handle a reboot
|
||||
if(GLOB.configuration.system.shutdown_on_reboot)
|
||||
sleep(0)
|
||||
@@ -174,12 +174,12 @@ GLOBAL_LIST_EMPTY(world_topic_handlers)
|
||||
C << link("byond://[GLOB.configuration.url.server_url]")
|
||||
|
||||
// And begin the real shutdown
|
||||
rustg_log_close_all() // Past this point, no logging procs can be used, at risk of data loss.
|
||||
rustlibs_log_close_all() // Past this point, no logging procs can be used, at risk of data loss.
|
||||
if(GLOB.configuration.system.shutdown_on_reboot)
|
||||
sleep(0)
|
||||
if(GLOB.configuration.system.shutdown_shell_command)
|
||||
shell(GLOB.configuration.system.shutdown_shell_command)
|
||||
rustg_log_close_all() // Past this point, no logging procs can be used, at risk of data loss.
|
||||
rustlibs_log_close_all() // Past this point, no logging procs can be used, at risk of data loss.
|
||||
del(world)
|
||||
TgsEndProcess() // We want to shutdown on reboot. That means kill our TGS process "gracefully", instead of the watchdog crying
|
||||
return
|
||||
|
||||
@@ -165,7 +165,7 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
var/png_name = "[name]_[size_id].png"
|
||||
var/file_directory = "data/spritesheets/[png_name]"
|
||||
fcopy(size[SPRSZ_ICON], file_directory)
|
||||
var/error = rustg_dmi_strip_metadata(file_directory)
|
||||
var/error = rustlibs_dmi_strip_metadata(file_directory)
|
||||
if(length(error))
|
||||
stack_trace("Failed to strip [png_name]: [error]")
|
||||
size[SPRSZ_STRIPPED] = icon(file_directory)
|
||||
|
||||
@@ -92,7 +92,7 @@ GLOBAL_LIST_INIT(caves_default_flora_spawns, list(
|
||||
seed = rand(1, 999999)
|
||||
|
||||
/datum/caves_theme/proc/setup()
|
||||
var/result = rustg_dbp_generate("[seed]", "[perlin_accuracy]", "[perlin_stamp_size]", "[world.maxx]", "[perlin_lower_range]", "[perlin_upper_range]")
|
||||
var/result = rustlibs_dbp_generate("[seed]", "[perlin_accuracy]", "[perlin_stamp_size]", "[world.maxx]", "[perlin_lower_range]", "[perlin_upper_range]")
|
||||
for(var/zlvl in levels_by_trait(ORE_LEVEL))
|
||||
for(var/turf/T in block(1, 1, zlvl, world.maxx, world.maxy, zlvl))
|
||||
if(!istype(get_area(T), /area/lavaland/surface/outdoors/unexplored))
|
||||
|
||||
@@ -208,7 +208,7 @@
|
||||
var/payload
|
||||
if(href_list["payload"])
|
||||
var/payload_text = href_list["payload"]
|
||||
if(!rustg_json_is_valid(payload_text))
|
||||
if(!rustlibs_json_is_valid(payload_text))
|
||||
log_tgui(usr, "Error: Invalid JSON")
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
"[generate_test_log_message(world.timeofday + 20)]",
|
||||
)
|
||||
|
||||
rustg_log_write(TEST_LOG_FILE, TEST_MESSAGE)
|
||||
rustlibs_log_write(TEST_LOG_FILE, TEST_MESSAGE)
|
||||
|
||||
var/list/lines = file2list(TEST_LOG_FILE)
|
||||
TEST_ASSERT(lines[1] in valid_lines, \
|
||||
"RUSTG log format is not valid 8601 format. Expected '[generate_test_log_message(world.timeofday)]', got '[lines[1]]'")
|
||||
"Rustlibs log format is not valid 8601 format. Expected '[generate_test_log_message(world.timeofday)]', got '[lines[1]]'")
|
||||
|
||||
#undef TEST_MESSAGE
|
||||
#undef TEST_LOG_FILE
|
||||
|
||||
Generated
+146
-13
@@ -1,6 +1,6 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
@@ -300,6 +300,44 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "dbpnoise"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2a92e2d3660e5513454071018433d22bbdfc8a79b9bcf1b6399aa72e96b8586"
|
||||
dependencies = [
|
||||
"lerp",
|
||||
"rand",
|
||||
"rand_pcg",
|
||||
"rand_seeder",
|
||||
"rayon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derivative"
|
||||
version = "2.2.0"
|
||||
@@ -385,7 +423,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"termcolor",
|
||||
"toml",
|
||||
"toml 0.5.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -516,9 +554,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
@@ -700,12 +738,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.2.6"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||
checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.5",
|
||||
"hashbrown 0.15.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -762,6 +800,15 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lerp"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b19ac50d419bff1a024a8eb8034bfbee6c1cf8fa3472502f6bd3def327b09e4c"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.154"
|
||||
@@ -1042,7 +1089,7 @@ version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284"
|
||||
dependencies = [
|
||||
"toml_edit",
|
||||
"toml_edit 0.21.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1151,12 +1198,50 @@ dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_seeder"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf2890aaef0aa82719a50e808de264f9484b74b442e1a3a0e5ee38243ac40bdb"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rawpointer"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redis"
|
||||
version = "0.21.7"
|
||||
@@ -1224,6 +1309,7 @@ dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"byondapi",
|
||||
"chrono",
|
||||
"dbpnoise",
|
||||
"diff",
|
||||
"dmm-tools",
|
||||
"dreammaker",
|
||||
@@ -1239,6 +1325,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thread-priority",
|
||||
"toml 0.8.20",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
@@ -1316,6 +1403,15 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.6.1"
|
||||
@@ -1446,10 +1542,25 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.5"
|
||||
name = "toml"
|
||||
version = "0.8.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
|
||||
checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit 0.22.24",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
@@ -1457,9 +1568,22 @@ version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
|
||||
dependencies = [
|
||||
"indexmap 2.2.6",
|
||||
"indexmap 2.8.0",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
"winnow 0.5.40",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
|
||||
dependencies = [
|
||||
"indexmap 2.8.0",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"winnow 0.7.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1689,6 +1813,15 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "write16"
|
||||
version = "1.0.0"
|
||||
|
||||
@@ -36,6 +36,8 @@ walkdir = "2.5.0"
|
||||
regex = "1.10.5"
|
||||
png = "0.17.16"
|
||||
chrono = "0.4.39"
|
||||
toml = "0.8.20"
|
||||
dbpnoise = "0.1.2"
|
||||
# redis - DO NOT CHANGE FROM 0.21.4 - also dont touch flume either please k thx. if you mess with these you make redis unstable
|
||||
redis = { version = "0.21.4" }
|
||||
flume = { version = "0.10" }
|
||||
|
||||
@@ -2,6 +2,12 @@ mod logging;
|
||||
mod mapmanip;
|
||||
mod milla;
|
||||
mod redis_pubsub;
|
||||
mod rustlibs_dmi;
|
||||
mod rustlibs_file;
|
||||
mod rustlibs_json;
|
||||
mod rustlibs_logging;
|
||||
mod rustlibs_noisegen;
|
||||
mod rustlibs_toml;
|
||||
|
||||
#[cfg(all(not(feature = "byond-515"), not(feature = "byond-516")))]
|
||||
compile_error!("Please specify byond-515 or byond-516 as a feature to specify BYOND version.");
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
use byondapi::value::ByondValue;
|
||||
use png::{Decoder, Encoder};
|
||||
use std::fs::File;
|
||||
|
||||
#[byondapi::bind]
|
||||
fn dmi_strip_metadata(path: ByondValue) -> eyre::Result<ByondValue> {
|
||||
strip_metadata(&path.get_string()?)?;
|
||||
Ok(ByondValue::null())
|
||||
}
|
||||
|
||||
fn strip_metadata(path: &str) -> eyre::Result<()> {
|
||||
let mut reader = Decoder::new(File::open(path)?).read_info()?;
|
||||
let mut buf = vec![0; reader.output_buffer_size()];
|
||||
let frame_info = reader.next_frame(&mut buf)?;
|
||||
|
||||
let mut encoder = Encoder::new(File::create(path)?, frame_info.width, frame_info.height);
|
||||
encoder.set_color(frame_info.color_type);
|
||||
encoder.set_depth(frame_info.bit_depth);
|
||||
let reader_info = reader.info();
|
||||
|
||||
if let Some(palette) = reader_info.palette.clone() {
|
||||
encoder.set_palette(palette);
|
||||
}
|
||||
if let Some(trns_chunk) = reader_info.trns.clone() {
|
||||
encoder.set_palette(trns_chunk);
|
||||
}
|
||||
|
||||
let mut writer = encoder.write_header()?;
|
||||
Ok(writer.write_image_data(&buf)?)
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
use byondapi::value::ByondValue;
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{BufReader, BufWriter, Read, Write},
|
||||
};
|
||||
|
||||
#[byondapi::bind]
|
||||
fn file_read(path: ByondValue) -> eyre::Result<ByondValue> {
|
||||
read(&path.get_string()?)
|
||||
}
|
||||
|
||||
fn read(path: &str) -> eyre::Result<ByondValue> {
|
||||
let file = File::open(path)?;
|
||||
let metadata = file.metadata()?;
|
||||
let mut file = BufReader::new(file);
|
||||
|
||||
let mut content = String::with_capacity(metadata.len() as usize);
|
||||
file.read_to_string(&mut content)?;
|
||||
let content = content.replace('\r', "");
|
||||
|
||||
Ok(content.try_into()?)
|
||||
}
|
||||
|
||||
#[byondapi::bind]
|
||||
fn file_write(data: ByondValue, path: ByondValue) -> eyre::Result<ByondValue> {
|
||||
let data: String = data.get_string()?;
|
||||
let path: String = path.get_string()?;
|
||||
write(&data, &path)
|
||||
}
|
||||
|
||||
fn write(data: &str, path: &str) -> eyre::Result<ByondValue> {
|
||||
let path: &std::path::Path = path.as_ref();
|
||||
if let Some(parent) = path.parent() {
|
||||
std::fs::create_dir_all(parent)?;
|
||||
}
|
||||
|
||||
let mut file = BufWriter::new(File::create(path)?);
|
||||
let written = file.write(data.as_bytes())? as f32;
|
||||
|
||||
file.flush()?;
|
||||
file.into_inner()
|
||||
.map_err(|e| std::io::Error::new(e.error().kind(), e.error().to_string()))?
|
||||
.sync_all()?;
|
||||
|
||||
Ok(written.into())
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
use byondapi::value::ByondValue;
|
||||
use serde_json::Value;
|
||||
use std::cmp;
|
||||
|
||||
const VALID_JSON_MAX_RECURSION_DEPTH: usize = 8;
|
||||
|
||||
#[byondapi::bind]
|
||||
fn json_is_valid(text: ByondValue) -> eyre::Result<ByondValue> {
|
||||
let value = match serde_json::from_str::<Value>(&text.get_string()?) {
|
||||
Ok(value) => value,
|
||||
Err(_) => return Ok("false".try_into()?),
|
||||
};
|
||||
|
||||
Ok(get_recursion_level(&value).is_ok().to_string().try_into()?)
|
||||
}
|
||||
|
||||
/// Gets the recursion level of the given value
|
||||
/// If it is above `VALID_JSON_MAX_RECURSION_DEPTH`, returns Err(())
|
||||
fn get_recursion_level(value: &Value) -> Result<usize, ()> {
|
||||
let values: Vec<&Value> = match value {
|
||||
Value::Array(array) => array.iter().collect(),
|
||||
|
||||
Value::Object(map) => map.values().collect(),
|
||||
|
||||
_ => return Ok(0),
|
||||
};
|
||||
|
||||
let mut max_recursion_level = 0;
|
||||
|
||||
for value in values {
|
||||
max_recursion_level = cmp::max(max_recursion_level, get_recursion_level(value)?);
|
||||
}
|
||||
|
||||
max_recursion_level += 1;
|
||||
|
||||
if max_recursion_level >= VALID_JSON_MAX_RECURSION_DEPTH {
|
||||
Err(())
|
||||
} else {
|
||||
Ok(max_recursion_level)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_get_recursion_level() {
|
||||
assert_eq!(
|
||||
get_recursion_level(&serde_json::from_str("[]").unwrap()),
|
||||
Ok(1)
|
||||
);
|
||||
assert_eq!(
|
||||
get_recursion_level(&serde_json::from_str("[[]]").unwrap()),
|
||||
Ok(2)
|
||||
);
|
||||
assert_eq!(
|
||||
get_recursion_level(&serde_json::from_str("[[[]]]").unwrap()),
|
||||
Ok(3)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_recursion_level_max_depth() {
|
||||
assert_eq!(
|
||||
get_recursion_level(
|
||||
&serde_json::from_str(&format!(
|
||||
"{}{}",
|
||||
"[".repeat(VALID_JSON_MAX_RECURSION_DEPTH),
|
||||
"]".repeat(VALID_JSON_MAX_RECURSION_DEPTH)
|
||||
))
|
||||
.unwrap()
|
||||
),
|
||||
Err(())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
use byondapi::value::ByondValue;
|
||||
use chrono::Utc;
|
||||
use eyre::Context;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
collections::hash_map::{Entry, HashMap},
|
||||
ffi::OsString,
|
||||
fs,
|
||||
fs::{File, OpenOptions},
|
||||
io::Write,
|
||||
path::Path,
|
||||
};
|
||||
|
||||
thread_local! {
|
||||
static FILE_MAP: RefCell<HashMap<OsString, File>> = RefCell::new(HashMap::new());
|
||||
}
|
||||
|
||||
#[byondapi::bind]
|
||||
fn log_write(path: ByondValue, data: ByondValue) -> eyre::Result<ByondValue> {
|
||||
FILE_MAP.with(|cell| -> eyre::Result<ByondValue> {
|
||||
let mut map = cell.borrow_mut();
|
||||
let path = path.get_string()?;
|
||||
let path = Path::new(&path as &str);
|
||||
let file = match map.entry(path.into()) {
|
||||
Entry::Occupied(e) => e.into_mut(),
|
||||
Entry::Vacant(e) => e.insert(open(path)?),
|
||||
};
|
||||
// Byond will happily send over invalid bytes from unpurged text macros, which Rust does not like
|
||||
// This circumvents ByondValue::get_string() to strip utf-8 before it can cause a panic
|
||||
let data = data
|
||||
.get_cstring()
|
||||
.map(|cstring| cstring.to_string_lossy().into_owned())
|
||||
.wrap_err(format!("UTF-8 decode error: {:#?}", data))?;
|
||||
let iter = data.split('\n');
|
||||
|
||||
for line in iter {
|
||||
writeln!(file, "[{}] {}", Utc::now().format("%FT%T"), line)?;
|
||||
}
|
||||
|
||||
Ok(ByondValue::null())
|
||||
})
|
||||
}
|
||||
|
||||
#[byondapi::bind]
|
||||
fn log_close_all() -> eyre::Result<ByondValue> {
|
||||
FILE_MAP.with(|cell| {
|
||||
let mut map = cell.borrow_mut();
|
||||
map.clear();
|
||||
});
|
||||
Ok(ByondValue::null())
|
||||
}
|
||||
|
||||
fn open(path: &Path) -> eyre::Result<File> {
|
||||
if let Some(parent) = path.parent() {
|
||||
fs::create_dir_all(parent)?;
|
||||
}
|
||||
Ok(OpenOptions::new().append(true).create(true).open(path)?)
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
use byondapi::value::ByondValue;
|
||||
use dbpnoise::gen_noise;
|
||||
|
||||
#[byondapi::bind]
|
||||
fn dbp_generate(
|
||||
seed: ByondValue,
|
||||
accuracy: ByondValue,
|
||||
stamp_size: ByondValue,
|
||||
world_size: ByondValue,
|
||||
lower_range: ByondValue,
|
||||
upper_range: ByondValue,
|
||||
) -> eyre::Result<ByondValue> {
|
||||
Ok(gen_dbp_noise(
|
||||
&seed.get_string()?,
|
||||
&accuracy.get_string()?,
|
||||
&stamp_size.get_string()?,
|
||||
&world_size.get_string()?,
|
||||
&lower_range.get_string()?,
|
||||
&upper_range.get_string()?,
|
||||
)?
|
||||
.try_into()?)
|
||||
}
|
||||
|
||||
fn gen_dbp_noise(
|
||||
seed: &str,
|
||||
accuracy: &str,
|
||||
stamp_size: &str,
|
||||
world_size: &str,
|
||||
lower_range: &str,
|
||||
upper_range: &str,
|
||||
) -> eyre::Result<String> {
|
||||
let map: Vec<Vec<bool>> = gen_noise(
|
||||
seed,
|
||||
accuracy.parse::<usize>()?,
|
||||
stamp_size.parse::<usize>()?,
|
||||
world_size.parse::<usize>()?,
|
||||
lower_range.parse::<f32>()?,
|
||||
upper_range.parse::<f32>()?,
|
||||
);
|
||||
let mut result = String::new();
|
||||
for row in map {
|
||||
for cell in row {
|
||||
result.push(if cell { '1' } else { '0' });
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::gen_dbp_noise;
|
||||
|
||||
const TEST_SEED: &str = "meowrrpmraoooow~";
|
||||
#[test]
|
||||
fn test_gen_dbp_noise() {
|
||||
let value = gen_dbp_noise(TEST_SEED, "360", "4", "25", "0.1", "1.1").unwrap();
|
||||
println!("(length: {})", value.len());
|
||||
println!("{}", value);
|
||||
assert_eq!(value.len(), 625);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
use byondapi::value::ByondValue;
|
||||
|
||||
#[byondapi::bind]
|
||||
fn toml_file_to_json(path: ByondValue) -> eyre::Result<ByondValue> {
|
||||
let path: String = path.get_string()?;
|
||||
Ok(serde_json::to_string(&match toml_file_to_json_impl(&path) {
|
||||
Ok(value) => serde_json::json!({
|
||||
"success": true, "content": value
|
||||
}),
|
||||
Err(error) => serde_json::json!({
|
||||
"success": false, "content": error.to_string()
|
||||
}),
|
||||
})?
|
||||
.try_into()?)
|
||||
}
|
||||
|
||||
fn toml_file_to_json_impl(path: &str) -> eyre::Result<String> {
|
||||
Ok(serde_json::to_string(&toml::from_str::<toml::Value>(
|
||||
&std::fs::read_to_string(path)?,
|
||||
)?)?)
|
||||
}
|
||||
|
||||
#[byondapi::bind]
|
||||
fn toml_encode(value: ByondValue) -> eyre::Result<ByondValue> {
|
||||
let path: String = value.get_string()?;
|
||||
Ok(serde_json::to_string(&match toml_encode_impl(&path) {
|
||||
Ok(value) => serde_json::json!({
|
||||
"success": true, "content": value
|
||||
}),
|
||||
Err(error) => serde_json::json!({
|
||||
"success": false, "content": error.to_string()
|
||||
}),
|
||||
})?
|
||||
.try_into()?)
|
||||
}
|
||||
|
||||
fn toml_encode_impl(value: &str) -> eyre::Result<String> {
|
||||
Ok(toml::to_string_pretty(
|
||||
&serde_json::from_str::<toml::Value>(value)?,
|
||||
)?)
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user