[MIRROR] Fix multiple pref issues (#11373)

Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
Co-authored-by: C.L. <killer65311@gmail.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-08-10 07:24:35 -07:00
committed by GitHub
parent b7c79d4a6a
commit ae778b99ee
15 changed files with 106 additions and 53 deletions

View File

@@ -62,3 +62,7 @@
#define EMOTE_SOUND_NO_FREQ "Default"
#define EMOTE_SOUND_VOICE_FREQ "Voice Frequency"
#define EMOTE_SOUND_VOICE_LIST "Voice Sound"
#define WRITE_PREF_NORMAL 1
#define WRITE_PREF_INSTANT 2
#define WRITE_PREF_MANUAL 3

View File

@@ -1651,3 +1651,5 @@ GLOBAL_LIST(chamelion_mask_choices)
GLOBAL_LIST(chamelion_belt_choices)
//Accessory
GLOBAL_LIST(chamelion_accessory_choices)
GLOBAL_LIST_INIT(tail_layer_options, list("Lower layer" = TAIL_UPPER_LAYER_LOW , "Default layer" = TAIL_UPPER_LAYER , "Upper layer" = TAIL_UPPER_LAYER_HIGH ))

View File

@@ -13,12 +13,15 @@ SUBSYSTEM_DEF(asset_loading)
while(length(generate_queue))
var/datum/asset/to_load = generate_queue[generate_queue.len]
last_queue_len = length(generate_queue)
generate_queue.len--
to_load.queued_generation()
if(MC_TICK_CHECK)
return
last_queue_len = length(generate_queue)
generate_queue.len--
// We just emptied the queue
if(last_queue_len && !length(generate_queue))
// Clean up cached icons, freeing memory.

View File

@@ -38,4 +38,6 @@ SUBSYSTEM_DEF(character_setup)
return
/datum/controller/subsystem/character_setup/proc/queue_preferences_save(var/datum/preferences/prefs)
if(!prefs)
return
save_queue |= prefs

View File

@@ -49,7 +49,7 @@
* Arguments:
* * datum/P the parent datum this component reacts to signals from
*/
/datum/component/New(list/raw_args)
/datum/component/New(list/raw_args, manual)
parent = raw_args[1]
var/list/arguments = raw_args.Copy(2)
if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE)
@@ -58,6 +58,8 @@
return
_JoinParent(parent)
if(manual)
lateload_pref_data()
/**
* Called during component creation with the same arguments as in new excluding parent.
@@ -310,7 +312,7 @@
*
* Properly handles duplicate situations based on the `dupe_mode` var
*/
/datum/proc/_AddComponent(list/raw_args, source)
/datum/proc/_AddComponent(list/raw_args, source, manual)
var/original_type = raw_args[1]
var/datum/component/component_type = original_type
@@ -349,14 +351,14 @@
switch(dupe_mode)
if(COMPONENT_DUPE_UNIQUE)
if(!new_component)
new_component = new component_type(raw_args)
new_component = new component_type(raw_args, manual)
if(!QDELETED(new_component))
old_component.InheritComponent(new_component, TRUE)
QDEL_NULL(new_component)
if(COMPONENT_DUPE_HIGHLANDER)
if(!new_component)
new_component = new component_type(raw_args)
new_component = new component_type(raw_args, manual)
if(!QDELETED(new_component))
new_component.InheritComponent(old_component, FALSE)
QDEL_NULL(old_component)
@@ -378,7 +380,7 @@
return null
else if(!new_component)
new_component = new component_type(raw_args) // There's a valid dupe mode but there's no old component, act like normal
new_component = new component_type(raw_args, manual) // There's a valid dupe mode but there's no old component, act like normal
else if(dupe_mode == COMPONENT_DUPE_SELECTIVE)
var/list/arguments = raw_args.Copy()
@@ -390,19 +392,19 @@
QDEL_NULL(new_component)
break
if(!new_component && make_new_component)
new_component = new component_type(raw_args)
new_component = new component_type(raw_args, manual)
else if(dupe_mode == COMPONENT_DUPE_SOURCES)
new_component = new component_type(raw_args)
new_component = new component_type(raw_args, manual)
if(new_component.on_source_add(arglist(list(source) + raw_args.Copy(2))) == COMPONENT_INCOMPATIBLE)
stack_trace("incompatible source added to a [new_component.type]. Args: [json_encode(raw_args)]")
return null
else if(!new_component)
new_component = new component_type(raw_args) // Dupes are allowed, act like normal
new_component = new component_type(raw_args, manual) // Dupes are allowed, act like normal
if(!old_component && !QDELETED(new_component)) // Nothing related to duplicate components happened and the new component is healthy
SEND_SIGNAL(src, COMSIG_COMPONENT_ADDED, new_component)
SEND_SIGNAL(src, COMSIG_COMPONENT_ADDED, new_component, manual)
return new_component
return old_component
@@ -424,12 +426,13 @@
*
* Arguments:
* * component_type The typepath of the component to create or return
* * manual_load If we are manually adding this (post-spawn) or not.
* * ... additional arguments to be passed when creating the component if it does not exist
*/
/datum/proc/_LoadComponent(list/arguments)
/datum/proc/_LoadComponent(list/arguments, manual_load)
. = GetComponent(arguments[1])
if(!.)
return _AddComponent(arguments)
return _AddComponent(arguments, manual = manual_load)
/**
* Removes the component from parent, ends up with a null parent
* Used as a helper proc by the component transfer proc, does not clean up the component like Destroy does
@@ -495,3 +498,9 @@
*/
/datum/component/tgui_host()
return parent
/**
* Loads lateload data for the component. Things such as preferences, which aren't applied if not done at character-spawn. Must be defined per-component.
*/
/datum/component/proc/lateload_pref_data()
return

