Fix creating and deleting character slots crashing the client and server (#2172)

* Fix creating a character slot crashing the client

* a

* Fix deleting character profiles
This commit is contained in:
DrSmugleaf
2020-10-06 12:03:14 +02:00
committed by GitHub
parent f9bb3fed6f
commit f35625630b
5 changed files with 89 additions and 5 deletions

View File

@@ -26,6 +26,7 @@ namespace Content.Client
HandlePreferencesAndSettings); HandlePreferencesAndSettings);
_netManager.RegisterNetMessage<MsgUpdateCharacter>(nameof(MsgUpdateCharacter)); _netManager.RegisterNetMessage<MsgUpdateCharacter>(nameof(MsgUpdateCharacter));
_netManager.RegisterNetMessage<MsgSelectCharacter>(nameof(MsgSelectCharacter)); _netManager.RegisterNetMessage<MsgSelectCharacter>(nameof(MsgSelectCharacter));
_netManager.RegisterNetMessage<MsgDeleteCharacter>(nameof(MsgDeleteCharacter));
} }
public void SelectCharacter(ICharacterProfile profile) public void SelectCharacter(ICharacterProfile profile)
@@ -54,7 +55,12 @@ namespace Content.Client
public void CreateCharacter(ICharacterProfile profile) public void CreateCharacter(ICharacterProfile profile)
{ {
UpdateCharacter(profile, Preferences.FirstEmptySlot); var characters = Preferences.Characters.ToList();
characters.Add(profile);
Preferences = new PlayerPreferences(characters, Preferences.SelectedCharacterIndex);
UpdateCharacter(profile, characters.Count - 1);
} }
public void DeleteCharacter(ICharacterProfile profile) public void DeleteCharacter(ICharacterProfile profile)
@@ -64,7 +70,11 @@ namespace Content.Client
public void DeleteCharacter(int slot) public void DeleteCharacter(int slot)
{ {
UpdateCharacter(null, slot); var characters = Preferences.Characters.Where((profile, index) => index != slot).ToArray();
Preferences = new PlayerPreferences(characters, Preferences.SelectedCharacterIndex);
var msg = _netManager.CreateNetMessage<MsgDeleteCharacter>();
msg.Slot = slot;
_netManager.ClientSendMessage(msg);
} }
private void HandlePreferencesAndSettings(MsgPreferencesAndSettings message) private void HandlePreferencesAndSettings(MsgPreferencesAndSettings message)

View File

@@ -27,7 +27,7 @@ namespace Content.Server.Database
// Preferences // Preferences
Task<PlayerPreferences> InitPrefsAsync(NetUserId userId, ICharacterProfile defaultProfile); Task<PlayerPreferences> InitPrefsAsync(NetUserId userId, ICharacterProfile defaultProfile);
Task SaveSelectedCharacterIndexAsync(NetUserId userId, int index); Task SaveSelectedCharacterIndexAsync(NetUserId userId, int index);
Task SaveCharacterSlotAsync(NetUserId userId, ICharacterProfile profile, int slot); Task SaveCharacterSlotAsync(NetUserId userId, ICharacterProfile? profile, int slot);
Task<PlayerPreferences?> GetPlayerPreferencesAsync(NetUserId userId); Task<PlayerPreferences?> GetPlayerPreferencesAsync(NetUserId userId);
// Username assignment (for guest accounts, so they persist GUID) // Username assignment (for guest accounts, so they persist GUID)
@@ -90,7 +90,7 @@ namespace Content.Server.Database
return _db.SaveSelectedCharacterIndexAsync(userId, index); return _db.SaveSelectedCharacterIndexAsync(userId, index);
} }
public Task SaveCharacterSlotAsync(NetUserId userId, ICharacterProfile profile, int slot) public Task SaveCharacterSlotAsync(NetUserId userId, ICharacterProfile? profile, int slot)
{ {
return _db.SaveCharacterSlotAsync(userId, profile, slot); return _db.SaveCharacterSlotAsync(userId, profile, slot);
} }

View File

