@adatechnology/game-floorplan 0.2.2 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/index.d.ts +655 -201
- package/dist/index.global.js +366 -207
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +272 -205
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -1,134 +1,120 @@
|
|
|
1
|
-
// src/constants.ts
|
|
2
|
-
var WALL_THICKNESS = 0.15;
|
|
3
|
-
var MARGIN = WALL_THICKNESS / 2;
|
|
4
|
-
var EPS = 1e-6;
|
|
5
|
-
var TOL = 1e-3;
|
|
6
|
-
var DOOR_CLEARANCE = 0.9;
|
|
7
|
-
var PLAYER_RADIUS = 0.24;
|
|
8
|
-
var DOOR_EDGE_CLEARANCE = 0.12;
|
|
9
|
-
var WINDOW_EDGE_CLEARANCE = 0.3;
|
|
10
|
-
var OVERHEAD_TOP = 2.15;
|
|
11
|
-
var WINDOWLESS_ROOM_TYPES = /* @__PURE__ */ new Set([
|
|
12
|
-
"stockroom",
|
|
13
|
-
"kitchen",
|
|
14
|
-
"laundry",
|
|
15
|
-
"bathroom",
|
|
16
|
-
"void",
|
|
17
|
-
"elevator",
|
|
18
|
-
"stairs",
|
|
19
|
-
"pantry",
|
|
20
|
-
"closet",
|
|
21
|
-
"corridor",
|
|
22
|
-
"hall",
|
|
23
|
-
"balcony",
|
|
24
|
-
"terrace",
|
|
25
|
-
"garage",
|
|
26
|
-
"storage",
|
|
27
|
-
"porch",
|
|
28
|
-
"tent",
|
|
29
|
-
"outhouse"
|
|
30
|
-
]);
|
|
31
|
-
var CAR_CLEARANCE = { driver: 0.8, side: 0.6, end: 0.6 };
|
|
32
|
-
|
|
33
1
|
// src/registry.ts
|
|
34
|
-
var
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
2
|
+
var createRegistries = () => ({
|
|
3
|
+
CATALOG: {},
|
|
4
|
+
LIBRARIES: {},
|
|
5
|
+
LIBRARY_ALIAS: {},
|
|
6
|
+
TEMPLATES: {},
|
|
7
|
+
STYLES: {},
|
|
8
|
+
STYLE_ALIAS: {},
|
|
9
|
+
PALETTE_STYLES: {},
|
|
10
|
+
ROOM_COLORS: [],
|
|
11
|
+
PASSES: [],
|
|
12
|
+
DECOR_PROFILES: {},
|
|
13
|
+
GROUND_OVERLAYS: [],
|
|
14
|
+
STATE_PLUGINS: { normal: { apply: () => [] } },
|
|
15
|
+
WALL_TOP_HEIGHTS: { none: 0 },
|
|
16
|
+
SEED_KEYS: { rooms: {}, items: {} },
|
|
17
|
+
stateDistribution: { weights: null, seedKey: "state" },
|
|
18
|
+
RESULT_EXTENSIONS: [],
|
|
19
|
+
FINDS_PROVIDERS: [],
|
|
20
|
+
VIEWER_LAYERS: [],
|
|
21
|
+
LOCALES: {},
|
|
22
|
+
ZONES: {},
|
|
23
|
+
PERMEABLE_GROUNDS: /* @__PURE__ */ new Set()
|
|
24
|
+
});
|
|
25
|
+
var defaultRegistries;
|
|
26
|
+
var activeRegistries;
|
|
27
|
+
var getDefaultRegistries = () => defaultRegistries ?? (defaultRegistries = createRegistries());
|
|
28
|
+
var registries = () => activeRegistries ?? getDefaultRegistries();
|
|
29
|
+
function withRegistries(scope, run) {
|
|
30
|
+
const previous = activeRegistries;
|
|
31
|
+
activeRegistries = scope;
|
|
32
|
+
try {
|
|
33
|
+
return run();
|
|
34
|
+
} finally {
|
|
35
|
+
activeRegistries = previous;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
49
38
|
function registerItem(def) {
|
|
50
39
|
const h = def.h;
|
|
51
40
|
const item = Object.assign({ front: "+z", window: h <= 0.95, low: h <= 0.5, flat: false, deck: false, rim: 0 }, def);
|
|
52
|
-
CATALOG[def.type] = item;
|
|
41
|
+
registries().CATALOG[def.type] = item;
|
|
53
42
|
return item;
|
|
54
43
|
}
|
|
55
44
|
function registerItems(list) {
|
|
56
45
|
for (const d of list) registerItem(d);
|
|
57
46
|
}
|
|
58
47
|
function registerLibrary(id, library) {
|
|
59
|
-
LIBRARIES[id] = library;
|
|
48
|
+
registries().LIBRARIES[id] = library;
|
|
60
49
|
}
|
|
61
50
|
function registerLibraryAlias(alias, id) {
|
|
62
|
-
LIBRARY_ALIAS[alias] = id;
|
|
51
|
+
registries().LIBRARY_ALIAS[alias] = id;
|
|
63
52
|
}
|
|
64
53
|
function registerTemplate(t) {
|
|
65
|
-
TEMPLATES[t.id] = t;
|
|
54
|
+
registries().TEMPLATES[t.id] = t;
|
|
66
55
|
return t;
|
|
67
56
|
}
|
|
68
57
|
function registerStyle(style) {
|
|
69
|
-
STYLES[style.id] = style;
|
|
70
|
-
for (const a of style.aliases || []) STYLE_ALIAS[a] = style.id;
|
|
58
|
+
registries().STYLES[style.id] = style;
|
|
59
|
+
for (const a of style.aliases || []) registries().STYLE_ALIAS[a] = style.id;
|
|
71
60
|
}
|
|
72
61
|
function registerPaletteStyle(id, def) {
|
|
73
|
-
PALETTE_STYLES[id] = def;
|
|
62
|
+
registries().PALETTE_STYLES[id] = def;
|
|
74
63
|
}
|
|
75
64
|
function registerRoomColors(list) {
|
|
76
65
|
for (const d of list) {
|
|
77
|
-
const i = ROOM_COLORS.findIndex((x) => x.type === d.type);
|
|
78
|
-
if (i >= 0) ROOM_COLORS.splice(i, 1);
|
|
79
|
-
ROOM_COLORS.push(d);
|
|
66
|
+
const i = registries().ROOM_COLORS.findIndex((x) => x.type === d.type);
|
|
67
|
+
if (i >= 0) registries().ROOM_COLORS.splice(i, 1);
|
|
68
|
+
registries().ROOM_COLORS.push(d);
|
|
80
69
|
}
|
|
81
|
-
ROOM_COLORS.sort((a, b) => a.order - b.order);
|
|
70
|
+
registries().ROOM_COLORS.sort((a, b) => a.order - b.order);
|
|
82
71
|
}
|
|
83
72
|
function registerDecorProfile(styleId, profile) {
|
|
84
|
-
DECOR_PROFILES[styleId] = profile;
|
|
73
|
+
registries().DECOR_PROFILES[styleId] = profile;
|
|
85
74
|
}
|
|
86
75
|
function registerPass(name, run) {
|
|
87
|
-
const i = PASSES.findIndex((p) => p.name === name);
|
|
88
|
-
if (i >= 0) PASSES[i] = { name, run };
|
|
89
|
-
else PASSES.push({ name, run });
|
|
76
|
+
const i = registries().PASSES.findIndex((p) => p.name === name);
|
|
77
|
+
if (i >= 0) registries().PASSES[i] = { name, run };
|
|
78
|
+
else registries().PASSES.push({ name, run });
|
|
90
79
|
}
|
|
91
80
|
function registerGroundOverlay(rule) {
|
|
92
|
-
GROUND_OVERLAYS.push(rule);
|
|
81
|
+
registries().GROUND_OVERLAYS.push(rule);
|
|
93
82
|
}
|
|
94
83
|
function registerWallTop(id, height) {
|
|
95
|
-
WALL_TOP_HEIGHTS[id] = height;
|
|
84
|
+
registries().WALL_TOP_HEIGHTS[id] = height;
|
|
96
85
|
}
|
|
97
86
|
function registerSeedKeys(keys) {
|
|
98
|
-
Object.assign(SEED_KEYS.rooms, keys.rooms);
|
|
99
|
-
Object.assign(SEED_KEYS.items, keys.items);
|
|
87
|
+
Object.assign(registries().SEED_KEYS.rooms, keys.rooms);
|
|
88
|
+
Object.assign(registries().SEED_KEYS.items, keys.items);
|
|
100
89
|
}
|
|
101
90
|
function registerState(name, plugin) {
|
|
102
|
-
STATE_PLUGINS[name] = plugin;
|
|
91
|
+
registries().STATE_PLUGINS[name] = plugin;
|
|
103
92
|
}
|
|
104
93
|
function setStateDistribution(weights, seedKey = "state") {
|
|
105
|
-
stateDistribution.weights = weights;
|
|
106
|
-
stateDistribution.seedKey = seedKey;
|
|
94
|
+
registries().stateDistribution.weights = weights;
|
|
95
|
+
registries().stateDistribution.seedKey = seedKey;
|
|
107
96
|
}
|
|
108
|
-
var listStates = () => Object.keys(STATE_PLUGINS);
|
|
97
|
+
var listStates = () => Object.keys(registries().STATE_PLUGINS);
|
|
109
98
|
function resolveStyleId(id) {
|
|
110
99
|
const s = id ?? "";
|
|
111
|
-
return STYLE_ALIAS[s] ?? s;
|
|
100
|
+
return registries().STYLE_ALIAS[s] ?? s;
|
|
112
101
|
}
|
|
113
102
|
function styleOf(id) {
|
|
114
|
-
return STYLES[id] || STYLES.budget || Object.values(STYLES)[0];
|
|
103
|
+
return registries().STYLES[id] || registries().STYLES.budget || Object.values(registries().STYLES)[0];
|
|
115
104
|
}
|
|
116
|
-
var RESULT_EXTENSIONS = [];
|
|
117
|
-
var FINDS_PROVIDERS = [];
|
|
118
105
|
function registerResultExtension(name, run, options = {}) {
|
|
119
106
|
const entry = { name, run, after: options.after || [], seedKey: options.seedKey ?? name };
|
|
120
|
-
const i = RESULT_EXTENSIONS.findIndex((x) => x.name === name);
|
|
121
|
-
if (i >= 0) RESULT_EXTENSIONS[i] = entry;
|
|
122
|
-
else RESULT_EXTENSIONS.push(entry);
|
|
107
|
+
const i = registries().RESULT_EXTENSIONS.findIndex((x) => x.name === name);
|
|
108
|
+
if (i >= 0) registries().RESULT_EXTENSIONS[i] = entry;
|
|
109
|
+
else registries().RESULT_EXTENSIONS.push(entry);
|
|
123
110
|
}
|
|
124
111
|
function registerFindsProvider(provider) {
|
|
125
|
-
FINDS_PROVIDERS.push(provider);
|
|
112
|
+
registries().FINDS_PROVIDERS.push(provider);
|
|
126
113
|
}
|
|
127
|
-
var VIEWER_LAYERS = [];
|
|
128
114
|
function registerViewerLayer(layer) {
|
|
129
|
-
const i = VIEWER_LAYERS.findIndex((x) => x.id === layer.id);
|
|
130
|
-
if (i >= 0) VIEWER_LAYERS[i] = layer;
|
|
131
|
-
else VIEWER_LAYERS.push(layer);
|
|
115
|
+
const i = registries().VIEWER_LAYERS.findIndex((x) => x.id === layer.id);
|
|
116
|
+
if (i >= 0) registries().VIEWER_LAYERS[i] = layer;
|
|
117
|
+
else registries().VIEWER_LAYERS.push(layer);
|
|
132
118
|
}
|
|
133
119
|
|
|
134
120
|
// src/rng.ts
|
|
@@ -208,7 +194,7 @@ function orderOf(extensions) {
|
|
|
208
194
|
return ordered;
|
|
209
195
|
}
|
|
210
196
|
function runResultExtensions(plan, result, seed, options) {
|
|
211
|
-
for (const extension of orderOf(RESULT_EXTENSIONS)) {
|
|
197
|
+
for (const extension of orderOf(registries().RESULT_EXTENSIONS)) {
|
|
212
198
|
result[extension.name] = extension.run({ plan, result, seed, rng: createRng(seed, extension.seedKey), options });
|
|
213
199
|
}
|
|
214
200
|
}
|
|
@@ -219,13 +205,45 @@ function findsAnswer(query) {
|
|
|
219
205
|
return answerOf(query);
|
|
220
206
|
}
|
|
221
207
|
function answerOf(query) {
|
|
222
|
-
for (const provider of FINDS_PROVIDERS) {
|
|
208
|
+
for (const provider of registries().FINDS_PROVIDERS) {
|
|
223
209
|
const stacks = provider.findsFor(query);
|
|
224
210
|
if (stacks !== null) return stacks;
|
|
225
211
|
}
|
|
226
212
|
return null;
|
|
227
213
|
}
|
|
228
214
|
|
|
215
|
+
// src/constants.ts
|
|
216
|
+
var WALL_THICKNESS = 0.15;
|
|
217
|
+
var MARGIN = WALL_THICKNESS / 2;
|
|
218
|
+
var EPS = 1e-6;
|
|
219
|
+
var TOL = 1e-3;
|
|
220
|
+
var DOOR_CLEARANCE = 0.9;
|
|
221
|
+
var PLAYER_RADIUS = 0.24;
|
|
222
|
+
var DOOR_EDGE_CLEARANCE = 0.12;
|
|
223
|
+
var WINDOW_EDGE_CLEARANCE = 0.3;
|
|
224
|
+
var OVERHEAD_TOP = 2.15;
|
|
225
|
+
var WINDOWLESS_ROOM_TYPES = /* @__PURE__ */ new Set([
|
|
226
|
+
"stockroom",
|
|
227
|
+
"kitchen",
|
|
228
|
+
"laundry",
|
|
229
|
+
"bathroom",
|
|
230
|
+
"void",
|
|
231
|
+
"elevator",
|
|
232
|
+
"stairs",
|
|
233
|
+
"pantry",
|
|
234
|
+
"closet",
|
|
235
|
+
"corridor",
|
|
236
|
+
"hall",
|
|
237
|
+
"balcony",
|
|
238
|
+
"terrace",
|
|
239
|
+
"garage",
|
|
240
|
+
"storage",
|
|
241
|
+
"porch",
|
|
242
|
+
"tent",
|
|
243
|
+
"outhouse"
|
|
244
|
+
]);
|
|
245
|
+
var CAR_CLEARANCE = { driver: 0.8, side: 0.6, end: 0.6 };
|
|
246
|
+
|
|
229
247
|
// src/geometry.ts
|
|
230
248
|
var r2 = (x) => Math.round(x * 100) / 100;
|
|
231
249
|
var clamp = (x, a, b) => Math.max(a, Math.min(b, x));
|
|
@@ -442,6 +460,7 @@ var STEP = 0.05;
|
|
|
442
460
|
var MAX_CANDIDATES = 80;
|
|
443
461
|
function carCandidates(slot, item, car) {
|
|
444
462
|
const front = [slot.frontU, slot.frontV];
|
|
463
|
+
if (!slot._cell) throw new Error("Slot without a cell: " + slot.id);
|
|
445
464
|
const zone = slot._cell.R;
|
|
446
465
|
const alongV = Math.abs(front[1]) === 1;
|
|
447
466
|
const [extentU, extentV] = extent([item.w, item.d], front);
|
|
@@ -660,13 +679,14 @@ function candidatesOf(cats) {
|
|
|
660
679
|
const out = [];
|
|
661
680
|
for (const [cat, weight] of Object.entries(cats)) {
|
|
662
681
|
const exact = cat[0] === "=";
|
|
663
|
-
const its = Object.values(CATALOG).filter((i) => !i.decor && (exact ? i.type === cat.slice(1) : !i.exactOnly && (i.category === cat || i.type === cat)));
|
|
682
|
+
const its = Object.values(registries().CATALOG).filter((i) => !i.decor && (exact ? i.type === cat.slice(1) : !i.exactOnly && (i.category === cat || i.type === cat)));
|
|
664
683
|
for (const it of its) out.push({ it, weight: weight / its.length });
|
|
665
684
|
}
|
|
666
685
|
return out;
|
|
667
686
|
}
|
|
668
687
|
function itemRect(slot, it, shift) {
|
|
669
688
|
const c = slot._cell;
|
|
689
|
+
if (!c) throw new Error("Slot without a cell: " + slot.id);
|
|
670
690
|
const f = c.f;
|
|
671
691
|
const [extentU, extentV] = extent([it.w, it.d], f);
|
|
672
692
|
const R = c.R;
|
|
@@ -751,7 +771,7 @@ function fillRoom(plan, room, slots2, rng) {
|
|
|
751
771
|
low: it.low,
|
|
752
772
|
aabb: r.map(r2),
|
|
753
773
|
_r: r,
|
|
754
|
-
_seedId: SEED_KEYS.items[id] ?? id
|
|
774
|
+
_seedId: registries().SEED_KEYS.items[id] ?? id
|
|
755
775
|
};
|
|
756
776
|
if (it.overhead) m.overhead = !overheadOff;
|
|
757
777
|
if (it.category === "car") {
|
|
@@ -771,7 +791,7 @@ function fillRoom(plan, room, slots2, rng) {
|
|
|
771
791
|
if (!parent) return null;
|
|
772
792
|
for (const { it } of cands) {
|
|
773
793
|
if (it.w > parent.w + EPS || it.d > parent.d + EPS) continue;
|
|
774
|
-
const f = [parent.frontU, parent.frontV];
|
|
794
|
+
const f = [parent.frontU ?? 0, parent.frontV ?? 1];
|
|
775
795
|
const r = parent.aabb;
|
|
776
796
|
const [extentU, extentV] = extent([it.w, it.d], f);
|
|
777
797
|
const cu = (r[0] + r[2]) / 2 - f[0] * (parent.d / 2 - it.d / 2);
|
|
@@ -805,7 +825,7 @@ function fillRoom(plan, room, slots2, rng) {
|
|
|
805
825
|
if (!car && !relax && s.clearance > 0 && !it.low) {
|
|
806
826
|
cl2 = clearRect(r3, f, s.clearance);
|
|
807
827
|
if (!insideUnion(cl2, inners)) continue;
|
|
808
|
-
if (items.some((m2) => !m2.low && !m2.flat && !m2.on && overlaps(cl2, m2._r))) continue;
|
|
828
|
+
if (items.some((m2) => !m2.low && !m2.flat && !m2.on && overlaps(cl2, m2._r ?? m2.aabb))) continue;
|
|
809
829
|
}
|
|
810
830
|
if (!it.low && reserves.some((q) => overlaps(r3, q))) continue;
|
|
811
831
|
let rimRect2 = null;
|
|
@@ -902,9 +922,9 @@ var placementKit = {
|
|
|
902
922
|
clearRect,
|
|
903
923
|
pickWeighted,
|
|
904
924
|
createRng,
|
|
905
|
-
roomSeedKey: (room) => room.seedKey ?? SEED_KEYS.rooms[room.id] ?? room.id,
|
|
925
|
+
roomSeedKey: (room) => room.seedKey ?? registries().SEED_KEYS.rooms[room.id] ?? room.id,
|
|
906
926
|
shuffle,
|
|
907
|
-
facingRotation: (f, type) => rotationFor(f, CATALOG[type].front),
|
|
927
|
+
facingRotation: (f, type) => rotationFor(f, registries().CATALOG[type].front),
|
|
908
928
|
cutIntervals,
|
|
909
929
|
blocksWindow
|
|
910
930
|
};
|
|
@@ -912,7 +932,7 @@ function createPlacementContext(plan, items) {
|
|
|
912
932
|
const added = [];
|
|
913
933
|
const counters = {};
|
|
914
934
|
const make = (room, type, r, f, o) => {
|
|
915
|
-
const it = CATALOG[type];
|
|
935
|
+
const it = registries().CATALOG[type];
|
|
916
936
|
const n = counters[room.id + type] = (counters[room.id + type] || 0) + 1;
|
|
917
937
|
return Object.assign(
|
|
918
938
|
{
|
|
@@ -958,9 +978,9 @@ function createPlacementContext(plan, items) {
|
|
|
958
978
|
const gridOf = (c) => gridCache[c.id] || (gridCache[c.id] = createGrid(plan, c, ignored));
|
|
959
979
|
function placeOnFloor(room, type, rng2, optsIn) {
|
|
960
980
|
const opts = Object.assign({}, optsIn || {});
|
|
961
|
-
const it0 = CATALOG[type];
|
|
981
|
+
const it0 = registries().CATALOG[type];
|
|
962
982
|
if (it0.flat) opts.flat = true;
|
|
963
|
-
const it = CATALOG[type];
|
|
983
|
+
const it = registries().CATALOG[type];
|
|
964
984
|
const inners = usableParts(room, 0);
|
|
965
985
|
const solidList = solidsOfRoom(room);
|
|
966
986
|
const zones = zonesOfFloor(plan, room.floor);
|
|
@@ -993,7 +1013,7 @@ function createPlacementContext(plan, items) {
|
|
|
993
1013
|
if (!(opts.without && opts.without(r))) return r;
|
|
994
1014
|
continue;
|
|
995
1015
|
}
|
|
996
|
-
if (occupied.some((m) => !m.low && !m.flat && !m.on && !m.decor && m.clearance > 0 && overlaps(r, clearRect(m._r, [m.frontU, m.frontV], m.clearance)))) continue;
|
|
1016
|
+
if (occupied.some((m) => !m.low && !m.flat && !m.on && !m.decor && (m.clearance ?? 0) > 0 && overlaps(r, clearRect(m._r, [m.frontU ?? 0, m.frontV ?? 1], m.clearance ?? 0)))) continue;
|
|
997
1017
|
if (opts.without && opts.without(r)) continue;
|
|
998
1018
|
if (!reachable(opts.railing || gridOf(room), solidList.concat([r]), room.outdoor ? 0.16 : plan.playerRadius)) continue;
|
|
999
1019
|
return r;
|
|
@@ -1039,7 +1059,7 @@ function groundCover(plan, items, ctx) {
|
|
|
1039
1059
|
z.parts.forEach((p, i) => groundPiece(z, z.ground, p, 0, i));
|
|
1040
1060
|
let k = 0;
|
|
1041
1061
|
const clip = (r) => z.parts.map((p) => [Math.max(r[0], p[0]), Math.max(r[1], p[1]), Math.min(r[2], p[2]), Math.min(r[3], p[3])]).filter((q) => q[2] - q[0] > 0.3 && q[3] - q[1] > 0.3).sort((a, b) => areaOf(b) - areaOf(a))[0];
|
|
1042
|
-
for (const rule of GROUND_OVERLAYS) {
|
|
1062
|
+
for (const rule of registries().GROUND_OVERLAYS) {
|
|
1043
1063
|
const triggers = items.filter((m) => m.room === z.id && m.category === rule.category);
|
|
1044
1064
|
if (rule.merge) {
|
|
1045
1065
|
if (triggers.length && z.ground !== rule.unlessGround) {
|
|
@@ -1059,19 +1079,20 @@ function groundCover(plan, items, ctx) {
|
|
|
1059
1079
|
function runPostProcess(plan, items, seed) {
|
|
1060
1080
|
const ctx = createPlacementContext(plan, items);
|
|
1061
1081
|
const rng = createRng(seed, STREAM.decor);
|
|
1062
|
-
for (const pass of PASSES) pass.run({ plan, items, seed, rng, ctx, kit: placementKit, catalog: CATALOG, profiles: DECOR_PROFILES });
|
|
1082
|
+
for (const pass of registries().PASSES) pass.run({ plan, items, seed, rng, ctx, kit: placementKit, catalog: registries().CATALOG, profiles: registries().DECOR_PROFILES });
|
|
1063
1083
|
groundCover(plan, items, ctx);
|
|
1064
1084
|
return ctx;
|
|
1065
1085
|
}
|
|
1066
1086
|
|
|
1067
1087
|
// src/locale.ts
|
|
1068
|
-
var locales = {};
|
|
1069
1088
|
function registerLocale(code, table) {
|
|
1089
|
+
const { LOCALES: locales } = registries();
|
|
1070
1090
|
const cur = locales[code] = locales[code] || {};
|
|
1071
1091
|
for (const ns of Object.keys(table)) cur[ns] = Object.assign(cur[ns] || {}, table[ns]);
|
|
1072
1092
|
}
|
|
1073
|
-
var listLocales = () => Object.keys(
|
|
1093
|
+
var listLocales = () => Object.keys(registries().LOCALES);
|
|
1074
1094
|
function translate(ns, key, locale = "en", vars) {
|
|
1095
|
+
const { LOCALES: locales } = registries();
|
|
1075
1096
|
const raw = locales[locale]?.[ns]?.[key] ?? locales.en?.[ns]?.[key] ?? key;
|
|
1076
1097
|
return vars ? raw.replace(/\{(\w+)\}/g, (m, k) => k in vars ? String(vars[k]) : m) : raw;
|
|
1077
1098
|
}
|
|
@@ -1200,22 +1221,20 @@ function addExteriorDoorPaths(plan, c) {
|
|
|
1200
1221
|
}
|
|
1201
1222
|
|
|
1202
1223
|
// src/zoning.ts
|
|
1203
|
-
var ZONES = {};
|
|
1204
|
-
var PERMEABLE_GROUNDS = /* @__PURE__ */ new Set();
|
|
1205
1224
|
function defineZone(zone) {
|
|
1206
1225
|
if (!zone || !zone.id) throw new Error("defineZone: id is required");
|
|
1207
|
-
ZONES[zone.id] = zone;
|
|
1226
|
+
registries().ZONES[zone.id] = zone;
|
|
1208
1227
|
return zone;
|
|
1209
1228
|
}
|
|
1210
|
-
var getZone = (id) => ZONES[id];
|
|
1211
|
-
var listZones = () => Object.values(ZONES);
|
|
1229
|
+
var getZone = (id) => registries().ZONES[id];
|
|
1230
|
+
var listZones = () => Object.values(registries().ZONES);
|
|
1212
1231
|
function registerPermeableGround(...types) {
|
|
1213
|
-
for (const t of types) PERMEABLE_GROUNDS.add(t);
|
|
1232
|
+
for (const t of types) registries().PERMEABLE_GROUNDS.add(t);
|
|
1214
1233
|
}
|
|
1215
1234
|
function resolveZone(z) {
|
|
1216
1235
|
if (!z) return null;
|
|
1217
1236
|
if (typeof z === "string") {
|
|
1218
|
-
const found = ZONES[z];
|
|
1237
|
+
const found = registries().ZONES[z];
|
|
1219
1238
|
if (!found) throw new Error("Unknown zone: " + z);
|
|
1220
1239
|
return found;
|
|
1221
1240
|
}
|
|
@@ -1261,7 +1280,7 @@ function checkLot(zoneIn, lot, plan) {
|
|
|
1261
1280
|
const far = m.built / area;
|
|
1262
1281
|
if (far > zone.maxFar + 1e-9) out.push({ rule: "far", actual: r2(far), limit: zone.maxFar });
|
|
1263
1282
|
let permeable = 0;
|
|
1264
|
-
for (const z of lot.zones) if (PERMEABLE_GROUNDS.has(z.ground)) for (const p of z.parts) permeable += (p[2] - p[0]) * (p[3] - p[1]);
|
|
1283
|
+
for (const z of lot.zones) if (z.ground && registries().PERMEABLE_GROUNDS.has(z.ground)) for (const p of z.parts) permeable += (p[2] - p[0]) * (p[3] - p[1]);
|
|
1265
1284
|
const permeability = permeable / area;
|
|
1266
1285
|
if (permeability < zone.permeableMin - 1e-9) out.push({ rule: "permeable", actual: r2(permeability), limit: zone.permeableMin });
|
|
1267
1286
|
return out;
|
|
@@ -1299,17 +1318,17 @@ function clampLotToZone(cfg, zone, adjustments, partyWalls = []) {
|
|
|
1299
1318
|
}
|
|
1300
1319
|
var ADJUSTABLE_ZONES = /* @__PURE__ */ new Set(["garden", "backyard", "side_yard"]);
|
|
1301
1320
|
function enforcePermeability(lot, zones, zone, adjustments) {
|
|
1302
|
-
const target = [...PERMEABLE_GROUNDS][0];
|
|
1321
|
+
const target = [...registries().PERMEABLE_GROUNDS][0];
|
|
1303
1322
|
if (!target) return;
|
|
1304
1323
|
const [u0, v0, u1, v1] = lot.rect;
|
|
1305
1324
|
const area = (u1 - u0) * (v1 - v0);
|
|
1306
1325
|
const areaOfZone = (z) => z.parts.reduce((s, p) => s + (p[2] - p[0]) * (p[3] - p[1]), 0);
|
|
1307
|
-
let permeable = zones.filter((z) => PERMEABLE_GROUNDS.has(z.ground)).reduce((s, z) => s + areaOfZone(z), 0);
|
|
1326
|
+
let permeable = zones.filter((z) => z.ground != null && registries().PERMEABLE_GROUNDS.has(z.ground)).reduce((s, z) => s + areaOfZone(z), 0);
|
|
1308
1327
|
if (permeable / area >= zone.permeableMin) return;
|
|
1309
|
-
const candidates = zones.filter((z) => ADJUSTABLE_ZONES.has(z.type) && !PERMEABLE_GROUNDS.has(z.ground)).sort((a, b) => areaOfZone(b) - areaOfZone(a));
|
|
1328
|
+
const candidates = zones.filter((z) => ADJUSTABLE_ZONES.has(z.type) && !(z.ground != null && registries().PERMEABLE_GROUNDS.has(z.ground))).sort((a, b) => areaOfZone(b) - areaOfZone(a));
|
|
1310
1329
|
for (const z of candidates) {
|
|
1311
1330
|
if (permeable / area >= zone.permeableMin) break;
|
|
1312
|
-
adjustments.push({ field: "ground:" + z.id, from: z.ground, to: target, reason: "permeable_min" });
|
|
1331
|
+
adjustments.push({ field: "ground:" + z.id, from: z.ground ?? "", to: target, reason: "permeable_min" });
|
|
1313
1332
|
z.ground = target;
|
|
1314
1333
|
permeable += areaOfZone(z);
|
|
1315
1334
|
}
|
|
@@ -1539,9 +1558,9 @@ function buildLot(plan, tpl, w, d, op, style, styleId, bc) {
|
|
|
1539
1558
|
paths: [],
|
|
1540
1559
|
pool: !!cfg.pool
|
|
1541
1560
|
};
|
|
1542
|
-
const
|
|
1561
|
+
const ZONES = [];
|
|
1543
1562
|
const libs = Object.assign({ garden: "garden", backyard: "backyard", parking: "parking", sideYard: "side_yard" }, cfg.libraries || {});
|
|
1544
|
-
const addZone = (id, type, label, parts, library) =>
|
|
1563
|
+
const addZone = (id, type, label, parts, library) => ZONES.push(Object.assign(normalizeRoom({ id, type, label, rect: parts[0], parts: parts.slice(1), library, outdoor: true }, -1), { floor: -1, outdoor: true }));
|
|
1545
1564
|
if (setback > 0) {
|
|
1546
1565
|
let parts = [[-marginL, -setback, w + marginR, 0]];
|
|
1547
1566
|
if (cfg.parking) {
|
|
@@ -1578,9 +1597,9 @@ function buildLot(plan, tpl, w, d, op, style, styleId, bc) {
|
|
|
1578
1597
|
height: type === "pedestrian" ? style.height : Math.min(style.height, 2.2),
|
|
1579
1598
|
side,
|
|
1580
1599
|
to: toTarget || null,
|
|
1581
|
-
material: "iron"
|
|
1600
|
+
material: "iron",
|
|
1601
|
+
zones: openingZones(u, v, "u", width, openingDepth(width, type === "pedestrian" ? width : 0))
|
|
1582
1602
|
};
|
|
1583
|
-
g.zones = openingZones(u, v, "u", width, openingDepth(width, type === "pedestrian" ? width : 0));
|
|
1584
1603
|
gates.push(g);
|
|
1585
1604
|
return g;
|
|
1586
1605
|
};
|
|
@@ -1621,14 +1640,14 @@ function buildLot(plan, tpl, w, d, op, style, styleId, bc) {
|
|
|
1621
1640
|
}
|
|
1622
1641
|
}
|
|
1623
1642
|
if (tpl.paths) paths.push(...tpl.paths(plan, { gates, setback, marginLeft: marginL, marginRight: marginR, backyard: backDepth, w, d }));
|
|
1624
|
-
else addExteriorDoorPaths(plan, { gates, paths, zones:
|
|
1643
|
+
else addExteriorDoorPaths(plan, { gates, paths, zones: ZONES, setback, marginLeft: marginL, marginRight: marginR, backyard: backDepth, w, target: cfg.doorTarget });
|
|
1625
1644
|
plan.paths = paths;
|
|
1626
1645
|
lot.paths = paths;
|
|
1627
1646
|
const boundary = (rule) => {
|
|
1628
1647
|
const type = pickWeighted(rLot, rule.type);
|
|
1629
1648
|
const top = type === "railing" ? "none" : pickWeighted(rLot, rule.top);
|
|
1630
1649
|
const wallHeight = type === "railing" ? 1.2 : type === "fence" ? style.fenceHeight ?? 2 : style.height;
|
|
1631
|
-
return { type, material: type === "wall" ? "block" : type === "fence" ? "wire_mesh" : "iron", height: wallHeight, top, totalHeight: r2(wallHeight + WALL_TOP_HEIGHTS[top]), thickness: WALL_THICKNESS };
|
|
1650
|
+
return { type, material: type === "wall" ? "block" : type === "fence" ? "wire_mesh" : "iron", height: wallHeight, top, totalHeight: r2(wallHeight + registries().WALL_TOP_HEIGHTS[top]), thickness: WALL_THICKNESS };
|
|
1632
1651
|
};
|
|
1633
1652
|
const A = { front: boundary(style.front), left: boundary(style.sideYard), right: boundary(style.sideYard), back: boundary(style.back) };
|
|
1634
1653
|
const seg = (side, u0, v0, u1, v1) => {
|
|
@@ -1661,10 +1680,10 @@ function buildLot(plan, tpl, w, d, op, style, styleId, bc) {
|
|
|
1661
1680
|
else if (backDepth > 0) seg("left", 0, d, 0, d + backDepth);
|
|
1662
1681
|
if (marginR > 0.5) seg("right", w + marginR, vi, w + marginR, d + backDepth);
|
|
1663
1682
|
else if (backDepth > 0) seg("right", w, d, w, d + backDepth);
|
|
1664
|
-
for (const z of
|
|
1665
|
-
if (bc.zone) enforcePermeability(lot,
|
|
1666
|
-
plan.zones =
|
|
1667
|
-
lot.zones =
|
|
1683
|
+
for (const z of ZONES) z.ground = (cfg.grounds || {})[z.id] || (cfg.grounds || {})[z.type] || pickWeighted(rLot, style.grounds[z.type] || { concrete: 1 });
|
|
1684
|
+
if (bc.zone) enforcePermeability(lot, ZONES, bc.zone, bc.adjustments || []);
|
|
1685
|
+
plan.zones = ZONES;
|
|
1686
|
+
lot.zones = ZONES;
|
|
1668
1687
|
plan.lot = lot;
|
|
1669
1688
|
}
|
|
1670
1689
|
|
|
@@ -1714,8 +1733,8 @@ var hexString = (n) => "#" + (n >>> 0).toString(16).padStart(6, "0");
|
|
|
1714
1733
|
function palette(o) {
|
|
1715
1734
|
const opt = o || {};
|
|
1716
1735
|
let style = resolveStyleId(opt.style || "budget");
|
|
1717
|
-
if (!PALETTE_STYLES[style]) style = PALETTE_STYLES.mid ? "mid" : Object.keys(PALETTE_STYLES)[0];
|
|
1718
|
-
const def = PALETTE_STYLES[style];
|
|
1736
|
+
if (!registries().PALETTE_STYLES[style]) style = registries().PALETTE_STYLES.mid ? "mid" : Object.keys(registries().PALETTE_STYLES)[0];
|
|
1737
|
+
const def = registries().PALETTE_STYLES[style];
|
|
1719
1738
|
const state = opt.state || "normal";
|
|
1720
1739
|
const seed = opt.seed == null ? 1 : opt.seed;
|
|
1721
1740
|
const rng = createRng(seed, STREAM.palettePrefix + (def.seedKey ?? style));
|
|
@@ -1733,14 +1752,14 @@ function palette(o) {
|
|
|
1733
1752
|
const { wallMode, sMax } = early;
|
|
1734
1753
|
const R = Object.assign({}, early.roles);
|
|
1735
1754
|
const ctx = Object.assign({ style, sMax, wallMode, generalFloor: early.generalFloor }, draw);
|
|
1736
|
-
for (const c of ROOM_COLORS) {
|
|
1755
|
+
for (const c of registries().ROOM_COLORS) {
|
|
1737
1756
|
const [wh, wl] = c.wall(ctx);
|
|
1738
1757
|
R["wall_" + c.type] = hsl(wh, c.neutral ? Math.min(0.16, sMax) : clamp(jit(sMax * 0.75, sMax * 0.5), 0.03, sMax), jit(wl, 0.03));
|
|
1739
1758
|
const pi = c.floor || early.generalFloor;
|
|
1740
1759
|
R["floor_" + c.type] = hsl(pi[0], Math.min(pi[1], wallMode ? 0.18 : 0.3), jit(pi[2], 0.04));
|
|
1741
1760
|
}
|
|
1742
1761
|
Object.assign(R, def.late(draw, early));
|
|
1743
|
-
STATE_PLUGINS[state]?.adjustPalette?.(R);
|
|
1762
|
+
registries().STATE_PLUGINS[state]?.adjustPalette?.(R);
|
|
1744
1763
|
const adjust = (color, ref, min, preferredDir) => {
|
|
1745
1764
|
for (let i = 0; i < 60; i++) {
|
|
1746
1765
|
if (Math.abs(lstar(hslToInt(color.h, color.s, color.l)) - lstar(hslToInt(ref.h, ref.s, ref.l))) >= min) return;
|
|
@@ -1750,7 +1769,7 @@ function palette(o) {
|
|
|
1750
1769
|
color.l = clamp(color.l + dir * 0.015, 0.04, 0.96);
|
|
1751
1770
|
}
|
|
1752
1771
|
};
|
|
1753
|
-
const types = ROOM_COLORS.map((c) => c.type);
|
|
1772
|
+
const types = registries().ROOM_COLORS.map((c) => c.type);
|
|
1754
1773
|
for (const c of types) {
|
|
1755
1774
|
const w = R["wall_" + c];
|
|
1756
1775
|
const p = R["floor_" + c];
|
|
@@ -1804,8 +1823,8 @@ var SIDE_OPPOSITE = { front: "back", back: "front", left: "right", right: "left"
|
|
|
1804
1823
|
var WINDOW_SIDE = { front: "front", back: "back", left: "left", right: "right" };
|
|
1805
1824
|
function slotDefsOf(plan, room) {
|
|
1806
1825
|
const name = room.library || room.type;
|
|
1807
|
-
const key = LIBRARY_ALIAS[name] || name;
|
|
1808
|
-
const library = room.slots ? room.slots : LIBRARIES[key];
|
|
1826
|
+
const key = registries().LIBRARY_ALIAS[name] || name;
|
|
1827
|
+
const library = room.slots ? room.slots : registries().LIBRARIES[key];
|
|
1809
1828
|
if (!library) return [];
|
|
1810
1829
|
const R = inner(room.parts[0]);
|
|
1811
1830
|
let defs = typeof library === "function" ? library({ w: R[2] - R[0], d: R[3] - R[1] }) : library.slice();
|
|
@@ -1867,7 +1886,7 @@ function resolveSlot(plan, room, def, byId, zones) {
|
|
|
1867
1886
|
};
|
|
1868
1887
|
const invalid = (m) => Object.assign(base, { valid: false, reason: m, x: 0, z: 0, ry: 0, w: 0, d: 0, frontU: 0, frontV: 1, aabb: [0, 0, 0, 0], _cell: null });
|
|
1869
1888
|
if (def.anchor === "on" || def.anchor === "inside") {
|
|
1870
|
-
const parent = byId[def.parent];
|
|
1889
|
+
const parent = def.parent ? byId[def.parent] : void 0;
|
|
1871
1890
|
if (!parent || !parent.valid) return invalid("invalid_parent");
|
|
1872
1891
|
return Object.assign(base, { x: parent.x, z: parent.z, ry: parent.ry, w: parent.w, d: parent.d, frontU: parent.frontU, frontV: parent.frontV, aabb: parent.aabb, _cell: parent._cell });
|
|
1873
1892
|
}
|
|
@@ -1908,9 +1927,10 @@ function resolveSlot(plan, room, def, byId, zones) {
|
|
|
1908
1927
|
const windowList = windowsOfRoom(plan, room);
|
|
1909
1928
|
win = windowList[def.n];
|
|
1910
1929
|
if (!win) return invalid("no_window");
|
|
1930
|
+
const found2 = win;
|
|
1911
1931
|
side = room.outdoor ? SIDE_OPPOSITE[win.side] : WINDOW_SIDE[win.side];
|
|
1912
1932
|
const cand = room.parts.map(inner).find(
|
|
1913
|
-
(r) => (
|
|
1933
|
+
(r) => (found2.axis === "u" ? found2.u >= r[0] - TOL && found2.u <= r[2] + TOL : found2.v >= r[1] - TOL && found2.v <= r[3] + TOL) && (side === "left" && eq(r[0], found2.pos + MARGIN) || side === "right" && eq(r[2], found2.pos - MARGIN) || side === "front" && eq(r[1], found2.pos + MARGIN) || side === "back" && eq(r[3], found2.pos - MARGIN))
|
|
1914
1934
|
);
|
|
1915
1935
|
if (!cand) return invalid("window_outside_room");
|
|
1916
1936
|
R = cand;
|
|
@@ -1995,8 +2015,8 @@ function resolveSlot(plan, room, def, byId, zones) {
|
|
|
1995
2015
|
// src/generate.ts
|
|
1996
2016
|
function templateOf(t) {
|
|
1997
2017
|
if (typeof t === "string") {
|
|
1998
|
-
if (!TEMPLATES[t]) throw new Error("Unknown template: " + t);
|
|
1999
|
-
return TEMPLATES[t];
|
|
2018
|
+
if (!registries().TEMPLATES[t]) throw new Error("Unknown template: " + t);
|
|
2019
|
+
return registries().TEMPLATES[t];
|
|
2000
2020
|
}
|
|
2001
2021
|
return t;
|
|
2002
2022
|
}
|
|
@@ -2014,10 +2034,10 @@ function slots(template, options) {
|
|
|
2014
2034
|
return resolveSlots(plan).map(cleanSlot).map((s) => s.reason ? Object.assign(s, { reason: translate("reasons", s.reason, locale) }) : s);
|
|
2015
2035
|
}
|
|
2016
2036
|
function pickState(requested, seed) {
|
|
2017
|
-
if (requested && STATE_PLUGINS[requested]) return requested;
|
|
2018
|
-
const dist = stateDistribution.weights;
|
|
2037
|
+
if (requested && registries().STATE_PLUGINS[requested]) return requested;
|
|
2038
|
+
const dist = registries().stateDistribution.weights;
|
|
2019
2039
|
if (!dist) return "normal";
|
|
2020
|
-
const x = createRng(seed, stateDistribution.seedKey)();
|
|
2040
|
+
const x = createRng(seed, registries().stateDistribution.seedKey)();
|
|
2021
2041
|
let acc = 0;
|
|
2022
2042
|
const keys = Object.keys(dist);
|
|
2023
2043
|
for (const k of keys) {
|
|
@@ -2027,13 +2047,13 @@ function pickState(requested, seed) {
|
|
|
2027
2047
|
return keys[keys.length - 1];
|
|
2028
2048
|
}
|
|
2029
2049
|
function colorOf(m, seed) {
|
|
2030
|
-
const spec = m.colorSpec || CATALOG[m.type]?.color || { role: "wood" };
|
|
2050
|
+
const spec = m.colorSpec || registries().CATALOG[m.type]?.color || { role: "wood" };
|
|
2031
2051
|
if ("role" in spec) return spec.role;
|
|
2032
2052
|
if ("hex" in spec) return spec.hex;
|
|
2033
2053
|
return spec.pick[hashString(seed + "|" + (m._seedId ?? m.id)) % spec.pick.length];
|
|
2034
2054
|
}
|
|
2035
2055
|
function applyState(plan, items, ctx, seed, state) {
|
|
2036
|
-
const plugin = STATE_PLUGINS[state];
|
|
2056
|
+
const plugin = registries().STATE_PLUGINS[state];
|
|
2037
2057
|
if (!plugin || state === "normal") return [];
|
|
2038
2058
|
const c = {
|
|
2039
2059
|
plan,
|
|
@@ -2043,8 +2063,8 @@ function applyState(plan, items, ctx, seed, state) {
|
|
|
2043
2063
|
rng: createRng(seed, plugin.seedKey ?? "state:" + state),
|
|
2044
2064
|
ctx,
|
|
2045
2065
|
kit: placementKit,
|
|
2046
|
-
catalog: CATALOG,
|
|
2047
|
-
wallTopHeights: WALL_TOP_HEIGHTS
|
|
2066
|
+
catalog: registries().CATALOG,
|
|
2067
|
+
wallTopHeights: registries().WALL_TOP_HEIGHTS
|
|
2048
2068
|
};
|
|
2049
2069
|
return plugin.apply(c);
|
|
2050
2070
|
}
|
|
@@ -2064,7 +2084,7 @@ function generate(template, options) {
|
|
|
2064
2084
|
const missing = [];
|
|
2065
2085
|
for (const room of plan.rooms.concat(plan.zones)) {
|
|
2066
2086
|
const sl = all.filter((s) => s.room === room.id && s.floor === room.floor);
|
|
2067
|
-
const r = fillRoom(plan, room, sl, createRng(seed, STREAM.roomPrefix + (room.seedKey ?? SEED_KEYS.rooms[room.id] ?? room.id)));
|
|
2087
|
+
const r = fillRoom(plan, room, sl, createRng(seed, STREAM.roomPrefix + (room.seedKey ?? registries().SEED_KEYS.rooms[room.id] ?? room.id)));
|
|
2068
2088
|
items.push(...r.items);
|
|
2069
2089
|
missing.push(...r.missing);
|
|
2070
2090
|
}
|
|
@@ -2104,7 +2124,7 @@ function generate(template, options) {
|
|
|
2104
2124
|
if (m.category) out.color = colorOf(m, seed);
|
|
2105
2125
|
return out;
|
|
2106
2126
|
});
|
|
2107
|
-
const
|
|
2127
|
+
const base = {
|
|
2108
2128
|
template: tpl.id,
|
|
2109
2129
|
name: translate("templates", tpl.id, locale),
|
|
2110
2130
|
use: useOf(tpl),
|
|
@@ -2141,8 +2161,8 @@ function generate(template, options) {
|
|
|
2141
2161
|
building: tpl.building ? tpl.building(plan.w, plan.d, op) : null,
|
|
2142
2162
|
missing
|
|
2143
2163
|
};
|
|
2144
|
-
if (tpl.singleFloor)
|
|
2145
|
-
result.partyWalls
|
|
2164
|
+
if (tpl.singleFloor) base.floorNumber = op.floor || 3;
|
|
2165
|
+
const result = Object.assign(base, { partyWalls: tpl.partyWalls || [] });
|
|
2146
2166
|
if (plan.config) result.config = plan.config;
|
|
2147
2167
|
runResultExtensions(plan, result, seed, op);
|
|
2148
2168
|
if (zone) {
|
|
@@ -2177,7 +2197,7 @@ function limitsOf(template, options) {
|
|
|
2177
2197
|
return { limits: tpl.limitsFn ? tpl.limitsFn(op) : tpl.limits, defaults: tpl.defaultsFn ? tpl.defaultsFn(op) : tpl.defaults };
|
|
2178
2198
|
}
|
|
2179
2199
|
function listTemplates(locale = "en") {
|
|
2180
|
-
return Object.values(TEMPLATES).map((t) => {
|
|
2200
|
+
return Object.values(registries().TEMPLATES).map((t) => {
|
|
2181
2201
|
const a = floorsOf(t, {});
|
|
2182
2202
|
return {
|
|
2183
2203
|
id: t.id,
|
|
@@ -2194,6 +2214,9 @@ function listTemplates(locale = "en") {
|
|
|
2194
2214
|
});
|
|
2195
2215
|
}
|
|
2196
2216
|
|
|
2217
|
+
// src/instance.ts
|
|
2218
|
+
import { applyPatches, removeIds } from "@adatechnology/game-contracts";
|
|
2219
|
+
|
|
2197
2220
|
// src/ground-items.ts
|
|
2198
2221
|
function registerGroundItems() {
|
|
2199
2222
|
const flat = { category: "ground_cover", w: 1, d: 1, h: 0, decor: true, mount: "ground", flat: true };
|
|
@@ -2414,6 +2437,109 @@ var pt_BR_default = {
|
|
|
2414
2437
|
}
|
|
2415
2438
|
};
|
|
2416
2439
|
|
|
2440
|
+
// src/instance.ts
|
|
2441
|
+
var version = "0.1.0";
|
|
2442
|
+
function editCatalog(catalog, patch, remove) {
|
|
2443
|
+
if (!patch && !remove) return;
|
|
2444
|
+
const entries = new Map(Object.entries(catalog).map(([key, definition]) => [key, { ...definition, id: key }]));
|
|
2445
|
+
applyPatches(entries, patch);
|
|
2446
|
+
removeIds(entries, remove);
|
|
2447
|
+
for (const key of Object.keys(catalog)) {
|
|
2448
|
+
const edited = entries.get(key);
|
|
2449
|
+
if (!edited) delete catalog[key];
|
|
2450
|
+
else if (patch && key in patch) {
|
|
2451
|
+
const hadId = "id" in catalog[key];
|
|
2452
|
+
const next = { ...edited };
|
|
2453
|
+
if (!hadId) delete next.id;
|
|
2454
|
+
catalog[key] = next;
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
function buildEngine(scope) {
|
|
2459
|
+
const scoped = (fn) => ((...args) => withRegistries(scope, () => fn(...args)));
|
|
2460
|
+
return {
|
|
2461
|
+
version,
|
|
2462
|
+
generate: scoped(generate),
|
|
2463
|
+
slots: scoped(slots),
|
|
2464
|
+
validate: scoped(validate),
|
|
2465
|
+
palette: scoped(palette),
|
|
2466
|
+
limitsOf: scoped(limitsOf),
|
|
2467
|
+
listTemplates: scoped(listTemplates),
|
|
2468
|
+
listStates: scoped(listStates),
|
|
2469
|
+
// content registration
|
|
2470
|
+
registerItem: scoped(registerItem),
|
|
2471
|
+
registerItems: scoped(registerItems),
|
|
2472
|
+
registerLibrary: scoped(registerLibrary),
|
|
2473
|
+
registerLibraryAlias: scoped(registerLibraryAlias),
|
|
2474
|
+
registerTemplate: scoped(registerTemplate),
|
|
2475
|
+
registerStyle: scoped(registerStyle),
|
|
2476
|
+
registerPaletteStyle: scoped(registerPaletteStyle),
|
|
2477
|
+
registerRoomColors: scoped(registerRoomColors),
|
|
2478
|
+
registerDecorProfile: scoped(registerDecorProfile),
|
|
2479
|
+
registerPass: scoped(registerPass),
|
|
2480
|
+
registerGroundOverlay: scoped(registerGroundOverlay),
|
|
2481
|
+
registerWallTop: scoped(registerWallTop),
|
|
2482
|
+
registerSeedKeys: scoped(registerSeedKeys),
|
|
2483
|
+
registerState: scoped(registerState),
|
|
2484
|
+
setStateDistribution: scoped(setStateDistribution),
|
|
2485
|
+
registerLocale: scoped(registerLocale),
|
|
2486
|
+
registerResultExtension: scoped(registerResultExtension),
|
|
2487
|
+
registerFindsProvider: scoped(registerFindsProvider),
|
|
2488
|
+
findsFor: scoped(findsFor),
|
|
2489
|
+
findsAnswer: scoped(findsAnswer),
|
|
2490
|
+
registerViewerLayer: scoped(registerViewerLayer),
|
|
2491
|
+
viewerLayers: scope.VIEWER_LAYERS,
|
|
2492
|
+
blocksWindow: scoped(blocksWindow),
|
|
2493
|
+
// zoning
|
|
2494
|
+
defineZone: scoped(defineZone),
|
|
2495
|
+
getZone: scoped(getZone),
|
|
2496
|
+
listZones: scoped(listZones),
|
|
2497
|
+
checkLot: scoped(checkLot),
|
|
2498
|
+
registerPermeableGround: scoped(registerPermeableGround),
|
|
2499
|
+
// kits and data
|
|
2500
|
+
slotKit,
|
|
2501
|
+
translate: scoped(translate),
|
|
2502
|
+
listLocales: scoped(listLocales),
|
|
2503
|
+
templates: scope.TEMPLATES,
|
|
2504
|
+
catalog: scope.CATALOG,
|
|
2505
|
+
libraries: scope.LIBRARIES,
|
|
2506
|
+
styles: scope.STYLES,
|
|
2507
|
+
paletteStyles: scope.PALETTE_STYLES,
|
|
2508
|
+
createRng,
|
|
2509
|
+
mulberry32,
|
|
2510
|
+
hashString,
|
|
2511
|
+
overlaps,
|
|
2512
|
+
windowZone,
|
|
2513
|
+
openingZones,
|
|
2514
|
+
color: { lstar, hex: hexString, hsl: intToHsl, HIGH_SATURATION, MIN_WALL_FLOOR_CONTRAST, MIN_FABRIC_FLOOR_CONTRAST },
|
|
2515
|
+
constants: { WALL_THICKNESS, DOOR_CLEARANCE, PLAYER_RADIUS, DOOR_EDGE_CLEARANCE, WINDOW_EDGE_CLEARANCE, OVERHEAD_TOP, CAR_CLEARANCE }
|
|
2516
|
+
};
|
|
2517
|
+
}
|
|
2518
|
+
function seedBase(scope) {
|
|
2519
|
+
withRegistries(scope, () => {
|
|
2520
|
+
registerGroundItems();
|
|
2521
|
+
registerPermeableGround("lawn", "dirt");
|
|
2522
|
+
registerLocale("en", en_default);
|
|
2523
|
+
registerLocale("pt-BR", pt_BR_default);
|
|
2524
|
+
});
|
|
2525
|
+
}
|
|
2526
|
+
function createFloorplan(options = {}) {
|
|
2527
|
+
const scope = createRegistries();
|
|
2528
|
+
seedBase(scope);
|
|
2529
|
+
const instance = buildEngine(scope);
|
|
2530
|
+
for (const pack of options.packs ?? []) (typeof pack === "function" ? pack : pack.register)(instance);
|
|
2531
|
+
editCatalog(scope.CATALOG, options.patch?.items, options.remove?.items);
|
|
2532
|
+
editCatalog(scope.TEMPLATES, options.patch?.templates, options.remove?.templates);
|
|
2533
|
+
return instance;
|
|
2534
|
+
}
|
|
2535
|
+
var defaultEngine;
|
|
2536
|
+
function defaultFloorplan() {
|
|
2537
|
+
if (defaultEngine) return defaultEngine;
|
|
2538
|
+
seedBase(getDefaultRegistries());
|
|
2539
|
+
defaultEngine = buildEngine(getDefaultRegistries());
|
|
2540
|
+
return defaultEngine;
|
|
2541
|
+
}
|
|
2542
|
+
|
|
2417
2543
|
// src/silhouettes/random.ts
|
|
2418
2544
|
function createSilhouetteRandom(seed) {
|
|
2419
2545
|
let state = seed;
|
|
@@ -2623,68 +2749,7 @@ function createDetachedHouse(p) {
|
|
|
2623
2749
|
}
|
|
2624
2750
|
|
|
2625
2751
|
// src/index.ts
|
|
2626
|
-
|
|
2627
|
-
registerPermeableGround("lawn", "dirt");
|
|
2628
|
-
registerLocale("en", en_default);
|
|
2629
|
-
registerLocale("pt-BR", pt_BR_default);
|
|
2630
|
-
var version = "0.1.0";
|
|
2631
|
-
var engine = {
|
|
2632
|
-
version,
|
|
2633
|
-
generate,
|
|
2634
|
-
slots,
|
|
2635
|
-
validate,
|
|
2636
|
-
palette,
|
|
2637
|
-
limitsOf,
|
|
2638
|
-
listTemplates,
|
|
2639
|
-
listStates,
|
|
2640
|
-
// content registration
|
|
2641
|
-
registerItem,
|
|
2642
|
-
registerItems,
|
|
2643
|
-
registerLibrary,
|
|
2644
|
-
registerLibraryAlias,
|
|
2645
|
-
registerTemplate,
|
|
2646
|
-
registerStyle,
|
|
2647
|
-
registerPaletteStyle,
|
|
2648
|
-
registerRoomColors,
|
|
2649
|
-
registerDecorProfile,
|
|
2650
|
-
registerPass,
|
|
2651
|
-
registerGroundOverlay,
|
|
2652
|
-
registerWallTop,
|
|
2653
|
-
registerSeedKeys,
|
|
2654
|
-
registerState,
|
|
2655
|
-
setStateDistribution,
|
|
2656
|
-
registerLocale,
|
|
2657
|
-
registerResultExtension,
|
|
2658
|
-
registerFindsProvider,
|
|
2659
|
-
findsFor,
|
|
2660
|
-
findsAnswer,
|
|
2661
|
-
registerViewerLayer,
|
|
2662
|
-
viewerLayers: VIEWER_LAYERS,
|
|
2663
|
-
blocksWindow,
|
|
2664
|
-
// zoning
|
|
2665
|
-
defineZone,
|
|
2666
|
-
getZone,
|
|
2667
|
-
listZones,
|
|
2668
|
-
checkLot,
|
|
2669
|
-
registerPermeableGround,
|
|
2670
|
-
// kits and data
|
|
2671
|
-
slotKit,
|
|
2672
|
-
translate,
|
|
2673
|
-
listLocales,
|
|
2674
|
-
templates: TEMPLATES,
|
|
2675
|
-
catalog: CATALOG,
|
|
2676
|
-
libraries: LIBRARIES,
|
|
2677
|
-
styles: STYLES,
|
|
2678
|
-
paletteStyles: PALETTE_STYLES,
|
|
2679
|
-
createRng,
|
|
2680
|
-
mulberry32,
|
|
2681
|
-
hashString,
|
|
2682
|
-
overlaps,
|
|
2683
|
-
windowZone,
|
|
2684
|
-
openingZones,
|
|
2685
|
-
color: { lstar, hex: hexString, hsl: intToHsl, HIGH_SATURATION, MIN_WALL_FLOOR_CONTRAST, MIN_FABRIC_FLOOR_CONTRAST },
|
|
2686
|
-
constants: { WALL_THICKNESS, DOOR_CLEARANCE, PLAYER_RADIUS, DOOR_EDGE_CLEARANCE, WINDOW_EDGE_CLEARANCE, OVERHEAD_TOP, CAR_CLEARANCE }
|
|
2687
|
-
};
|
|
2752
|
+
var engine = defaultFloorplan();
|
|
2688
2753
|
export {
|
|
2689
2754
|
blocksWindow,
|
|
2690
2755
|
boxRadius,
|
|
@@ -2695,11 +2760,13 @@ export {
|
|
|
2695
2760
|
createCompanyHouse,
|
|
2696
2761
|
createDetachedHouse,
|
|
2697
2762
|
createFarmhouse,
|
|
2763
|
+
createFloorplan,
|
|
2698
2764
|
createRng,
|
|
2699
2765
|
createSilhouetteRandom,
|
|
2700
2766
|
createSlabHouse,
|
|
2701
2767
|
createStiltHouse,
|
|
2702
2768
|
createTwoStoreyHouse,
|
|
2769
|
+
defaultFloorplan,
|
|
2703
2770
|
defineZone,
|
|
2704
2771
|
engine,
|
|
2705
2772
|
findsAnswer,
|