From 07ec2f9abfdf1775007de4bc8e426eac976c6fa1 Mon Sep 17 00:00:00 2001 From: Naruse <71993948+DevilProMT@users.noreply.github.com> Date: Sat, 14 Jun 2025 14:13:48 +0800 Subject: [PATCH] feat: add in game command handler --- Common/Configuration/ConfigContainer.cs | 13 ++--- Common/Database/Player/PlayerData.cs | 48 ++++++++-------- GameServer/Command/CommandSender.cs | 3 +- GameServer/Command/Commands/CommandHelp.cs | 52 +++++++++++++++++ GameServer/Game/Chat/WorldChatManager.cs | 31 ++++++++++ GameServer/Game/Player/PlayerInstance.cs | 3 + GameServer/Server/Connection.cs | 4 ++ .../Recv/Chat/HandlerSendChatMsgNotify.cs | 21 +++++++ .../Warship/HandlerSetWarshipAvatarReq.cs | 4 +- .../Send/Chat/PacketRecvChatMsgNotify.cs | 56 +++++++++++++++++++ 10 files changed, 201 insertions(+), 34 deletions(-) create mode 100644 GameServer/Command/Commands/CommandHelp.cs create mode 100644 GameServer/Game/Chat/WorldChatManager.cs create mode 100644 GameServer/Server/Packet/Recv/Chat/HandlerSendChatMsgNotify.cs create mode 100644 GameServer/Server/Packet/Send/Chat/PacketRecvChatMsgNotify.cs diff --git a/Common/Configuration/ConfigContainer.cs b/Common/Configuration/ConfigContainer.cs index 5b3e1bc..caaf743 100644 --- a/Common/Configuration/ConfigContainer.cs +++ b/Common/Configuration/ConfigContainer.cs @@ -71,12 +71,11 @@ public class ServerOption public class ServerProfile { - public string Name { get; set; } = "Server"; + public string Name { get; set; } = "Ai-chan"; public int Uid { get; set; } = 80; - public string Signature { get; set; } = "Type /help for a list of commands"; - public int Level { get; set; } = 1; - public int HeadIcon { get; set; } = 200105; - public int ChatBubbleId { get; set; } = 220001; - public int DisplayAvatarId { get; set; } = 1001; - public int DisplayAvatarLevel { get; set; } = 1; + public int AvatarId { get; set; } = 3201; + public int DressId { get; set; } = 593201; + public int FrameId { get; set; } = 200001; + public int HeadId { get; set; } = 161080; + } \ No newline at end of file diff --git a/Common/Database/Player/PlayerData.cs b/Common/Database/Player/PlayerData.cs index 0c483d1..dc48a39 100644 --- a/Common/Database/Player/PlayerData.cs +++ b/Common/Database/Player/PlayerData.cs @@ -11,16 +11,16 @@ public class PlayerData : BaseDatabaseDataHelper { public string? Name { get; set; } = ""; public string? Signature { get; set; } = "KianaPS"; - public uint Level { get; set; } = 88; - public uint Exp { get; set; } = 0; - public uint HCoin { get; set; } = 0; - public uint Stamina { get; set; } = 240; - public uint HeadIcon { get; set; } = 161090; - public uint HeadFrame { get; set; } = 200001; - public uint WarshipId { get; set; } = 400004; - public uint PhonePendantId { get; set; } = 350005; - public uint AssistantAvatarId { get; set; } = 101; - public uint BirthDay { get; set; } = 0; + public int Level { get; set; } = 88; + public int Exp { get; set; } = 0; + public int HCoin { get; set; } = 0; + public int Stamina { get; set; } = 240; + public int HeadIcon { get; set; } = 161090; + public int HeadFrame { get; set; } = 200001; + public int WarshipId { get; set; } = 400004; + public int PhonePendantId { get; set; } = 350005; + public int AssistantAvatarId { get; set; } = 101; + public int BirthDay { get; set; } = 0; [SugarColumn(IsJson = true)] public WarshipAvatarData WarshipAvatar { get; set; } = new(); [SugarColumn(IsNullable = true)] public long LastActiveTime { get; set; } public long RegisterTime { get; set; } = Extensions.GetUnixSec(); @@ -35,23 +35,23 @@ public class PlayerData : BaseDatabaseDataHelper return new GetMainDataRsp { IsAll = true, - AssistantAvatarId = 0, - Birthday = BirthDay, + AssistantAvatarId = (uint)AssistantAvatarId, + Birthday = (uint)BirthDay, Nickname = Name, - Level = Level, - Exp = Exp, - Hcoin = HCoin, - CustomHeadId = HeadIcon, + Level = (uint)Level, + Exp = (uint)Exp, + Hcoin = (uint)HCoin, + CustomHeadId = (uint)HeadIcon, RegisterTime = (uint)RegisterTime, WarshipAvatar = new Proto.WarshipAvatarData { - WarshipFirstAvatarId = 0, - WarshipSecondAvatarId = 0, + WarshipFirstAvatarId = (uint)WarshipAvatar.FirstAvatarId, + WarshipSecondAvatarId = (uint)WarshipAvatar.SecondAvatarId, }, SelfDesc = Signature, - UseFrameId = HeadFrame, - OnPhonePendantId = PhonePendantId, - Stamina = Stamina, + UseFrameId = (uint)HeadFrame, + OnPhonePendantId = (uint)PhonePendantId, + Stamina = (uint)Stamina, StaminaRecoverConfigTime = GameConstants.STAMINA_RECOVERY_TIME, StaminaRecoverLeftTime = GameConstants.STAMINA_RECOVERY_TIME, EquipmentSizeLimit = GameConstants.INVENTORY_MAX_EQUIPMENT, @@ -59,7 +59,7 @@ public class PlayerData : BaseDatabaseDataHelper LevelLockId = 1, WarshipTheme = new WarshipThemeData { - WarshipId=0 + WarshipId=(uint)WarshipId }, TotalLoginDays = 1 }; @@ -68,6 +68,6 @@ public class PlayerData : BaseDatabaseDataHelper public class WarshipAvatarData { - public uint FirstAvatarId { get; set; } = 101; - public uint SecondAvatarId { get; set; } = 0; + public int FirstAvatarId { get; set; } = 101; + public int SecondAvatarId { get; set; } = 0; } \ No newline at end of file diff --git a/GameServer/Command/CommandSender.cs b/GameServer/Command/CommandSender.cs index 4a06ce4..93aebad 100644 --- a/GameServer/Command/CommandSender.cs +++ b/GameServer/Command/CommandSender.cs @@ -1,5 +1,6 @@ using KianaBH.Enums.Player; using KianaBH.GameServer.Game.Player; +using KianaBH.GameServer.Server.Packet.Send.Chat; using KianaBH.Util; namespace KianaBH.GameServer.Command; @@ -31,7 +32,7 @@ public class PlayerCommandSender(PlayerInstance player) : ICommandSender public async ValueTask SendMsg(string msg) { - // TODO SEND MSG + await Player.SendPacket(new PacketRecvChatMsgNotify(msg)); } public int GetSender() diff --git a/GameServer/Command/Commands/CommandHelp.cs b/GameServer/Command/Commands/CommandHelp.cs new file mode 100644 index 0000000..8b2aa77 --- /dev/null +++ b/GameServer/Command/Commands/CommandHelp.cs @@ -0,0 +1,52 @@ +using KianaBH.Enums.Player; +using KianaBH.Internationalization; +using KianaBH.Util.Extensions; + +namespace KianaBH.GameServer.Command.Commands; + +[CommandInfo("help", "Game.Command.Help.Desc", "Game.Command.Help.Usage", ["h"], [PermEnum.Support, PermEnum.Trial])] +public class CommandHelp : ICommands +{ + [CommandDefault] + public async static ValueTask Help(CommandArg arg) + { + if (arg.Args.Count == 1) + { + var cmd = arg.Args[0]; + if (CommandManager.CommandInfo == null || !CommandManager.CommandInfo.TryGetValue(cmd, out var command)) + { + await arg.SendMsg(I18NManager.Translate("Game.Command.Notice.CommandNotFound")); + return; + } + + var msg = + $"/{command.Name} - {I18NManager.Translate(command.Description)}\n{I18NManager.Translate(command.Usage)}"; + if (command.Alias.Length > 0) + msg += + $"\n{I18NManager.Translate("Game.Command.Help.CommandAlias")} {command.Alias.ToList().ToArrayString()}"; + if (command.Perm != null) + msg += $"\n{I18NManager.Translate("Game.Command.Help.CommandPermission")} {string.Join(", ", command.Perm.Select(perm => perm.ToString()))}"; + + await arg.SendMsg(msg + "\n"); + return; + } + else + { + await arg.SendMsg(I18NManager.Translate("Game.Command.Help.Commands")); + if (CommandManager.CommandInfo == null) return; + + foreach (var command in CommandManager.CommandInfo.Values) + { + var msg = + $"/{command.Name} - {I18NManager.Translate(command.Description)}\n{I18NManager.Translate(command.Usage)}"; + if (command.Alias.Length > 0) + msg += + $"\n{I18NManager.Translate("Game.Command.Help.CommandAlias")} {command.Alias.ToList().ToArrayString()}"; + + if (command.Perm != null) + msg += $"\n{I18NManager.Translate("Game.Command.Help.CommandPermission")} {string.Join(", ", command.Perm.Select(perm => perm.ToString()))}"; + await arg.SendMsg(msg + "\n"); + } + } + } +} \ No newline at end of file diff --git a/GameServer/Game/Chat/WorldChatManager.cs b/GameServer/Game/Chat/WorldChatManager.cs new file mode 100644 index 0000000..52f82f4 --- /dev/null +++ b/GameServer/Game/Chat/WorldChatManager.cs @@ -0,0 +1,31 @@ +using KianaBH.GameServer.Command; +using KianaBH.GameServer.Game.Player; +using KianaBH.GameServer.Server.Packet.Send.Chat; +using KianaBH.Proto; +using KianaBH.Util.Extensions; + +namespace KianaBH.GameServer.Game.Battle; + +public class WorldChatManager(PlayerInstance player) : BasePlayerManager(player) +{ + public List Chats { get; set; } = []; + + public async ValueTask SendMessage(string message, ChatMsg chatMsg) + { + chatMsg.Uid = (uint)Player.Data.Uid; + chatMsg.Nickname = Player.Data.Name; + chatMsg.Time = (uint)Extensions.GetUnixSec(); + chatMsg.AvatarId = (uint)Player.Data.AssistantAvatarId; + chatMsg.DressId = (uint)Player.AvatarManager!.AvatarData.Avatars.Where(avatar => avatar.AvatarId == Player.Data.AssistantAvatarId).First().DressId; + chatMsg.FrameId = (uint)Player.Data.HeadFrame; + chatMsg.CustomHeadId = (uint)Player.Data.HeadIcon; + + await Player.SendPacket(new PacketRecvChatMsgNotify(chatMsg)); + + if (message.StartsWith('/') == true) + { + var cmd = message[1..]; + CommandExecutor.ExecuteCommand(new PlayerCommandSender(Player), cmd); + } + } +} \ No newline at end of file diff --git a/GameServer/Game/Player/PlayerInstance.cs b/GameServer/Game/Player/PlayerInstance.cs index 174112a..e7d085f 100644 --- a/GameServer/Game/Player/PlayerInstance.cs +++ b/GameServer/Game/Player/PlayerInstance.cs @@ -4,6 +4,7 @@ using KianaBH.Database.Account; using KianaBH.Database.Client; using KianaBH.Database.Player; using KianaBH.GameServer.Game.Avatar; +using KianaBH.GameServer.Game.Battle; using KianaBH.GameServer.Game.Inventory; using KianaBH.GameServer.Server; using KianaBH.KcpSharp; @@ -20,6 +21,7 @@ public class PlayerInstance(PlayerData data) public PlayerData Data { get; set; } = data; public ClientData? ClientData { get; private set; } public GuideData? GuideData { get; private set; } + public WorldChatManager? WorldChatManager { get; private set; } public int Uid { get; set; } public Connection? Connection { get; set; } public bool Initialized { get; set; } @@ -53,6 +55,7 @@ public class PlayerInstance(PlayerData data) InventoryManager = new InventoryManager(this); ClientData = InitializeDatabase(); GuideData = InitializeDatabase(); + WorldChatManager = new WorldChatManager(this); Data.LastActiveTime = Extensions.GetUnixSec(); await Task.CompletedTask; diff --git a/GameServer/Server/Connection.cs b/GameServer/Server/Connection.cs index 493d7da..32b97cc 100644 --- a/GameServer/Server/Connection.cs +++ b/GameServer/Server/Connection.cs @@ -175,6 +175,10 @@ public class Connection(KcpConversation conversation, IPEndPoint remote) : KcpCo } return; } + + if (ConfigManager.Config.ServerOption.EnableDebug && + ConfigManager.Config.ServerOption.DebugNoHandlerPacket) + Logger.Error($"No handler found for {packetName}({opcode})"); } private async Task SendDummy(string packetName) diff --git a/GameServer/Server/Packet/Recv/Chat/HandlerSendChatMsgNotify.cs b/GameServer/Server/Packet/Recv/Chat/HandlerSendChatMsgNotify.cs new file mode 100644 index 0000000..51631b2 --- /dev/null +++ b/GameServer/Server/Packet/Recv/Chat/HandlerSendChatMsgNotify.cs @@ -0,0 +1,21 @@ +using KianaBH.GameServer.Command; +using KianaBH.GameServer.Server.Packet.Send.Chat; +using KianaBH.Proto; + +namespace KianaBH.GameServer.Server.Packet.Recv.Chat; + +[Opcode(CmdIds.SendChatMsgNotify)] +public class HandlerSendChatMsgNotify : Handler +{ + public override async Task OnHandle(Connection connection, byte[] header, byte[] data) + { + var req = SendChatMsgNotify.Parser.ParseFrom(data); + var player = connection.Player!; + if (player == null) return; + + string msg = req.ChatMsg.Content.Items.Where(item => item.MsgStr != null).FirstOrDefault()?.MsgStr!; + if (msg == null) return; + + await player.WorldChatManager!.SendMessage(msg,req.ChatMsg); + } +} diff --git a/GameServer/Server/Packet/Recv/Warship/HandlerSetWarshipAvatarReq.cs b/GameServer/Server/Packet/Recv/Warship/HandlerSetWarshipAvatarReq.cs index a594998..58fbf28 100644 --- a/GameServer/Server/Packet/Recv/Warship/HandlerSetWarshipAvatarReq.cs +++ b/GameServer/Server/Packet/Recv/Warship/HandlerSetWarshipAvatarReq.cs @@ -12,8 +12,8 @@ public class HandlerSetWarshipAvatarReq : Handler var player = connection.Player!; var req = SetWarshipAvatarReq.Parser.ParseFrom(data); - player.Data.WarshipAvatar.FirstAvatarId = req.FirstAvatarId; - player.Data.WarshipAvatar.SecondAvatarId = req.SecondAvatarId; + player.Data.WarshipAvatar.FirstAvatarId = (int)req.FirstAvatarId; + player.Data.WarshipAvatar.SecondAvatarId = (int)req.SecondAvatarId; await connection.SendPacket(new PacketGetMainDataRsp(req.FirstAvatarId,req.SecondAvatarId)); await connection.SendPacket(CmdIds.SetWarshipAvatarRsp); diff --git a/GameServer/Server/Packet/Send/Chat/PacketRecvChatMsgNotify.cs b/GameServer/Server/Packet/Send/Chat/PacketRecvChatMsgNotify.cs new file mode 100644 index 0000000..f475e8d --- /dev/null +++ b/GameServer/Server/Packet/Send/Chat/PacketRecvChatMsgNotify.cs @@ -0,0 +1,56 @@ +using KianaBH.KcpSharp; +using KianaBH.Proto; +using KianaBH.Util; +using KianaBH.Util.Extensions; + +namespace KianaBH.GameServer.Server.Packet.Send.Chat; + +public class PacketRecvChatMsgNotify : BasePacket +{ + public PacketRecvChatMsgNotify(ChatMsg msgs) : base(CmdIds.RecvChatMsgNotify) + { + var proto = new RecvChatMsgNotify + { + ChatMsgList = { msgs } + }; + + SetData(proto); + } + + public PacketRecvChatMsgNotify(string message) : base(CmdIds.RecvChatMsgNotify) + { + var proto = new RecvChatMsgNotify + { + ChatMsgList = + { + new ChatMsg + { + Uid = (uint)ConfigManager.Config.ServerOption.ServerProfile.Uid, + Nickname = ConfigManager.Config.ServerOption.ServerProfile.Name, + Time = (uint)Extensions.GetUnixSec(), + Msg = message, + Channel = ChatMsg.Types.MsgChannel.World, + AvatarId = (uint)ConfigManager.Config.ServerOption.ServerProfile.AvatarId, + DressId = (uint)ConfigManager.Config.ServerOption.ServerProfile.DressId, + FrameId = (uint)ConfigManager.Config.ServerOption.ServerProfile.FrameId, + CustomHeadId = (uint)ConfigManager.Config.ServerOption.ServerProfile.HeadId, + CheckResult = new ChatMsgSensitiveCheckResult + { + RewriteText = message + }, + Content = new ChatMsgContent + { + Items = + { + new ChatMsgItem + { + MsgStr = message, + } + } + } + } + } + }; + SetData(proto); + } +}