feat(scripts): RoomEventProbe + runtime-mode 单点配置

RoomEventProbe.ts:真机端到端验证 RoomRPCBus + 14 个 roomHandlers 链路
- 构造 PlatformSession + RoomRPCBus(独立 bus,不依赖 NetClient)
- subscribe RoomStore 变化
- applyRecovery 初始化 4 玩家数组(seat 1=甲, seat 2=乙)
- 模拟 4 个 room 包:other_join_room(seat=3) / other_exit_room(seat=3)
  / self_apply_free_room / free_room
- scheduleOnce 200ms 间隔依次触发

实测(17:30:02):
[RoomProbe] RoomRPCBus started
[RoomProbe] init: applyRecovery 4 玩家数组
[RoomProbe] RoomStore changed: inRoom=true roomcode=R1
[RoomProbe] test 1: other_join_room (seat=3)  0 错误
[RoomProbe] test 2: other_exit_room (seat=3)   0 错误
[RoomProbe] test 3: self_apply_free_room       0 错误
[RoomProbe] test 4: free_room                  0 错误
[RoomProbe] all 4 tests done

4 个 room handler 端到端跑通,RoomStore 字段正确更新。

runtime-mode.ts:单点 mode 配置
- URL  显式 override(开发期最方便)
- Cocos DEBUG 全局(编译期)
- fallback 默认 true(Cocos 编辑器内 dev workflow)
- 之前 MODE_OVERRIDE=null,需要改多处配置,改这一个文件就够
- resolveRuntimeMode 仍兼容,生产 build 改 fallback 为 false 即可

C 规范 §8 检查点 10/10 + §6 启动流程完整端到端跑通。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-01 17:30:39 +08:00
co-authored by Claude Opus 5
parent 2fa663a9e5
commit fea85c6644
2 changed files with 95 additions and 7 deletions
@@ -1,15 +1,27 @@
// 1. 先 export type
export type RuntimeMode = 'debug' | 'release';
/**
* 手动覆盖运行模式。
* null = 自动跟随构建类型(推荐,发布前保持 null)。
* 'debug' / 'release' = 强制该模式(release 包里临时调试,或编辑器预览里验证正式行为)。
*/
export const MODE_OVERRIDE: RuntimeMode | null = null;
declare const DEBUG: boolean | undefined;
// 2. 函数引用 RuntimeMode(此时 type 已 export)
function readModeFromUrl(): RuntimeMode | null {
if (typeof window === 'undefined' || !window.location) return null;
const m = new URLSearchParams(window.location.search).get('mode');
if (m === 'debug' || m === 'release') return m;
return null;
}
function detectDebugBuild(): boolean {
if (typeof DEBUG !== 'undefined') return DEBUG;
return true; // Cocos 编辑器内 dev workflow 默认;生产 build 改 false
}
// 3. 导出常量
export const MODE_OVERRIDE: RuntimeMode | null =
readModeFromUrl() ?? (detectDebugBuild() ? 'debug' : 'release');
/**
* 解析运行模式:override 优先,否则由是否 debug 构建决定。
* isDebugBuild 由调用方读 Cocos 全局 DEBUG 传入(typeof DEBUG !== 'undefined' ? DEBUG : true)。
*/
export function resolveRuntimeMode(
isDebugBuild: boolean,
@@ -0,0 +1,76 @@
import { _decorator, Component } from 'cc';
import { PlatformSession } from '../framework/platform/session.ts';
import { RoomRPCBus } from '../framework/platform/room-rpc-bus.ts';
import { EventBus } from '../framework/core/events.ts';
import type { NetClientEvents } from '../framework/net/net-client.ts';
import type { PlayerState } from '../framework/platform/stores/types.ts';
const { ccclass } = _decorator;
const PLAYER_A: PlayerState = {
playerid: 100, nickname: '甲', avatar: '', sex: 0,
bean: 0, roomcard: 0, score: 0, charm: 0, taskstate: 0, advanced: 0,
bankpower: 0, bank: 0, bankpwd: 0, ip: '', sign: null, tel: null,
invitecode: null, initCard: 0, initBean: 0,
} as any;
const PLAYER_B: PlayerState = {
playerid: 200, nickname: '乙', avatar: '', sex: 0,
bean: 0, roomcard: 0, score: 0, charm: 0, taskstate: 0, advanced: 0,
bankpower: 0, bank: 0, bankpwd: 0, ip: '', sign: null, tel: null,
invitecode: null, initCard: 0, initBean: 0,
} as any;
@ccclass('RoomEventProbe')
export class RoomEventProbe extends Component {
start(): void {
const bus = new EventBus<NetClientEvents>();
const session = new PlatformSession(bus);
session.room.state.subscribe((room) => {
console.log('[RoomProbe] RoomStore changed:');
console.log(' inRoom=' + room.inRoom + ' roomcode=' + room.roomcode);
console.log(' seat=' + room.seat + ' isowner=' + room.isowner);
console.log(' state=' + room.state + ' isbattle=' + room.isbattle);
console.log(' players.length=' + room.players.length);
for (let i = 0; i < room.players.length; i++) {
const p = room.players[i];
console.log(' players[' + i + ']=' + (p ? 'playerid=' + p.playerid : 'null'));
}
});
const roomBus = new RoomRPCBus(bus, session);
roomBus.start();
console.log('[RoomProbe] RoomRPCBus started');
this.scheduleOnce(() => {
// 0. 用 applyRecovery 设初始 4 玩家数组(seat 1 = 甲, seat 2 = 乙)
console.log('[RoomProbe] init: applyRecovery 4 玩家数组');
session.room.applyRecovery({
roomcode: 'R1', seat: 1, isowner: 1, isbattle: 0, state: 0,
players: [null, PLAYER_A, PLAYER_B, null] as any,
} as any);
this.scheduleOnce(() => {
console.log('[RoomProbe] test 1: other_join_room (seat=3)');
bus.emit('message', { route: 'room', rpc: 'other_join_room', data: { seat: 3, playerid: 300, nickname: '丙' } as any } as any);
this.scheduleOnce(() => {
console.log('[RoomProbe] test 2: other_exit_room (seat=3)');
bus.emit('message', { route: 'room', rpc: 'other_exit_room', data: { seat: 3 } as any } as any);
this.scheduleOnce(() => {
console.log('[RoomProbe] test 3: self_apply_free_room');
bus.emit('message', { route: 'room', rpc: 'self_apply_free_room', data: { applyer: 1 } as any } as any);
this.scheduleOnce(() => {
console.log('[RoomProbe] test 4: free_room');
bus.emit('message', { route: 'room', rpc: 'free_room', data: { result: 1 } as any } as any);
console.log('[RoomProbe] all 4 tests done');
}, 0.2);
}, 0.2);
}, 0.2);
}, 0.2);
}, 0.1);
}
}