112 lines
4.2 KiB
TypeScript
112 lines
4.2 KiB
TypeScript
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']);
|
|
});
|