diff --git a/Common/Database/Player/PlayerGameData.cs b/Common/Database/Player/PlayerGameData.cs index d7c5e59..894d192 100644 --- a/Common/Database/Player/PlayerGameData.cs +++ b/Common/Database/Player/PlayerGameData.cs @@ -7,6 +7,8 @@ namespace MikuSB.Database.Player; [SugarTable("Player")] public class PlayerGameData : BaseDatabaseDataHelper { + public const string DefaultDisplayName = "Miku"; + public string? Name { get; set; } = ""; public string? Signature { get; set; } = "MikuPS"; public uint Level { get; set; } = 100; @@ -25,13 +27,30 @@ public class PlayerGameData : BaseDatabaseDataHelper return result; } + public static string NormalizeDisplayName(string? name) + { + var normalized = name?.Trim(); + return string.IsNullOrWhiteSpace(normalized) ? DefaultDisplayName : normalized; + } + + public bool EnsureDisplayName() + { + var normalized = NormalizeDisplayName(Name); + if (string.Equals(Name, normalized, StringComparison.Ordinal)) + return false; + + Name = normalized; + return true; + } + public PlayerProfile ToProfileProto() { + var displayName = NormalizeDisplayName(Name); var proto = new PlayerProfile { Pid = (uint)Uid, - Account = Name, - Name = Name, + Account = displayName, + Name = displayName, Level = Level, Sex = Gender, Sign = Signature, diff --git a/GameServer/Game/Player/PlayerInstance.cs b/GameServer/Game/Player/PlayerInstance.cs index a848ef6..04995c8 100644 --- a/GameServer/Game/Player/PlayerInstance.cs +++ b/GameServer/Game/Player/PlayerInstance.cs @@ -43,7 +43,7 @@ public class PlayerInstance(PlayerGameData data) { // new player IsNewPlayer = true; - Data.Name = AccountData.GetAccountByUid(uid)?.Username; + Data.Name = PlayerGameData.NormalizeDisplayName(AccountData.GetAccountByUid(uid)?.Username); DatabaseHelper.CreateInstance(Data); @@ -138,6 +138,7 @@ public class PlayerInstance(PlayerGameData data) public async ValueTask OnEnterGame() { if (!Initialized) await InitialPlayerManager(); + Data.EnsureDisplayName(); await CharacterManager.RepairCharacterWeapons(); await EnsureSupplies(); } @@ -229,12 +230,13 @@ public class PlayerInstance(PlayerGameData data) public Proto.Player ToPlayerProto() { + var displayName = PlayerGameData.NormalizeDisplayName(Data.Name); var proto = new Proto.Player { Pid = (ulong)Data.Uid, - Account = Data.Name, - Provider = Data.Name, - Name = Data.Name, + Account = displayName, + Provider = displayName, + Name = displayName, Level = Data.Level, Sex = Data.Gender, Vigor = Data.Vigor, @@ -263,6 +265,11 @@ public class PlayerInstance(PlayerGameData data) return proto; } + public void SetDisplayName(string? name) + { + Data.Name = PlayerGameData.NormalizeDisplayName(name); + } + public void SetShowItem(int index, ulong itemId) { if (index <= 0) diff --git a/GameServer/Server/Packet/Recv/Login/HandlerReqLogin.cs b/GameServer/Server/Packet/Recv/Login/HandlerReqLogin.cs index fef7dac..8efef28 100644 --- a/GameServer/Server/Packet/Recv/Login/HandlerReqLogin.cs +++ b/GameServer/Server/Packet/Recv/Login/HandlerReqLogin.cs @@ -43,6 +43,8 @@ public class HandlerReqLogin : Handler connection.State = SessionStateEnum.WAITING_FOR_LOGIN; var pd = DatabaseHelper.GetInstance(account.Uid); connection.Player = pd == null ? new PlayerInstance(account.Uid) : new PlayerInstance(pd); + if (connection.Player.Data.EnsureDisplayName()) + DatabaseHelper.UpdateInstance(connection.Player.Data); connection.DebugFile = Path.Combine(ConfigManager.Config.Path.LogPath, "Debug/", $"{account.Uid}/", $"Debug-{DateTime.Now:yyyy-MM-dd HH-mm-ss}.log"); diff --git a/GameServer/Server/Packet/Recv/Player/HandlerReqRename.cs b/GameServer/Server/Packet/Recv/Player/HandlerReqRename.cs index 8bb2440..072b6bf 100644 --- a/GameServer/Server/Packet/Recv/Player/HandlerReqRename.cs +++ b/GameServer/Server/Packet/Recv/Player/HandlerReqRename.cs @@ -1,4 +1,6 @@ -using MikuSB.Proto; +using Google.Protobuf; +using MikuSB.Database; +using MikuSB.Proto; namespace MikuSB.GameServer.Server.Packet.Recv.Login; @@ -7,6 +9,57 @@ public class HandlerReqRename : Handler { public override async Task OnHandle(Connection connection, byte[] data, ushort seqNo) { + var player = connection.Player; + if (player != null) + { + var requestedName = ParseDisplayName(data); + player.SetDisplayName(requestedName); + DatabaseHelper.UpdateInstance(player.Data); + await player.OnHeartBeat(); + } + await connection.SendPacket(CmdIds.RspRename); } + + private static string? ParseDisplayName(byte[] data) + { + if (data.Length == 0) + return null; + + try + { + var input = new CodedInputStream(data); + while (!input.IsAtEnd) + { + var tag = input.ReadTag(); + if (tag == 0) + break; + + if (WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited) + { + var value = input.ReadString(); + if (!string.IsNullOrWhiteSpace(value)) + return value; + } + else + { + input.SkipLastField(); + } + } + } + catch + { + // Fall back to raw UTF-8 payload handling below. + } + + try + { + var rawText = System.Text.Encoding.UTF8.GetString(data).Trim('\0', ' ', '\r', '\n', '\t'); + return string.IsNullOrWhiteSpace(rawText) ? null : rawText; + } + catch + { + return null; + } + } }