1
0

feat: add active SF and LA HQ environments

This commit is contained in:
2026-08-19 02:51:17 -07:00
parent afa285bd5c
commit 0557a26e6b
14 changed files with 1096 additions and 2312 deletions
+61 -66
View File
@@ -118,25 +118,21 @@ describe("the reference pack resolves cleanly", () => {
* and setting it to the ceiling height is the classic way to bury one storey's
* slab inside the one below.
*/
it("stacks the storeys floor-to-floor, not floor-to-ceiling", () => {
const [first, second] = plan.levels;
assert.ok(first && second, "both storeys should resolve");
assert.equal(first.id, "level-1");
assert.equal(second.id, "level-2");
assert.equal(first.floorY, 0);
const ceiling = LUMBRIDGE_HQ.levels[0]?.wallHeight ?? 0;
assert.ok(
second.floorY > ceiling,
`level 2's slab at ${second.floorY} m is inside level 1, whose ceiling is at ${ceiling} m`,
);
it("is an honest twelve-by-nine metre single-level studio", () => {
assert.deepEqual(plan.levels.map((level) => [level.id, level.floorY]), [["level-1", 0]]);
assert.deepEqual(LUMBRIDGE_HQ.levels[0]?.floorplan.rooms[3]?.outline, [
{ x: 0.2, z: 3.15 },
{ x: 0.2, z: 8.8 },
{ x: 11.8, z: 8.8 },
{ x: 11.8, z: 3.15 },
]);
});
it("keeps every viewpoint on a level that exists", () => {
// `Plan` drops a viewpoint whose level does not resolve, so this is really
// an assertion that none were dropped — which the count makes visible in a
// way `problems` being empty already implies but does not state.
assert.equal(plan.viewpoints.length, 8);
assert.equal(plan.viewpoints.length, 5);
const levels = new Set(plan.levels.map((l) => l.id));
for (const v of plan.viewpoints) assert.ok(levels.has(v.levelId), `${v.id} is on nothing`);
});
@@ -163,7 +159,8 @@ describe("seat ids", () => {
*/
it("expand the desk banks to the documented ids", () => {
const ids = new Set(seats.map((s) => s.id));
for (const id of ["eng-01", "eng-12", "studio-01", "studio-12", "studio-b-01"]) {
assert.equal(seats.length, 5);
for (const id of ["sf-agent-01", "sf-agent-02", "sf-island-01", "sf-island-02", "sf-lounge-01"]) {
assert.ok(ids.has(id), `${id} is missing`);
}
});
@@ -186,8 +183,7 @@ describe("every room is reachable on foot", () => {
/** Where somebody arrives: the entrance downstairs, the landing upstairs. */
const ENTRY: Record<string, { x: number; z: number }> = {
"level-1": { x: 1.2, z: 4.9 },
"level-2": { x: 2.4, z: 4.0 },
"level-1": { x: 1.02, z: 7.68 },
};
function reachableRooms(levelId: string): Set<string> {
@@ -257,24 +253,12 @@ describe("every room is reachable on foot", () => {
* the only place the difference between a balustrade and a handrail-shaped prop
* is observable. A prop would leave the edge open and nothing would look wrong.
*/
describe("the gallery balustrade", () => {
const OUTSIDE = 0.6;
it("stops a walker at all three open edges", () => {
const edges: [string, { x: number; z: number }, { x: number; z: number }][] = [
// North edge, at z = 2.0: standing on the gallery, stepping north.
["north", { x: 36.0, z: 2.6 }, { x: 36.0, z: 2.0 - OUTSIDE }],
// East edge, at x = 38.2: stepping out over the commons.
["east", { x: 37.6, z: 9.0 }, { x: 38.2 + OUTSIDE, z: 9.0 }],
// South edge, at z = 16.0.
["south", { x: 36.0, z: 15.4 }, { x: 36.0, z: 16.0 + OUTSIDE }],
];
for (const [name, from, to] of edges) {
assert.ok(
plan.blocked("level-2", from, to, 0.3),
`the ${name} edge of the gallery lets a walker off a 16.8 m drop`,
);
}
describe("the studio arrival", () => {
it("starts inside the live/work room with collision-clear movement", () => {
const arrival = LUMBRIDGE_HQ.viewpoints[0]?.focus.at;
assert.ok(arrival);
assert.equal(plan.roomAt("level-1", arrival)?.id, "live-work");
assert.equal(plan.blocked("level-1", arrival, { x: arrival.x + 0.6, z: arrival.z }, 0.3), false);
});
/**
@@ -282,8 +266,11 @@ describe("the gallery balustrade", () => {
* balcony you cannot fall off and also cannot reach is a balcony nobody has
* noticed is broken.
*/
it("does not seal the gallery off from the studio", () => {
assert.ok(!plan.blocked("level-2", { x: 33.0, z: 7.4 }, { x: 35.0, z: 7.4 }, 0.3));
it("keeps all five authored views meaningful and distinct", () => {
assert.deepEqual(
LUMBRIDGE_HQ.viewpoints.map((view) => view.id),
["arrival", "studio", "agent-bench", "demo-lounge", "kitchen-home"],
);
});
});
@@ -293,38 +280,26 @@ describe("the gallery balustrade", () => {
* `Wall` carries a height; get the second wrong and the void has a lid at 2.8 m
* that you cannot see but the light rig can.
*/
describe("the commons is open to both storeys", () => {
it("has no ceiling", () => {
describe("the studio programme", () => {
it("names every promised live/work zone without pretending it is a tower floor", () => {
const level1 = plan.levels.find((l) => l.id === "level-1");
const commons = level1?.rooms.find((r) => r.id === "commons");
assert.ok(commons, "the commons is missing");
assert.equal(commons.ceiling, null);
assert.deepEqual(
level1?.rooms.map((room) => room.name),
["Kitchen", "Sleeping Alcove", "Bath / Storage", "Live / Work Studio"],
);
});
it("is enclosed to two storeys rather than one", () => {
const [level1, level2] = plan.levels;
assert.ok(level1 && level2);
// The height the void *should* be, derived rather than typed: everything up
// to level 2's slab, plus level 2's own room. That is what "open to both
// storeys" means, and it stays true whatever the interstitial is set to.
const ceiling = LUMBRIDGE_HQ.levels[1]?.wallHeight ?? 0;
const expected = level2.floorY + ceiling;
// `solid` only. The splitting pass emits a run per piece, so a wall with a
// door in it also yields a `lintel` over the opening — correct, and not the
// wall's height.
const wingWalls = level1.runs.filter(
(run) => run.wallId.startsWith("wing-") && run.role === "solid",
);
assert.ok(wingWalls.length > 0, "the wing has no walls");
for (const run of wingWalls) {
assert.equal(
run.top - run.bottom,
expected,
`${run.wallId} is ${run.top - run.bottom} m tall, not the ${expected} m the void needs`,
);
}
it("uses the complete original habitat kit", () => {
const kinds = new Set((LUMBRIDGE_HQ.levels[0]?.floorplan.props ?? []).map((prop) => prop.kind));
for (const id of [
"tera:bed.platform",
"tera:sofa.modular",
"tera:kitchen.run",
"tera:kitchen.island",
"tera:storage.wardrobe",
"tera:seat.stool",
"tera:light.floor",
]) assert.ok(kinds.has(id), `${id} is not placed in SF HQ`);
});
});
@@ -530,6 +505,17 @@ describe("the office site table", () => {
assert.equal(entry.site, pack.site, `${pack.id} has a site of its own`);
}
});
it("publishes truthful environment names and runtime status", () => {
assert.deepEqual(
OFFICE_SITES.map(({ id, name, status }) => ({ id, name, status })),
[
{ id: "lumbridge-hq", name: "SF HQ · Studio", status: "active" },
{ id: "frontier-valley", name: "Frontier Valley", status: "building" },
{ id: "mateo-court", name: "LA HQ · Office", status: "active" },
],
);
});
});
/**
@@ -571,6 +557,15 @@ describe("the Mateo Court pack", () => {
assert.deepEqual(mine.filter((id) => others.has(id)), []);
});
it("caps the authored office at twenty-four useful seat addresses", () => {
const ids = mc.allSeats().map((seat) => seat.id);
assert.equal(ids.length, 24);
for (const id of ["works-a-01", "works-a-12", "loft-a-01", "loft-a-02", "review-04", "loggia-01"]) {
assert.ok(ids.includes(id), `${id} is missing`);
}
assert.equal(ids.some((id) => id.startsWith("works-b-")), false);
});
/**
* **The check that matters most in this pack.**
*
@@ -613,7 +608,7 @@ describe("the Mateo Court pack", () => {
});
it("stands its upper-floor occupants on the deck", () => {
for (const id of ["loggia-01", "palmetto-01"]) {
for (const id of ["loggia-01", "loft-a-01"]) {
assert.equal(mc.seat(id)?.y, 5, `${id} is not on the deck`);
}
});
+64
View File
@@ -0,0 +1,64 @@
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import * as THREE from "three";
import { createAssetContext, kit } from "../assets/kit.ts";
import { MaterialRegistry } from "../assets/materials.ts";
import "../assets/office/index.ts";
const HABITAT_IDS = [
"tera:bed.platform",
"tera:sofa.modular",
"tera:kitchen.run",
"tera:kitchen.island",
"tera:storage.wardrobe",
"tera:seat.stool",
"tera:light.floor",
] as const;
function seeded(): () => number {
let value = 0x12345678;
return () => {
value = (Math.imul(value, 1664525) + 1013904223) >>> 0;
return value / 0x1_0000_0000;
};
}
function disposeObject(object: THREE.Object3D): void {
object.traverse((child) => {
if (child instanceof THREE.Mesh) child.geometry.dispose();
});
}
describe("procedural habitat assets", () => {
it("registers finite metre-scale footprints for the complete studio kit", () => {
for (const id of HABITAT_IDS) {
assert.equal(kit.has(id), true, `${id} is not registered`);
const footprint = kit.footprintOf(id);
for (const value of [footprint.width, footprint.depth, footprint.height]) {
assert.ok(Number.isFinite(value) && value > 0 && value < 5, `${id} has invalid footprint ${value}`);
}
}
});
it("builds deterministic, non-placeholder geometry with finite bounds", () => {
const materials = new MaterialRegistry({ quality: "low" });
try {
for (const id of HABITAT_IDS) {
const first = kit.build(id, createAssetContext({ materials, rand: seeded() }));
const second = kit.build(id, createAssetContext({ materials, rand: seeded() }));
assert.equal(first.userData.assetId, id);
assert.notEqual(first.userData.missing, true);
const firstBox = new THREE.Box3().setFromObject(first);
const secondBox = new THREE.Box3().setFromObject(second);
const encode = (box: THREE.Box3) => [...box.min.toArray(), ...box.max.toArray()];
assert.deepEqual(encode(firstBox), encode(secondBox), `${id} is not deterministic`);
assert.ok(encode(firstBox).every(Number.isFinite), `${id} has non-finite bounds`);
assert.ok(firstBox.max.y > 0, `${id} has no visible height`);
disposeObject(first);
disposeObject(second);
}
} finally {
materials.dispose();
}
});
});
+42
View File
@@ -0,0 +1,42 @@
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { samplePresenceAt, samplePresenceForOfficeAt } from "../adapters/sample.ts";
import FRONTIER_VALLEY from "../offices/frontier-valley.ts";
import LUMBRIDGE_HQ from "../offices/lumbridge-hq.ts";
import MATEO_COURT from "../offices/mateo-court.ts";
import { activityRobotsForOffice } from "../offices/runtime.ts";
describe("office-keyed runtime activity", () => {
it("authors one deterministic SF robot, two LA robots, and none in a building preview", () => {
assert.deepEqual(activityRobotsForOffice(LUMBRIDGE_HQ), [
{ id: "sf-studio-activity-01", levelId: "level-1", seed: 0x53464851, jobSet: "studio-support" },
]);
assert.deepEqual(activityRobotsForOffice(MATEO_COURT), [
{ id: "la-office-activity-01", levelId: "level-1", seed: 0x4c414851, jobSet: "office-operations" },
{ id: "la-office-activity-02", levelId: "level-2", seed: 0x4c414852, jobSet: "model-review" },
]);
assert.deepEqual(activityRobotsForOffice(FRONTIER_VALLEY), []);
});
it("returns defensive specs and drops a robot when a local pack removes its level", () => {
const first = activityRobotsForOffice(MATEO_COURT);
first[0]!.id = "mutated";
assert.equal(activityRobotsForOffice(MATEO_COURT)[0]?.id, "la-office-activity-01");
assert.deepEqual(activityRobotsForOffice({ id: MATEO_COURT.id, levels: [MATEO_COURT.levels[0]!] }), [
{ id: "la-office-activity-01", levelId: "level-1", seed: 0x4c414851, jobSet: "office-operations" },
]);
});
});
describe("office-keyed presence fallback", () => {
const workingHour = new Date(2026, 7, 19, 11, 0, 0);
it("never fabricates people at either active HQ", () => {
assert.deepEqual(samplePresenceForOfficeAt("lumbridge-hq", workingHour), []);
assert.deepEqual(samplePresenceForOfficeAt("mateo-court", workingHour), []);
});
it("retains the legacy roster only as an explicit renderer fixture", () => {
assert.ok(samplePresenceAt(workingHour).length > 0);
});
});