Files
sunrise/tests/multiplayer-client.test.ts
T

41 lines
1.9 KiB
TypeScript

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { Group } from 'three';
import { createServerClock } from '../src/multiplayer/clock.ts';
import { createRemotePlayers } from '../src/multiplayer/remotePlayers.ts';
import type { Sheep } from '../src/scene/sheep.ts';
import type { PlayerState } from '../src/multiplayer/protocol.ts';
test('server clock uses round trip midpoint and monotonic elapsed time', () => {
let mono = 100;
const clock = createServerClock(() => mono);
mono = 140;
clock.synchronize(1000000, 100);
assert.equal(clock.now(), 1000020);
mono = 1140;
assert.equal(clock.now(), 1001020);
});
test('remote snapshot reconciles membership, equipment and interpolated motion without local duplicate', () => {
const scene = new Group();
const equipment: boolean[][] = [];
let disposed = 0;
const template = { clone() { return { group: new Group(), setEquipment: (...v: boolean[]) => equipment.push(v),
pose: () => false, dispose() { this.group.removeFromParent(); disposed++; } } as unknown as Sheep; } } as Sheep;
const remote = createRemotePlayers(template, scene, () => 3);
const player: PlayerState = { id: 'other', nickname: '방문자', x: 0, z: 0, yaw: 0, moving: false,
emote: 'idle', equipment: { umbrella: true, raincoat: true, hood: false }, updatedAt: 1000, emoteStartedAt: 1000 };
remote.synchronize([player, { ...player, id: 'self' }], 'self');
assert.equal(scene.children.length, 1);
assert.deepEqual(equipment.at(-1), [true, true, false]);
remote.synchronize([{ ...player, x: 1, updatedAt: 1100 }], 'self');
remote.update(.075, 1100);
assert.ok(scene.children[0].position.x > 0 && scene.children[0].position.x < 1);
remote.update(.2, 1300);
assert.equal(scene.children[0].position.x, 1);
assert.equal(scene.children[0].position.y, 3);
remote.synchronize([], 'self');
assert.equal(scene.children.length, 0);
assert.equal(disposed, 1);
});