[MIRROR] JSON Logging Refactor (#11623)

Co-authored-by: Selis <12716288+ItsSelis@users.noreply.github.com>
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-09-14 11:05:26 -07:00
committed by GitHub
parent 272afa33c8
commit 5a62077f2c
425 changed files with 4081 additions and 2568 deletions

View File

@@ -86,6 +86,9 @@
///Used for limiting the rate of clicks sends by the client to avoid abuse
var/list/clicklimiter
///these persist between logins/logouts during the same round.
var/datum/persistent_client/persistent_client
////////////////////////////////////
//things that require the database//
////////////////////////////////////

View File

@@ -1,6 +1,11 @@
////////////
//SECURITY//
////////////
GLOBAL_LIST_INIT(blacklisted_builds, list(
"1622" = "Bug breaking rendering can lead to wallhacks.",
))
#define UPLOAD_LIMIT 10485760 //Restricts client uploads to the server to 10MB //Boosted this thing. What's the worst that can happen?
#define MIN_CLIENT_VERSION 0 //Just an ambiguously low version for now, I don't want to suddenly stop people playing.
//I would just like the code ready should it ever need to be used.
@@ -68,7 +73,8 @@
if (minute != topiclimiter[ADMINSWARNED_AT]) //only one admin message per-minute. (if they spam the admins can just boot/ban them)
topiclimiter[ADMINSWARNED_AT] = minute
msg += " Administrators have been informed."
log_and_message_admins("[key_name(src)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute", src)
log_game("[key_name(src)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute")
message_admins("[ADMIN_LOOKUPFLW(usr)] [ADMIN_KICK(usr)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute")
to_chat(src, span_danger("[msg]"))
return
@@ -87,7 +93,7 @@
//search the href for script injection
if( findtext(href,"<script",1,0) )
to_world_log("Attempted use of scripts within a topic call, by [src]")
log_world("Attempted use of scripts within a topic call, by [src]")
message_admins("Attempted use of scripts within a topic call, by [src]")
return
@@ -158,8 +164,7 @@
stat_panel.reinitialize() //CHOMPEdit
//Logs all hrefs
if(config && CONFIG_GET(flag/log_hrefs) && GLOB.href_logfile)
WRITE_LOG(GLOB.href_logfile, "[src] (usr:[usr])</small> || [hsrc ? "[hsrc] " : ""][href]")
log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
//byond bug ID:2256651
if (asset_cache_job && (asset_cache_job in completed_asset_jobs))
@@ -226,9 +231,12 @@
//CONNECT//
///////////
/client/New(TopicData)
winset(src, null, "browser-options=[DEFAULT_CLIENT_BROWSER_OPTIONS]")
TopicData = null //Prevent calls to client.Topic from connect
TopicData = null //Prevent calls to client.Topic from connect
if(connection != "seeker" && connection != "web")//Invalid connection type.
return null
winset(src, null, "browser-options=[DEFAULT_CLIENT_BROWSER_OPTIONS]")
if(!(connection in list("seeker", "web"))) //Invalid connection type.
return null
@@ -247,6 +255,14 @@
GLOB.clients += src
GLOB.directory[ckey] = src
//var/reconnecting = FALSE we are not using this var yet
if(GLOB.persistent_clients_by_ckey[ckey])
//reconnecting = TRUE
persistent_client = GLOB.persistent_clients_by_ckey[ckey]
else
persistent_client = new(ckey)
persistent_client.set_client(src)
if (CONFIG_GET(flag/chatlog_database_backend))
chatlog_token = vchatlog_generate_token(ckey, GLOB.round_id)
@@ -262,12 +278,6 @@
GLOB.tickets.ClientLogin(src)
//Admin Authorisation
holder = GLOB.admin_datums[ckey]
if(holder)
GLOB.admins += src
holder.owner = src
//preferences datum - also holds some persistant data for the client (because we may as well keep these datums to a minimum)
prefs = preferences_datums[ckey]
if(prefs)
@@ -280,9 +290,42 @@
prefs.last_ip = address //these are gonna be used for banning
prefs.last_id = computer_id //these are gonna be used for banning
var/full_version = "[byond_version].[byond_build ? byond_build : "xxx"]"
log_access("Login: [key_name(src)] from [address ? address : "localhost"]-[computer_id] || BYOND v[full_version]")
prefs_vr = new/datum/vore_preferences(src)
. = ..() //calls mob.Login()
// Admin Verbs need the client's mob to exist. Must be after ..()
var/connecting_admin = FALSE //because de-admined admins connecting should be treated like admins.
//Admin Authorisation
var/datum/admins/admin_datum = GLOB.admin_datums[ckey]
if (!isnull(admin_datum))
admin_datum.associate(src)
connecting_admin = TRUE
else if(GLOB.deadmins[ckey])
add_verb(src, /client/proc/readmin)
connecting_admin = TRUE
if (byond_version >= 512)
if (!byond_build || byond_build < 1386)
message_admins(span_adminnotice("[key_name(src)] has been detected as spoofing their byond version. Connection rejected."))
//add_system_note("Spoofed-Byond-Version", "Detected as using a spoofed byond version.")
log_suspicious_login("Failed Login: [key] - Spoofed byond version")
qdel(src)
if (num2text(byond_build) in GLOB.blacklisted_builds)
log_access("Failed login: [key] - blacklisted byond version")
to_chat_immediate(src, span_userdanger("Your version of byond is blacklisted."))
to_chat_immediate(src, span_danger("Byond build [byond_build] ([byond_version].[byond_build]) has been blacklisted for the following reason: [GLOB.blacklisted_builds[num2text(byond_build)]]."))
to_chat_immediate(src, span_danger("Please download a new version of byond. If [byond_build] is the latest, you can go to <a href=\"https://secure.byond.com/download/build\">BYOND's website</a> to download other versions."))
if(connecting_admin)
to_chat_immediate(src, "As an admin, you are being allowed to continue using this version, but please consider changing byond versions")
else
qdel(src)
return
prefs.sanitize_preferences()
if(prefs)
prefs.selecting_slots = FALSE
@@ -371,8 +414,6 @@
if (!QDELING(src))
stack_trace("Client does not purport to be QDELING, this is going to cause bugs in other places!")
GLOB.tickets.ClientLogout(src)
// Yes this is the same as what's found in qdel(). Yes it does need to be here
// Get off my back
SEND_SIGNAL(src, COMSIG_QDELETING, TRUE)
@@ -380,11 +421,15 @@
return ..()
/client/Destroy()
GLOB.directory -= ckey
GLOB.clients -= src
persistent_client.set_client(null)
log_access("Logout: [key_name(src)]")
GLOB.tickets.ClientLogout(src)
if(holder)
holder.owner = null
GLOB.admins -= src
GLOB.directory -= ckey
GLOB.clients -= src
QDEL_NULL(loot_panel)
..()
@@ -475,7 +520,7 @@
//Panic bunker code
if (isnum(player_age) && player_age == 0) //first connection
if (CONFIG_GET(flag/panic_bunker) && !holder && !GLOB.deadmins[key])
log_adminwarn("Failed Login: [key] - New account attempting to connect during panic bunker")
log_admin_private("Failed Login: [key] - New account attempting to connect during panic bunker")
message_admins(span_adminnotice("Failed Login: [key] - New account attempting to connect during panic bunker"))
disconnect_with_message("Sorry but the server is currently not accepting connections from never before seen players.")
return 0
@@ -503,7 +548,6 @@
else
log_admin("Couldn't perform IP check on [key] with [address]")
// VOREStation Edit Start - Department Hours
var/datum/db_query/query_hours = SSdbcore.NewQuery("SELECT department, hours, total_hours FROM vr_player_hours WHERE ckey = '[sql_ckey]'")
if(query_hours.Execute())
while(query_hours.NextRow())
@@ -511,9 +555,8 @@
play_hours[query_hours.item[1]] = text2num(query_hours.item[3])
else
var/error_message = query_hours.ErrorMsg() // Need this out here since the spawn below will split the stack and who knows what'll happen by the time it runs
log_debug("Error loading play hours for [ckey]: [error_message]")
log_sql("Error loading play hours for [ckey]: [error_message]")
tgui_alert_async(src, "The query to load your existing playtime failed. Screenshot this, give the screenshot to a developer, and reconnect, otherwise you may lose any recorded play hours (which may limit access to jobs). ERROR: [error_message]", "PROBLEMS!!")
// VOREStation Edit End - Department Hours
qdel(query_hours)
if(sql_id)
//Player already identified previously, we need to just update the 'lastseen', 'ip' and 'computer_id' variables

View File

@@ -0,0 +1,107 @@
///assoc list of ckey -> /datum/persistent_client
GLOBAL_LIST_EMPTY_TYPED(persistent_clients_by_ckey, /datum/persistent_client)
/// A flat list of all persistent clients, for her looping pleasure.
GLOBAL_LIST_EMPTY_TYPED(persistent_clients, /datum/persistent_client)
/// Tracks information about a client between log in and log outs
/datum/persistent_client
/// The true client
var/client/client
/// The mob this persistent client is currently bound to.
var/mob/mob
/// Major version of BYOND this client was last using.
var/byond_version
/// Build number of BYOND this client was last using.
var/byond_build
/// Action datums assigned to this player
var/list/datum/action/player_actions = list()
/// Tracks client action logging
var/list/logging = list()
/// Callbacks invoked when this client logs in again
var/list/post_login_callbacks = list()
/// Callbacks invoked when this client logs out
var/list/post_logout_callbacks = list()
/// List of names this key played under this round
/// assoc list of name -> mob tag
var/list/played_names = list()
/// Lazylist of preference slots this client has joined the round under
/// Numbers are stored as strings
var/list/joined_as_slots
/// Tracks achievements they have earned
//var/datum/achievement_data/achievements
/// World.time this player last died
var/time_of_death = 0
/datum/persistent_client/New(ckey)
//achievements = new(ckey)
GLOB.persistent_clients_by_ckey[ckey] = src
GLOB.persistent_clients += src
/datum/persistent_client/Destroy(force)
SHOULD_CALL_PARENT(FALSE)
. = QDEL_HINT_LETMELIVE
CRASH("Who the FUCK tried to delete a persistent client? Get your head checked you leadskull.")
/// Setter for the client var, updates any vars we have that might be dependent on client state
/datum/persistent_client/proc/set_client(client/new_client)
if(client == new_client)
return
if(client)
client.persistent_client = null
client = new_client
if(client)
client.persistent_client = src
byond_build = client.byond_build
byond_version = client.byond_version
/// Setter for the mob var, handles both references.
/datum/persistent_client/proc/set_mob(mob/new_mob)
if(mob == new_mob)
return
mob?.persistent_client = null
new_mob?.persistent_client?.set_mob(null)
mob = new_mob
new_mob?.persistent_client = src
/// Writes all of the `played_names` into an HTML-escaped string.
/datum/persistent_client/proc/get_played_names()
var/list/previous_names = list()
for(var/previous_name in played_names)
previous_names += html_encode("[previous_name] ([played_names[previous_name]])")
return previous_names.Join("; ")
/// Returns the full version string (i.e 515.1642) of the BYOND version and build.
/datum/persistent_client/proc/full_byond_version()
if(!byond_version)
return "Unknown"
return "[byond_version].[byond_build || "xxx"]"
/// Adds the new names to the player's played_names list on their /datum/persistent_client for use of admins.
/// `ckey` should be their ckey, and `data` should be an associative list with the keys being the names they played under and the values being the unique mob ID tied to that name.
/proc/log_played_names(ckey, data)
if(!ckey)
return
var/datum/persistent_client/writable = GLOB.persistent_clients_by_ckey[ckey]
if(isnull(writable))
return
for(var/name in data)
if(!name)
continue
var/mob_tag = data[name]
var/encoded_name = html_encode(name)
if(writable.played_names.Find("[encoded_name]"))
continue
writable.played_names += list("[encoded_name]" = mob_tag)

View File

@@ -131,16 +131,16 @@
//Neutral traits
for(var/datum/trait/path as anything in pref.neu_traits)
if(!(path in GLOB.neutral_traits))
to_world_log("removing [path] for not being in neutral_traits")
log_world("removing [path] for not being in neutral_traits")
pref.neu_traits -= path
continue
if(!(pref.species == SPECIES_CUSTOM) && !(path in GLOB.everyone_traits_neutral))
to_world_log("removing [path] for not being a custom species")
log_world("removing [path] for not being a custom species")
pref.neu_traits -= path
continue
var/take_flags = initial(path.can_take)
if((pref.dirty_synth && !(take_flags & SYNTHETICS)) || (pref.gross_meatbag && !(take_flags & ORGANICS)))
to_world_log("removing [path] for being a dirty synth")
log_world("removing [path] for being a dirty synth")
pref.neu_traits -= path
//Negative traits
for(var/datum/trait/path as anything in pref.neg_traits)

View File

@@ -19,13 +19,13 @@ var/list/gear_datums = list()
var/use_category = initial(G.sort_category)
if(!use_name)
error("Loadout - Missing display name: [G]")
log_world("## ERROR Loadout - Missing display name: [G]")
continue
if(isnull(initial(G.cost)))
error("Loadout - Missing cost: [G]")
log_world("## ERROR Loadout - Missing cost: [G]")
continue
if(!initial(G.path))
error("Loadout - Missing path definition: [G]")
log_world("## ERROR Loadout - Missing path definition: [G]")
continue
if(!loadout_categories[use_category])

View File

@@ -355,7 +355,7 @@ var/list/preferences_datums = list()
var/slotnum = charlist[choice]
if(!slotnum)
error("Player picked [choice] slot to load, but that wasn't one we sent.")
log_world("## ERROR Player picked [choice] slot to load, but that wasn't one we sent.")
return
load_preferences(TRUE)
@@ -396,7 +396,7 @@ var/list/preferences_datums = list()
var/slotnum = charlist[choice]
if(!slotnum)
error("Player picked [choice] slot to copy to, but that wasn't one we sent.")
log_world("## ERROR Player picked [choice] slot to copy to, but that wasn't one we sent.")
return
if(tgui_alert(user, "Are you sure you want to override slot [slotnum], [choice]'s savedata?", "Confirm Override", list("No", "Yes")) == "Yes")

View File

@@ -41,62 +41,62 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
// Migration for client preferences
if(current_version < 13)
log_debug("[client_ckey] preferences migrating from [current_version] to v13....")
log_world("[client_ckey] preferences migrating from [current_version] to v13....")
to_chat(client, span_danger("Migrating savefile from version [current_version] to v13..."))
migration_13_preferences(S)
log_debug("[client_ckey] preferences successfully migrated from [current_version] to v13.")
log_world("[client_ckey] preferences successfully migrated from [current_version] to v13.")
to_chat(client, span_danger("v13 savefile migration complete."))
// Migration for nifs
if(current_version < 14)
log_debug("[client_ckey] preferences migrating from [current_version] to v14....")
log_world("[client_ckey] preferences migrating from [current_version] to v14....")
to_chat(client, span_danger("Migrating savefile from version [current_version] to v14..."))
migration_14_nifs(S)
log_debug("[client_ckey] preferences successfully migrated from [current_version] to v14.")
log_world("[client_ckey] preferences successfully migrated from [current_version] to v14.")
to_chat(client, span_danger("v14 savefile migration complete."))
// Migration for nifs, again, to get rid of the /device path
if(current_version < 15)
log_debug("[client_ckey] preferences migrating from [current_version] to v15....")
log_world("[client_ckey] preferences migrating from [current_version] to v15....")
to_chat(client, span_danger("Migrating savefile from version [current_version] to v15..."))
migration_15_nif_path(S)
log_debug("[client_ckey] preferences successfully migrated from [current_version] to v15.")
log_world("[client_ckey] preferences successfully migrated from [current_version] to v15.")
to_chat(client, span_danger("v15 savefile migration complete."))
// Migration for colors
if(current_version < 16)
log_debug("[client_ckey] preferences migrating from [current_version] to v16....")
log_world("[client_ckey] preferences migrating from [current_version] to v16....")
to_chat(client, span_danger("Migrating savefile from version [current_version] to v16..."))
migration_16_colors(S)
log_debug("[client_ckey] preferences successfully migrated from [current_version] to v16.")
log_world("[client_ckey] preferences successfully migrated from [current_version] to v16.")
to_chat(client, span_danger("v16 savefile migration complete."))
// Migration for old named tails so downstream doesn't have their savefiles borked
if(current_version < 17)
log_debug("[client_ckey] preferences migrating from [current_version] to v17....")
log_world("[client_ckey] preferences migrating from [current_version] to v17....")
to_chat(client, span_danger("Migrating savefile from version [current_version] to v17..."))
migration_17_tails(S)
log_debug("[client_ckey] preferences successfully migrated from [current_version] to v17.")
log_world("[client_ckey] preferences successfully migrated from [current_version] to v17.")
to_chat(client, span_danger("v17 savefile migration complete."))
// Migration for jukebox volume from 0-1 to 0-100
if(current_version < 18)
log_debug("[client_ckey] preferences migrating from [current_version] to v18....")
log_world("[client_ckey] preferences migrating from [current_version] to v18....")
to_chat(client, span_danger("Migrating savefile from version [current_version] to v18..."))
migration_18_jukebox(S)
log_debug("[client_ckey] preferences successfully migrated from [current_version] to v18.")
log_world("[client_ckey] preferences successfully migrated from [current_version] to v18.")
to_chat(client, span_danger("v18 savefile migration complete."))
/datum/preferences/proc/update_character(current_version, list/save_data)
// Migration from BYOND savefiles to JSON: Important milemark.
@@ -106,7 +106,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
/// Migrates from byond savefile to json savefile
/datum/preferences/proc/try_savefile_type_migration()
log_debug("[client_ckey] preferences migrating from savefile to JSON...")
log_world("[client_ckey] preferences migrating from savefile to JSON...")
to_chat(client, span_danger("Savefile migration to JSON in progress..."))
load_path(client.ckey, "preferences.sav") // old save file
@@ -118,7 +118,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
json_savefile.import_byond_savefile(new /savefile(old_path))
json_savefile.save()
log_debug("[client_ckey] preferences successfully migrated from savefile to JSON.")
log_world("[client_ckey] preferences successfully migrated from savefile to JSON.")
to_chat(client, span_danger("Savefile migration to JSON is complete."))
return TRUE

View File

@@ -82,7 +82,7 @@
connected = FALSE
else if(type == "error")
connected = FALSE
log_debug("WebSocket Error [json_encode(payload)]")
log_runtime("WebSocket Error [json_encode(payload)]")
else if(type == "incomingMessage")
if(payload["lastCall"] == "get_devices")
available_devices = json_decode(payload["data"])

View File

@@ -42,7 +42,7 @@
message_admins("[key_name_admin(src)] has attempted to post a link in OOC: [msg]")
return
log_ooc(msg, src)
src.mob.log_talk(msg, LOG_OOC)
if(msg)
handle_spam_prevention(MUTE_OOC)
@@ -125,7 +125,7 @@
message_admins("[key_name_admin(src)] has attempted to post a link in OOC: [msg]")
return
log_looc(msg,src)
src.mob.log_message(msg, LOG_LOOC)
if(msg)
handle_spam_prevention(MUTE_LOOC)