SQL Saving - Rewrite + Implenetation (#350)

Rewrite's Mahzel's SQL character and preference saving.
Introduces easy config switching between the new and old system, with no troubles at all.

Also introduces better logging for DBQuery/proc/parseArguments(), should something go wrong. And classes SQL query errors as full on error snow, as opposed to debug data.
This commit is contained in:
skull132
2016-05-30 23:39:07 +03:00
parent 6881213b75
commit 7dacaa28dd
21 changed files with 1333 additions and 1339 deletions
+1
View File
@@ -46,5 +46,6 @@
var/related_accounts_ip = "Requires database" //So admins know why it isn't working - Used to determine what other accounts previously logged in from this ip
var/related_accounts_cid = "Requires database" //So admins know why it isn't working - Used to determine what other accounts previously logged in from this computer id
var/whitelist_status = 0 //Used to determine what whitelists the player has access to. Uses bitflag values!
var/need_saves_migrated = "Requires database" //Used to determine whether or not the ckey needs their saves migrated over to the database. Default is 0 upon successful connection.
preload_rsc = 0 // This is 0 so we can set it to an URL once the player logs in and have them download the resources from a different server.
+20 -3
View File
@@ -200,6 +200,8 @@
admins += src
holder.owner = src
log_client_to_db()
//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)
@@ -234,8 +236,6 @@
warnings_alert()
log_client_to_db()
check_linking_requests()
send_resources()
@@ -280,6 +280,22 @@
else
return -1
/client/verb/test_shit()
set category = "OOC"
set name = "Test Muh Shit"
var/savefile/S = new /savefile(src.prefs.path)
if (!S)
testing("Error opening save file!")
return
S.cd = "/"
testing("Starting to cycle through the dirs!")
for (var/a in S.dir)
testing("Found a dir! [a]")
testing("Cycled through all the dirs!")
/client/proc/log_client_to_db()
@@ -292,7 +308,7 @@
var/sql_ckey = sql_sanitize_text(src.ckey)
var/DBQuery/query = dbcon.NewQuery("SELECT id, datediff(Now(),firstseen) as age, whitelist_status FROM ss13_player WHERE ckey = '[sql_ckey]'")
var/DBQuery/query = dbcon.NewQuery("SELECT id, datediff(Now(),firstseen) as age, whitelist_status, migration_status FROM ss13_player WHERE ckey = '[sql_ckey]'")
query.Execute()
var/sql_id = 0
player_age = 0 // New players won't have an entry so knowing we have a connection we set this to zero to be updated if their is a record.
@@ -300,6 +316,7 @@
sql_id = query.item[1]
player_age = text2num(query.item[2])
whitelist_status = text2num(query.item[3])
need_saves_migrated = text2num(query.item[4])
break
var/DBQuery/query_ip = dbcon.NewQuery("SELECT ckey FROM ss13_player WHERE ip = '[address]'")
-732
View File
@@ -1,732 +0,0 @@
//handles saving to SQL Format
//MAKE SURE YOU KEEP THIS UP TO DATE!
//if the db can't be updated, return 0
//if the db was updated, return 1
/datum/preferences/proc/SQLsave_character(var/cslot)
char_slot = cslot
if(!cslot)
log_debug("invalid slot")
return 0
for(var/ckey in preferences_datums)
var/datum/preferences/D = preferences_datums[ckey]
if(D == src)
log_debug("Ckey is [ckey]")
establish_db_connection(dbcon)
if(!dbcon.IsConnected())
return 0
else
log_debug("db connected, real name is [real_name]")
if(!getCharId(ckey))
log_debug("New Character")
query = dbcon.NewQuery("INSERT INTO ss13_characters (ckey, slot) VALUES ('[ckey]', '[cslot]')")
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
getCharId(ckey)
InsertCharData()
InsertJobsData()
InsertFlavourData()
InsertRobotFlavourData()
InsertMiscData()
InsertSkillsData()
InsertGearData()
InsertOrgansData()
else
log_debug("ID = [char_id]")
log_debug("Update entry")
UpdateCharData()
UpdateJobsData()
UpdateFlavourData()
UpdateRobotFlavourData()
UpdateMiscData()
UpdateSkillsData()
UpdateGearData()
UpdateOrgansData()
TextQuery = "UPDATE SS13_characters SET Character_Name = (SELECT name FROM characters_data WHERE char_id = '[char_id]') WHERE id = '[char_id]'"
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
log_debug("Save query executed")
return 1
log_debug("No ckey in datums")
return 0
/datum/preferences/proc/SQLload_character(var/slot, var/pckey)
establish_db_connection(dbcon)
if(!dbcon.IsConnected())
return 0
char_slot = slot
if(!getCharId(pckey))
return 0
log_debug("Loading character ID [char_id] from slot [char_slot]")
if(LoadCharData())
if(LoadJobsData())
if(LoadFlavourData())
if(LoadRobotFlavourData())
if(LoadMiscData())
if(LoadSkillsData())
if(LoadGearData())
if(LoadOrgansData())
SanitizeCharacter()
return 1
return 0
/datum/preferences/proc/getCharId(var/ckey)
TextQuery = "SELECT id FROM ss13_characters WHERE ckey='[ckey]' AND slot = '[char_slot]'"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
log_debug("Query ready")
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
var/rowDebug = query.RowCount()
log_debug("Query executed, [rowDebug] rows")
if(!query.RowCount())
return 0
query.NextRow()
char_id = query.item[1]
log_debug("GetCharId : [char_id]")
return char_id
/datum/preferences/proc/InsertCharData()
log_debug("Insert Char Data")
TextQuery = "INSERT INTO characters_data (age, backbag, b_type, char_id, eyes_B, eyes_G, eyes_R, facial_B, facial_G, facial_R, facial_style, "
TextQuery += "gender, hair_B, hair_G, hair_R, hair_style, isRandom, language, name, OOC,skin_B, skin_G, skin_R, skin_tone, spawnpoint, species, undershirt, underwear) VALUES "
TextQuery += "('[age]', '[backbag]', '[b_type]', '[char_id]', '[b_eyes]', '[g_eyes]', '[r_eyes]', '[b_facial]', '[g_facial]', '[r_facial]', '[f_style]', "
TextQuery += "'[gender]', '[b_hair]', '[g_hair]', '[r_hair]', '[h_style]', '[be_random_name]', '[language]', '[real_name]', "
TextQuery += "'[metadata]', '[b_skin]', '[g_skin]', '[r_skin]', '[s_tone]', '[spawnpoint]', '[species]', '[undershirt]', '[underwear]')"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/UpdateCharData()
log_debug("Update Char Data")
query = dbcon.NewQuery("SELECT id FROM characters_data WHERE char_id = '[char_id]'")
query.Execute()
if(!query.RowCount())
InsertCharData()
TextQuery = "UPDATE characters_data SET age = '[age]', backbag='[backbag]', b_type='[b_type]', eyes_B = '[b_eyes]', eyes_G='[g_eyes]', eyes_R='[r_eyes]',"
TextQuery += "facial_B='[b_facial]', facial_G='[g_facial]', facial_R='[r_facial]', facial_style='[f_style]', gender = '[gender]', hair_B='[b_hair]', hair_G='[g_hair]',"
TextQuery += "hair_R='[r_hair]', hair_style='[h_style]', isRandom='[be_random_name]', language='[language]', name='[real_name]', OOC='[metadata]',skin_B='[b_skin]', skin_G='[g_skin]',"
TextQuery += "skin_R='[r_skin]', skin_tone='[s_tone]', spawnpoint='[spawnpoint]', species='[species]', undershirt='[undershirt]', underwear='[underwear]'"
TextQuery += "WHERE char_id = '[char_id]'"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/LoadCharData()
log_debug("Load char data")
TextQuery = "SELECT age, backbag, b_type, eyes_B, eyes_G, eyes_R, facial_B, facial_G, facial_R, facial_style, gender, "
TextQuery += "hair_B, hair_G, hair_R, hair_style, isRandom, language, name, OOC, skin_B, skin_G, skin_R, skin_tone, spawnpoint, species, undershirt, underwear "
TextQuery += "FROM characters_data WHERE char_id = [char_id]"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
if(!query.RowCount())
return 0
log_debug("Load query executed successfully")
query.NextRow()
age = text2num(query.item[1])
backbag = text2num(query.item[2])
b_type = text2num(query.item[3])
b_eyes = text2num(query.item[4])
g_eyes = text2num(query.item[5])
r_eyes = text2num(query.item[6])
b_facial = text2num(query.item[7])
g_facial = text2num(query.item[8])
r_facial = text2num(query.item[9])
f_style = query.item[10]
gender = query.item[11]
b_hair = text2num(query.item[12])
g_hair = text2num(query.item[13])
r_hair = text2num(query.item[14])
h_style = query.item[15]
be_random_name = text2num(query.item[16])
language = query.item[17]
real_name = query.item[18]
metadata = query.item[19]
b_skin = text2num(query.item[20])
g_skin = text2num(query.item[21])
r_skin = text2num(query.item[22])
s_tone = text2num(query.item[23])
spawnpoint = query.item[24]
species = query.item[25]
undershirt = query.item[26]
underwear = query.item[27]
return 1
/datum/preferences/proc/InsertJobsData()
log_debug("Insert jobs")
var/alt_titles_list = list2params(player_alt_titles)
TextQuery = "INSERT INTO characters_jobs (char_id, Alternate, civ_high, civ_med, civ_low, medsci_high, medsci_med, medsci_low, engsec_high, engsec_med, engsec_low, alt_titles) "
TextQuery += " VALUES ('[char_id]','[alternate_option]', '[job_civilian_high]', '[job_civilian_med]', '[job_civilian_low]', '[job_medsci_high]', '[job_medsci_med]', '[job_medsci_low]', "
TextQuery += "'[job_engsec_high]', '[job_engsec_med]', '[job_engsec_low]', '[alt_titles_list]')"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/UpdateJobsData()
log_debug("update jobs")
query = dbcon.NewQuery("SELECT id FROM characters_jobs WHERE char_id = '[char_id]'")
query.Execute()
if(!query.RowCount())
InsertJobsData()
var/alt_titles_list = list2params(player_alt_titles)
TextQuery = "UPDATE characters_jobs SET Alternate='[alternate_option]', civ_high='[job_civilian_high]', civ_med='[job_civilian_med]', civ_low='[job_civilian_low]', "
TextQuery += "medsci_high='[job_medsci_high]', medsci_med='[job_medsci_med]', medsci_low='[job_medsci_low]', "
TextQuery += "engsec_high='[job_engsec_high]', engsec_med='[job_engsec_med]', engsec_low='[job_engsec_low]', alt_titles = '[alt_titles_list]' WHERE char_id = [char_id] "
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/LoadJobsData()
log_debug("load_jobs")
TextQuery = "SELECT * FROM characters_jobs WHERE char_id = [char_id]"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
if(!query.RowCount())
return 0
log_debug("Load query executed successfully")
query.NextRow()
alternate_option = text2num(query.item[3])
job_civilian_high = text2num(query.item[4])
job_civilian_med = text2num(query.item[5])
job_civilian_low = text2num(query.item[6])
job_medsci_high = text2num(query.item[7])
job_medsci_med = text2num(query.item[8])
job_medsci_low = text2num(query.item[9])
job_engsec_high = text2num(query.item[10])
job_engsec_med = text2num(query.item[11])
job_engsec_low = text2num(query.item[12])
player_alt_titles = params2list(query.item[13])
return 1
/datum/preferences/proc/InsertFlavourData()
log_debug("insert flavour")
TextQuery = "INSERT INTO characters_flavour (char_id, generals, head, face, eyes, torso, arms, hands, legs, feet) "
TextQuery += " VALUES ('[char_id]','[flavor_texts["general"]]', '[flavor_texts["head"]]', '[flavor_texts["face"]]', '[flavor_texts["eyes"]]', '[flavor_texts["torso"]]', "
TextQuery += "'[flavor_texts["arms"]]', '[flavor_texts["hands"]]', '[flavor_texts["legs"]]', '[flavor_texts["feet"]]')"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/UpdateFlavourData()
log_debug("update flavour")
query = dbcon.NewQuery("SELECT id FROM characters_data WHERE char_id = '[char_id]'")
query.Execute()
if(!query.RowCount())
InsertFlavourData()
TextQuery = "UPDATE characters_flavour SET generals='[flavor_texts["general"]]', head='[flavor_texts["head"]]', face='[flavor_texts["face"]]', eyes='[flavor_texts["eyes"]]', "
TextQuery += "torso='[flavor_texts["torso"]]', arms='[flavor_texts["arms"]]', hands='[flavor_texts["hands"]]', legs='[flavor_texts["legs"]]', feet='[flavor_texts["feet"]]' "
TextQuery += "WHERE char_id = [char_id]"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/LoadFlavourData()
log_debug("load flavour")
TextQuery = "SELECT * FROM characters_flavour WHERE char_id = [char_id]"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
if(!query.RowCount())
return 0
log_debug("Load query executed successfully")
query.NextRow()
flavor_texts["general"] = query.item[3]
flavor_texts["head"] = query.item[4]
flavor_texts["face"] = query.item[5]
flavor_texts["eyes"] = query.item[6]
flavor_texts["torso"] = query.item[7]
flavor_texts["arms"] = query.item[8]
flavor_texts["hands"]= query.item[9]
flavor_texts["legs"] = query.item[10]
flavor_texts["feet"] = query.item[11]
return 1
/datum/preferences/proc/InsertRobotFlavourData()
log_debug("insert robot")
TextQuery = "INSERT INTO characters_robot_flavour (char_id, Default_Robot, Standard, Engineering, Construction, Surgeon, Crisis, Miner, Janitor, Service, Clerical, Security, Research) "
TextQuery += " VALUES ('[char_id]','[flavour_texts_robot["Default"]]', '[flavour_texts_robot["Standard"]]', '[flavour_texts_robot["Engineering"]]', '[flavour_texts_robot["Construction"]]', "
TextQuery += "'[flavour_texts_robot["Surgeon"]]', '[flavour_texts_robot["Crisis"]]', '[flavour_texts_robot["Miner"]]', '[flavour_texts_robot["Janitor"]]', '[flavour_texts_robot["Service"]]', "
TextQuery += "'[flavour_texts_robot["Clerical"]]', '[flavour_texts_robot["Security"]]','[flavour_texts_robot["Research"]]')"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/UpdateRobotFlavourData()
log_debug("update robot")
query = dbcon.NewQuery("SELECT id FROM characters_robot_flavour WHERE char_id = '[char_id]'")
query.Execute()
if(!query.RowCount())
InsertRobotFlavourData()
TextQuery = "UPDATE characters_robot_flavour SET Default_Robot='[flavour_texts_robot["Default"]]', Standard='[flavour_texts_robot["Standard"]]', Engineering='[flavour_texts_robot["Engineering"]]', "
TextQuery += "Construction='[flavour_texts_robot["Construction"]]', Surgeon='[flavour_texts_robot["Surgeon"]]', Crisis='[flavour_texts_robot["Crisis"]]', Miner='[flavour_texts_robot["Miner"]]', "
TextQuery += "Janitor='[flavour_texts_robot["Janitor"]]', Service='[flavour_texts_robot["Service"]]', Clerical='[flavour_texts_robot["Clerical"]]', "
TextQuery += "Security='[flavour_texts_robot["Security"]]', Research='[flavour_texts_robot["Research"]]' WHERE char_id = [char_id]"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/LoadRobotFlavourData()
log_debug("load robot")
TextQuery = "SELECT * FROM characters_robot_flavour WHERE char_id = [char_id]"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
if(!query.RowCount())
return 0
log_debug("Load query executed successfully")
query.NextRow()
flavour_texts_robot["Default"] = query.item[3]
flavour_texts_robot["Standard"] = query.item[4]
flavour_texts_robot["Engineering"] = query.item[5]
flavour_texts_robot["Construction"] = query.item[6]
flavour_texts_robot["Surgeon"] = query.item[7]
flavour_texts_robot["Crisis"] = query.item[8]
flavour_texts_robot["Miner"] = query.item[9]
flavour_texts_robot["Janitor"] = query.item[10]
flavour_texts_robot["Service"] = query.item[11]
flavour_texts_robot["Clerical"] = query.item[12]
flavour_texts_robot["Security"] = query.item[13]
flavour_texts_robot["Research"] = query.item[14]
return 1
/datum/preferences/proc/InsertMiscData()
log_debug("insert misc")
sanitizePrefs()
TextQuery = "INSERT INTO characters_misc (char_id, med_rec, sec_rec, gen_rec, disab, used_skill, skills_spec, "
TextQuery += "home_sys, citizen, faction, religion, NT_relation, uplink_loc, exploit_rec) VALUES ("
TextQuery += "'[char_id]', '[med_record]', '[sec_record]', '[gen_record]', '[disabilities]', '[used_skillpoints]', "
TextQuery += "'[skill_specialization]', '[home_system]', '[citizenship]', '[faction]', '[religion]', '[nanotrasen_relation]', "
TextQuery += "'[uplinklocation]', '[exploit_record]')"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/UpdateMiscData()
log_debug("update misc")
query = dbcon.NewQuery("SELECT id FROM characters_misc WHERE char_id = '[char_id]'")
query.Execute()
if(!query.RowCount())
InsertMiscData()
TextQuery = "UPDATE characters_misc SET med_rec='[med_record]', sec_rec='[sec_record]', gen_rec='[gen_record]', disab='[disabilities]', "
TextQuery += "used_skill='[used_skillpoints]', skills_spec='[skill_specialization]', "
TextQuery += "home_sys='[home_system]', citizen='[citizenship]', faction='[faction]', religion='[religion]', NT_relation='[nanotrasen_relation]', uplink_loc='[uplinklocation]', "
TextQuery += "exploit_rec='[exploit_record]' WHERE char_id = [char_id]"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/LoadMiscData()
log_debug("load_misc")
TextQuery = "SELECT * FROM characters_misc WHERE char_id = [char_id]"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
if(!query.RowCount())
return 0
log_debug("Load query executed successfully")
query.NextRow()
med_record = query.item[3]
sec_record = query.item[4]
gen_record = query.item[5]
disabilities = text2num(query.item[6])
used_skillpoints = text2num(query.item[7])
skill_specialization = query.item[8]
home_system = query.item[9]
citizenship = query.item[10]
faction = query.item[11]
religion = query.item[12]
nanotrasen_relation = query.item[13]
uplinklocation = query.item[14]
exploit_record = query.item[15]
return 1
/datum/preferences/proc/InsertSkillsData()
log_debug("insert skills")
TextQuery = "INSERT INTO characters_skills (char_id, Command, Botany, Cooking, Close_Combat, Weapons_Expertise, Forensics, NanoTrasen_Law, EVA, "
TextQuery += "Construction, Electrical, Atmos, Engines, Heavy_Mach, Complex_Devices, Information_Tech, Genetics, Chemistry, Science, Medicine, Anatomy, Virology) VALUES "
TextQuery += "('[char_id]', '[skills["management"]]', '[skills["botany"]]', '[skills["cooking"]]', '[skills["combat"]]', '[skills["weapons"]]', '[skills["forensics"]]', '[skills["law"]]', '[skills["EVA"]]',"
TextQuery += " '[skills["construction"]]', '[skills["electrical"]]', '[skills["atmos"]]', '[skills["engines"]]', '[skills["pilot"]]', '[skills["devices"]]', '[skills["computer"]]', '[skills["genetics"]]',"
TextQuery += " '[skills["chemistry"]]', '[skills["science"]]', '[skills["medical"]]', '[skills["anatomy"]]', '[skills["virology"]]')"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/UpdateSkillsData()
log_debug("update skills")
query = dbcon.NewQuery("SELECT id FROM characters_skills WHERE char_id = '[char_id]'")
query.Execute()
if(!query.RowCount())
InsertSkillsData()
TextQuery = "UPDATE characters_skills SET Command='[skills["management"]]', Botany='[skills["botany"]]', Cooking='[skills["cooking"]]', Close_Combat='[skills["combat"]]', "
TextQuery += "Weapons_Expertise='[skills["weapons"]]', Forensics='[skills["forensics"]]', NanoTrasen_Law='[skills["law"]]', EVA='[skills["EVA"]]', "
TextQuery += "Construction='[skills["construction"]]', Electrical='[skills["electrical"]]', Atmos='[skills["atmos"]]', Engines='[skills["engines"]]', Heavy_Mach='[skills["pilot"]]', Complex_Devices='[skills["devices"]]', "
TextQuery += "Information_Tech='[skills["computer"]]', Genetics='[skills["genetics"]]', Chemistry='[skills["chemistry"]]', Science='[skills["science"]]', Medicine='[skills["medical"]]', "
TextQuery += "Anatomy='[skills["anatomy"]]', Virology='[skills["virology"]]' WHERE char_id = '[char_id]'"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/LoadSkillsData()
log_debug("load skills")
TextQuery = "SELECT * FROM characters_skills WHERE char_id = '[char_id]'"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
if(!query.RowCount())
return 0
log_debug("Load query executed successfully")
query.NextRow()
skills["management"] = text2num(query.item[3])
skills["botany"] = text2num(query.item[4])
skills["cooking"] = text2num(query.item[5])
skills["combat"] = text2num(query.item[6])
skills["weapons"] = text2num(query.item[7])
skills["forensics"] = text2num(query.item[8])
skills["law"] = text2num(query.item[9])
skills["EVA"] = text2num(query.item[10])
skills["construction"] = text2num(query.item[11])
skills["electrical"] = text2num(query.item[12])
skills["atmos"] = text2num(query.item[13])
skills["engines"] = text2num(query.item[14])
skills["pilot"] = text2num(query.item[15])
skills["devices"] = text2num(query.item[16])
skills["computer"] = text2num(query.item[17])
skills["genetics"] = text2num(query.item[18])
skills["chemistry"] = text2num(query.item[19])
skills["science"] = text2num(query.item[20])
skills["medical"] = text2num(query.item[21])
skills["anatomy"] = text2num(query.item[22])
skills["virology"] = text2num(query.item[23])
return 1
/datum/preferences/proc/InsertGearData()
log_debug("insert gear")
//var/loop_id = 0
var/gear_list = list2params(gear)
//test
TextQuery = "INSERT INTO characters_gear (char_id, gear) VALUES ('[char_id]', '[gear_list]')"
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/UpdateGearData()
log_debug("update gear")
query = dbcon.NewQuery("SELECT id FROM characters_gear WHERE char_id = '[char_id]'")
query.Execute()
if(!query.RowCount())
InsertGearData()
//var/loop_id = 0
var/gear_list = list2params(gear)
TextQuery = "UPDATE characters_gear SET gear='[gear_list]' WHERE char_id = '[char_id]'"
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/LoadGearData()
log_debug("load gear")
TextQuery = "SELECT * FROM characters_gear WHERE char_id = '[char_id]'"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
if(!query.RowCount())
return 0
log_debug("Load query executed successfully")
query.NextRow()
gear = params2list(query.item[3])
return 1
/datum/preferences/proc/InsertOrgansData()
log_debug("insert organs")
TextQuery = "INSERT INTO characters_organs (char_id, l_leg, r_leg, l_arm, r_arm, l_foot, r_foot, l_hand, r_hand, heart, eyes) VALUES ("
TextQuery += "'[char_id]', '[organ_data["l_leg"]]', '[organ_data["r_leg"]]', '[organ_data["l_arm"]]', '[organ_data["r_arm"]]', '[organ_data["l_foot"]]', '[organ_data["r_foot"]]', "
TextQuery += "'[organ_data["l_hand"]]', '[organ_data["r_hand"]]', '[organ_data["heart"]]', '[organ_data["eyes"]]')"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
InsertRorgansData()
return 1
/datum/preferences/proc/UpdateOrgansData()
log_debug("update organs")
query = dbcon.NewQuery("SELECT id FROM characters_organs WHERE char_id = '[char_id]'")
query.Execute()
if(!query.RowCount())
InsertOrgansData()
TextQuery = "UPDATE characters_organs SET char_id='[char_id]', l_leg='[organ_data["l_leg"]]', r_leg='[organ_data["r_leg"]]', l_arm='[organ_data["l_arm"]]', r_arm='[organ_data["r_arm"]]', "
TextQuery += "l_foot='[organ_data["l_foot"]]', r_foot='[organ_data["r_foot"]]', l_hand='[organ_data["l_hand"]]', r_hand='[organ_data["r_hand"]]', heart='[organ_data["heart"]]', eyes='[organ_data["eyes"]]'"
TextQuery += " WHERE char_id='[char_id]'"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
UpdateRorgansData()
return 1
/datum/preferences/proc/LoadOrgansData()
log_debug("load organs")
TextQuery = "SELECT * FROM characters_organs WHERE char_id = '[char_id]'"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
if(!query.RowCount())
return 0
log_debug("Load query executed successfully")
query.NextRow()
organ_data["l_leg"] = query.item[3]
organ_data["r_leg"] = query.item[4]
organ_data["l_arm"] = query.item[5]
organ_data["r_arm"] = query.item[6]
organ_data["l_foot"] = query.item[7]
organ_data["r_foot"] = query.item[8]
organ_data["l_hand"] = query.item[9]
organ_data["r_hand"] = query.item[10]
organ_data["heart"] = query.item[11]
organ_data["eyes"] = query.item[12]
LoadRorgansData()
return 1
/datum/preferences/proc/InsertRorgansData()
log_debug("insert robotics organs")
TextQuery = "INSERT INTO characters_rlimb (char_id, l_leg, r_leg, l_arm, r_arm, l_foot, r_foot, l_hand, r_hand) VALUES ("
TextQuery += "'[char_id]', '[rlimb_data["l_leg"]]', '[rlimb_data["r_leg"]]', '[rlimb_data["l_arm"]]', '[rlimb_data["r_arm"]]', '[rlimb_data["l_foot"]]', '[rlimb_data["r_foot"]]', "
TextQuery += "'[rlimb_data["l_hand"]]', '[rlimb_data["r_hand"]]')"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/UpdateRorgansData()
log_debug("update robotics organs")
TextQuery = "UPDATE characters_rlimb SET char_id='[char_id]', l_leg='[rlimb_data["l_leg"]]', r_leg='[rlimb_data["r_leg"]]', l_arm='[rlimb_data["l_arm"]]', r_arm='[rlimb_data["r_arm"]]', "
TextQuery += "l_foot='[rlimb_data["l_foot"]]', r_foot='[rlimb_data["r_foot"]]', l_hand='[rlimb_data["l_hand"]]', r_hand='[rlimb_data["r_hand"]]'"
TextQuery += " WHERE char_id = '[char_id]'"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/LoadRorgansData()
log_debug("load robotics organs")
TextQuery = "SELECT * FROM characters_rlimb WHERE char_id = '[char_id]'"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
if(!query.RowCount())
return 0
log_debug("Load query executed successfully")
query.NextRow()
rlimb_data["l_leg"] = query.item[3]
rlimb_data["r_leg"] = query.item[4]
rlimb_data["l_arm"] = query.item[5]
rlimb_data["r_arm"] = query.item[6]
rlimb_data["l_foot"] = query.item[7]
rlimb_data["r_foot"] = query.item[8]
rlimb_data["l_hand"] = query.item[9]
rlimb_data["r_hand"] = query.item[10]
return 1
/datum/preferences/proc/SavePrefData(var/ckey)
log_debug("Save pref data")
TextQuery = "SELECT * FROM player_preferences WHERE ckey = '[ckey]'"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(!query.RowCount())
sanitizePrefs()
TextQuery = "INSERT INTO player_preferences (ckey, ooccolor, lastchangelog, UI_style, default_slot, toggles, UI_style_color, UI_style_alpha, be_special) "
TextQuery += "VALUES ('[ckey]', '[ooccolor]','[lastchangelog]', '[UI_style]', '[default_slot]', '[toggles]', '[UI_style_color]', '[UI_style_alpha]','[be_special]')"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
else
return UpdatePrefData(ckey)
/datum/preferences/proc/UpdatePrefData(var/ckey)
log_debug("Update pref data")
sanitizePrefs()
TextQuery = "UPDATE player_preferences SET ooccolor='[ooccolor]', lastchangelog='[lastchangelog]', UI_style='[UI_style]', default_slot='[default_slot]', toggles='[toggles]', "
TextQuery += "UI_style_color='[UI_style_color]', UI_style_alpha='[UI_style_alpha]', be_special='[be_special]' WHERE ckey = '[ckey]'"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
return 1
/datum/preferences/proc/LoadPrefData(var/ckey)
log_debug("load pref data")
establish_db_connection(dbcon)
if(!dbcon.IsConnected())
return 0
TextQuery = "SELECT * FROM player_preferences WHERE ckey = '[ckey]'"
log_debug(TextQuery)
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(dbcon.ErrorMsg())
log_debug(dbcon.ErrorMsg())
if(!query.RowCount())
return 0
log_debug("Load query executed successfully")
query.NextRow()
ooccolor = query.item[3]
lastchangelog = text2num(query.item[4])
UI_style = query.item[5]
default_slot = text2num(query.item[6])
toggles = text2num(query.item[7])
UI_style_color = query.item[8]
UI_style_alpha = text2num(query.item[9])
be_special = text2num(query.item[10])
sanitizePrefs()
return 1
/datum/preferences/proc/sanitizePrefs()
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
UI_style = sanitize_inlist(UI_style, list("White", "Midnight","Orange","old"), initial(UI_style))
be_special = sanitize_integer(be_special, 0, 65535, initial(be_special))
default_slot = sanitize_integer(default_slot, 1, config.character_slots, initial(default_slot))
toggles = sanitize_integer(toggles, 0, 65535, initial(toggles))
UI_style_color = sanitize_hexcolor(UI_style_color, initial(UI_style_color))
UI_style_alpha = sanitize_integer(UI_style_alpha, 0, 255, initial(UI_style_alpha))
return 1
/datum/preferences/proc/SanitizeCharacter()
metadata = sanitize_text(metadata, initial(metadata))
real_name = sanitizeName(real_name)
if(isnull(species) || !(species in playable_species))
species = "Human"
if(isnum(underwear))
var/list/undies = gender == MALE ? underwear_m : underwear_f
underwear = undies[undies[underwear]]
if(isnum(undershirt))
undershirt = undershirt_t[undershirt_t[undershirt]]
if(isnull(language)) language = "None"
if(isnull(spawnpoint)) spawnpoint = "Arrivals Shuttle"
if(isnull(nanotrasen_relation)) nanotrasen_relation = initial(nanotrasen_relation)
if(!real_name) real_name = random_name(gender)
be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name))
gender = sanitize_gender(gender)
age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age))
r_hair = sanitize_integer(r_hair, 0, 255, initial(r_hair))
g_hair = sanitize_integer(g_hair, 0, 255, initial(g_hair))
b_hair = sanitize_integer(b_hair, 0, 255, initial(b_hair))
r_facial = sanitize_integer(r_facial, 0, 255, initial(r_facial))
g_facial = sanitize_integer(g_facial, 0, 255, initial(g_facial))
b_facial = sanitize_integer(b_facial, 0, 255, initial(b_facial))
s_tone = sanitize_integer(s_tone, -185, 34, initial(s_tone))
r_skin = sanitize_integer(r_skin, 0, 255, initial(r_skin))
g_skin = sanitize_integer(g_skin, 0, 255, initial(g_skin))
b_skin = sanitize_integer(b_skin, 0, 255, initial(b_skin))
h_style = sanitize_inlist(h_style, hair_styles_list, initial(h_style))
f_style = sanitize_inlist(f_style, facial_hair_styles_list, initial(f_style))
r_eyes = sanitize_integer(r_eyes, 0, 255, initial(r_eyes))
g_eyes = sanitize_integer(g_eyes, 0, 255, initial(g_eyes))
b_eyes = sanitize_integer(b_eyes, 0, 255, initial(b_eyes))
backbag = sanitize_integer(backbag, 1, backbaglist.len, initial(backbag))
b_type = sanitize_text(b_type, initial(b_type))
alternate_option = sanitize_integer(alternate_option, 0, 2, initial(alternate_option))
job_civilian_high = sanitize_integer(job_civilian_high, 0, 65535, initial(job_civilian_high))
job_civilian_med = sanitize_integer(job_civilian_med, 0, 65535, initial(job_civilian_med))
job_civilian_low = sanitize_integer(job_civilian_low, 0, 65535, initial(job_civilian_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))
if(!skills) skills = list()
if(!used_skillpoints) used_skillpoints= 0
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(!gear) src.gear = list()
if(!home_system) home_system = "Unset"
if(!citizenship) citizenship = "None"
if(!faction) faction = "None"
if(!religion) religion = "None"
return 1
+78 -111
View File
@@ -32,7 +32,7 @@ datum/preferences
//doohickeys for savefiles
var/path
var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used
var/current_slot = 1
var/current_character = 0 //SQL character ID.
var/savefile_version = 0
//non-preference stuff
@@ -135,37 +135,36 @@ datum/preferences
var/metadata = ""
var/slot_name = ""
//SQL Save system vars
var/chardata[]
var/jobsdata[]
var/flavourdata[]
var/miscdata[]
var/DBQuery/query
var/TextQuery
var/char_id
var/char_slot
/datum/preferences/New(client/C)
b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+")
if (config.sql_saves && C.need_saves_migrated)
var/dat = "<center>The server attempted to automatically migrate your saves from the old file-system onto an SQL database.<br>"
dat += "This operation was "
if (!handle_saves_migration(C))
error("Failed migrating saves from [C.ckey] to the database!")
dat += "<font color='red'><b>unsuccessful!</b></font><br><br>"
dat += "There was most likely an error in one of the SQL commands used to handle this migration. Do not worry: your saves are still safe in the old system and retreivable. Please contact Skull132 <b>immediately</b> in order to have the issue resolved. Until such a time, you will have to play without your old characters.</center>"
else
dat += "<font color='green'><b>successful!</b></font><br><br>"
dat += "All of your character and preference data should be now neatly housed on the SQL database. Please look over it to see if anything is wrong or otherwise messed up. If you find something like that, please contact Skull132 <b>immediately.</b> Your old saves are still completely safe on the old system, should anything have gone wrong!<br><br>"
dat += "<b>You should now immediately load a character. Otherwise you risk overriding one of your characters!</b> Once that is done, everything shuold be fine.</center>"
C << browse(dat, "window=migrate_status")
update_migrate_status(C)
if(istype(C))
if(!IsGuestKey(C.key))
load_path(C.ckey)
log_debug("loading data for [C.ckey]")
if(LoadPrefData(C.ckey))
log_debug("Default slot loaded : [default_slot]")
if(SQLload_character(default_slot, C.ckey))
current_slot = default_slot
log_debug("Character [real_name] loaded, slot is [current_slot]")
if(handle_preferences_load(C))
if(handle_character_load(get_default_character(), C))
return
if(load_preferences())
if(load_character(default_slot))
current_slot = getCharSlot_File()
return
//this ensure that if db fail the file system is used to load an initial character
b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+")
gender = pick(MALE, FEMALE)
real_name = random_name(gender,species)
gear = list()
ZeroSkills(1)
/datum/preferences/proc/ZeroSkills(var/forced = 0)
for(var/V in SKILLS) for(var/datum/skill/S in SKILLS[V])
if(!skills.Find(S.ID) || forced)
@@ -262,7 +261,14 @@ datum/preferences
user << browse_rsc(preview_icon_side, "previewicon2.png")
var/dat = "<html><body><center>"
if(path)
if (config.sql_saves)
dat += "<center>"
dat += "<a href=\"byond://?src=\ref[user];preference=open_load_dialog\">Load another character</a> - "
dat += "<a href=\"byond://?src=\ref[user];preference=save\">Save character</a> - "
dat += "<a href=\"byond://?src=\ref[user];preference=reload\">Discard changes</a> - "
dat += "<a href=\"byond://?src=\ref[user];preference=delete_character_sql\">Delete Character</a>"
dat += "</center>"
else if (path)
dat += "<center>"
dat += "Slot <b>[slot_name]</b> - "
dat += "<a href=\"byond://?src=\ref[user];preference=open_load_dialog\">Load slot</a> - "
@@ -468,10 +474,14 @@ datum/preferences
dat += "</td></tr></table><hr><center>"
if(!IsGuestKey(user.key))
dat += "<a href='?_src_=prefs;preference=load'>Undo</a> - "
dat += "<a href='?_src_=prefs;preference=save'>Save Setup</a> - "
dat += "<a href='?_src_=prefs;preference=reset_all'>Reset Setup</a>"
if (config.sql_saves)
dat += "<a href=\"byond://?_src_=prefs;preference=save\">Save character</a> - "
dat += "<a href=\"byond://?_src_=prefs;preference=reload\">Discard changes</a> - "
dat += "<a href=\"byond://?_src_=prefs;preference=delete_character_sql\">Delete Character</a>"
else
dat += "<a href='?_src_=prefs;preference=load'>Undo</a> - "
dat += "<a href='?_src_=prefs;preference=save'>Save Setup</a> - "
dat += "<a href='?_src_=prefs;preference=reset_all'>Reset Setup</a>"
dat += "</center></body></html>"
user << browse(dat, "window=preferences;size=560x736")
@@ -1616,50 +1626,35 @@ datum/preferences
toggles ^= CHAT_GHOSTRADIO
if("save")
for(var/ckey in preferences_datums)
var/datum/preferences/D = preferences_datums[ckey]
if(D == src)
//switch comment to switch to file save system
default_slot = current_slot
SavePrefData(ckey)
SQLsave_character(current_slot, ckey)
//save_preferences()
//save_character()
handle_preferences_save(user.client)
handle_character_save(user.client)
if("reload")
for(var/ckey in preferences_datums)
var/datum/preferences/D = preferences_datums[ckey]
if(D == src)
//switch comment to switch to file save system
LoadPrefData(ckey)
SQLload_character(current_slot, ckey)
//load_preferences()
//load_character()
handle_preferences_load(user.client)
handle_character_load(get_default_character(), user.client)
if("open_load_dialog")
if(!IsGuestKey(user.key))
//file system preferences
//open_load_dialog_file(user)
open_load_dialog(user)
if (config.sql_saves)
open_load_dialog_sql(user)
else
open_load_dialog_file(user)
if("close_load_dialog")
close_load_dialog(user)
if("changeslot")
for(var/ckey in preferences_datums)
var/datum/preferences/D = preferences_datums[ckey]
if(D == src)
current_slot = text2num(href_list["num"])
if(!SQLload_character(current_slot, ckey))
gender = pick(MALE, FEMALE)
real_name = random_name(gender,species)
gear.Cut()
ZeroSkills(1)
ResetJobs()
//file system load
//load_character()
handle_character_load(text2num(href_list["num"]), user.client)
close_load_dialog(user)
if("new_character_sql")
new_character_sql(user.client)
close_load_dialog(user)
if("delete_character_sql")
delete_character_sql(user.client)
new_character_sql(user.client)
ShowChoices(user)
return 1
@@ -1771,37 +1766,38 @@ datum/preferences
message_admins("[character] ([character.ckey]) has spawned with their gender as plural or neuter. Please notify coders.")
character.gender = MALE
/datum/preferences/proc/open_load_dialog(mob/user)
/datum/preferences/proc/open_load_dialog_sql(mob/user)
var/dat = "<body>"
dat += "<tt><center>"
for(var/ckey in preferences_datums)
var/datum/preferences/D = preferences_datums[ckey]
if(D == src)
var/TextQuery = "SELECT Character_Name FROM SS13_characters WHERE ckey = '[ckey]' ORDER BY slot"
var/DBQuery/query
establish_db_connection(dbcon)
if(!dbcon.IsConnected())
open_load_dialog_file(user)
query = dbcon.NewQuery(TextQuery)
query.Execute()
var/rows
if(!query.RowCount())
rows = 0
else
rows = query.RowCount()
dat += "<b>Select a character slot to load (SQL Edition !)</b><hr>"
return open_load_dialog_file(user)
var/DBQuery/query = dbcon.NewQuery("SELECT id, name FROM ss13_characters WHERE ckey = :ckey ORDER BY id ASC")
query.Execute(list(":ckey" = user.client.ckey))
dat += "<b>Select a character slot to load</b><hr>"
var/name
for(var/i=1, i<= config.character_slots, i++)
log_debug("[rows] rows queried, i = [i]")
if(i<=rows)
query.NextRow()
name = query.item[1]
log_debug("adding [query.item[1]] to list")
else name = "Character[i]"
if(i==default_slot)
name = "<b>[name]</b>"
dat += "<a href='?_src_=prefs;preference=changeslot;num=[i];'>[name]</a><br>"
var/id
while (query.NextRow())
id = text2num(query.item[1])
name = query.item[2]
if (id == current_character)
dat += "<b><a href='?_src_=prefs;preference=changeslot;num=[id];'>[name]</a></b><br>"
else
dat += "<a href='?_src_=prefs;preference=changeslot;num=[id];'>[name]</a><br>"
dat += "<hr>"
dat += "<b>[query.RowCount()]/[config.character_slots] slots used</b><br>"
if (query.RowCount() < config.character_slots)
dat += "<a href='byond://?_src_=prefs;preference=new_character_sql;'>New Character</a>"
else
dat += "<strike>New Character</strike>"
dat += "<hr>"
dat += "<a href='byond://?src=\ref[user];preference=close_load_dialog'>Close</a><br>"
@@ -1829,34 +1825,5 @@ datum/preferences
dat += "</center></tt>"
user << browse(dat, "window=saves;size=300x390")
/datum/preferences/proc/getCharSlot()
for(var/ckey in preferences_datums)
var/datum/preferences/D = preferences_datums[ckey]
if(D == src)
var/TextQuery = "SELECT slot FROM SS13_characters WHERE ckey = '[ckey]' AND Character_Name = '[real_name]'"
var/DBQuery/query
establish_db_connection(dbcon)
if(!dbcon.IsConnected())
getCharSlot_File()
query = dbcon.NewQuery(TextQuery)
query.Execute()
if(!query.RowCount())
return 1
query.NextRow()
return text2num(query.item[1])
return 1
/datum/preferences/proc/getCharSlot_File() //get character slot from savefile
var/savefile/S = new /savefile(path)
if(S)
var/name
for(var/i=1, i<= config.character_slots, i++)
S.cd = "/character[i]"
S["real_name"] >> name
if(name == real_name)
return i
return 1
/datum/preferences/proc/close_load_dialog(mob/user)
user << browse(null, "window=saves")
+3 -4
View File
@@ -18,7 +18,7 @@
set category = "Preferences"
set desc = "Toggles hearing ambient sound effects"
prefs.asfx_togs ^= ASFX_AMBIENCE
prefs.save_preferences()
prefs.handle_preferences_save(src)
if(prefs.asfx_togs & ASFX_AMBIENCE)
src << "You will now hear ambient sounds."
else
@@ -33,7 +33,7 @@
set desc = "Toggles hearing footstep sound effects"
prefs.asfx_togs ^= ASFX_FOOTSTEPS
prefs.save_preferences()
prefs.handle_preferences_save(src)
if(prefs.asfx_togs & ASFX_FOOTSTEPS)
src << "You will now hear footstep sounds."
else
@@ -45,10 +45,9 @@
set category = "SoundFx Prefs"
set desc = "Toggles hearing of the vote alarm"
prefs.asfx_togs ^= ASFX_VOTE
prefs.save_preferences()
prefs.handle_preferences_save(src)
if(prefs.asfx_togs & ASFX_VOTE)
src << "You will now hear the vote alarm."
else
src << "<font color='red'>You will no longer hear the vote alarm.</font>"
feedback_add_details("admin_verb","TSFXFV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -0,0 +1,86 @@
/*
* The method by which player saves are migrated to the SQL database from savefile oriented storage.
*/
/datum/preferences/proc/handle_saves_migration(var/client/C)
if (!C || !C.need_saves_migrated)
return 1
if (!path)
load_path(C.ckey)
if (!path)
log_debug("Migration of [C.ckey]'s saves failed at attaining path to save file.")
return 0
if (!migrate_client_preferences(C))
log_debug("Migration of [C.ckey]'s saves failed at the uploading of client preferences.")
return 0
if (!migrate_client_characters(C))
log_debug("Migration of [C.ckey]'s saves failed at the uploading of client characters.")
return 0
return 1
/*
* Handles the migration of preferences.
* Loads the prefs to the datum, then saves them to SQL.
*/
/datum/preferences/proc/migrate_client_preferences(var/client/C)
load_preferences()
return insert_preferences_sql(C)
/*
* Handles the migration of characters.
* Finds all of your saved characters, loads them into the datum, and saves them onto the SQL.
*/
/datum/preferences/proc/migrate_client_characters(var/client/C)
var/savefile/S = new /savefile(path)
if (!S)
return 1
S.cd = "/"
var/list/character_slots = list()
for (var/a in S.dir)
if (findtext(a, "character"))
var/slot_id = replacetext(a, "character", "")
character_slots.Add(text2num(slot_id))
if (!character_slots.len)
return 1
for (var/slot in character_slots)
load_character(slot)
if (!skills || !skills.len)
ZeroSkills(1)
if (!insert_character_sql(C))
log_debug("Character insert error during migration. Client: [C.ckey], character slot: [slot].")
return 0
return 1
/*
* Update's the client's migrate status.
*/
/datum/preferences/proc/update_migrate_status(var/client/C)
C.need_saves_migrated = 0
establish_db_connection(dbcon)
if (!dbcon.IsConnected())
return
var/DBQuery/query = dbcon.NewQuery("UPDATE ss13_player SET migration_status = 0 WHERE ckey = :ckey")
query.Execute(list(":ckey" = C.ckey))
var/DBQuery/current_query = dbcon.NewQuery("SELECT id FROM ss13_characters WHERE ckey = :ckey ORDER BY id ASC LIMIT 1")
current_query.Execute(list(":ckey" = C.ckey))
if (current_query.NextRow())
current_character = text2num(current_query.item[1])
load_character_sql(current_character, C)
return
+643
View File
@@ -0,0 +1,643 @@
/datum/preferences/proc/load_preferences_sql(var/client/C)
if (!C)
return 0
var/DBQuery/query = dbcon.NewQuery({"SELECT
ooccolor,
lastchangelog,
UI_style,
current_character,
toggles,
UI_style_color,
UI_style_alpha,
be_special,
asfx_togs
FROM ss13_player_preferences
WHERE ckey = :ckey"})
query.Execute(list(":ckey" = C.ckey))
if (!query.NextRow())
return insert_preferences_sql(C)
ooccolor = query.item[1]
lastchangelog = query.item[2]
UI_style = query.item[3]
current_character = text2num(query.item[4])
toggles = text2num(query.item[5])
UI_style_color = query.item[6]
UI_style_alpha = text2num(query.item[7])
be_special = text2num(query.item[8])
asfx_togs = text2num(query.item[9])
//Sanitize
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
UI_style = sanitize_inlist(UI_style, list("White", "Midnight","Orange","old"), initial(UI_style))
be_special = sanitize_integer(be_special, 0, 65535, initial(be_special))
default_slot = sanitize_integer(default_slot, 1, config.character_slots, initial(default_slot))
toggles = sanitize_integer(toggles, 0, 65535, initial(toggles))
asfx_togs = sanitize_integer(asfx_togs, 0, 65535, initial(asfx_togs))
UI_style_color = sanitize_hexcolor(UI_style_color, initial(UI_style_color))
UI_style_alpha = sanitize_integer(UI_style_alpha, 0, 255, initial(UI_style_alpha))
return 1
/datum/preferences/proc/save_preferences_sql(var/client/C)
if (!C)
return 0
var/DBQuery/initial_query = dbcon.NewQuery("SELECT COUNT(*) AS rowsFound FROM ss13_player_preferences WHERE ckey = :ckey")
initial_query.Execute(list(":ckey" = C.ckey))
if (!initial_query.NextRow())
return insert_preferences_sql(C)
var/DBQuery/update_query = dbcon.NewQuery({"UPDATE ss13_player_preferences SET
ooccolor = :ooccolor,
lastchangelog = :lastchangelog,
UI_style = :ui_style,
current_character = :current_character,
toggles = :toggles,
UI_style_color = :ui_color,
UI_style_alpha = :ui_alpha,
be_special = :be_special,
asfx_togs = :asfx_togs
WHERE ckey = :ckey"})
update_query.Execute(get_prefs_update_insert_params(C))
return 1
/datum/preferences/proc/insert_preferences_sql(var/client/C)
if (!C)
return 0
var/DBQuery/query = dbcon.NewQuery({"INSERT INTO ss13_player_preferences (ckey, ooccolor, lastchangelog, UI_style, current_character, toggles, UI_style_color, UI_style_alpha, be_special, asfx_togs)
VALUES (:ckey, :ooccolor, :lastchangelog, :ui_style, :current_character, :toggles, :ui_color, :ui_alpha, :be_special, :asfx_togs);"})
query.Execute(get_prefs_update_insert_params(C))
return 1
//Helper function.
/datum/preferences/proc/get_prefs_update_insert_params(var/client/C)
var/params[] = list()
params[":ckey"] = C.ckey
params[":ooccolor"] = ooccolor
params[":lastchangelog"] = lastchangelog
params[":ui_style"] = UI_style
params[":current_character"] = current_character
params[":toggles"] = toggles
params[":ui_color"] = UI_style_color
params[":ui_alpha"] = UI_style_alpha
params[":be_special"] = be_special
params[":asfx_togs"] = asfx_togs
return params
/datum/preferences/proc/load_character_sql(slot, var/client/C)
if (!C)
return 0
if (!slot || slot == 0)
return new_character_sql(C)
current_character = slot
establish_db_connection(dbcon)
if (!dbcon.IsConnected())
error("Error attempting to connect to MySQL server while loading a character.")
return 0
var/DBQuery/initial_query = dbcon.NewQuery("SELECT name FROM ss13_characters WHERE id = :character_id AND ckey = :ckey")
initial_query.Execute(list(":character_id" = current_character, ":ckey" = C.ckey))
// In case someone got themselves an invalid character ID.
if (!initial_query.NextRow())
error("[C.ckey] attempted to load character #[current_character] and failed. No such character found.")
new_character_sql(C)
return 0
var/DBQuery/character_query = dbcon.NewQuery({"SELECT
dat.name,
dat.metadata,
dat.random_name,
dat.gender,
dat.age,
dat.species,
dat.language,
dat.spawnpoint,
dat.hair_colour,
dat.facial_colour,
dat.skin_tone,
dat.skin_colour,
dat.hair_style,
dat.facial_style,
dat.eyes_colour,
dat.underwear,
dat.undershirt,
dat.backbag,
dat.b_type,
dat.jobs,
dat.alternate_option,
dat.alternate_titles,
flv.flavour_general,
flv.flavour_head,
flv.flavour_face,
flv.flavour_eyes,
flv.flavour_torso,
flv.flavour_arms,
flv.flavour_hands,
flv.flavour_legs,
flv.flavour_feet,
flv.robot_default,
flv.robot_standard,
flv.robot_engineering,
flv.robot_construction,
flv.robot_surgeon,
flv.robot_crisis,
flv.robot_miner,
flv.robot_janitor,
flv.robot_service,
flv.robot_clerical,
flv.robot_security,
flv.robot_research,
flv.records_employment,
flv.records_medical,
flv.records_security,
flv.records_exploit,
dat.disabilities,
dat.skills,
dat.skills_specialization,
dat.home_system,
dat.citizenship,
dat.faction,
dat.religion,
dat.nt_relation,
dat.uplink_location,
dat.organs_data,
dat.organs_robotic,
dat.gear
FROM ss13_characters dat
JOIN ss13_characters_flavour flv ON dat.id = flv.char_id
WHERE dat.id = :char_id"})
if (!character_query.Execute(list(":char_id" = current_character)))
error("Error loading character #[current_character]. SQL error message: '[character_query.ErrorMsg()]'.")
new_character_sql(C)
return 0
if (!character_query.NextRow())
error("Error loading character #[current_character]. No such character exists.")
new_character_sql(C)
return 0
var/DBQuery/char_id_update = dbcon.NewQuery("UPDATE ss13_player_preferences SET current_character = :char_id WHERE ckey = :ckey")
char_id_update.Execute(list(":char_id" = current_character, ":ckey" = C.ckey))
// Character
real_name = character_query.item[1]
metadata = character_query.item[2]
be_random_name = text2num(character_query.item[3])
gender = character_query.item[4]
age = text2num(character_query.item[5])
species = character_query.item[6]
language = character_query.item[7]
spawnpoint = character_query.item[8]
// Other customization data
var/list/hair_rgb = length(character_query.item[9]) == 7 ? GetHexColors(character_query.item[9]) : null
if (hair_rgb)
r_hair = hair_rgb[1]
g_hair = hair_rgb[2]
b_hair = hair_rgb[3]
var/list/facial_rgb = length(character_query.item[10]) == 7 ? GetHexColors(character_query.item[10]) : null
if (facial_rgb)
r_facial = facial_rgb[1]
g_facial = facial_rgb[2]
b_facial = facial_rgb[3]
s_tone = text2num(character_query.item[11])
var/list/skin_rgb = length(character_query.item[12]) == 7 ? GetHexColors(character_query.item[12]) : null
if (skin_rgb)
r_skin = skin_rgb[1]
g_skin = skin_rgb[2]
b_skin = skin_rgb[3]
h_style = character_query.item[13]
f_style = character_query.item[14]
var/list/eyes_rgb = length(character_query.item[15]) == 7 ? GetHexColors(character_query.item[15]) : null
if (eyes_rgb)
r_eyes = eyes_rgb[1]
g_eyes = eyes_rgb[2]
b_eyes = eyes_rgb[3]
underwear = character_query.item[16]
undershirt = character_query.item[17]
backbag = text2num(character_query.item[18])
b_type = character_query.item[19]
var/list/jobs_list = params2list(character_query.item[20])
// Job preferences + alt titles and options
if (jobs_list.len == 9)
job_civilian_high = text2num(jobs_list["civ_high"])
job_civilian_med = text2num(jobs_list["civ_med"])
job_civilian_low = text2num(jobs_list["civ_low"])
job_medsci_high = text2num(jobs_list["medsci_high"])
job_medsci_med = text2num(jobs_list["medsci_med"])
job_medsci_low = text2num(jobs_list["medsci_low"])
job_engsec_high = text2num(jobs_list["engsec_high"])
job_engsec_med = text2num(jobs_list["engsec_med"])
job_engsec_low = text2num(jobs_list["engsec_low"])
alternate_option = text2num(character_query.item[21])
player_alt_titles = params2list(character_query.item[22])
// Flavour texts
flavor_texts["general"] = character_query.item[23]
flavor_texts["head"] = character_query.item[24]
flavor_texts["face"] = character_query.item[25]
flavor_texts["eyes"] = character_query.item[26]
flavor_texts["torso"] = character_query.item[27]
flavor_texts["arms"] = character_query.item[28]
flavor_texts["hands"] = character_query.item[29]
flavor_texts["legs"] = character_query.item[30]
flavor_texts["feet"] = character_query.item[31]
flavour_texts_robot["Default"] = character_query.item[32]
flavour_texts_robot["Standard"] = character_query.item[33]
flavour_texts_robot["Engineering"] = character_query.item[34]
flavour_texts_robot["Construction"] = character_query.item[35]
flavour_texts_robot["Surgeon"] = character_query.item[36]
flavour_texts_robot["Crisis"] = character_query.item[37]
flavour_texts_robot["Miner"] = character_query.item[38]
flavour_texts_robot["Janitor"] = character_query.item[39]
flavour_texts_robot["Service"] = character_query.item[40]
flavour_texts_robot["Clerical"] = character_query.item[41]
flavour_texts_robot["Security"] = character_query.item[42]
flavour_texts_robot["Research"] = character_query.item[43]
// Records
gen_record = character_query.item[44]
med_record = character_query.item[45]
sec_record = character_query.item[46]
exploit_record = character_query.item[47]
// Miscellaneous
disabilities = text2num(character_query.item[48])
skills = params2list(character_query.item[49])
skill_specialization = character_query.item[50]
home_system = character_query.item[51]
citizenship = character_query.item[52]
faction = character_query.item[53]
religion = character_query.item[54]
nanotrasen_relation = character_query.item[55]
uplinklocation = character_query.item[56]
organ_data = params2list(character_query.item[57])
rlimb_data = params2list(character_query.item[58])
gear = params2list(character_query.item[59])
// Sanitization
metadata = sanitize_text(metadata, initial(metadata))
real_name = sanitizeName(real_name)
if (isnull(species) || !(species in playable_species))
species = "Human"
if (isnum(underwear))
var/list/undies = gender == MALE ? underwear_m : underwear_f
underwear = undies[undies[underwear]]
if (isnum(undershirt))
undershirt = undershirt_t[undershirt_t[undershirt]]
if (isnull(language)) language = "None"
if (isnull(spawnpoint)) spawnpoint = "Arrivals Shuttle"
if (isnull(nanotrasen_relation)) nanotrasen_relation = initial(nanotrasen_relation)
if (!real_name) real_name = random_name(gender)
be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name))
gender = sanitize_gender(gender)
age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age))
r_hair = sanitize_integer(r_hair, 0, 255, initial(r_hair))
g_hair = sanitize_integer(g_hair, 0, 255, initial(g_hair))
b_hair = sanitize_integer(b_hair, 0, 255, initial(b_hair))
r_facial = sanitize_integer(r_facial, 0, 255, initial(r_facial))
g_facial = sanitize_integer(g_facial, 0, 255, initial(g_facial))
b_facial = sanitize_integer(b_facial, 0, 255, initial(b_facial))
s_tone = sanitize_integer(s_tone, -185, 34, initial(s_tone))
r_skin = sanitize_integer(r_skin, 0, 255, initial(r_skin))
g_skin = sanitize_integer(g_skin, 0, 255, initial(g_skin))
b_skin = sanitize_integer(b_skin, 0, 255, initial(b_skin))
h_style = sanitize_inlist(h_style, hair_styles_list, initial(h_style))
f_style = sanitize_inlist(f_style, facial_hair_styles_list, initial(f_style))
r_eyes = sanitize_integer(r_eyes, 0, 255, initial(r_eyes))
g_eyes = sanitize_integer(g_eyes, 0, 255, initial(g_eyes))
b_eyes = sanitize_integer(b_eyes, 0, 255, initial(b_eyes))
backbag = sanitize_integer(backbag, 1, backbaglist.len, initial(backbag))
b_type = sanitize_text(b_type, initial(b_type))
alternate_option = sanitize_integer(alternate_option, 0, 2, initial(alternate_option))
job_civilian_high = sanitize_integer(job_civilian_high, 0, 65535, initial(job_civilian_high))
job_civilian_med = sanitize_integer(job_civilian_med, 0, 65535, initial(job_civilian_med))
job_civilian_low = sanitize_integer(job_civilian_low, 0, 65535, initial(job_civilian_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))
if (!skills) ZeroSkills(1)
if (skills.len) CalculateSkillPoints()
if (!used_skillpoints) used_skillpoints = 0
if (isnull(disabilities)) disabilities = 0
if (!player_alt_titles) player_alt_titles = new()
if (!organ_data) organ_data = list()
if (!rlimb_data) rlimb_data = list()
if (!gear) gear = list()
if (!home_system) home_system = "Unset"
if (!citizenship) citizenship = "None"
if (!faction) faction = "None"
if (!religion) religion = "None"
return 1
/datum/preferences/proc/save_character_sql(var/client/C)
if (!C)
return 0
if (!current_character)
return insert_character_sql(C)
establish_db_connection(dbcon)
if (!dbcon.IsConnected())
error("Error attempting to connect to MySQL server while saving a character.")
return 0
var/DBQuery/initial_query = dbcon.NewQuery("SELECT COUNT(*) AS rowCount FROM ss13_characters WHERE id = :char_id")
initial_query.Execute(list(":char_id" = current_character))
if (!initial_query.NextRow())
current_character = 0
return insert_character_sql(C)
var/DBQuery/update_query = dbcon.NewQuery({"UPDATE ss13_characters dat
JOIN ss13_characters_flavour flv ON dat.id = flv.char_id
SET
dat.name = :real_name,
dat.metadata = :metadata,
dat.random_name = :is_random,
dat.gender = :gender,
dat.age = :age,
dat.species = :species,
dat.language = :language,
dat.spawnpoint = :spawnpoint,
dat.hair_colour = :hair_colour,
dat.facial_colour = :facial_colour,
dat.skin_tone = :skin_tone,
dat.skin_colour = :skin_colour,
dat.hair_style = :hair_style,
dat.facial_style = :facial_style,
dat.eyes_colour = :eyes_colour,
dat.underwear = :underwear,
dat.undershirt = :undershirt,
dat.backbag = :backbag,
dat.b_type = :b_type,
dat.jobs = :jobs,
dat.alternate_option = :alternate_option,
dat.alternate_titles = :alternate_titles,
dat.disabilities = :disabilities,
dat.skills = :skills,
dat.skills_specialization = :specialization,
dat.home_system = :home_system,
dat.citizenship = :citizenship,
dat.faction = :faction,
dat.religion = :religion,
dat.nt_relation = :nt_relation,
dat.uplink_location = :uplink_loc,
dat.organs_data = :organ_data,
dat.organs_robotic = :organs_robotic,
dat.gear = :gear,
flv.flavour_general = :flv_general,
flv.flavour_head = :flv_head,
flv.flavour_face = :flv_face,
flv.flavour_eyes = :flv_eyes,
flv.flavour_torso = :flv_torso,
flv.flavour_arms = :flv_arms,
flv.flavour_hands = :flv_hands,
flv.flavour_legs = :flv_legs,
flv.flavour_feet = :flv_feet,
flv.robot_default = :robot_default,
flv.robot_standard = :robot_standard,
flv.robot_engineering = :robot_engineering,
flv.robot_construction = :robot_construction,
flv.robot_surgeon = :robot_surgeon,
flv.robot_crisis = :robot_crisis,
flv.robot_miner = :robot_miner,
flv.robot_janitor = :robot_janitor,
flv.robot_service = :robot_service,
flv.robot_clerical = :robot_clerical,
flv.robot_security = :robot_security,
flv.robot_research = :robot_research,
flv.records_medical = :med_rec,
flv.records_security = :sec_rec,
flv.records_employment = :gen_rec,
flv.records_exploit = :exploit_record
WHERE dat.id = :char_id"})
update_query.Execute(get_update_insert_params())
if (update_query.ErrorMsg())
error("Error updating character #[current_character]: [update_query.ErrorMsg()]")
return 0
return 1
/datum/preferences/proc/insert_character_sql(var/client/C)
if (!C)
return 0
establish_db_connection(dbcon)
if (!dbcon.IsConnected())
error("Error attempting to connect to MySQL server while inserting a character.")
return 0
var/params[] = get_update_insert_params(0, C)
var/DBQuery/insert_query = dbcon.NewQuery({"INSERT INTO ss13_characters (id, ckey, name, metadata, random_name, gender, age, species, language, hair_colour, facial_colour, skin_tone, skin_colour, hair_style, facial_style, eyes_colour, underwear, undershirt, backbag, b_type, spawnpoint, jobs, alternate_option, alternate_titles, disabilities, skills, skills_specialization, home_system, citizenship, faction, religion, nt_relation, uplink_location, organs_data, organs_robotic, gear)
VALUES (NULL, :ckey, :real_name, :metadata, :is_random, :gender, :age, :species, :language, :hair_colour, :facial_colour, :skin_tone, :skin_colour, :hair_style, :facial_style, :eyes_colour, :underwear, :undershirt, :backbag, :b_type, :spawnpoint, :jobs, :alternate_option, :alternate_titles, :disabilities, :skills, :specialization, :home_system, :citizenship, :faction, :religion, :nt_relation, :uplink_loc, :organ_data, :organs_robotic, :gear);"})
insert_query.Execute(params, 1)
if (insert_query.ErrorMsg())
return 0
var/DBQuery/get_query = dbcon.NewQuery("SELECT id FROM ss13_characters WHERE ckey = :ckey AND name = :real_name ORDER BY id DESC LIMIT 1;")
get_query.Execute(list(":ckey" = C.ckey, ":real_name" = real_name))
if (get_query.NextRow())
current_character = text2num(get_query.item[1])
params[":char_id"] = current_character
insert_query = dbcon.NewQuery({"INSERT INTO ss13_characters_flavour (char_id, records_employment, records_medical, records_security, records_exploit, flavour_general, flavour_head, flavour_face, flavour_eyes, flavour_torso, flavour_arms, flavour_hands, flavour_legs, flavour_feet, robot_default, robot_standard, robot_engineering, robot_construction, robot_surgeon, robot_crisis, robot_miner, robot_janitor, robot_service, robot_clerical, robot_security, robot_research)
VALUES (:char_id, :gen_rec, :med_rec, :sec_rec, :exploit_record, :flv_general, :flv_head, :flv_face, :flv_eyes, :flv_torso, :flv_arms, :flv_hands, :flv_legs, :flv_feet, :robot_default, :robot_standard, :robot_engineering, :robot_construction, :robot_surgeon, :robot_crisis, :robot_miner, :robot_janitor, :robot_service, :robot_clerical, :robot_security, :robot_research);"})
insert_query.Execute(params, 1)
if (insert_query.ErrorMsg())
return 0
return 1
// Helper function.
// Returns an array to be used in save_character_sql and insert_character_sql.
/datum/preferences/proc/get_update_insert_params(var/include_id = 1, var/client/C = null)
var/hair_hex = "#" + num2hex(r_hair) + num2hex(g_hair) + num2hex(b_hair)
var/facial_hex = "#" + num2hex(r_facial) + num2hex(g_facial) + num2hex(b_facial)
var/eyes_hex = "#" + num2hex(r_eyes) + num2hex(g_eyes) + num2hex(b_eyes)
var/skin_hex = "#" + num2hex(r_skin) + num2hex(g_skin) + num2hex(b_skin)
var/language_string = "None"
if (!istext(language))
if (istype(language, /datum/language))
for (var/L in all_languages)
if (language == all_languages[L])
language_string = L
break
else
language_string = language
var/jobs_list[] = list()
jobs_list["civ_high"] = job_civilian_high
jobs_list["civ_med"] = job_civilian_med
jobs_list["civ_low"] = job_civilian_low
jobs_list["medsci_high"] = job_medsci_high
jobs_list["medsci_med"] = job_medsci_med
jobs_list["medsci_low"] = job_medsci_low
jobs_list["engsec_high"] = job_engsec_high
jobs_list["engsec_med"] = job_engsec_med
jobs_list["engsec_low"] = job_engsec_low
var/params[] = list()
params[":real_name"] = real_name
params[":metadata"] = metadata
params[":is_random"] = be_random_name
params[":gender"] = gender
params[":age"] = age
params[":species"] = species
params[":language"] = language_string
params[":spawnpoint"] = spawnpoint
params[":hair_colour"] = hair_hex
params[":facial_colour"] = facial_hex
params[":skin_tone"] = s_tone
params[":skin_colour"] = skin_hex
params[":hair_style"] = h_style
params[":facial_style"] = f_style
params[":eyes_colour"] = eyes_hex
params[":underwear"] = underwear
params[":undershirt"] = undershirt
params[":backbag"] = backbag
params[":b_type"] = b_type
params[":alternate_option"] = alternate_option
params[":jobs"] = list2params(jobs_list)
params[":alternate_titles"] = list2params(player_alt_titles)
params[":flv_general"] = flavor_texts["general"]
params[":flv_head"] = flavor_texts["head"]
params[":flv_face"] = flavor_texts["face"]
params[":flv_eyes"] = flavor_texts["eyes"]
params[":flv_torso"] = flavor_texts["torso"]
params[":flv_arms"] = flavor_texts["arms"]
params[":flv_hands"] = flavor_texts["hands"]
params[":flv_legs"] = flavor_texts["legs"]
params[":flv_feet"] = flavor_texts["feet"]
params[":robot_default"] = flavour_texts_robot["Default"]
params[":robot_standard"] = flavour_texts_robot["Standard"]
params[":robot_engineering"] = flavour_texts_robot["Engineering"]
params[":robot_construction"] = flavour_texts_robot["Construction"]
params[":robot_surgeon"] = flavour_texts_robot["Surgeon"]
params[":robot_crisis"] = flavour_texts_robot["Crisis"]
params[":robot_miner"] = flavour_texts_robot["Miner"]
params[":robot_janitor"] = flavour_texts_robot["Janitor"]
params[":robot_service"] = flavour_texts_robot["Service"]
params[":robot_clerical"] = flavour_texts_robot["Clerical"]
params[":robot_security"] = flavour_texts_robot["Security"]
params[":robot_research"] = flavour_texts_robot["Research"]
params[":med_rec"] = med_record
params[":sec_rec"] = sec_record
params[":gen_rec"] = gen_record
params[":disabilities"] = disabilities
params[":skills"] = list2params(skills)
params[":specialization"] = skill_specialization
params[":home_system"] = home_system
params[":citizenship"] = citizenship
params[":faction"] = faction
params[":religion"] = religion
params[":nt_relation"] = nanotrasen_relation
params[":uplink_loc"] = uplinklocation
params[":exploit_record"] = exploit_record
params[":organ_data"] = list2params(organ_data)
params[":organs_robotic"] = list2params(rlimb_data)
params[":gear"] = list2params(gear)
if (include_id)
params[":char_id"] = current_character
if (C)
params[":ckey"] = C.ckey
return params
/datum/preferences/proc/new_character_sql(var/client/C)
if (!C)
return 0
current_character = 0
var/DBQuery/char_id_update = dbcon.NewQuery("UPDATE ss13_player_preferences SET current_character = '0' WHERE ckey = :ckey")
char_id_update.Execute(list(":ckey" = C.ckey))
species = "Human"
language = "None"
spawnpoint = "Arrivals Shuttle"
nanotrasen_relation = initial(nanotrasen_relation)
gender = pick(MALE, FEMALE)
real_name = random_name(gender, species)
gear = list()
b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+")
return 1
/datum/preferences/proc/delete_character_sql(var/client/C)
if (!C)
return 0
if (!current_character)
return 0
establish_db_connection(dbcon)
if (!dbcon.IsConnected())
error("Error attempting to connect to MySQL server while deleting a character.")
return 0
var/DBQuery/query = dbcon.NewQuery("SELECT COUNT(*) AS rowCount FROM ss13_characters WHERE id = :char_id AND ckey = :ckey")
query.Execute(list(":char_id" = current_character, ":ckey" = C.ckey))
if (!query.NextRow())
return 0
var/DBQuery/delete_query = dbcon.NewQuery("DELETE FROM ss13_characters WHERE id = :id")
delete_query.Execute(list(":id" = current_character))
var/DBQuery/select_query = dbcon.NewQuery("SELECT id FROM ss13_characters WHERE ckey = :ckey ORDER BY id ASC LIMIT 1")
select_query.Execute(list(":ckey" = C.ckey))
if (select_query.NextRow())
load_character_sql(text2num(select_query.item[1]), C)
else
new_character_sql(C)
C << "<span class='notice'>Your character has been deleted from the database.</span>"
return 1
@@ -0,0 +1,35 @@
/*
* These procs manage the calling of savefile or SQL oriented save and load procs for characters and preference data.
* This way of doing it is necessary for migration to be possible without a huge load of hacks.
* Will also ensure in neat and modular compatibility between the two systems, and the potential introduction of further systems.
*/
/datum/preferences/proc/handle_preferences_load(var/client/C)
if (config.sql_saves)
return load_preferences_sql(C)
else
return load_preferences()
/datum/preferences/proc/handle_preferences_save(var/client/C)
if (config.sql_saves)
return save_preferences_sql(C)
else
return save_preferences()
/datum/preferences/proc/handle_character_load(var/slot = 0, var/client/C)
if (config.sql_saves)
return load_character_sql(slot, C)
else
return load_character(slot)
/datum/preferences/proc/handle_character_save(var/client/C)
if (config.sql_saves)
return save_character_sql(C)
else
return save_character()
/datum/preferences/proc/get_default_character()
if (config.sql_saves)
return current_character
else
return default_slot
+16 -16
View File
@@ -5,7 +5,7 @@
set desc = ".Toggle Between seeing all mob speech, and only speech of nearby mobs"
prefs.toggles ^= CHAT_GHOSTEARS
src << "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTEARS) ? "see all speech in the world" : "only see speech from nearby mobs"]."
prefs.save_preferences()
prefs.handle_preferences_save(src)
feedback_add_details("admin_verb","TGE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggle_ghost_sight()
@@ -14,7 +14,7 @@
set desc = ".Toggle Between seeing all mob emotes, and only emotes of nearby mobs"
prefs.toggles ^= CHAT_GHOSTSIGHT
src << "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTSIGHT) ? "see all emotes in the world" : "only see emotes from nearby mobs"]."
prefs.save_preferences()
prefs.handle_preferences_save(src)
feedback_add_details("admin_verb","TGS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggle_ghost_radio()
@@ -23,7 +23,7 @@
set desc = ".Toggle between hearing all radio chatter, or only from nearby speakers"
prefs.toggles ^= CHAT_GHOSTRADIO
src << "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTRADIO) ? "hear all radio chat in the world" : "only hear from nearby speakers"]."
prefs.save_preferences()
prefs.handle_preferences_save(src)
feedback_add_details("admin_verb","TGR")
/client/proc/toggle_hear_radio()
@@ -32,7 +32,7 @@
set desc = "Toggle seeing radiochatter from radios and speakers"
if(!holder) return
prefs.toggles ^= CHAT_RADIO
prefs.save_preferences()
prefs.handle_preferences_save(src)
usr << "You will [(prefs.toggles & CHAT_RADIO) ? "now" : "no longer"] see radio chatter from radios or speakers"
feedback_add_details("admin_verb","THR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -42,7 +42,7 @@
set desc = "Toggle hearing a notification when admin PMs are recieved"
if(!holder) return
prefs.toggles ^= SOUND_ADMINHELP
prefs.save_preferences()
prefs.handle_preferences_save(src)
usr << "You will [(prefs.toggles & SOUND_ADMINHELP) ? "now" : "no longer"] hear a sound when adminhelps arrive."
feedback_add_details("admin_verb","AHS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -51,7 +51,7 @@
set category = "Preferences"
set desc ="Toggles seeing deadchat"
prefs.toggles ^= CHAT_DEAD
prefs.save_preferences()
prefs.handle_preferences_save(src)
if(src.holder)
src << "You will [(prefs.toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat."
@@ -65,7 +65,7 @@
set category = "Preferences"
set desc = "Toggles seeing prayers"
prefs.toggles ^= CHAT_PRAYER
prefs.save_preferences()
prefs.handle_preferences_save(src)
src << "You will [(prefs.toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat."
feedback_add_details("admin_verb","TP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -74,7 +74,7 @@
set category = "Preferences"
set desc = "Toggles hearing the GameLobby music"
prefs.toggles ^= SOUND_LOBBY
prefs.save_preferences()
prefs.handle_preferences_save(src)
if(prefs.toggles & SOUND_LOBBY)
src << "You will now hear music in the game lobby."
if(istype(mob, /mob/new_player))
@@ -90,7 +90,7 @@
set category = "Preferences"
set desc = "Toggles hearing sounds uploaded by admins"
prefs.toggles ^= SOUND_MIDI
prefs.save_preferences()
prefs.handle_preferences_save(src)
if(prefs.toggles & SOUND_MIDI)
src << "You will now hear any sounds uploaded by admins."
var/sound/break_sound = sound(null, repeat = 0, wait = 0, channel = 777)
@@ -105,7 +105,7 @@
set category = "Preferences"
set desc = "Toggles seeing OutOfCharacter chat"
prefs.toggles ^= CHAT_OOC
prefs.save_preferences()
prefs.handle_preferences_save(src)
src << "You will [(prefs.toggles & CHAT_OOC) ? "now" : "no longer"] see messages on the OOC channel."
feedback_add_details("admin_verb","TOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -115,7 +115,7 @@
set category = "Preferences"
set desc = "Toggles seeing Local OutOfCharacter chat"
prefs.toggles ^= CHAT_LOOC
prefs.save_preferences()
prefs.handle_preferences_save(src)
src << "You will [(prefs.toggles & CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel."
feedback_add_details("admin_verb","TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -126,7 +126,7 @@
set category = "Preferences"
set desc = "Toggles seeing chat tags/icons"
prefs.toggles ^= CHAT_NOICONS
prefs.save_preferences()
prefs.handle_preferences_save(src)
src << "You will [!(prefs.toggles & CHAT_NOICONS) ? "now" : "no longer"] see chat tag icons."
feedback_add_details("admin_verb","TCTAG") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -137,7 +137,7 @@
set category = "Preferences"
set desc = "Toggles hearing ambient sound effects"
prefs.toggles ^= SOUND_AMBIENCE
prefs.save_preferences()
prefs.handle_preferences_save(src)
if(prefs.toggles & SOUND_AMBIENCE)
src << "You will now hear ambient sounds."
else
@@ -154,7 +154,7 @@
var/role_flag = be_special_flags[role]
if(!role_flag) return
prefs.be_special ^= role_flag
prefs.save_preferences()
prefs.handle_preferences_save(src)
src << "You will [(prefs.be_special & role_flag) ? "now" : "no longer"] be considered for [role] events (where possible)."
feedback_add_details("admin_verb","TBeSpecial") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -193,5 +193,5 @@
prefs.UI_style = UI_style_new
prefs.UI_style_alpha = UI_style_alpha_new
prefs.UI_style_color = UI_style_color_new
prefs.save_preferences()
usr << "UI was saved"
prefs.handle_preferences_save(src)
usr << "UI was saved"