@adatechnology/game-floorplan 0.1.0 → 0.2.0
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 +32 -0
- package/dist/index.d.ts +446 -62
- package/dist/index.global.js +847 -214
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +847 -214
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
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
|
|
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<
|
|
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,
|
|
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:
|
|
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,
|
|
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
|
+
}
|
|
517
634
|
|
|
518
|
-
|
|
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;
|
|
693
|
+
|
|
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,191 @@ 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
|
+
type CityBuildingParams = {
|
|
883
|
+
x: number;
|
|
884
|
+
z: number;
|
|
885
|
+
width: number;
|
|
886
|
+
depth: number;
|
|
887
|
+
height: number;
|
|
888
|
+
color: number;
|
|
889
|
+
/** Chance of a ground-floor shop on both long faces; omitted means none. */
|
|
890
|
+
shopChance?: number;
|
|
891
|
+
/** Chance that a window is lit. */
|
|
892
|
+
litChance?: number;
|
|
893
|
+
random?: RandomSource;
|
|
894
|
+
seed?: number;
|
|
895
|
+
};
|
|
896
|
+
/** City building: block, roof slab, maybe a vent, maybe a shop front, and window instances on the four faces. */
|
|
897
|
+
declare function createCityBuilding(p: CityBuildingParams): Silhouette;
|
|
898
|
+
|
|
899
|
+
type Seeded = {
|
|
900
|
+
random?: RandomSource;
|
|
901
|
+
seed?: number;
|
|
902
|
+
};
|
|
903
|
+
type TwoStoreyParams = Seeded & {
|
|
904
|
+
x: number;
|
|
905
|
+
z: number;
|
|
906
|
+
width: number;
|
|
907
|
+
depth: number;
|
|
908
|
+
color: number;
|
|
909
|
+
roofColor?: number;
|
|
910
|
+
ry?: number;
|
|
911
|
+
};
|
|
912
|
+
/** Two-storey house with a balcony slab, pitched roof and four windows. */
|
|
913
|
+
declare function createTwoStoreyHouse(p: TwoStoreyParams): Silhouette;
|
|
914
|
+
type SlabHouseParams = Seeded & {
|
|
915
|
+
x: number;
|
|
916
|
+
z: number;
|
|
917
|
+
width: number;
|
|
918
|
+
depth: number;
|
|
919
|
+
floors: number;
|
|
920
|
+
color: number;
|
|
921
|
+
};
|
|
922
|
+
/** Reinforced-concrete slab house of one to three floors, with water tank, side stair and sometimes rebar starters. */
|
|
923
|
+
declare function createSlabHouse(p: SlabHouseParams): Silhouette;
|
|
924
|
+
type ColonialParams = Seeded & {
|
|
925
|
+
x: number;
|
|
926
|
+
z: number;
|
|
927
|
+
width: number;
|
|
928
|
+
color: number;
|
|
929
|
+
hasDoor: boolean;
|
|
930
|
+
};
|
|
931
|
+
/** Colonial terrace house: parapet, roof behind it and a row of doors or windows. */
|
|
932
|
+
declare function createColonialHouse(p: ColonialParams): Silhouette;
|
|
933
|
+
type ChaletParams = Seeded & {
|
|
934
|
+
x: number;
|
|
935
|
+
z: number;
|
|
936
|
+
color?: number;
|
|
937
|
+
ry?: number;
|
|
938
|
+
};
|
|
939
|
+
/** Wooden chalet on a stone base with a steep roof and a chimney. */
|
|
940
|
+
declare function createChalet(p: ChaletParams): Silhouette;
|
|
941
|
+
type CompanyHouseParams = Seeded & {
|
|
942
|
+
x: number;
|
|
943
|
+
z: number;
|
|
944
|
+
color?: number;
|
|
945
|
+
};
|
|
946
|
+
/** Company-town house with a low front fence. */
|
|
947
|
+
declare function createCompanyHouse(p: CompanyHouseParams): Silhouette;
|
|
948
|
+
type StiltHouseParams = Seeded & {
|
|
949
|
+
x: number;
|
|
950
|
+
z: number;
|
|
951
|
+
color?: number;
|
|
952
|
+
};
|
|
953
|
+
/** House on stilts with a ramp-like entry platform. */
|
|
954
|
+
declare function createStiltHouse(p: StiltHouseParams): Silhouette;
|
|
955
|
+
type FarmhouseParams = Seeded & {
|
|
956
|
+
x: number;
|
|
957
|
+
z: number;
|
|
958
|
+
};
|
|
959
|
+
/** Farm house with a long covered porch on six posts. */
|
|
960
|
+
declare function createFarmhouse(p: FarmhouseParams): Silhouette;
|
|
961
|
+
type DetachedHouseParams = Seeded & {
|
|
962
|
+
x: number;
|
|
963
|
+
z: number;
|
|
964
|
+
width: number;
|
|
965
|
+
depth: number;
|
|
966
|
+
color: number;
|
|
967
|
+
roofColor?: number;
|
|
968
|
+
ry?: number;
|
|
969
|
+
isBoarded?: boolean;
|
|
970
|
+
};
|
|
971
|
+
/** One-storey detached house; boarded windows get two crossed planks each. */
|
|
972
|
+
declare function createDetachedHouse(p: DetachedHouseParams): Silhouette;
|
|
606
973
|
|
|
607
974
|
declare const version = "0.1.0";
|
|
608
975
|
/**
|
|
@@ -634,6 +1001,13 @@ declare const engine: {
|
|
|
634
1001
|
registerState: typeof registerState;
|
|
635
1002
|
setStateDistribution: typeof setStateDistribution;
|
|
636
1003
|
registerLocale: typeof registerLocale;
|
|
1004
|
+
registerResultExtension: typeof registerResultExtension;
|
|
1005
|
+
registerFindsProvider: typeof registerFindsProvider;
|
|
1006
|
+
findsFor: typeof findsFor;
|
|
1007
|
+
findsAnswer: typeof findsAnswer;
|
|
1008
|
+
registerViewerLayer: typeof registerViewerLayer;
|
|
1009
|
+
viewerLayers: ViewerLayer[];
|
|
1010
|
+
blocksWindow: typeof blocksWindow;
|
|
637
1011
|
defineZone: typeof defineZone;
|
|
638
1012
|
getZone: (id: string) => ZoneDef | undefined;
|
|
639
1013
|
listZones: () => ZoneDef[];
|
|
@@ -643,9 +1017,10 @@ declare const engine: {
|
|
|
643
1017
|
translate: typeof translate;
|
|
644
1018
|
listLocales: () => string[];
|
|
645
1019
|
templates: Record<string, TemplateDef>;
|
|
646
|
-
catalog: Record<string,
|
|
1020
|
+
catalog: Record<string, FurnitureDef>;
|
|
647
1021
|
libraries: Record<string, SlotLibrary>;
|
|
648
1022
|
styles: Record<string, StyleDef>;
|
|
1023
|
+
paletteStyles: Record<string, PaletteStyleDef>;
|
|
649
1024
|
createRng: (seed: string | number, key: string) => Rng;
|
|
650
1025
|
mulberry32: typeof mulberry32;
|
|
651
1026
|
hashString: typeof hashString;
|
|
@@ -663,8 +1038,17 @@ declare const engine: {
|
|
|
663
1038
|
constants: {
|
|
664
1039
|
WALL_THICKNESS: number;
|
|
665
1040
|
DOOR_CLEARANCE: number;
|
|
1041
|
+
PLAYER_RADIUS: number;
|
|
1042
|
+
DOOR_EDGE_CLEARANCE: number;
|
|
1043
|
+
WINDOW_EDGE_CLEARANCE: number;
|
|
1044
|
+
OVERHEAD_TOP: number;
|
|
1045
|
+
CAR_CLEARANCE: {
|
|
1046
|
+
readonly driver: 0.8;
|
|
1047
|
+
readonly side: 0.6;
|
|
1048
|
+
readonly end: 0.6;
|
|
1049
|
+
};
|
|
666
1050
|
};
|
|
667
1051
|
};
|
|
668
1052
|
type FloorplanEngine = typeof engine;
|
|
669
1053
|
|
|
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
|
|
1054
|
+
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, 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 };
|