View File

@@ -155,7 +155,7 @@ var/list/datum/power/changeling/powerinstances = list()
if(!mind)
return
//The current mob is made a changeling AND the mind is made a changeling.
var/datum/component/antag/changeling/comp = LoadComponent(/datum/component/antag/changeling)
var/datum/component/antag/changeling/comp = LoadComponent(/datum/component/antag/changeling, TRUE)
mind.antag_holder.changeling = comp
var/lesser_form = !ishuman(src)
@@ -423,10 +423,23 @@ var/list/datum/power/changeling/powerinstances = list()
//Debug item. Here because during debugging I DO NOT want to have to open the player panel 5000 times.
/obj/item/toy/katana/changeling_debug
/obj/item/changeling_debug
name = "Katana of the Changeling"
desc = "A katana imbued with special powers. It is said that those who wield it will become a changeling."
/obj/item/toy/katana/changeling_debug/attack_self(mob/user)
icon = 'icons/obj/weapons.dmi'
icon_state = "katana"
item_state = "katana"
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_material.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_material.dmi',
)
slot_flags = SLOT_BELT | SLOT_BACK
force = 5
throwforce = 5
w_class = ITEMSIZE_NORMAL
attack_verb = list("attacked", "slashed", "stabbed", "sliced")
/obj/item/changeling_debug/attack_self(mob/user)
user.make_changeling()
///Changeling Panel

View File

@@ -255,3 +255,13 @@
to_chat(owner, span_danger("The VR systems cannot comprehend this power! This is useless to you!"))
return TRUE
return FALSE
///Gets late-load preferences for the shadekin component. Used when the component is applied post-spawn.
/datum/component/shadekin/lateload_pref_data()
if(owner.client)
flicker_color = owner.read_preference(/datum/preference/color/living/flicker_color)
flicker_time = owner.read_preference(/datum/preference/numeric/living/flicker_time)
flicker_break_chance = owner.read_preference(/datum/preference/numeric/living/flicker_break_chance)
flicker_distance = owner.read_preference(/datum/preference/numeric/living/flicker_distance)
no_retreat = owner.read_preference(/datum/preference/toggle/living/dark_retreat_toggle)
nutrition_energy_conversion = owner.read_preference(/datum/preference/toggle/living/shadekin_nutrition_conversion)

View File

@@ -212,6 +212,9 @@
return data
/datum/component/shadekin/tgui_close(mob/user)
SScharacter_setup.queue_preferences_save(user?.client?.prefs)
. = ..()
/datum/component/shadekin/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
@@ -224,14 +227,14 @@
if(!isnum(new_time))
return FALSE
flicker_time = new_time
ui.user.write_preference_directly(/datum/preference/numeric/living/flicker_time, new_time)
ui.user.write_preference_directly(/datum/preference/numeric/living/flicker_time, new_time, WRITE_PREF_MANUAL)
return TRUE
if("adjust_color")
var/set_new_color = tgui_color_picker(ui.user, "Select a color you wish the lights to flicker as (Default is #E0EFF0)", "Color Selector", flicker_color)
if(!set_new_color)
return FALSE
flicker_color = set_new_color
ui.user.write_preference_directly(/datum/preference/color/living/flicker_color, set_new_color)
ui.user.write_preference_directly(/datum/preference/color/living/flicker_color, set_new_color, WRITE_PREF_MANUAL)
return TRUE
if("adjust_break")
var/new_break_chance = text2num(params["val"])
@@ -239,7 +242,7 @@
if(!isnum(new_break_chance))
return FALSE
flicker_break_chance = new_break_chance
ui.user.write_preference_directly(/datum/preference/numeric/living/flicker_break_chance, new_break_chance)
ui.user.write_preference_directly(/datum/preference/numeric/living/flicker_break_chance, new_break_chance, WRITE_PREF_MANUAL)
return TRUE
if("adjust_distance")
var/new_distance = text2num(params["val"])
@@ -247,16 +250,16 @@
if(!isnum(new_distance))
return FALSE
flicker_distance = new_distance
ui.user.write_preference_directly(/datum/preference/numeric/living/flicker_distance, new_distance)
ui.user.write_preference_directly(/datum/preference/numeric/living/flicker_distance, new_distance, WRITE_PREF_MANUAL)
return TRUE
if("toggle_retreat")
var/new_retreat = !no_retreat
no_retreat = !no_retreat
ui.user.write_preference_directly(/datum/preference/toggle/living/dark_retreat_toggle, new_retreat)
ui.user.write_preference_directly(/datum/preference/toggle/living/dark_retreat_toggle, new_retreat, WRITE_PREF_MANUAL)
if("toggle_nutrition")
var/new_retreat = !nutrition_energy_conversion
nutrition_energy_conversion = !nutrition_energy_conversion
ui.user.write_preference_directly(/datum/preference/toggle/living/shadekin_nutrition_conversion, new_retreat)
ui.user.write_preference_directly(/datum/preference/toggle/living/shadekin_nutrition_conversion, new_retreat, WRITE_PREF_MANUAL)
/mob/living/proc/shadekin_control_panel()
set name = "Shadekin Control Panel"

