Refactors client data loading

This commit is contained in:
AffectedArc07
2021-07-29 12:52:45 +01:00
parent 0032043740
commit f73af8b3cf
49 changed files with 2951 additions and 2810 deletions
+47 -207
View File
@@ -268,8 +268,8 @@
show_update_prompt = TRUE
else if(byond_version == SUGGESTED_CLIENT_VERSION && byond_build < SUGGESTED_CLIENT_BUILD)
show_update_prompt = TRUE
// Actually sent to client much later, so it appears after MOTD.
// Actually sent to client much later, so it appears after MOTD.
to_chat(src, "<span class='warning'>If the title screen is black, resources are still downloading. Please be patient until the title screen appears.</span>")
GLOB.directory[ckey] = src
@@ -278,25 +278,54 @@
if(GLOB.configuration.admin.enable_localhost_autoadmin)
if(is_connecting_from_localhost())
new /datum/admins("!LOCALHOST!", R_HOST, ckey) // Makes localhost rank
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 = GLOB.preferences_datums[ckey]
if(!prefs)
prefs = new /datum/preferences(src)
GLOB.preferences_datums[ckey] = prefs
log_client_to_db(tdata) // Make sure our client exists in the DB
// This is where stuff happens on the client
if(SSdbcore.IsConnected())
// Load in all our client data from the DB
var/list/datum/db_query/login_queries = list() // List of queries to run for login processing
for(var/datum/client_login_processor/CLP in GLOB.client_login_processors)
login_queries[CLP.type] = CLP.get_query(src)
SSdbcore.MassExecute(login_queries, TRUE, FALSE, TRUE, FALSE) // Warn, no qdel, assoc, no log
// Now do fancy things with the results
for(var/datum/client_login_processor/CLP in GLOB.client_login_processors)
CLP.process_result(login_queries[CLP.type], src)
QDEL_LIST_ASSOC_VAL(login_queries) // Clear out the used queries
else
prefs.parent = src
// Set vars here that need to be set if the DB is offline
// Give blank prefs
prefs = new /datum/preferences(src)
prefs.character_saves = list()
// Random character
prefs.character_saves.Add(new /datum/character_save)
prefs.active_character = prefs.character_saves[1]
// ToS accepted
tos_consent = TRUE
prefs.last_ip = address //these are gonna be used for banning
prefs.last_id = computer_id //these are gonna be used for banning
if(world.byond_version >= 511 && byond_version >= 511 && prefs.clientfps)
fps = prefs.clientfps
// Check if the client has or has not accepted TOS
check_tos_consent()
// Log alts
if(length(related_accounts_ip))
log_admin("[key_name(src)] Alts by IP: [jointext(related_accounts_ip, " ")]")
if(length(related_accounts_cid))
log_admin("[key_name(src)] Alts by CID: [jointext(related_accounts_cid, " ")]")
// This has to go here to avoid issues
// If you sleep past this point, you will get SSinput errors as well as goonchat errors
@@ -320,7 +349,6 @@
winset(src, null, "command=\".configure graphics-hwmode off\"")
winset(src, null, "command=\".configure graphics-hwmode on\"")
log_client_to_db(tdata)
. = ..() //calls mob.Login()
@@ -332,7 +360,6 @@
if(SSinput.initialized)
set_macros()
donator_check()
check_ip_intel()
send_resources()
@@ -394,8 +421,6 @@
if(world.TgsAvailable() && length(GLOB.revision_info.testmerges))
to_chat(src, GLOB.revision_info.get_testmerge_chatmessage(TRUE))
INVOKE_ASYNC(src, .proc/cid_count_check)
/client/proc/is_connecting_from_localhost()
var/localhost_addresses = list("127.0.0.1", "::1") // Adresses
@@ -428,52 +453,18 @@
return QDEL_HINT_HARDDEL_NOW
/client/proc/donator_check()
set waitfor = FALSE // This needs to run async because any sleep() inside /client/New() breaks stuff badly
if(IsGuestKey(key))
return
if(!SSdbcore.IsConnected())
return
if(check_rights(R_ADMIN, 0, mob)) // Yes, the mob is required, regardless of other examples in this file, it won't work otherwise
donator_level = DONATOR_LEVEL_MAX
donor_loadout_points()
return
//Donator stuff.
var/datum/db_query/query_donor_select = SSdbcore.NewQuery("SELECT ckey, tier, active FROM donators WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query_donor_select.warn_execute())
qdel(query_donor_select)
return
while(query_donor_select.NextRow())
if(!text2num(query_donor_select.item[3]))
// Inactive donator.
donator_level = 0
qdel(query_donor_select)
return
donator_level = text2num(query_donor_select.item[2])
donor_loadout_points()
break
qdel(query_donor_select)
/client/proc/donor_loadout_points()
if(donator_level > 0 && prefs)
prefs.max_gear_slots = GLOB.configuration.general.base_loadout_points + 5
/client/proc/log_client_to_db(connectiontopic)
set waitfor = FALSE // This needs to run async because any sleep() inside /client/New() breaks stuff badly
if(IsGuestKey(key))
return
if(!SSdbcore.IsConnected())
return
var/datum/db_query/query = SSdbcore.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM player WHERE ckey=:ckey", list(
var/datum/db_query/query = SSdbcore.NewQuery("SELECT id, datediff(Now(), firstseen) as age FROM player WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query.warn_execute())
@@ -488,67 +479,29 @@
break
qdel(query)
var/datum/db_query/query_ip = SSdbcore.NewQuery("SELECT ckey FROM player WHERE ip=:address", list(
"address" = address
))
if(!query_ip.warn_execute())
qdel(query_ip)
return
related_accounts_ip = list()
while(query_ip.NextRow())
if(ckey != query_ip.item[1])
related_accounts_ip.Add("[query_ip.item[1]]")
qdel(query_ip)
var/datum/db_query/query_cid = SSdbcore.NewQuery("SELECT ckey FROM player WHERE computerid=:cid", list(
"cid" = computer_id
))
if(!query_cid.warn_execute())
qdel(query_cid)
return
related_accounts_cid = list()
while(query_cid.NextRow())
if(ckey != query_cid.item[1])
related_accounts_cid.Add("[query_cid.item[1]]")
qdel(query_cid)
var/admin_rank = "Player"
// Admins don't get slammed by this, I guess
if(holder)
admin_rank = holder.rank
// Admins don't get slammed by this, I guess
else
if(check_randomizer(connectiontopic))
return
//Log all the alts
if(related_accounts_cid.len)
log_admin("[key_name(src)] alts:[jointext(related_accounts_cid, " - ")]")
var/watchreason = check_watchlist(ckey)
if(watchreason)
message_admins("<font color='red'><B>Notice: </B></font><font color='blue'>[key_name_admin(src)] is on the watchlist and has just connected - Reason: [watchreason]</font>")
SSdiscord.send2discord_simple_noadmins("**\[Watchlist]** [key_name(src)] is on the watchlist and has just connected - Reason: [watchreason]")
watchlisted = TRUE
//Just the standard check to see if it's actually a number
if(sql_id)
//Just the standard check to see if it's actually a number
if(istext(sql_id))
sql_id = text2num(sql_id)
if(!isnum(sql_id))
return
return // Return here because if we somehow didnt pull a number from an INT column, EVERYTHING is breaking
if(sql_id)
var/client_address = address
if(!client_address) // Localhost can sometimes have no address set
client_address = "127.0.0.1"
//Player already identified previously, we need to just update the 'lastseen', 'ip' and 'computer_id' variables
var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE player SET lastseen = Now(), ip=:sql_ip, computerid=:sql_cid, lastadminrank=:sql_ar WHERE id=:sql_id", list(
var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE player SET lastseen=NOW(), ip=:sql_ip, computerid=:sql_cid, lastadminrank=:sql_ar WHERE id=:sql_id", list(
"sql_ip" = client_address,
"sql_cid" = computer_id,
"sql_ar" = admin_rank,
@@ -558,6 +511,7 @@
if(!query_update.warn_execute())
qdel(query_update)
return
qdel(query_update)
// After the regular update
INVOKE_ASYNC(src, /client/.proc/get_byond_account_date, FALSE) // Async to avoid other procs in the client chain being delayed by a web request
@@ -573,7 +527,7 @@
qdel(query_insert)
return
qdel(query_insert)
// This is their first connection instance, so TRUE here to nofiy admins
// This is their first connection instance, so TRUE here to notify admins
// This needs to happen here to ensure they actually have a row to update
INVOKE_ASYNC(src, /client/.proc/get_byond_account_date, TRUE) // Async to avoid other procs in the client chain being delayed by a web request
@@ -1059,7 +1013,7 @@
qdel(query_date)
// They have a date, lets bail
// They have a date already, lets bail
if(byondacc_date)
return
@@ -1100,120 +1054,6 @@
/client/proc/show_update_notice()
to_chat(src, "<span class='userdanger'>Your BYOND client (v: [byond_version].[byond_build]) is out of date. This can cause glitches. We highly suggest you download the latest client from <a href='https://www.byond.com/download/'>byond.com</a> before playing. You can also update via the BYOND launcher application.</span>")
/**
* Checks if the client has accepted TOS
*
* Runs some checks against vars and the DB to see if the client has accepted TOS.
* Returns TRUE or FALSE if they have or have not
*/
/client/proc/check_tos_consent()
// If there is no TOS, auto accept
if(!GLOB.join_tos)
tos_consent = TRUE
return TRUE
// If theres no DB, assume yes
if(!SSdbcore.IsConnected())
tos_consent = TRUE
return TRUE
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey FROM privacy WHERE ckey=:ckey AND consent=1", list(
"ckey" = ckey
))
if(!query.warn_execute())
qdel(query)
// If our query failed, just assume yes
tos_consent = TRUE
return TRUE
// If we returned a row, they accepted
while(query.NextRow())
qdel(query)
tos_consent = TRUE
return TRUE
qdel(query)
// If we are here, they have not accepted, and need to read it
return FALSE
/**
* Checks if the client has more than a configured amount of CIDs tied to them in the past
*/
/client/proc/cid_count_check()
// If the config is 0, disable this
if(GLOB.configuration.general.max_client_cid_history == 0)
return
// If we have no DB, dont even bother
if(!SSdbcore.IsConnected())
return
// Now query how many cids they have
var/datum/db_query/query_cidcheck = SSdbcore.NewQuery("SELECT COUNT(DISTINCT computerID) FROM connection_log WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query_cidcheck.warn_execute())
qdel(query_cidcheck)
return
var/cidcount = 0
if(query_cidcheck.NextRow())
cidcount = query_cidcheck.item[1]
qdel(query_cidcheck)
if(cidcount > GLOB.configuration.general.max_client_cid_history)
// Check their notes for CID tracking in the past
var/has_note = FALSE
var/note_text = ""
var/datum/db_query/query_find_track_note = SSdbcore.NewQuery("SELECT notetext FROM notes WHERE ckey=:ckey AND adminckey=:ackey", list(
"ckey" = ckey,
"ackey" = CIDTRACKING_PSUEDO_CKEY
))
if(!query_find_track_note.warn_execute())
qdel(query_find_track_note)
return
if(query_find_track_note.NextRow())
note_text = query_find_track_note.item[1] // Grab existing note text
has_note = TRUE
qdel(query_find_track_note)
if(has_note) // They have a note. Update it.
var/new_text = "Connected on the date of this note with unique CID #[cidcount]"
// Only update the note if the text is different. Otherwise it bumps the timestamp when it shouldnt
if(note_text != new_text)
var/datum/db_query/query_update_track_note = SSdbcore.NewQuery("UPDATE notes SET notetext=:notetext, timestamp=NOW(), round_id=:rid WHERE ckey=:ckey AND adminckey=:ackey", list(
"notetext" = new_text,
"ckey" = ckey,
"ackey" = CIDTRACKING_PSUEDO_CKEY,
"rid" = GLOB.round_id
))
if(!query_update_track_note.warn_execute())
qdel(query_update_track_note)
return
qdel(query_update_track_note)
else // They dont have a note. Make one.
// NOT logged because its automatic and will spam logs otherwise
// Also right checking must be disabled because its a psuedockey, not a real one
add_note(ckey, "Connected on the date of this note with unique CID #[cidcount]", adminckey = CIDTRACKING_PSUEDO_CKEY, logged = FALSE, checkrights = FALSE, automated = TRUE)
var/show_warning = TRUE
// Check if they have a note that matches the warning suppressor
var/datum/db_query/query_find_note = SSdbcore.NewQuery("SELECT id FROM notes WHERE ckey=:ckey AND notetext=:notetext", list(
"ckey" = ckey,
"notetext" = CIDWARNING_SUPPRESSED_NOTETEXT
))
if(!query_find_note.warn_execute())
qdel(query_find_note)
return
if(query_find_note.NextRow())
show_warning = FALSE
qdel(query_find_note)
if(show_warning)
message_admins("<font color='red'>[ckey] has just connected and has a history of [cidcount] different CIDs.</font> (<a href='?_src_=holder;webtools=[ckey]'>WebInfo</a>) (<a href='?_src_=holder;suppresscidwarning=[ckey]'>Suppress Warning</a>)")
/client/proc/update_ambience_pref()
if(prefs.sound & SOUND_AMBIENCE)
if(SSambience.ambience_listening_clients[src] > world.time)