151 lines
4.7 KiB
TypeScript
151 lines
4.7 KiB
TypeScript
/**
|
|
* Where the shipped buildings stand, separately from the buildings themselves.
|
|
*
|
|
* An `Office` pack carries its own `site`, and that is still the authority — a
|
|
* pack handed over HTTP by a self-hoster brings its site with it and never
|
|
* touches this file. What this file exists for is the one question the *city*
|
|
* asks, which a pack cannot answer without being loaded: **where are the
|
|
* buildings I could walk into?**
|
|
*
|
|
* The office packs are deliberately lazy chunks. `lumbridge-hq` alone is 25 kB
|
|
* of furniture and floor plan, and the whole point of `loadOffice`'s dynamic
|
|
* import is that a visitor who only ever looks at the city never pays for it.
|
|
* But the city wants to draw a marker on the two buildings the moment the board
|
|
* appears, which is long before anybody has opened a door — so importing a pack
|
|
* to read four numbers off it would put the entire catalogue back in the entry
|
|
* chunk and undo the split.
|
|
*
|
|
* Hence a tiny eagerly-imported module holding just the coordinates, and each
|
|
* pack importing its own site **from here** rather than declaring it inline. One
|
|
* source of truth, and the direction of the dependency is the safe one: the
|
|
* small thing does not know about the large one.
|
|
*/
|
|
|
|
import type { OfficeSite } from "../interiors/types.ts";
|
|
|
|
/**
|
|
* High in a Transbay tower. See `lumbridge-hq.ts` for what the four numbers mean
|
|
* and why `heading` is the one that decides whether the sun ever gets in.
|
|
*/
|
|
export const LUMBRIDGE_HQ_SITE: OfficeSite = {
|
|
lat: 37.7897,
|
|
lng: -122.3972,
|
|
elevation: 188,
|
|
heading: 205,
|
|
label: "Transbay, San Francisco",
|
|
exterior: {
|
|
kind: "building",
|
|
width: 48,
|
|
depth: 42,
|
|
height: 326,
|
|
storeys: 61,
|
|
heading: 205,
|
|
profile: "tower",
|
|
seed: 115,
|
|
bodyColor: 0x8799a8,
|
|
},
|
|
};
|
|
|
|
/** A hangar on the old naval air station. See `frontier-valley.ts`. */
|
|
export const FRONTIER_VALLEY_SITE: OfficeSite = {
|
|
lat: 37.7756,
|
|
lng: -122.3186,
|
|
elevation: 4,
|
|
heading: 0,
|
|
label: "Alameda Point",
|
|
exterior: {
|
|
kind: "building",
|
|
width: 54,
|
|
depth: 30,
|
|
height: 11,
|
|
storeys: 2,
|
|
heading: 0,
|
|
profile: "hangar",
|
|
seed: 2718,
|
|
bodyColor: 0x899397,
|
|
},
|
|
};
|
|
|
|
/**
|
|
* A courtyard block in the Arts District, square to the pueblo grid rather than
|
|
* to the compass — which is the whole reason `heading` is a field. See
|
|
* `mateo-court.ts` for where the numbers come from: 1.2 m is a loading dock, and
|
|
* 36° is the 1781 survey the downtown street grid still follows.
|
|
*/
|
|
export const MATEO_COURT_SITE: OfficeSite = {
|
|
lat: 34.0395,
|
|
lng: -118.2288,
|
|
elevation: 1.2,
|
|
heading: 36,
|
|
label: "Arts District, Los Angeles",
|
|
exterior: {
|
|
kind: "building",
|
|
width: 36,
|
|
depth: 26,
|
|
height: 9,
|
|
storeys: 2,
|
|
heading: 36,
|
|
profile: "courtyard",
|
|
seed: 1781,
|
|
bodyColor: 0xa87960,
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Every building this build can walk into, for the city to point at.
|
|
*
|
|
* `id` matches the pack's own `Office.id` and the `OFFICES` table in `main.ts`,
|
|
* which is what lets a click on a marker resolve to a door. Keeping the three in
|
|
* step is not enforced by the type system; it is enforced by there being three of
|
|
* them and by `office.test.ts` asserting that each pack's site is the very
|
|
* object named here — identity, not equality, so a restated coordinate fails.
|
|
*/
|
|
export const SHIPPED_OFFICE_IDS = ["lumbridge-hq", "frontier-valley", "mateo-court"] as const;
|
|
|
|
export type ShippedOfficeId = (typeof SHIPPED_OFFICE_IDS)[number];
|
|
export type OfficeStatus = "active" | "building";
|
|
|
|
/**
|
|
* The public, eager metadata for one shipped environment.
|
|
*
|
|
* `status` is about the authored runtime, not a lease or a headcount. `active`
|
|
* means the environment is ready to enter; it never implies that people are in
|
|
* the building. `entryCopy` is intentionally operational and contains no
|
|
* invented street address or staffing claim.
|
|
*/
|
|
export interface OfficeDirectoryEntry {
|
|
id: ShippedOfficeId;
|
|
name: string;
|
|
status: OfficeStatus;
|
|
entryCopy: string;
|
|
site: OfficeSite;
|
|
}
|
|
|
|
export const OFFICE_SITES: readonly OfficeDirectoryEntry[] = [
|
|
{
|
|
id: "lumbridge-hq",
|
|
name: "SF HQ · Studio",
|
|
status: "active",
|
|
entryCopy: "Enter the compact live/work studio",
|
|
site: LUMBRIDGE_HQ_SITE,
|
|
},
|
|
{
|
|
id: "frontier-valley",
|
|
name: "Frontier Valley",
|
|
status: "building",
|
|
entryCopy: "Preview the hangar environment in progress",
|
|
site: FRONTIER_VALLEY_SITE,
|
|
},
|
|
{
|
|
id: "mateo-court",
|
|
name: "LA HQ · Office",
|
|
status: "active",
|
|
entryCopy: "Enter the courtyard office and robotics lab",
|
|
site: MATEO_COURT_SITE,
|
|
},
|
|
];
|
|
|
|
export function officeDirectoryEntry(id: string): OfficeDirectoryEntry | undefined {
|
|
return OFFICE_SITES.find((entry) => entry.id === id);
|
|
}
|