diff --git a/Content.Client/ClientPreferencesManager.cs b/Content.Client/ClientPreferencesManager.cs index 4c87277c36..9dd2ce7fd0 100644 --- a/Content.Client/ClientPreferencesManager.cs +++ b/Content.Client/ClientPreferencesManager.cs @@ -47,6 +47,7 @@ namespace Content.Client public void UpdateCharacter(ICharacterProfile profile, int slot) { + profile.EnsureValid(); var characters = new Dictionary(Preferences.Characters) {[slot] = profile}; Preferences = new PlayerPreferences(characters, Preferences.SelectedCharacterIndex, Preferences.AdminOOCColor); var msg = _netManager.CreateNetMessage(); diff --git a/Content.Client/UserInterface/CharacterSetupGui.cs b/Content.Client/UserInterface/CharacterSetupGui.cs index f7eebf0044..3b04b74440 100644 --- a/Content.Client/UserInterface/CharacterSetupGui.cs +++ b/Content.Client/UserInterface/CharacterSetupGui.cs @@ -136,7 +136,7 @@ namespace Content.Client.UserInterface MinSize = (2, 0) }); _humanoidProfileEditor = new HumanoidProfileEditor(preferencesManager, prototypeManager, entityManager); - _humanoidProfileEditor.OnProfileChanged += newProfile => { UpdateUI(); }; + _humanoidProfileEditor.OnProfileChanged += ProfileChanged; hBox.AddChild(_humanoidProfileEditor); UpdateUI(); @@ -155,6 +155,12 @@ namespace Content.Client.UserInterface public void Save() => _humanoidProfileEditor.Save(); + private void ProfileChanged(ICharacterProfile profile, int profileSlot) + { + _humanoidProfileEditor.UpdateControls(); + UpdateUI(); + } + private void UpdateUI() { var numberOfFullSlots = 0; diff --git a/Content.Client/UserInterface/HumanoidProfileEditor.cs b/Content.Client/UserInterface/HumanoidProfileEditor.cs index 1839004116..954262b103 100644 --- a/Content.Client/UserInterface/HumanoidProfileEditor.cs +++ b/Content.Client/UserInterface/HumanoidProfileEditor.cs @@ -62,7 +62,7 @@ namespace Content.Client.UserInterface private bool _isDirty; public int CharacterSlot; public HumanoidCharacterProfile Profile; - public event Action OnProfileChanged; + public event Action OnProfileChanged; public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IPrototypeManager prototypeManager, IEntityManager entityManager) @@ -709,7 +709,7 @@ namespace Content.Client.UserInterface { IsDirty = false; _preferencesManager.UpdateCharacter(Profile, CharacterSlot); - OnProfileChanged?.Invoke(Profile); + OnProfileChanged?.Invoke(Profile, CharacterSlot); } private bool IsDirty diff --git a/Content.Server/Preferences/ServerPreferencesManager.cs b/Content.Server/Preferences/ServerPreferencesManager.cs index fc3592bacb..23f791d17e 100644 --- a/Content.Server/Preferences/ServerPreferencesManager.cs +++ b/Content.Server/Preferences/ServerPreferencesManager.cs @@ -48,7 +48,6 @@ namespace Content.Server.Preferences HandleDeleteCharacterMessage); } - private async void HandleSelectCharacterMessage(MsgSelectCharacter message) { var index = message.SelectedCharacterIndex; @@ -107,9 +106,11 @@ namespace Content.Server.Preferences var curPrefs = prefsData.Prefs!; + profile.EnsureValid(); + var profiles = new Dictionary(curPrefs.Characters) { - [slot] = HumanoidCharacterProfile.EnsureValid((HumanoidCharacterProfile) profile, _protos) + [slot] = profile }; prefsData.Prefs = new PlayerPreferences(profiles, slot, curPrefs.AdminOOCColor); diff --git a/Content.Shared/Preferences/HumanoidCharacterProfile.cs b/Content.Shared/Preferences/HumanoidCharacterProfile.cs index 5dcc2c77b6..1ef4488ce4 100644 --- a/Content.Shared/Preferences/HumanoidCharacterProfile.cs +++ b/Content.Shared/Preferences/HumanoidCharacterProfile.cs @@ -201,96 +201,12 @@ namespace Content.Shared.Preferences return new(this, _jobPriorities, list); } - /// - /// Makes this profile valid so there's no bad data like negative ages. - /// - public static HumanoidCharacterProfile EnsureValid( - HumanoidCharacterProfile profile, - IPrototypeManager prototypeManager) - { - var age = Math.Clamp(profile.Age, MinimumAge, MaximumAge); - var sex = profile.Sex switch - { - Sex.Male => Sex.Male, - Sex.Female => Sex.Female, - _ => Sex.Male // Invalid enum values. - }; - var gender = profile.Gender switch - { - Gender.Epicene => Gender.Epicene, - Gender.Female => Gender.Female, - Gender.Male => Gender.Male, - Gender.Neuter => Gender.Neuter, - _ => Gender.Epicene // Invalid enum values. - }; - - string name; - if (string.IsNullOrEmpty(profile.Name)) - { - name = "Urist McHands"; - } - else if (profile.Name.Length > MaxNameLength) - { - name = profile.Name[..MaxNameLength]; - } - else - { - name = profile.Name; - } - - // TODO: Avoid Z̨͇̙͉͎̭͔̼̿͋A͚̖̞̗̞͈̓̾̀ͩͩ̔L̟ͮ̈͝G̙O͍͎̗̺̺ͫ̀̽͊̓͝ͅ tier shenanigans. - // And other stuff like RTL overrides and such. - // Probably also emojis... - - name = name.Trim(); - - var appearance = HumanoidCharacterAppearance.EnsureValid(profile.Appearance); - - var prefsUnavailableMode = profile.PreferenceUnavailable switch - { - PreferenceUnavailableMode.StayInLobby => PreferenceUnavailableMode.StayInLobby, - PreferenceUnavailableMode.SpawnAsOverflow => PreferenceUnavailableMode.SpawnAsOverflow, - _ => PreferenceUnavailableMode.StayInLobby // Invalid enum values. - }; - - var clothing = profile.Clothing switch - { - ClothingPreference.Jumpsuit => ClothingPreference.Jumpsuit, - ClothingPreference.Jumpskirt => ClothingPreference.Jumpskirt, - _ => ClothingPreference.Jumpsuit // Invalid enum values. - }; - - var backpack = profile.Backpack switch - { - BackpackPreference.Backpack => BackpackPreference.Backpack, - BackpackPreference.Satchel => BackpackPreference.Satchel, - BackpackPreference.Duffelbag => BackpackPreference.Duffelbag, - _ => BackpackPreference.Backpack // Invalid enum values. - }; - - var priorities = new Dictionary(profile.JobPriorities - .Where(p => prototypeManager.HasIndex(p.Key) && p.Value switch - { - JobPriority.Never => false, // Drop never since that's assumed default. - JobPriority.Low => true, - JobPriority.Medium => true, - JobPriority.High => true, - _ => false - })); - - var antags = profile.AntagPreferences - .Where(prototypeManager.HasIndex) - .ToList(); - - return new HumanoidCharacterProfile(name, age, sex, gender, appearance, clothing, backpack, priorities, prefsUnavailableMode, antags); - } - public string Summary => - Loc.GetString( - "humanoid-character-profile-summary", - ("name", Name), - ("gender", Gender.ToString().ToLowerInvariant()), - ("age", Age) + Loc.GetString( + "humanoid-character-profile-summary", + ("name", Name), + ("gender", Gender.ToString().ToLowerInvariant()), + ("age", Age) ); public bool MemberwiseEquals(ICharacterProfile maybeOther) @@ -308,6 +224,107 @@ namespace Content.Shared.Preferences return Appearance.MemberwiseEquals(other.Appearance); } + public void EnsureValid() + { + var age = Math.Clamp(Age, MinimumAge, MaximumAge); + + var sex = Sex switch + { + Sex.Male => Sex.Male, + Sex.Female => Sex.Female, + _ => Sex.Male // Invalid enum values. + }; + + var gender = Gender switch + { + Gender.Epicene => Gender.Epicene, + Gender.Female => Gender.Female, + Gender.Male => Gender.Male, + Gender.Neuter => Gender.Neuter, + _ => Gender.Epicene // Invalid enum values. + }; + + string name; + if (string.IsNullOrEmpty(Name)) + { + name = "Urist McHands"; + } + else if (Name.Length > MaxNameLength) + { + name = Name[..MaxNameLength]; + } + else + { + name = Name; + } + + // TODO: Avoid Z̨͇̙͉͎̭͔̼̿͋A͚̖̞̗̞͈̓̾̀ͩͩ̔L̟ͮ̈͝G̙O͍͎̗̺̺ͫ̀̽͊̓͝ͅ tier shenanigans. + // And other stuff like RTL overrides and such. + // Probably also emojis... + + name = name.Trim(); + + var appearance = HumanoidCharacterAppearance.EnsureValid(Appearance); + + var prefsUnavailableMode = PreferenceUnavailable switch + { + PreferenceUnavailableMode.StayInLobby => PreferenceUnavailableMode.StayInLobby, + PreferenceUnavailableMode.SpawnAsOverflow => PreferenceUnavailableMode.SpawnAsOverflow, + _ => PreferenceUnavailableMode.StayInLobby // Invalid enum values. + }; + + var clothing = Clothing switch + { + ClothingPreference.Jumpsuit => ClothingPreference.Jumpsuit, + ClothingPreference.Jumpskirt => ClothingPreference.Jumpskirt, + _ => ClothingPreference.Jumpsuit // Invalid enum values. + }; + + var backpack = Backpack switch + { + BackpackPreference.Backpack => BackpackPreference.Backpack, + BackpackPreference.Satchel => BackpackPreference.Satchel, + BackpackPreference.Duffelbag => BackpackPreference.Duffelbag, + _ => BackpackPreference.Backpack // Invalid enum values. + }; + + var prototypeManager = IoCManager.Resolve(); + + var priorities = new Dictionary(JobPriorities + .Where(p => prototypeManager.HasIndex(p.Key) && p.Value switch + { + JobPriority.Never => false, // Drop never since that's assumed default. + JobPriority.Low => true, + JobPriority.Medium => true, + JobPriority.High => true, + _ => false + })); + + var antags = AntagPreferences + .Where(prototypeManager.HasIndex) + .ToList(); + + Name = name; + Age = age; + Sex = sex; + Gender = gender; + Appearance = appearance; + Clothing = clothing; + Backpack = backpack; + + _jobPriorities.Clear(); + + foreach (var (job, priority) in priorities) + { + _jobPriorities.Add(job, priority); + } + + PreferenceUnavailable = prefsUnavailableMode; + + _antagPreferences.Clear(); + _antagPreferences.AddRange(antags); + } + public override bool Equals(object? obj) { return obj is HumanoidCharacterProfile other && MemberwiseEquals(other); @@ -328,7 +345,7 @@ namespace Content.Shared.Preferences PreferenceUnavailable, _jobPriorities, _antagPreferences - ); + ); } } } diff --git a/Content.Shared/Preferences/ICharacterProfile.cs b/Content.Shared/Preferences/ICharacterProfile.cs index eab98e941b..222d69af14 100644 --- a/Content.Shared/Preferences/ICharacterProfile.cs +++ b/Content.Shared/Preferences/ICharacterProfile.cs @@ -5,7 +5,14 @@ namespace Content.Shared.Preferences public interface ICharacterProfile { string Name { get; } + ICharacterAppearance CharacterAppearance { get; } + bool MemberwiseEquals(ICharacterProfile other); + + /// + /// Makes this profile valid so there's no bad data like negative ages. + /// + void EnsureValid(); } }