diff --git a/Content.Client/Lobby/ClientPreferencesManager.cs b/Content.Client/Lobby/ClientPreferencesManager.cs index 63a12a99bf2..daa522ab611 100644 --- a/Content.Client/Lobby/ClientPreferencesManager.cs +++ b/Content.Client/Lobby/ClientPreferencesManager.cs @@ -44,7 +44,7 @@ namespace Content.Client.Lobby } } - public void SelectCharacter(ICharacterProfile profile) + public void SelectCharacter(HumanoidCharacterProfile profile) { SelectCharacter(Preferences.IndexOfCharacter(profile)); } @@ -59,11 +59,11 @@ namespace Content.Client.Lobby _netManager.ClientSendMessage(msg); } - public void UpdateCharacter(ICharacterProfile profile, int slot) + public void UpdateCharacter(HumanoidCharacterProfile profile, int slot) { var collection = IoCManager.Instance!; profile.EnsureValid(_playerManager.LocalSession!, collection); - var characters = new Dictionary(Preferences.Characters) {[slot] = profile}; + var characters = new Dictionary(Preferences.Characters) {[slot] = profile}; Preferences = new PlayerPreferences(characters, Preferences.SelectedCharacterIndex, Preferences.AdminOOCColor, Preferences.ConstructionFavorites); var msg = new MsgUpdateCharacter { @@ -73,9 +73,9 @@ namespace Content.Client.Lobby _netManager.ClientSendMessage(msg); } - public void CreateCharacter(ICharacterProfile profile) + public void CreateCharacter(HumanoidCharacterProfile profile) { - var characters = new Dictionary(Preferences.Characters); + var characters = new Dictionary(Preferences.Characters); var lowest = Enumerable.Range(0, Settings.MaxCharacterSlots) .Except(characters.Keys) .FirstOrNull(); @@ -92,7 +92,7 @@ namespace Content.Client.Lobby UpdateCharacter(profile, l); } - public void DeleteCharacter(ICharacterProfile profile) + public void DeleteCharacter(HumanoidCharacterProfile profile) { DeleteCharacter(Preferences.IndexOfCharacter(profile)); } diff --git a/Content.Client/Lobby/IClientPreferencesManager.cs b/Content.Client/Lobby/IClientPreferencesManager.cs index c9b58d632cf..30b518cf519 100644 --- a/Content.Client/Lobby/IClientPreferencesManager.cs +++ b/Content.Client/Lobby/IClientPreferencesManager.cs @@ -13,11 +13,11 @@ namespace Content.Client.Lobby GameSettings? Settings { get; } PlayerPreferences? Preferences { get; } void Initialize(); - void SelectCharacter(ICharacterProfile profile); + void SelectCharacter(HumanoidCharacterProfile profile); void SelectCharacter(int slot); - void UpdateCharacter(ICharacterProfile profile, int slot); - void CreateCharacter(ICharacterProfile profile); - void DeleteCharacter(ICharacterProfile profile); + void UpdateCharacter(HumanoidCharacterProfile profile, int slot); + void CreateCharacter(HumanoidCharacterProfile profile); + void DeleteCharacter(HumanoidCharacterProfile profile); void DeleteCharacter(int slot); void UpdateConstructionFavorites(List> favorites); } diff --git a/Content.Client/Lobby/UI/CharacterPickerButton.xaml.cs b/Content.Client/Lobby/UI/CharacterPickerButton.xaml.cs index cf05c4b4482..432b8e76754 100644 --- a/Content.Client/Lobby/UI/CharacterPickerButton.xaml.cs +++ b/Content.Client/Lobby/UI/CharacterPickerButton.xaml.cs @@ -30,7 +30,7 @@ public sealed partial class CharacterPickerButton : ContainerButton IPrototypeManager prototypeManager, ISharedPlayerManager playerMan, ButtonGroup group, - ICharacterProfile profile, + HumanoidCharacterProfile profile, bool isSelected) { RobustXamlLoader.Load(this); @@ -41,15 +41,11 @@ public sealed partial class CharacterPickerButton : ContainerButton View.LoadPreview(profile); - if (profile is HumanoidCharacterProfile humanoid) + var highPriorityJob = profile.JobPriorities.SingleOrDefault(p => p.Value == JobPriority.High).Key; + if (highPriorityJob != default) { - - var highPriorityJob = humanoid.JobPriorities.SingleOrDefault(p => p.Value == JobPriority.High).Key; - if (highPriorityJob != default) - { - var jobName = prototypeManager.Index(highPriorityJob).LocalizedName; - description = $"{description}\n{jobName}"; - } + var jobName = prototypeManager.Index(highPriorityJob).LocalizedName; + description = $"{description}\n{jobName}"; } Pressed = isSelected; diff --git a/Content.Client/Lobby/UI/ProfileEditorControls/ProfilePreviewSpriteView.cs b/Content.Client/Lobby/UI/ProfileEditorControls/ProfilePreviewSpriteView.cs index 7f834ecf3a3..7f3a12a7cc1 100644 --- a/Content.Client/Lobby/UI/ProfileEditorControls/ProfilePreviewSpriteView.cs +++ b/Content.Client/Lobby/UI/ProfileEditorControls/ProfilePreviewSpriteView.cs @@ -27,19 +27,12 @@ public sealed partial class ProfilePreviewSpriteView : SpriteView /// /// This is expensive so not recommended to run if you have a slider. /// - public void LoadPreview(ICharacterProfile profile, JobPrototype? jobOverride = null, bool showClothes = true) + public void LoadPreview(HumanoidCharacterProfile profile, JobPrototype? jobOverride = null, bool showClothes = true) { EntMan.DeleteEntity(PreviewDummy); PreviewDummy = EntityUid.Invalid; - switch (profile) - { - case HumanoidCharacterProfile humanoid: - LoadHumanoidEntity(humanoid, jobOverride, showClothes); - break; - default: - throw new ArgumentException("Only humanoid profiles are implemented in ProfilePreviewSpriteView"); - } + LoadHumanoidEntity(profile, jobOverride, showClothes); SetEntity(PreviewDummy); SetName(profile.Name); @@ -56,16 +49,9 @@ public sealed partial class ProfilePreviewSpriteView : SpriteView /// /// A slim reload that only updates the entity itself and not any of the job entities, etc. /// - public void ReloadProfilePreview(ICharacterProfile profile) + public void ReloadProfilePreview(HumanoidCharacterProfile profile) { - switch (profile) - { - case HumanoidCharacterProfile humanoid: - ReloadHumanoidEntity(humanoid); - break; - default: - throw new ArgumentException("Only humanoid profiles are implemented in ProfilePreviewSpriteView"); - } + ReloadHumanoidEntity(profile); } public void ClearPreview() diff --git a/Content.IntegrationTests/Tests/Lobby/CharacterCreationTest.cs b/Content.IntegrationTests/Tests/Lobby/CharacterCreationTest.cs index a940df82d24..2fa3c9961c4 100644 --- a/Content.IntegrationTests/Tests/Lobby/CharacterCreationTest.cs +++ b/Content.IntegrationTests/Tests/Lobby/CharacterCreationTest.cs @@ -75,17 +75,11 @@ public sealed class CharacterCreationTest await pair.CleanReturnAsync(); } - private void AssertEqual(ICharacterProfile clientCharacter, HumanoidCharacterProfile b) + private void AssertEqual(HumanoidCharacterProfile a, HumanoidCharacterProfile b) { - if (clientCharacter.MemberwiseEquals(b)) + if (a.MemberwiseEquals(b)) return; - if (clientCharacter is not HumanoidCharacterProfile a) - { - Assert.Fail($"Not a {nameof(HumanoidCharacterProfile)}"); - return; - } - Assert.Multiple(() => { Assert.That(a.Name, Is.EqualTo(b.Name)); @@ -107,7 +101,7 @@ public sealed class CharacterCreationTest private void AssertEqual(HumanoidCharacterAppearance a, HumanoidCharacterAppearance b) { - if (a.MemberwiseEquals(b)) + if (a.Equals(b)) return; Assert.That(a.EyeColor, Is.EqualTo(b.EyeColor)); diff --git a/Content.Server/Database/ServerDbBase.cs b/Content.Server/Database/ServerDbBase.cs index ec463012354..eee17bdef87 100644 --- a/Content.Server/Database/ServerDbBase.cs +++ b/Content.Server/Database/ServerDbBase.cs @@ -66,7 +66,7 @@ namespace Content.Server.Database return null; var maxSlot = prefs.Profiles.Max(p => p.Slot) + 1; - var profiles = new Dictionary(maxSlot); + var profiles = new Dictionary(maxSlot); foreach (var profile in prefs.Profiles) { profiles[profile.Slot] = await ConvertProfiles(profile); @@ -88,23 +88,17 @@ namespace Content.Server.Database await db.DbContext.SaveChangesAsync(); } - public async Task SaveCharacterSlotAsync(NetUserId userId, ICharacterProfile? profile, int slot) + public async Task SaveCharacterSlotAsync(NetUserId userId, HumanoidCharacterProfile? humanoid, int slot) { await using var db = await GetDb(); - if (profile is null) + if (humanoid is null) { await DeleteCharacterSlot(db.DbContext, userId, slot); await db.DbContext.SaveChangesAsync(); return; } - if (profile is not HumanoidCharacterProfile humanoid) - { - // TODO: Handle other ICharacterProfile implementations properly - throw new NotImplementedException(); - } - var oldProfile = db.DbContext.Profile .Include(p => p.Preference) .Where(p => p.Preference.UserId == userId.UserId) @@ -145,7 +139,7 @@ namespace Content.Server.Database db.Profile.Remove(profile); } - public async Task InitPrefsAsync(NetUserId userId, ICharacterProfile defaultProfile) + public async Task InitPrefsAsync(NetUserId userId, HumanoidCharacterProfile defaultProfile) { await using var db = await GetDb(); @@ -164,7 +158,7 @@ namespace Content.Server.Database await db.DbContext.SaveChangesAsync(); - return new PlayerPreferences(new[] { new KeyValuePair(0, defaultProfile) }, 0, Color.FromHex(prefs.AdminOOCColor), []); + return new PlayerPreferences(new[] { new KeyValuePair(0, defaultProfile) }, 0, Color.FromHex(prefs.AdminOOCColor), []); } public async Task DeleteSlotAndSetSelectedIndex(NetUserId userId, int deleteSlot, int newSlot) @@ -336,7 +330,7 @@ namespace Content.Server.Database private Profile ConvertProfiles(HumanoidCharacterProfile humanoid, int slot, Profile? profile = null) { profile ??= new Profile(); - var appearance = (HumanoidCharacterAppearance) humanoid.CharacterAppearance; + var appearance = humanoid.Appearance; var dataNode = _serialization.WriteValue(appearance.Markings, alwaysWrite: true, notNullableOverride: true); profile.CharacterName = humanoid.Name; diff --git a/Content.Server/Database/ServerDbManager.cs b/Content.Server/Database/ServerDbManager.cs index 9231ef5d753..44479b133c0 100644 --- a/Content.Server/Database/ServerDbManager.cs +++ b/Content.Server/Database/ServerDbManager.cs @@ -38,12 +38,12 @@ namespace Content.Server.Database #region Preferences Task InitPrefsAsync( NetUserId userId, - ICharacterProfile defaultProfile, + HumanoidCharacterProfile defaultProfile, CancellationToken cancel); Task SaveSelectedCharacterIndexAsync(NetUserId userId, int index); - Task SaveCharacterSlotAsync(NetUserId userId, ICharacterProfile? profile, int slot); + Task SaveCharacterSlotAsync(NetUserId userId, HumanoidCharacterProfile? profile, int slot); Task SaveAdminOOCColorAsync(NetUserId userId, Color color); @@ -428,7 +428,7 @@ namespace Content.Server.Database public Task InitPrefsAsync( NetUserId userId, - ICharacterProfile defaultProfile, + HumanoidCharacterProfile defaultProfile, CancellationToken cancel) { DbWriteOpsMetric.Inc(); @@ -441,7 +441,7 @@ namespace Content.Server.Database return RunDbCommand(() => _db.SaveSelectedCharacterIndexAsync(userId, index)); } - public Task SaveCharacterSlotAsync(NetUserId userId, ICharacterProfile? profile, int slot) + public Task SaveCharacterSlotAsync(NetUserId userId, HumanoidCharacterProfile? profile, int slot) { DbWriteOpsMetric.Inc(); return RunDbCommand(() => _db.SaveCharacterSlotAsync(userId, profile, slot)); diff --git a/Content.Server/Preferences/Managers/IServerPreferencesManager.cs b/Content.Server/Preferences/Managers/IServerPreferencesManager.cs index ed6f2b17e64..15620c462ec 100644 --- a/Content.Server/Preferences/Managers/IServerPreferencesManager.cs +++ b/Content.Server/Preferences/Managers/IServerPreferencesManager.cs @@ -20,10 +20,10 @@ namespace Content.Server.Preferences.Managers bool TryGetCachedPreferences(NetUserId userId, [NotNullWhen(true)] out PlayerPreferences? playerPreferences); PlayerPreferences GetPreferences(NetUserId userId); PlayerPreferences? GetPreferencesOrNull(NetUserId? userId); - IEnumerable> GetSelectedProfilesForPlayers(List userIds); + IEnumerable> GetSelectedProfilesForPlayers(List userIds); bool HavePreferencesLoaded(ICommonSession session); - Task SetProfile(NetUserId userId, int slot, ICharacterProfile profile); + Task SetProfile(NetUserId userId, int slot, HumanoidCharacterProfile profile); Task SetConstructionFavorites(NetUserId userId, List> favorites); } } diff --git a/Content.Server/Preferences/Managers/ServerPreferencesManager.cs b/Content.Server/Preferences/Managers/ServerPreferencesManager.cs index 10380f6b7fc..4cde984254f 100644 --- a/Content.Server/Preferences/Managers/ServerPreferencesManager.cs +++ b/Content.Server/Preferences/Managers/ServerPreferencesManager.cs @@ -91,7 +91,7 @@ namespace Content.Server.Preferences.Managers await SetProfile(userId, message.Slot, message.Profile); } - public async Task SetProfile(NetUserId userId, int slot, ICharacterProfile profile) + public async Task SetProfile(NetUserId userId, int slot, HumanoidCharacterProfile profile) { if (!_cachedPlayerPrefs.TryGetValue(userId, out var prefsData) || !prefsData.PrefsLoaded) { @@ -107,7 +107,7 @@ namespace Content.Server.Preferences.Managers profile.EnsureValid(session, _dependencies); - var profiles = new Dictionary(curPrefs.Characters) + var profiles = new Dictionary(curPrefs.Characters) { [slot] = profile }; @@ -168,7 +168,7 @@ namespace Content.Server.Preferences.Managers nextSlot = ns; } - var arr = new Dictionary(curPrefs.Characters); + var arr = new Dictionary(curPrefs.Characters); arr.Remove(slot); prefsData.Prefs = new PlayerPreferences(arr, nextSlot ?? curPrefs.SelectedCharacterIndex, curPrefs.AdminOOCColor, curPrefs.ConstructionFavorites); @@ -230,7 +230,7 @@ namespace Content.Server.Preferences.Managers { PrefsLoaded = true, Prefs = new PlayerPreferences( - new[] { new KeyValuePair(0, HumanoidCharacterProfile.Random()) }, + new[] { new KeyValuePair(0, HumanoidCharacterProfile.Random()) }, 0, Color.Transparent, []) }; @@ -349,17 +349,17 @@ namespace Content.Server.Preferences.Managers return new PlayerPreferences(prefs.Characters.Select(p => { - return new KeyValuePair(p.Key, p.Value.Validated(session, collection)); + return new KeyValuePair(p.Key, p.Value.Validated(session, collection)); }), prefs.SelectedCharacterIndex, prefs.AdminOOCColor, prefs.ConstructionFavorites); } - public IEnumerable> GetSelectedProfilesForPlayers( + public IEnumerable> GetSelectedProfilesForPlayers( List usernames) { return usernames .Select(p => (_cachedPlayerPrefs[p].Prefs, p)) .Where(p => p.Prefs != null) - .Select(p => new KeyValuePair(p.p, p.Prefs!.SelectedCharacter)); + .Select(p => new KeyValuePair(p.p, p.Prefs!.SelectedCharacter)); } internal static bool ShouldStorePrefs(LoginType loginType) diff --git a/Content.Shared/Humanoid/HumanoidCharacterAppearance.cs b/Content.Shared/Humanoid/HumanoidCharacterAppearance.cs index 734f0b8b6aa..e9b1f0a076e 100644 --- a/Content.Shared/Humanoid/HumanoidCharacterAppearance.cs +++ b/Content.Shared/Humanoid/HumanoidCharacterAppearance.cs @@ -12,7 +12,7 @@ namespace Content.Shared.Humanoid; [DataDefinition] [Serializable, NetSerializable] -public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance, IEquatable +public sealed partial class HumanoidCharacterAppearance : IEquatable { [DataField] public Color EyeColor { get; set; } = Color.Black; @@ -158,15 +158,6 @@ public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance, validatedMarkings); } - public bool MemberwiseEquals(ICharacterAppearance maybeOther) - { - if (maybeOther is not HumanoidCharacterAppearance other) return false; - if (!EyeColor.Equals(other.EyeColor)) return false; - if (!SkinColor.Equals(other.SkinColor)) return false; - if (!MarkingManager.MarkingsAreEqual(Markings, other.Markings)) return false; - return true; - } - public bool Equals(HumanoidCharacterAppearance? other) { if (ReferenceEquals(null, other)) return false; diff --git a/Content.Shared/Humanoid/ICharacterAppearance.cs b/Content.Shared/Humanoid/ICharacterAppearance.cs deleted file mode 100644 index 517df7fb493..00000000000 --- a/Content.Shared/Humanoid/ICharacterAppearance.cs +++ /dev/null @@ -1,8 +0,0 @@ - -namespace Content.Shared.Humanoid -{ - public interface ICharacterAppearance - { - bool MemberwiseEquals(ICharacterAppearance other); - } -} diff --git a/Content.Shared/Preferences/HumanoidCharacterProfile.cs b/Content.Shared/Preferences/HumanoidCharacterProfile.cs index a1990fa42e3..7dfd21e7182 100644 --- a/Content.Shared/Preferences/HumanoidCharacterProfile.cs +++ b/Content.Shared/Preferences/HumanoidCharacterProfile.cs @@ -28,7 +28,7 @@ namespace Content.Shared.Preferences /// [DataDefinition] [Serializable, NetSerializable] - public sealed partial class HumanoidCharacterProfile : ICharacterProfile + public sealed partial class HumanoidCharacterProfile { public static readonly ProtoId DefaultSpecies = "Human"; private static readonly Regex RestrictedNameRegex = new(@"[^A-Za-z0-9 '\-]"); @@ -89,11 +89,6 @@ namespace Content.Shared.Preferences [DataField] public Gender Gender { get; private set; } = Gender.Male; - /// - /// - /// - public ICharacterAppearance CharacterAppearance => Appearance; - /// /// Stores markings, eye colors, etc for the profile. /// @@ -465,9 +460,8 @@ namespace Content.Shared.Preferences ("age", Age) ); - public bool MemberwiseEquals(ICharacterProfile maybeOther) + public bool MemberwiseEquals(HumanoidCharacterProfile other) { - if (maybeOther is not HumanoidCharacterProfile other) return false; if (Name != other.Name) return false; if (Age != other.Age) return false; if (Sex != other.Sex) return false; @@ -480,7 +474,7 @@ namespace Content.Shared.Preferences if (!_traitPreferences.SequenceEqual(other._traitPreferences)) return false; if (!Loadouts.SequenceEqual(other.Loadouts)) return false; if (FlavorText != other.FlavorText) return false; - return Appearance.MemberwiseEquals(other.Appearance); + return Appearance.Equals(other.Appearance); } public void EnsureValid(ICommonSession session, IDependencyCollection collection) @@ -692,7 +686,7 @@ namespace Content.Shared.Preferences return result; } - public ICharacterProfile Validated(ICommonSession session, IDependencyCollection collection) + public HumanoidCharacterProfile Validated(ICommonSession session, IDependencyCollection collection) { var profile = new HumanoidCharacterProfile(this); profile.EnsureValid(session, collection); diff --git a/Content.Shared/Preferences/ICharacterProfile.cs b/Content.Shared/Preferences/ICharacterProfile.cs deleted file mode 100644 index 3e7dbc41588..00000000000 --- a/Content.Shared/Preferences/ICharacterProfile.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Content.Shared.Humanoid; -using Robust.Shared.Configuration; -using Robust.Shared.Player; -using Robust.Shared.Prototypes; - -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(ICommonSession session, IDependencyCollection collection); - - /// - /// Gets a copy of this profile that has applied, i.e. no invalid data. - /// - ICharacterProfile Validated(ICommonSession session, IDependencyCollection collection); - } -} diff --git a/Content.Shared/Preferences/MsgUpdateCharacter.cs b/Content.Shared/Preferences/MsgUpdateCharacter.cs index 3c4af1833ed..decb0182228 100644 --- a/Content.Shared/Preferences/MsgUpdateCharacter.cs +++ b/Content.Shared/Preferences/MsgUpdateCharacter.cs @@ -13,7 +13,7 @@ namespace Content.Shared.Preferences public override MsgGroups MsgGroup => MsgGroups.Command; public int Slot; - public ICharacterProfile Profile = default!; + public HumanoidCharacterProfile Profile = default!; public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer) { @@ -21,7 +21,7 @@ namespace Content.Shared.Preferences var length = buffer.ReadVariableInt32(); using var stream = new MemoryStream(length); buffer.ReadAlignedMemory(stream, length); - Profile = serializer.Deserialize(stream); + Profile = serializer.Deserialize(stream); } public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer) diff --git a/Content.Shared/Preferences/PlayerPreferences.cs b/Content.Shared/Preferences/PlayerPreferences.cs index aee46f488b1..d4f67364c76 100644 --- a/Content.Shared/Preferences/PlayerPreferences.cs +++ b/Content.Shared/Preferences/PlayerPreferences.cs @@ -13,11 +13,11 @@ namespace Content.Shared.Preferences [NetSerializable] public sealed class PlayerPreferences { - private Dictionary _characters; + private Dictionary _characters; - public PlayerPreferences(IEnumerable> characters, int selectedCharacterIndex, Color adminOOCColor, List> constructionFavorites) + public PlayerPreferences(IEnumerable> characters, int selectedCharacterIndex, Color adminOOCColor, List> constructionFavorites) { - _characters = new Dictionary(characters); + _characters = new Dictionary(characters); SelectedCharacterIndex = selectedCharacterIndex; AdminOOCColor = adminOOCColor; ConstructionFavorites = constructionFavorites; @@ -26,9 +26,9 @@ namespace Content.Shared.Preferences /// /// All player characters. /// - public IReadOnlyDictionary Characters => _characters; + public IReadOnlyDictionary Characters => _characters; - public ICharacterProfile GetProfile(int index) + public HumanoidCharacterProfile GetProfile(int index) { return _characters[index]; } @@ -41,7 +41,7 @@ namespace Content.Shared.Preferences /// /// The currently selected character. /// - public ICharacterProfile SelectedCharacter => Characters[SelectedCharacterIndex]; + public HumanoidCharacterProfile SelectedCharacter => Characters[SelectedCharacterIndex]; public Color AdminOOCColor { get; set; } @@ -50,12 +50,12 @@ namespace Content.Shared.Preferences /// public List> ConstructionFavorites { get; set; } = []; - public int IndexOfCharacter(ICharacterProfile profile) + public int IndexOfCharacter(HumanoidCharacterProfile profile) { return _characters.FirstOrNull(p => p.Value == profile)?.Key ?? -1; } - public bool TryIndexOfCharacter(ICharacterProfile profile, out int index) + public bool TryIndexOfCharacter(HumanoidCharacterProfile profile, out int index) { return (index = IndexOfCharacter(profile)) != -1; }