Files
ft/CodexOutput/upserver/客户端与服务端对比分析.md

8.9 KiB
Raw Blame History

客户端与 N3-Server-CN 对比分析

更新说明:服务端 a3d3faa 已补齐通用玩家 KV Get/Set/Delete,本文未找到KV的结论已过期;最新接口及兼容差异见《KV更新复核.md》。

进一步核查修正:friend/GetHomePage仅返回社交列表,不能作为本人资料恢复接口。当前开发方案、资料来源限制及评审裁决见《客户端迁移详细修改方案.md》。

日期:2026-09-15。客户端 feat/upserver / f40a816cc,加已批准的 SignalR 选项修改;服务端本地 main / 696fc8c。分析以当前源码为准,不代表远端部署版本已经核对。此次只分析及更新文档。

一、结论

服务端已实现渠道十进制身份、Cookie 登录、自建 SignalR 和好友列表;它尚不能在当前检出中完整替代客户端使用的全部 PlayFab 功能。优先打通账号和实时连接,再补齐 KV 契约及外围依赖,最后删除 SDK。

二、核心接口对照

项目 客户端当前实现 服务端当前实现 差异与处理
API 地址 DebugConfig 和 CustomServerMgr 缺省指向旧 IP:5292;本地配置可覆盖 用户指定 s101.local:18080,根路径/时间接口已可达 地址及生效配置仍需修改;本次仅 SignalR 选项已改
身份来源 AggUserService 将渠道 ID 放在 CustomId;随后 PlayFab 登录生成 hex UserId PlayerIdUtil 使用 long.Parse,拒绝负值 UserId 应来自渠道 ID;不能对旧 hex 做进制转换代替身份迁移
登录路由 POST account/Login,发送 playerId/playerProfile 同一路由;playerProfile 可选 路由基本一致,主要差异是身份语义与初始化数据
登录返回 只读 state/internalId,LoginApiServer 为 async void 成功返回 state=0、internalId、createTime、svrTime、newCreate,签发 Cookie await 业务登录,失败不返回 Done;专用 DTO 接收并映射时间/新账号标志
登录附带资料 PlayFab 返回 UserData、昵称、头像、地区、创建/上次登录时间、EntityToken LoginResp 无 KV、昵称头像、地区、上次登录时间和实体令牌 逐项指定新来源;不能删掉 PlayFab 调用后用空值继续初始化
KV 读取 PlayFab 登录 InfoResultPayload.UserData,CompareDatas 后 LoadPlayerData 当前检出未找到通用 KV 读取路由,登录也不带存档 需要确定 KV 服务/分支;不能用服务器 players 表代替游戏存档
KV 写入 UpdateUserData,字符串键值、LastUpdated、本地缓存、批量及立即同步 当前检出未找到等价通用写入路由 定义批量读写、时间/版本、失败重试、跨玩家读取权限后实施
SignalR /gamehub,业务登录事件触发,复用 CookieContainer /gamehub RequireAuthorization,用户标识来自 Cookie 认证与路径一致,已添加 SkipNegotiation+WebSockets;仍需实际登录验证

注:服务端模型属性 InternalId/CreateTime 采用默认 MVC JSON 命名策略;客户端的 internalId 不能仅凭 C# 属性大小写判为不兼容。最终用真实响应或契约测试确认。

三、登录顺序必须调整

旧顺序:渠道身份 → PlayFab 登录/资料/KV → 初始化玩法 → 异步发业务登录 → 提前返回 Done。

建议新顺序:渠道身份 → 等待 account/Login 并确认 state → 保存会话/内部 ID/服务时间 → 获取完整玩家资料与 KV → 初始化玩法 → 返回 Done。

API 授权成功事件与游戏数据就绪要明确分开:SignalR 可以在拿到 Cookie 后建立连接,但消费玩法消息的代码需要在数据就绪后执行,或在此期间缓存消息。实施方案需核查所有 EvtAPISvrLoginSuccess 订阅者再确定事件时序。

首次登录建议不上传尚未恢复的等级/昵称等默认资料:服务端 AccountService 每次登录都会把非空 playerProfile 写回 DBPlayer,客户端默认数据可能覆盖已有资料。先取资料/存档,再按明确字段更新。服务端 GetHomePage 可作为资料查询候选,需核对响应是否覆盖登录初始化所需字段。

四、KV 需要的契约

PlayFabMgr 不只是本地缓存。它负责远端记录与本地值合并,再供大量玩法加载;服务端的 DBPlayer 只有账号资料,Redis 的玩法状态也不能证明存在可供客户端调用的通用 KV API。

