1
0

feat: complete actor handoff and piloted aircraft presence

This commit is contained in:
2026-08-11 22:17:06 -07:00
parent 655c383061
commit 3326d2e6d0
20 changed files with 907 additions and 41 deletions
+37
View File
@@ -5,6 +5,7 @@ import {
createScenePeers,
scenePeerId,
type ActorPoseSnapshot,
type AircraftPoseSnapshot,
type EntityPoseSnapshot,
type InterestCell,
type ScenePeersOptions,
@@ -48,6 +49,25 @@ function vehicle(sequence: number, timestampMs: number, lat: number): VehiclePos
};
}
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<ScenePeersOptions> = {}) {
return createScenePeers({
project: (lat, lng) => [lng * 2, -lat * 3],
@@ -120,6 +140,23 @@ describe("remote scene peers", () => {
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));