mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-19 02:54:41 +01:00
Refactors client data loading
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/datum/client_login_processor/load_preferences
|
||||
priority = 10
|
||||
|
||||
/datum/client_login_processor/load_preferences/get_query(client/C)
|
||||
var/datum/db_query/query = SSdbcore.NewQuery({"SELECT
|
||||
ooccolor,
|
||||
UI_style,
|
||||
UI_style_color,
|
||||
UI_style_alpha,
|
||||
be_role,
|
||||
default_slot,
|
||||
toggles,
|
||||
toggles_2,
|
||||
sound,
|
||||
volume_mixer,
|
||||
lastchangelog,
|
||||
exp,
|
||||
clientfps,
|
||||
atklog,
|
||||
fuid,
|
||||
parallax,
|
||||
2fa_status
|
||||
FROM player
|
||||
WHERE ckey=:ckey"}, list(
|
||||
"ckey" = C.ckey
|
||||
))
|
||||
|
||||
return query
|
||||
|
||||
/datum/client_login_processor/load_preferences/process_result(datum/db_query/Q, client/C)
|
||||
C.prefs = GLOB.preferences_datums[C.ckey]
|
||||
if(!C.prefs)
|
||||
C.prefs = new /datum/preferences(C, Q)
|
||||
GLOB.preferences_datums[C.ckey] = C.prefs
|
||||
else
|
||||
C.prefs.parent = C
|
||||
@@ -0,0 +1,106 @@
|
||||
// AA TODO:
|
||||
// - split character out of the prefs datum
|
||||
// - make this load **ALL CHARACTERS**
|
||||
// - make a post_load() op for stuff
|
||||
/datum/client_login_processor/load_characters
|
||||
priority = 20
|
||||
|
||||
/datum/client_login_processor/load_characters/get_query(client/C)
|
||||
// Get all their characters
|
||||
var/datum/db_query/query = SSdbcore.NewQuery({"SELECT
|
||||
OOC_Notes,
|
||||
real_name,
|
||||
name_is_always_random,
|
||||
gender,
|
||||
age,
|
||||
species,
|
||||
language,
|
||||
hair_colour,
|
||||
secondary_hair_colour,
|
||||
facial_hair_colour,
|
||||
secondary_facial_hair_colour,
|
||||
skin_tone,
|
||||
skin_colour,
|
||||
marking_colours,
|
||||
head_accessory_colour,
|
||||
hair_style_name,
|
||||
facial_style_name,
|
||||
marking_styles,
|
||||
head_accessory_style_name,
|
||||
alt_head_name,
|
||||
eye_colour,
|
||||
underwear,
|
||||
undershirt,
|
||||
backbag,
|
||||
b_type,
|
||||
alternate_option,
|
||||
job_support_high,
|
||||
job_support_med,
|
||||
job_support_low,
|
||||
job_medsci_high,
|
||||
job_medsci_med,
|
||||
job_medsci_low,
|
||||
job_engsec_high,
|
||||
job_engsec_med,
|
||||
job_engsec_low,
|
||||
job_karma_high,
|
||||
job_karma_med,
|
||||
job_karma_low,
|
||||
flavor_text,
|
||||
med_record,
|
||||
sec_record,
|
||||
gen_record,
|
||||
disabilities,
|
||||
player_alt_titles,
|
||||
organ_data,
|
||||
rlimb_data,
|
||||
nanotrasen_relation,
|
||||
speciesprefs,
|
||||
socks,
|
||||
body_accessory,
|
||||
gear,
|
||||
autohiss,
|
||||
slot
|
||||
FROM characters WHERE ckey=:ckey"}, list(
|
||||
"ckey" = C.ckey
|
||||
))
|
||||
|
||||
return query
|
||||
|
||||
/datum/client_login_processor/load_characters/process_result(datum/db_query/Q, client/C)
|
||||
// If we already loaded their characters, dont do it all again
|
||||
if(C.prefs.characters_loaded)
|
||||
return
|
||||
// Step one, initialize their list of characters
|
||||
C.prefs.character_saves = list()
|
||||
C.prefs.character_saves.len = C.prefs.max_save_slots // Fill the list with empty indexes
|
||||
// Fill it with blank characters first
|
||||
for(var/i in 1 to C.prefs.max_save_slots)
|
||||
var/datum/character_save/CS = new()
|
||||
CS.slot_number = i
|
||||
C.prefs.character_saves[i] = CS
|
||||
|
||||
// Did we load at all
|
||||
var/character_loaded = FALSE
|
||||
|
||||
while(Q.NextRow())
|
||||
character_loaded = TRUE
|
||||
var/datum/character_save/CS = C.prefs.character_saves[Q.item[53]] // Get the slot referenced by this query
|
||||
CS.load(Q) // Let the save handle the query processing
|
||||
CS.valid_save = TRUE
|
||||
|
||||
if(character_loaded)
|
||||
// They have a character, set their active as their default slot
|
||||
C.prefs.active_character = C.prefs.character_saves[C.prefs.default_slot]
|
||||
else
|
||||
// If we are here, they dont have a character. Lets make them a random one
|
||||
var/datum/character_save/CS = C.prefs.character_saves[1] // Get slot 1
|
||||
CS.randomise()
|
||||
CS.real_name = random_name(CS.gender) // Pick a name
|
||||
CS.valid_save = TRUE
|
||||
CS.save()
|
||||
C.prefs.active_character = C.prefs.character_saves[1] // Set slot 1 as their active
|
||||
C.prefs.default_slot = 1
|
||||
C.prefs.save_preferences(C)
|
||||
|
||||
C.prefs.characters_loaded = TRUE // Avoid this happening again
|
||||
@@ -0,0 +1,24 @@
|
||||
/datum/client_login_processor/tos_consent
|
||||
priority = 30
|
||||
|
||||
/datum/client_login_processor/tos_consent/get_query(client/C)
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey FROM privacy WHERE ckey=:ckey AND consent=1", list(
|
||||
"ckey" = C.ckey
|
||||
))
|
||||
return query
|
||||
|
||||
/datum/client_login_processor/tos_consent/process_result(datum/db_query/Q, client/C)
|
||||
// If there is no TOS, auto accept
|
||||
if(!GLOB.join_tos)
|
||||
C.tos_consent = TRUE
|
||||
return
|
||||
|
||||
// If our query failed, just assume yes
|
||||
if(Q.last_error)
|
||||
C.tos_consent = TRUE
|
||||
return
|
||||
|
||||
// If we returned a row, they accepted
|
||||
while(Q.NextRow())
|
||||
C.tos_consent = TRUE
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/datum/client_login_processor/donator_check
|
||||
priority = 35
|
||||
|
||||
/datum/client_login_processor/donator_check/get_query(client/C)
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, tier, active FROM donators WHERE ckey=:ckey", list(
|
||||
"ckey" = C.ckey
|
||||
))
|
||||
return query
|
||||
|
||||
/datum/client_login_processor/donator_check/process_result(datum/db_query/Q, client/C)
|
||||
if(IsGuestKey(C.key))
|
||||
return
|
||||
|
||||
// Admins get all donor perks
|
||||
if(check_rights_client(R_ADMIN, FALSE, C))
|
||||
C.donator_level = DONATOR_LEVEL_MAX
|
||||
C.donor_loadout_points()
|
||||
return
|
||||
|
||||
while(Q.NextRow())
|
||||
if(!text2num(Q.item[3]))
|
||||
// Inactive donator.
|
||||
C.donator_level = 0
|
||||
return
|
||||
|
||||
C.donator_level = text2num(Q.item[2])
|
||||
C.donor_loadout_points()
|
||||
@@ -0,0 +1,15 @@
|
||||
/datum/client_login_processor/watchlist
|
||||
priority = 36
|
||||
|
||||
/datum/client_login_processor/watchlist/get_query(client/C)
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT reason FROM watch WHERE ckey=:target_ckey", list(
|
||||
"target_ckey" = C.ckey
|
||||
))
|
||||
return query
|
||||
|
||||
/datum/client_login_processor/watchlist/process_result(datum/db_query/Q, client/C)
|
||||
if(Q.NextRow())
|
||||
var/watchreason = Q.item[1]
|
||||
message_admins("<font color='red'><B>Notice: </B></font><font color='blue'>[key_name_admin(C)] is on the watchlist and has just connected - Reason: [watchreason]</font>")
|
||||
SSdiscord.send2discord_simple_noadmins("**\[Watchlist]** [key_name(C)] is on the watchlist and has just connected - Reason: [watchreason]")
|
||||
C.watchlisted = TRUE
|
||||
@@ -0,0 +1,14 @@
|
||||
/datum/client_login_processor/alts_ip
|
||||
priority = 37
|
||||
|
||||
/datum/client_login_processor/alts_ip/get_query(client/C)
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey FROM player WHERE ip=:address", list(
|
||||
"address" = C.address
|
||||
))
|
||||
return query
|
||||
|
||||
/datum/client_login_processor/alts_ip/process_result(datum/db_query/Q, client/C)
|
||||
while(Q.NextRow())
|
||||
if("[Q.item[1]]" == C.ckey)
|
||||
continue
|
||||
C.related_accounts_ip.Add("[Q.item[1]]")
|
||||
@@ -0,0 +1,14 @@
|
||||
/datum/client_login_processor/alts_cid
|
||||
priority = 38
|
||||
|
||||
/datum/client_login_processor/alts_cid/get_query(client/C)
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey FROM player WHERE computerid=:cid", list(
|
||||
"cid" = C.computer_id
|
||||
))
|
||||
return query
|
||||
|
||||
/datum/client_login_processor/alts_cid/process_result(datum/db_query/Q, client/C)
|
||||
while(Q.NextRow())
|
||||
if("[Q.item[1]]" == C.ckey)
|
||||
continue
|
||||
C.related_accounts_cid.Add("[Q.item[1]]")
|
||||
@@ -0,0 +1,71 @@
|
||||
/datum/client_login_processor/cid_count
|
||||
priority = 39
|
||||
|
||||
/datum/client_login_processor/cid_count/get_query(client/C)
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT COUNT(DISTINCT computerID) FROM connection_log WHERE ckey=:ckey", list(
|
||||
"ckey" = C.ckey
|
||||
))
|
||||
return query
|
||||
|
||||
/datum/client_login_processor/cid_count/process_result(datum/db_query/Q, client/C)
|
||||
// If the config is 0, disable this
|
||||
if(GLOB.configuration.general.max_client_cid_history == 0)
|
||||
return
|
||||
|
||||
// Now query how many cids they have
|
||||
var/cidcount = 0
|
||||
if(Q.NextRow())
|
||||
cidcount = Q.item[1]
|
||||
|
||||
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" = C.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" = C.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(C.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" = C.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'>[C.ckey] has just connected and has a history of [cidcount] different CIDs.</font> (<a href='?_src_=holder;webtools=[C.ckey]'>WebInfo</a>) (<a href='?_src_=holder;suppresscidwarning=[C.ckey]'>Suppress Warning</a>)")
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* # Client Login Processor Framework
|
||||
*
|
||||
* The holder class for all client data processing
|
||||
*
|
||||
* This framework is designed for loading in client data from the database.
|
||||
* Login processors have their own queries, which will be put into one async batch and
|
||||
* executed at the same time, to reduce the time it takes for a client to login.
|
||||
* Login processors can also be given priorities to have things fire in specific orders
|
||||
* EG: Load their preferences before their job bans, etc etc
|
||||
*
|
||||
* When creating these, please name the files with the priority at the start, and the typepath after
|
||||
* EG: 10-load_preferences.dm
|
||||
* This makes it easier to track stuff down -AA07
|
||||
*
|
||||
* Also if you have used other languages before with "interface" types (Java, C# (Microsoft Java), etc),
|
||||
* treat this class as one of those. [get_query(client/C)] and [process_result(datum/db_query/Q, client/C)] MUST be overriden
|
||||
*/
|
||||
/datum/client_login_processor
|
||||
/// The login priority. A lower priority will fire first
|
||||
var/priority = 0
|
||||
|
||||
/**
|
||||
* Query Getter
|
||||
*
|
||||
* Gets the DB query for this login processor
|
||||
*
|
||||
* Takes the client as an arg instead of just the ckey incase we need more data (IP, CID, etc).
|
||||
* Returns a DB query datum.
|
||||
*
|
||||
* Arguments:
|
||||
* * C - The client to use to generate the query
|
||||
*/
|
||||
/datum/client_login_processor/proc/get_query(client/C)
|
||||
RETURN_TYPE(/datum/db_query)
|
||||
CRASH("get_query() not overriden for [type]!")
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Result Processor
|
||||
*
|
||||
* Takes the (now executed) query and the client and parses the required data out
|
||||
* Note: This can be a no-op if you want to just update the DB, just return on the override
|
||||
*
|
||||
* Arguments:
|
||||
* * Q - The DB query to process data from
|
||||
* * C - The client to store stuff on
|
||||
*/
|
||||
/datum/client_login_processor/proc/process_result(datum/db_query/Q, client/C)
|
||||
CRASH("process_result() not overriden for [type]!")
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,32 +1,6 @@
|
||||
/datum/preferences/proc/load_preferences(client/C)
|
||||
|
||||
var/datum/db_query/query = SSdbcore.NewQuery({"SELECT
|
||||
ooccolor,
|
||||
UI_style,
|
||||
UI_style_color,
|
||||
UI_style_alpha,
|
||||
be_role,
|
||||
default_slot,
|
||||
toggles,
|
||||
toggles_2,
|
||||
sound,
|
||||
volume_mixer,
|
||||
lastchangelog,
|
||||
exp,
|
||||
clientfps,
|
||||
atklog,
|
||||
fuid,
|
||||
parallax,
|
||||
2fa_status
|
||||
FROM player
|
||||
WHERE ckey=:ckey"}, list(
|
||||
"ckey" = C.ckey
|
||||
))
|
||||
|
||||
if(!query.warn_execute())
|
||||
qdel(query)
|
||||
return
|
||||
|
||||
/datum/preferences/proc/load_preferences(datum/db_query/query)
|
||||
// Looking for the query?
|
||||
// Check ../login_processing/10-load_preferences.dm
|
||||
|
||||
//general preferences
|
||||
while(query.NextRow())
|
||||
@@ -48,8 +22,6 @@
|
||||
parallax = text2num(query.item[16])
|
||||
_2fa_status = query.item[17]
|
||||
|
||||
qdel(query)
|
||||
|
||||
//Sanitize
|
||||
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
|
||||
UI_style = sanitize_inlist(UI_style, list("White", "Midnight", "Plasmafire", "Retro", "Slimecore", "Operative"), initial(UI_style))
|
||||
@@ -65,7 +37,7 @@
|
||||
atklog = sanitize_integer(atklog, 0, 100, initial(atklog))
|
||||
fuid = sanitize_integer(fuid, 0, 10000000, initial(fuid))
|
||||
parallax = sanitize_integer(parallax, 0, 16, initial(parallax))
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/datum/preferences/proc/save_preferences(client/C)
|
||||
|
||||
@@ -126,545 +98,24 @@
|
||||
qdel(query)
|
||||
return 1
|
||||
|
||||
/datum/preferences/proc/load_character(client/C,slot)
|
||||
saved = FALSE
|
||||
|
||||
if(!slot) slot = default_slot
|
||||
slot = sanitize_integer(slot, 1, max_save_slots, initial(default_slot))
|
||||
if(slot != default_slot)
|
||||
default_slot = slot
|
||||
var/datum/db_query/firstquery = SSdbcore.NewQuery("UPDATE player SET default_slot=:slot WHERE ckey=:ckey", list(
|
||||
"slot" = slot,
|
||||
"ckey" = C.ckey
|
||||
))
|
||||
if(!firstquery.warn_execute(async = FALSE)) // Dont make this async. It makes roundstart slow.
|
||||
qdel(firstquery)
|
||||
return
|
||||
qdel(firstquery)
|
||||
|
||||
// Let's not have this explode if you sneeze on the DB
|
||||
var/datum/db_query/query = SSdbcore.NewQuery({"SELECT
|
||||
OOC_Notes,
|
||||
real_name,
|
||||
name_is_always_random,
|
||||
gender,
|
||||
age,
|
||||
species,
|
||||
language,
|
||||
hair_colour,
|
||||
secondary_hair_colour,
|
||||
facial_hair_colour,
|
||||
secondary_facial_hair_colour,
|
||||
skin_tone,
|
||||
skin_colour,
|
||||
marking_colours,
|
||||
head_accessory_colour,
|
||||
hair_style_name,
|
||||
facial_style_name,
|
||||
marking_styles,
|
||||
head_accessory_style_name,
|
||||
alt_head_name,
|
||||
eye_colour,
|
||||
underwear,
|
||||
undershirt,
|
||||
backbag,
|
||||
b_type,
|
||||
alternate_option,
|
||||
job_support_high,
|
||||
job_support_med,
|
||||
job_support_low,
|
||||
job_medsci_high,
|
||||
job_medsci_med,
|
||||
job_medsci_low,
|
||||
job_engsec_high,
|
||||
job_engsec_med,
|
||||
job_engsec_low,
|
||||
job_karma_high,
|
||||
job_karma_med,
|
||||
job_karma_low,
|
||||
flavor_text,
|
||||
med_record,
|
||||
sec_record,
|
||||
gen_record,
|
||||
disabilities,
|
||||
player_alt_titles,
|
||||
organ_data,
|
||||
rlimb_data,
|
||||
nanotrasen_relation,
|
||||
speciesprefs,
|
||||
socks,
|
||||
body_accessory,
|
||||
gear,
|
||||
autohiss
|
||||
FROM characters WHERE ckey=:ckey AND slot=:slot"}, list(
|
||||
"ckey" = C.ckey,
|
||||
"slot" = slot
|
||||
))
|
||||
if(!query.warn_execute(async = FALSE)) // Dont make this async. It makes roundstart slow.
|
||||
qdel(query)
|
||||
return
|
||||
|
||||
while(query.NextRow())
|
||||
//Character
|
||||
metadata = query.item[1]
|
||||
real_name = query.item[2]
|
||||
be_random_name = text2num(query.item[3])
|
||||
gender = query.item[4]
|
||||
age = text2num(query.item[5])
|
||||
species = query.item[6]
|
||||
language = query.item[7]
|
||||
|
||||
h_colour = query.item[8]
|
||||
h_sec_colour = query.item[9]
|
||||
f_colour = query.item[10]
|
||||
f_sec_colour = query.item[11]
|
||||
s_tone = text2num(query.item[12])
|
||||
s_colour = query.item[13]
|
||||
m_colours = params2list(query.item[14])
|
||||
hacc_colour = query.item[15]
|
||||
h_style = query.item[16]
|
||||
f_style = query.item[17]
|
||||
m_styles = params2list(query.item[18])
|
||||
ha_style = query.item[19]
|
||||
alt_head = query.item[20]
|
||||
e_colour = query.item[21]
|
||||
underwear = query.item[22]
|
||||
undershirt = query.item[23]
|
||||
backbag = query.item[24]
|
||||
b_type = query.item[25]
|
||||
|
||||
|
||||
//Jobs
|
||||
alternate_option = text2num(query.item[26])
|
||||
job_support_high = text2num(query.item[27])
|
||||
job_support_med = text2num(query.item[28])
|
||||
job_support_low = text2num(query.item[29])
|
||||
job_medsci_high = text2num(query.item[30])
|
||||
job_medsci_med = text2num(query.item[31])
|
||||
job_medsci_low = text2num(query.item[32])
|
||||
job_engsec_high = text2num(query.item[33])
|
||||
job_engsec_med = text2num(query.item[34])
|
||||
job_engsec_low = text2num(query.item[35])
|
||||
job_karma_high = text2num(query.item[36])
|
||||
job_karma_med = text2num(query.item[37])
|
||||
job_karma_low = text2num(query.item[38])
|
||||
|
||||
//Miscellaneous
|
||||
flavor_text = query.item[39]
|
||||
med_record = query.item[40]
|
||||
sec_record = query.item[41]
|
||||
gen_record = query.item[42]
|
||||
// Apparently, the preceding vars weren't always encoded properly...
|
||||
if(findtext(flavor_text, "<")) // ... so let's clumsily check for tags!
|
||||
flavor_text = html_encode(flavor_text)
|
||||
if(findtext(med_record, "<"))
|
||||
med_record = html_encode(med_record)
|
||||
if(findtext(sec_record, "<"))
|
||||
sec_record = html_encode(sec_record)
|
||||
if(findtext(gen_record, "<"))
|
||||
gen_record = html_encode(gen_record)
|
||||
disabilities = text2num(query.item[43])
|
||||
player_alt_titles = params2list(query.item[44])
|
||||
organ_data = params2list(query.item[45])
|
||||
rlimb_data = params2list(query.item[46])
|
||||
nanotrasen_relation = query.item[47]
|
||||
speciesprefs = text2num(query.item[48])
|
||||
|
||||
//socks
|
||||
socks = query.item[49]
|
||||
body_accessory = query.item[50]
|
||||
loadout_gear = params2list(query.item[51])
|
||||
autohiss_mode = text2num(query.item[52])
|
||||
|
||||
saved = TRUE
|
||||
|
||||
qdel(query)
|
||||
//Sanitize
|
||||
var/datum/species/SP = GLOB.all_species[species]
|
||||
metadata = sanitize_text(metadata, initial(metadata))
|
||||
real_name = reject_bad_name(real_name, 1)
|
||||
if(isnull(species)) species = "Human"
|
||||
if(isnull(language)) language = "None"
|
||||
if(isnull(nanotrasen_relation)) nanotrasen_relation = initial(nanotrasen_relation)
|
||||
if(isnull(speciesprefs)) speciesprefs = initial(speciesprefs)
|
||||
if(!real_name) real_name = random_name(gender,species)
|
||||
be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name))
|
||||
gender = sanitize_gender(gender, FALSE, !SP.has_gender)
|
||||
age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age))
|
||||
h_colour = sanitize_hexcolor(h_colour)
|
||||
h_sec_colour = sanitize_hexcolor(h_sec_colour)
|
||||
f_colour = sanitize_hexcolor(f_colour)
|
||||
f_sec_colour = sanitize_hexcolor(f_sec_colour)
|
||||
s_tone = sanitize_integer(s_tone, -185, 34, initial(s_tone))
|
||||
s_colour = sanitize_hexcolor(s_colour)
|
||||
for(var/marking_location in m_colours)
|
||||
m_colours[marking_location] = sanitize_hexcolor(m_colours[marking_location], DEFAULT_MARKING_COLOURS[marking_location])
|
||||
hacc_colour = sanitize_hexcolor(hacc_colour)
|
||||
h_style = sanitize_inlist(h_style, GLOB.hair_styles_public_list, initial(h_style))
|
||||
f_style = sanitize_inlist(f_style, GLOB.facial_hair_styles_list, initial(f_style))
|
||||
for(var/marking_location in m_styles)
|
||||
m_styles[marking_location] = sanitize_inlist(m_styles[marking_location], GLOB.marking_styles_list, DEFAULT_MARKING_STYLES[marking_location])
|
||||
ha_style = sanitize_inlist(ha_style, GLOB.head_accessory_styles_list, initial(ha_style))
|
||||
alt_head = sanitize_inlist(alt_head, GLOB.alt_heads_list, initial(alt_head))
|
||||
e_colour = sanitize_hexcolor(e_colour)
|
||||
underwear = sanitize_text(underwear, initial(underwear))
|
||||
undershirt = sanitize_text(undershirt, initial(undershirt))
|
||||
backbag = sanitize_text(backbag, initial(backbag))
|
||||
b_type = sanitize_text(b_type, initial(b_type))
|
||||
autohiss_mode = sanitize_integer(autohiss_mode, 0, 2, initial(autohiss_mode))
|
||||
|
||||
alternate_option = sanitize_integer(alternate_option, 0, 2, initial(alternate_option))
|
||||
job_support_high = sanitize_integer(job_support_high, 0, 65535, initial(job_support_high))
|
||||
job_support_med = sanitize_integer(job_support_med, 0, 65535, initial(job_support_med))
|
||||
job_support_low = sanitize_integer(job_support_low, 0, 65535, initial(job_support_low))
|
||||
job_medsci_high = sanitize_integer(job_medsci_high, 0, 65535, initial(job_medsci_high))
|
||||
job_medsci_med = sanitize_integer(job_medsci_med, 0, 65535, initial(job_medsci_med))
|
||||
job_medsci_low = sanitize_integer(job_medsci_low, 0, 65535, initial(job_medsci_low))
|
||||
job_engsec_high = sanitize_integer(job_engsec_high, 0, 65535, initial(job_engsec_high))
|
||||
job_engsec_med = sanitize_integer(job_engsec_med, 0, 65535, initial(job_engsec_med))
|
||||
job_engsec_low = sanitize_integer(job_engsec_low, 0, 65535, initial(job_engsec_low))
|
||||
job_karma_high = sanitize_integer(job_karma_high, 0, 65535, initial(job_karma_high))
|
||||
job_karma_med = sanitize_integer(job_karma_med, 0, 65535, initial(job_karma_med))
|
||||
job_karma_low = sanitize_integer(job_karma_low, 0, 65535, initial(job_karma_low))
|
||||
disabilities = sanitize_integer(disabilities, 0, 65535, initial(disabilities))
|
||||
|
||||
socks = sanitize_text(socks, initial(socks))
|
||||
body_accessory = sanitize_text(body_accessory, initial(body_accessory))
|
||||
|
||||
// if(isnull(disabilities)) disabilities = 0
|
||||
if(!player_alt_titles) player_alt_titles = new()
|
||||
if(!organ_data) src.organ_data = list()
|
||||
if(!rlimb_data) src.rlimb_data = list()
|
||||
if(!loadout_gear) loadout_gear = list()
|
||||
|
||||
// Check if the current body accessory exists
|
||||
if(!GLOB.body_accessory_by_name[body_accessory])
|
||||
body_accessory = null
|
||||
|
||||
return 1
|
||||
|
||||
/datum/preferences/proc/save_character(client/C)
|
||||
var/organlist
|
||||
var/rlimblist
|
||||
var/playertitlelist
|
||||
var/gearlist
|
||||
|
||||
var/markingcolourslist = list2params(m_colours)
|
||||
var/markingstyleslist = list2params(m_styles)
|
||||
if(!isemptylist(organ_data))
|
||||
organlist = list2params(organ_data)
|
||||
if(!isemptylist(rlimb_data))
|
||||
rlimblist = list2params(rlimb_data)
|
||||
if(!isemptylist(player_alt_titles))
|
||||
playertitlelist = list2params(player_alt_titles)
|
||||
if(!isemptylist(loadout_gear))
|
||||
gearlist = list2params(loadout_gear)
|
||||
|
||||
var/datum/db_query/firstquery = SSdbcore.NewQuery("SELECT slot FROM characters WHERE ckey=:ckey ORDER BY slot", list(
|
||||
"ckey" = C.ckey
|
||||
))
|
||||
if(!firstquery.warn_execute())
|
||||
qdel(firstquery)
|
||||
return
|
||||
while(firstquery.NextRow())
|
||||
if(text2num(firstquery.item[1]) == default_slot)
|
||||
var/datum/db_query/query = SSdbcore.NewQuery({"UPDATE characters
|
||||
SET
|
||||
OOC_Notes=:metadata,
|
||||
real_name=:real_name,
|
||||
name_is_always_random=:be_random_name,
|
||||
gender=:gender,
|
||||
age=:age,
|
||||
species=:species,
|
||||
language=:language,
|
||||
hair_colour=:h_colour,
|
||||
secondary_hair_colour=:h_sec_colour,
|
||||
facial_hair_colour=:f_colour,
|
||||
secondary_facial_hair_colour=:f_sec_colour,
|
||||
skin_tone=:s_tone,
|
||||
skin_colour=:s_colour,
|
||||
marking_colours=:markingcolourslist,
|
||||
head_accessory_colour=:hacc_colour,
|
||||
hair_style_name=:h_style,
|
||||
facial_style_name=:f_style,
|
||||
marking_styles=:markingstyleslist,
|
||||
head_accessory_style_name=:ha_style,
|
||||
alt_head_name=:alt_head,
|
||||
eye_colour=:e_colour,
|
||||
underwear=:underwear,
|
||||
undershirt=:undershirt,
|
||||
backbag=:backbag,
|
||||
b_type=:b_type,
|
||||
alternate_option=:alternate_option,
|
||||
job_support_high=:job_support_high,
|
||||
job_support_med=:job_support_med,
|
||||
job_support_low=:job_support_low,
|
||||
job_medsci_high=:job_medsci_high,
|
||||
job_medsci_med=:job_medsci_med,
|
||||
job_medsci_low=:job_medsci_low,
|
||||
job_engsec_high=:job_engsec_high,
|
||||
job_engsec_med=:job_engsec_med,
|
||||
job_engsec_low=:job_engsec_low,
|
||||
job_karma_high=:job_karma_high,
|
||||
job_karma_med=:job_karma_med,
|
||||
job_karma_low=:job_karma_low,
|
||||
flavor_text=:flavor_text,
|
||||
med_record=:med_record,
|
||||
sec_record=:sec_record,
|
||||
gen_record=:gen_record,
|
||||
player_alt_titles=:playertitlelist,
|
||||
disabilities=:disabilities,
|
||||
organ_data=:organlist,
|
||||
rlimb_data=:rlimblist,
|
||||
nanotrasen_relation=:nanotrasen_relation,
|
||||
speciesprefs=:speciesprefs,
|
||||
socks=:socks,
|
||||
body_accessory=:body_accessory,
|
||||
gear=:gearlist,
|
||||
autohiss=:autohiss_mode
|
||||
WHERE ckey=:ckey
|
||||
AND slot=:slot"}, list(
|
||||
// OH GOD SO MANY PARAMETERS
|
||||
"metadata" = metadata,
|
||||
"real_name" = real_name,
|
||||
"be_random_name" = be_random_name,
|
||||
"gender" = gender,
|
||||
"age" = age,
|
||||
"species" = species,
|
||||
"language" = language,
|
||||
"h_colour" = h_colour,
|
||||
"h_sec_colour" = h_sec_colour,
|
||||
"f_colour" = f_colour,
|
||||
"f_sec_colour" = f_sec_colour,
|
||||
"s_tone" = s_tone,
|
||||
"s_colour" = s_colour,
|
||||
"markingcolourslist" = markingcolourslist,
|
||||
"hacc_colour" = hacc_colour,
|
||||
"h_style" = h_style,
|
||||
"f_style" = f_style,
|
||||
"markingstyleslist" = markingstyleslist,
|
||||
"ha_style" = ha_style,
|
||||
"alt_head" = (alt_head ? alt_head : ""), // This it intentional. It wont work without it!
|
||||
"e_colour" = e_colour,
|
||||
"underwear" = underwear,
|
||||
"undershirt" = undershirt,
|
||||
"backbag" = backbag,
|
||||
"b_type" = b_type,
|
||||
"alternate_option" = alternate_option,
|
||||
"job_support_high" = job_support_high,
|
||||
"job_support_med" = job_support_med,
|
||||
"job_support_low" = job_support_low,
|
||||
"job_medsci_high" = job_medsci_high,
|
||||
"job_medsci_med" = job_medsci_med,
|
||||
"job_medsci_low" = job_medsci_low,
|
||||
"job_engsec_high" = job_engsec_high,
|
||||
"job_engsec_med" = job_engsec_med,
|
||||
"job_engsec_low" = job_engsec_low,
|
||||
"job_karma_high" = job_karma_high,
|
||||
"job_karma_med" = job_karma_med,
|
||||
"job_karma_low" = job_karma_low,
|
||||
"flavor_text" = flavor_text,
|
||||
"med_record" = med_record,
|
||||
"sec_record" = sec_record,
|
||||
"gen_record" = gen_record,
|
||||
"playertitlelist" = (playertitlelist ? playertitlelist : ""), // This it intentnional. It wont work without it!
|
||||
"disabilities" = disabilities,
|
||||
"organlist" = (organlist ? organlist : ""),
|
||||
"rlimblist" = (rlimblist ? rlimblist : ""),
|
||||
"nanotrasen_relation" = nanotrasen_relation,
|
||||
"speciesprefs" = speciesprefs,
|
||||
"socks" = socks,
|
||||
"body_accessory" = (body_accessory ? body_accessory : ""),
|
||||
"gearlist" = (gearlist ? gearlist : ""),
|
||||
"autohiss_mode" = autohiss_mode,
|
||||
"ckey" = C.ckey,
|
||||
"slot" = default_slot
|
||||
)
|
||||
)
|
||||
|
||||
if(!query.warn_execute())
|
||||
qdel(firstquery)
|
||||
qdel(query)
|
||||
return
|
||||
qdel(firstquery)
|
||||
qdel(query)
|
||||
return 1
|
||||
|
||||
qdel(firstquery)
|
||||
|
||||
var/datum/db_query/query = SSdbcore.NewQuery({"
|
||||
INSERT INTO characters (ckey, slot, OOC_Notes, real_name, name_is_always_random, gender,
|
||||
age, species, language,
|
||||
hair_colour, secondary_hair_colour,
|
||||
facial_hair_colour, secondary_facial_hair_colour,
|
||||
skin_tone, skin_colour,
|
||||
marking_colours,
|
||||
head_accessory_colour,
|
||||
hair_style_name,
|
||||
facial_style_name,
|
||||
marking_styles,
|
||||
head_accessory_style_name,
|
||||
alt_head_name,
|
||||
eye_colour,
|
||||
underwear, undershirt,
|
||||
backbag, b_type, alternate_option,
|
||||
job_support_high, job_support_med, job_support_low,
|
||||
job_medsci_high, job_medsci_med, job_medsci_low,
|
||||
job_engsec_high, job_engsec_med, job_engsec_low,
|
||||
job_karma_high, job_karma_med, job_karma_low,
|
||||
flavor_text,
|
||||
med_record,
|
||||
sec_record,
|
||||
gen_record,
|
||||
player_alt_titles,
|
||||
disabilities, organ_data, rlimb_data, nanotrasen_relation, speciesprefs,
|
||||
socks, body_accessory, gear, autohiss)
|
||||
|
||||
VALUES
|
||||
(:ckey, :slot, :metadata, :name, :be_random_name, :gender,
|
||||
:age, :species, :language,
|
||||
:h_colour, :h_sec_colour,
|
||||
:f_colour, :f_sec_colour,
|
||||
:s_tone, :s_colour,
|
||||
:markingcolourslist,
|
||||
:hacc_colour,
|
||||
:h_style,
|
||||
:f_style,
|
||||
:markingstyleslist,
|
||||
:ha_style,
|
||||
:alt_head,
|
||||
:e_colour,
|
||||
:underwear, :undershirt,
|
||||
:backbag, :b_type, :alternate_option,
|
||||
:job_support_high, :job_support_med, :job_support_low,
|
||||
:job_medsci_high, :job_medsci_med, :job_medsci_low,
|
||||
:job_engsec_high, :job_engsec_med, :job_engsec_low,
|
||||
:job_karma_high, :job_karma_med, :job_karma_low,
|
||||
:flavor_text,
|
||||
:med_record,
|
||||
:sec_record,
|
||||
:gen_record,
|
||||
:playertitlelist,
|
||||
:disabilities, :organlist, :rlimblist, :nanotrasen_relation, :speciesprefs,
|
||||
:socks, :body_accessory, :gearlist, :autohiss_mode)
|
||||
|
||||
"}, list(
|
||||
// This has too many params for anyone to look at this without going insae
|
||||
"ckey" = C.ckey,
|
||||
"slot" = default_slot,
|
||||
"metadata" = metadata,
|
||||
"name" = real_name,
|
||||
"be_random_name" = be_random_name,
|
||||
"gender" = gender,
|
||||
"age" = age,
|
||||
"species" = species,
|
||||
"language" = language,
|
||||
"h_colour" = h_colour,
|
||||
"h_sec_colour" = h_sec_colour,
|
||||
"f_colour" = f_colour,
|
||||
"f_sec_colour" = f_sec_colour,
|
||||
"s_tone" = s_tone,
|
||||
"s_colour" = s_colour,
|
||||
"markingcolourslist" = markingcolourslist,
|
||||
"hacc_colour" = hacc_colour,
|
||||
"h_style" = h_style,
|
||||
"f_style" = f_style,
|
||||
"markingstyleslist" = markingstyleslist,
|
||||
"ha_style" = ha_style,
|
||||
"alt_head" = alt_head,
|
||||
"e_colour" = e_colour,
|
||||
"underwear" = underwear,
|
||||
"undershirt" = undershirt,
|
||||
"backbag" = backbag,
|
||||
"b_type" = b_type,
|
||||
"alternate_option" = alternate_option,
|
||||
"job_support_high" = job_support_high,
|
||||
"job_support_med" = job_support_med,
|
||||
"job_support_low" = job_support_low,
|
||||
"job_medsci_high" = job_medsci_high,
|
||||
"job_medsci_med" = job_medsci_med,
|
||||
"job_medsci_low" = job_medsci_low,
|
||||
"job_engsec_high" = job_engsec_high,
|
||||
"job_engsec_med" = job_engsec_med,
|
||||
"job_engsec_low" = job_engsec_low,
|
||||
"job_karma_high" = job_karma_high,
|
||||
"job_karma_med" = job_karma_med,
|
||||
"job_karma_low" = job_karma_low,
|
||||
"flavor_text" = flavor_text,
|
||||
"med_record" = med_record,
|
||||
"sec_record" = sec_record,
|
||||
"gen_record" = gen_record,
|
||||
"playertitlelist" = (playertitlelist ? playertitlelist : ""), // This it intentnional. It wont work without it!
|
||||
"disabilities" = disabilities,
|
||||
"organlist" = (organlist ? organlist : ""),
|
||||
"rlimblist" = (rlimblist ? rlimblist : ""),
|
||||
"nanotrasen_relation" = nanotrasen_relation,
|
||||
"speciesprefs" = speciesprefs,
|
||||
"socks" = socks,
|
||||
"body_accessory" = (body_accessory ? body_accessory : ""),
|
||||
"gearlist" = (gearlist ? gearlist : ""),
|
||||
"autohiss_mode" = autohiss_mode
|
||||
))
|
||||
|
||||
if(!query.warn_execute())
|
||||
qdel(query)
|
||||
return
|
||||
|
||||
qdel(query)
|
||||
saved = TRUE
|
||||
return 1
|
||||
|
||||
/datum/preferences/proc/load_random_character_slot(client/C)
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT slot FROM characters WHERE ckey=:ckey ORDER BY slot", list(
|
||||
"ckey" = C.ckey
|
||||
))
|
||||
var/list/saves = list()
|
||||
var/list/datum/character_save/valid_slots = list()
|
||||
for(var/datum/character_save/CS in character_saves)
|
||||
if(CS.valid_save)
|
||||
valid_slots.Add(CS)
|
||||
|
||||
if(!query.warn_execute(async = FALSE)) // Dont async this. Youll make roundstart slow.
|
||||
qdel(query)
|
||||
if(!length(valid_slots))
|
||||
// They have no valid saves. Lets just randomise #1
|
||||
var/datum/character_save/CS = C.prefs.character_saves[1] // Get slot 1
|
||||
CS.randomise()
|
||||
CS.real_name = random_name(CS.gender) // Pick a name
|
||||
C.prefs.active_character = C.prefs.character_saves[1] // Set slot 1 as their active
|
||||
return
|
||||
|
||||
while(query.NextRow())
|
||||
saves += text2num(query.item[1])
|
||||
qdel(query)
|
||||
|
||||
if(!saves.len)
|
||||
load_character(C)
|
||||
return 0
|
||||
load_character(C,pick(saves))
|
||||
return 1
|
||||
|
||||
/datum/preferences/proc/clear_character_slot(client/C)
|
||||
. = FALSE
|
||||
// Is there a character in that slot?
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT slot FROM characters WHERE ckey=:ckey AND slot=:slot", list(
|
||||
"ckey" = C.ckey,
|
||||
"slot" = default_slot
|
||||
))
|
||||
|
||||
if(!query.warn_execute())
|
||||
qdel(query)
|
||||
return
|
||||
|
||||
if(!query.NextRow())
|
||||
qdel(query)
|
||||
return
|
||||
|
||||
qdel(query)
|
||||
|
||||
var/datum/db_query/delete_query = SSdbcore.NewQuery("DELETE FROM characters WHERE ckey=:ckey AND slot=:slot", list(
|
||||
"ckey" = C.ckey,
|
||||
"slot" = default_slot
|
||||
))
|
||||
|
||||
if(!delete_query.warn_execute())
|
||||
qdel(delete_query)
|
||||
return
|
||||
|
||||
qdel(delete_query)
|
||||
|
||||
saved = FALSE
|
||||
return TRUE
|
||||
var/datum/character_save/CS = pick(valid_slots)
|
||||
C.prefs.active_character = CS
|
||||
return
|
||||
|
||||
/**
|
||||
* Saves [/datum/preferences/proc/volume_mixer] for the current client.
|
||||
|
||||
Reference in New Issue
Block a user