必须明确:

  1. 读写路径、鉴权方式、全量/指定 key 读取及响应模型。
  2. 空存档与请求失败的区分;字符串值、每 key 更新时间/版本。
  3. 并发策略、写入确认与重试、批量大小限制。
  4. 当前 Public UserData 中哪些允许其他玩家读取,哪些只能当前账号访问。
  5. 全新区服是否沿用服务端文档“不迁移旧 PlayFab 存量”决策;本地旧缓存也不能混入新渠道账号。

现有队列还有可靠性缺口:SyncData 在请求确认前轮换缓冲,失败仅记日志;改造时应保留未确认批次并防止旧重试覆盖新值。立即同步与批量同步也必须有明确先后规则。

五、删除 SDK 的外围依赖

功能 客户端依赖 服务端可用能力 判断
好友列表 PlayFab GetFriendsList,读取 Profile.Statistics/LastLogin POST friend/GetFriendsList;Friends 为每项已序列化的 JSON 字符串 可适配,需两层解析;PlayerInfo 给 Level,不给 Statistics/LastLogin,在线时长展示需另定来源
玩家资料 GetPlayerProfile、UpdateAvatarUrl、UpdateUserTitleDisplayName account/UpdateProfile、friend/GetHomePage 有候选;需核对读取/失败语义,不能保持原“先 PlayFab 后业务”双写
地区与语言 PlayFab Locations、SetProfileLanguage 登录响应未提供 明确渠道/本地设置/服务端字段的责任,不编造地区
等级/地区排行榜 UpdatePlayerStatistics、GetLeaderboard,LevelB 等统计名 event/GetLeaderboards、event/UpdateScore 已有的是活动排行榜,不能直接当作全球/地区等级榜替代
公告 GetTitleNews 本次控制器检索未找到等价公告端点 契约缺口;不能用空列表假装迁移完成
对战匹配 Create/Get/CancelMatchmakingTicket、GetMatch,依赖 EntityKey duel/DuelRT 负责对战实时请求 对战同步不等于票据匹配,需要等价匹配服务或经评审的玩法切换
账号工具 PlayFabTools 用渠道 ID 再登录 PlayFab 查资料 服务端渠道身份/玩家查询 删除这条旧映射,具体替代查询需核实

六、易遗漏的客户端兼容问题

  • FriendService.cs:375:邀请码把 ID 当 hex 转整数;应核对编码和解码的整个链路。
  • SurveyService.cs:56:用户尾号筛选按 hex 转换,会改变十进制渠道用户分组。
  • DinggingSceneData.cs:94:随机种子按 hex 转换;迁移后需要明确可复现规则,避免既有玩法结果突变。
  • UserService.cs:140:默认名使用 id[0..5];服务端允许较短数字 ID,不能默认长度至少为 5。
  • RTService:连接前注册的订阅进入 _cachedEvents,但刷新仅挂在 Reconnected;首次 StartAsync 成功没有刷新调用。从控制流看存在首连漏订阅风险,需回归测试验证,不属于已批准的两项选项修改。
  • Logout 当前只清 PlayFab 凭据和字段,业务 Cookie 生命周期需在迁移方案中一并处理。

七、建议实施顺序与评审裁决

  1. API 地址与现有本地覆盖项修改,验证实际生效;SignalR 两项配置已经落地。
  2. 完成十进制账号登录方案:响应 DTO、await、时间/资料来源、Cookie、失败处理和所有 ID 依赖点。
  3. 确认 KV 契约;无契约前不替换存档初始化,不直接删除 SDK。
  4. 迁移好友等有明确替代接口的功能;逐项解决公告、排行、匹配缺口。
  5. 清理 SDK 包、类型、程序集和热更新引用,执行编译及回归。
  6. 用专用账号验证登录、KV 写后读与重新登录、SignalR 无 negotiate 且可调用 Test/接收推送/重连。

裁决:SignalR 选项子集实现与服务端方向一致;全量去 SDK 方案仍有 KV 和外围能力缺口,暂不放行。地址/登录可分别形成限定边界的开发批次,但账号登录成功不能冒充完整游戏登录验收。

源码入口

  • 客户端:Client/Assets/Scripts/Services/{UserService,AggUserService,FriendService,RTService,SurveyService,TileNewsManager}.cs
  • 客户端:Client/Assets/Scripts/Core/PlayFabMgr.cs、Client/Assets/Scripts/DataCenter/DataCenter.LeadboardData.cs、Client/Assets/Scripts/Duel/UI/EventFishingDuelPanel.cs
  • 服务端:LeaderboardAPI/Controllers/{AccountApi,FriendApi,EventLeaderboardApi,DuelApi}.cs、LeaderboardAPI/Program.cs
  • 服务端:LeaderboardBLL/Models/AccountModel.cs、LeaderboardBLL/Utils/PlayerIdUtil.cs、LeaderboardBLL/Services/PlayerInfo/{AccountService,PlayerInfoCacheService}.cs、LeaderboardBLL/Services/Friend/NewFriendService.cs