- CLAUDE.md 新增「第二准则:数据源权威、唯一,下游不兜底」 - bootstrap 删除 fallbackServers 选项与 ?? DEFAULT_GAMESERVER 猜默认 - 无 server/gameserver、远程失败、解析不出地址 → 一律抛 ConfigFetchError 显式暴露 - 同步 guide + 两篇 spec(删 fallback/降级措辞) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
12 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
第一准则:服务器零改动
任何前端开发都必须完全遵循前后端数据包的协议与数据结构,做到服务器零改动。 这是本仓库不可逾越的最高准则,优先于一切其它考量:
- 协议信封、
route/rpc命名、字段名与类型、roomtype配置数组、deskinfo快照结构等,必须与现有协议逐字节对齐(依据docs/protocol/),不得为前端方便而改变格式或新增/重命名字段。 - 遇到协议层有疑问时,先读
docs/protocol/对应章节核对,不要臆测;宁可前端多做适配,也绝不要求服务器配合改动。 - 新的 Cocos 前端(
YouleNexus)的目标,就是在不改服务器的前提下复刻该协议契约、实现联调兼容。
第二准则:数据源权威、唯一,下游不兜底
每一类数据只能有一个权威且唯一的来源(single source of truth);下游消费方不得猜测、修补、兜底。
- 唯一来源:同一份配置/数据(如服务器地址、渠道身份、协议常量)只在一个地方定义,其它地方一律引用,不得各处复制或并存第二份。
- 下游零兜底:消费方拿到的数据缺失或非法时,直接显式报错/抛出,把问题暴露到来源,不得用默认值「猜一个」、不得静默
?? 兜底值、不得 try/catch 后塞个 fallback 蒙混。错误要早暴露、可定位,而不是被下游悄悄掩盖。 - 配置即契约:来源(如
profiles.ts的服务器地址)必须把该提供的字段显式提供齐全;缺了就是配置错误,应在来源处修正,而不是让下游补。 - 例外只有一种:来源本身明确定义了「可选 + 缺省语义」,且该缺省写在来源处(而非散落在各下游)。
这条与「服务器零改动」并列:前者保边界契约不变,后者保内部数据流可信、单源、可追溯。新增/修改任何带默认值、回退、容错分支的代码前,先问:这是不是在替上游兜底?若是,改为在来源处修正 + 在下游暴露。
仓库总览
这是友乐(Youle)棋牌游戏平台的前端工作区,核心是「一套前端模板 + 多个子游戏」的架构,并正在迁移到 Cocos Creator。三个顶层目录:
projects/—— 旧版 HTML5 前端。projects/Game_Surface_3是前端模板(平台外壳),其余目录(doudizhu/erqiwang/niuniu/majiang_jx/guanpai-jx/pdk_card_client-jinxian/sangelaok/zpy/gamehall3…)都是基于该模板扩展出来的子游戏,平台层几乎不动,只改子游戏层 + 美术数据。docs/protocol/—— 前端模板框架与服务器收发包的协议规范(权威文档,8 篇)。改动任何网络层代码前必须先读对应章节,服务器不可改,前端必须严格对齐协议。cocoscreator_projects/YouleNexus/—— 新的 Cocos Creator 3.8+ 前端工程,目标是按docs/protocol复刻协议契约,做到服务器零改动即可联调。
前端模板 Game_Surface_3 与子游戏(projects/)
四层结构(自底向上):
- 引擎层 ——
js/gameabc.min.js(gameabc 精灵引擎)+ Spine(spine-canvas.js/SpineMgr.js)+ Canvas 渲染;提供触屏/定时器/资源/WebSocket 底层回调。 - 桥接层 ——
js/gamemain.js:统一事件总线,把引擎回调分发到平台 UI、子游戏Game_Modify、对战逻辑。 - 平台层 ——
js/00_Surface/*(12 个文件):登录、大厅、房间、聊天、社交、网络、资源、排行、任务等通用能力。子游戏间几乎不变。 - 子游戏层 ——
js/01_SubGame/*(3 个文件):只实现本游戏的对局逻辑与房间 UI。
平台层关键文件(js/00_Surface/): 02_Const.js(ConstVal/AppList/路由表)、04_Data.js(GameData 全局态)、09_Net.js(Net._SendData() 收发分发)、12_Logic.js(Logic 连接/重连/分发编排)、07_Desk.js(Desk 房间状态机)、06_Player.js(C_Player/Player 数据结构)、11_GameUI.js(平台 UI)、00_minhttp.js(WebSocket 底层封装)。
子游戏层(js/01_SubGame/,开发子游戏 = 改这 3 个文件 + 美术数据):
00_SubGame_Config.js——Game_Config(房间数、气泡位置、分享、调试开关)01_SubGame_modify.js——Game_Modify/gameCombat(对局实现 + 房间/胜负 UI)02_SubGame_Input.js—— 平台回调钩子(模板里是桩,子游戏覆写为真实逻辑)- 另需补充:
gamemain.js(扩展对局初始化)、专用算法模块(牌型/出牌等)、美术数据output/gameabc_data.min.js。
状态归属: 平台层维护 Desk(房间/座位)、C_Player(自己)、GameData(连接/资产);子游戏维护对局态(手牌、出牌历史、轮次、分数)于自身命名空间,并需可序列化为 deskinfo 以支持断线重连。
网络协议(docs/protocol/,新旧前端共同契约)
- 传输层: 单条长连 WebSocket,纯 JSON 文本(无二进制/protobuf)。先 HTTP GET 配置服务拿
urlserver,再ws://<ip:port>连接;支持connect_agentserver/connect_roomserver切换服务器。 - 消息信封:
- 客户端→服务器(单层):
{ "app":"youle", "route":"agent|room|platform|<game_route>", "rpc":"<name>", "data":{…} } - 服务器→客户端(双层包裹):外层
{ "data": <inner> };inner 可能是字符串需JSON.parse。收包必做过滤:@toconcon(前 9 字符,握手包,忽略)、data.com === "@serverheartbeat"(服务器心跳,~20s 一次,不回复)。
- 客户端→服务器(单层):
- 路由分发:
route ∈ {agent, room, platform}→ 平台层处理(Net.<rpc>→Desk.*/C_Player.*);route为其它值 → 交子游戏Game_Modify._ReceiveData(msg),由子游戏switch(msg.rpc)派发对局包。平台请求通用身份字段:agentid/gameid/playerid(房间操作再加roomcode)。 - 心跳/超时/重连: 客户端 30s 收包超时(
ConstVal.Max.heartbeat = 30000),超时报“网络慢”并重连;断线时Logic轮询候选服务器,重连后重发player_login。 - 核心数据结构(详见
04-数据结构.md):C_Player(本地玩家)、Player(seat)(座位玩家)、Desk(房间/牌桌)、player_login响应(账号资产 + 可选房间恢复段:roomcode/isbattle/deskinfo…)。 - 两个不可妥协的约束: ①
roomtype房间配置数组结构必须与目标子游戏逐字节一致(服务器据此解析规则);②deskinfo对局快照须可序列化/反序列化以支持isbattle==1时Game_Modify.Reconnect(deskinfo)断线重连。
协议文档索引: 00-框架架构设计 · 01-传输层与架构 · 02-协议-agent路由 · 03-协议-room路由 · 04-数据结构 · 05-游戏内协议与桥接 · 06-子游戏开发模式与Cocos方案。改协议相关代码前先读对应篇。
客户端侧适配约束:远程配置 / 原生数据接口 / 原生↔H5 桥接(须与原项目逐字一致)
继「服务器零改动」之后的第二类不可妥协约束:除 WebSocket 协议外,前端还通过「远程配置文件」与「原生接口」获取大量数据。新 Cocos 前端必须与原项目逐字一致地复刻这些读取/互调/注册方式(接口名、数据格式、回调约定、URL 构造),让原生侧与配置服务零改动即可对接。三类机制:
-
远程配置文件读取:入口
Game_Config.Debugger.gameserver(projects/Game_Surface_3/js/01_SubGame/00_SubGame_Config.js:11,远程.txtURL +ifast_random()防缓存 +serverType切正式/本地)。读取链:Logic.setGameServer()(解析 URL 参数gameconfig或Func.getothername("gameserver")覆盖,12_Logic.js:1259-1281)→get_config(gameserver)(引擎层函数,GET 远程 txt,12_Logic.js:521)→ServerUrl_Succ(_msg)回调(12_Logic.js:533)→GameData.Server = _msg.data.urlserver(12_Logic.js:549)。URL 构造、请求方式、回包字段解析须一致。 -
原生同步数据接口(注入对象):
Func.getothername(name)→window.settings.getothername(name)(js/00_Surface/05_Func.js:2467-2471)。window.settings是原生注入的全局对象,用于同步取配置(如渠道/包信息/gameserver 覆盖)。 -
原生↔H5 异步桥 = WebViewJavascriptBridge (WVJB)(
05_Func.js:2627起):- 初始化
setupWebViewJavascriptBridge(callback)(经window.WVJBCallbacks/WebViewJavascriptBridgeReady事件 /wvjbscheme://__BRIDGE_LOADED__iframe)。 - H5 注册供原生调用:
bridge.registerHandler("<name>", (data, responseCallback) => {…})。已注册 handler(名称/数据结构须一致):getVideoinfo、sharelogin、sharesuccess、gameui_play_voice、gameui_stop_voice、getphoneinfo、getAddressBook、phonestate、appservice、getaudiourl、getBattery、getwifiLevel、getnetwork、shakeEnd等(05_Func.js:2651+)。 - H5 调用原生:
bridge.callHandler("<name>", data, responseCallback)(WVJB 约定)。 - 覆盖能力:分享、视频、语音录制/播放、电话状态、通讯录、电量/wifi/网络、摇一摇等。
- 初始化
Cocos 适配注意:原项目是 H5(WebView + WVJB +
window.settings+ 引擎get_config)。新 Cocos 前端无论走 WebView 还是原生(jsb),都必须对接同名 handler、同样的数据结构与回调约定,并保持远程配置读取流程一致,使原生侧与配置服务无需改动即可互通。这套桥接的落地属 sdk/平台层范畴(后续 Plan)。改这部分前先核对上述源码位置,不要臆测接口名或数据格式。
Cocos Creator 新前端:优先使用 cocos-creator-mcp
新工程 cocoscreator_projects/YouleNexus。任何涉及该工程的编辑器操作(场景、节点、组件、prefab、资源、预览/截图/录制等),都应优先使用 cocos-creator-mcp 这组 MCP 工具(命名空间 mcp__cocos-creator-mcp__*,共 164 个)直接驱动编辑器,而不是手改 .scene / .prefab / .meta 等序列化文件——手改极易破坏 UUID 引用与序列化结构。
前置条件(缺一不可,否则工具调用必然失败):
- Cocos Creator 3.8+ 已打开
YouleNexus工程; - 扩展
cocos-creator-mcp已启用,并在其面板里点了 Start Server(监听http://127.0.0.1:3000/mcp)。
开工前先探活:先调用 mcp__cocos-creator-mcp__server_get_status(或 curl http://127.0.0.1:3000/health,期望 {"status":"ok","tools":164})。连不上时,提示用户在编辑器里启动服务,不要盲目重试——MCP 桥(extensions/cocos-creator-mcp/client/stdio-bridge.js)只转发,无法替你启动编辑器服务。
工具分类(按前缀): scene_*(场景生命周期/层级/查询/撤销)、node_*(增删改/变换/树)、component_*、prefab_*、asset_*、project_*、builder_*(预览/构建)、debug_*(截图、录制、game command、控制台日志)、view_*(gizmo/相机/网格)、refimage_*、preferences_*、server_*。
MCP 的项目级安装方式与排障细节(扩展位置、
package.jsonname 必须为cocos-creator-mcp、镜像 404 等坑)记录在项目记忆cocos-creator-mcp-setup。