import assert from "node:assert/strict"; import { describe, it } from "node:test"; import * as THREE from "three"; import { createScenePeers, scenePeerId, type ActorPoseSnapshot, type AircraftPoseSnapshot, type EntityPoseSnapshot, type InterestCell, type ScenePeersOptions, type VehiclePoseSnapshot, } from "../realtime/index.ts"; const VELOCITY = { xMps: 0, yMps: 0, zMps: 0, yawDegPerSec: 0 }; function actor( id: string, kind: "humanoid" | "dog" | "crow", sequence: number, timestampMs: number, xM: number, cell: InterestCell = { kind: "floor", officeId: "hq", floorId: "one" }, ): ActorPoseSnapshot { if (cell.kind === "california-tile") throw new Error("local poses cannot use tile cells"); return { entity: "actor", actorId: id, kind, sequence, timestampMs, pose: { space: "local", cell, xM, yM: 2, zM: 3, headingDeg: 0, pitchDeg: 0 }, velocity: { ...VELOCITY, xMps: 2 }, }; } function vehicle(sequence: number, timestampMs: number, lat: number): VehiclePoseSnapshot { return { entity: "vehicle", vehicleId: "ev-1", kind: "model-x", driverActorId: null, sequence, timestampMs, pose: { space: "geographic", lat, lng: -120, altitudeM: 10, headingDeg: 90, pitchDeg: 2 }, velocity: { ...VELOCITY, xMps: 20 }, steering: 0.4, wheelRadians: 3, }; } function aircraft(sequence: number, timestampMs: number, lat: number): AircraftPoseSnapshot { return { entity: "aircraft", aircraftId: "evtol-1", kind: "electric-vtail", pilotActorId: "pilot-1", sequence, timestampMs, pose: { space: "geographic", lat, lng: -121, altitudeM: 1_500, headingDeg: 30, pitchDeg: 5 }, velocity: { xMps: 30, yMps: 2, zMps: 52, yawDegPerSec: 4 }, rollDeg: 18, throttle: 0.72, rollInput: 0.4, pitchInput: -0.2, yawInput: 0.1, fanRadians: 2.4, }; } function fixture(over: Partial = {}) { return createScenePeers({ project: (lat, lng) => [lng * 2, -lat * 3], groundAt: () => 5, geographicSceneUnitsPerMetre: 0.1, localSceneUnitsPerMetre: 1, interpolation: { interpolationDelayMs: 0, maximumExtrapolationMs: 0 }, ...over, }); } function mesh(root: THREE.Object3D, name: string): THREE.Mesh { const found = root.getObjectByName(name); if (!(found instanceof THREE.Mesh)) throw new Error(`missing mesh ${name}`); return found; } describe("remote scene peers", () => { it("maps local poses directly and keeps one identity-free stable root per peer", () => { const peers = fixture(); const first = actor("private-member-id", "humanoid", 1, 1_000, 1); assert.equal(peers.upsert(first), true); assert.deepEqual(peers.ids(), ["actor:private-member-id"]); assert.equal(peers.count(), 1); const root = peers.root.children[0] as THREE.Group; assert.equal(root.name, "remote-peer"); assert.equal(JSON.stringify(root.userData).includes("private-member-id"), false); assert.equal(root.getObjectByName("humanoid.face") instanceof THREE.Mesh, true); assert.equal((mesh(root, "humanoid.face").material as THREE.MeshBasicMaterial).map, null); peers.tick(1_000); assert.deepEqual(root.position.toArray(), [1, 2, 3]); assert.equal(peers.upsert(actor("private-member-id", "humanoid", 2, 2_000, 5)), true); peers.tick(1_500); assert.equal(peers.root.children[0], root); assert.equal(root.position.x, 3); assert.equal(peers.upsert(actor("private-member-id", "humanoid", 2, 2_100, 8)), false); peers.dispose(); }); it("resets interpolation at local interest-cell boundaries without replacing the root", () => { const peers = fixture(); peers.upsert(actor("a", "dog", 1, 1_000, 0)); peers.upsert(actor("a", "dog", 2, 2_000, 10)); peers.tick(1_500); const root = peers.root.children[0] as THREE.Group; assert.equal(root.position.x, 5); const nextCell = { kind: "floor", officeId: "hq", floorId: "two" } as const; assert.equal(peers.upsert(actor("a", "dog", 3, 3_000, 100, nextCell)), true); peers.tick(2_500); assert.equal(peers.root.children[0], root); assert.equal(root.position.x, 100, "new coordinate frame is held, never mixed with old floor"); peers.dispose(); }); it("projects geographic vehicles onto caller terrain and renders a generic black EV", () => { const peers = fixture(); const snapshot = vehicle(1, 1_000, 34); assert.equal(scenePeerId(snapshot), "vehicle:ev-1"); peers.upsert(snapshot); assert.equal(peers.tick(1_000), 1); const root = peers.root.children[0] as THREE.Group; assert.deepEqual(root.position.toArray(), [-240, 6, -102]); assert.equal(root.scale.x, 0.1); assert.ok(Math.abs(root.rotation.y + Math.PI / 2) < 1e-12); assert.equal(root.getObjectByName("generic-black-ev")?.userData.vehicleModel, "generic-black-ev"); assert.equal(root.getObjectByName("frontLeft.spin")?.rotation.x, -snapshot.wheelRadians); const paint = root.getObjectByName("model-x.body:model-x.paint") as THREE.Mesh; assert.equal((paint.material as THREE.MeshStandardMaterial).color.getHex(), 0x050607); peers.dispose(); }); it("renders a remote piloted aircraft with authoritative bank and rig state", () => { const peers = fixture(); const snapshot = aircraft(1, 1_000, 37.7); assert.equal(scenePeerId(snapshot), "aircraft:evtol-1"); assert.equal(peers.upsert(snapshot), true); assert.equal(peers.tick(1_000), 1); const root = peers.root.children[0] as THREE.Group; assert.deepEqual(root.position.toArray(), [-242, 155, -113.10000000000001]); assert.ok(Math.abs(root.rotation.x - 5 * Math.PI / 180) < 1e-12); assert.ok(Math.abs(root.rotation.y + 30 * Math.PI / 180) < 1e-12); assert.ok(Math.abs(root.rotation.z + 18 * Math.PI / 180) < 1e-12); assert.ok(root.getObjectByName("electric-aircraft")); assert.equal(root.getObjectByName("electric-aircraft.fan-left")?.rotation.z, 2.4); assert.ok(Math.abs((root.getObjectByName("electric-aircraft.aileron-left")?.rotation.x ?? 0) - 0.18) < 1e-12); peers.dispose(); }); it("shares prototype resources while kind changes retain the entity root", () => { const peers = fixture(); peers.upsert(actor("one", "humanoid", 1, 1_000, 0)); peers.upsert(actor("two", "humanoid", 1, 1_000, 2)); const one = peers.root.children[0] as THREE.Group; const two = peers.root.children[1] as THREE.Group; assert.equal(mesh(one, "humanoid.chest").geometry, mesh(two, "humanoid.chest").geometry); assert.equal(mesh(one, "humanoid.chest").material, mesh(two, "humanoid.chest").material); const oldRig = one.children[0]; peers.upsert(actor("one", "crow", 2, 2_000, 1)); peers.tick(2_000); assert.equal(peers.root.children[0], one); assert.equal(oldRig?.parent, null); assert.ok(one.getObjectByName("crow")); peers.dispose(); }); it("bounds nearby peers and removes/clears without prematurely disposing shared assets", () => { const peers = fixture({ maximumPeers: 2 }); peers.upsert(actor("one", "humanoid", 1, 1_000, 0)); peers.upsert(actor("two", "dog", 1, 1_000, 1)); assert.equal(peers.upsert(actor("three", "crow", 1, 1_000, 2)), false); const firstPeer = peers.root.children[0]; if (!firstPeer) throw new Error("missing first peer"); const geometry = mesh(firstPeer, "humanoid.chest").geometry; let disposals = 0; geometry.addEventListener("dispose", () => disposals++); assert.equal(peers.remove("actor:one"), true); assert.equal(peers.remove("actor:one"), false); assert.equal(disposals, 0, "removing one clone cannot release shared prototype resources"); peers.clear(); assert.equal(peers.count(), 0); assert.deepEqual(peers.ids(), []); assert.equal(disposals, 0); peers.dispose(); peers.dispose(); assert.equal(disposals, 1); assert.equal(peers.upsert(actor("late", "humanoid", 1, 1_000, 0)), false); }); it("contains invalid snapshots and projection failures", () => { const peers = fixture({ project: () => [Number.NaN, 0] }); assert.equal(peers.upsert({} as EntityPoseSnapshot), false); peers.upsert(vehicle(1, 1_000, 34)); assert.equal(peers.tick(1_000), 0); assert.equal(peers.root.children[0]?.visible, false); assert.equal(peers.tick(Number.NaN), 0); peers.dispose(); assert.throws(() => fixture({ maximumPeers: 0 }), RangeError); }); });