# 捕鱼游戏模块(FishGame)—— 功能与代码目录文档 > 本文档为「捕鱼游戏模块(FishGame)」的完整上下文说明,供其他对话/开发者在不阅读源码的情况下理解该模块的定位、职责、核心业务流程、项目结构、代码目录与模块间交互。文档内容全部基于对真实源代码的通读整理,未读到的内容不作臆测。 --- ## 一、平台背景与模块位置 ### 1.1 平台总览 本平台是一套「捕鱼 + 棋牌」游戏运营平台后端,解决方案文件为 `Template0524.sln`(位于仓库根目录 `d:\BUYUHouDuanNet\BuYu`)。 技术栈(依据各项目 `.csproj` 与配置核对): - 运行时/框架:**.NET 8**(`net8.0`,`Microsoft.NET.Sdk.Web` / `Microsoft.NET.Sdk`) - 数据存储:**MongoDB**(`MongoRepository` / `MongoDB.Driver`,`[BsonCollection(..., "data_0524")]`) - 缓存:**Redis**(`StackExchange.Redis`、`RedisService`、`RedisHelper`) - 消息队列:**RabbitMQ**,通过 **DotNetCore.CAP**(`DotNetCore.CAP` + `.RabbitMQ` + `.PostgreSql` + `.Dashboard`)封装发布/订阅 - 实时通信:**SignalR**(`Microsoft.AspNetCore.SignalR`,JSON 协议 + `MessagePack` 协议包引用) - 网关:**Ocelot**(`Gateway\ocelot.json`,BaseUrl `http://localhost:8001`) - 日志:**NLog**(`NLog.Web.AspNetCore` + 根目录 `nlog.config`) - DI:**Autofac**(`Autofac` + `Autofac.Extensions.DependencyInjection`) - 对象映射:**AutoMapper** ### 1.2 网关路由(来自 `Gateway\ocelot.json`) 网关全局 BaseUrl:`http://localhost:8001`。各上游路径映射到的下游服务与端口如下: | 上游路径(网关) | 下游路径模板 | 下游端口 | 对应服务 | | --- | --- | --- | --- | | `/adminapi/{everything}` | `/adminapi/{everything}` | 5241 | AdminHost | | `/api/{everything}` | `/api/{everything}` | 5245 | UserHost | | `/loginhub/{everything}` | `/loginhub/{everything}` | 5245 | UserHost | | `/customerapi/{everything}` | `/customerapi/{everything}` | 5247 | CustomerHost | | `/customerHub/{everything}` | `/customerHub/{everything}` | 5247 | CustomerHost | | `/chess/{everything}` | `/chess/{everything}` | 5242 | ChessGameHost | | `/chessgamehub/{everything}` | `/chessgamehub/{everything}` | 5242 | ChessGameHost | | `/fishingroomhub/{everything}` | `/fishingroomhub/{everything}` | **5244** | **FishRoomHost(本模块·房间层)** | | `/gamehub/{everything}` | **`/fishinghub/{everything}`** | **5248** | **FishGameHost(本模块·对局层)** | > 注意:ocelot 中捕鱼「对局层」的上游是 `/gamehub`,下游实际转发到 FishGameHost 的 `/fishinghub`(端口 5248)。这是本模块一个容易混淆的点。 ### 1.3 本模块两个进程入口 本模块由两个独立进程(微服务)构成: - **房间层:`FishGameSrc\FishRoomHost`** —— 监听端口 **5244**,SignalR Hub 路径 **`/fishingroomhub`**(网关上游同名),负责大厅房间列表、房间初始化、房间分组广播等。 - **对局层:`FishGameSrc\FishGameHost`** —— 网关侧端口 **5248**,SignalR Hub 路径 **`/fishinghub`**(网关上游为 `/gamehub`),负责进房、对局(开炮/击杀)、出鱼、结算、掉线重连等核心玩法逻辑。 两个进程各自引用一个类库: - `FishGameSrc\FishGameService`(被 FishGameHost 引用,承载对局层业务逻辑) - `FishRoomService`(位于仓库根目录,被 FishRoomHost 引用,承载房间层业务逻辑) --- ## 二、模块简介 ### 2.1 定位与职责 捕鱼游戏模块是整个运营平台的「捕鱼玩法」业务域,划分为 **房间层** 与 **对局层** 两层职责: - **房间层(FishRoomHost + FishRoomService)** - 维护「大区/分区 → 房间列表」,按后台下发的 `GameConfig`(房间配置)批量生成房间,并结合「空房率配置(EmptyRoomRateConfig)」与「机器人配置(BotConfig)」决定每个房间预置的机器人数量。 - 玩家在大厅请求房间列表时,将其连接加入一个「分区 SignalR 分组」,并单独推送房间列表。 - 订阅「房间变化」消息,向对应分区分组广播房间状态变化;订阅「用户资产同步前端」消息,向玩家推送资产变更。 - **对局层(FishGameHost + FishGameService)** - 玩家从大厅进入某个房间 → 连接到对局层 Hub(`/fishinghub`)→ 绑定用户 → 加入房间(占座、生成玩家对象、推送房间信息与活跃鱼)→ 对局(开炮、击杀、道具、鱼雷、炮倍切换、挂机)→ 离房/掉线结算。 - 由后台服务 `FishSpawnService` 负责每个房间的「出鱼」(按概率配置按类型/航线定时刷鱼)、活跃鱼快照、出鱼权租约、命中校验与击杀标记;`RobotKillAnnounceService` 负责按配置定时伪造「机器人爆金击杀」全局公告。 ### 2.2 核心业务流程(以代码为准) 1. **服务启动初始化房间(房间层)** - `FishRoomHost\Program.cs` 启动时,若 `IRedisService.GetGameRoomAllList()` 为空,则调用 `IFishingRoomService.InitRoom()` 初始化房间。房间初始化失败会记录日志并抛出(`throw`)。 2. **大厅 → 房间列表(房间层)** - 客户端连接 `/fishingroomhub`,调用 Hub 方法 `GetRoomList(userId, gameType, roomLevel, roomPartition)`。 - `FishingRoomService.GetRoomList` 计算分区字符串 `partition = $"{(int)gameType}{roomLevel}{roomPartition}"`;写入/更新 `RedisUserCid`(含 `PartitionId`、`FishRoomCId`、`CId`);把当前连接加入该分区的 SignalR 分组;读取该分区房间列表,若为空则即时 `InitRoom(...)` 生成;最后通过 `FishingRoomSendService.GetRoomListResult` 单独回推 `GetRoomListResult`(按 `RoomNumber` 排序)。 - 另有 `GetRoomInfo(roomId)` 直接从 Redis 读取单个房间回推 `GetRoomInfoResult`。 3. **房间初始化(房间层,`InitRoom`)** - 依据 `GameConfig.RoomConfigs`(可用 `gameType`/`roomLevel` 过滤)逐条房间配置,遍历 `RoomPartitionNum × RoomCount` 生成 `RedisGameRoom`。 - 读取该 GameType/RoomLevel 的 `EmptyRoomRateConfig`(空房率);结合 `GameConfig.BotConfig.Enabled`:机器人关闭时空房率为 100%(无机器人房间);否则按 `100 - EmptyRoomRate` 的比例随机挑选要预置机器人的房间,`RobotCount = Random(1, MaxPlayerCount)`。 - 每生成一个房间前先 `RemoveGameRoom(partition)`(清除旧数据)再重建;`RoomId = $"{(int)GameType}{RoomLevel}{RoomPartition}{c:00}"`。 - 房间上限:`星际迷航`/`中国象棋` 为 2 人,其余为 4 人(`MaxPlayerCount`)。 - `RoomBotFactory.FixedBotSeats` 当前为空数组,故 `FixedBotSeatsEnabled == false`,固定座位机器人逻辑(`CreateFixedSeatBots`)当前不会生效。 - 最后逐个 `SetGameRoom` 写回 Redis。 4. **进房(对局层,`FishingGameService.JoinRoom`)** - 若玩家此前在其它房间,先 `SettleGoldAsync` 结算旧房间金币。 - 从 Redis 取房间;若房间不存在则以默认「新手渔场(风雷之渊/1)」房间创建兜底。 - 已有玩家(重连/重复加入):刷新座位 CId、重置 State、必要时接管房主,推送 `RoomInfo`、`OnPlayerInfo`、`SendRoomChange` 后返回。 - 新玩家:校验座位(固定座位、手动选座权限 `SeatSelectLimit`:3=全部可手选,1=VIP,2=代理),校验 `RoomGoldLimit` 金币门槛;构建 `RedisGamePlayer`(金币、钻石、炮台/翅膀/战神、初始炮倍、`BeginCoin`、`PlayerFactor` 等)加入房间;`CurrentOnlinePlayerCount++`、加入房间分组、设置房主。 - 依据 `BotConfig` 决定是否创建机器人(`CreateRoomBots`)或移除机器人;随后推送 `RoomInfo`(含活跃鱼)、`RoomJoinNotice`、`OnSeatChange(join)`、`OnPlayerInfo`,并 `SendRoomChange`(CAP 发布「房间变化」)。 5. **对局中(对局层)** - **开炮 `FireCannon`**:校验签名与时间窗、玩家身份、金币、扣费、生成子弹 Id 存入 `BulletTracker`、广播 `RoomFireNotice`、累加消耗进度与「开炮任务」进度。 - **击杀 `KillFish`**:校验签名/子弹/鱼命中(`FishSpawnService.ValidateFishHit`);按玩家因子(`PlayerFactor`)、系统因子、鱼 `KillWeight` 加权随机判定是否击杀;击杀后计算爆金(`CalcSkillGold`,支持 Boss 轮盘/扑克/飞盘/全屏/范围/概率/星际巡航/烈焰风暴/炸弹/机械蝎/神龙等玩法)、掉落、经验、任务进度,并处理补偿/罚款配额;广播 `RoomKillNotice`;超阈值爆金触发全局击杀公告(CAP 发布「全局击杀公告」+ Redis 频道广播)。 - **道具/鱼雷**:`UseProp`(消耗钻石或背包道具,`40003` 触发冻结鱼 `FishFrozen`,`40004` 触发狂暴任务)、`UseTorpedo`(按权重抽奖加金币)。 - **炮倍/挂机/信息**:`ChangeGunMultiple`、`SetPlayerAfk`/`CancelPlayerAfk`、`GetPlayerInfo`。 - **出鱼**:`FishSpawnService` 以 1 秒 Tick 驱动机器人房间出鱼逻辑,并通过 Redis 租约(`fish:spawn:owner:{roomId}`)保证同一房间只有一台实例出鱼,快照写 `fish:spawn:snapshot:{roomId}` 供无租约实例读取。 6. **离房 / 掉线 / 结算(对局层)** - **主动离房 `LeaveRoom`**:在分布式锁 `lock:fish:gold:{roomId}:{userId}` 下,先「标记离房(State=2)」,再在满足条件时执行 `LeaveRoomInternal`(累加在线时长、结算钓鱼进度与 `GameCoinsSettlement`、清理运行时数据、移除玩家、房主转移、`NormalizeRoomPlayerCounts`、无人时清空并 `UnregisterRoom`、广播 `OnSeatChange(leave)`/`RoomLeaveNotice`、`SendRoomChange`)。 - **掉线 `HandleDisconnect`**:玩家 State 置 1,房主转移;启动 60 秒延迟任务;超时后 `OnDisconnectTimeoutInternal` 结算并清理房间。 - **重连 `Reconnect` / `JoinRoom`**:恢复连接、取消待掉线定时器、恢复座位与房主、补发活跃鱼同步。 7. **结算(结算链)** - `TryFlushFishingSettlement` → `GameCoinsSettlement`(记录本局金币变化),`TryFlushFishingProgress` 结算经验(`UpdateAssets`)与消耗记录(`RecordFishingConsume`),`FlushFishingTaskProgress` 发布各「任务完成」事件。 --- ## 三、业务功能清单 ### 3.1 房间层(FishRoomHost / FishRoomService) **SignalR Hub:`FishRoomService\Hubs\FishRoomHub.cs`(挂载于 `/fishingroomhub`)** | 类型 | 名称 | 说明 | | --- | --- | --- | | Hub 方法 | `OnConnectedAsync` / `OnDisconnectedAsync` | 仅透传基类实现 | | Hub 方法 | `GetRoomList(userId, gameType, roomLevel, roomPartition)` | 大厅请求房间列表(含分组加入与即时初始化) | | Hub 方法 | `GetRoomInfo(roomId)` | 读取单房间并回推 `GetRoomInfoResult` | | 服务端推送 | `GetRoomListResult` | 房间列表结果(`GameRoomReponse` 列表) | | 服务端推送 | `GetRoomInfoResult` | 单房间信息 | | 服务端推送 | `RoomChange` | 房间变化广播(向分区分组) | | 服务端推送 | `AssetUpdated` | 用户资产变更推送 | **业务服务** | 接口/类 | 职责 | | --- | --- | | `IFishingRoomService` / `FishingRoomService` | `GetRoomList`(大厅房间列表)、`InitRoom`(按配置初始化房间) | | `IFishingRoomSendService` / `FishingRoomSendService` | `GetRoomListResult`(回推列表)、`RoomChange`(向分区分组广播) | | `IRoomMQService` / `RoomMQService`(实现 `ICapSubscribe`) | 订阅「房间变化」与「用户资产同步前端」 | **消息订阅者(CAP)** | 订阅方法 | 主题(`TopicKeys`) | 行为 | | --- | --- | --- | | `RoomMQService.RoomChange` | `房间变化` = `Topic_0524_RoomChage` | 调用 `FishingRoomSendService.RoomChange`,向房间分区分组广播 `RoomChange` | | `RoomMQService.UserAssetSync` | `用户资产同步前端` = `Topic_0524_UserAssetSyncFrontend` | 按 `RedisUserCid`(`FishRoomCId`/`CId`)定位连接,推送 `AssetUpdated` | **HTTP 控制器**:无(房间层仅 Hub + MQ)。 ### 3.2 对局层(FishGameHost / FishGameService) **SignalR Hub:`FishGameService\Hubs\FishGameHub.cs`(挂载于 `/fishinghub`)** | 类型 | 名称 | 说明 | | --- | --- | --- | | Hub 方法 | `OnConnectedAsync` | 建立连接(异常记录日志) | | Hub 方法 | `OnDisconnectedAsync` | 断线处理(调用 `HandleDisconnect`) | | Hub 方法 | `Reconnect(userId)` | 重连恢复(座位、房主、活跃鱼同步) | | Hub 方法 | `JoinRoom(roomId, userId, posituin)` | 加入房间 | | Hub 方法 | `GetRoomInfo(roomId)` | 读取房间并回推 `GetRoomInfoResult`(需连接在房) | | Hub 方法 | `SyncGameData(roomId, data)` | 房间内同步自定义数据 | | Hub 方法 | `UseProp(roomId, userId, propNumber, diamond)` | 使用道具,返回剩余数量 | | Hub 方法 | `UseTorpedo(roomId, userId, propNumber)` | 使用鱼雷,返回金币 | | Hub 方法 | `FireCannon(roomId, userId, gold, count, timestamp, sign, extra)` | 开炮,返回投递的子弹 Id 列表与金币 | | Hub 方法 | `KillFish(roomId, userId, fishNumber, fihsId, gold, timespan, bulletId, timestamp, sign)` | 击杀鱼,返回当前金币 | | Hub 方法 | `LeaveRoom(roomId, userId)` | 主动离房 | | Hub 方法 | `ChangeGunMultiple(roomId, userId, multiple)` | 切换炮倍 | | Hub 方法 | `GetPlayerInfo(roomId, userId)` | 请求玩家信息 | | Hub 方法 | `SetPlayerAfk` / `CancelPlayerAfk` | 挂机 / 取消挂机 | | Hub 方法 | `BotFireCannon` / `BotKillFish` | 机器人开炮 / 击杀(返回子弹 Id / 无返回) | | 服务端推送 | `RoomInfo` | 房间信息(含活跃鱼 `activeFishes`) | | 服务端推送 | `OnFishSpawn` | 出鱼/首屏鱼同步(`type = init/spawn/sync`) | | 服务端推送 | `RoomKillNotice` | 房间内击杀公告(含倍数、掉落、玩法结果 param) | | 服务端推送 | `RoomFireNotice` | 开炮广播 | | 服务端推送 | `RoomJoinNotice` / `RoomLeaveNotice` / `BotLeaveRoomNotice` | 加入/离开/机器人离开 | | 服务端推送 | `RoomDisconnectNotice` / `HostDisconnect` | 断线通知 / 房主断线 | | 服务端推送 | `ChangeControllerUser` | 房主变更 | | 服务端推送 | `OnSeatChange` | 座位变化(join/leave) | | 服务端推送 | `OnPlayerInfo` | 本玩家信息(金币、钻石、炮倍、炮台、翅膀、座位等) | | 服务端推送 | `SyncPlayerGold` / `SendPlayerInfoResult` | 金币同步 / 玩家信息结果 | | 服务端推送 | `ChangeGunMultipleNotice` / `UsePropNotice` / `TorpedoResultNotice` | 炮倍/道具/鱼雷结果 | | 服务端推送 | `PlayerAfkNotice` / `PlayerCancelAfkNotice` | 挂机状态 | | 服务端推送 | `Exception` / `BindSuccess` / `KickToMainPage` | 错误 / 绑定成功 / 踢回主页 | | 服务端推送 | `AssetUpdated` | 资产变更(道具消耗等) | | 服务端推送 | `FishFrozen` / `SummonCardFishNotice` | 冻结鱼 / 召唤卡出鱼 | | 全局推送 | `KillNotice` | 经 Redis 频道 `fishgame:global` 广播的全服击杀公告 | **HTTP 控制器(`FishGameHost\Controllers`)** | 控制器 | 路由 | 方法 | 说明 | | --- | --- | --- | --- | | `TimeController` | `fishapi/Time/GetDateTime` | GET | 返回服务端时间/时间戳/时区/容器名(供客户端校时) | | `RoomController` | `api/Room/QuickJoin` | GET | 按 `gameType`/`level` 从未满房间随机快速匹配,返回 `RoomId` 与 WebSocket 地址 | | `RoomController` | `api/Room/Assign` | GET | 按 `roomId` 返回求 WebSocket 地址(读取配置 `GameServerInstances`) | | `PlayerController` | `api/Player/login` | POST | 演示用登录:生成 JWT(`uid` 倒序 + `uname`),返回固定玩家数据 | **后台服务** | 服务 | 基类 | 职责 | | --- | --- | --- | | `FishSpawnService` | `BackgroundService`(同时注册为 `IHostedService`) | 房间出鱼主循环:租约、刷鱼、活跃鱼快照、命中/击杀校验、系统因子同步、冻结延时、临时/召唤卡出鱼 | | `RobotKillAnnounceService` | `BackgroundService` | 按 `RobotKillConfig` 定时(最小 30 秒)伪造机器人爆金击杀并发布「全局击杀公告」;仅 `INSTANCE_ID` 为 `1` 或 `default` 的实例运行 | | `GlobalBroadcastSubscriber`(`FishGameHost\Services`) | `BackgroundService` | 订阅 Redis 频道 `fishgame:global`,按 `Target=All` 或 `Room` 通过 Hub 广播事件 | **消息订阅者(CAP)** | 订阅方法 | 主题(`TopicKeys`) | 行为 | | --- | --- | --- | | `PlayerFactorSubscriber.HandlePlayerFactorChanged` | `因子变更` = `Topic_0524_PlayerFactorChanged` | 清理本地玩家因子缓存,并把最新因子同步到 Redis 房间与玩家 | | `PlayerFactorSubscriber.HandleConfigChanged` | `配置变更` = `Topic_0524_ConfigChanged` | 清空配置缓存、失效出鱼配置、重载所有房间配置 | | `LoginBindSubscriber.HandleLoginBind` | `登录绑定` = `Topic_0524_LoginBind` | 结算并清理玩家在房状态,回发「登录结果通知」 | | `LoginBindSubscriber.HandleDismissPendingRoom` | `拒绝回房` = `Topic_0524_DismissPendingRoom` | 强制执行 `CleanupRoomAsync(userId, force: true)` | | `BackgroundAssetSubscriber.HandleNotify` | `BackgroundOperation.NotifyUser` | 后台加减金币(仅 `CurrencyType==1`),分布式锁下更新房间内玩家金币并 `SyncPlayerGold` | | `TempSpawnFishSubscriber.HandleTempSpawnFish` | `临时强制出鱼` = `Topic_0524_TempSpawnFish` | 调用 `FishSpawnService.SpawnTemporaryFish` | | `TempSpawnFishSubscriber.HandleSummonCardFish` | `召唤卡出鱼` = `Topic_0524_SummonCardFish` | 调用 `SpawnSummonCardFish` 并推送 `SummonCardFishNotice` | **对局层对外发布的消息** | 发布者 | 主题(`TopicKeys`) | 触发点 | | --- | --- | --- | | `FishingGameService.SendRoomChange` | `房间变化` = `Topic_0524_RoomChage` | 进房/离房/清理房间等(`PublishAsync`) | | `FishingGameService.UseProp` / `UseTorpedo` | `用户资产变更` = `Topic_0524_UserAssetsChanged` | 消耗钻石/背包道具/鱼雷(`Publish`) | | `FishingGameService.FishKillControl` | `全局击杀公告` = `Topic_0524_GlobalKillAnnounce` | 房间内爆金达到阈值 | | `FishingGameService.FlushFishingTaskProgress` | `任务完成` = `Topic_0524_CompletedTask` | 离房/结算时汇总任务进度 | | `RobotKillAnnounceService` | `全局击杀公告` = `Topic_0524_GlobalKillAnnounce` | 定时伪造机器人爆金 | | `LoginBindSubscriber.HandleLoginBind` | `登录结果通知` = `Topic_0524_LoginBindResult` | 登录结算成功/失败回执 | > 说明:对局层 Hub 的 `KillNotice` 还有一条「非 CAP」的广播通道——`FishingSendService.KillNotice` 通过 `IConnectionMultiplexer` 向 Redis 频道 `fishgame:global` 发布 JSON 消息,由 `GlobalBroadcastSubscriber` 消费后经 Hub 下发。 --- ## 四、项目结构与技术要点 ### 4.1 各项目 csproj(框架版本与依赖) | 项目 | 相对路径 | SDK/TFM | 项目引用 | 关键 NuGet | | --- | --- | --- | --- | --- | | FishRoomHost | `FishGameSrc\FishRoomHost\FishRoomHost.csproj` | `Microsoft.NET.Sdk.Web` / `net8.0` | `FishRoomService`、`Infrastructure\CommonInfrastructure`、`Infrastructure\SharpAbp.Infrastructure.Api` | SignalR.StackExchangeRedis 8.0.0、StackExchange.Redis 2.7.4、NLog.Web.AspNetCore 6.1.2、Autofac 8.3.0、AutoMapper 14.0.0、DotNetCore.CAP(.Dashboard/.PostgreSql/.RabbitMQ) 8.3.4、SignalR.Protocols.MessagePack 8.0.17 | | FishGameHost | `FishGameSrc\FishGameHost\FishGameHost.csproj` | `Microsoft.NET.Sdk.Web` / `net8.0` | `FishGameService`、`Infrastructure\CommonInfrastructure`、`Infrastructure\SharpAbp.Infrastructure.Api` | StackExchange.Redis 2.7.4、SignalR.Protocols.MessagePack 8.0.0、NLog.Web.AspNetCore 6.1.2、Autofac 8.3.0、AutoMapper 14.0.0、DotNetCore.CAP(.Dashboard/.PostgreSql/.RabbitMQ) 8.3.4 | | FishGameService | `FishGameSrc\FishGameService\FishGameService.csproj` | `Microsoft.NET.Sdk` / `net8.0`(类库) | `CommonDomain`、`CommonService`、`RedisService`、`UserSrc\UserService` | AutoMapper 14.0.0、DotNetCore.CAP 8.3.4 | | FishRoomService | `FishRoomService\FishRoomService.csproj` | `Microsoft.NET.Sdk` / `net8.0`(类库) | `CommonService`、`RedisService`、`UserSrc\UserService` | AutoMapper 14.0.0、DotNetCore.CAP 8.3.4、Microsoft.AspNetCore.SignalR.Core 1.2.9 | 三个 Host/Service 项目均以 `None` 方式引入根目录 `nlog.config`,并拷贝 `docker-compose.yaml`、`Dockerfile` 到输出目录。 ### 4.2 两个进程入口要点 **FishRoomHost\Program.cs** - 设置环境变量 `SERVICE_NAME`、`INSTANCE_ID`(默认 `default`),并注册单例 `AppInstanceId`。 - 配置加载顺序:默认 `appsettings*.json` 之后追加 `Config\system.json`(`builder.Configuration.AddJsonFile(Path.Combine("Config", "system.json"), optional: true)`)。 - 绑定 `MongoDbSettings`(`IOptions` + `IMongoDbSettings`)。 - Redis 连接串优先取 `ConnectionStrings:Redis`,否则由 `RedisConfig`(Host/Port/Password/Database)拼装,注册单例 `IConnectionMultiplexer`。 - SignalR:`MaximumReceiveMessageSize = 64KB`、`StreamBufferCapacity = 512`、`ClientTimeoutInterval = 60s`、`KeepAliveInterval = 5s`,注册 Hub 过滤器 `MovementFilter` 与 `HubExceptionFilter`,使用 `.AddJsonProtocol()`。 - 其他注册:`FormOptions` 上传上限 16MB、内存缓存、`DatetimeJsonConverter`、`IHttpContextAccessor`、`IHubSend`、`IRequestApi`、`AddAutoMapper(typeof(AutoMapperConfig))`、健康检查 `self`、CORS(`Cors` 策略,允许任意源+凭证)、`AddCustomJwt`、`AddRedisCacheSingleton`。 - Autofac:`UseServiceProviderFactory` + `RegisterModule()`。 - CAP:`builder.Services.AddCap(builder.Configuration)`(见 4.4)。 - 管道:`UseApiLogging` → `UseRouting` → `UseGlobalExceptionHandler` → `UseStaticFiles` → `UseCors("Cors")` → `UseAuthentication` → `UseAuthorization` → `MapHub("/fishingroomhub", WebSockets)` → `MapControllers` → `MapHealthChecks("/health")`。 - 启动后若房间列表为空则 `InitRoom()`。 **FishGameHost\Program.cs** - 与 FishRoomHost 结构基本一致(环境变量、`AppInstanceId`、配置、Redis、SignalR、CORS、JWT、RedisCache)。 - 额外注册 `BulletConfig`(`GetSection("BulletConfig")`)。 - CAP 相关:显式注册 4 个 `ICapSubscribe` 订阅者(`PlayerFactorSubscriber`、`LoginBindSubscriber`、`BackgroundAssetSubscriber`、`TempSpawnFishSubscriber`),再 `AddCap`。 - 后台服务:`AddHostedService()`、`AddHostedService()`(`FishSpawnService` 在 AutofacModule 中注册为单例 `IHostedService`)。 - 管道:`MapHub("/fishinghub", WebSockets)`。 ### 4.3 DI 注册位置(AutofacModule) **FishRoomHost\Middleware\AutofacModule.cs** - 泛型注册 `MongoBaseRepository<>` → `IMongoBaseRepository<>`、`MongoBaseService<>` → `IMongoBaseService<>`(`InstancePerLifetimeScope`)。 - 注册 `RedisService` → `IRedisService`。 - 按程序集批量注册以 `Service` 结尾的类型(`ApiLogService` 所在程序集、`FishingRoomService` 所在程序集、`UserService.User.UserService` 所在程序集),`AsImplementedInterfaces`。 **FishGameHost\Middleware\AutofacModule.cs** - 上述 Mongo/Redis/批量服务注册之外,额外: - `ReconnectTracker` → `IReconnectTracker`(单例) - `BulletTracker` → `IBulletTracker`(单例) - `FishKillTracker` → `IFishKillTracker`(单例) - `FishSpawnConfigStore`(`AsSelf`,单例) - `FishSpawnService` → `AsSelf` 且 `As`(单例) - 批量注册 `Service` 结尾类型(排除 `FishSpawnService`、`RobotKillAnnounceService`)与 `Subscriber` 结尾类型(`AsSelf`)。 ### 4.4 SignalR / CAP / Redis 配置 **SignalR**:两进程均在 `Program.cs` 配置过滤器和消息包参数;Hub 均只启用 **WebSockets** 传输。房间层 `MovementFilter` 内附一个令牌桶式 `RateLimiter`(速率常量 30、间隔 33ms),但调用点目前被注释;对局层 `MovementFilter` 记录非跳过方法(`SyncGameData`、`FireCannon`、`KillFish`、`BotFireCannon`、`BotKillFish` 被跳过)的调用日志。 **CAP(两个 CapExtension.cs)**: - 均启用 `UseDashboard()`;RabbitMQ 读取 `CapConfig:Host/UserName/Password/VirtualHost`,`ExchangeName = "cap.exchange"`;存储用 PostgreSQL(`CapConfig:PGLogHost`,Schema `public`);`SucceedMessageExpiredAfter = 7*24*3600`、`FailedRetryCount = 5`、`FailedRetryInterval = 10`,并设置失败阈值回调。 - **差异**:`FishGameHost\Extension\CapExtension.cs` 额外设置 `x.DefaultGroupName = $"FishGameHost-{instanceId}"`(`INSTANCE_ID` 环境变量),用于多实例分组订阅;`FishRoomHost` 的 CapExtension 额外注册 `IRoomMQService → RoomMQService`。 **Redis**: - 房间层 `Config\system.json`:`RedisConfig` Host `localhost`、Port `6378`、Database `2`、密码 `123456`。 - 对局层 `Config\system.json`:`RedisConfig` Host `localhost`、Port `6379`、Database `1`、密码 `123456`。 - 数据存储:房间层 Mongo `mongodb://localhost:27018/?authSource=admin`;对局层 `mongodb://localhost:27017`(Database `data_buyu`)。 - CAP 存储库:两进程 PostgreSQL 均指向 `data_0524` 库。 **对局层独有配置**(`FishGameHost\Config\system.json`): ``` "BulletConfig": { "SignKey": "63215f0afa3f5b25", "MaxBulletPerUser": 100, "TimeWindowSeconds": 5 }, "GameServerInstances": [ "http://localhost/fishinghub?instance=1" ] ``` - `BulletConfig` 用于开炮/击杀签名校验(`SignHelper`:`MD5(raw + "|" + key)` 取前 8 位小写十六进制)与时间窗防重放(`TimeWindowSeconds` 默认 5 秒)。 - `GameServerInstances` 供 `RoomController` 返回 WebSocket 地址。 > 端口补充说明(以代码与配置文件实际值为准,存在多处不一致,需注意): > - 房间层 `Program.cs` 将 Hub 挂载在 `/fishingroomhub`;`Config\system.json` 中 `"urls": "http://*:8004"`;`launchSettings.json` 开发 URL 为 `http://localhost:8004`;`docker-compose.yaml`(服务名 `0524fishroom`)映射 `5244:80`;ocelot 下游指向 5244。 > - 对局层 `Program.cs` 将 Hub 挂载在 `/fishinghub`;`Config\system.json` 中 `"urls": "http://*:8003"`;`launchSettings.json` 开发 URL 为 `http://localhost:5263`;`docker-compose.yaml`(服务名 `0524fishgame`)映射 `5243:80`;ocelot 下游指向 5248。 > > 即:容器内监听 80,`docker-compose` 将房间层映射到宿主机 5244;对局层的 compose 映射到 5243,而 ocelot 指向 5248——两部分配置本身不一致,文档如实记录,未作统一。 ### 4.5 docker-compose 端口 - `FishGameSrc\FishRoomHost\docker-compose.yaml`:`name: webapi`,服务 `0524fishroom`,镜像 `0524fishroom`,`ports: 5244:80`,`restart: always`。 - `FishGameSrc\FishGameHost\docker-compose.yaml`:`name: webapi`,服务 `0524fishgame`,镜像 `0524fishgame`,`ports: 5243:80`,`restart: always`。 --- ## 五、代码目录说明 > 以下目录树覆盖 `FishGameSrc\**` 与 `FishRoomService\**` 下的全部文件夹与 `.cs/.json` 文件,并标注关键文件职责。 ### 5.1 `FishGameSrc\FishRoomHost`(房间层进程,5244 / `/fishingroomhub`) ``` FishGameSrc\FishRoomHost\ ├── Config\ │ └── system.json # 运行配置:urls=8004、JwtConfig、PgSql、Cap(RabbitMQ+PG)、RedisConfig、MongoDbSettings、WXConfig ├── Extension\ │ └── CapExtension.cs # AddCap 扩展:RabbitMQ(cap.exchange)+PostgreSQL 存储+Dashboard,并注册 IRoomMQService ├── Middleware\ │ ├── ApiLoggingMiddleware.cs # /api 请求响应日志中间件(脱敏 Data 后写 ApiLog 到 Mongo),含 UseApiLogging 扩展 │ ├── AutofacModule.cs # Autofac 注册:Mongo 泛型仓储/服务、RedisService、按程序集批量注册 Service │ ├── HubExceptionFilter.cs # SignalR Hub 异常过滤器(记录并吞掉异常,返回 null) │ └── MovementFilter.cs # SignalR Hub 过滤器(含未启用的 RateLimiter 令牌桶) ├── Properties\ │ └── launchSettings.json # 开发启动配置(applicationUrl 8004) ├── .dockerignore # Docker 忽略规则 ├── appsettings.json # 基础日志配置 ├── appsettings.Development.json # 开发日志配置 ├── docker-compose.yaml # 容器编排:0524fishroom,5244:80 ├── FishRoomHost.csproj # 房间层进程项目文件 └── Program.cs # 进程入口:DI、SignalR、CAP、JWT、Redis、MapHub(/fishingroomhub)、启动即 InitRoom ``` ### 5.2 `FishGameSrc\FishGameHost`(对局层进程,5248 / `/fishinghub`) ``` FishGameSrc\FishGameHost\ ├── Config\ │ └── system.json # urls=8003、JwtConfig、PgSql、Cap、RedisConfig、MongoDbSettings、WXConfig、BulletConfig、GameServerInstances ├── Controllers\ │ ├── PlayerController.cs # api/Player/login:演示登录签发 JWT 并返回固定玩家数据 │ ├── RoomController.cs # api/Room/QuickJoin、api/Room/Assign:快速匹配与游戏服地址分配 │ └── TimeController.cs # fishapi/Time/GetDateTime:服务端校时 ├── Extension\ │ └── CapExtension.cs # AddCap 扩展:含 DefaultGroupName=FishGameHost-{instanceId} 的多实例分组订阅 ├── Middleware\ │ ├── ApiLoggingMiddleware.cs # 同房间层,/api 日志中间件 │ ├── AutofacModule.cs # Autofac:额外注册 Tracker/ConfigStore/FishSpawnService(IHostedService)/Subscriber │ ├── HubExceptionFilter.cs # Hub 异常过滤器 │ └── MovementFilter.cs # Hub 过滤器(日志,跳过高频方法的参数打印) ├── Properties\ │ └── launchSettings.json # 开发启动配置(applicationUrl 5263) ├── Services\ │ └── GlobalBroadcastSubscriber.cs# 订阅 Redis 频道 fishgame:global,按 All/Room 经 Hub 广播(含 GlobalBroadcastMessage 定义) ├── .dockerignore # Docker 忽略规则 ├── appsettings.json # 基础日志配置 ├── appsettings.Development.json # 开发日志配置 ├── docker-compose.yaml # 容器编排:0524fishgame,5243:80 ├── FishGameHost.csproj # 对局层进程项目文件 └── Program.cs # 进程入口:DI、SignalR、CAP 订阅者注册、托管服务、MapHub(/fishinghub) ``` ### 5.3 `FishGameSrc\FishGameService`(对局层类库) ``` FishGameSrc\FishGameService\ ├── Config\ │ └── BulletConfig.cs # 开炮/击杀签名配置:SignKey、MaxBulletPerUser、TimeWindowSeconds ├── GameSend\ │ ├── IFishingSendService.cs # 对局层推送服务接口(房间信息/击杀/开炮/座位/道具等全部服务端事件) │ └── FishingSendService.cs # 实现:Hub 发送封装 + 经 Redis 频道 fishgame:global 发布 KillNotice 全局公告 ├── GameService\ │ ├── FishSpawnConfigStore.cs # 出鱼配置存储:从 Redis(GetFishSpawnConfig) 读取并按 {gameType}:{roomLevel} 缓存,缺失时从 GameConfig 提取 │ ├── FishingGameService.cs # 对局核心服务(进房/开炮/击杀/道具/鱼雷/离房/掉线/结算/因子/机器人),实现 IPendingSettlementService │ ├── IBulletTracker.cs # 子弹追踪(BulletTracker) 与 击杀标记(FishKillTracker) 接口与实现(内存,带上限 LRU) │ ├── IFishingGameService.cs # 对局核心服务接口 │ └── ReconnectTracker.cs # 重连追踪(内存 ConcurrentDictionary) ├── Hubs\ │ └── FishGameHub.cs # 对局 Hub:全部客户端方法入口与基础校验 ├── Services\ │ ├── FishSpawnService.cs # 出鱼后台服务(IHostedService):租约/刷鱼/快照/命中击杀校验/临时出鱼/冻结,含 RoomFishState、ActiveFish、SpawnFishItem │ ├── KillAnnouncePolicy.cs # 击杀公告阈值策略:gold >= minGold(默认 10,000,000) │ └── RobotKillAnnounceService.cs # 机器人爆金公告后台服务(RobotKillConfig 驱动) ├── Subscribers\ │ ├── BackgroundAssetSubscriber.cs# 订阅 BackgroundOperation.NotifyUser:后台加减金币并同步房间 │ ├── LoginBindSubscriber.cs # 订阅「登录绑定」「拒绝回房」 │ ├── PlayerFactorSubscriber.cs # 订阅「因子变更」「配置变更」 │ └── TempSpawnFishSubscriber.cs # 订阅「临时强制出鱼」「召唤卡出鱼」 ├── Utils\ │ └── SignHelper.cs # 签名工具:MD5(raw|key) 取前 8 位 + 校验 └── FishGameService.csproj # 对局层类库项目文件 ``` ### 5.4 `FishRoomService`(仓库根目录,房间层类库) ``` FishRoomService\ ├── Hubs\ │ └── FishRoomHub.cs # 房间 Hub:GetRoomList、GetRoomInfo ├── MQ\ │ ├── IRoomMQService.cs # 房间 MQ 服务接口(RoomChange) │ └── RoomMQService.cs # ICapSubscribe:订阅「房间变化」「用户资产同步前端」 ├── RoomSend\ │ ├── FishingRoomSendService.cs # 房间推送实现:GetRoomListResult、RoomChange │ ├── IFishingRoomSendService.cs # 房间推送接口 │ └── Response\ │ └── GameRoomReponse.cs # 房间列表响应 DTO(RoomId/MaxPlayerCount/CurrentOnlinePlayerCount/RobotCount/RoomNumber) ├── RoomService\ │ ├── FishingRoomService.cs # 房间业务:GetRoomList(分组+列表)、InitRoom(按配置+空房率+机器人初始化) │ └── IFishingRoomService.cs # 房间业务接口 ├── AutoMapperConfig.cs # AutoMapper 配置:RedisGameRoom → GameRoomReponse └── FishRoomService.csproj # 房间层类库项目文件 ``` --- ## 六、关键文件索引 | 文件相对路径 | 职责 | | --- | --- | | `FishGameSrc\FishRoomHost\Program.cs` | 房间层进程入口:DI、Redis、SignalR(`/fishingroomhub`)、CAP、JWT、启动 `InitRoom` | | `FishGameSrc\FishRoomHost\Extension\CapExtension.cs` | 房间层 CAP 配置(RabbitMQ+PostgreSQL+Dashboard)与 `IRoomMQService` 注册 | | `FishGameSrc\FishRoomHost\Middleware\AutofacModule.cs` | 房间层 Autofac 容器注册 | | `FishGameSrc\FishRoomHost\Middleware\ApiLoggingMiddleware.cs` | 房间层 `/api` 日志中间件 | | `FishGameSrc\FishRoomHost\Config\system.json` | 房间层运行配置(端口/Redis/Mongo/CAP/JWT) | | `FishGameSrc\FishRoomHost\docker-compose.yaml` | 房间层容器编排(5244:80) | | `FishGameSrc\FishGameHost\Program.cs` | 对局层进程入口:DI、SignalR(`/fishinghub`)、CAP 订阅者、托管服务 | | `FishGameSrc\FishGameHost\Extension\CapExtension.cs` | 对局层 CAP 配置(含多实例 DefaultGroupName) | | `FishGameSrc\FishGameHost\Middleware\AutofacModule.cs` | 对局层 Autofac 容器注册(Tracker/ConfigStore/FishSpawnService) | | `FishGameSrc\FishGameHost\Services\GlobalBroadcastSubscriber.cs` | 订阅 Redis 频道 `fishgame:global` 并广播 | | `FishGameSrc\FishGameHost\Controllers\RoomController.cs` | `api/Room/QuickJoin`、`api/Room/Assign` | | `FishGameSrc\FishGameHost\Controllers\TimeController.cs` | `fishapi/Time/GetDateTime` 校时接口 | | `FishGameSrc\FishGameHost\Controllers\PlayerController.cs` | `api/Player/login` 演示登录 | | `FishGameSrc\FishGameHost\Config\system.json` | 对局层运行配置(BulletConfig、GameServerInstances 等) | | `FishGameSrc\FishGameHost\docker-compose.yaml` | 对局层容器编排(5243:80) | | `FishGameSrc\FishGameService\Hubs\FishGameHub.cs` | 对局 Hub:全部客户端方法入口 | | `FishGameSrc\FishGameService\GameService\FishingGameService.cs` | 对局核心业务(进房/开炮/击杀/结算/掉线/机器人/因子) | | `FishGameSrc\FishGameService\GameService\IFishingGameService.cs` | 对局核心服务接口 | | `FishGameSrc\FishGameService\GameService\IBulletTracker.cs` | 子弹追踪与击杀标记(内存实现) | | `FishGameSrc\FishGameService\GameService\ReconnectTracker.cs` | 重连追踪 | | `FishGameSrc\FishGameService\GameService\FishSpawnConfigStore.cs` | 出鱼配置缓存与从 GameConfig 提取 | | `FishGameSrc\FishGameService\Services\FishSpawnService.cs` | 出鱼后台服务(租约/刷鱼/快照/命中校验/冻结) | | `FishGameSrc\FishGameService\Services\RobotKillAnnounceService.cs` | 机器人爆金公告后台服务 | | `FishGameSrc\FishGameService\Services\KillAnnouncePolicy.cs` | 击杀公告阈值策略 | | `FishGameSrc\FishGameService\GameSend\FishingSendService.cs` | 对局层推送实现 + Redis 全局击杀公告 | | `FishGameSrc\FishGameService\GameSend\IFishingSendService.cs` | 对局层推送接口 | | `FishGameSrc\FishGameService\Subscribers\LoginBindSubscriber.cs` | 订阅登录绑定/拒绝回房 | | `FishGameSrc\FishGameService\Subscribers\PlayerFactorSubscriber.cs` | 订阅因子变更/配置变更 | | `FishGameSrc\FishGameService\Subscribers\TempSpawnFishSubscriber.cs` | 订阅临时出鱼/召唤卡出鱼 | | `FishGameSrc\FishGameService\Subscribers\BackgroundAssetSubscriber.cs` | 订阅后台资产变更 | | `FishGameSrc\FishGameService\Config\BulletConfig.cs` | 签名与子弹配置模型 | | `FishGameSrc\FishGameService\Utils\SignHelper.cs` | 签名计算与校验 | | `FishRoomService\Hubs\FishRoomHub.cs` | 房间 Hub:GetRoomList、GetRoomInfo | | `FishRoomService\RoomService\FishingRoomService.cs` | 房间业务:大厅列表与房间初始化 | | `FishRoomService\RoomService\IFishingRoomService.cs` | 房间业务接口 | | `FishRoomService\RoomSend\FishingRoomSendService.cs` | 房间推送实现 | | `FishRoomService\MQ\RoomMQService.cs` | 房间级 CAP 订阅(房间变化、资产同步前端) | | `FishRoomService\RoomSend\Response\GameRoomReponse.cs` | 房间列表响应 DTO | | `FishRoomService\AutoMapperConfig.cs` | 房间层 AutoMapper 配置 | | `Gateway\ocelot.json` | 网关路由(含 `/fishingroomhub`→5244、`/gamehub`→`/fishinghub` 5248) | | `CommonDomain\TopicKeys.cs` | 全局 CAP 主题常量定义 | | `CommonDomain\GameConfig.cs` | 游戏配置(房间/鱼/机器人/击杀/出鱼因子等) | | `CommonDomain\EmptyRoomRateConfig.cs` | 空房率配置 | | `CommonDomain\BotProfileEntity.cs` | 机器人昵称/头像配置 | | `CommonDomain\CapMessageModels.cs` | CAP 消息模型(登录绑定/临时出鱼/召唤卡/因子变更/配置变更/后台操作) | | `Infrastructure\Common\Redis\RedisKey.cs` | Redis Key 生成器(含捕鱼相关 Key) | | `RedisService\IRedisService.cs` | Redis 服务接口(房间/玩家/配置/因子/进度等读写) | | `RedisService\Param\RedisGameRoom.cs` | 房间模型 | | `RedisService\Param\RedisGamePlayer.cs` | 房间内玩家模型 | | `RedisService\Param\RedisUserCid.cs` | 用户-连接-房间映射模型 | | `RedisService\Param\RoomBotFactory.cs` | 机器人工厂(`FixedBotSeats` 当前为空) | --- ## 七、与其他模块的交互 ### 7.1 CAP / RabbitMQ 消息(主题常量见 `CommonDomain\TopicKeys.cs`) **本模块「订阅」的消息** | 主题常量 | 实际主题名 | 订阅者 | | --- | --- | --- | | `房间变化` | `Topic_0524_RoomChage` | `FishRoomService\MQ\RoomMQService`(房间层向分区分组广播 `RoomChange`) | | `用户资产同步前端` | `Topic_0524_UserAssetSyncFrontend` | `RoomMQService`(房间层推送 `AssetUpdated`) | | `因子变更` | `Topic_0524_PlayerFactorChanged` | `PlayerFactorSubscriber`(对局层) | | `配置变更` | `Topic_0524_ConfigChanged` | `PlayerFactorSubscriber`(对局层) | | `登录绑定` | `Topic_0524_LoginBind` | `LoginBindSubscriber`(对局层,登录前结算离房) | | `拒绝回房` | `Topic_0524_DismissPendingRoom` | `LoginBindSubscriber`(对局层强制清房) | | `临时强制出鱼` | `Topic_0524_TempSpawnFish` | `TempSpawnFishSubscriber`(对局层) | | `召唤卡出鱼` | `Topic_0524_SummonCardFish` | `TempSpawnFishSubscriber`(对局层) | | `BackgroundOperation.NotifyUser`(字符串常量) | `BackgroundOperation.NotifyUser` | `BackgroundAssetSubscriber`(对局层后台加减币) | **本模块「发布」的消息** | 主题常量 | 实际主题名 | 发布者 | 消费方(平台其它模块,来自全局定义) | | --- | --- | --- | --- | | `房间变化` | `Topic_0524_RoomChage` | `FishingGameService.SendRoomChange`(对局层) | 房间层 `RoomMQService`(本模块内闭环) | | `用户资产变更` | `Topic_0524_UserAssetsChanged` | `FishingGameService.UseProp/UseTorpedo` | 用户资产模块(UserService) | | `全局击杀公告` | `Topic_0524_GlobalKillAnnounce` | `FishingGameService.FishKillControl`、`RobotKillAnnounceService` | 全服公告消费方(`UserService\Hubs\KillAnnounceSubscriber.cs` 等) | | `任务完成` | `Topic_0524_CompletedTask` | `FishingGameService.FlushFishingTaskProgress` | 任务系统(`CompletedTaskParam`,UserService 侧) | | `登录结果通知` | `Topic_0524_LoginBindResult` | `LoginBindSubscriber.HandleLoginBind` | 登录模块(UserService `LoginResultSubscriber`) | > 说明:`全局击杀公告` 由 `UserService\Hubs\KillAnnounceSubscriber.cs` 承接(全服广播);`登录绑定`/`登录结果通知`/`用户资产变更` 等由 UserService 侧订阅者处理,跨进程完成「登录前结算离房」「资产落库与前端同步」等协作。以上消费方文件位于本模块之外,此处仅据主题名与命名对应关系指出大致去向,具体实现不在本模块范围内。 ### 7.2 Redis Key 来源 `Infrastructure\Common\Redis\RedisKey.cs` + `RedisKeyGenerator.cs`。`RedisKeyGenerator` 按服务名加前缀(`game`→`game-service`、`user`→`user-service`、`common`→`app-shared`),故实际 Key 形如 `game-service:...`: | 属性/常量 | 生成方式 | 实际 Key | 用途 | | --- | --- | --- | --- | | `GameConfig` | `GameKey("config")` | `game-service:config` | 游戏配置(`GameConfig`) | | `ActivityConfig` | `GameKey("activity:config")` | `game-service:activity:config` | 活动配置 | | `FishingKillConfig` | `GameKey("fishing:killconfig")` | `game-service:fishing:killconfig` | 击杀/玩法配置(`FishingKillConfig`) | | `FishSpawnConfig` | `GameKey("fish:spawn:config:v1")` | `game-service:fish:spawn:config:v1` | 出鱼配置 JSON | | `SystemGoldDayKey` | `GameKey("fish:gamestatic")` | `game-service:fish:gamestatic` | 系统当日金币(系统因子计算) | | `GameRoomIdKey` | `GameKey("room:model:{0}_{1}")` | `game-service:room:model:{0}_{1}` | 房间模型 Key | | `DistributedLockPrefix` | `CommonKey("lock:")` | `app-shared:lock:` | 分布式锁前缀 | | `UserCIDGID` | `UserKey("uid:{0}")` | `user-service:uid:{0}` | 用户 → 连接/房间映射 | | `CIDUser` / `LoginCIDUser` | `UserKey("cid:{0}")` | `user-service:cid:{0}` | 连接 → 用户映射 | `FishSpawnService` 内自定义 Redis Key: | 常量前缀 | 完整 Key | 用途 | | --- | --- | --- | | `fish:spawn:global:id` | 同左 | 全局自增鱼 Id | | `SpawnOwnerKeyPrefix` | `fish:spawn:owner:{roomId}` | 房间出鱼权租约(10 秒) | | `ActiveFishSnapshotKeyPrefix` | `fish:spawn:snapshot:{roomId}` | 活跃鱼快照(60 秒) | | `FishKilledKeyPrefix` | `fish:spawn:killed:{roomId}:{fishId}` | 鱼已击杀标记 | | `SpawnStopKeyPrefix` | `fish:spawn:stop:{roomId}` | 房间停止出鱼标记 | `FishingGameService` 使用分布式锁 Key:`{lock:}fish:gold:{roomId}:{userId}`(金币/结算互斥)。 Redis 发布/订阅频道(非 CAP):`fishgame:global` —— `FishingSendService.KillNotice` 发布,`GlobalBroadcastSubscriber` 订阅。 ### 7.3 HTTP 调用 - 本模块内 `FishGameHost\Controllers\RoomController.cs` 读取配置 `GameServerInstances` 返回游戏服 WebSocket 地址(当前取列表第 0 项),并读取 Redis 房间列表做快速匹配。 - 通过 `IRequestApi`(注册于 `Program.cs`)提供对外 HTTP 请求能力;`FishingGameService`、房间层服务通过 `IUserService`(UserService 项目)读写用户资产、属性、结算等(`GameCoinsSettlement`、`UpdateAssets`、`UpdateUser`、`RecordFishingConsume`、`GetUser`)。 - 校时接口 `fishapi/Time/GetDateTime` 供客户端对齐服务器时间。 ### 7.4 共享实体 / 项目引用 - **项目引用链**: - `FishRoomHost` → `FishRoomService`、`CommonInfrastructure`、`SharpAbp.Infrastructure.Api` - `FishGameHost` → `FishGameService`、`CommonInfrastructure`、`SharpAbp.Infrastructure.Api` - `FishGameService` → `CommonDomain`、`CommonService`、`RedisService`、`UserService` - `FishRoomService` → `CommonService`、`RedisService`、`UserService` - **共享实体/模型**:`RedisService.Param`(`RedisGameRoom`、`RedisGamePlayer`、`RedisUserCid`、`RoomBotFactory`)、`CommonDomain`(`GameConfig`、`EmptyRoomRateConfig`、`BotProfileEntity`、`FishingKillConfig`、`ActiveFish` 相关、`TopicKeys`、`CapMessageModels`、`KillAnnounceParam`)、`UserDomain.Entity`(`UserEntity`)、`CommonDomain.Enum`(`GameTypeEnum`、`FishTypeEnum`、`ProductTypeEnum`、`TaskEvent`、`ErrorCodes` 等)。 - **公共基础设施**:`MongoRepository`(`IMongoBaseRepository<>` / `IMongoBaseService<>`)、`RedisService` / `RedisHelper`(`ICache`、`IDistributedLock`)、`SharpAbp.Infrastructure.Api`(`UseGlobalExceptionHandler` 等中间件)、`JWTHelper`(`AddCustomJwt`、`JwtTools`)、`CommonService`(`IHubSend<>`、`HubSend<>`、`ApiLogService`、`AppInstanceId`)。 --- > 本文档为一次性通读源码后整理的静态说明;如后续修改了 Hub 方法、CAP 主题、Redis Key 或端口配置,请同步更新本文件。