diff --git a/baystation12.dme b/baystation12.dme
index e4c660ca7e1..884ad691a88 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -1013,6 +1013,7 @@
#include "code\modules\client\preferences_toggles.dm"
#include "code\modules\client\ui_style.dm"
#include "code\modules\client\preference_setup\preference_setup.dm"
+#include "code\modules\client\preference_setup\preferences_sql.dm"
#include "code\modules\client\preference_setup\antagonism\01_candidacy.dm"
#include "code\modules\client\preference_setup\antagonism\02_setup.dm"
#include "code\modules\client\preference_setup\general\01_basic.dm"
diff --git a/code/datums/server_greeting.dm b/code/datums/server_greeting.dm
index 70c9409ef95..0a9511d018f 100644
--- a/code/datums/server_greeting.dm
+++ b/code/datums/server_greeting.dm
@@ -207,7 +207,7 @@
user << output(JS_SANITIZE(data), "greeting.browser:AddContent")
if (save_prefs)
- user.prefs.handle_preferences_save(user)
+ user.prefs.save_preferences()
/*
* Basically the Topic proc for the greeting datum.
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 732421ab782..56be3304b8e 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -551,7 +551,7 @@ var/list/admin_verbs_cciaa = list(
prefs.ooccolor = input(src, "Please select your OOC colour.", "OOC colour") as color
else if(response == "Reset to default")
prefs.ooccolor = initial(prefs.ooccolor)
- prefs.handle_preferences_save(src)
+ prefs.save_preferences()
feedback_add_details("admin_verb","OC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
@@ -920,7 +920,7 @@ var/list/admin_verbs_cciaa = list(
usr << "You now will get attack log messages"
else
usr << "You now won't get attack log messages"
- prefs.handle_preferences_save(src)
+ prefs.save_preferences()
/client/proc/toggleghostwriters()
diff --git a/code/modules/client/preference_setup/antagonism/01_candidacy.dm b/code/modules/client/preference_setup/antagonism/01_candidacy.dm
index 1bb96e80224..8909069f3d4 100644
--- a/code/modules/client/preference_setup/antagonism/01_candidacy.dm
+++ b/code/modules/client/preference_setup/antagonism/01_candidacy.dm
@@ -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)
diff --git a/code/modules/client/preference_setup/antagonism/02_setup.dm b/code/modules/client/preference_setup/antagonism/02_setup.dm
index c84c2a6781f..59e06d2b3dc 100644
--- a/code/modules/client/preference_setup/antagonism/02_setup.dm
+++ b/code/modules/client/preference_setup/antagonism/02_setup.dm
@@ -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))
diff --git a/code/modules/client/preference_setup/general/01_basic.dm b/code/modules/client/preference_setup/general/01_basic.dm
index 4665e87d82a..651c7ad331b 100644
--- a/code/modules/client/preference_setup/general/01_basic.dm
+++ b/code/modules/client/preference_setup/general/01_basic.dm
@@ -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))
diff --git a/code/modules/client/preference_setup/general/02_language.dm b/code/modules/client/preference_setup/general/02_language.dm
index 101695cc0c4..61857ffbf48 100644
--- a/code/modules/client/preference_setup/general/02_language.dm
+++ b/code/modules/client/preference_setup/general/02_language.dm
@@ -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)
diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm
index 81868b07db6..eb68f418c98 100644
--- a/code/modules/client/preference_setup/general/03_body.dm
+++ b/code/modules/client/preference_setup/general/03_body.dm
@@ -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"
diff --git a/code/modules/client/preference_setup/general/04_equipment.dm b/code/modules/client/preference_setup/general/04_equipment.dm
index 8d53fb4c60a..a4297812471 100644
--- a/code/modules/client/preference_setup/general/04_equipment.dm
+++ b/code/modules/client/preference_setup/general/04_equipment.dm
@@ -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)
diff --git a/code/modules/client/preference_setup/general/05_background.dm b/code/modules/client/preference_setup/general/05_background.dm
index f110bb5df38..7fe7a7be13e 100644
--- a/code/modules/client/preference_setup/general/05_background.dm
+++ b/code/modules/client/preference_setup/general/05_background.dm
@@ -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"
diff --git a/code/modules/client/preference_setup/general/06_flavor.dm b/code/modules/client/preference_setup/general/06_flavor.dm
index 19873858e61..f4cbdbe1b43 100644
--- a/code/modules/client/preference_setup/general/06_flavor.dm
+++ b/code/modules/client/preference_setup/general/06_flavor.dm
@@ -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
diff --git a/code/modules/client/preference_setup/global/01_ui.dm b/code/modules/client/preference_setup/global/01_ui.dm
index d69de5b8ea8..0585039cad7 100644
--- a/code/modules/client/preference_setup/global/01_ui.dm
+++ b/code/modules/client/preference_setup/global/01_ui.dm
@@ -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))
diff --git a/code/modules/client/preference_setup/global/02_settings.dm b/code/modules/client/preference_setup/global/02_settings.dm
index 33c1b13b117..332e6bdd0a5 100644
--- a/code/modules/client/preference_setup/global/02_settings.dm
+++ b/code/modules/client/preference_setup/global/02_settings.dm
@@ -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)
. += "Play admin midis: [(pref.toggles & SOUND_MIDI) ? "Yes" : "No"]
"
diff --git a/code/modules/client/preference_setup/global/03_language.dm b/code/modules/client/preference_setup/global/03_language.dm
index 740806cef7d..c5f8a7d1164 100644
--- a/code/modules/client/preference_setup/global/03_language.dm
+++ b/code/modules/client/preference_setup/global/03_language.dm
@@ -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)
diff --git a/code/modules/client/preference_setup/occupation/occupation.dm b/code/modules/client/preference_setup/occupation/occupation.dm
index 08d771c98d1..0a9fa071a61 100644
--- a/code/modules/client/preference_setup/occupation/occupation.dm
+++ b/code/modules/client/preference_setup/occupation/occupation.dm
@@ -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)
diff --git a/code/modules/client/preference_setup/preference_setup.dm b/code/modules/client/preference_setup/preference_setup.dm
index da59832595d..6d80bb3f315 100644
--- a/code/modules/client/preference_setup/preference_setup.dm
+++ b/code/modules/client/preference_setup/preference_setup.dm
@@ -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
diff --git a/code/modules/client/preference_setup/preferences_sql.dm b/code/modules/client/preference_setup/preferences_sql.dm
new file mode 100644
index 00000000000..369dbcbac21
--- /dev/null
+++ b/code/modules/client/preference_setup/preferences_sql.dm
@@ -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
diff --git a/code/modules/client/preference_setup/skills/skills.dm b/code/modules/client/preference_setup/skills/skills.dm
index 8960673f0e8..1cb25641828 100644
--- a/code/modules/client/preference_setup/skills/skills.dm
+++ b/code/modules/client/preference_setup/skills/skills.dm
@@ -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()
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 6ea1f057db3..22467520d60 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -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 = "