# 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/`) **四层结构(自底向上):** 1. **引擎层** —— `js/gameabc.min.js`(gameabc 精灵引擎)+ Spine(`spine-canvas.js` / `SpineMgr.js`)+ Canvas 渲染;提供触屏/定时器/资源/WebSocket 底层回调。 2. **桥接层** —— `js/gamemain.js`:统一事件总线,把引擎回调分发到平台 UI、子游戏 `Game_Modify`、对战逻辑。 3. **平台层** —— `js/00_Surface/*`(12 个文件):登录、大厅、房间、聊天、社交、网络、资源、排行、任务等通用能力。**子游戏间几乎不变**。 4. **子游戏层** —— `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://` 连接;支持 `connect_agentserver`/`connect_roomserver` 切换服务器。 - **消息信封:** - 客户端→服务器(单层):`{ "app":"youle", "route":"agent|room|platform|", "rpc":"", "data":{…} }` - 服务器→客户端(**双层包裹**):外层 `{ "data": }`;inner 可能是字符串需 `JSON.parse`。**收包必做过滤**:`@toconcon`(前 9 字符,握手包,忽略)、`data.com === "@serverheartbeat"`(服务器心跳,~20s 一次,**不回复**)。 - **路由分发:** `route ∈ {agent, room, platform}` → 平台层处理(`Net.` → `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 构造),让原生侧与配置服务**零改动**即可对接。三类机制: 1. **远程配置文件读取**:入口 `Game_Config.Debugger.gameserver`(`projects/Game_Surface_3/js/01_SubGame/00_SubGame_Config.js:11`,远程 `.txt` URL + `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 构造、请求方式、回包字段解析须一致。** 2. **原生同步数据接口(注入对象)**:`Func.getothername(name)` → `window.settings.getothername(name)`(`js/00_Surface/05_Func.js:2467-2471`)。`window.settings` 是**原生注入的全局对象**,用于同步取配置(如渠道/包信息/gameserver 覆盖)。 3. **原生↔H5 异步桥 = WebViewJavascriptBridge (WVJB)**(`05_Func.js:2627` 起): - 初始化 `setupWebViewJavascriptBridge(callback)`(经 `window.WVJBCallbacks` / `WebViewJavascriptBridgeReady` 事件 / `wvjbscheme://__BRIDGE_LOADED__` iframe)。 - **H5 注册供原生调用**:`bridge.registerHandler("", (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("", 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 引用与序列化结构。 **前置条件(缺一不可,否则工具调用必然失败):** 1. Cocos Creator 3.8+ 已打开 `YouleNexus` 工程; 2. 扩展 `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.json` name 必须为 `cocos-creator-mcp`、镜像 404 等坑)记录在项目记忆 `cocos-creator-mcp-setup`。