From ddbc1702a52b02dc803d0d3e1615726bfa8d7ad8 Mon Sep 17 00:00:00 2001 From: Bloop <13398309+vinylspiders@users.noreply.github.com> Date: Mon, 13 Jul 2026 18:49:12 -0400 Subject: [PATCH] Fixes f5 bluescreen with character prefs menu (#96947) ## About The Pull Request It was caused by `tainted_character_profiles` not being reset upon `send_full_update()`. To get around this issue, since `ui_data()` has no way of knowing whether it's a full update or not we will just keep the list of profiles in memory in the event that tgui gets its copy cleared. No other functional difference, everything still works the same. It's just a little more reliable now.
Working as intended dreamseeker_2zhIL6owdE
## Changelog :cl: fix: fixes an issue that would cause the character preferences menu to bluescreen if you press f5 to reload or used the Refresh-Tgui verb while it was open fix: fixes an issue that was preventing a selected new slot from updating properly /:cl: --- code/modules/client/preferences.dm | 11 ++++++++--- code/modules/client/preferences_savefile.dm | 14 ++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 311381ebdcf..57f656f5922 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -93,8 +93,10 @@ GLOBAL_LIST_EMPTY(preferences_datums) /// Used to avoid expensive READ_FILE every time a preference is retrieved. var/value_cache = list() - /// If set to TRUE, will update character_profiles on the next ui_data tick. + /// If set to TRUE, will update cached_character_profiles on the next ui_data tick. var/tainted_character_profiles = FALSE + /// The character profiles, saved so we can cheaply recompute them in ui_data only when necessary, without having to use expensive update_static_data calls. + var/list/cached_character_profiles /datum/preferences/Destroy(force) QDEL_NULL(character_preview_view) @@ -172,10 +174,12 @@ GLOBAL_LIST_EMPTY(preferences_datums) /datum/preferences/ui_data(mob/user) var/list/data = list() - if (tainted_character_profiles) - data["character_profiles"] = create_character_profiles() + if (tainted_character_profiles || isnull(cached_character_profiles)) + cached_character_profiles = create_character_profiles() tainted_character_profiles = FALSE + data["character_profiles"] = cached_character_profiles + data["character_preferences"] = compile_character_preferences(user) data["active_slot"] = default_slot @@ -289,6 +293,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) save_character() save_preferences() QDEL_NULL(character_preview_view) + cached_character_profiles = null /datum/preferences/Topic(href, list/href_list) . = ..() diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 2d48f29ce0a..8ed8fd46bb3 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -340,11 +340,15 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car /datum/preferences/proc/load_character(slot = default_slot) SHOULD_NOT_SLEEP(TRUE) slot = sanitize_integer(slot, 1, max_save_slots, initial(default_slot)) + var/original_default_slot = default_slot + if(slot != default_slot) + default_slot = slot + savefile.set_entry("default_slot", slot) var/tree_key = "character[slot]" var/list/save_data = savefile.get_entry(tree_key) - if(isnull(save_data)) - for (var/datum/preference/preference as anything in get_preferences_in_priority_order()) + if(isnull(save_data)) // This is the case where we have a new character slot being switched to + for (var/datum/preference/preference as anything in get_preferences_in_priority_order()) // clear the cache in this case if (preference.savefile_identifier != PREFERENCE_CHARACTER) continue value_cache -= preference.type @@ -352,12 +356,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car var/data_validity_integer = check_savedata_version(save_data) if(IS_DATA_OBSOLETE(data_validity_integer)) //fatal, can't load any data + default_slot = original_default_slot + savefile.set_entry("default_slot", original_default_slot) return FALSE - if(slot != default_slot) - default_slot = slot - savefile.set_entry("default_slot", slot) - // Read everything into cache // Uses priority order as some values may rely on others for creating default values for (var/datum/preference/preference as anything in get_preferences_in_priority_order())