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.

<details><summary>Working as intended</summary>

<img width="1109" height="1054" alt="dreamseeker_2zhIL6owdE"
src="https://github.com/user-attachments/assets/bfb9f7b9-5963-47b9-b726-cc9185e531a8"
/>

</details>

## Changelog

🆑
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
/🆑
This commit is contained in:
Bloop
2026-07-13 16:49:12 -06:00
committed by GitHub
parent a3860f3f6c
commit ddbc1702a5
2 changed files with 16 additions and 9 deletions
+8 -3
View File
@@ -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)
. = ..()
+8 -6
View File
@@ -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())