From e1a4db89ae5ed9c64a04fa448a0f26ebdd8d206e Mon Sep 17 00:00:00 2001 From: bob <605277374@qq.com> Date: Thu, 7 Aug 2025 17:51:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B9=BF=E6=92=AD=E8=81=8A=E5=A4=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NetworkProtocol/Inner/InnerMessage.proto | 18 +++++ Entity/Chat/ChatComponent.cs | 2 +- Entity/Chat/ChatUnit.cs | 2 +- Entity/Chat/ChatUnitManageComponent.cs | 8 ++ .../Generate/NetworkProtocol/InnerMessage.cs | 65 ++++++++++++++++ .../Generate/NetworkProtocol/InnerOpcode.cs | 3 + .../C2Chat_SendMessageRequestHandler.cs | 1 + .../Handler/G2Chat_EnterRequestHandler.cs | 22 ++++++ Hotfix/Chat/Helper/ChatSceneHelper.cs | 34 ++++++++- Hotfix/Chat/Helper/ChatUnitFactory.cs | 20 +++++ .../System/ChatUnitManageComponentSystem.cs | 75 +++++++++++++++++++ Hotfix/Game/Helper/GameSceneHelper.cs | 23 +++++- .../Inner/Chat2G_ChatMessageHandler.cs | 24 ++++++ .../{ => Outer}/C2G_LoginRequestHandler.cs | 0 Hotfix/Gate/Helper/GateLoginHelper.cs | 41 ++++++---- .../System/GateUnitManageComponentSystem.cs | 15 ++++ .../Gate/System/JWT/GateJWTComponentSystem.cs | 4 +- Hotfix/OnSceneCreate_Init.cs | 7 ++ Server.sln.DotSettings.user | 4 + 19 files changed, 347 insertions(+), 21 deletions(-) create mode 100644 Entity/Chat/ChatUnitManageComponent.cs create mode 100644 Hotfix/Chat/Handler/G2Chat_EnterRequestHandler.cs create mode 100644 Hotfix/Chat/Helper/ChatUnitFactory.cs create mode 100644 Hotfix/Chat/System/ChatUnitManageComponentSystem.cs create mode 100644 Hotfix/Gate/Handler/Inner/Chat2G_ChatMessageHandler.cs rename Hotfix/Gate/Handler/{ => Outer}/C2G_LoginRequestHandler.cs (100%) diff --git a/Config/NetworkProtocol/Inner/InnerMessage.proto b/Config/NetworkProtocol/Inner/InnerMessage.proto index 789a48e..9054eff 100644 --- a/Config/NetworkProtocol/Inner/InnerMessage.proto +++ b/Config/NetworkProtocol/Inner/InnerMessage.proto @@ -10,4 +10,22 @@ message G2Game_EnterRequest // IRouteRequest,Game2G_EnterResponse message Game2G_EnterResponse // IRouteResponse { int64 RoleRouteId = 1; //角色实体的路由id +} + + +///通知游戏服角色进入该聊天服 +message G2Chat_EnterRequest // IRouteRequest,Game2G_EnterResponse +{ + int64 AccountId = 1; //账号id + int64 GateRouteId = 2;//网关路由地址 +} + +message Chat2G_EnterResponse // IRouteResponse +{ + int64 RoleRouteId = 1; //角色实体的路由id +} + +message Chat2G_ChatMessage // IRouteMessage +{ + string Message = 1; //聊天内容 } \ No newline at end of file diff --git a/Entity/Chat/ChatComponent.cs b/Entity/Chat/ChatComponent.cs index 5afd10f..9ee62ac 100644 --- a/Entity/Chat/ChatComponent.cs +++ b/Entity/Chat/ChatComponent.cs @@ -1,6 +1,6 @@ using Fantasy.Entitas; -namespace Fantasy; +namespace NB.Chat; public class ChatComponent : Entity { diff --git a/Entity/Chat/ChatUnit.cs b/Entity/Chat/ChatUnit.cs index 4120d1f..6d9da62 100644 --- a/Entity/Chat/ChatUnit.cs +++ b/Entity/Chat/ChatUnit.cs @@ -1,6 +1,6 @@ using Fantasy.Entitas; -namespace Fantasy; +namespace NB.Chat; public sealed class ChatUnit : Entity { diff --git a/Entity/Chat/ChatUnitManageComponent.cs b/Entity/Chat/ChatUnitManageComponent.cs new file mode 100644 index 0000000..3d679e2 --- /dev/null +++ b/Entity/Chat/ChatUnitManageComponent.cs @@ -0,0 +1,8 @@ +using Fantasy.Entitas; + +namespace NB.Chat; + +public class ChatUnitManageComponent : Entity +{ + public readonly Dictionary ChatUnits = new(); +} \ No newline at end of file diff --git a/Entity/Generate/NetworkProtocol/InnerMessage.cs b/Entity/Generate/NetworkProtocol/InnerMessage.cs index f576f13..4c8c1e8 100644 --- a/Entity/Generate/NetworkProtocol/InnerMessage.cs +++ b/Entity/Generate/NetworkProtocol/InnerMessage.cs @@ -64,4 +64,69 @@ namespace Fantasy [ProtoMember(2)] public uint ErrorCode { get; set; } } + /// + /// 通知游戏服角色进入该聊天服 + /// + [ProtoContract] + public partial class G2Chat_EnterRequest : AMessage, IRouteRequest, IProto + { + public static G2Chat_EnterRequest Create(Scene scene) + { + return scene.MessagePoolComponent.Rent(); + } + public override void Dispose() + { + AccountId = default; + GateRouteId = default; +#if FANTASY_NET || FANTASY_UNITY + GetScene().MessagePoolComponent.Return(this); +#endif + } + [ProtoIgnore] + public Game2G_EnterResponse ResponseType { get; set; } + public uint OpCode() { return InnerOpcode.G2Chat_EnterRequest; } + [ProtoMember(1)] + public long AccountId { get; set; } + [ProtoMember(2)] + public long GateRouteId { get; set; } + } + [ProtoContract] + public partial class Chat2G_EnterResponse : AMessage, IRouteResponse, IProto + { + public static Chat2G_EnterResponse Create(Scene scene) + { + return scene.MessagePoolComponent.Rent(); + } + public override void Dispose() + { + ErrorCode = default; + RoleRouteId = default; +#if FANTASY_NET || FANTASY_UNITY + GetScene().MessagePoolComponent.Return(this); +#endif + } + public uint OpCode() { return InnerOpcode.Chat2G_EnterResponse; } + [ProtoMember(1)] + public long RoleRouteId { get; set; } + [ProtoMember(2)] + public uint ErrorCode { get; set; } + } + [ProtoContract] + public partial class Chat2G_ChatMessage : AMessage, IRouteMessage, IProto + { + public static Chat2G_ChatMessage Create(Scene scene) + { + return scene.MessagePoolComponent.Rent(); + } + public override void Dispose() + { + Message = default; +#if FANTASY_NET || FANTASY_UNITY + GetScene().MessagePoolComponent.Return(this); +#endif + } + public uint OpCode() { return InnerOpcode.Chat2G_ChatMessage; } + [ProtoMember(1)] + public string Message { get; set; } + } } diff --git a/Entity/Generate/NetworkProtocol/InnerOpcode.cs b/Entity/Generate/NetworkProtocol/InnerOpcode.cs index 0dfe652..96bcb3c 100644 --- a/Entity/Generate/NetworkProtocol/InnerOpcode.cs +++ b/Entity/Generate/NetworkProtocol/InnerOpcode.cs @@ -4,5 +4,8 @@ namespace Fantasy { public const uint G2Game_EnterRequest = 1073751825; public const uint Game2G_EnterResponse = 1207969553; + public const uint G2Chat_EnterRequest = 1073751826; + public const uint Chat2G_EnterResponse = 1207969554; + public const uint Chat2G_ChatMessage = 939534097; } } diff --git a/Hotfix/Chat/Handler/C2Chat_SendMessageRequestHandler.cs b/Hotfix/Chat/Handler/C2Chat_SendMessageRequestHandler.cs index 2907994..410b843 100644 --- a/Hotfix/Chat/Handler/C2Chat_SendMessageRequestHandler.cs +++ b/Hotfix/Chat/Handler/C2Chat_SendMessageRequestHandler.cs @@ -11,5 +11,6 @@ public sealed class Caht2C_SendMessageResponse response, Action reply) { ChatSceneHelper.Broadcast(chatUnit.Scene, request.Message); + await FTask.CompletedTask; } } \ No newline at end of file diff --git a/Hotfix/Chat/Handler/G2Chat_EnterRequestHandler.cs b/Hotfix/Chat/Handler/G2Chat_EnterRequestHandler.cs new file mode 100644 index 0000000..f3a6b0a --- /dev/null +++ b/Hotfix/Chat/Handler/G2Chat_EnterRequestHandler.cs @@ -0,0 +1,22 @@ +using Fantasy; +using Fantasy.Async; +using Fantasy.Network.Interface; +using NB.Game; + +namespace NB.Chat; + +public class G2Chat_EnterRequestHandler: RouteRPC +{ + protected override async FTask Run(Scene scene, G2Chat_EnterRequest request, Chat2G_EnterResponse response, + Action reply) + { + Log.Debug($"收到 G2Chat_EnterRequestHandler {request.AccountId}"); + + // 在缓存中检查该账号是否存在 + var chatUnitManageComponent = scene.GetComponent(); + var account = await chatUnitManageComponent.Online(scene, request.AccountId, request.GateRouteId); + + response.RoleRouteId = account.RuntimeId; + await FTask.CompletedTask; + } +} \ No newline at end of file diff --git a/Hotfix/Chat/Helper/ChatSceneHelper.cs b/Hotfix/Chat/Helper/ChatSceneHelper.cs index 9417fd2..c322d38 100644 --- a/Hotfix/Chat/Helper/ChatSceneHelper.cs +++ b/Hotfix/Chat/Helper/ChatSceneHelper.cs @@ -1,4 +1,5 @@ using Fantasy; +using Fantasy.Async; using Fantasy.Platform.Net; namespace NB.Chat; @@ -12,10 +13,11 @@ public static class ChatSceneHelper /// public static void Broadcast(Scene scene, string message) { + Log.Info("广播消息==="); //发送给所有Gate服务器,让Gate转发给其他客户端 var gateConfigs = SceneConfigData.Instance.GetSceneBySceneType(SceneType.Gate); - var sendMessage = new Chat2C_Message() + var sendMessage = new Chat2G_ChatMessage() { Message = message }; @@ -26,4 +28,34 @@ public static class ChatSceneHelper networkMessagingComponent.SendInnerRoute(config.RouteId, sendMessage); } } + + public static async FTask Online(Scene scene, long accountID, long gateRuntimeId) + { + var gameSceneConfig = GetSceneConfig(); + var gameRouteId = gameSceneConfig.RouteId; + //连接到游戏中心服 + var gameResponse = (Chat2G_EnterResponse)await scene.NetworkMessagingComponent.CallInnerRoute( + gameRouteId, new G2Chat_EnterRequest() + { + AccountId = accountID, + GateRouteId = gateRuntimeId + }); + + if (gameResponse.ErrorCode != 0) + { + return 0; + } + + return gameResponse.RoleRouteId; + } + + private static SceneConfig GetSceneConfig() + { + var gameSceneConfigs = SceneConfigData.Instance.GetSceneBySceneType(SceneType.Chat); + + return gameSceneConfigs.First(); + } + + + } \ No newline at end of file diff --git a/Hotfix/Chat/Helper/ChatUnitFactory.cs b/Hotfix/Chat/Helper/ChatUnitFactory.cs new file mode 100644 index 0000000..e41a934 --- /dev/null +++ b/Hotfix/Chat/Helper/ChatUnitFactory.cs @@ -0,0 +1,20 @@ +using Fantasy; +using Fantasy.Entitas; + +namespace NB.Chat; + +public static class ChatUnitFactory +{ + /// + /// 创建一个新的Player + /// + /// + /// ToKen令牌传递过来的aId + /// 是否在创建的过程中保存到数据库 + /// + public static ChatUnit Create(Scene scene, long aId) + { + var player = Entity.Create(scene, aId, true, true); + return player; + } +} \ No newline at end of file diff --git a/Hotfix/Chat/System/ChatUnitManageComponentSystem.cs b/Hotfix/Chat/System/ChatUnitManageComponentSystem.cs new file mode 100644 index 0000000..62c26fa --- /dev/null +++ b/Hotfix/Chat/System/ChatUnitManageComponentSystem.cs @@ -0,0 +1,75 @@ +using Fantasy; +using Fantasy.Async; +using NB.Game; + +namespace NB.Chat; + +public static class ChatUnitManageComponentSystem +{ + #region 上线下线 + + /// + /// 玩家上线 + /// + /// + /// + /// + /// + public static async FTask Online(this ChatUnitManageComponent self, Scene scene, long accountId, + long gateRouteId) + { + if (!self.TryGet(accountId, out var account)) + { + account = ChatUnitFactory.Create(scene, accountId); + self.Add(account); + } + + account.GateRouteId = gateRouteId; + + await FTask.CompletedTask; + + return account; + } + + public static async FTask Offline(this ChatUnitManageComponent self, Scene scene, long accountId) + { + self.Remove(accountId); + await FTask.CompletedTask; + } + + #endregion + + #region 获取&移除 + + public static void Add(this ChatUnitManageComponent self, ChatUnit account) + { + self.ChatUnits.Add(account.Id, account); + } + + public static ChatUnit? Get(this ChatUnitManageComponent self, long accountId) + { + return self.ChatUnits.GetValueOrDefault(accountId); + } + + public static bool TryGet(this ChatUnitManageComponent self, long accountId, out ChatUnit? account) + { + return self.ChatUnits.TryGetValue(accountId, out account); + } + + public static void Remove(this ChatUnitManageComponent self, long accountId, bool isDispose = true) + { + if (!self.ChatUnits.Remove(accountId, out var account)) + { + return; + } + + if (!isDispose) + { + return; + } + + account.Dispose(); + } + + #endregion +} \ No newline at end of file diff --git a/Hotfix/Game/Helper/GameSceneHelper.cs b/Hotfix/Game/Helper/GameSceneHelper.cs index 993db41..6116ad5 100644 --- a/Hotfix/Game/Helper/GameSceneHelper.cs +++ b/Hotfix/Game/Helper/GameSceneHelper.cs @@ -1,5 +1,6 @@ using System.Net; using Fantasy; +using Fantasy.Async; using Fantasy.Network; using Fantasy.Platform.Net; @@ -7,10 +8,30 @@ namespace NB.Game; public static class GameSceneHelper { - public static SceneConfig GetSceneConfig(Session session) + private static SceneConfig GetSceneConfig() { var gameSceneConfigs = SceneConfigData.Instance.GetSceneBySceneType(SceneType.Game); return gameSceneConfigs.First(); } + + public static async FTask Online(Scene scene, long accountID, long gateRuntimeId) + { + var gameSceneConfig = GetSceneConfig(); + var gameRouteId = gameSceneConfig.RouteId; + //连接到游戏中心服 + var gameResponse = (Game2G_EnterResponse)await scene.NetworkMessagingComponent.CallInnerRoute( + gameRouteId, new G2Game_EnterRequest() + { + AccountId = accountID, + GateRouteId = gateRuntimeId + }); + + if (gameResponse.ErrorCode != 0) + { + return 0; + } + + return gameResponse.RoleRouteId; + } } \ No newline at end of file diff --git a/Hotfix/Gate/Handler/Inner/Chat2G_ChatMessageHandler.cs b/Hotfix/Gate/Handler/Inner/Chat2G_ChatMessageHandler.cs new file mode 100644 index 0000000..a228fef --- /dev/null +++ b/Hotfix/Gate/Handler/Inner/Chat2G_ChatMessageHandler.cs @@ -0,0 +1,24 @@ +using Fantasy; +using Fantasy.Async; +using Fantasy.Network.Interface; + +namespace NB.Gate; + +public class Chat2G_ChatMessageHandler : Route +{ + protected override async FTask Run(Scene scene, Chat2G_ChatMessage message) + { + var chatMessage = new Chat2C_Message() + { + Message = message.Message, + }; + + var gateUnitManage = scene.GetComponent(); + foreach (var session in gateUnitManage.ForEachUnitSession()) + { + session.Send(chatMessage); + } + + await FTask.CompletedTask; + } +} \ No newline at end of file diff --git a/Hotfix/Gate/Handler/C2G_LoginRequestHandler.cs b/Hotfix/Gate/Handler/Outer/C2G_LoginRequestHandler.cs similarity index 100% rename from Hotfix/Gate/Handler/C2G_LoginRequestHandler.cs rename to Hotfix/Gate/Handler/Outer/C2G_LoginRequestHandler.cs diff --git a/Hotfix/Gate/Helper/GateLoginHelper.cs b/Hotfix/Gate/Helper/GateLoginHelper.cs index bb8b844..b7e4e6d 100644 --- a/Hotfix/Gate/Helper/GateLoginHelper.cs +++ b/Hotfix/Gate/Helper/GateLoginHelper.cs @@ -1,16 +1,18 @@ using Fantasy; using Fantasy.Async; using Fantasy.Network; +using NB.Chat; using NB.Game; namespace NB.Gate; public static class GateLoginHelper { + #region 上线 + /// /// 网关通知其他服务器上线 /// - /// /// public static async FTask Online(GateUnit gateUnit) { @@ -39,29 +41,34 @@ public static class GateLoginHelper gateUnitSessionComponent.AccountID = gateUnit.AccountID; - //安排服务器,并通知进入 - var gameSceneConfig = GameSceneHelper.GetSceneConfig(session); - var gameRouteId = gameSceneConfig.RouteId; - //连接到游戏中心服 - var gameResponse = (Game2G_EnterResponse)await session.Scene.NetworkMessagingComponent.CallInnerRoute( - gameRouteId, new G2Game_EnterRequest() - { - AccountId = gateUnit.AccountID, - GateRouteId = session.RuntimeId - }); - if (gameResponse.ErrorCode != 0) + //安排游戏服务器,并通知进入 + var gameRouteId = await GameSceneHelper.Online(session.Scene, gateUnit.AccountID, session.RuntimeId); + if (gameRouteId <= 0) { return ErrorCode.OnlineSceneFailed; } - - routeComponent.AddAddress(RouteType.GameRoute, gameResponse.RoleRouteId); + Log.Info($"连接游戏服成功,gameRouteId:{gameRouteId}"); + routeComponent.AddAddress(RouteType.GameRoute, gameRouteId); gateUnit.GameSceneRouteId = gameRouteId; - + + // //安排进入的聊天服 + var chatRouteId = await ChatSceneHelper.Online(session.Scene, gateUnit.AccountID, session.RuntimeId); + if (chatRouteId <= 0) + { + return ErrorCode.OnlineSceneFailed; + } + routeComponent.AddAddress(RouteType.ChatRoute, chatRouteId); + gateUnit.ChatSceneRouteId = chatRouteId; + Log.Info($"连接聊天服成功,gameRouteId:{gameRouteId}"); return ErrorCode.Successful; } + #endregion + + #region 下线 + /// /// 网关通知其他服务器下线 /// @@ -69,7 +76,11 @@ public static class GateLoginHelper /// public static async FTask Offline(GateUnit gateUnit) { + await FTask.CompletedTask; //通知服务器下线 return ErrorCode.Successful; } + + #endregion + } \ No newline at end of file diff --git a/Hotfix/Gate/System/GateUnitManageComponentSystem.cs b/Hotfix/Gate/System/GateUnitManageComponentSystem.cs index cd3c4cd..a0efea5 100644 --- a/Hotfix/Gate/System/GateUnitManageComponentSystem.cs +++ b/Hotfix/Gate/System/GateUnitManageComponentSystem.cs @@ -52,4 +52,19 @@ public static class GateUnitManageComponentSystem unit.Dispose(); } } + + /// + /// 回话迭代器 + /// + /// + /// + public static IEnumerable ForEachUnitSession(this GateUnitManageComponent self) + { + foreach (var (_, gateUnit) in self.Units) + { + Session gateSession = gateUnit.Session; + if (gateSession == null) continue; + yield return gateSession; + } + } } \ No newline at end of file diff --git a/Hotfix/Gate/System/JWT/GateJWTComponentSystem.cs b/Hotfix/Gate/System/JWT/GateJWTComponentSystem.cs index 720052b..6b57a61 100644 --- a/Hotfix/Gate/System/JWT/GateJWTComponentSystem.cs +++ b/Hotfix/Gate/System/JWT/GateJWTComponentSystem.cs @@ -28,8 +28,8 @@ public static class GateJWTComponentSystem ValidateIssuer = true, // 验证发行者 ValidateAudience = true, // 验证受众 ValidateIssuerSigningKey = true, // 验证签名密钥 - ValidIssuer = "Fantasy", // 有效的发行者 - ValidAudience = "Fantasy", // 有效的受众 + ValidIssuer = "NoBug", // 有效的发行者 + ValidAudience = "NoBug", // 有效的受众 IssuerSigningKey = new RsaSecurityKey(rsa) // RSA公钥作为签名密钥 }; } diff --git a/Hotfix/OnSceneCreate_Init.cs b/Hotfix/OnSceneCreate_Init.cs index 0a5cc6a..fa70832 100644 --- a/Hotfix/OnSceneCreate_Init.cs +++ b/Hotfix/OnSceneCreate_Init.cs @@ -2,6 +2,7 @@ using Fantasy.Async; using Fantasy.Event; using NB.Authentication; +using NB.Chat; using NB.Game; using NB.Gate; @@ -37,6 +38,12 @@ public class OnSceneCreate_Init : AsyncEventSystem scene.AddComponent(); break; } + case SceneType.Chat: + { + //用于管理玩家的组件 + scene.AddComponent(); + break; + } } await FTask.CompletedTask; diff --git a/Server.sln.DotSettings.user b/Server.sln.DotSettings.user index 08fab59..c758943 100644 --- a/Server.sln.DotSettings.user +++ b/Server.sln.DotSettings.user @@ -1,6 +1,7 @@  ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded @@ -32,6 +33,7 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded @@ -43,6 +45,7 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded @@ -70,4 +73,5 @@ ForceIncluded ForceIncluded ForceIncluded + VISIBLE_FILES \ No newline at end of file