refactor(platform): unify routing and session dispatch

This commit is contained in:
2026-09-05 05:23:58 +08:00
parent e47d9d3007
commit 1c124cf216
10 changed files with 916 additions and 171 deletions
@@ -0,0 +1,111 @@
import { readFileSync } from 'node:fs';
import assert from 'node:assert/strict';
import { test } from 'node:test';
import type {
GameEntry,
GameHost,
GameModule,
PlatformGameSnapshot,
PlatformToGameEvent,
} from '../../YouleNexus/assets/framework/sdk/contracts/index.ts';
import { GameSessionHost } from '../../YouleNexus/assets/framework/sdk/runtime/game-session-host.ts';
import { RuntimeSession } from '../../YouleNexus/assets/framework/platform/runtime-session.ts';
import { PlatformStore } from '../../YouleNexus/assets/framework/platform/stores/platform-store.ts';
import { selectGameSnapshot } from '../../YouleNexus/assets/framework/platform/stores/selectors.ts';
function fixture(name: string): Record<string, unknown> {
return JSON.parse(readFileSync(new URL(`../fixtures/contracts/${name}`, import.meta.url), 'utf8')).data;
}
function makeSession() {
const store = new PlatformStore();
const log: string[] = [];
const restored: unknown[] = [];
const events: Array<{ event: PlatformToGameEvent; snapshot: PlatformGameSnapshot }> = [];
let host: GameHost;
const entry: GameEntry = {
key: 'fixture',
gameId: 41,
route: 'fixture-game',
resolveSeatCount: () => 4,
createModule: (): GameModule => ({
attach(attachedHost) {
host = attachedHost;
attachedHost.getSnapshot();
log.push('attach');
},
handlePlatformEvent(event) {
events.push({ event, snapshot: host.getSnapshot() });
log.push(`event:${event.type}`);
},
handleGameMessage() {},
restore(deskinfo) {
restored.push(deskinfo);
log.push('restore');
},
dispose() { log.push('dispose'); },
}),
};
const gameSession = new GameSessionHost(entry);
log.length = 0;
const gameHost: GameHost = {
seat: { toView: (seat) => seat, toServer: (seat) => seat },
getSnapshot: () => selectGameSnapshot(store.getState()),
subscribe: () => () => {},
sendGameMessage() {},
execute() {},
};
const session = new RuntimeSession({ store, gameSession, gameHost });
return { store, gameSession, session, log, restored, events };
}
test('RuntimeSession commits a room login before opening, publishing, and restoring deskinfo', () => {
const setup = makeSession();
const data = fixture('player-login-room.json');
setup.store.subscribe(() => { setup.log.push('store'); });
setup.session.markLoginPending();
setup.session.handleLogin(data);
assert.equal(setup.session.loginPending, false);
assert.equal(setup.store.getState().room.kind, 'inside');
assert.equal('deskinfo' in setup.store.getState().room, false);
assert.equal(setup.restored.length, 1);
assert.equal(setup.restored[0], data.deskinfo);
assert.deepEqual(setup.log, ['store', 'attach', 'event:room.entered', 'restore']);
assert.equal(setup.events[0]?.snapshot.room.roomcode, '100001');
assert.equal(setup.events[0]?.event.type, 'room.entered');
if (setup.events[0]?.event.type === 'room.entered') {
assert.equal(setup.events[0].event.roomtype, setup.events[0].snapshot.room.roomtype);
}
});
test('RuntimeSession never treats isbattle as a restore signal without truthy deskinfo', () => {
for (const deskinfo of [undefined, null, false, 0, '']) {
const setup = makeSession();
const data = fixture('player-login-room.json');
if (deskinfo === undefined) delete data.deskinfo;
else data.deskinfo = deskinfo;
data.isbattle = 1;
setup.session.handleLogin(data);
assert.deepEqual(setup.restored, [], `deskinfo=${String(deskinfo)}`);
assert.equal(setup.store.getState().room.kind, 'inside');
}
});
test('RuntimeSession self join commits, opens a fresh session, and restores the same snapshot once', () => {
const setup = makeSession();
setup.session.handleLogin(fixture('player-login-success.json'));
setup.log.length = 0;
const join = fixture('self-join-room.json');
setup.store.subscribe(() => { setup.log.push('store'); });
setup.session.handleSelfJoin(join);
assert.equal(setup.store.getState().room.kind, 'inside');
assert.equal(setup.restored.length, 1);
assert.equal(setup.restored[0], join.deskinfo);
assert.deepEqual(setup.log, ['store', 'attach', 'event:room.entered', 'restore']);
});