@@ -42,6 +42,8 @@ namespace Content.Server.Preferences
HandleSelectCharacterMessage); HandleSelectCharacterMessage);
_netManager.RegisterNetMessage<MsgUpdateCharacter>(nameof(MsgUpdateCharacter), _netManager.RegisterNetMessage<MsgUpdateCharacter>(nameof(MsgUpdateCharacter),
HandleUpdateCharacterMessage); HandleUpdateCharacterMessage);
_netManager.RegisterNetMessage<MsgDeleteCharacter>(nameof(MsgDeleteCharacter),
HandleDeleteCharacterMessage);
} }
@@ -77,6 +79,13 @@ namespace Content.Server.Preferences
var profile = message.Profile; var profile = message.Profile;
var userId = message.MsgChannel.UserId; var userId = message.MsgChannel.UserId;
if (profile == null)
{
Logger.WarningS("prefs",
$"User {userId} sent a {nameof(MsgUpdateCharacter)} with a null profile in slot {slot}.");
return;
}
if (!_cachedPlayerPrefs.TryGetValue(userId, out var prefsData) || !prefsData.PrefsLoaded.IsCompleted) if (!_cachedPlayerPrefs.TryGetValue(userId, out var prefsData) || !prefsData.PrefsLoaded.IsCompleted)
{ {
Logger.WarningS("prefs", $"User {userId} tried to modify preferences before they loaded."); Logger.WarningS("prefs", $"User {userId} tried to modify preferences before they loaded.");
@@ -103,6 +112,35 @@ namespace Content.Server.Preferences
} }
} }
private async void HandleDeleteCharacterMessage(MsgDeleteCharacter message)
{
var slot = message.Slot;
var userId = message.MsgChannel.UserId;
if (!_cachedPlayerPrefs.TryGetValue(userId, out var prefsData) || !prefsData.PrefsLoaded.IsCompleted)
{
Logger.WarningS("prefs", $"User {userId} tried to modify preferences before they loaded.");
return;
}
if (slot < 0 || slot >= MaxCharacterSlots)
{
return;
}
var curPrefs = prefsData.Prefs!;
var arr = new ICharacterProfile[MaxCharacterSlots];
curPrefs.Characters.Where((profile, index) => index != slot).ToArray().CopyTo(arr, 0);
prefsData.Prefs = new PlayerPreferences(arr, slot);
if (ShouldStorePrefs(message.MsgChannel.AuthType))
{
await _db.SaveCharacterSlotAsync(message.MsgChannel.UserId, null, message.Slot);
}
}
public async void OnClientConnected(IPlayerSession session) public async void OnClientConnected(IPlayerSession session)
{ {
if (!ShouldStorePrefs(session.ConnectedClient.AuthType)) if (!ShouldStorePrefs(session.ConnectedClient.AuthType))

View File

@@ -41,11 +41,20 @@ namespace Content.Shared.Preferences
/// </summary> /// </summary>
public ICharacterProfile SelectedCharacter => Characters.ElementAtOrDefault(SelectedCharacterIndex); public ICharacterProfile SelectedCharacter => Characters.ElementAtOrDefault(SelectedCharacterIndex);
public int FirstEmptySlot => IndexOfCharacter(null); public int FirstEmptySlot()
{
var firstEmpty = IndexOfCharacter(null);
return firstEmpty == -1 ? _characters.Count : firstEmpty;
}
public int IndexOfCharacter(ICharacterProfile profile) public int IndexOfCharacter(ICharacterProfile profile)
{ {
return _characters.FindIndex(x => x == profile); return _characters.FindIndex(x => x == profile);
} }
public bool TryIndexOfCharacter(ICharacterProfile profile, out int index)
{
return (index = IndexOfCharacter(profile)) != -1;
}
} }
} }

View File

@@ -128,5 +128,32 @@ namespace Content.Shared.Preferences
} }
} }
} }
/// <summary>
/// The client sends this to delete a character profile.
/// </summary>
protected class MsgDeleteCharacter : NetMessage
{
#region REQUIRED
public const MsgGroups GROUP = MsgGroups.Command;
public const string NAME = nameof(MsgDeleteCharacter);
public MsgDeleteCharacter(INetChannel channel) : base(NAME, GROUP) { }
#endregion
public int Slot;
public override void ReadFromBuffer(NetIncomingMessage buffer)
{
Slot = buffer.ReadInt32();
}
public override void WriteToBuffer(NetOutgoingMessage buffer)
{
buffer.Write(Slot);
}
}
} }
} }