@adatechnology/game-floorplan 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/MIGRATION.md CHANGED
@@ -331,6 +331,38 @@ The palette recipes per style are data supplied by the packs (`registerPaletteSt
331
331
  - Everything the old SDK held in Portuguese (names, labels, reasons, messages) is now a key plus a locale entry (`en`, `pt-BR`). Register more with `engine.registerLocale('xx', table)`.
332
332
  - Randomness is drawn from the same named streams as before so seeds reproduce. Those stream names are the only Portuguese left in the code, in each pack's `legacy-seeds.ts` (for example `'fachada'`, `'lote'`, `'c:sala'`, `'estado:protegida'`). Do not translate them: changing a stream name changes every plan generated from an existing seed.
333
333
 
334
+ ## Rules from the Visor de casas 3D (spec 001, T2.2b)
335
+
336
+ The team page (PlantasSDK of the Visor de casas 3D, VC3) kept changing the generator after this port was made (86 regions, rules R01-R72). The engine now follows it; with the id
337
+ tables of the four MIGRATION files, the 12 residential and commercial templates give the same rooms, walls, openings, items, state items and lot as the page
338
+ (900 plans recorded in `game-floorplan-post-apocalyptic/tests/fixtures/team-golden/vc3-plans.json`, plus 4500 more checked once). **The old VP-equality claim above no longer holds**:
339
+ plans differ from the earlier port on purpose. The five rural templates are still to come (T2.2f).
340
+
341
+ | VC3 | Engine | Effect |
342
+ |---|---|---|
343
+ | `RAIO_JOG` 0.24 | option `playerRadius` (default 0.24, `engine.constants.PLAYER_RADIUS`) | walkability grid has 10 cm cells indoors and drops cells closer than the radius to a wall body; furniture may not close the way for that disc (relaxed pass: 0.12) |
344
+ | `PORTA_FOLGA`, `folga` | `DoorDef.clearance`, `TemplateDef.clearance.door` (default 0.12) | door never closer to a corner or junction than this |
345
+ | `JAN_FOLGA` 0.3, R10 | `TemplateDef.clearance.window`; windows are spread over the wall stretch they fall in (one centred, several with equal gaps, never near a corner, junction or door; bathroom windows small and high) | window positions differ from the earlier port |
346
+ | R43 `SEM_JANELA` | `WINDOWLESS_ROOM_TYPES`: any other room with an exterior wall gets a window in its longest free stretch | |
347
+ | `bloqueiaJanela`, `hjan`, `aereo`, `H_AEREO` 2.15 | `blocksWindow(item, window, overheadOff?)`, `FurnitureDef.windowHeight`, `FurnitureDef.overhead` | a wall cabinet and a shower enclosure block a window; a second pass drops the cabinet (`item.overhead = false`) |
348
+ | R30 `FOLGA_CARRO`, `candidatosCarro` | `parking.ts` (`carCandidates`), option `carClearance` (driver 0.8, side 0.6, end 0.6); the item gets `driver` and `carClearance` | the driver door of a parked car opens |
349
+ | `partesUteis` | `usableParts` | inset only where there is a real wall |
350
+ | `corposParedes` | the grid reads the wall bodies | |
351
+ | R07 | `paths.ts`: every ground-floor exterior door gets a paved path to the pedestrian gate or the nearest path (`path_<door id>`, `entrance_path` for the template's `doorTarget`); a building at the street line has `from: null` | |
352
+ | R23 | the yard water tank slot has `chance: 0` (the tank sits on the slab, T2.2e) | |
353
+ | R20 | `mailbox` item on the front wall beside the pedestrian gate | |
354
+ | R64 | `table_lamp` on a nightstand, dresser or console table (stream `abajur:<room legacy key>`) | |
355
+ | R66 | `single_storey_a`: the bathroom opens from the living room, washbasin on the back wall | |
356
+ | state | fortified: at least one window boarded, the barricade must cover the door zone, a mattress search on a fixed grid in tight houses; abandoned: clothes and stains retry until 2 | |
357
+ | hooks for the rural pack | `TemplateDef.noWalls`, `cumulativeCeilings`, `reservations`, `paths`, `place`; `DoorDef.edge`, `model`, `type`, `steps`; `LotConfig.extraZones`; `StyleDef.fenceHeight`; slot `floorFree`; `FurnitureDef.exactOnly` | |
358
+
359
+ New vocabulary (VC3 names to SDK): door `tipo` is `type` (`porta` is `door`), `degraus` is `steps`, item `aereo` is `overhead`, `hjan` is `windowHeight`, `so` is `exactOnly`.
360
+
361
+ New API: `registerResultExtension(name, run, { after?, seedKey? })` (output in `result[name]`, runs after the state and before the zoning report, `rng = createRng(seed, seedKey ?? name)`, so a pack can
362
+ reproduce a team stream and the structure pack puts `result.structure` in the plan), `registerFindsProvider(provider)` and `findsFor(query)` (stub for phase 3: `FindsQuery { place, container, state, rng, day?, region?, footprint?, key? }`,
363
+ `FindStack { itemId, count, data? }`), `registerViewerLayer(layer)` (a pack adds a checkbox and a drawing to the 2D viewer; `engine.viewerLayers`). Furniture extension fields live on `FurnitureDef` (the former `ItemDef` of this package,
364
+ renamed so it does not collide with the item catalogue's `ItemDef`).
365
+
334
366
  ## Zoning (new)
335
367
 
336
368
  Urban zoning is a generic layer in the engine; the zones themselves are content (see the residential and commercial `regions/br`).
package/dist/index.d.ts CHANGED
@@ -5,60 +5,6 @@ declare function hashString(input: string | number): number;
5
5
  /** Independent stream for a `(seed, key)` pair. */
6
6
  declare const createRng: (seed: string | number, key: string) => Rng;
7
7
 
8
- /** Tools handed to a style recipe. `jit` and `rng` draw from the style's seeded stream: draw order is part of the contract. */
9
- interface PaletteDraw {
10
- rng: Rng;
11
- base: [string, number, number, number];
12
- H0: number;
13
- H1: number;
14
- H2: number;
15
- jit(v: number, a: number): number;
16
- hsl(h: number, s: number, l: number): Hsl;
17
- }
18
- interface PaletteEarly {
19
- /** Accent mode: true saturates walls, false puts accents on objects. */
20
- wallMode: boolean;
21
- /** Maximum wall saturation. */
22
- sMax: number;
23
- /** Facade, wall, gate, roof, ceiling... in insertion order. */
24
- roles: Record<string, Hsl>;
25
- /** General floor `[h, s, l]` for room types that do not define their own. */
26
- generalFloor: [number, number, number];
27
- }
28
- interface PaletteStyleDef {
29
- /** Legacy stream suffix; defaults to the style id. */
30
- seedKey?: string;
31
- /** Facade colour table `[labelKey, h, s, l]`. */
32
- facadeColors: [string, number, number, number][];
33
- /** Draws up to the room colours (before the room loop). */
34
- early(d: PaletteDraw): PaletteEarly;
35
- /** Draws the object roles (wood, fabrics, metal, ground colours) after the room loop. */
36
- late(d: PaletteDraw, e: PaletteEarly): Record<string, Hsl>;
37
- }
38
- interface PaletteContext extends PaletteDraw {
39
- style: string;
40
- sMax: number;
41
- wallMode: boolean;
42
- generalFloor: [number, number, number];
43
- }
44
- interface PaletteOptions {
45
- seed?: number | string;
46
- style?: string;
47
- state?: string;
48
- }
49
- type Palette = {
50
- meta: {
51
- seed: number | string;
52
- style: string;
53
- state: string;
54
- scheme: string;
55
- base: string;
56
- accentMode: 'wall' | 'object';
57
- };
58
- } & Record<string, number | object>;
59
- /** Seeded colour-harmony palette: a facade base colour, a harmony scheme, role colours and contrast rules. */
60
- declare function palette(o?: PaletteOptions): Palette;
61
-
62
8
  /** Axis-aligned rectangle `[u0, v0, u1, v1]`. `u` runs along the facade, `v` from the street to the back. */
63
9
  type Rect = [number, number, number, number];
64
10
  type Vec2 = [number, number];
@@ -74,7 +20,7 @@ type ItemColor = {
74
20
  } | {
75
21
  pick: number[];
76
22
  };
77
- interface ItemDef {
23
+ interface FurnitureDef {
78
24
  type: string;
79
25
  category: string;
80
26
  w: number;
@@ -92,11 +38,19 @@ interface ItemDef {
92
38
  /** Keep-out margin around the item (pools). */
93
39
  rim: number;
94
40
  decor?: boolean;
41
+ /** Hangs a wall cabinet over the counter (y 1.55 to 2.15 m): it blocks a window unless the fill dropped the cabinet. */
42
+ overhead?: boolean;
43
+ /** Effective height that blocks a window when taller than `h` (a shower enclosure is 0.1 m tray plus 1.95 m glass). */
44
+ windowHeight?: number;
45
+ /** Plugs into a socket (lamps, appliances). */
46
+ powered?: boolean;
47
+ /** Only picked when a slot names its exact type (`=type`), never through its category. */
48
+ exactOnly?: boolean;
95
49
  mount?: Mount;
96
50
  equip?: string[];
97
51
  color?: ItemColor;
98
52
  }
99
- type ItemInput = Pick<ItemDef, 'type' | 'category' | 'w' | 'd' | 'h'> & Partial<ItemDef>;
53
+ type ItemInput = Pick<FurnitureDef, 'type' | 'category' | 'w' | 'd' | 'h'> & Partial<FurnitureDef>;
100
54
  type Anchor = 'wall' | 'corner' | 'center' | 'window' | 'on' | 'inside';
101
55
  type Side = 'left' | 'right' | 'front' | 'back' | 'any';
102
56
  type FacingRule = 'center' | 'door' | 'target' | 'u+' | 'u-' | 'v+' | 'v-';
@@ -163,6 +117,18 @@ interface DoorDef {
163
117
  width: number;
164
118
  opensTo?: string;
165
119
  steel?: boolean;
120
+ /** Clear wall from the opening to a corner or junction; defaults to the template's `clearance.door`, else 0.12 m. */
121
+ clearance?: number;
122
+ /** Explicit position instead of a wall edge (a tent flap in the middle of the lot). */
123
+ edge?: {
124
+ axis: 'u' | 'v';
125
+ pos: number;
126
+ a0: number;
127
+ a1: number;
128
+ };
129
+ model?: string;
130
+ type?: string;
131
+ steps?: number;
166
132
  [extra: string]: Json;
167
133
  }
168
134
  interface WindowDef {
@@ -206,6 +172,14 @@ interface LotConfig {
206
172
  side: string;
207
173
  };
208
174
  libraries?: Record<string, string>;
175
+ /** Lot zones over the building area (a camp). */
176
+ extraZones?: {
177
+ id: string;
178
+ type: string;
179
+ label?: string;
180
+ parts: Rect[];
181
+ library?: string;
182
+ }[];
209
183
  yardZones?: {
210
184
  id: string;
211
185
  type: string;
@@ -246,6 +220,35 @@ interface TemplateDef {
246
220
  facadeExtra?: (facade: Json, rng: Rng, w: number, d: number, o: FloorplanOptions) => void;
247
221
  building?: (w: number, d: number, o: FloorplanOptions) => Json;
248
222
  singleFloor?: boolean;
223
+ /** Place tag of the building for finds (`house`, `pharmacy`...). */
224
+ place?: string;
225
+ /** Building system the structure pack builds (a reference registered there). */
226
+ construction?: string;
227
+ /** Region of the content (`br`...), chosen by the pack that registered the template. */
228
+ region?: string;
229
+ /** Clear wall around openings: from a door to a corner or junction, and from a window to a corner, junction or door. */
230
+ clearance?: {
231
+ door?: number;
232
+ window?: number;
233
+ };
234
+ /** No walls are built (a tent): rooms and openings stay. */
235
+ noWalls?: boolean;
236
+ /** Storey heights add up (a mezzanine with a different ceiling) instead of `index * ceiling`. */
237
+ cumulativeCeilings?: boolean;
238
+ /** Settings the packs read from the plan (`power`: `grid`, `offgrid` or `tap`; `solar`); it lands in `result.config`. */
239
+ config?: (o: FloorplanOptions, w: number, d: number) => Json;
240
+ /** Marks lot areas taken by the building (chimney, tank, tents) as keep-out zones for the lot fill. */
241
+ reservations?: (plan: Plan) => void;
242
+ /** Own paths from the doors that sit away from the building edge (tents); replaces the generated ones. */
243
+ paths?: (plan: Plan, context: {
244
+ gates: Json[];
245
+ setback: number;
246
+ marginLeft: number;
247
+ marginRight: number;
248
+ backyard: number;
249
+ w: number;
250
+ d: number;
251
+ }) => Json[];
249
252
  /** Sides built against a neighbour (`left` / `right`): exempt from the side setback. */
250
253
  partyWalls?: ('left' | 'right')[];
251
254
  options?: Json;
@@ -262,6 +265,8 @@ interface StyleDef {
262
265
  /** Name of the legacy palette RNG stream (kept so old seeds still reproduce). */
263
266
  seedKey?: string;
264
267
  height: number;
268
+ /** Height of a fence boundary (default 2.0 m). */
269
+ fenceHeight?: number;
265
270
  front: BoundaryRule;
266
271
  sideYard: BoundaryRule;
267
272
  back: BoundaryRule;
@@ -278,7 +283,72 @@ interface StyleDef {
278
283
  /** Ground type weights per lot zone type. */
279
284
  grounds: Record<string, Weights>;
280
285
  }
286
+ interface CarClearance {
287
+ /** Clear space beside the driver door (m). */
288
+ driver: number;
289
+ /** Clear space on the passenger side (m). */
290
+ side: number;
291
+ /** Clear space in front of and behind the car (m). */
292
+ end: number;
293
+ }
294
+ interface ResultExtensionContext {
295
+ plan: Plan;
296
+ /** The result built so far: the plan, the items, the state items and the extensions that ran before. */
297
+ result: Json;
298
+ seed: number | string;
299
+ /** Seeded stream of the extension: `createRng(seed, seedKey ?? name)`. */
300
+ rng: Rng;
301
+ options: FloorplanOptions;
302
+ }
303
+ type ResultExtensionRun = (context: ResultExtensionContext) => Json;
304
+ interface ResultExtensionOptions {
305
+ /** Extensions that must run first. */
306
+ after?: string[];
307
+ /** Name of the seeded stream; defaults to the extension name. A pack sets the name of the team's own flow to reproduce its seeds. */
308
+ seedKey?: string;
309
+ }
310
+ interface FindStack {
311
+ readonly itemId: string;
312
+ readonly count: number;
313
+ readonly data?: {
314
+ readonly ageDays?: number;
315
+ readonly condition?: number;
316
+ readonly charge?: number;
317
+ readonly fill?: number;
318
+ };
319
+ }
320
+ interface FindsQuery {
321
+ /** Kind of place (`TemplateDef.place`, a room type, a lot zone type). */
322
+ place: string;
323
+ /** Kind of container (a furniture category). */
324
+ container: string;
325
+ state: string;
326
+ rng: Rng;
327
+ /** Outbreak days; 0 is the normal world. */
328
+ day?: number;
329
+ region?: string;
330
+ /** Footprint of the place in m². */
331
+ footprint?: number;
332
+ key?: string;
333
+ }
334
+ /**
335
+ * Answers what a container holds. Registered by an item pack; the engine only keeps the registry. An array is the answer, even an empty one (an abandoned
336
+ * cupboard that holds nothing); `null` means this provider does not know the container, and the next provider (or the default of the pack) answers.
337
+ */
338
+ interface FindsProvider {
339
+ findsFor(query: FindsQuery): readonly FindStack[] | null;
340
+ }
281
341
  interface FloorplanOptions {
342
+ /** Number of storeys, for templates that accept it. */
343
+ floors?: number;
344
+ /** Building system of the structure pack (`masonry`, `wood_frame`, ...). */
345
+ construction?: string;
346
+ /** How finely the structure pack splits the walls (`coarse`, `panels`, `units`). */
347
+ wallDetail?: 'coarse' | 'panels' | 'units';
348
+ /** Radius of the player body (m, default 0.24): a disc this wide must pass between doors and rooms once the furniture is placed. */
349
+ playerRadius?: number;
350
+ /** Space a parked car keeps from walls (default driver 0.8, side 0.6, end 0.6). */
351
+ carClearance?: Partial<CarClearance>;
282
352
  seed?: number | string;
283
353
  w?: number;
284
354
  d?: number;
@@ -291,6 +361,10 @@ interface FloorplanOptions {
291
361
  locale?: string;
292
362
  /** Urban zone id or definition to clamp the plan to. */
293
363
  zone?: string | ZoneDef;
364
+ /** Outbreak days for the finds (`FindsQuery.day`); 0 or none is the normal world. */
365
+ day?: number;
366
+ /** Region of the world for the finds (`FindsQuery.region`), as the item pack names it. */
367
+ region?: string;
294
368
  [extra: string]: Json;
295
369
  }
296
370
  interface Room {
@@ -334,6 +408,16 @@ interface Plan {
334
408
  facade?: Json;
335
409
  openPairs: Record<number, [string, string][]>;
336
410
  zoning?: ZoningReport;
411
+ /** Lot areas the building keeps out of the fill (set by `TemplateDef.reservations`). */
412
+ reservations: Rect[];
413
+ /** The options the plan was built with (seed included). */
414
+ options: FloorplanOptions;
415
+ /** Result of `TemplateDef.config`. */
416
+ config?: Json;
417
+ /** Cache of the wall bodies per storey, filled by the walkability grid. */
418
+ wallBodies?: Record<number, Rect[]>;
419
+ playerRadius: number;
420
+ carClearance: CarClearance;
337
421
  }
338
422
  interface Slot {
339
423
  id: string;
@@ -415,7 +499,7 @@ interface StateContext {
415
499
  /** Placement helpers shared with the decor passes. */
416
500
  ctx: PlacementContext;
417
501
  kit: PlacementKit;
418
- catalog: Record<string, ItemDef>;
502
+ catalog: Record<string, FurnitureDef>;
419
503
  wallTopHeights: Record<string, number>;
420
504
  }
421
505
  interface StatePlugin {
@@ -459,10 +543,13 @@ interface PlacementKit {
459
543
  createGrid(plan: Plan, room: Room, ignored?: Set<string> | null): Json;
460
544
  clearRect(r: Rect, f: Vec2, clearance: number): Rect;
461
545
  pickWeighted(rng: Rng, w: Weights): string;
546
+ createRng(seed: number | string, key: string): Rng;
547
+ /** Name of the room in seeded streams: the legacy key when the room id was renamed, else the id. */
548
+ roomSeedKey(room: Room): string;
462
549
  shuffle<T>(a: T[], rng: Rng): T[];
463
550
  facingRotation(f: Vec2, type: string): number;
464
551
  cutIntervals(intervals: [number, number][], a: number, b: number): [number, number][];
465
- blocksWindow(it: ItemDef, j: Json): boolean;
552
+ blocksWindow(it: FurnitureDef, j: Json, overheadOff?: boolean): boolean;
466
553
  }
467
554
  interface DecorPassContext {
468
555
  plan: Plan;
@@ -471,7 +558,7 @@ interface DecorPassContext {
471
558
  rng: Rng;
472
559
  ctx: PlacementContext;
473
560
  kit: PlacementKit;
474
- catalog: Record<string, ItemDef>;
561
+ catalog: Record<string, FurnitureDef>;
475
562
  /** Decor profiles registered per style id. */
476
563
  profiles: Record<string, Json>;
477
564
  }
@@ -514,8 +601,97 @@ interface FloorplanLocale {
514
601
  messages?: Record<string, string>;
515
602
  ui?: Record<string, string>;
516
603
  }
604
+ interface ViewerLayerContext {
605
+ /** Canvas 2D context, already in CSS pixels. */
606
+ g: CanvasRenderingContext2D;
607
+ plan: Json;
608
+ /** Storey being drawn (0 when `all`). */
609
+ floor: number;
610
+ /** All storeys at once (the lot view). */
611
+ all: boolean;
612
+ /** Metres to pixels. */
613
+ scale: number;
614
+ X(u: number): number;
615
+ Z(v: number): number;
616
+ rect(r: Rect, fill?: string | null, stroke?: string | null, lineWidth?: number): void;
617
+ /** Tooltip area (metres) with its text. */
618
+ hit(r: Rect, text: string): void;
619
+ }
620
+ interface ViewerLayerLegendEntry {
621
+ label: string;
622
+ color: string;
623
+ shape: 'filled' | 'hollow' | 'dashed' | 'line';
624
+ }
625
+ /** A layer a pack adds to the 2D viewer (the structure pack draws pillars and beams); the viewer shows a checkbox for it. */
626
+ interface ViewerLayer {
627
+ id: string;
628
+ /** Checkbox text, or a key of the `ui` locale table. */
629
+ label: string;
630
+ defaultOn?: boolean;
631
+ draw(context: ViewerLayerContext): void;
632
+ legend?(plan: Json): ViewerLayerLegendEntry[];
633
+ }
634
+
635
+ /** Tools handed to a style recipe. `jit` and `rng` draw from the style's seeded stream: draw order is part of the contract. */
636
+ interface PaletteDraw {
637
+ rng: Rng;
638
+ base: [string, number, number, number];
639
+ H0: number;
640
+ H1: number;
641
+ H2: number;
642
+ jit(v: number, a: number): number;
643
+ hsl(h: number, s: number, l: number): Hsl;
644
+ }
645
+ interface PaletteEarly {
646
+ /** Accent mode: true saturates walls, false puts accents on objects. */
647
+ wallMode: boolean;
648
+ /** Maximum wall saturation. */
649
+ sMax: number;
650
+ /** Facade, wall, gate, roof, ceiling... in insertion order. */
651
+ roles: Record<string, Hsl>;
652
+ /** General floor `[h, s, l]` for room types that do not define their own. */
653
+ generalFloor: [number, number, number];
654
+ }
655
+ interface PaletteStyleDef {
656
+ /** Legacy stream suffix; defaults to the style id. */
657
+ seedKey?: string;
658
+ /** Facade colour table `[labelKey, h, s, l]`. */
659
+ facadeColors: [string, number, number, number][];
660
+ /** Draws up to the room colours (before the room loop). */
661
+ early(d: PaletteDraw): PaletteEarly;
662
+ /** Draws the object roles (wood, fabrics, metal, ground colours) after the room loop. */
663
+ late(d: PaletteDraw, e: PaletteEarly): Record<string, Hsl>;
664
+ }
665
+ interface PaletteContext extends PaletteDraw {
666
+ style: string;
667
+ sMax: number;
668
+ wallMode: boolean;
669
+ generalFloor: [number, number, number];
670
+ }
671
+ interface PaletteOptions {
672
+ seed?: number | string;
673
+ style?: string;
674
+ state?: string;
675
+ }
676
+ type Palette = {
677
+ meta: {
678
+ seed: number | string;
679
+ style: string;
680
+ state: string;
681
+ scheme: string;
682
+ base: string;
683
+ accentMode: 'wall' | 'object';
684
+ };
685
+ } & Record<string, number | object>;
686
+ /** Seeded colour-harmony palette: a facade base colour, a harmony scheme, role colours and contrast rules. */
687
+ declare function palette(o?: PaletteOptions): Palette;
688
+
689
+ /** What a container holds, from the first registered provider that answers (`null` passes to the next); none answering means nothing. */
690
+ declare function findsFor(query: FindsQuery): readonly FindStack[];
691
+ /** Like `findsFor`, but `null` when no provider answered, so a pack can fall back to its own default. */
692
+ declare function findsAnswer(query: FindsQuery): readonly FindStack[] | null;
517
693
 
518
- declare function registerItem(def: ItemInput): ItemDef;
694
+ declare function registerItem(def: ItemInput): FurnitureDef;
519
695
  declare function registerItems(list: ItemInput[]): void;
520
696
  declare function registerLibrary(id: string, library: SlotLibrary): void;
521
697
  declare function registerLibraryAlias(alias: string, id: string): void;
@@ -537,6 +713,12 @@ declare function registerState(name: string, plugin: StatePlugin): void;
537
713
  /** Default state draw when `options.state` is absent: `{ state: weight }` on its own seeded stream. */
538
714
  declare function setStateDistribution(weights: Record<string, number> | null, seedKey?: string): void;
539
715
  declare const listStates: () => string[];
716
+ /** Adds a named piece to every result, after the state and before the zoning report; its output lands in `result[name]`. */
717
+ declare function registerResultExtension(name: string, run: ResultExtensionRun, options?: ResultExtensionOptions): void;
718
+ /** Registers who answers what a container holds (the item packs, from phase 3 on). */
719
+ declare function registerFindsProvider(provider: FindsProvider): void;
720
+ /** Adds (or replaces, by id) a layer of the 2D viewer; drawn after the items, before the labels. */
721
+ declare function registerViewerLayer(layer: ViewerLayer): void;
540
722
 
541
723
  /** Recorded slots (resolved positions) of every storey and of the lot. */
542
724
  declare function slots(template: string | TemplateDef, options?: FloorplanOptions): Json[];
@@ -603,6 +785,194 @@ declare function openingZones(u: number, v: number, axis: 'u' | 'v', width: numb
603
785
 
604
786
  /** Keep-out zone of a window (inside, or outside for the lot). */
605
787
  declare function windowZone(j: Json, outside?: boolean): Rect;
788
+ /** `overheadOff`: the counter sits under the window without its wall cabinet. */
789
+ declare function blocksWindow(it: Pick<FurnitureDef, 'window' | 'overhead' | 'windowHeight'> & {
790
+ h: number;
791
+ }, win: Json, overheadOff?: boolean): boolean;
792
+
793
+ /** One primitive of a far-away silhouette. Parts are listed in creation order; `parent` is the index of a group part (`-1` is the root). */
794
+ type SilhouettePart = {
795
+ shape: 'group';
796
+ parent: number;
797
+ x: number;
798
+ y: number;
799
+ z: number;
800
+ ry: number;
801
+ } | {
802
+ shape: 'box';
803
+ parent: number;
804
+ x: number;
805
+ y: number;
806
+ z: number;
807
+ width: number;
808
+ height: number;
809
+ depth: number;
810
+ color: number;
811
+ emissive: boolean;
812
+ ry: number;
813
+ rz: number;
814
+ radius: number;
815
+ } | {
816
+ shape: 'prism';
817
+ parent: number;
818
+ x: number;
819
+ y: number;
820
+ z: number;
821
+ width: number;
822
+ height: number;
823
+ depth: number;
824
+ color: number;
825
+ ry: number;
826
+ } | {
827
+ shape: 'cylinder';
828
+ parent: number;
829
+ x: number;
830
+ y: number;
831
+ z: number;
832
+ radiusTop: number;
833
+ radiusBottom: number;
834
+ height: number;
835
+ color: number;
836
+ segments: number;
837
+ } | {
838
+ shape: 'line';
839
+ parent: number;
840
+ points: [number, number, number][];
841
+ color: number;
842
+ } | {
843
+ shape: 'sign';
844
+ parent: number;
845
+ x: number;
846
+ y: number;
847
+ z: number;
848
+ width: number;
849
+ height: number;
850
+ ry: number;
851
+ text: string;
852
+ background: string;
853
+ foreground: string;
854
+ };
855
+ /** A window the renderer draws as an instance (a lit one glows). `ry` is the facing; the size is width by height. */
856
+ type SilhouetteWindow = {
857
+ x: number;
858
+ y: number;
859
+ z: number;
860
+ ry: number;
861
+ width: number;
862
+ height: number;
863
+ isLit: boolean;
864
+ };
865
+ type Silhouette = {
866
+ parts: SilhouettePart[];
867
+ windows: SilhouetteWindow[];
868
+ /** Footprint on the ground: centre and size, for the LOD plan. */
869
+ footprint: {
870
+ x: number;
871
+ z: number;
872
+ width: number;
873
+ depth: number;
874
+ height: number;
875
+ };
876
+ };
877
+ type RandomSource = () => number;
878
+
879
+ /** The page's own seeded generator (mulberry32), so a silhouette drawn from the same seed has the same windows and colours. */
880
+ declare function createSilhouetteRandom(seed: number): RandomSource;
881
+
882
+ /** Rounded-box radius the team page gives a box; below 1.2 cm it is a plain box. */
883
+ declare function boxRadius(width: number, height: number, depth: number): number;
884
+
885
+ type CityBuildingParams = {
886
+ x: number;
887
+ z: number;
888
+ width: number;
889
+ depth: number;
890
+ height: number;
891
+ color: number;
892
+ /** Chance of a ground-floor shop on both long faces; omitted means none. */
893
+ shopChance?: number;
894
+ /** Chance that a window is lit. */
895
+ litChance?: number;
896
+ random?: RandomSource;
897
+ seed?: number;
898
+ };
899
+ /** City building: block, roof slab, maybe a vent, maybe a shop front, and window instances on the four faces. */
900
+ declare function createCityBuilding(p: CityBuildingParams): Silhouette;
901
+
902
+ type Seeded = {
903
+ random?: RandomSource;
904
+ seed?: number;
905
+ };
906
+ type TwoStoreyParams = Seeded & {
907
+ x: number;
908
+ z: number;
909
+ width: number;
910
+ depth: number;
911
+ color: number;
912
+ roofColor?: number;
913
+ ry?: number;
914
+ };
915
+ /** Two-storey house with a balcony slab, pitched roof and four windows. */
916
+ declare function createTwoStoreyHouse(p: TwoStoreyParams): Silhouette;
917
+ type SlabHouseParams = Seeded & {
918
+ x: number;
919
+ z: number;
920
+ width: number;
921
+ depth: number;
922
+ floors: number;
923
+ color: number;
924
+ };
925
+ /** Reinforced-concrete slab house of one to three floors, with water tank, side stair and sometimes rebar starters. */
926
+ declare function createSlabHouse(p: SlabHouseParams): Silhouette;
927
+ type ColonialParams = Seeded & {
928
+ x: number;
929
+ z: number;
930
+ width: number;
931
+ color: number;
932
+ hasDoor: boolean;
933
+ };
934
+ /** Colonial terrace house: parapet, roof behind it and a row of doors or windows. */
935
+ declare function createColonialHouse(p: ColonialParams): Silhouette;
936
+ type ChaletParams = Seeded & {
937
+ x: number;
938
+ z: number;
939
+ color?: number;
940
+ ry?: number;
941
+ };
942
+ /** Wooden chalet on a stone base with a steep roof and a chimney. */
943
+ declare function createChalet(p: ChaletParams): Silhouette;
944
+ type CompanyHouseParams = Seeded & {
945
+ x: number;
946
+ z: number;
947
+ color?: number;
948
+ };
949
+ /** Company-town house with a low front fence. */
950
+ declare function createCompanyHouse(p: CompanyHouseParams): Silhouette;
951
+ type StiltHouseParams = Seeded & {
952
+ x: number;
953
+ z: number;
954
+ color?: number;
955
+ };
956
+ /** House on stilts with a ramp-like entry platform. */
957
+ declare function createStiltHouse(p: StiltHouseParams): Silhouette;
958
+ type FarmhouseParams = Seeded & {
959
+ x: number;
960
+ z: number;
961
+ };
962
+ /** Farm house with a long covered porch on six posts. */
963
+ declare function createFarmhouse(p: FarmhouseParams): Silhouette;
964
+ type DetachedHouseParams = Seeded & {
965
+ x: number;
966
+ z: number;
967
+ width: number;
968
+ depth: number;
969
+ color: number;
970
+ roofColor?: number;
971
+ ry?: number;
972
+ isBoarded?: boolean;
973
+ };
974
+ /** One-storey detached house; boarded windows get two crossed planks each. */
975
+ declare function createDetachedHouse(p: DetachedHouseParams): Silhouette;
606
976
 
607
977
  declare const version = "0.1.0";
608
978
  /**
@@ -634,6 +1004,13 @@ declare const engine: {
634
1004
  registerState: typeof registerState;
635
1005
  setStateDistribution: typeof setStateDistribution;
636
1006
  registerLocale: typeof registerLocale;
1007
+ registerResultExtension: typeof registerResultExtension;
1008
+ registerFindsProvider: typeof registerFindsProvider;
1009
+ findsFor: typeof findsFor;
1010
+ findsAnswer: typeof findsAnswer;
1011
+ registerViewerLayer: typeof registerViewerLayer;
1012
+ viewerLayers: ViewerLayer[];
1013
+ blocksWindow: typeof blocksWindow;
637
1014
  defineZone: typeof defineZone;
638
1015
  getZone: (id: string) => ZoneDef | undefined;
639
1016
  listZones: () => ZoneDef[];
@@ -643,9 +1020,10 @@ declare const engine: {
643
1020
  translate: typeof translate;
644
1021
  listLocales: () => string[];
645
1022
  templates: Record<string, TemplateDef>;
646
- catalog: Record<string, ItemDef>;
1023
+ catalog: Record<string, FurnitureDef>;
647
1024
  libraries: Record<string, SlotLibrary>;
648
1025
  styles: Record<string, StyleDef>;
1026
+ paletteStyles: Record<string, PaletteStyleDef>;
649
1027
  createRng: (seed: string | number, key: string) => Rng;
650
1028
  mulberry32: typeof mulberry32;
651
1029
  hashString: typeof hashString;
@@ -663,8 +1041,17 @@ declare const engine: {
663
1041
  constants: {
664
1042
  WALL_THICKNESS: number;
665
1043
  DOOR_CLEARANCE: number;
1044
+ PLAYER_RADIUS: number;
1045
+ DOOR_EDGE_CLEARANCE: number;
1046
+ WINDOW_EDGE_CLEARANCE: number;
1047
+ OVERHEAD_TOP: number;
1048
+ CAR_CLEARANCE: {
1049
+ readonly driver: 0.8;
1050
+ readonly side: 0.6;
1051
+ readonly end: 0.6;
1052
+ };
666
1053
  };
667
1054
  };
668
1055
  type FloorplanEngine = typeof engine;
669
1056
 
670
- export { type Anchor, type BoundaryRule, type DecorPass, type DecorPassContext, type DoorDef, type FacingRule, type FloorDef, type FloorplanEngine, type FloorplanLocale, type FloorplanOptions, type GateCfg, type GroundOverlayRule, type Hsl, type ItemColor, type ItemDef, type ItemInput, type Json, type LotConfig, type MeshFront, type Mount, type PaletteDraw, type PaletteEarly, type PaletteStyleDef, type PlacedItem, type PlacementContext, type PlacementKit, type Plan, type Rect, type Room, type RoomColorDef, type RoomDef, type Side, type Slot, type SlotDef, type SlotKit, type SlotLibrary, type StateContext, type StatePlugin, type StyleDef, type TemplateDef, type Vec2, type Weights, type WindowDef, type ZoneAdjustment, type ZoneDef, type ZoneViolation, type ZoningReport, checkLot, createRng, defineZone, engine, generate, getZone, hashString, limitsOf, listLocales, listStates, listTemplates, listZones, mulberry32, openingZones, overlaps, palette, registerDecorProfile, registerGroundOverlay, registerItem, registerItems, registerLibrary, registerLibraryAlias, registerLocale, registerPaletteStyle, registerPass, registerPermeableGround, registerRoomColors, registerSeedKeys, registerState, registerStyle, registerTemplate, registerWallTop, setStateDistribution, slotKit, slots, translate, validate, version, windowZone };
1057
+ export { type Anchor, type BoundaryRule, type CarClearance, type ChaletParams, type CityBuildingParams, type ColonialParams, type CompanyHouseParams, type DecorPass, type DecorPassContext, type DetachedHouseParams, type DoorDef, type FacingRule, type FarmhouseParams, type FindStack, type FindsProvider, type FindsQuery, type FloorDef, type FloorplanEngine, type FloorplanLocale, type FloorplanOptions, type FurnitureDef, type GateCfg, type GroundOverlayRule, type Hsl, type ItemColor, type ItemInput, type Json, type LotConfig, type MeshFront, type Mount, type PaletteDraw, type PaletteEarly, type PaletteStyleDef, type PlacedItem, type PlacementContext, type PlacementKit, type Plan, type RandomSource, type Rect, type ResultExtensionContext, type ResultExtensionOptions, type ResultExtensionRun, type Room, type RoomColorDef, type RoomDef, type Side, type Silhouette, type SilhouettePart, type SilhouetteWindow, type SlabHouseParams, type Slot, type SlotDef, type SlotKit, type SlotLibrary, type StateContext, type StatePlugin, type StiltHouseParams, type StyleDef, type TemplateDef, type TwoStoreyParams, type Vec2, type ViewerLayer, type ViewerLayerContext, type ViewerLayerLegendEntry, type Weights, type WindowDef, type ZoneAdjustment, type ZoneDef, type ZoneViolation, type ZoningReport, blocksWindow, boxRadius, checkLot, createChalet, createCityBuilding, createColonialHouse, createCompanyHouse, createDetachedHouse, createFarmhouse, createRng, createSilhouetteRandom, createSlabHouse, createStiltHouse, createTwoStoreyHouse, defineZone, engine, findsAnswer, findsFor, generate, getZone, hashString, limitsOf, listLocales, listStates, listTemplates, listZones, mulberry32, openingZones, overlaps, palette, registerDecorProfile, registerFindsProvider, registerGroundOverlay, registerItem, registerItems, registerLibrary, registerLibraryAlias, registerLocale, registerPaletteStyle, registerPass, registerPermeableGround, registerResultExtension, registerRoomColors, registerSeedKeys, registerState, registerStyle, registerTemplate, registerViewerLayer, registerWallTop, setStateDistribution, slotKit, slots, translate, validate, version, windowZone };