Saving + Updating + ALL THE THINGS

Everything. Absoloutely positively everything. Fuck.

Hey, it compiles now, doe!
This commit is contained in:
skull132
2016-12-11 21:44:35 +02:00
parent 5fbd15a846
commit ff7f93cbd8
23 changed files with 494 additions and 168 deletions
@@ -11,6 +11,15 @@
/datum/category_item/player_setup_item/antagonism/candidacy/gather_load_query()
return list("ss13_characters" = list("vars" = list("be_special_role"), "args" = list("id")))
/datum/category_item/player_setup_item/antagonism/candidacy/gather_load_parameters()
return list(":id" = pref.current_character)
/datum/category_item/player_setup_item/antagonism/candidacy/gather_save_query()
return list("ss13_characters" = list("be_special_role", "id" = 1))
/datum/category_item/player_setup_item/antagonism/candidacy/gather_save_parameters()
return list(":be_special_role" = list2params(pref.be_special_role), ":id" = pref.current_character)
/datum/category_item/player_setup_item/antagonism/candidacy/sanitize_character(var/sql_load = 0)
if (sql_load)
if (pref.be_special_role)
@@ -16,6 +16,16 @@ var/global/list/uplink_locations = list("PDA", "Headset", "None")
return list("ss13_characters_flavour" = list("vars" = list("records_exploit" = "exploit_record"), "args" = list("char_id")),
"ss13_characters" = list("vars" = list("uplink_location" = "uplinklocation"), "args" = list("id")))
/datum/category_item/player_setup_item/antagonism/basic/gather_load_parameters()
return list(":char_id" = pref.current_character, ":id" = pref.current_character)
/datum/category_item/player_setup_item/antagonism/basic/gather_save_query()
return list("ss13_characters_flavour" = list("records_exploit", "char_id" = 1),
"ss13_characters" = list("uplink_location", "id" = 1))
/datum/category_item/player_setup_item/antagonism/basic/gather_save_parameters()
return list(":records_exploit" = pref.exploit_record, ":char_id" = pref.current_character, ":uplink_location" = pref.uplinklocation, ":id" = pref.current_character)
/datum/category_item/player_setup_item/antagonism/basic/sanitize_character()
pref.uplinklocation = sanitize_inlist(pref.uplinklocation, uplink_locations, initial(pref.uplinklocation))
@@ -1,7 +1,7 @@
/datum/category_item/player_setup_item/general/basic
name = "Basic"
sort_order = 1
var/list/valid_player_genders = list(MALE, FEMALE)
var/static/list/valid_player_genders = list(MALE, FEMALE)
/datum/category_item/player_setup_item/general/basic/load_character(var/savefile/S)
S["real_name"] >> pref.real_name
@@ -28,6 +28,27 @@
"spawnpoint",),
"args" = list("id")))
/datum/category_item/player_setup_item/general/basic/gather_load_parameters()
return list(":id" = pref.current_character)
/datum/category_item/player_setup_item/general/basic/gather_save_query()
return list("ss13_characters" = list("name",
"random_name",
"gender",
"age",
"metadata",
"spawnpoint",
"id" = 1))
/datum/category_item/player_setup_item/general/basic/gather_save_parameters()
return list("ss13_characters" = list(":name" = pref.real_name,
":random_name" = pref.be_random_name,
":gender" = pref.gender,
":age" = pref.age,
":metadata" = pref.metadata,
":spawnpoint" = pref.spawnpoint,
":id" = pref.current_character))
/datum/category_item/player_setup_item/general/basic/sanitize_character()
pref.age = sanitize_integer(text2num(pref.age), AGE_MIN, AGE_MAX, initial(pref.age))
pref.gender = sanitize_inlist(pref.gender, valid_player_genders, pick(valid_player_genders))
@@ -11,6 +11,17 @@
/datum/category_item/player_setup_item/general/language/gather_load_query()
return list("ss13_characters" = list("vars" = list("language" = "alternate_languages"), "args" = list("id")))
/datum/category_item/player_setup_item/general/language/gather_load_parameters()
return list(":id" = pref.current_character)
/datum/category_item/player_setup_item/general/language/gather_save_query()
return list("ss13_characters" = list("language",
"id" = 1))
/datum/category_item/player_setup_item/general/language/gather_save_parameters()
return list("ss13_characters" = list(":language" = list2params(pref.alternate_languages),
":id" = pref.current_character))
/datum/category_item/player_setup_item/general/language/sanitize_character(var/sql_load = 0)
if (sql_load)
pref.alternate_languages = params2list(pref.alternate_languages)
@@ -63,6 +63,39 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
"organs_robotic" = "rlimb_data"),
"args" = list("id")))
/datum/category_item/player_setup_item/general/body/gather_load_parameters()
return list(":id" = pref.current_character)
/datum/category_item/player_setup_item/general/body/gather_save_query()
return list("ss13_characters" = list("species",
"hair_colour",
"facial_colour",
"skin_tone",
"skin_colour",
"hair_style",
"facial_style",
"eyes_colour",
"b_type",
"disabilities",
"organs_data",
"organs_robotic",
"id" = 1))
/datum/category_item/player_setup_item/general/body/gather_save_parameters()
return list("ss13_characters" = list(":species" = pref.species,
":hair_colour" = "#" + num2hex(pref.r_hair) + num2hex(pref.g_hair) + num2hex(pref.b_hair),
":facial_colour" = "#" + num2hex(pref.r_facial) + num2hex(pref.g_facial) + num2hex(pref.b_facial),
":skin_tone" = pref.s_tone,
":skin_colour" = "#" + num2hex(pref.r_skin) + num2hex(pref.g_skin) + num2hex(pref.b_skin),
":hair_style" = pref.h_style,
":facial_style" = pref.f_style,
":eyes_colour" = "#" + num2hex(pref.r_eyes) + num2hex(pref.g_eyes) + num2hex(pref.b_eyes),
":b_type" = pref.b_type,
":disabilities" = pref.disabilities,
":organs_data" = list2params(pref.organ_data),
":organs_robotic"= list2params(pref.rlimb_data),
":id" = pref.current_character))
/datum/category_item/player_setup_item/general/body/sanitize_character(var/sql_load = 0)
if(!pref.species || !(pref.species in playable_species))
pref.species = "Human"
@@ -17,6 +17,15 @@
/datum/category_item/player_setup_item/general/equipment/gather_load_query()
return list("ss13_characters" = list("vars" = list("underwear", "undershirt", "backbag", "gear"), "args" = list("id")))
/datum/category_item/player_setup_item/general/equipment/gather_load_parameters()
return list(":id" = pref.current_character)
/datum/category_item/player_setup_item/general/equipment/gather_save_query()
return list("ss13_characters" = list("underwear", "undershirt", "backbag", "gear", "id" = 1))
/datum/category_item/player_setup_item/general/equipment/gather_save_parameters()
return list(":underwear" = pref.underwear, ":undershirt" = pref.undershirt, ":backbag" = pref.backbag, ":gear" = list2params(pref.gear), ":id" = pref.current_character)
/datum/category_item/player_setup_item/general/equipment/sanitize_character(var/sql_load = 0)
if (sql_load)
pref.backbag = text2num(pref.backbag)
@@ -29,6 +29,27 @@
"args" = list("char_id")),
"ss13_characters" = list("vars" = list("home_system", "citizenship", "faction", "religion"), "args" = list("id")))
/datum/category_item/player_setup_item/general/background/gather_load_parameters()
return list(":id" = pref.current_character, ":char_id" = pref.current_character)
/datum/category_item/player_setup_item/general/background/gather_save_query()
return list("ss13_characters_flavour" = list("records_employment",
"records_medical",
"records_security",
"char_id" = 1),
"ss13_characters" = list("home_system", "citizenship", "faction", "religion", "id" = 1))
/datum/category_item/player_setup_item/general/background/gather_save_parameters()
return list(":records_employment" = pref.gen_record,
":records_medical" = pref.med_record,
":records_security" = pref.sec_record,
":char_id" = pref.current_character,
":home_system" = pref.home_system,
":citizenship" = pref.citizenship,
":faction" = pref.faction,
":religion" = pref.religion,
":id" = pref.current_character)
/datum/category_item/player_setup_item/general/background/sanitize_character()
if(!pref.home_system)
pref.home_system = "Unset"
@@ -35,14 +35,14 @@
/datum/category_item/player_setup_item/general/flavor/gather_load_query()
var/list/var_list = list("flavour_general" = "flavor_texts/general",
"flavour_head" = "flavour_texts/head",
"flavour_face" = "flavour_texts/face",
"flavour_eyes" = "flavour_texts/eyes",
"flavour_torso" = "flavour_texts/torso",
"flavour_arms" = "flavour_texts/arms",
"flavour_hands" = "flavour_texts/hands",
"flavour_legs" = "flavour_texts/legs",
"flavour_feet" = "flavour_texts/feet",
"flavour_head" = "flavor_texts/head",
"flavour_face" = "flavor_texts/face",
"flavour_eyes" = "flavor_texts/eyes",
"flavour_torso" = "flavor_texts/torso",
"flavour_arms" = "flavor_texts/arms",
"flavour_hands" = "flavor_texts/hands",
"flavour_legs" = "flavor_texts/legs",
"flavour_feet" = "flavor_texts/feet",
"robot_default" = "flavour_texts_robot/default")
for (var/module in robot_module_types)
@@ -50,6 +50,44 @@
return list("ss13_characters_flavour" = list("vars" = var_list, "args" = list("char_id")))
/datum/category_item/player_setup_item/general/flavor/gather_load_parameters()
return list(":char_id" = pref.current_character)
/datum/category_item/player_setup_item/general/flavor/gather_save_query()
var/list/var_list = list("flavour_general",
"flavour_head",
"flavour_face",
"flavour_eyes",
"flavour_torso",
"flavour_arms",
"flavour_hands",
"flavour_legs",
"flavour_feet",
"robot_default",
"char_id" = 1)
for (var/module in robot_module_types)
var_list += "robot_[module]"
return list("ss13_characters_flavour" = var_list)
/datum/category_item/player_setup_item/general/flavor/gather_save_parameters()
var/list/var_list = list(":char_id" = pref.current_character,
":flavour_head" = pref.flavor_texts["head"],
":flavour_face" = pref.flavor_texts["face"],
":flavour_eyes" = pref.flavor_texts["eyes"],
":flavour_torso" = pref.flavor_texts["torso"],
":flavour_arms" = pref.flavor_texts["arms"],
":flavour_hands" = pref.flavor_texts["hands"],
":flavour_legs" = pref.flavor_texts["legs"],
":flavour_feet" = pref.flavor_texts["feet"],
":robot_default" = pref.flavour_texts_robot["default"])
for (var/module in robot_module_types)
var_list[":robot_[module]"] += pref.flavour_texts_robot[module]
return list("ss13_characters_flavour" = var_list)
/datum/category_item/player_setup_item/general/flavor/sanitize_character()
return
@@ -17,6 +17,15 @@
/datum/category_item/player_setup_item/player_global/ui/gather_load_query()
return list("ss13_player_preferences" = list("vars" = list("UI_style", "UI_style_color", "UI_style_alpha", "ooccolor"), "args" = list("ckey")))
/datum/category_item/player_setup_item/player_global/ui/gather_load_parameters()
return list(":ckey" = pref.client.ckey)
/datum/category_item/player_setup_item/player_global/ui/gather_save_query()
return list("ss13_player_preferences" = list("UI_style", "UI_style_color", "UI_style_alpha", "ooccolor", "ckey" = 1))
/datum/category_item/player_setup_item/player_global/ui/gather_save_parameters()
return list(":ckey" = pref.client.ckey, ":UI_style" = pref.UI_style, ":UI_style_alpha" = pref.UI_style_alpha, ":UI_style_color" = pref.UI_style_color, ":ooccolor" = pref.ooccolor)
/datum/category_item/player_setup_item/player_global/ui/sanitize_preferences()
pref.UI_style = sanitize_inlist(pref.UI_style, all_ui_styles, initial(pref.UI_style))
pref.UI_style_color = sanitize_hexcolor(pref.UI_style_color, initial(pref.UI_style_color))
@@ -21,6 +21,21 @@
/datum/category_item/player_setup_item/player_global/settings/gather_load_query()
return list("ss13_player_preferences" = list("vars" = list("lastchangelog", "current_character", "toggles", "asfx_toggles" = "asfx_togs", "motd_hash", "memo_hash"), "args" = list("ckey")))
/datum/category_item/player_setup_item/player_global/settings/gather_load_parameters()
return list(":ckey" = pref.client.ckey)
/datum/category_item/player_setup_item/player_global/settings/gather_save_query()
return list("ss13_player_preferences" = list("lastchangelog", "current_character", "toggles", "asfx_toggles", "motd_hash", "memo_hash", "ckey" = 1))
/datum/category_item/player_setup_item/player_global/settings/gather_save_parameters()
return list(":ckey" = pref.client.ckey,
":lastchangelog" = pref.lastchangelog,
":current_character" = pref.current_character,
":toggles" = pref.toggles,
":asfx_toggles" = pref.asfx_togs,
":motd_hash" = pref.motd_hash,
":memo_hash" = pref.memo_hash)
/datum/category_item/player_setup_item/player_global/settings/sanitize_preferences(var/sql_load = 0)
if (sql_load)
pref.current_character = text2num(pref.current_character)
@@ -28,6 +43,9 @@
pref.lastchangelog = sanitize_text(pref.lastchangelog, initial(pref.lastchangelog))
pref.default_slot = sanitize_integer(text2num(pref.default_slot), 1, config.character_slots, initial(pref.default_slot))
pref.toggles = sanitize_integer(text2num(pref.toggles), 0, 65535, initial(pref.toggles))
pref.asfx_togs = sanitize_integer(text2num(pref.asfx_togs), 0, 65535, initial(pref.toggles))
pref.motd_hash = sanitize_text(pref.motd_hash, initial(pref.motd_hash))
pref.memo_hash = sanitize_text(pref.memo_hash, initial(pref.memo_hash))
/datum/category_item/player_setup_item/player_global/settings/content(var/mob/user)
. += "<b>Play admin midis:</b> <a href='?src=\ref[src];toggle=[SOUND_MIDI]'><b>[(pref.toggles & SOUND_MIDI) ? "Yes" : "No"]</b></a><br>"
@@ -11,6 +11,15 @@
/datum/category_item/player_setup_item/player_global/language/gather_load_query()
return list("ss13_player_preferences" = list("vars" = list("language_prefixes"), "args" = list("ckey")))
/datum/category_item/player_setup_item/player_global/language/gather_load_parameters()
return list(":ckey" = pref.client.ckey)
/datum/category_item/player_setup_item/player_global/ui/gather_save_query()
return list("ss13_player_preferences" = list("language_prefixes", "ckey" = 1))
/datum/category_item/player_setup_item/player_global/language/gather_save_parameters()
return list(":ckey" = pref.client.ckey, ":language_prefixes" = list2params(pref.language_prefixes))
/datum/category_item/player_setup_item/player_global/language/sanitize_preferences(var/sql_load = 0)
if (sql_load && pref.language_prefixes)
pref.language_prefixes = params2list(pref.language_prefixes)
@@ -36,9 +36,28 @@
/datum/category_item/player_setup_item/occupation/gather_load_query()
return list("ss13_characters" = list("vars" = list("jobs" = "unsanitized_jobs", "alternate_option", "alternate_titles" = "player_alt_titles"), "args" = list("id")))
/datum/category_item/player_setup_item/occupation/gather_load_parameters()
return list(":id" = pref.current_character)
/datum/category_item/player_setup_item/occupation/gather_save_query()
return list("ss13_characters" = list("jobs", "alternate_option", "alternate_titles", "id" = 1))
/datum/category_item/player_setup_item/occupation/gather_save_parameters()
var/list/compiled_jobs = list("job_civilian_high" = pref.job_civilian_high,
"job_civilian_med" = pref.job_civilian_med,
"job_civilian_low" = pref.job_civilian_low,
"job_medsci_high" = pref.job_medsci_high,
"job_medsci_med" = pref.job_medsci_med,
"job_medsci_low" = pref.job_medsci_low,
"job_engsec_high" = pref.job_engsec_high,
"job_engsec_med" = pref.job_engsec_med,
"job_engsec_low" = pref.job_engsec_low)
return list(":jobs" = list2params(compiled_jobs), ":alternate_option" = pref.alternate_option, ":alternate_titles" = list2params(pref.player_alt_titles), ":id" = pref.current_character)
/datum/category_item/player_setup_item/occupation/sanitize_character(var/sql_load = 0)
if (sql_load)
pref.alternate_option = text2num(alternate_option)
pref.alternate_option = text2num(pref.alternate_option)
var/list/jobs = params2list(pref.unsanitized_jobs)
@@ -109,6 +109,7 @@
/datum/category_group/player_setup_category
var/sort_order = 0
var/sql_role = SQL_CHARACTER
var/modified = 0
/datum/category_group/player_setup_category/dd_SortValue()
return sort_order
@@ -132,131 +133,40 @@
for(var/datum/category_item/player_setup_item/PI in items)
PI.sanitize_character(config.sql_saves)
/*
* A proc for dynamically loading a character from the database.
* See the category items for procs on what pieces are given.
*
* Each query is cached as well, after generation. Only things recompiled are the arguments and the finalized query text (with arguments in it).
*/
/datum/category_group/player_setup_category/proc/handle_sql_loading(var/load_type)
var/static/list/query_cache
// We aren't loading this category. Bye.
if (sql_role != load_type)
return
if (isnull(query_cache))
query_cache = list()
// This handles the generation of queries. One per category, total of 5 UNLESS one category wants to query more than one table.
// It uses like, 3+ levels of lists. But it works, and is only run once per category in the global sense. So technically, efficient!
// :D - Skull132
if (!query_cache.len || isnull(query_cache[type]))
query_cache[type] = list()
var/list/tables = list()
// First, consolidate the different lists into one.
for (var/datum/category_item/player_setup_item/PI in items)
var/list/pi_tables = PI.gather_load_query()
// Expected layout: list("table A name" = list("vars" = list("column name" = "var name"), "args" = list()),
// "table B name" = list("vars" = list(), "args" = list()))
for (var/table in pi_tables)
var/list/A = pi_tables[table]
if (isnull(tables[table]))
tables[table] = list("vars" = list(), "args" = list())
tables[table]["vars"] |= A["vars"]
tables[table]["args"] |= A["args"]
// Second, create the queries and save them.
for (var/table in tables)
var/query = "SELECT "
var/list/var_names = tables[table]["vars"]
var/count = var_names.len
// Process the variables and rows we want.
var/i = 1
for (var/name in var_names)
query += name
if (!isnull(var_names[name]))
var/new_name = var_names[name]
var_names.Remove(name)
var_names.Insert(i, new_name)
if (i != count)
query += ", "
else
query += " "
i++
query += "FROM [table] WHERE "
// Process the args.
var/list/arg_names = tables[table]["args"]
count = arg_names.len
for (i = 1, i <= count, i++)
query += "[arg_names[i]] = :[arg_names[i]]"
arg_names[i] = ":[arg_names[i]]"
if (i != count)
query += " AND "
else
query += ";"
// Save it.
query_cache[type][query] = var_names
// Need to typecast due to reasons.
var/datum/category_collection/player_setup_collection/cc = collection
// Actually utilize the queries.
var/list/arg_list = gather_load_parameters()
for (var/query_text in query_cache[type])
var/DBQuery/query = dbcon.NewQuery(query_text)
query.Execute(arg_list, 1)
// Each query should only return exactly 1 row.
var/list/var_names = query_cache[type][query_text]
if (query.NextRow())
for (var/i = 1, i <= var_names.len, i++)
var/list/layers = splittext(var_names[i], "/")
if (layers.len == 1)
cc.preferences.vars[var_names[i]] = query.item[i]
else
cc.preferences.vars[layers[1]][layers[2]] = query.item[i]
/datum/category_group/player_setup_category/proc/gather_load_parameters()
var/list/arg_list = list()
for (var/datum/category_item/player_setup_item/PI in items)
arg_list |= PI.gather_load_parameters()
return arg_list
/datum/category_group/player_setup_category/proc/save_character(var/savefile/S)
// Sanitize all data, then save it
for(var/datum/category_item/player_setup_item/PI in items)
for (var/datum/category_item/player_setup_item/PI in items)
PI.sanitize_character()
for(var/datum/category_item/player_setup_item/PI in items)
PI.save_character(S)
if (!config.sql_saves || !establish_db_connection(dbcon))
for (var/datum/category_item/player_setup_item/PI in items)
PI.save_character(S)
else
if (modified && sql_role == SQL_CHARACTER)
handle_sql_saving(SQL_CHARACTER)
modified = 0
/datum/category_group/player_setup_category/proc/load_preferences(var/savefile/S)
if (!config.sql_saves || !establish_db_connection(dbcon))
for(var/datum/category_item/player_setup_item/PI in items)
for (var/datum/category_item/player_setup_item/PI in items)
PI.load_preferences(S)
else
handle_sql_loading(SQL_PREFERENCES)
for(var/datum/category_item/player_setup_item/PI in items)
for (var/datum/category_item/player_setup_item/PI in items)
PI.sanitize_preferences(config.sql_saves)
/datum/category_group/player_setup_category/proc/save_preferences(var/savefile/S)
for(var/datum/category_item/player_setup_item/PI in items)
for (var/datum/category_item/player_setup_item/PI in items)
PI.sanitize_preferences()
for(var/datum/category_item/player_setup_item/PI in items)
PI.save_preferences(S)
if (!config.sql_saves || !establish_db_connection(dbcon))
for (var/datum/category_item/player_setup_item/PI in items)
PI.save_preferences(S)
else
if (modified && sql_role == SQL_PREFERENCES)
handle_sql_saving(SQL_PREFERENCES)
modified = 0
/datum/category_group/player_setup_category/proc/update_setup(var/savefile/preferences, var/savefile/character)
for(var/datum/category_item/player_setup_item/PI in items)
@@ -332,12 +242,24 @@
/datum/category_item/player_setup_item/proc/gather_load_query()
return list()
/*
* Called when the owner category is composing its insert query
*/
/datum/category_item/player_setup_item/proc/gather_save_query()
return list()
/*
* Called when the owner category is composing its query parameters for loading.
*/
/datum/category_item/player_setup_item/proc/gather_load_parameters()
return list()
/*
* Called when the owner category is composing its query parameters for inserting a new record.
*/
/datum/category_item/player_setup_item/proc/gather_save_parameters()
return list()
/datum/category_item/player_setup_item/proc/content()
return
@@ -351,11 +273,14 @@
if(..())
return 1
var/mob/user = usr
if(!user.client)
if (!user.client)
return 1
. = OnTopic(href, href_list, user)
if(. == TOPIC_REFRESH)
if (. != TOPIC_NOACTION)
var/datum/category_group/player_setup_category/cat = category
cat.modified = 1
if (. == TOPIC_REFRESH)
user.client.prefs.ShowChoices(user)
/datum/category_item/player_setup_item/CanUseTopic(var/mob/user)
@@ -367,6 +292,3 @@
/datum/category_item/player_setup_item/proc/preference_mob()
if(pref && pref.client && pref.client.mob)
return pref.client.mob
#undef SQL_CHARACTER
#undef SQL_PREFERENCES
@@ -0,0 +1,197 @@
/*
* A proc for dynamically loading a character from the database.
* See the category items for procs on what pieces are given.
*
* Each query is cached as well, after generation. Only things recompiled are the arguments and the finalized query text (with arguments in it).
*/
/datum/category_group/player_setup_category/proc/handle_sql_loading(var/role_type)
var/static/list/query_cache
// We aren't loading this category. Bye.
if (role_type && sql_role != role_type)
return
if (isnull(query_cache))
query_cache = list()
// This handles the generation of queries. One per category, total of 5 UNLESS one category wants to query more than one table.
// It uses like, 3+ levels of lists. But it works, and is only run once per category in the global sense. So technically, efficient!
// :D - Skull132
if (!query_cache.len || isnull(query_cache[type]))
query_cache[type] = list()
var/list/tables = list()
// First, consolidate the different lists into one.
for (var/datum/category_item/player_setup_item/PI in items)
var/list/pi_tables = PI.gather_load_query()
// Expected layout: list("table A name" = list("vars" = list("column name" = "var name"), "args" = list()),
// "table B name" = list("vars" = list(), "args" = list()))
for (var/table in pi_tables)
var/list/A = pi_tables[table]
if (isnull(tables[table]))
tables[table] = list("vars" = list(), "args" = list())
tables[table]["vars"] |= A["vars"]
tables[table]["args"] |= A["args"]
// Second, create the queries and save them.
for (var/table in tables)
var/query = "SELECT "
var/list/var_names = tables[table]["vars"]
var/count = var_names.len
// Process the variables and rows we want.
var/i = 1
for (var/name in var_names)
query += name
if (!isnull(var_names[name]))
var/new_name = var_names[name]
var_names.Remove(name)
var_names.Insert(i, new_name)
if (i != count)
query += ", "
else
query += " "
i++
query += "FROM [table] WHERE "
// Process the args.
var/list/arg_names = tables[table]["args"]
count = arg_names.len
for (i = 1, i <= count, i++)
query += "[arg_names[i]] = :[arg_names[i]]"
arg_names[i] = ":[arg_names[i]]"
if (i != count)
query += " AND "
else
query += ";"
// Save it.
query_cache[type][query] = var_names
// Need to typecast due to reasons.
var/datum/category_collection/player_setup_collection/cc = collection
// Actually utilize the queries.
var/list/arg_list = gather_load_parameters()
for (var/query_text in query_cache[type])
var/DBQuery/query = dbcon.NewQuery(query_text)
query.Execute(arg_list, 1)
if (query.ErrorMsg())
error("Error loading character from SQL: [query.ErrorMsg()]")
// Each query should only return exactly 1 row.
var/list/var_names = query_cache[type][query_text]
if (query.NextRow())
for (var/i = 1, i <= var_names.len, i++)
var/list/layers = splittext(var_names[i], "/")
try
if (layers.len == 1)
cc.preferences.vars[var_names[i]] = query.item[i]
else
cc.preferences.vars[layers[1]][layers[2]] = query.item[i]
catch(var/exception/e)
error("Error loading character from SQL: [e.name]")
log_debug("SQL Saves: [e.name]")
log_debug("SQL Saves: [e.desc]")
/datum/category_group/player_setup_category/proc/gather_load_parameters()
var/list/arg_list = list()
for (var/datum/category_item/player_setup_item/PI in items)
arg_list |= PI.gather_load_parameters()
return arg_list
/*
* A proc for dynamically inserting new character and preference records into the database.
* See the category items for procs on what pieces are given.
*
* Each query is cached as well, after generation. Only things recompiled are the arguments and the finalized query text (with arguments in it).
*/
/datum/category_group/player_setup_category/proc/handle_sql_saving(var/role_type)
var/static/list/query_cache
// We aren't loading this category. Bye.
if (role_type && sql_role != role_type)
return
if (isnull(query_cache))
query_cache = list()
// This handles the generation of queries. One per category, total of 5 UNLESS one category wants to query more than one table.
// It uses like, 3+ levels of lists. But it works, and is only run once per category in the global sense. So technically, efficient!
// :D - Skull132
if (!query_cache.len || isnull(query_cache[type]))
query_cache[type] = list()
var/list/tables = list()
// First, consolidate the different lists into one.
for (var/datum/category_item/player_setup_item/PI in items)
var/list/pi_tables = PI.gather_save_query()
// Expected layout: list("table A name" = list("var1" = 1, "var2" = 0, "var3" = 1),
// "table B name" = list("var4" = 0, "var5" = 0, "var6" = 0))
for (var/table in pi_tables)
var/list/A = pi_tables[table]
if (isnull(tables[table]))
tables[table] = list()
tables[table] |= A
// Second, create the queries and save them.
for (var/table in tables)
var/query = "INSERT INTO [table] ("
var/list/var_names = tables[table]
query += "[jointext(var_names, ", ")]) VALUES ("
// Process the args.
var/list/arg_names = list()
for (var/variable in var_names)
arg_names += ":[variable]"
query += "[jointext(arg_names, ", ")]) ON DUPLICATE KEY UPDATE"
var/i = 1
for (var/variable in var_names)
if (isnull(var_names[variable]))
query += " [variable] = [arg_names[i]]"
i++
// Save it.
query_cache[type] += query
// Actually utilize the queries.
var/list/arg_list = gather_save_parameters()
for (var/query_text in query_cache[type])
var/DBQuery/query = dbcon.NewQuery(query_text)
query.Execute(arg_list, 1)
if (query.ErrorMsg())
error("Error saving character to SQL: [query.ErrorMsg()]")
// Get the character ID if we inserted a new character.
if (role_type == SQL_CHARACTER)
// Need to typecast due to reasons.
var/datum/category_collection/player_setup_collection/cc = collection
if (!cc.preferences.current_character)
var/DBQuery/query = dbcon.NewQuery("SELECT id FROM ss13_characters WHERE ckey = :ckey ORDER BY id DESC LIMIT 1")
query.Execute(list(":ckey" = cc.preferences.client.ckey))
if (query.NextRow())
cc.preferences.current_character = text2num(query.item[1])
/datum/category_group/player_setup_category/proc/gather_save_parameters()
var/list/arg_list = list()
for (var/datum/category_item/player_setup_item/PI in items)
arg_list |= PI.gather_save_parameters()
return arg_list
@@ -15,6 +15,15 @@
/datum/category_item/player_setup_item/skills/gather_load_query()
return list("ss13_characters" = list("vars" = list("skills", "skill_specialization"), "args" = list("id")))
/datum/category_item/player_setup_item/skills/gather_load_parameters()
return list(":id" = pref.current_character)
/datum/category_item/player_setup_item/skills/gather_save_query()
return list("ss13_characters" = list("skills", "skill_specialization", "id" = 1))
/datum/category_item/player_setup_item/skills/gather_save_parameters()
return list(":skills" = list2params(pref.skills), ":skill_specialization" = pref.skill_specialization, ":id" = pref.current_character)
/datum/category_item/player_setup_item/skills/sanitize_character(var/sql_load = 0)
if (SKILLS == null)
setup_skills()
+11 -21
View File
@@ -88,6 +88,9 @@ datum/preferences
var/job_engsec_med = 0
var/job_engsec_low = 0
// A text blob which temporarily houses data from the SQL.
var/unsanitized_jobs = ""
//Keeps track of preferrence for not getting any wanted jobs
var/alternate_option = 0
@@ -126,22 +129,6 @@ datum/preferences
var/datum/category_collection/player_setup_collection/player_setup
/datum/preferences/New(client/C)
// #TODO-MERGE: Review SQL saving and migration
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)
player_setup = new(src)
gender = pick(MALE, FEMALE)
real_name = random_name(gender,species)
@@ -153,16 +140,16 @@ datum/preferences
client = C
if(!IsGuestKey(C.key))
load_path(C.ckey)
handle_preferences_load(C)
load_preferences()
load_and_update_character()
ZeroSkills(1)
/datum/preferences/proc/load_and_update_character(var/slot)
handle_character_load(get_default_slot(), client)
load_character(slot)
if(update_setup(loaded_preferences, loaded_character))
handle_preferences_save(client)
handle_character_save(client)
save_preferences()
save_character()
/datum/preferences/proc/getMinAge(var/age_min)
if(species == "Vaurca" || species == "Machine" || species == "Diona")
@@ -284,7 +271,10 @@ datum/preferences
load_character()
else if(href_list["load"])
if(!IsGuestKey(usr.key))
open_load_dialog(usr)
if (config.sql_saves)
open_load_dialog_sql(usr)
else
open_load_dialog_file(usr)
return 1
else if(href_list["changeslot"])
load_character(text2num(href_list["changeslot"]))
+3 -3
View File
@@ -18,7 +18,7 @@
set category = "Preferences"
set desc = "Toggles hearing ambient sound effects"
prefs.asfx_togs ^= ASFX_AMBIENCE
prefs.handle_preferences_save(src)
prefs.save_preferences()
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.handle_preferences_save(src)
prefs.save_preferences()
if(prefs.asfx_togs & ASFX_FOOTSTEPS)
src << "You will now hear footstep sounds."
else
@@ -45,7 +45,7 @@
set category = "SoundFx Prefs"
set desc = "Toggles hearing of the vote alarm"
prefs.asfx_togs ^= ASFX_VOTE
prefs.handle_preferences_save(src)
prefs.save_preferences()
if(prefs.asfx_togs & ASFX_VOTE)
src << "You will now hear the vote alarm."
else
+13 -13
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.handle_preferences_save(src)
prefs.save_preferences()
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.handle_preferences_save(src)
prefs.save_preferences()
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.handle_preferences_save(src)
prefs.save_preferences()
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.handle_preferences_save(src)
prefs.save_preferences()
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.handle_preferences_save(src)
prefs.save_preferences()
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.handle_preferences_save(src)
prefs.save_preferences()
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.handle_preferences_save(src)
prefs.save_preferences()
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.handle_preferences_save(src)
prefs.save_preferences()
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.handle_preferences_save(src)
prefs.save_preferences()
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.handle_preferences_save(src)
prefs.save_preferences()
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.handle_preferences_save(src)
prefs.save_preferences()
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.handle_preferences_save(src)
prefs.save_preferences()
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.handle_preferences_save(src)
prefs.save_preferences()
if(prefs.toggles & SOUND_AMBIENCE)
src << "You will now hear ambient sounds."
else