@adatechnology/game-floorplan-three 0.9.3 → 0.10.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.
@@ -0,0 +1,1611 @@
1
+ import { DeferredQueue, ModuleScenario, TestableModule, DestructibleSpec } from '@adatechnology/game-contracts';
2
+ import { DestructionWorld, DestructionEvent } from '@adatechnology/game-destruction';
3
+ import { DestructionRenderer } from '@adatechnology/game-destruction-three';
4
+ import { FloorplanResult, ResultGate, FloorplanResultFields, ResultRoom, PlanWall, PlanDoor, PlanWindow, Rect } from '@adatechnology/game-floorplan';
5
+ import * as THREE_NS from 'three';
6
+ import { LightBudget, LightHandle } from '@adatechnology/game-render-three';
7
+ import { DocumentLike, Props3dOptions, Props3d } from '@adatechnology/game-props3d';
8
+ import { catenary } from '@adatechnology/game-shapes-three';
9
+ import * as Vegetation from '@adatechnology/game-vegetation';
10
+ import { PlantSpec } from '@adatechnology/game-vegetation';
11
+ import * as Interactables from '@adatechnology/game-interactables';
12
+ import { ObjectSpec, World } from '@adatechnology/game-interactables';
13
+ import { FloorplanAdapter, HouseholdKit, AdapterOptions, PlanEntry, AdapterPlan, WaterNetwork, AddResult, BlockedFn } from '@adatechnology/game-floorplan-interactables';
14
+ import { StructurePart, Support, Outbuilding, Utilities, WaterTank, Construction, Structure, PlumbingPoint, PlumbingRun } from '@adatechnology/game-floorplan-structure';
15
+ import * as VegetationThree from '@adatechnology/game-vegetation/three';
16
+
17
+ /** Texts the house shows to the player (interaction prompts, messages, outbuilding labels), by locale. */
18
+ type Messages = Record<string, string>;
19
+ declare const en: Messages;
20
+ declare const ptBR: Messages;
21
+ declare const locales: Record<string, Messages>;
22
+ type Translate = (key: string, params?: Record<string, string | number>) => string;
23
+ /**
24
+ * Translator for a locale id ('en', 'pt-BR'), or for a partial table that overrides the English one.
25
+ * A missing key falls back to English and then to the key itself.
26
+ */
27
+ declare function createTranslator(locale?: string | Partial<Messages>): Translate;
28
+
29
+ /**
30
+ * What the house reads of the adapters the game hands it, by shape: one domain adapter does not import another (layer rule
31
+ * `no-domain-adapter-to-adapter`), nor a content pack (`adapter-not-content`). The game passes `game-interactables-three`'s
32
+ * `createThreeAdapter`, `game-destruction-three`'s renderer and `game-vegetation-species` by option; these types hold only what
33
+ * the house calls, so the real modules fit them.
34
+ */
35
+
36
+ /** A TV screen of the interactables adapter (`createScreen`): a canvas material that turns on and changes channel. */
37
+ interface InteractablesScreen {
38
+ material: THREE_NS.MeshStandardMaterial;
39
+ readonly on: boolean;
40
+ readonly channel: number;
41
+ setOn(on: boolean): void;
42
+ setChannel(channel: number): void;
43
+ update(dt: number): void;
44
+ dispose(): void;
45
+ }
46
+ /** The particle effects of the interactables adapter (`createEffects`): water, steam, sparks and flames of the objects. */
47
+ interface InteractablesEffects {
48
+ update(dt: number, emitters: readonly unknown[], camera?: unknown): void;
49
+ stats(): {
50
+ alive: number;
51
+ };
52
+ dispose(): void;
53
+ }
54
+ /** What `finish` of a mesh api gives back: the object's groups, its moving parts and the lights its builders asked for. */
55
+ interface InteractablesMeshResult {
56
+ group: THREE_NS.Group;
57
+ parts: Record<string, THREE_NS.Group>;
58
+ lights: THREE_NS.Light[];
59
+ }
60
+ /** The interactables adapter bound to the house's three.js (`createThreeAdapter(THREE, options)` of game-interactables-three). */
61
+ interface InteractablesGfx {
62
+ createMeshApi(options?: {
63
+ quality?: string;
64
+ materials?: Record<string, THREE_NS.Material | undefined>;
65
+ shadows?: boolean;
66
+ mergeParts?: boolean;
67
+ swayAmplitude?: number;
68
+ }): {
69
+ api: Parameters<FloorplanAdapter['household']['build']>[2];
70
+ finish(spec?: ObjectSpec): InteractablesMeshResult;
71
+ };
72
+ syncObject(world: World, objectId: string, parts: Record<string, THREE_NS.Object3D>, options?: {
73
+ time?: number;
74
+ }): void;
75
+ createEffects(scene: THREE_NS.Object3D, options?: Record<string, unknown>): InteractablesEffects;
76
+ createScreen(options?: {
77
+ w?: number;
78
+ h?: number;
79
+ seed?: number;
80
+ }): InteractablesScreen;
81
+ createCord(points: readonly Vec3$1[], radius: number, material: THREE_NS.Material): THREE_NS.Mesh;
82
+ catenary: typeof catenary;
83
+ }
84
+ /** What draws a part of a bound object: a mesh or group, or a vertex range `[v0, v1)` of a mesh. */
85
+ type BoundMeshes = THREE_NS.Object3D | {
86
+ mesh: THREE_NS.Mesh;
87
+ range: [number, number];
88
+ };
89
+ /** The destruction renderer the game hands the house (`createDestructionRenderer(THREE, { scene, world })` of game-destruction-three). */
90
+ interface HouseDestructionRenderer {
91
+ bind(objectId: string, root: THREE_NS.Object3D, options?: {
92
+ parts?: Record<string, BoundMeshes | BoundMeshes[]>;
93
+ onFrame?: (dt: number) => void;
94
+ }): void;
95
+ unbind(objectId: string): void;
96
+ restore(objectId: string): void;
97
+ }
98
+ /** The species pack the game hands the house's vegetation (`game-vegetation-species`): a plant spec by species id. */
99
+ interface SpeciesLibrary {
100
+ toSpec(species: string): PlantSpec;
101
+ }
102
+
103
+ /** A part of the house a hit can damage (door, window, glass, tank...): the game reads `hp`. */
104
+ interface Damageable {
105
+ type: string;
106
+ hp: number;
107
+ hpMax: number;
108
+ }
109
+ /** A damageable box of a fleet car, in the car's frame (`game-vehicles` gives them). */
110
+ interface HouseFleetDamageable {
111
+ box: THREE_NS.Box3;
112
+ zone: string;
113
+ part?: string;
114
+ side?: string;
115
+ type?: string;
116
+ }
117
+ /** A car the fleet built: its group (+z in front), its damageable boxes, and how to give its resources back. */
118
+ interface HouseFleetCar {
119
+ group: THREE_NS.Object3D;
120
+ damageables?: HouseFleetDamageable[];
121
+ release?(): void;
122
+ }
123
+ /** The interactables kit a game injects (`interactives`): its modules, and optionally its own adapter of the plan. */
124
+ interface HouseInteractivesOptions {
125
+ GameInteractables?: InteractablesRefs['GI'];
126
+ GameInteractablesHousehold?: HouseholdKit;
127
+ GameInteractablesThree?: InteractablesRefs['GT'];
128
+ /** An adapter, or a factory with `create(options)`; the default is `@adatechnology/game-floorplan-interactables`. */
129
+ adapter?: FloorplanAdapter | {
130
+ create(options: AdapterOptions): FloorplanAdapter;
131
+ };
132
+ /** Passed to the factory's `create()`. */
133
+ adapterOptions?: AdapterOptions;
134
+ locale?: AdapterOptions['locale'];
135
+ region?: AdapterOptions['region'];
136
+ /** `false`: the kit does not draw the items of the plan. */
137
+ items?: boolean;
138
+ /** `false`: no particle effects. */
139
+ effects?: boolean;
140
+ /** () => the host's `EffectSink`: smoke, steam, fire and sparks go through its world. */
141
+ effectSink?: unknown;
142
+ camera?: unknown;
143
+ onEvent?: InteractablesRefs['onEvent'];
144
+ onSeat?: InteractablesRefs['onSeat'];
145
+ }
146
+ /** The vegetation packages a game injects (`vegetation`): `{ GameVegetation, GameVegetationSpecies }`, or one object with both sides. */
147
+ type HouseVegetationOptions = {
148
+ GameVegetation?: VegetationLibs['G'];
149
+ GameVegetationSpecies?: VegetationLibs['S'];
150
+ } & Partial<VegetationLibs['G'] & VegetationLibs['S']>;
151
+ /** What `onInteract` gets: the id, type and label of what the player acts on, and the house's or the kit's own reference to it. */
152
+ interface HouseInteractTarget {
153
+ id: string;
154
+ type: string;
155
+ label: string;
156
+ ref: unknown;
157
+ }
158
+ /** What `onDamage` gets for a wall. */
159
+ interface HouseWallDamage {
160
+ type: 'wall';
161
+ damageable: Damageable;
162
+ collider: {
163
+ damageable?: Damageable;
164
+ piece?: string;
165
+ };
166
+ }
167
+ /** What `create(THREE, options)` reads. Everything is optional; the three.js namespace is the first argument. */
168
+ interface HouseRendererOptions {
169
+ /** Document used to draw the procedural textures on a canvas (default: the page's). */
170
+ document?: DocumentLike;
171
+ /** `'game'` merges more and draws less than `'high'`. */
172
+ quality?: 'high' | 'game';
173
+ /** Locale of the texts the house shows (`en`, `pt-BR`) or a table of messages. */
174
+ locale?: string | Partial<Messages>;
175
+ /** `@adatechnology/game-props3d` (default: the package's own dependency). */
176
+ props?: {
177
+ create(THREE: Three, options?: Props3dOptions): Props3d;
178
+ };
179
+ /** `THREE.Reflector` (three/examples/jsm/objects/Reflector.js); without it the mirrors use only the environment map. */
180
+ reflector?: ReflectorClass;
181
+ /** Cars of the lot and garage: `build(kind, { quality, seed })` -> `{ group, damageable, release() }`. Without it there are no cars. */
182
+ fleet?: {
183
+ build(kind: string, options: {
184
+ quality: string;
185
+ seed: number;
186
+ }): HouseFleetCar;
187
+ } | null;
188
+ /** Car kinds (fleet ids) per lot style (`budget`, `mid`, `high`); replaces the list of a style. */
189
+ carKinds?: Record<string, string[]>;
190
+ /** Hit points per damage class (glass, wood, water, metal, masonry, rubber, fuel, gas). */
191
+ hp?: Record<string, number>;
192
+ /** Textures from the app that replace the procedural ones. */
193
+ textures?: Partial<Record<'roughcast' | 'block' | 'tile' | 'dirt' | 'grass' | 'asphalt' | 'sidewalk' | 'fiber_cement', THREE_NS.Texture>>;
194
+ /** Atlas textures from the app: framed pictures, floor kinds, water. */
195
+ atlas?: {
196
+ picture?: THREE_NS.Texture;
197
+ floorKind?: THREE_NS.Texture;
198
+ water?: THREE_NS.Texture;
199
+ };
200
+ /** Materials the game swaps (a material or a function of the default one). */
201
+ materials?: Record<string, THREE_NS.Material | ((material: THREE_NS.Material, key: string) => THREE_NS.Material | null | undefined | void)>;
202
+ /** The world of `@adatechnology/game-destruction`; the house registers itself in it on first need. */
203
+ destruction?: DestructionWorld;
204
+ /** `createDestructionRenderer(THREE, { scene, world })` of `@adatechnology/game-destruction-three`: draws fracture, collapse, fragments, spalls and the rebar cage on the house's meshes. */
205
+ destructionRenderer?: HouseDestructionRenderer;
206
+ /** The lights of effects (a blast, a fire, a flare) light the room where their point is, and the rooms either side of an open door or window next to it (see `effectLights` and `lighting`). Default true; false keeps them off every house surface. */
207
+ effectLightsIndoors?: boolean;
208
+ /** Milliseconds per frame the house may spend repainting damaged walls (chipped plaster, holes); events of one frame are painted together. Default `Infinity` (all of them at the frame's flush); a game loop sets a few ms. */
209
+ breachPaintBudgetMs?: number;
210
+ /** The interactables kit, injected: `{ GameInteractables, GameInteractablesHousehold, GameInteractablesThree, adapter (optional), adapterOptions, locale, region, items, effects, effectSink, camera, onEvent, onSeat }`. */
211
+ interactives?: HouseInteractivesOptions;
212
+ /** The vegetation packages, injected: `{ GameVegetation, GameVegetationSpecies }`. */
213
+ vegetation?: HouseVegetationOptions;
214
+ /** Maps an id of the plan to the key its seeded random draws use, to reproduce a scene drawn with other ids (golden tests). */
215
+ seedKey?: (id: string) => string | null | undefined;
216
+ /** Distance (m) beyond which the interior (`interior`) and the house (`hide`) are drawn no more, or `false` to switch distance LOD off. */
217
+ lod?: false | {
218
+ interior?: number;
219
+ hide?: number;
220
+ };
221
+ drawCallBudget?: number;
222
+ onChange?: (change: {
223
+ shadow: boolean;
224
+ }) => void;
225
+ /** A collider opened or closed (a door, a gate, a piece of furniture moved). */
226
+ onCollider?: (collider: HouseBoxCollider | HouseFurnitureCollider) => void;
227
+ /** A part took damage (`house.damage`, a hit of the destruction world): the part, or for a wall `{ type: 'wall', damageable, collider }`. */
228
+ onDamage?: (part: HousePart | HouseWallDamage, point: HousePoint | null | undefined, type: string) => void;
229
+ /** Every event of the destruction world about this house, with the house's inner group. */
230
+ onWreck?: (event: DestructionEvent, house: THREE_NS.Group) => void;
231
+ /** The player acts on something; returning `false` cancels it. */
232
+ onInteract?: (target: HouseInteractTarget, action?: InteractionTarget | KitInteractionTarget) => boolean | void;
233
+ /** A room's light turned on or off (`on` is what it shows now). */
234
+ onLight?: (roomId: string, on: boolean) => void;
235
+ onMessage?: (text: string) => void;
236
+ }
237
+ interface BuildOptions {
238
+ /** `'high'` (default) or `'game'`. */
239
+ quality?: 'high' | 'game';
240
+ /** Night: lit windows and room lamps. */
241
+ night?: boolean;
242
+ /** Roof cut off and floors above hidden, to look into the plan. */
243
+ cut?: boolean;
244
+ /** A state returned by `newState()`: pass the same one to rebuild without closing every door. */
245
+ state?: SavedHouseState;
246
+ /** `false`: the app already has ground, street and lawn. */
247
+ terrain?: boolean;
248
+ /** `true`: no lot wall, fence or gates (the game has its own). */
249
+ noPerimeter?: boolean;
250
+ /** `'meshes'`: one mesh per structural piece instead of one per group and material. */
251
+ pieces?: 'meshes';
252
+ /**
253
+ * The concrete pillars that stand in the masonry walls (`wall_column_*`, `column_*` at the corners and `jamb_column_*` of the structure). `'shown'` (default): drawn as what they are, plastered and painted
254
+ * a shade off the wall and standing 2.5 cm out of each face (a 20 cm pillar in a 15 cm wall), so the frame reads from the ends of each wall, its corners
255
+ * and its openings, and a shot or a blow that takes their plaster off shows their concrete and bars. `'hidden'`: inside the wall, seen only where it is
256
+ * damaged, as the Visor de casas 3D drew the houses.
257
+ */
258
+ pillars?: 'shown' | 'hidden';
259
+ drawCallBudget?: number;
260
+ building?: {
261
+ floors?: number;
262
+ floor?: number;
263
+ unit?: number;
264
+ showBuilding?: boolean;
265
+ };
266
+ }
267
+ /** Something the player can use, as the house publishes it: where it is, how far it reaches, its prompt and how to use it. */
268
+ interface HouseInteractable {
269
+ id: string;
270
+ type: string;
271
+ floor: number;
272
+ pos: number[];
273
+ radius: number;
274
+ angle?: number;
275
+ readonly label: string;
276
+ ref: unknown;
277
+ _action: () => unknown;
278
+ act?: () => boolean;
279
+ }
280
+ /** A part of the house that moves or takes damage (`house.parts[id]`): its group, its damage and how to open it. */
281
+ interface HousePart {
282
+ id: string;
283
+ type: string;
284
+ group: THREE_NS.Object3D | null;
285
+ damageable: Damageable | null;
286
+ opens(t: number): void;
287
+ readonly t: number;
288
+ floor?: number;
289
+ /** Box of a virtual part (window, mirror, car zone): `[x0, y0, z0, x1, y1, z1]`. */
290
+ aabb?: number[];
291
+ virtual?: boolean;
292
+ [extra: string]: unknown;
293
+ }
294
+ /** What `HouseRenderer.build` takes: a plan of `game-floorplan` (`generate`), or a house record made from one. */
295
+ type HousePlan = FloorplanResult | HouseRecord;
296
+ /** A point in world coordinates. */
297
+ interface HousePoint {
298
+ x: number;
299
+ y: number;
300
+ z: number;
301
+ }
302
+ /** A box collider of `house.colliders`: a wall, door, lot wall or gate on floor `f`, `[x0, z0]`-`[x1, z1]`. */
303
+ type HouseBoxCollider = BoxCollider;
304
+ /** A furniture collider of `house.colliders`: the oriented box of a piece on its floor. */
305
+ interface HouseFurnitureCollider {
306
+ type: 'furniture';
307
+ f: number;
308
+ obb: {
309
+ cx: number;
310
+ cz: number;
311
+ hw: number;
312
+ hd: number;
313
+ c: number;
314
+ s: number;
315
+ };
316
+ item: string;
317
+ off: boolean;
318
+ }
319
+ /** Options of `house.target` and `house.interact`: the ray test the game uses for the meshes, and the options of the interactables kit's targeting. */
320
+ interface HouseTargetOptions {
321
+ strike?: (meshes: THREE_NS.Mesh[]) => THREE_NS.Intersection | null | undefined;
322
+ interactives?: KitTargetOptions;
323
+ }
324
+ /** The house the renderer built. The three.js groups are ready to add to a scene. */
325
+ interface House {
326
+ version: string;
327
+ /** The plan it was built from. */
328
+ r: HouseRecord;
329
+ name: string;
330
+ quality: 'high' | 'game';
331
+ group: THREE_NS.Group;
332
+ house: THREE_NS.Group;
333
+ groups: Record<string, THREE_NS.Group>;
334
+ floors: THREE_NS.Group[];
335
+ ceilings: (THREE_NS.Group | null)[];
336
+ roof: THREE_NS.Group | null;
337
+ lot: THREE_NS.Group | null;
338
+ ground: THREE_NS.Group | null;
339
+ building: THREE_NS.Group | null;
340
+ /** The water tank of the plan: its part, its group, where it stands and the plan's tank. */
341
+ waterTank: {
342
+ part: HousePart | null;
343
+ group: THREE_NS.Object3D | null;
344
+ pos: {
345
+ x: number;
346
+ z: number;
347
+ y: number;
348
+ group: string;
349
+ } | null;
350
+ plant: NonNullable<HouseRecord['waterTank']>;
351
+ } | null;
352
+ /** Public colliders: walls, doors, lot walls and gates (aabb) and furniture (obb). */
353
+ colliders: (HouseBoxCollider | HouseFurnitureCollider)[];
354
+ /** Parts that move or take damage: id -> `{ group, type, opens(t), damageable }`. */
355
+ parts: Record<string, HousePart>;
356
+ /** The lot and garage cars: fleet kind, seed, place and the ids of their virtual parts. */
357
+ cars: {
358
+ i: number;
359
+ k: string;
360
+ seed: number;
361
+ pos: number[];
362
+ ry: number;
363
+ scale: number;
364
+ parts: string[];
365
+ }[];
366
+ interactables: HouseInteractable[];
367
+ doors: DoorLeaf[];
368
+ stairs: StairRecord[];
369
+ labels: HouseLabel[];
370
+ /** Item types of the plan the props kit has no model for, with their count. */
371
+ noModel: Map<string, number>;
372
+ /** The real lights the builders asked for (at night) in `list`, and the same grouped by room id in `byRoom`. */
373
+ lights: {
374
+ list: LightRequest[];
375
+ byRoom: Record<string, LightRequest[]>;
376
+ };
377
+ limits: {
378
+ x0: number;
379
+ z0: number;
380
+ x1: number;
381
+ z1: number;
382
+ };
383
+ apartment: boolean;
384
+ showBuilding: boolean;
385
+ buildingConfig: {
386
+ floors: number;
387
+ floor: number;
388
+ unit: number;
389
+ };
390
+ unitRy: number;
391
+ night: boolean;
392
+ cut: boolean;
393
+ /** What the interactables kit published for the house (with `interactives`). */
394
+ interactives: HouseInteractives | null;
395
+ /** The doors and pieces state to pass to a rebuild (`build(plan, { state })`). */
396
+ state: SavedHouseState;
397
+ stats: {
398
+ quality: 'high' | 'game';
399
+ drawCalls: number;
400
+ drawCallsLOD1: number;
401
+ triangles: number;
402
+ trianglesLod1: number;
403
+ budget: number | null;
404
+ overBudget: boolean;
405
+ tBuild: number;
406
+ };
407
+ vegetation: VegetationInfo | null;
408
+ solar: SolarInfo | null;
409
+ water: WaterApi;
410
+ electrical: ElectricalInfo | null;
411
+ gutters: GutterInfo | null;
412
+ /** The structure of the house (`game-floorplan-structure`): its parts and `spec()`, the destructible spec. */
413
+ structure: any;
414
+ /** The adapter to the destruction world (`destruction` option). */
415
+ destruction: any;
416
+ update(dt: number, time?: number, focus?: HousePoint): void;
417
+ show(options?: {
418
+ floor?: number;
419
+ cut?: boolean;
420
+ lot?: boolean;
421
+ }): void;
422
+ target(eye: Eye, options?: HouseTargetOptions): InteractionTarget | null;
423
+ interact(eye: Eye, options?: HouseTargetOptions): boolean;
424
+ /** The message the house shows now (a locked door...), or null. */
425
+ message(): string | null;
426
+ toggleDoor(door: DoorLeaf | string): void;
427
+ toggleLight(room: string): void;
428
+ lightOn(room: string): boolean;
429
+ collide(x: number, z: number, floor: number, options?: {
430
+ radius?: number;
431
+ from?: readonly number[];
432
+ }): boolean;
433
+ roomAt(floor: number, x: number, z: number): HouseRoom | null;
434
+ /** Height of the floor `f`. */
435
+ y0(floor: number): number;
436
+ chooseMirror(camera: THREE_NS.Camera): void;
437
+ setLod(level: number): void;
438
+ readonly lod: number;
439
+ /** World centre of the house, and its distance to a point (the shared draw budget sorts by it). */
440
+ center(): THREE_NS.Vector3;
441
+ distance(focus: THREE_NS.Vector3 | HousePoint): number;
442
+ damage(id: string, point?: HousePoint | null, type?: string, amount?: number): {
443
+ part: HousePart;
444
+ hp: number;
445
+ destroyed: boolean;
446
+ } | null;
447
+ colliderDamage(collider: {
448
+ damageable?: Damageable;
449
+ piece?: string;
450
+ } | null | undefined, point?: HousePoint | null, type?: string, amount?: number): {
451
+ hp: number;
452
+ destroyed: boolean;
453
+ } | null;
454
+ /** The part (door, window, furniture piece...) an object belongs to, found by going up its parents. */
455
+ partOf(object: THREE_NS.Object3D | null | undefined): HousePart | null;
456
+ /** The first part whose box holds the point (with a tolerance, default 5 cm). */
457
+ partAt(point: HousePoint, tolerance?: number): HousePart | null;
458
+ dispose(): void;
459
+ /** The builder's own state, for the recorders and the tests: not a stable api. */
460
+ internal: {
461
+ h: HouseInstance;
462
+ ctx: BuildContext;
463
+ inter: InteractiveState;
464
+ partState: Map<string, number | boolean>;
465
+ doorState: Map<string, boolean>;
466
+ mirrors: MirrorState;
467
+ };
468
+ }
469
+ /** What `HouseRenderer.lighting` reads. */
470
+ interface LightingOptions {
471
+ scene?: THREE_NS.Object3D;
472
+ /** Room lights, 1 to 12 (6). */
473
+ n?: number;
474
+ /** How many of them cast shadows (2). */
475
+ shadows?: number;
476
+ shadowSize?: number;
477
+ /** Outside lamps that may take a light (2). */
478
+ external?: number;
479
+ /**
480
+ * The host's LightBudget: the house leases `n` point slots (`shadows` with shadow) for good instead of creating lights, and the room masks are written at the slot of each light (what the shader
481
+ * indexes by). Without it the lights are created here, which changes every lit material's program key (deprecated, removed in the next major).
482
+ */
483
+ budget?: LightBudget;
484
+ }
485
+ /** The renderer `create(THREE, options)` returns. */
486
+ interface HouseRenderer {
487
+ version: string;
488
+ /** Builds the house of a plan (the result of `game-floorplan`, or a house record such as `wallPlan`'s). */
489
+ build(plan: HousePlan, options?: BuildOptions): House;
490
+ newState(): SavedHouseState;
491
+ /** Damage class and props kit type of each item type. */
492
+ types: TypeTable;
493
+ /** The props kit (`game-props3d`) the renderer draws with. */
494
+ mv: Props3d;
495
+ applyPart(group: THREE_NS.Object3D, t: number): void;
496
+ materials: MaterialTable;
497
+ /** Lets a material take the room light mask of `lighting()` (returns it). */
498
+ roomLightMask<M extends THREE_NS.Material | null | undefined>(material: M): M;
499
+ lighting(options?: LightingOptions): RoomLighting;
500
+ /**
501
+ * Lets the lights of effects (a blast, a fire, a flare) that hold slots of `budget` light the room their point is in, and the rooms either side of an open door or window next to it.
502
+ * Call `update(houses)` every frame after the budget's `present`. Works without `lighting()`. Off for every house with `effectLightsIndoors: false`.
503
+ */
504
+ effectLights?(options?: {
505
+ budget?: LightBudget;
506
+ ours?: readonly number[];
507
+ }): EffectLighting;
508
+ setNight(night: boolean): void;
509
+ /** The painting of the damaged walls of every house as a `DeferredQueue` for a shared frame budget; `budget.register` attaches it and `flush()` stops painting from `onFrame`. */
510
+ deferredQueue?(): DeferredQueue;
511
+ cars: {
512
+ model(kind: string, seed?: number): CarModel | null;
513
+ group(kind: string, w: number, d: number, seed?: number): THREE_NS.Group | null;
514
+ info(kind: string, seed?: number): {
515
+ parts: number;
516
+ tris: number;
517
+ L: number;
518
+ W: number;
519
+ H: number;
520
+ } | null;
521
+ };
522
+ dispose(): void;
523
+ }
524
+
525
+ interface PanelView {
526
+ /** The panels the slabs of the structure are cut into (as `toDestructibleSpec` names them), each with `slab`, the id of the slab it comes from. */
527
+ panels: StructurePart[];
528
+ /** Ids of the slabs that the spec no longer has (a panel for each room, or less, took their place). */
529
+ replaced: string[];
530
+ supports: Support[];
531
+ }
532
+
533
+ /** The kernel's types of the house's systems and state: materials, mirrors, cars, vegetation, interaction, room lights, the interactables kit and the build. */
534
+
535
+ /** The house's materials by name (`plain`, `glass`, `dirt`...). */
536
+ type MaterialTable = Record<string, THREE_NS.Material>;
537
+ /** A mirror assembled with a real reflection: the group, its environment-map plane and the reflector (null when it failed). */
538
+ interface MirrorEntry {
539
+ E: MirrorRecord;
540
+ g: THREE_NS.Group;
541
+ fake: THREE_NS.Mesh;
542
+ real: THREE_NS.Mesh | null;
543
+ }
544
+ /** Mirrors of a house: the assembled ones, the one reflecting now, a scratch vector and the house group. */
545
+ interface MirrorState {
546
+ list: MirrorEntry[];
547
+ active: MirrorEntry | null;
548
+ tmp: THREE_NS.Vector3;
549
+ house: THREE_NS.Object3D | null;
550
+ }
551
+ /** A car model merged by material, built once per kind, quality and seed. */
552
+ interface CarModel {
553
+ damageables: HouseFleetDamageable[];
554
+ /** Where the fleet group's centre (x, z) and floor (y) were. */
555
+ off: Vec3$1;
556
+ parts: {
557
+ geo: THREE_NS.BufferGeometry;
558
+ mat: THREE_NS.Material;
559
+ }[];
560
+ W: number;
561
+ L: number;
562
+ H: number;
563
+ tris: number;
564
+ }
565
+ /** The vegetation packages the game injected (`cfg.vegetation`): what the house uses of them. */
566
+ interface VegetationLibs {
567
+ G: Pick<typeof Vegetation, 'scatter' | 'buildLot'> & Pick<typeof VegetationThree, 'createLotObject' | 'createVegetationMaterials'>;
568
+ S: SpeciesLibrary;
569
+ }
570
+ /** The plants of one group and height, collected by `vegItem` and merged by `assembleVegetation`. */
571
+ interface VegetationGroup {
572
+ group: string;
573
+ y: number;
574
+ pl: Vegetation.Placement[];
575
+ }
576
+ /** The vegetation of the house being built (`shared.ctx.veg`). */
577
+ interface VegetationContext extends VegetationLibs {
578
+ mats(): VegetationThree.VegetationMaterials;
579
+ groups: Map<string, VegetationGroup>;
580
+ /** Species the package knows (cached `toSpec` checks). */
581
+ ok: Map<string, boolean>;
582
+ opts: Omit<Vegetation.BuildLotOptions, 'seed'>;
583
+ }
584
+ /**
585
+ * A moving piece of the house (`definePiece`): a cabinet door, a drawer, a curtain, a gate, a light switch, a door handle, a lamp, or a part
586
+ * of the `part:` contract. `t` is where it is (0 closed, 1 open), `target` where it goes; `outer` stands at the hinge and `inner` moves.
587
+ */
588
+ interface InteractivePiece {
589
+ name: string;
590
+ kind: string;
591
+ pivot: number[];
592
+ ry: number;
593
+ parent?: string;
594
+ meshes: THREE_NS.Mesh[];
595
+ t: number;
596
+ target: number;
597
+ t0?: number;
598
+ outer?: THREE_NS.Group;
599
+ inner?: THREE_NS.Object3D;
600
+ /** A handle: the door leaf and which of its groups holds it. */
601
+ leaf?: DoorLeaf;
602
+ k?: number;
603
+ /** A lamp: the room it lights. */
604
+ roomId?: string | null;
605
+ col?: BoxCollider;
606
+ gate?: ResultGate;
607
+ sgn?: number;
608
+ angle?: number;
609
+ travel?: number;
610
+ axis?: 'x' | 'y' | 'z';
611
+ /** The item that opens it. */
612
+ item?: InteractiveItem;
613
+ damageable?: Damageable;
614
+ }
615
+ /** Something the player can use (`E`): where they aim at, how far and at what angle it reaches, the pieces it moves, its prompt and action. */
616
+ interface InteractiveItem {
617
+ type: string;
618
+ id: string;
619
+ floor: number;
620
+ anchor: number[];
621
+ range: number;
622
+ angle: number;
623
+ pieces: InteractivePiece[];
624
+ text(): string;
625
+ action(): void;
626
+ /** True: reached through walls (gates, mailbox). */
627
+ noWall?: boolean;
628
+ /** Its public view (`house.interactables`). */
629
+ pub?: HouseInteractable;
630
+ }
631
+ /** A piece of furniture that blocks walking: rotated rectangle on a floor (`-1`: the lot). */
632
+ interface CollisionObject {
633
+ f: number;
634
+ cx: number;
635
+ cz: number;
636
+ c: number;
637
+ s: number;
638
+ hw: number;
639
+ hd: number;
640
+ type: string;
641
+ }
642
+ /** The interaction state of a house (`shared.inter`). */
643
+ interface InteractiveState {
644
+ defs: Map<string, InteractivePiece>;
645
+ items: InteractiveItem[];
646
+ pieces: InteractivePiece[];
647
+ /** Lamp pieces per room. */
648
+ lights: Map<string, InteractivePiece[]>;
649
+ litRooms: Set<string>;
650
+ objs: CollisionObject[];
651
+ anim: Set<InteractivePiece>;
652
+ msg: {
653
+ text: string;
654
+ until: number;
655
+ } | null;
656
+ target: unknown;
657
+ }
658
+ /** The eye of whoever interacts, in house coordinates. */
659
+ interface Eye {
660
+ x: number;
661
+ y: number;
662
+ z: number;
663
+ yaw: number;
664
+ pitch?: number;
665
+ floor: number;
666
+ }
667
+ /** The best target of an eye: its score (lower is better), prompt, action and what it is. */
668
+ interface InteractionTarget {
669
+ score: number;
670
+ text: string;
671
+ action: () => unknown;
672
+ target: TargetRef;
673
+ }
674
+ /** What a target is: a door leaf, an item of the house or an object of the interactables kit (`kit`, with its public view in `pub`). */
675
+ interface TargetRef {
676
+ id?: string;
677
+ type?: string;
678
+ kit?: unknown;
679
+ pub?: unknown;
680
+ }
681
+ /** A built house as the room lighting reads it (`House` is one). */
682
+ interface LitHouse {
683
+ group?: THREE_NS.Object3D | null;
684
+ house: THREE_NS.Object3D;
685
+ lights: {
686
+ list: LightRequest[];
687
+ };
688
+ r: HouseRecord;
689
+ y0(f: number): number;
690
+ lightOn(room: unknown): boolean;
691
+ internal?: {
692
+ doorState?: Map<string, boolean>;
693
+ };
694
+ }
695
+ /** A rectangle of a light box in world x/z: `[x0, z0, x1, z1]`. */
696
+ type BoxRect = [number, number, number, number];
697
+ /** What a room light lit in the last update: the room (or outdoor lamp) key, its boxes, its y band, the exclusion box and its distance. */
698
+ interface LightCrate {
699
+ k: unknown;
700
+ rects: BoxRect[];
701
+ y: [number, number];
702
+ exterior: boolean;
703
+ exclusion: BoxRect | null;
704
+ d: number;
705
+ }
706
+ /** The room lights of `lighting()`: one light per slot, given every frame to the rooms closest to the focus. */
707
+ interface RoomLighting {
708
+ lights: readonly (LightHandle | THREE_NS.PointLight)[];
709
+ crates: (LightCrate | null)[];
710
+ n: number;
711
+ shadows: number;
712
+ stats: {
713
+ rooms: number;
714
+ external: number;
715
+ shadows: number;
716
+ shadowChanged: boolean;
717
+ };
718
+ /** Strength of the fake indirect light inside each box. */
719
+ indirect(v: number): void;
720
+ invalidate(): void;
721
+ update(houses: LitHouse | readonly (LitHouse | null | undefined)[] | null | undefined, focus: {
722
+ x: number;
723
+ y: number;
724
+ z: number;
725
+ }, op?: {
726
+ floorMax?: number;
727
+ focusHouse?: LitHouse;
728
+ focusRoom?: unknown;
729
+ }): RoomLighting['stats'];
730
+ dispose(): void;
731
+ }
732
+ /** The masks of the effect lights of a budget (`effectLights`). */
733
+ interface EffectLighting {
734
+ update(houses: LitHouse | readonly (LitHouse | null | undefined)[] | null | undefined): void;
735
+ }
736
+ /** The interactables kit the game injected (`cfg.interactives`), bound: the modules, the adapter of the plan and the three.js side. */
737
+ interface InteractablesRefs {
738
+ GI: typeof Interactables;
739
+ HH: HouseholdKit;
740
+ GT: {
741
+ createThreeAdapter(THREE: Three, options?: Record<string, unknown>): InteractablesGfx;
742
+ };
743
+ A: FloorplanAdapter;
744
+ gfx: InteractablesGfx;
745
+ items: boolean;
746
+ effects: boolean;
747
+ effectSink: unknown;
748
+ camera: unknown;
749
+ onEvent: ((event: Interactables.WorldEvent, pub: unknown) => void) | null;
750
+ onSeat: ((seat: KitSeat | null, event: Interactables.WorldEvent) => void) | null;
751
+ }
752
+ /** A kit object of the house: its plan entry, where it is drawn, its moving parts and its spec. */
753
+ interface KitEntry {
754
+ id: string;
755
+ type: string;
756
+ entry: PlanEntry;
757
+ floor: number;
758
+ group: string;
759
+ root: THREE_NS.Group;
760
+ parts: Record<string, THREE_NS.Object3D>;
761
+ spec: Interactables.ObjectSpec;
762
+ /** The TV screen mesh, which swaps material. */
763
+ screen: THREE_NS.Mesh | null;
764
+ pos: Vec3$1;
765
+ ry: number;
766
+ origin: string;
767
+ }
768
+ /** The kit lamps of a room, its switches and whether it is lit (`ef`: some lamp on and powered). */
769
+ interface KitRoomState {
770
+ id: string;
771
+ lamps: string[];
772
+ ef: boolean;
773
+ switches: string[];
774
+ }
775
+ /** Where the player sits or lies in the kit. */
776
+ interface KitSeat {
777
+ object: string;
778
+ seatInfo: string;
779
+ pose: string;
780
+ eye: Vec3$1;
781
+ yaw: number;
782
+ pitch: number;
783
+ exitPoint: Vec3$1;
784
+ floor: number;
785
+ type: string | null;
786
+ }
787
+ /** The kit side of a house (`h.IV`). */
788
+ interface InteractablesState {
789
+ k: InteractablesRefs;
790
+ plane: AdapterPlan;
791
+ world: Interactables.World;
792
+ water: WaterNetwork;
793
+ entries: Map<string, KitEntry>;
794
+ roots: KitEntry[];
795
+ replace: Set<string>;
796
+ roomStates: Map<string, KitRoomState>;
797
+ lampRoom: Map<string, string>;
798
+ anim: Map<string, {
799
+ object: string;
800
+ part: string;
801
+ target: number;
802
+ t0: number;
803
+ }>;
804
+ screens: Map<string, InteractablesScreen>;
805
+ efx: InteractablesEffects | null;
806
+ items: THREE_NS.Mesh | null;
807
+ itemsDirty: boolean;
808
+ itemsT: number;
809
+ dirty: boolean;
810
+ list: null;
811
+ listT: number;
812
+ t: number;
813
+ circuits: {
814
+ id: string;
815
+ room?: string;
816
+ outlets: string[];
817
+ switches: string[];
818
+ lamps: string[];
819
+ }[];
820
+ switchRooms: Set<string>;
821
+ warnings: string[];
822
+ tBuild: number;
823
+ mats: Record<string, THREE_NS.Material | undefined>;
824
+ added?: AddResult;
825
+ focus?: {
826
+ x: number;
827
+ y: number;
828
+ z: number;
829
+ } | null;
830
+ isBlocked?: BlockedFn;
831
+ pub?: HouseInteractives;
832
+ }
833
+ /** What the house publishes of the interactables kit (`house.interactives`): the kit world and its tables, and the calls a game makes on it (in house coordinates). */
834
+ interface HouseInteractives {
835
+ active: boolean;
836
+ world: Interactables.World;
837
+ plane: AdapterPlan;
838
+ kit: InteractablesRefs;
839
+ entries: Map<string, KitEntry>;
840
+ circuits: InteractablesState['circuits'];
841
+ roomStates: Map<string, KitRoomState>;
842
+ warnings: string[];
843
+ water: WaterNetwork;
844
+ /** TV screens (id -> kit screen). */
845
+ screens: Map<string, InteractablesScreen>;
846
+ /** The particle system (smoke). */
847
+ effects(): InteractablesEffects | null;
848
+ /** (x, z, floor) -> inside a wall (the check of the furniture doors' sweep). */
849
+ isBlocked: BlockedFn;
850
+ /** The kit objects one piece of furniture became (a sink: basin, cabinet, overhead). */
851
+ furnitureObjects(mid: string): KitEntry[];
852
+ target(eye: Eye, options?: KitTargetOptions): KitInteractionTarget | null;
853
+ interact(eye: Eye, options?: KitTargetOptions): boolean;
854
+ interactables(): {
855
+ id: string;
856
+ type: string;
857
+ floor: number;
858
+ pos: Vec3$1;
859
+ radius: number;
860
+ label: string;
861
+ act: () => boolean;
862
+ }[];
863
+ /** Where the player sits or lies, if they do. */
864
+ seatInfo(): KitSeat | null;
865
+ sit(object: string, seat: string): boolean;
866
+ stand(): Vec3$1 | null;
867
+ /** Opens (`target` truthy) or closes all the doors and drawers of a piece of furniture. */
868
+ opens(mid: string, target: unknown): void;
869
+ /** Reads a breaker (no `on`) or sets it. */
870
+ breaker(circuit: string, on?: unknown): boolean;
871
+ lightOn(roomId: string): boolean | null;
872
+ light(roomId: string, on: unknown): void;
873
+ /** Whether a kit animation is running. */
874
+ animate(): boolean;
875
+ }
876
+ /** A house being built or played, as the kit side reads it (the per-house state `enter(h)` swaps in). */
877
+ interface HouseInstance {
878
+ ctx: BuildContext;
879
+ inter: InteractiveState;
880
+ state: SavedHouseState;
881
+ mirrors: MirrorState;
882
+ quality: 'high' | 'game';
883
+ /** Distance LOD now (0 full, 1 without the small pieces, 2 hidden) and the least the draw budget allows. */
884
+ lodCurrent: number;
885
+ lodMin: number;
886
+ IV?: InteractablesState | null;
887
+ groups?: Record<string, THREE_NS.Group>;
888
+ root?: THREE_NS.Group;
889
+ house?: THREE_NS.Group;
890
+ houseGroup: THREE_NS.Group;
891
+ destruction?: {
892
+ breach: {
893
+ setLod(n: number): void;
894
+ };
895
+ };
896
+ }
897
+ /** A kit object as an interaction target. */
898
+ interface KitTarget extends TargetRef {
899
+ kit: true;
900
+ id: string;
901
+ type: string;
902
+ object: KitEntry;
903
+ item: Interactables.Interactable;
904
+ floor: number;
905
+ pos: number[];
906
+ text(): string;
907
+ }
908
+ /** The best kit target of an eye. */
909
+ type KitInteractionTarget = InteractionTarget & {
910
+ target: KitTarget;
911
+ };
912
+ /** Options of the kit target: reach, cone and a filter of the candidates. */
913
+ interface KitTargetOptions {
914
+ reach?: number;
915
+ cone?: number;
916
+ exclude?: (E: KitEntry, k: Interactables.Interactable) => boolean;
917
+ }
918
+ /** A text label of the plan view: a room name or a type with no model. */
919
+ interface HouseLabel {
920
+ pos: THREE_NS.Vector3;
921
+ text: string;
922
+ group: string;
923
+ type: string;
924
+ floor?: number;
925
+ }
926
+ /** Gutters, downpipes and drains the roof drew (`house.gutters`). */
927
+ interface GutterInfo {
928
+ /** Each gutter: floor, side of the roof, axis it runs along, from `a` to `b` at `p` across, at height `y`. */
929
+ gutters: {
930
+ f: number;
931
+ side: string;
932
+ axis: string;
933
+ a: number;
934
+ b: number;
935
+ p: number;
936
+ y: number;
937
+ }[];
938
+ /** Each downpipe: floor, place, bottom and top, and the drain it ends in (none when it floats over a lower roof). */
939
+ downpipes: {
940
+ f: number;
941
+ x: number;
942
+ z: number;
943
+ y0: number;
944
+ y1: number;
945
+ drain: [number, number] | null;
946
+ hornBox?: boolean;
947
+ }[];
948
+ drains: {
949
+ x: number;
950
+ z: number;
951
+ }[];
952
+ }
953
+ /** The plants the vegetation drew (`house.vegetation`). */
954
+ interface VegetationInfo {
955
+ plants: number;
956
+ triangles: number;
957
+ colliders: (Vegetation.LotColliderData & {
958
+ y: number;
959
+ group: string;
960
+ })[];
961
+ lodCounts: number[];
962
+ materials: VegetationThree.VegetationMaterials;
963
+ }
964
+ /** What one build of a house knows while it draws (`shared.ctx`): the record, its tables and what each module collected. */
965
+ interface BuildContext {
966
+ mv: Props3d;
967
+ types: TypeTable;
968
+ r: HouseRecord;
969
+ /** The colour roles of the palette, `0xrrggbb` (`r.colors`, its `meta` aside). */
970
+ colors: Record<string, Hex>;
971
+ cut: boolean;
972
+ night: boolean;
973
+ labels: HouseLabel[];
974
+ colliders: BoxCollider[];
975
+ /** How many of the colliders are walls (they come first). */
976
+ wallColliders: number;
977
+ stairs: StairRecord[];
978
+ noTerrain: boolean;
979
+ roomById: Record<string, HouseRoom>;
980
+ pieces: Map<string, PieceRecord>;
981
+ pieceObjects: Map<string, THREE_NS.Object3D[]>;
982
+ structureIndex: Record<string, StructurePart>;
983
+ panelView: PanelView;
984
+ panelsOf: Map<string, StructurePart[]>;
985
+ showPillars: boolean;
986
+ apartment: boolean;
987
+ /** Apartment building: floors, the unit's floor and the unit index. */
988
+ pa: number;
989
+ pf: number;
990
+ pu: number;
991
+ showBuilding: boolean;
992
+ limits: {
993
+ x0: number;
994
+ z0: number;
995
+ x1: number;
996
+ z1: number;
997
+ };
998
+ veg: VegetationContext | null;
999
+ vegInfo: VegetationInfo | null;
1000
+ iv: InteractablesState | null;
1001
+ leaves: DoorLeaf[];
1002
+ /** Groups of the `part:` contract by name (`laundry_<seed>`, `mailbox_<id>`). */
1003
+ parts: Record<string, THREE_NS.Object3D>;
1004
+ clotheslines: unknown[];
1005
+ animateDoorsOn: boolean;
1006
+ waterTankPos?: {
1007
+ x: number;
1008
+ z: number;
1009
+ y: number;
1010
+ group: string;
1011
+ };
1012
+ roofRects: RoofRect[];
1013
+ noPiece: boolean;
1014
+ _flights?: {
1015
+ r: HouseRecord;
1016
+ l: Flight[];
1017
+ };
1018
+ solarInfo: SolarInfo | null;
1019
+ electricalInfo: ElectricalInfo | null;
1020
+ gutter: GutterConfig;
1021
+ gutterInfo: GutterInfo | null;
1022
+ /** Roof planes of the plan (`res.roof.panes`). */
1023
+ panes: {
1024
+ id: string;
1025
+ aabb?: number[];
1026
+ [extra: string]: unknown;
1027
+ }[];
1028
+ lights: LightRequest[];
1029
+ unitRy?: number;
1030
+ unitInverse: THREE_NS.Matrix4;
1031
+ outbuildingList?: Outbuilding[];
1032
+ tBuild: number;
1033
+ /** Types with no builder, and how many items of each. */
1034
+ noModel: Map<string, number>;
1035
+ }
1036
+ /** The state a house keeps between builds (`newState()`): doors, moving pieces, water and the kit world. */
1037
+ interface SavedHouseState {
1038
+ doors: Map<string, boolean>;
1039
+ inter: Map<string, number | boolean>;
1040
+ water?: WaterState | null;
1041
+ iv?: Interactables.WorldState | null;
1042
+ }
1043
+
1044
+ /**
1045
+ * The kernel `K` is the closure the team's Casa3DSDK kept in one function: every installer of a module reads what the earlier ones
1046
+ * defined from it and adds what it defines (`Object.assign(K, ...)`). `Shared` holds the per-house state `enter(house)` swaps.
1047
+ *
1048
+ * The members are typed module by module (`KernelGeometry`, ...). Until every installer is typed, the index signature keeps the members
1049
+ * of the modules not yet typed reachable; it goes away with the last one (docs/migracao-typescript.md). The modules already typed are
1050
+ * checked with `strict` by `tsconfig.strict.json`.
1051
+ */
1052
+
1053
+ type Three = typeof THREE_NS;
1054
+ type Vec3$1 = [number, number, number];
1055
+ /** A colour as three.js takes it: `0xrrggbb`. */
1056
+ type Hex = number;
1057
+ /** Atlas cell of a face (`u0..v1`), its rotation in quarter turns, a mirror flag and a per-vertex colour multiplier. */
1058
+ interface UvRect {
1059
+ u0: number;
1060
+ v0: number;
1061
+ u1: number;
1062
+ v1: number;
1063
+ rot?: number;
1064
+ fx?: boolean | number;
1065
+ vc?: (x: number, z: number) => readonly number[];
1066
+ }
1067
+ /** A destruction piece being drawn: the meshes record where it starts so a hit finds it again. */
1068
+ interface PieceRecord {
1069
+ id: string;
1070
+ mat: string;
1071
+ role: string | null;
1072
+ floor?: number;
1073
+ [extra: string]: unknown;
1074
+ }
1075
+ /** A real mirror to assemble at the end of the build (`furniture/fixtures` writes it, `mirrors.ts` assembles it). */
1076
+ interface MirrorRecord {
1077
+ x: number;
1078
+ y: number;
1079
+ z: number;
1080
+ ry: number;
1081
+ w: number;
1082
+ h: number;
1083
+ room: unknown;
1084
+ floor?: number;
1085
+ parent: string;
1086
+ }
1087
+ /** The frame an item is drawn in: where it stands (`x`, `z`, `ry`, `base` floor height, `y` mounting height) and its palette. */
1088
+ interface Frame {
1089
+ x: number;
1090
+ z: number;
1091
+ ry: number;
1092
+ base: number;
1093
+ y?: number;
1094
+ floor?: number;
1095
+ /** Id of the room the item stands in. */
1096
+ room?: string | null;
1097
+ lampId?: string;
1098
+ palette?: Record<string, Hex>;
1099
+ }
1100
+ /**
1101
+ * A furniture item being drawn (the `M` every builder takes): its frame, its size, and what the house gave it (colour, seed, room).
1102
+ * Builders read other flags by name.
1103
+ */
1104
+ interface Mount extends Frame {
1105
+ w: number;
1106
+ d: number;
1107
+ h: number;
1108
+ id?: string;
1109
+ seed?: string | number;
1110
+ color?: Hex;
1111
+ on?: boolean;
1112
+ ceiling?: number;
1113
+ typeWith?: string | null;
1114
+ /** Hose of a wall tap, as points from the tap (`furniture/yard`). */
1115
+ hose?: number[][];
1116
+ u?: number;
1117
+ v?: number;
1118
+ [extra: string]: unknown;
1119
+ }
1120
+ /** A real light a builder asks for (`api.light`); the lighting turns it into a lamp. */
1121
+ interface LightRequest {
1122
+ x: number;
1123
+ y: number;
1124
+ z: number;
1125
+ color: Hex;
1126
+ range: number;
1127
+ type: string;
1128
+ floor?: number;
1129
+ group: string;
1130
+ base: number;
1131
+ /** The room id of the item that asked for it (a lamp of the lot has none). */
1132
+ room?: string | null;
1133
+ id?: string;
1134
+ roomId?: string | null;
1135
+ [extra: string]: unknown;
1136
+ }
1137
+ /** What a builder draws with, in the item's frame (`makeApi()`); the lamps and curtains swap it for a recorder. */
1138
+ interface FurnitureApi {
1139
+ box(M: Frame, mat: string, x: number, y: number, z: number, w: number, h: number, d: number, color: Hex, ry?: number, rx?: number, rz?: number): void;
1140
+ cylinder(M: Frame, mat: string, x: number, y: number, z: number, r: number, h: number, color: Hex, rx?: number, rz?: number, seg?: string): void;
1141
+ leaf(M: Frame, x: number, y: number, z: number, w: number, h: number, color: Hex, ry?: number, rx?: number): void;
1142
+ plane(M: Frame, mat: string, x: number, y: number, z: number, w: number, h: number, color: Hex, ry?: number, rx?: number, rz?: number, uv?: UvRect | null): void;
1143
+ light(M: Frame, x: number, y: number, z: number, color: Hex, range: number, type: string, ex?: Record<string, unknown> | null): void;
1144
+ }
1145
+ /** Variations a builder takes (`FURNITURE.cabinet(M, A, { doors: 2 })`). */
1146
+ interface BuilderOptions {
1147
+ color?: Hex;
1148
+ top?: Hex;
1149
+ useColor?: boolean;
1150
+ ceiling?: number;
1151
+ doors?: number;
1152
+ glass?: boolean;
1153
+ iron?: boolean;
1154
+ open?: boolean;
1155
+ crates?: boolean;
1156
+ round?: boolean;
1157
+ tablecloth?: boolean;
1158
+ noChairs?: boolean;
1159
+ oneSide?: boolean;
1160
+ headboard?: boolean;
1161
+ backrest?: boolean;
1162
+ column?: boolean;
1163
+ items?: boolean;
1164
+ low?: boolean;
1165
+ lowCrown?: boolean;
1166
+ noBasin?: boolean;
1167
+ noOverhead?: boolean;
1168
+ register?: boolean;
1169
+ shrub?: boolean;
1170
+ stool?: boolean;
1171
+ [flag: string]: unknown;
1172
+ }
1173
+ /** Draws one furniture item with the api, in the item's frame. */
1174
+ type FurnitureBuilder = (M: Mount, A: FurnitureApi, o?: BuilderOptions) => void;
1175
+ /** The `Reflector` of three's examples: a plane that mirrors the scene. */
1176
+ type ReflectorClass = new (geometry: THREE_NS.BufferGeometry, options: Record<string, unknown>) => THREE_NS.Mesh;
1177
+ /**
1178
+ * An item of the house record (`r.items`, `r.stateItems`): the placed item of `game-floorplan` (its `ResultItem`), with the fields the
1179
+ * state plugins add (`polygon` of a ground cover, an open door, the hose of a gas cylinder).
1180
+ */
1181
+ interface HouseItem {
1182
+ id: string;
1183
+ type: string;
1184
+ category: string;
1185
+ x: number;
1186
+ z: number;
1187
+ ry: number;
1188
+ w: number;
1189
+ d: number;
1190
+ h: number;
1191
+ y: number;
1192
+ room: string | null;
1193
+ floor: number;
1194
+ outdoor: boolean;
1195
+ color?: number | string;
1196
+ overhead?: boolean;
1197
+ polygon?: number[][];
1198
+ doorOpen?: boolean;
1199
+ hose?: number[][];
1200
+ assembly?: unknown;
1201
+ /** Storeys a stair connects, or the id of the item this one serves. */
1202
+ link?: {
1203
+ from: number;
1204
+ to: number;
1205
+ } | string;
1206
+ [extra: string]: unknown;
1207
+ }
1208
+ /** The builder picked for a furniture type, and where it came from (`props3d`, `game`...). */
1209
+ interface TypeEntry {
1210
+ f: FurnitureBuilder;
1211
+ source?: string;
1212
+ [extra: string]: unknown;
1213
+ }
1214
+ /** Furniture type -> its builder (`typeTable(props)`). */
1215
+ type TypeTable = Record<string, TypeEntry>;
1216
+ /** What has plan rectangles: its `parts`, or its own `u0..v1` when it has none (a room, a lot zone). */
1217
+ interface RoomRects {
1218
+ parts?: readonly Rect[] | null;
1219
+ u0: number;
1220
+ v0: number;
1221
+ u1: number;
1222
+ v1: number;
1223
+ }
1224
+ /** A room of the house record; the open areas of a plugin may be marked `outdoor`, and the rooms of an outbuilding name it. */
1225
+ type HouseRoom = ResultRoom & {
1226
+ outdoor?: boolean;
1227
+ outbuilding?: unknown;
1228
+ [extra: string]: unknown;
1229
+ };
1230
+ /** A wall of the house record, with the structure fields the structure extension adds (`id`, `material`, `role`). */
1231
+ interface HouseWall extends PlanWall {
1232
+ id?: string;
1233
+ material?: string;
1234
+ role?: string;
1235
+ outbuilding?: string;
1236
+ }
1237
+ /** The house record the renderer draws: the `generate` result of `game-floorplan`, with the fields the plugins add to its rooms, walls and items. */
1238
+ interface HouseRecord extends Omit<FloorplanResultFields, 'rooms' | 'walls' | 'doors' | 'windows' | 'items' | 'stateItems'> {
1239
+ rooms: HouseRoom[];
1240
+ walls: HouseWall[];
1241
+ doors: HouseDoor[];
1242
+ windows: HouseWindow[];
1243
+ items: HouseItem[];
1244
+ stateItems: HouseItem[];
1245
+ /** Utilities of `game-floorplan-structure` (empty until its extension ran). */
1246
+ utilities?: Partial<Utilities>;
1247
+ /** Walk-in yard buildings of `game-floorplan-structure`. */
1248
+ outbuildings?: Outbuilding[];
1249
+ /** The water tank of `game-floorplan-structure`. */
1250
+ waterTank?: WaterTank | null;
1251
+ /** The construction and the structure of `game-floorplan-structure` (its `extendWithStructure`). */
1252
+ construction?: Construction;
1253
+ structure?: Structure;
1254
+ [extension: string]: unknown;
1255
+ }
1256
+ /** A door of the house record; an outbuilding's door names it, and has no stair steps or type of its own. */
1257
+ interface HouseDoor extends Omit<PlanDoor, 'type' | 'steps'> {
1258
+ type?: string;
1259
+ steps?: number;
1260
+ outbuilding?: string;
1261
+ }
1262
+ /** A window of the house record; an outbuilding's window names it. */
1263
+ interface HouseWindow extends PlanWindow {
1264
+ outbuilding?: string;
1265
+ }
1266
+ /** A flight of stairs between two storeys, once (the house record repeats the stair item on both): its plan box, the landing under its first steps when
1267
+ * another flight stands below it, and the flat top of a flight with none above (`LP` long). */
1268
+ interface Flight {
1269
+ m: HouseItem;
1270
+ from: number;
1271
+ to: number;
1272
+ rect: Rect;
1273
+ landing?: Rect;
1274
+ top?: Rect;
1275
+ LP?: number;
1276
+ }
1277
+ /** A stair drawn in the house (`ctx.stairs`): its item, storeys, foot height, rise and plan box, and where its landing starts (share of its depth). */
1278
+ interface StairRecord {
1279
+ m: HouseItem;
1280
+ f: number;
1281
+ to: number;
1282
+ y0: number;
1283
+ H: number;
1284
+ rect: Rect;
1285
+ landingPoint: number;
1286
+ }
1287
+ /** A box collider of the house (`ctx.colliders`): a wall, door, board, lot wall or gate on storey `f` (`-1`: the lot); `off` while a door is open. */
1288
+ interface BoxCollider {
1289
+ type: string;
1290
+ f: number;
1291
+ x0: number;
1292
+ z0: number;
1293
+ x1: number;
1294
+ z1: number;
1295
+ piece?: string;
1296
+ off?: boolean;
1297
+ [extra: string]: unknown;
1298
+ }
1299
+ /** A door leaf group: its name and where its hinge stands. */
1300
+ interface LeafGroup {
1301
+ name: string;
1302
+ pos: number[];
1303
+ }
1304
+ /** A door of the house as it moves (`ctx.leaves`): its state, its leaf groups and handles, and its collider. */
1305
+ interface DoorLeaf {
1306
+ id: string;
1307
+ floor: number;
1308
+ type: string;
1309
+ open: boolean;
1310
+ t: number;
1311
+ blockedFlag: boolean;
1312
+ locked: boolean;
1313
+ handleNames: string[];
1314
+ hT: number;
1315
+ cx: number;
1316
+ cz: number;
1317
+ visH: number;
1318
+ groups: LeafGroup[];
1319
+ col: BoxCollider | null;
1320
+ minScale?: number;
1321
+ rot?: number;
1322
+ /** The leaf's groups once the build placed them. */
1323
+ gs: THREE_NS.Group[];
1324
+ /** The handle pieces (`linkDoorLeaves`). */
1325
+ handles?: InteractivePiece[];
1326
+ /** Where the door's movement is: turning the handle, swinging, letting the handle rise, or rattling when locked. */
1327
+ phase?: 'handle' | 'swing' | 'rise' | 'rattle' | null;
1328
+ anim?: boolean;
1329
+ jig?: number;
1330
+ [extra: string]: unknown;
1331
+ }
1332
+ /** A roof rectangle of the house (`ctx.roofRects`): where it is and, once drawn, the geometry the solar panels rest on. */
1333
+ interface RoofRect {
1334
+ f: number;
1335
+ r: Rect;
1336
+ touchesU?: number[];
1337
+ slab?: boolean;
1338
+ outbuilding?: string;
1339
+ yb?: number;
1340
+ tp?: number;
1341
+ gable?: boolean;
1342
+ alongX?: boolean;
1343
+ exterior?: Rect;
1344
+ rm?: number;
1345
+ }
1346
+ /** Gutter settings of a house (`ctx.gutter`), drawn from its seed. */
1347
+ interface GutterConfig {
1348
+ on: boolean;
1349
+ rnd: () => number;
1350
+ color: Hex;
1351
+ bad: boolean;
1352
+ fallback: boolean;
1353
+ ncond?: number;
1354
+ nbuz?: number;
1355
+ bz?: Set<string>;
1356
+ }
1357
+ /** Water in a house's tank: kept in the house's state so it survives a rebuild (night, cut). */
1358
+ interface WaterState {
1359
+ cap: number;
1360
+ level: number;
1361
+ rate: number;
1362
+ }
1363
+ /** The water network of a house (`house.water`): the tank level and the points that draw from it. */
1364
+ interface WaterApi {
1365
+ capacity: number;
1366
+ points: Record<string, PlumbingPoint>;
1367
+ itemPoint: Record<string, string>;
1368
+ runs: PlumbingRun[];
1369
+ level(): number;
1370
+ fraction(): number;
1371
+ /** Draws litres from a point; returns the litres delivered. */
1372
+ consume(pointId: string, liters: number): number;
1373
+ fill(liters: number): number;
1374
+ /** Litres per second; 0 stops it. */
1375
+ leak(rate: number): number;
1376
+ readonly leakage: number;
1377
+ readonly dry: boolean;
1378
+ on(ev: 'dry' | 'full', fn: (api: WaterApi) => void): () => void;
1379
+ off(ev: 'dry' | 'full', fn: (api: WaterApi) => void): void;
1380
+ step(dt: number): void;
1381
+ }
1382
+ /** The solar panels and inverter as the game sees them (`house.solar`). */
1383
+ interface SolarInfo {
1384
+ type: string;
1385
+ panels: {
1386
+ id: string;
1387
+ pos: Vec3$1;
1388
+ tilt: number;
1389
+ w: number;
1390
+ length: number;
1391
+ }[];
1392
+ inverter: {
1393
+ id: string;
1394
+ pos: Vec3$1;
1395
+ side: string;
1396
+ link: string;
1397
+ } | null;
1398
+ }
1399
+ /** The electrical structure as the game sees it (`house.electrical`). */
1400
+ interface ElectricalInfo {
1401
+ pole: {
1402
+ pos: Vec3$1;
1403
+ h: number;
1404
+ } | null;
1405
+ meter: {
1406
+ id: string;
1407
+ pos: Vec3$1;
1408
+ place: string;
1409
+ } | null;
1410
+ panel: {
1411
+ id: string;
1412
+ pos: Vec3$1;
1413
+ normal: Vec3$1;
1414
+ room: string;
1415
+ breakers: number;
1416
+ } | null;
1417
+ conduits: string[];
1418
+ outlets: {
1419
+ id: string;
1420
+ pos: Vec3$1;
1421
+ normal: Vec3$1;
1422
+ room: string;
1423
+ floor: number;
1424
+ type: string;
1425
+ voltage: number;
1426
+ }[];
1427
+ switches: {
1428
+ id: string;
1429
+ pos: Vec3$1;
1430
+ normal: Vec3$1;
1431
+ room: string;
1432
+ floor: number;
1433
+ controls: string[];
1434
+ }[];
1435
+ circuits: unknown[];
1436
+ exposed: boolean;
1437
+ }
1438
+
1439
+ type AreaText = {
1440
+ group: string;
1441
+ name: string;
1442
+ controls: Record<'package' | 'template' | 'state' | 'seed' | 'quality' | 'lod' | 'houses' | 'budget' | 'floor_view' | 'hit', string>;
1443
+ hints: Record<'template' | 'houses' | 'budget' | 'lod' | 'floor_view' | 'hit', string>;
1444
+ actions: Record<'build' | 'enter' | 'up' | 'down' | 'door' | 'strike' | 'reset' | 'clear', string>;
1445
+ options: {
1446
+ quality: Record<string, string>;
1447
+ lod: Record<string, string>;
1448
+ floor_view: Record<string, string>;
1449
+ hit: Record<string, string>;
1450
+ state: Record<string, string>;
1451
+ };
1452
+ layers: Record<'roof' | 'lot' | 'night' | 'room_lights', string>;
1453
+ metrics: Record<'houses' | 'parts' | 'standing' | 'broken' | 'holes' | 'draw_calls' | 'triangles' | 'lod' | 'floor' | 'doors_open' | 'target' | 'planned', string>;
1454
+ sheet: {
1455
+ kicker: string;
1456
+ title: string;
1457
+ template: string;
1458
+ seed: string;
1459
+ state: string;
1460
+ floors: string;
1461
+ size: string;
1462
+ parts: string;
1463
+ look: string;
1464
+ none: string;
1465
+ no_engine: string;
1466
+ };
1467
+ specimens: Record<string, string>;
1468
+ scenarios: Record<string, string>;
1469
+ steps: Record<'built' | 'no_engine' | 'entered' | 'floor' | 'no_floor' | 'door' | 'no_door' | 'strike' | 'no_aim' | 'cleared' | 'reset' | 'one_pillar_broke' | 'slabs_whole' | 'no_slab_fell' | 'two_slab_fell' | 'two_roof_fell' | 'partition_broke' | 'slab_stayed' | 'glass_hole' | 'glass_broke' | 'walls_whole' | 'tank_hole' | 'tank_leaked' | 'gas_exploded' | 'gas_damaged', string>;
1470
+ };
1471
+
1472
+ /** The room as these scenarios use it: its destruction world, and `spawn` of an item at a point (its root carries the specimen's spec in `userData.floorplanSpec`). */
1473
+ interface AreaRoom {
1474
+ world: DestructionWorld;
1475
+ spawn(item: string, position: [number, number, number], rotationY: number): {
1476
+ objectId: string;
1477
+ root: {
1478
+ userData: Record<string, unknown>;
1479
+ };
1480
+ };
1481
+ }
1482
+ /** What the room hands a scenario (`ScenarioContext` of game-test-room), narrowed to what these use. */
1483
+ interface AreaContext {
1484
+ room: AreaRoom;
1485
+ step(seconds: number): void;
1486
+ expect(condition: boolean, label: string, data?: Record<string, unknown>): void;
1487
+ }
1488
+ type Vec3 = readonly [number, number, number];
1489
+ /** Where the team's page lays its specimens (the arena has 14 m of half width). */
1490
+ declare const SPECIMEN_AT: Vec3;
1491
+ /**
1492
+ * The six structural scenarios of the team's house area (sala-de-testes/area-casas, L3833-3868), same ids and same checks, on the specimens the area builds: destroy a pillar, two pillars, a partition,
1493
+ * shoot a window, puncture the water tank, set the gas bottle on fire. The hits are the team's (3 MJ blunt on a pillar, 600 J 9 mm on the glass and the tank, 900 C fire on the bottle). A scenario
1494
+ * passes when every check holds; the names of the checks are in `text.steps`.
1495
+ */
1496
+ declare function createHouseScenarios(text: AreaText, at?: Vec3): Array<ModuleScenario<AreaContext>>;
1497
+
1498
+ /** The part of the floorplan engine (`engine` of `@adatechnology/game-floorplan`, with the content packs the page registered) the test area reads. */
1499
+ interface FloorplanEngineLike {
1500
+ generate(template: string, options?: {
1501
+ seed?: number;
1502
+ state?: string;
1503
+ floors?: number;
1504
+ }): FloorplanResult;
1505
+ listTemplates(): Array<{
1506
+ id: string;
1507
+ name?: string;
1508
+ floors?: number;
1509
+ floorRange?: number[] | null;
1510
+ }>;
1511
+ listStates(): string[];
1512
+ translate?(namespace: string, key: string, locale?: string, vars?: Record<string, string | number>): string;
1513
+ }
1514
+ /** A pack of templates the bench lists together (residential, commercial, rural, post-apocalyptic). Ids the engine does not know are left out. */
1515
+ interface TemplateGroup {
1516
+ id: string;
1517
+ /** Name by locale (`en`, `pt-BR`); the id when absent. */
1518
+ name?: Record<string, string>;
1519
+ templates: readonly string[];
1520
+ }
1521
+ /** A small house the area lays out for the structural scenarios: the structure spec of a template, drawn as boxes named by part (the team's HouseArea items). */
1522
+ interface SpecimenDef {
1523
+ /** Item id (`house_casa_portico`): the scenarios and the golden name them. */
1524
+ id: string;
1525
+ template: string;
1526
+ seed?: number;
1527
+ state?: string;
1528
+ /** The bearing walls only close: a frame of pillars and beams carries the building. */
1529
+ portico?: boolean;
1530
+ /**
1531
+ * How the structure is sized (`toDestructibleSpec`): `safety` is the share of its capacity a pillar uses at rest, `redundancy` the most it uses after one other pillar is lost.
1532
+ * A slab on four pillars is held by the sum of the four: with `safety` 0.72 and `redundancy` 0.97 it holds one loss (0.96) and falls with two.
1533
+ */
1534
+ sizing?: {
1535
+ safety?: number;
1536
+ redundancy?: number;
1537
+ safetyOthers?: number;
1538
+ };
1539
+ /** Name by locale; the text of the area when absent. */
1540
+ name?: Record<string, string>;
1541
+ }
1542
+ interface FloorplanTestOptions {
1543
+ locale?: string;
1544
+ /** The engine with the packs registered. Without it the module has no houses to build. */
1545
+ engine?: FloorplanEngineLike;
1546
+ /** The packs the bench lists, in order. Default: every template of the engine in one group. */
1547
+ groups?: readonly TemplateGroup[];
1548
+ /** The states the bench offers (`normal`, `fortified`, `abandoned`). Default: the engine's. */
1549
+ states?: readonly string[];
1550
+ /** The room's destruction world and renderer (`room.world`, `room.renderer`): the houses built here register in them, so every shot, blast and fire of the room reaches the walls. */
1551
+ world?: DestructionWorld;
1552
+ renderer?: DestructionRenderer;
1553
+ /** Passed to the house renderer: `fleet`, `reflector`, `interactives`, `vegetation`, `props`, `textures`... */
1554
+ house?: Partial<HouseRendererOptions>;
1555
+ /** Template and seed the bench starts with. */
1556
+ template?: string;
1557
+ seed?: number;
1558
+ /** Specimens of the structural scenarios; default the five of the team's house area, those whose template the engine has. */
1559
+ specimens?: readonly SpecimenDef[];
1560
+ /** Half size of the room's arena (`createTestRoom({ arenaSize })`), 14 by default: where the houses are laid. */
1561
+ arenaSize?: number;
1562
+ /** Where the specimens stand for the scenarios (the team's page: `[-5, 0, -11]`). */
1563
+ specimenAt?: readonly [number, number, number];
1564
+ }
1565
+
1566
+ declare const FLOORPLAN_AREA_ID = "floorplan_area";
1567
+ type Placed = {
1568
+ house: House;
1569
+ plan: FloorplanResult;
1570
+ seed: number;
1571
+ width: number;
1572
+ depth: number;
1573
+ };
1574
+ /**
1575
+ * The houses test area as a `TestableModule`: any typology of the content packs the page registered (residential, commercial, rural, post-apocalyptic) built with game-floorplan-three from a seed, laid
1576
+ * in the room, with the player able to walk in (walls and closed doors stop the walk), use the doors (E), go up and down the floors, see the level of detail (manual, by distance, or shared among a row
1577
+ * of houses by a draw-call budget), and hit the walls with what the room throws (its tools, or the bench's hit): the houses register in the room's destruction world, so shots, blows, blasts and fire
1578
+ * reach the structure and the room's renderer draws the fracture, the brick courses and the collapse. Dust and sparks are the room's own effects: this module draws no particles.
1579
+ * Everything that is a pack of content comes in by option: this package knows no game.
1580
+ */
1581
+ declare function createFloorplanTestModule(options?: FloorplanTestOptions): TestableModule<AreaContext> & {
1582
+ readonly houses: readonly Placed[];
1583
+ build(): void;
1584
+ clear(): void;
1585
+ groups(): readonly TemplateGroup[];
1586
+ };
1587
+
1588
+ /**
1589
+ * The five items of the team's house area (sala-de-testes/area-casas): a frame house, a whole house, a wood-frame house, a log cabin and a tent. The team's frame house is its single-storey house A; here it is the
1590
+ * two-storey townhouse, because the ceiling slab of the single-storey plan keeps standing on its bearing partitions when two pillars go (see evidence, T2.6). The frame house is a reinforced concrete frame (T10 §12): the slabs
1591
+ * are cut into panels on real beams, the pillars are sized (`sizing`) to carry the load of the ones lost, and the beams to carry the span the lost pillar leaves: one pillar lost and the slab stays,
1592
+ * the two ends of a side lost and that side comes down (owner, 2026-10-24: "4 pilares e a sustentação é a soma dos 4"; 2026-10-25: the real structure of the houses).
1593
+ */
1594
+ declare const DEFAULT_SPECIMENS: readonly SpecimenDef[];
1595
+ /** What the area keeps of a built specimen: the structure spec the house draws (what the destruction world is given) and the plan it came from. */
1596
+ interface SpecimenSpec {
1597
+ readonly spec: DestructibleSpec;
1598
+ readonly plan: FloorplanResult;
1599
+ }
1600
+ /**
1601
+ * The structure spec of a specimen: the engine draws the plan, the house renderer draws the house, and the house describes its structure (`house.structure.spec`) with what the water tank holds and
1602
+ * what makes the gas bottle explode. The spec is cached per three.js namespace and specimen; each call hands out a copy.
1603
+ */
1604
+ declare function specimenSpec(THREE: Three, engine: FloorplanEngineLike, def: SpecimenDef, houseOptions?: Partial<HouseRendererOptions>): SpecimenSpec;
1605
+ /**
1606
+ * One box (or cylinder, sphere) per part, named by the part id and coloured by its material, in the space of the house (the origin at the corner of the plan): what the team's house area draws, so the
1607
+ * room binds each mesh to the part of the same name. The anchored terrain slab is left out (the room has a floor).
1608
+ */
1609
+ declare function buildSpecimenMeshes(THREE: Three, spec: DestructibleSpec): THREE_NS.Group;
1610
+
1611
+ export { type AreaContext as A, type BuildOptions as B, DEFAULT_SPECIMENS as D, FLOORPLAN_AREA_ID as F, type HouseRendererOptions as H, type LightingOptions as L, type Messages as M, type RoomRects as R, SPECIMEN_AT as S, type Three as T, type HouseRenderer as a, type HouseRecord as b, type Damageable as c, type FloorplanEngineLike as d, type FloorplanTestOptions as e, type House as f, type HouseBoxCollider as g, type HouseFurnitureCollider as h, type HouseInteractable as i, type HouseInteractives as j, type HousePart as k, type HousePlan as l, type HousePoint as m, type HouseTargetOptions as n, type SpecimenDef as o, type TemplateGroup as p, type Translate as q, buildSpecimenMeshes as r, createFloorplanTestModule as s, createHouseScenarios as t, createTranslator as u, en as v, locales as w, ptBR as x, specimenSpec as y };