View File

@@ -18,7 +18,7 @@
/mob/living/carbon/human/proc/birthday(var/birthday = 0)
var/msg
var/lastyear = read_preference(/datum/preference/numeric/human/last_bday_note)
write_preference_directly(/datum/preference/numeric/human/last_bday_note, GLOB.world_time_year) //We only want to ask once a year per character, this persists, update early in case of shenanigans
write_preference_directly(/datum/preference/numeric/human/last_bday_note, GLOB.world_time_year, WRITE_PREF_MANUAL) //We only want to ask once a year per character, this persists, update early in case of shenanigans
if(birthday) //woo
msg = "Today is your birthday! Do you want to increase your character's listed age?"
/* //Chomp DISABLE - Absolutely not.
@@ -36,6 +36,6 @@
var/howmuch = GLOB.world_time_year - lastyear
age += howmuch
to_chat(src, span_notice("You are now [age]! Happy birthday!"))
write_preference_directly(/datum/preference/numeric/human/age, age) //Set the age on the character sheet
write_preference_directly(/datum/preference/numeric/human/age, age, WRITE_PREF_MANUAL) //Set the age on the character sheet
client?.prefs.save_character() //Save the info
SScharacter_setup.queue_preferences_save(client?.prefs)

View File

@@ -88,7 +88,7 @@
lst.Insert(1, result)
if(result in componentsubtypes)
datumname = "component"
target._AddComponent(lst, add_source)
target._AddComponent(lst, add_source, TRUE)
else
datumname = "element"
target._AddElement(lst)

View File

@@ -317,8 +317,9 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
return client?.prefs?.read_preference(preference_type)
/// Write a /datum/preference type and return its value directly to the json.
/mob/proc/write_preference_directly(preference_type, preference_value)
var/success = client?.prefs?.write_preference_by_type(preference_type, preference_value)
/// Please use SScharacter_setup.queue_preferences_save(prefs) when you edit multiple at once and set direct_write to WRITE_PREF_MANUAL
/mob/proc/write_preference_directly(preference_type, preference_value, write_mode = WRITE_PREF_INSTANT)
var/success = client?.prefs?.write_preference_by_type(preference_type, preference_value, write_mode)
if(success)
client?.prefs?.value_cache[preference_type] = preference_value
return success
@@ -336,7 +337,7 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
/// Writes a value and saves to disk immediately
/// Used by things that need to directly write to the player savefile things that aren't "really" prefs
/datum/preferences/proc/write_preference_by_type(preference_type, preference_value)
/datum/preferences/proc/write_preference_by_type(preference_type, preference_value, write_mode = WRITE_PREF_NORMAL)
var/datum/preference/preference_entry = GLOB.preference_entries[preference_type]
if(isnull(preference_entry))
CRASH("Preference type `[preference_type]` is invalid!")
@@ -344,7 +345,10 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key())
if(!write_preference(preference_entry, preference_entry.pref_serialize(preference_value)))
return
if(preference_entry.savefile_identifier == PREFERENCE_CHARACTER)
if(write_mode == WRITE_PREF_MANUAL)
return TRUE
if(preference_entry.savefile_identifier == PREFERENCE_CHARACTER && write_mode != WRITE_PREF_INSTANT)
var/save_data = get_save_data_for_savefile_identifier(preference_entry.savefile_identifier)
player_setup.save_character(save_data)
else

View File

@@ -213,16 +213,17 @@
return 255 //no randomization here.
///Tail style.
/datum/preference/numeric/human/tail_layering
/datum/preference/choiced/human/tail_layering
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
savefile_identifier = PREFERENCE_CHARACTER
savefile_key = "tail_layering"
can_randomize = FALSE
minimum = TAIL_UPPER_LAYER
maximum = TAIL_UPPER_LAYER_HIGH
/datum/preference/numeric/human/tail_layering/create_default_value()
return TAIL_UPPER_LAYER
/datum/preference/choiced/human/tail_layering/init_possible_values()
return assoc_to_keys(GLOB.tail_layer_options)
/datum/preference/numeric/human/tail_layering/apply_to_human(mob/living/carbon/human/target, value)
target.tail_layering = value
/datum/preference/choiced/human/tail_layering/create_default_value()
return GLOB.tail_layer_options[2]
/datum/preference/choiced/human/tail_layering/apply_to_human(mob/living/carbon/human/target, value)
target.tail_layering = GLOB.tail_layer_options[value]

View File

@@ -136,6 +136,9 @@
switch(action)
// Basic actions
if("load")
if(!isnewplayer(ui.user))
to_chat(ui.user, span_userdanger("You can't change your character slot while being in round."))
return FALSE
if(!IsGuestKey(ui.user.key))
open_load_dialog(ui.user)
. = TRUE
@@ -152,6 +155,8 @@
sanitize_preferences()
. = TRUE
if("resetslot")
if(!isnewplayer(ui.user))
to_chat(ui.user, span_userdanger("You can't change your character slot while being in round."))
if("Yes" != tgui_alert(ui.user, "This will reset the current slot. Continue?", "Reset current slot?", list("No", "Yes")))
return
if("Yes" != tgui_alert(ui.user, "Are you completely sure that you want to reset this character slot?", "Reset current slot?", list("No", "Yes")))
@@ -160,6 +165,8 @@
sanitize_preferences()
. = TRUE
if("copy")
if(!isnewplayer(ui.user))
to_chat(ui.user, span_userdanger("You can't change your character slot while being in round."))
if(!IsGuestKey(ui.user.key))
open_copy_dialog(ui.user)
. = TRUE
@@ -192,7 +199,7 @@
PMH.screen_loc = LAZYACCESS(preview_screen_locs, "PMH")
/datum/preferences/tgui_close(mob/user)
// save_character()
load_character()
save_preferences()
/datum/preferences/proc/create_character_profiles()

View File

@@ -30,9 +30,9 @@
usr.update_ui_style(UI_style_new, UI_style_alpha_new, UI_style_color_new)
if(tgui_alert(src, "Like it? Save changes?","Save?",list("Yes", "No")) == "Yes")
usr.write_preference_directly(/datum/preference/choiced/ui_style, UI_style_new)
usr.write_preference_directly(/datum/preference/numeric/ui_style_alpha, UI_style_alpha_new)
usr.write_preference_directly(/datum/preference/color/ui_style_color, UI_style_color_new)
usr.write_preference_directly(/datum/preference/choiced/ui_style, UI_style_new, WRITE_PREF_MANUAL)
usr.write_preference_directly(/datum/preference/numeric/ui_style_alpha, UI_style_alpha_new, WRITE_PREF_MANUAL)
usr.write_preference_directly(/datum/preference/color/ui_style_color, UI_style_color_new, WRITE_PREF_MANUAL)
SScharacter_setup.queue_preferences_save(prefs)
to_chat(src, "UI was saved")
return

View File

@@ -69,19 +69,14 @@
set category = "IC.Game"
set desc = "Switch tail layer to show below/above/between clothing or other things such as wings!."
var/input = tgui_input_list(src, "Select a tail layer.", "Set Tail Layer", list(SWITCH_TAIL_LAYER_UPPER, SWITCH_TAIL_LAYER_STANDARD, SWITCH_TAIL_LAYER_LOWER))
if(isnull(input))
var/input = tgui_input_list(src, "Select a tail layer.", "Set Tail Layer", GLOB.tail_layer_options, read_preference(/datum/preference/choiced/human/tail_layering))
if(!input)
return
switch(input)
if(SWITCH_TAIL_LAYER_UPPER)
tail_layering = input
write_preference_directly(/datum/preference/numeric/human/tail_layering, TAIL_UPPER_LAYER_HIGH)
if(SWITCH_TAIL_LAYER_STANDARD)
tail_layering = input
write_preference_directly(/datum/preference/numeric/human/tail_layering, TAIL_UPPER_LAYER)
if(SWITCH_TAIL_LAYER_LOWER)
tail_layering = input
write_preference_directly(/datum/preference/numeric/human/tail_layering, TAIL_UPPER_LAYER_LOW)
var/tail_option = GLOB.tail_layer_options[input]
if(!tail_option)
return
tail_layering = tail_option
write_preference_directly(/datum/preference/choiced/human/tail_layering, input)
update_tail_showing()