@adatechnology/game-floorplan-three 0.10.0 → 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.
@@ -1,3 +1,7 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+
1
5
  // src/test-area/module.ts
2
6
  import { DEFERRED_PRIORITY, DEFERRED_QUEUE_ID as DEFERRED_QUEUE_ID2 } from "@adatechnology/game-contracts";
3
7
  import { isLightBudget } from "@adatechnology/game-render-three";
@@ -108,6 +112,20 @@ function installKernelGeometry(K, shared) {
108
112
  const WITH_MAP = { roughcast: 1, block: 1 };
109
113
  class Accumulator {
110
114
  constructor() {
115
+ __publicField(this, "cv");
116
+ __publicField(this, "ci");
117
+ __publicField(this, "p");
118
+ __publicField(this, "n");
119
+ __publicField(this, "c");
120
+ __publicField(this, "u");
121
+ __publicField(this, "i");
122
+ __publicField(this, "nv");
123
+ __publicField(this, "ni");
124
+ __publicField(this, "lim");
125
+ __publicField(this, "cur");
126
+ __publicField(this, "piece0");
127
+ __publicField(this, "mat", "");
128
+ __publicField(this, "group", "");
111
129
  this.cv = 2048;
112
130
  this.ci = 3072;
113
131
  this.p = new Float32Array(this.cv * 3);
@@ -170,7 +188,8 @@ function installKernelGeometry(K, shared) {
170
188
  g.position.copy(u.pose0.p);
171
189
  g.quaternion.copy(u.pose0.q);
172
190
  g.scale.copy(u.pose0.s);
173
- const e = new THREE.Vector3(...a.axis || [0, 1, 0]);
191
+ const [ax, ay, az] = a.axis || [0, 1, 0];
192
+ const e = new THREE.Vector3(ax, ay, az);
174
193
  if (a.type === "swing" || a.type === "toggle") g.rotateOnAxis(e, (a.angle || 0) * t);
175
194
  else if (a.type === "slide") g.translateOnAxis(e, (a.dist || 0) * t);
176
195
  else if (a.type === "scale") {
@@ -265,7 +284,7 @@ function installKernelGeometry(K, shared) {
265
284
  }
266
285
  if (uvr) {
267
286
  let gu = G.u[k * 2], gv = G.u[k * 2 + 1];
268
- for (let r = uvr.rot | 0; r > 0; r--) {
287
+ for (let r = (uvr.rot ?? 0) | 0; r > 0; r--) {
269
288
  const t = gu;
270
289
  gu = gv;
271
290
  gv = 1 - t;
@@ -363,14 +382,13 @@ function installKernelGeometry(K, shared) {
363
382
  A.nv += n;
364
383
  }
365
384
  let bxImpl = bxBase;
366
- function bx(...a) {
367
- return bxImpl(...a);
368
- }
369
- K.getBx = () => bxImpl;
370
- K.setBx = (f) => {
385
+ const bx = (...a) => bxImpl(...a);
386
+ const getBx = () => bxImpl;
387
+ const setBx = (f) => {
371
388
  bxImpl = f;
372
389
  };
373
- Object.assign(K, { GEO, UV_SCALE, WITH_MAP, Accumulator, cursor, PARTS, MIRRORS, part, applyPart, _Y, _qa, _qb, pieceRecord, structurePiece, accFor, _q, _e, _col, rgbOf, put, boxC, bx, cylBase, polyFace });
390
+ const defined = { GEO, UV_SCALE, WITH_MAP, Accumulator, cursor, PARTS, MIRRORS, part, applyPart, _Y, _qa, _qb, pieceRecord, structurePiece, accFor, _q, _e, _col, rgbOf, put, boxC, bx, getBx, setBx, cylBase, polyFace };
391
+ Object.assign(K, defined);
374
392
  }
375
393
 
376
394
  // src/kernel/noise.ts
@@ -388,17 +406,20 @@ function installKernelNoise(K, _shared) {
388
406
  const n = 0.5 * vnoise(x / 5.5, z / 5.5) + 0.32 * vnoise(x / 1.9 + 31, z / 1.9) + 0.18 * vnoise(x / 0.8 + 7, z / 0.8), m = vnoise(x / 9 + 100, z / 9 + 50) - 0.5, f = 0.76 + 0.5 * n;
389
407
  return type === "dirt" ? [f * (1 + 0.14 * m), f * (1 + 0.03 * m), f * (1 - 0.18 * m)] : [f * (1 + 0.1 * m), f * (1 + 0.05 * m), f * (1 - 0.1 * m)];
390
408
  }
391
- Object.assign(K, { _h2, vnoise, macroGround });
409
+ const defined = { _h2, vnoise, macroGround };
410
+ Object.assign(K, defined);
392
411
  }
393
412
 
394
413
  // src/materials/textures.ts
395
414
  function installMaterialsTextures(K, _shared) {
396
415
  const { DOC, THREE, cfg } = K;
397
416
  function texture(n, f, rep = true, rx = 1, ry = 1) {
417
+ if (!DOC) throw new Error("game-floorplan-three: the procedural textures need a document (options.document)");
398
418
  const c = DOC.createElement("canvas");
399
419
  c.width = n;
400
420
  c.height = n;
401
421
  const g = c.getContext("2d");
422
+ if (!g) throw new Error("game-floorplan-three: no 2d canvas context");
402
423
  f(g, n);
403
424
  const t = new THREE.CanvasTexture(c);
404
425
  t.colorSpace = THREE.SRGBColorSpace;
@@ -517,10 +538,16 @@ function installMaterialsTextures(K, _shared) {
517
538
  const TEX = {};
518
539
  for (const k of Object.keys(TEXGEN)) TEX[k] = cfg.textures && cfg.textures[k] || TEXGEN[k]();
519
540
  const ATLAS = {};
520
- Object.assign(K, { texture, rngTexture, TEXGEN, TEX, ATLAS });
541
+ const defined = { texture, rngTexture, TEXGEN, TEX, ATLAS };
542
+ Object.assign(K, defined);
521
543
  }
522
544
 
523
545
  // src/materials/materials.ts
546
+ function context2d(c) {
547
+ const g = c.getContext("2d");
548
+ if (!g) throw new Error("game-floorplan-three: no 2d canvas context");
549
+ return g;
550
+ }
524
551
  function installMaterialsMaterials(K, _shared) {
525
552
  const { THREE, cfg, ATLAS, TEX, rngTexture } = K;
526
553
  function createMaterials(props) {
@@ -532,7 +559,7 @@ function installMaterialsMaterials(K, _shared) {
532
559
  return t;
533
560
  };
534
561
  if (!(cfg.atlas && cfg.atlas.floorKind)) {
535
- const pc = props.atlas("floor").canvas, g = pc.getContext("2d");
562
+ const pc = props.atlas("floor").canvas, g = context2d(pc);
536
563
  for (const c of [0, 1]) {
537
564
  g.save();
538
565
  g.globalCompositeOperation = "screen";
@@ -547,7 +574,7 @@ function installMaterialsMaterials(K, _shared) {
547
574
  g.restore();
548
575
  }
549
576
  if (!(cfg.atlas && cfg.atlas.floorKind)) {
550
- const pc = props.atlas("floor").canvas, g = pc.getContext("2d");
577
+ const pc = props.atlas("floor").canvas, g = context2d(pc);
551
578
  g.save();
552
579
  g.fillStyle = "rgba(128,92,62,0.52)";
553
580
  g.fillRect(256, 256, 256, 256);
@@ -644,7 +671,8 @@ function installMaterialsMaterials(K, _shared) {
644
671
  }
645
672
  const ORDER = { glass: 3, water: 2, screen: 3, building: 4 };
646
673
  const NO_SHADOW = /* @__PURE__ */ new Set(["dirt", "glass", "water", "screen", "building", "picture", "floor", "emissive"]);
647
- Object.assign(K, { createMaterials, antiTile, dirtMaterial, CLOTHES_UNIFORMS, clothesMaterial, ORDER, NO_SHADOW });
674
+ const defined = { createMaterials, antiTile, dirtMaterial, CLOTHES_UNIFORMS, clothesMaterial, ORDER, NO_SHADOW };
675
+ Object.assign(K, defined);
648
676
  }
649
677
 
650
678
  // src/kernel/close-scene.ts
@@ -655,15 +683,18 @@ function installKernelCloseScene(K, shared) {
655
683
  const assembleVegetation = (...a) => K.assembleVegetation(...a);
656
684
  function markMesh(m, A) {
657
685
  const L = A.lim, fx = [];
686
+ const pieces = shared.ctx.pieces;
658
687
  for (let k = 0; k < L.length; k++) {
659
- if (!L[k].pc) continue;
660
- const v1 = k + 1 < L.length ? L[k + 1].v : A.nv, i1 = k + 1 < L.length ? L[k + 1].i : A.ni;
661
- if (v1 > L[k].v) fx.push({ id: L[k].pc.id, v0: L[k].v, v1, i0: L[k].i, i1 });
688
+ const lim = L[k], pc = lim.pc;
689
+ if (!pc) continue;
690
+ const next = L[k + 1];
691
+ const v1 = next ? next.v : A.nv, i1 = next ? next.i : A.ni;
692
+ if (v1 > lim.v) fx.push({ id: pc.id, v0: lim.v, v1, i0: lim.i, i1 });
662
693
  }
663
694
  if (!fx.length) return;
664
695
  const u = m.userData, ids = [...new Set(fx.map((f) => f.id))], weight = {};
665
696
  for (const f of fx) {
666
- const mt = shared.ctx.pieces.get(f.id).mat;
697
+ const mt = pieces.get(f.id).mat;
667
698
  weight[mt] = (weight[mt] || 0) + f.v1 - f.v0;
668
699
  }
669
700
  u.ranges = fx;
@@ -671,7 +702,7 @@ function installKernelCloseScene(K, shared) {
671
702
  u.destructionMaterial = Object.keys(weight).sort((a, b) => weight[b] - weight[a])[0];
672
703
  if (ids.length === 1) {
673
704
  u.destructionPart = ids[0];
674
- const pc = shared.ctx.pieces.get(ids[0]);
705
+ const pc = pieces.get(ids[0]);
675
706
  if (pc.role) u.structuralRole = pc.role;
676
707
  }
677
708
  }
@@ -722,7 +753,8 @@ function installKernelCloseScene(K, shared) {
722
753
  assembleVegetation(groups);
723
754
  return groups;
724
755
  }
725
- Object.assign(K, { markMesh, closeScene });
756
+ const defined = { markMesh, closeScene };
757
+ Object.assign(K, defined);
726
758
  }
727
759
 
728
760
  // src/house/helpers.ts
@@ -760,8 +792,14 @@ function installHouseHelpers(K, shared) {
760
792
  for (const h of holes) L = L.flatMap((r) => subRect(r, h));
761
793
  return L;
762
794
  }
763
- const wallColor = (c) => c && c.color && colorOf(c.color.wall) != null ? colorOf(c.color.wall) : 14999768;
764
- const floorColor = (c) => c && c.color && colorOf(c.color.floor) != null ? colorOf(c.color.floor) : 11577496;
795
+ const wallColor = (c) => {
796
+ const k = c && c.color ? colorOf(c.color.wall) : null;
797
+ return k != null ? k : 14999768;
798
+ };
799
+ const floorColor = (c) => {
800
+ const k = c && c.color ? colorOf(c.color.floor) : null;
801
+ return k != null ? k : 11577496;
802
+ };
765
803
  function stairFootprint(m) {
766
804
  const c = Math.cos(m.ry), s = Math.sin(m.ry), pts = [[-m.w / 2, -m.d / 2], [m.w / 2, -m.d / 2], [m.w / 2, m.d / 2], [-m.w / 2, m.d / 2]].map(([a, b]) => [m.x + a * c + b * s, m.z - a * s + b * c]);
767
805
  return [Math.min(...pts.map((p) => p[0])), Math.min(...pts.map((p) => p[1])), Math.max(...pts.map((p) => p[0])), Math.max(...pts.map((p) => p[1]))];
@@ -772,13 +810,14 @@ function installHouseHelpers(K, shared) {
772
810
  const pitch = A[f + 1].y0 - A[f].y0;
773
811
  return h > pitch && h - pitch <= 0.45 ? pitch : h;
774
812
  }
775
- Object.assign(K, { OPEN_ROOM_TYPES: OPEN_ROOM_TYPES2, NO_CEILING, OPEN_AREA, EPS, Y0, colorOf, rectsOf: rectsOf2, roomAt, subRect, subRects, wallColor, floorColor, stairFootprint, effectiveHeight });
813
+ const defined = { OPEN_ROOM_TYPES: OPEN_ROOM_TYPES2, NO_CEILING, OPEN_AREA, EPS, Y0, colorOf, rectsOf: rectsOf2, roomAt, subRect, subRects, wallColor, floorColor, stairFootprint, effectiveHeight };
814
+ Object.assign(K, defined);
776
815
  }
777
816
 
778
817
  // src/house/walls.ts
779
818
  function installHouseWalls(K, shared) {
780
819
  const { EPS, Y0, boxC, bx, cursor, effectiveHeight, pieceRecord, structurePiece, wallColor } = K;
781
- const sh = (color, factor) => K.sh(color, factor);
820
+ const sh = (...a) => K.sh(...a);
782
821
  function wallBox(alongU, L, a, b, ya, yb, th, cL, cH, mL, mH) {
783
822
  if (yb - ya < 1e-4 || b - a < 1e-4) return;
784
823
  if (alongU) {
@@ -824,7 +863,7 @@ function installHouseWalls(K, shared) {
824
863
  const corners = /* @__PURE__ */ new Map();
825
864
  const looks = /* @__PURE__ */ new Map();
826
865
  for (const w of R.walls) {
827
- const f = w.floor;
866
+ const f = w.floor, colliders = shared.ctx.colliders;
828
867
  cursor.group = "f" + f;
829
868
  cursor.pc = pieceOf(w);
830
869
  const y0 = Y0(f), pitch = f + 1 < nA ? Y0(f + 1) - y0 : Infinity, th = w.thickness || 0.15, alongU = w.axis === "u";
@@ -836,7 +875,7 @@ function installHouseWalls(K, shared) {
836
875
  const face = sideL.exterior ? sideL : sideH;
837
876
  looks.set(w.id, { mat: face.mat, color: face.color, top: y0 + hh });
838
877
  }
839
- shared.ctx.colliders.push({ type: "wall", piece: w.id, f, x0: alongU ? s0 : L - th / 2, z0: alongU ? L - th / 2 : s0, x1: alongU ? s1 : L + th / 2, z1: alongU ? L + th / 2 : s1 });
878
+ colliders.push({ type: "wall", piece: w.id, f, x0: alongU ? s0 : L - th / 2, z0: alongU ? L - th / 2 : s0, x1: alongU ? s1 : L + th / 2, z1: alongU ? L + th / 2 : s1 });
840
879
  if (w.type === "railing") {
841
880
  const c0 = shared.ctx.colors.metal != null ? shared.ctx.colors.metal : 9080466;
842
881
  const sx = alongU ? 1 : 0, sz = alongU ? 0 : 1, len = s1 - s0, n = Math.max(1, Math.round(len / 1.4));
@@ -902,7 +941,8 @@ function installHouseWalls(K, shared) {
902
941
  }
903
942
  cursor.pc = null;
904
943
  }
905
- Object.assign(K, { wallBox, sideOf, pieceOf, nearestWall, walls, wallPillars });
944
+ const defined = { wallBox, sideOf, pieceOf, nearestWall, walls, wallPillars };
945
+ Object.assign(K, defined);
906
946
  }
907
947
 
908
948
  // src/house/doors.ts
@@ -921,7 +961,7 @@ function installHouseDoors(K, shared) {
921
961
  }
922
962
  shared.doorState = /* @__PURE__ */ new Map();
923
963
  function doors() {
924
- shared.ctx.leaves = [];
964
+ const leaves = shared.ctx.leaves = [], doorState = shared.doorState, colliders = shared.ctx.colliders;
925
965
  const R = shared.ctx.r, cut = shared.ctx.cut, C = shared.ctx.colors, wood = C.wood != null ? C.wood : 8016948, frame = sh(wood, 0.55);
926
966
  for (const p of R.doors) {
927
967
  const f = p.floor;
@@ -952,21 +992,21 @@ function installHouseDoors(K, shared) {
952
992
  }
953
993
  const leaf = (u0, u1, y_0, y_1, tt, color, mat = "wood") => alongU ? bx(mat, u0, y0 + y_0, L - tt / 2, u1, y0 + y_1, L + tt / 2, color) : bx(mat, L - tt / 2, y0 + y_0, u0, L + tt / 2, y0 + y_1, u1, color);
954
994
  const extC = wood;
955
- const open0 = p.blocked ? false : shared.doorState.has(p.id) ? shared.doorState.get(p.id) : !!p.open;
956
- shared.doorState.set(p.id, open0);
995
+ const open0 = p.blocked ? false : doorState.has(p.id) ? doorState.get(p.id) === true : !!p.open;
996
+ doorState.set(p.id, open0);
957
997
  const dc = alongU ? [p.at, L] : [L, p.at];
958
- const fo = { id: p.id, floor: f, type: p.model === "steel" ? "steel" : "swing", open: open0, t: open0 ? 1 : 0, blockedFlag: !!p.blocked, locked: R.state === "fortified" && !!p.exterior, handleNames: [], hT: 0, cx: dc[0], cz: dc[1], visH, groups: [], col: null };
998
+ const fo = { id: p.id, floor: f, type: p.model === "steel" ? "steel" : "swing", open: open0, t: open0 ? 1 : 0, blockedFlag: !!p.blocked, locked: R.state === "fortified" && !!p.exterior, handleNames: [], hT: 0, cx: dc[0], cz: dc[1], visH, groups: [], gs: [], col: null };
959
999
  const colR = { type: "door", f, x0: alongU ? a : L - th / 2, z0: alongU ? L - th / 2 : a, x1: alongU ? b : L + th / 2, z1: alongU ? L + th / 2 : b, off: open0 };
960
- shared.ctx.colliders.push(colR);
1000
+ colliders.push(colR);
961
1001
  fo.col = colR;
962
1002
  const leafBox = (hu, d0, d1, y_0, y_1, tt, color, mat) => alongU ? bx(mat, d0, y_0, -tt / 2, d1, y_1, tt / 2, color) : bx(mat, -tt / 2, y_0, d0, tt / 2, y_1, d1, color);
963
- const newGroup = (k, hu, topY) => {
1003
+ const newGroup2 = (k, hu, topY) => {
964
1004
  cursor.group = "dyn:" + p.id + ":" + k;
965
1005
  fo.groups.push({ name: cursor.group, pos: alongU ? [hu, topY != null ? y0 + topY : y0, L] : [L, topY != null ? y0 + topY : y0, hu] });
966
1006
  };
967
1007
  if (p.model === "steel") {
968
- const light = [14276044, 13223615, 14999766], pal = ((R.seed | 0) + p.id.length * 7) % 4, color = pal === 3 ? wood : light[pal], mid = (a + b) / 2;
969
- newGroup(0, mid, visH);
1008
+ const light = [14276044, 13223615, 14999766], pal = ((Number(R.seed) | 0) + p.id.length * 7) % 4, color = pal === 3 ? wood : light[pal], mid = (a + b) / 2;
1009
+ newGroup2(0, mid, visH);
970
1010
  const la = a + jw - mid, lb = b - jw - mid, nSec = Math.max(4, Math.round(visH / 0.5)), hs = visH / nSec, grv = sh(color, 0.55);
971
1011
  leafBox(0, la, lb, -visH, 0, 0.05, color, "metal");
972
1012
  for (let k = 1; k < nSec; k++) leafBox(0, la, lb, -k * hs - 0.012, -k * hs + 0.012, 0.07, grv, "metal");
@@ -981,7 +1021,7 @@ function installHouseDoors(K, shared) {
981
1021
  for (let k = 0; k < nf; k++) {
982
1022
  const u0 = nf === 2 ? k ? (aa + bb) / 2 : aa : aa, u1 = nf === 2 ? k ? bb : (aa + bb) / 2 : bb, color = p.exterior ? extC : wood;
983
1023
  const hingeAt = nf === 2 ? k ? u1 : u0 : p.hinge === "end" ? u1 : u0, dir = hingeAt === u0 ? 1 : -1, len = u1 - u0;
984
- newGroup(k, hingeAt);
1024
+ newGroup2(k, hingeAt);
985
1025
  const d0 = dir > 0 ? 5e-3 : -len + 5e-3, d1 = dir > 0 ? len - 5e-3 : -5e-3;
986
1026
  leafBox(hingeAt, d0, d1, 0, visH, 0.04, color, PMAT);
987
1027
  {
@@ -1017,7 +1057,7 @@ function installHouseDoors(K, shared) {
1017
1057
  fo.rot = Math.atan2(n[0] * A[1] - n[1] * A[0], A[0] * n[0] + A[1] * n[1]);
1018
1058
  }
1019
1059
  }
1020
- shared.ctx.leaves.push(fo);
1060
+ leaves.push(fo);
1021
1061
  cursor.group = "f" + f;
1022
1062
  if (p.blocked) {
1023
1063
  part("window_boards", [0, 0, 0], () => {
@@ -1045,11 +1085,12 @@ function installHouseDoors(K, shared) {
1045
1085
  }
1046
1086
  }
1047
1087
  }, { id: "boards:" + p.id }, "f" + f);
1048
- shared.ctx.colliders.push({ type: "board", f, x0: alongU ? a : L - th / 2, z0: alongU ? L - th / 2 : a, x1: alongU ? b : L + th / 2, z1: alongU ? L + th / 2 : b });
1088
+ colliders.push({ type: "board", f, x0: alongU ? a : L - th / 2, z0: alongU ? L - th / 2 : a, x1: alongU ? b : L + th / 2, z1: alongU ? L + th / 2 : b });
1049
1089
  }
1050
1090
  }
1051
1091
  }
1052
- Object.assign(K, { doorLineSides, doors });
1092
+ const defined = { doorLineSides, doors };
1093
+ Object.assign(K, defined);
1053
1094
  }
1054
1095
 
1055
1096
  // src/house/windows.ts
@@ -1109,7 +1150,8 @@ function installHouseWindows(K, shared) {
1109
1150
  }
1110
1151
  }
1111
1152
  }
1112
- Object.assign(K, { FRAME_COLORS, SILL_COLORS, windows });
1153
+ const defined = { FRAME_COLORS, SILL_COLORS, windows };
1154
+ Object.assign(K, defined);
1113
1155
  }
1114
1156
 
1115
1157
  // src/house/floors.ts
@@ -1119,7 +1161,7 @@ function installHouseFloors(K, shared) {
1119
1161
  if (shared.ctx._flights && shared.ctx._flights.r === shared.ctx.r) return shared.ctx._flights.l;
1120
1162
  const R = shared.ctx.r, mp = /* @__PURE__ */ new Map();
1121
1163
  for (const m of R.items) {
1122
- if (m.type !== "stairs" || !m.link) continue;
1164
+ if (m.type !== "stairs" || !m.link || typeof m.link !== "object") continue;
1123
1165
  const k = [m.link.from, m.link.to, m.x.toFixed(2), m.z.toFixed(2), (m.ry || 0).toFixed(2)].join("|");
1124
1166
  if (!mp.has(k)) mp.set(k, { m, from: m.link.from, to: m.link.to, rect: stairFootprint(m) });
1125
1167
  }
@@ -1138,7 +1180,7 @@ function installHouseFloors(K, shared) {
1138
1180
  }
1139
1181
  const panelRects = (p) => p.footprint && p.footprint.length ? p.footprint : [p.aabb];
1140
1182
  function tilesOf(parent, rc) {
1141
- const ps = parent && shared.ctx.panelsOf && shared.ctx.panelsOf.get(parent);
1183
+ const ps = parent ? shared.ctx.panelsOf && shared.ctx.panelsOf.get(parent) : void 0;
1142
1184
  if (!ps) return [[parent ? structurePiece(parent) : null, rc]];
1143
1185
  const out = [], taken = [];
1144
1186
  for (const p of ps) for (const q of panelRects(p)) {
@@ -1202,13 +1244,12 @@ function installHouseStairs(K, shared) {
1202
1244
  const { rectsOf: rectsOf2, Y0, boxC, bx, cursor, flights, stairFootprint, structurePiece } = K;
1203
1245
  const sh = (...a) => K.sh(...a);
1204
1246
  function buildStairs() {
1205
- const R = shared.ctx.r;
1206
- shared.ctx.stairs = [];
1247
+ const R = shared.ctx.r, stairs = shared.ctx.stairs = [];
1207
1248
  for (const vo of flights()) {
1208
1249
  const m = vo.m, f = vo.from, Dr = m.d - (vo.LP || 0);
1209
1250
  cursor.group = "f" + f;
1210
1251
  cursor.pc = structurePiece("stairs_" + vo.from + "_" + vo.to);
1211
- const y0 = Y0(f), H = Y0(m.link.to) - y0, n = Math.max(8, Math.round(H / 0.18)), c = Math.cos(m.ry), s = Math.sin(m.ry);
1252
+ const y0 = Y0(f), H = Y0(vo.to) - y0, n = Math.max(8, Math.round(H / 0.18)), c = Math.cos(m.ry), s = Math.sin(m.ry);
1212
1253
  const wood = shared.ctx.colors.wood != null ? shared.ctx.colors.wood : 9071176, under = sh(wood, 0.7);
1213
1254
  const P = (lx, lz) => [m.x + lx * c + lz * s, m.z - lx * s + lz * c];
1214
1255
  const boxL = (mat, lx, y, lz, w, h, d, color, rx = 0) => {
@@ -1231,7 +1272,7 @@ function installHouseStairs(K, shared) {
1231
1272
  }
1232
1273
  }
1233
1274
  cursor.pc = null;
1234
- shared.ctx.stairs.push({ m, f, to: vo.to, y0, H, rect: stairFootprint(m), landingPoint: (vo.LP || 0) / m.d });
1275
+ stairs.push({ m, f, to: vo.to, y0, H, rect: stairFootprint(m), landingPoint: (vo.LP || 0) / m.d });
1235
1276
  }
1236
1277
  }
1237
1278
  function elevator() {
@@ -1248,7 +1289,8 @@ function installHouseStairs(K, shared) {
1248
1289
  }
1249
1290
  }
1250
1291
  }
1251
- Object.assign(K, { buildStairs, elevator });
1292
+ const defined = { buildStairs, elevator };
1293
+ Object.assign(K, defined);
1252
1294
  }
1253
1295
 
1254
1296
  // src/lights/fixtures.ts
@@ -1288,14 +1330,15 @@ function installLightsFixtures(K, shared) {
1288
1330
  c: (mat, x, y, z, r, h, color, seg) => api.cylinder(M, mat, x, y0 + y, z, r, h, color, 0, 0, seg),
1289
1331
  e: (mat, x, y, z, r, h, color) => api.cylinder(M, mat, x, y0 + y - h / 2, z, r, h, color, 0, 0, "sphere"),
1290
1332
  t(mat, p, q, r, color, seg) {
1333
+ const tc = color ?? NaN;
1291
1334
  const dx = q[0] - p[0], dy = q[1] - p[1], dz = q[2] - p[2], L = Math.hypot(dx, dy, dz);
1292
1335
  if (L < 1e-5) return;
1293
1336
  const nx = dx / L, ny = dy / L, nz = dz / L;
1294
1337
  if (Math.abs(nx) < 1e-4 && Math.abs(nz) < 1e-4) {
1295
- api.cylinder(M, mat, p[0], y0 + Math.min(p[1], q[1]), p[2], r, L, color, 0, 0, seg);
1338
+ api.cylinder(M, mat, p[0], y0 + Math.min(p[1], q[1]), p[2], r, L, tc, 0, 0, seg);
1296
1339
  return;
1297
1340
  }
1298
- api.cylinder(M, mat, (p[0] + q[0]) / 2, y0 + (p[1] + q[1]) / 2, (p[2] + q[2]) / 2, r, L, color, Math.atan2(nz, ny), -Math.asin(nx), seg);
1341
+ api.cylinder(M, mat, (p[0] + q[0]) / 2, y0 + (p[1] + q[1]) / 2, (p[2] + q[2]) / 2, r, L, tc, Math.atan2(nz, ny), -Math.asin(nx), seg);
1299
1342
  },
1300
1343
  polyFace: (mat, pts, color, hint) => polyFace(mat, pts.map((p) => W(p[0], p[1], p[2])), color, hint && [hint[0] * c + hint[2] * s, hint[1], -hint[0] * s + hint[2] * c]),
1301
1344
  part(type, lx, ly, lz, fn, meta) {
@@ -1474,7 +1517,8 @@ function installLightsFixtures(K, shared) {
1474
1517
  K2.part("light_switch", x, 0, 0.011, () => K2.b("plain", x, -0.018, 0.0125, two ? 0.03 : 0.036, 0.034, 8e-3, 16513782, 0, -0.12), { id: "sw_" + M.seed + "_" + i, room: M.room, target: M.target || M.room, opens: { type: "toggle", axis: [1, 0, 0], angle: 0.24 }, on: !!M.on, t0: M.on ? 1 : 0 });
1475
1518
  }
1476
1519
  }
1477
- Object.assign(K, { hashString, rngString, SEED, STYLE, kit2, arcPoints, TEMP_WARM, TEMP_NEUTRAL, TEMP_COOL, colorTemperature, lightStyle, ceilingLamp, tableLamp, floorLamp, sconce, outdoorLamp, lightSwitch });
1520
+ const defined = { hashString, rngString, SEED, STYLE, kit2, arcPoints, TEMP_WARM, TEMP_NEUTRAL, TEMP_COOL, colorTemperature, lightStyle, ceilingLamp, tableLamp, floorLamp, sconce, outdoorLamp, lightSwitch };
1521
+ Object.assign(K, defined);
1478
1522
  }
1479
1523
 
1480
1524
  // src/lights/decor.ts
@@ -1541,7 +1585,8 @@ function installLightsDecor(K, shared) {
1541
1585
  void sd;
1542
1586
  }
1543
1587
  }
1544
- Object.assign(K, { decorLights });
1588
+ const defined = { decorLights };
1589
+ Object.assign(K, defined);
1545
1590
  }
1546
1591
 
1547
1592
  // src/lot/terrain.ts
@@ -1594,7 +1639,8 @@ function installLotTerrain(K, shared) {
1594
1639
  if (x < b) out.push([x, b]);
1595
1640
  return out.filter((q) => q[1] - q[0] > 0.3);
1596
1641
  }
1597
- Object.assign(K, { terrain, freeSpans });
1642
+ const defined = { terrain, freeSpans };
1643
+ Object.assign(K, defined);
1598
1644
  }
1599
1645
 
1600
1646
  // src/lot/perimeter.ts
@@ -1614,7 +1660,7 @@ function installLotPerimeter(K, shared) {
1614
1660
  for (const s of lt.perimeter) {
1615
1661
  const alongU = Math.abs(s.v1 - s.v0) < EPS, L = alongU ? s.v0 : s.u0, a = Math.min(alongU ? s.u0 : s.v0, alongU ? s.u1 : s.v1), b = Math.max(alongU ? s.u0 : s.v0, alongU ? s.u1 : s.v1);
1616
1662
  cursor.pc = pieceRecord("lot_wall:" + s.id, s.type === "wall" ? "brick" : s.type === "fence" ? "wood_soft" : "steel", null, { tags: ["wall"] });
1617
- const th = s.thickness || 0.15, h = s.height, color = colorOf(s.color) != null ? colorOf(s.color) : C.wall || 12104874, len = b - a;
1663
+ const th = s.thickness || 0.15, h = s.height, color = colorOf(s.color) ?? (C.wall || 12104874), len = b - a;
1618
1664
  const B = (mat, u0, y0, u1, y1, t, c, off = 0) => alongU ? bx(mat, u0, y0, L + off - t / 2, u1, y1, L + off + t / 2, c) : bx(mat, L + off - t / 2, y0, u0, L + off + t / 2, y1, u1, c);
1619
1665
  const col = { type: "lot_wall", f: -1, x0: alongU ? a : L - th / 2, z0: alongU ? L - th / 2 : a, x1: alongU ? b : L + th / 2, z1: alongU ? L + th / 2 : b };
1620
1666
  shared.ctx.colliders.push(col);
@@ -1688,7 +1734,8 @@ function installLotPerimeter(K, shared) {
1688
1734
  }
1689
1735
  }
1690
1736
  }
1691
- Object.assign(K, { perimeter, paths });
1737
+ const defined = { perimeter, paths };
1738
+ Object.assign(K, defined);
1692
1739
  }
1693
1740
 
1694
1741
  // src/lot/gates.ts
@@ -1704,7 +1751,7 @@ function installLotGates(K, shared) {
1704
1751
  cursor.group = "lot";
1705
1752
  const structure = R.style, auto = structure !== "budget", wall = colorOf("wall") || 12104874, cu = (lt.rect[0] + lt.rect[2]) / 2, cz = (lt.rect[1] + lt.rect[3]) / 2;
1706
1753
  for (const g of lt.gates) {
1707
- const gc = colorOf(g.color) != null ? colorOf(g.color) : C.gate != null ? C.gate : 2763310, a = g.u - g.width / 2, b = g.u + g.width / 2, v = g.v, h = g.height, t = 0.05, ped = g.model === "pedestrian", tilt = g.model === "tilting";
1754
+ const gc = colorOf(g.color) ?? (C.gate != null ? C.gate : 2763310), a = g.u - g.width / 2, b = g.u + g.width / 2, v = g.v, h = g.height, t = 0.05, ped = g.model === "pedestrian", tilt = g.model === "tilting";
1708
1755
  const sd = cz - v >= 0 ? 1 : -1;
1709
1756
  const pil = (x0, x1, high) => {
1710
1757
  bx("plaster", x0, 0, v - 0.13, x1, high, v + 0.13, wall);
@@ -1776,7 +1823,8 @@ function installLotGates(K, shared) {
1776
1823
  if (!g.open || ped) shared.ctx.colliders.push({ type: "gate", f: -1, x0: a, z0: v - 0.1, x1: b, z1: v + 0.1 });
1777
1824
  }
1778
1825
  }
1779
- Object.assign(K, { slideDirection, gates });
1826
+ const defined = { slideDirection, gates };
1827
+ Object.assign(K, defined);
1780
1828
  }
1781
1829
 
1782
1830
  // src/roof/roofs.ts
@@ -1790,13 +1838,13 @@ function installRoofRoofs(K, shared) {
1790
1838
  function roofs() {
1791
1839
  const R = shared.ctx.r, F = R.facade, C = shared.ctx.colors, nA = R.floors.length, type = F.roof;
1792
1840
  cursor.group = "roof";
1793
- shared.ctx.roofRects = [];
1794
- shared.ctx.gutter = gutterConfig();
1795
- shared.ctx.gutter.ncond = 0;
1796
- shared.ctx.gutter.nbuz = 0;
1797
- shared.ctx.gutter.bz = /* @__PURE__ */ new Set();
1841
+ const roofRects = shared.ctx.roofRects = [];
1842
+ const G = shared.ctx.gutter = gutterConfig();
1843
+ G.ncond = 0;
1844
+ G.nbuz = 0;
1845
+ G.bz = /* @__PURE__ */ new Set();
1798
1846
  shared.ctx.gutterInfo = { gutters: [], downpipes: [], drains: [] };
1799
- const roofColor = C.roof != null ? C.roof : 11031610, gable = (R.seed | 0) % 2 === 0;
1847
+ const roofColor = C.roof != null ? C.roof : 11031610, gable = (Number(R.seed) | 0) % 2 === 0;
1800
1848
  for (let f = 0; f < nA; f++) {
1801
1849
  const rs = R.rooms.filter((c) => c.floor === f && c.type !== "void" && !c.outbuilding && !OPEN_AREA(c)).flatMap(rectsOf2), up = R.rooms.filter((c) => c.floor === f + 1 && c.type !== "void").flatMap(rectsOf2);
1802
1850
  if (!rs.length) continue;
@@ -1818,7 +1866,7 @@ function installRoofRoofs(K, shared) {
1818
1866
  return Y0(f) + Math.max(...cs.map((c) => c.ceiling)) + 0.2;
1819
1867
  };
1820
1868
  if (type === "slab") {
1821
- for (let j = 0; j < nz; j++) for (let i = 0; i < nx; i++) if (O(j, i)) shared.ctx.roofRects.push({ f, r: [xs[i], zs[j], xs[i + 1], zs[j + 1]], slab: true, yb: pe(xs[i], zs[j], xs[i + 1], zs[j + 1]) + 0.03 });
1869
+ for (let j = 0; j < nz; j++) for (let i = 0; i < nx; i++) if (O(j, i)) roofRects.push({ f, r: [xs[i], zs[j], xs[i + 1], zs[j + 1]], slab: true, yb: pe(xs[i], zs[j], xs[i + 1], zs[j + 1]) + 0.03 });
1822
1870
  slabs(f, xs, zs, O, U, nx, nz, full, pe, C);
1823
1871
  cursor.pc = null;
1824
1872
  continue;
@@ -1841,16 +1889,16 @@ function installRoofRoofs(K, shared) {
1841
1889
  if (U(q.j0 - 1, i)) touchesU[1] = 1;
1842
1890
  if (U(q.j1 + 1, i)) touchesU[3] = 1;
1843
1891
  }
1844
- shared.ctx.roofRects.push({ f, r: [x0, z0, x1, z1], touchesU });
1892
+ roofRects.push({ f, r: [x0, z0, x1, z1], touchesU });
1845
1893
  const ybq = pe(x0, z0, x1, z1);
1846
1894
  roofRect(type, x0, z0, x1, z1, ybq, roofColor, gable && single, F, touchesU);
1847
1895
  cursor.pc = null;
1848
- if (shared.ctx.gutter.on) gutter(type, f, x0, z0, x1, z1, ybq, touchesU);
1896
+ if (G.on) gutter(type, f, x0, z0, x1, z1, ybq, touchesU);
1849
1897
  }
1850
1898
  }
1851
1899
  for (const e of shared.ctx.outbuildingList || []) {
1852
1900
  const [x0, z0, x1, z1] = e.aabb, yb = Y0(0) + (e.ceiling || 2.6) + 0.2;
1853
- shared.ctx.roofRects.push({ f: 0, r: [x0, z0, x1, z1], outbuilding: e.id });
1901
+ roofRects.push({ f: 0, r: [x0, z0, x1, z1], outbuilding: e.id });
1854
1902
  if (type === "slab") {
1855
1903
  const c = C.facade != null ? C.facade : 14209216;
1856
1904
  bx("plaster", x0 - 0.08, yb, z0 - 0.08, x1 + 0.08, yb + 0.03, z1 + 0.08, sh(C.ceiling != null ? C.ceiling : 12104876, 0.85));
@@ -1861,13 +1909,15 @@ function installRoofRoofs(K, shared) {
1861
1909
  roofRect(type, x0, z0, x1, z1, yb, roofColor, true, F, [0, 0, 0, 0]);
1862
1910
  cursor.pc = null;
1863
1911
  shared.ctx.noPiece = false;
1864
- if (shared.ctx.gutter.on) gutter(type, 0, x0, z0, x1, z1, yb, [0, 0, 0, 0]);
1912
+ if (G.on) gutter(type, 0, x0, z0, x1, z1, yb, [0, 0, 0, 0]);
1865
1913
  }
1866
1914
  }
1867
- Object.assign(K, { roofs });
1915
+ const defined = { roofs };
1916
+ Object.assign(K, defined);
1868
1917
  }
1869
1918
 
1870
1919
  // src/roof/gutters.ts
1920
+ var paletteMeta = (colors) => colors.meta;
1871
1921
  function installRoofGutters(K, shared) {
1872
1922
  const { boxC, bx, cursor, roomAt } = K;
1873
1923
  const sh = (...a) => K.sh(...a);
@@ -1884,7 +1934,7 @@ function installRoofGutters(K, shared) {
1884
1934
  const draw = rnd() < p, light = rnd() < 0.6;
1885
1935
  void draw;
1886
1936
  const on = true;
1887
- return { on, rnd, color: high ? 3816770 : light ? 15527921 : 10857392, bad: (shared.ctx.colors.meta && shared.ctx.colors.meta.state) === "abandoned" || R.state === "abandoned", fallback: false };
1937
+ return { on, rnd, color: high ? 3816770 : light ? 15527921 : 10857392, bad: paletteMeta(shared.ctx.colors)?.state === "abandoned" || R.state === "abandoned", fallback: false };
1888
1938
  }
1889
1939
  function gutter(type, f, X0, Z0, X1, Z1, yb, touchesU) {
1890
1940
  const G = shared.ctx.gutter, o = type === "fiber_cement" ? 0.3 : 0.45, x0 = X0 - (touchesU[0] ? 0 : o), x1 = X1 + (touchesU[2] ? 0 : o), z0 = Z0 - (touchesU[1] ? 0 : o), z1 = Z1 + (touchesU[3] ? 0 : o), c = G.color, y = yb - 0.05;
@@ -1926,7 +1976,7 @@ function installRoofGutters(K, shared) {
1926
1976
  const px = cx + sx * 0.06, pz = cz + sz * 0.06;
1927
1977
  if (!freeAt(px, pz, sx, sz)) return false;
1928
1978
  const floats = G.bad && G.ncond === 1, yt = yb - 0.1, ybx = floats ? 0.7 : 0.04;
1929
- G.ncond++;
1979
+ G.ncond = (G.ncond ?? 0) + 1;
1930
1980
  if (run2 >= 2) boxC("plain", (sides[run2][4] + px) / 2, yt, pz, Math.abs(sides[run2][4] - px), 0.07, 0.07, c);
1931
1981
  else boxC("plain", px, yt, (sides[run2][4] + pz) / 2, 0.07, 0.07, Math.abs(sides[run2][4] - pz), c);
1932
1982
  boxC("plain", px, (ybx + yt) / 2, pz, 0.08, yt - ybx, 0.08, c);
@@ -1960,7 +2010,7 @@ function installRoofGutters(K, shared) {
1960
2010
  function drain(x, z, px, pz, c) {
1961
2011
  const g0 = cursor.group;
1962
2012
  cursor.group = "f0";
1963
- if (px != null) boxC("plain", (px + x) / 2, 0.075, (pz + z) / 2, Math.abs(x - px) + 0.05, 0.05, Math.abs(z - pz) + 0.05, sh(c, 0.85));
2013
+ if (px != null && pz != null && c != null) boxC("plain", (px + x) / 2, 0.075, (pz + z) / 2, Math.abs(x - px) + 0.05, 0.05, Math.abs(z - pz) + 0.05, sh(c, 0.85));
1964
2014
  const t = 0.045;
1965
2015
  bx("plain", x - 0.12, 0, z - 0.12, x + 0.12, t - 6e-3, z + 0.12, 12170668);
1966
2016
  bx("metal", x - 0.11, t, z - 0.11, x + 0.11, t + 0.012, z + 0.11, 5922145);
@@ -1971,7 +2021,8 @@ function installRoofGutters(K, shared) {
1971
2021
  bx("metal", x - 0.085, t + 0.012, z - 6e-3, x + 0.085, t + 0.02, z + 6e-3, 9080466);
1972
2022
  cursor.group = g0;
1973
2023
  }
1974
- Object.assign(K, { gutterConfig, gutter, drain });
2024
+ const defined = { gutterConfig, gutter, drain };
2025
+ Object.assign(K, defined);
1975
2026
  }
1976
2027
 
1977
2028
  // src/roof/slabs.ts
@@ -2005,15 +2056,16 @@ function installRoofSlabs(K, shared) {
2005
2056
  side(free(j, i + 1), x1 + o - t, z0 - ez0, x1 + o, z1 + ez1);
2006
2057
  side(free(j - 1, i), x0 - ex0, z0 - o, x1 + ex1, z0 - o + t);
2007
2058
  side(free(j + 1, i), x0 - ex0, z1 + o - t, x1 + ex1, z1 + o);
2008
- if (shared.ctx.gutter && shared.ctx.gutter.on) for (const [ok, dx, dz] of [[free(j - 1, i), 0, -1], [free(j + 1, i), 0, 1], [free(j, i - 1), -1, 0], [free(j, i + 1), 1, 0]]) {
2059
+ const G = shared.ctx.gutter;
2060
+ if (G && G.on && G.bz) for (const [ok, dx, dz] of [[free(j - 1, i), 0, -1], [free(j + 1, i), 0, 1], [free(j, i - 1), -1, 0], [free(j, i + 1), 1, 0]]) {
2009
2061
  const kd = f + ":" + dx + ":" + dz;
2010
- if (!ok || shared.ctx.gutter.bz.has(kd)) continue;
2011
- shared.ctx.gutter.bz.add(kd);
2012
- shared.ctx.gutter.nbuz++;
2013
- const mx = (x0 + x1) / 2, mz = (z0 + z1) / 2, ex = dx ? dx < 0 ? x0 - o : x1 + o : mx, ez = dz ? dz < 0 ? z0 - o : z1 + o : mz, cc = shared.ctx.gutter.color;
2062
+ if (!ok || G.bz.has(kd)) continue;
2063
+ G.bz.add(kd);
2064
+ G.nbuz = (G.nbuz ?? 0) + 1;
2065
+ const mx = (x0 + x1) / 2, mz = (z0 + z1) / 2, ex = dx ? dx < 0 ? x0 - o : x1 + o : mx, ez = dz ? dz < 0 ? z0 - o : z1 + o : mz, cc = G.color;
2014
2066
  boxC("plain", ex + dx * 0.15, yb + 0.1, ez + dz * 0.15, dx ? 0.42 : 0.14, 0.1, dz ? 0.42 : 0.14, cc);
2015
2067
  boxC("plain", ex + dx * 0.36, yb + 0.1, ez + dz * 0.36, dx ? 0.04 : 0.18, 0.14, dz ? 0.04 : 0.18, sh(cc, 0.8));
2016
- if (shared.ctx.gutter.bad) boxC("plain", ex + dx * 0.05, yb + 0.5 * 0, ez + dz * 0.05, dx ? 0.06 : 0.3, 0.02, dz ? 0.06 : 0.3, 4868674);
2068
+ if (G.bad) boxC("plain", ex + dx * 0.05, yb + 0.5 * 0, ez + dz * 0.05, dx ? 0.06 : 0.3, 0.02, dz ? 0.06 : 0.3, 4868674);
2017
2069
  {
2018
2070
  const tx = ex + dx * 0.38, tz = ez + dz * 0.38;
2019
2071
  let lv = true;
@@ -2033,7 +2085,8 @@ function installRoofSlabs(K, shared) {
2033
2085
  }
2034
2086
  }
2035
2087
  }
2036
- Object.assign(K, { slabs });
2088
+ const defined = { slabs };
2089
+ Object.assign(K, defined);
2037
2090
  }
2038
2091
 
2039
2092
  // src/roof/tiles.ts
@@ -2166,7 +2219,8 @@ function installRoofTiles(K, shared) {
2166
2219
  }
2167
2220
  return m ? structurePiece(m.id) : null;
2168
2221
  }
2169
- Object.assign(K, { R_STYLE, tileRelief, ridge, pieceOfPane });
2222
+ const defined = { R_STYLE, tileRelief, ridge, pieceOfPane };
2223
+ Object.assign(K, defined);
2170
2224
  }
2171
2225
 
2172
2226
  // src/roof/rect.ts
@@ -2212,7 +2266,7 @@ function installRoofRect(K, shared) {
2212
2266
  }
2213
2267
  const rm = alongX ? dz / 2 : dx / 2;
2214
2268
  {
2215
- const rr = shared.ctx.roofRects[shared.ctx.roofRects.length - 1];
2269
+ const roofRects = shared.ctx.roofRects, rr = roofRects[roofRects.length - 1];
2216
2270
  if (rr && !rr.yb) Object.assign(rr, { yb, tp, gable: !!gable, alongX, exterior: [x0, z0, x1, z1], rm });
2217
2271
  }
2218
2272
  if (gable) {
@@ -2249,7 +2303,8 @@ function installRoofRect(K, shared) {
2249
2303
  }
2250
2304
  }
2251
2305
  }
2252
- Object.assign(K, { roofRect });
2306
+ const defined = { roofRect };
2307
+ Object.assign(K, defined);
2253
2308
  }
2254
2309
 
2255
2310
  // src/mirrors.ts
@@ -2260,9 +2315,11 @@ function installMirrors(K, shared) {
2260
2315
  function mirrorEnv() {
2261
2316
  if (shared.mirrorEnv) return shared.mirrorEnv;
2262
2317
  const mk = (f) => {
2318
+ if (!DOC) throw new Error("game-floorplan-three: the mirrors need a document (options.document)");
2263
2319
  const c = DOC.createElement("canvas");
2264
2320
  c.width = c.height = 64;
2265
2321
  const g = c.getContext("2d");
2322
+ if (!g) throw new Error("game-floorplan-three: no 2d canvas context");
2266
2323
  f(g);
2267
2324
  return c;
2268
2325
  };
@@ -2321,7 +2378,7 @@ function installMirrors(K, shared) {
2321
2378
  B.N.push(v.x, v.y, v.z);
2322
2379
  B.U.push(ua.getX(i), ua.getY(i));
2323
2380
  }
2324
- for (const k of geo.index.array) B.I.push(B.nv + k);
2381
+ for (const k of geo.index?.array ?? []) B.I.push(B.nv + k);
2325
2382
  B.nv += pa.count;
2326
2383
  geo.dispose();
2327
2384
  }
@@ -2399,10 +2456,12 @@ function installMirrors(K, shared) {
2399
2456
  m.fake.visible = !on;
2400
2457
  }
2401
2458
  }
2402
- Object.assign(K, { mirrorEnv, newMirrorState, assembleMirrors, floorAtY, chooseMirror });
2459
+ const defined = { mirrorEnv, newMirrorState, assembleMirrors, floorAtY, chooseMirror };
2460
+ Object.assign(K, defined);
2403
2461
  }
2404
2462
 
2405
2463
  // src/cars.ts
2464
+ import { isMesh } from "@adatechnology/game-shapes-three";
2406
2465
  function installCars(K, shared) {
2407
2466
  const { THREE, FLEET, _Y } = K;
2408
2467
  const CARS = [];
@@ -2412,13 +2471,16 @@ function installCars(K, shared) {
2412
2471
  high: ["electric_hatch", "hybrid_suv", "midsize_suv", "v8_coupe", "large_suv", "midsize_pickup", "crossover_pickup", "fastback_sedan"]
2413
2472
  }, K.cfg.carKinds);
2414
2473
  const CAR_CACHE = /* @__PURE__ */ new Map();
2415
- function materialSignature(m) {
2474
+ function materialSignature(material) {
2475
+ const m = material;
2416
2476
  const f = (v) => v == null ? "" : typeof v === "number" ? v.toFixed(3) : v.isColor ? v.getHexString() : v.uuid || String(v);
2417
2477
  return [m.type, f(m.color), f(m.roughness), f(m.metalness), f(m.opacity), m.transparent ? 1 : 0, m.side, f(m.map), f(m.emissive), f(m.emissiveIntensity), m.vertexColors ? 1 : 0, m.flatShading ? 1 : 0, f(m.envMapIntensity), f(m.alphaTest)].join("|");
2418
2478
  }
2419
2479
  const BUCKETS = /* @__PURE__ */ new Map();
2420
- function bucketMaterial(m) {
2421
- if (m.type !== "MeshStandardMaterial" || m.map || m.alphaTest || m.vertexColors || !m.color) return null;
2480
+ function bucketMaterial(material) {
2481
+ if (material.type !== "MeshStandardMaterial") return null;
2482
+ const m = material;
2483
+ if (m.map || m.alphaTest || m.vertexColors || !m.color) return null;
2422
2484
  const mt = m.metalness > 0.5 ? 2 : m.metalness > 0.2 ? 1 : 0, rg = m.roughness < 0.3 ? 0 : m.roughness < 0.6 ? 1 : 2, tr = m.transparent || m.opacity < 1, op = tr ? Math.max(0.2, Math.min(0.9, Math.round(m.opacity * 5) / 5)) : 1, sig = "bucket" + mt + rg + "s" + m.side + (tr ? "t" + op : "");
2423
2485
  let b = BUCKETS.get(sig);
2424
2486
  if (!b) {
@@ -2430,7 +2492,7 @@ function installCars(K, shared) {
2430
2492
  }
2431
2493
  function carModel(k, seed) {
2432
2494
  const kc = k + "|" + shared.quality + "|" + (seed || 0);
2433
- if (CAR_CACHE.has(kc)) return CAR_CACHE.get(kc);
2495
+ if (CAR_CACHE.has(kc)) return CAR_CACHE.get(kc) ?? null;
2434
2496
  if (!FLEET) return null;
2435
2497
  let res = null;
2436
2498
  try {
@@ -2438,8 +2500,10 @@ function installCars(K, shared) {
2438
2500
  c.root.updateMatrixWorld(true);
2439
2501
  const inv = new THREE.Matrix4();
2440
2502
  const byMaterial = /* @__PURE__ */ new Map(), tmp = new THREE.Matrix4(), v = new THREE.Vector3(), nm = new THREE.Matrix3(), bb = new THREE.Box3();
2441
- c.g.traverse((o) => {
2442
- if (!o.isMesh || o.isInstancedMesh || o.isSkinnedMesh || !o.geometry || !o.geometry.attributes.position) return;
2503
+ c.g.traverse((node) => {
2504
+ if (!isMesh(node)) return;
2505
+ const o = node;
2506
+ if (o.isInstancedMesh || o.isSkinnedMesh || !o.geometry || !o.geometry.attributes.position) return;
2443
2507
  for (let p = o; p; p = p.parent) if (p.visible === false) return;
2444
2508
  const mats = Array.isArray(o.material) ? o.material : [o.material];
2445
2509
  let geo = o.geometry;
@@ -2453,7 +2517,7 @@ function installCars(K, shared) {
2453
2517
  const pa = geo.attributes.position, na = geo.attributes.normal, ua = geo.attributes.uv, total = pa.count;
2454
2518
  const grs = Array.isArray(o.material) && o.geometry.groups.length ? o.geometry.groups : [{ start: 0, count: total, materialIndex: 0 }];
2455
2519
  for (const gr of grs) {
2456
- const m = mats[gr.materialIndex] || mats[0];
2520
+ const m = (gr.materialIndex != null ? mats[gr.materialIndex] : void 0) || mats[0];
2457
2521
  if (!m) continue;
2458
2522
  const a0 = Math.min(gr.start, total), n0 = Math.min(gr.count, total - a0) - Math.min(gr.count, total - a0) % 3;
2459
2523
  if (n0 < 3) continue;
@@ -2554,7 +2618,10 @@ function installCars(K, shared) {
2554
2618
  return g;
2555
2619
  }
2556
2620
  function assembleCars(groups) {
2557
- if (shared.quality === "game") return assembleMergedCars(groups);
2621
+ if (shared.quality === "game") {
2622
+ assembleMergedCars(groups);
2623
+ return;
2624
+ }
2558
2625
  for (const C of CARS) {
2559
2626
  const g = carGroup(C.k, C.w, C.d, C.seed);
2560
2627
  if (!g) continue;
@@ -2605,7 +2672,8 @@ function installCars(K, shared) {
2605
2672
  (groups[B.parent] || (groups[B.parent] = new THREE.Group())).add(m);
2606
2673
  }
2607
2674
  }
2608
- Object.assign(K, { CARS, CAR_BY_STYLE, CAR_CACHE, materialSignature, BUCKETS, bucketMaterial, carModel, carGroup, assembleCars, assembleMergedCars });
2675
+ const defined = { CARS, CAR_BY_STYLE, CAR_CACHE, materialSignature, BUCKETS, bucketMaterial, carModel, carGroup, assembleCars, assembleMergedCars };
2676
+ Object.assign(K, defined);
2609
2677
  }
2610
2678
 
2611
2679
  // src/house/building.ts
@@ -2661,14 +2729,15 @@ function installHouseBuilding(K, shared) {
2661
2729
  bx("plaster", Math.min(hall[0] - 3, color[0]), ytop, Math.min(un[1] ? unitBox(un[1])[1] : 0, el[1]), Math.max(color[2], un0[2]), ytop + 0.2, Math.max(un0[3], un[1] ? unitBox(un[1])[3] : 0), 11841704);
2662
2730
  shared.ctx.limits = { x0: Math.min(hall[0] - 3, color[0]), z0: Math.min(el[1], un[1] ? unitBox(un[1])[1] : 0), x1: Math.max(color[2], un0[2]), z1: Math.max(un0[3], un[1] ? unitBox(un[1])[3] : 0) };
2663
2731
  }
2664
- Object.assign(K, { building });
2732
+ const defined = { building };
2733
+ Object.assign(K, defined);
2665
2734
  }
2666
2735
 
2667
2736
  // src/utilities/water.ts
2668
2737
  function installUtilitiesWater(K, shared) {
2669
2738
  const { THREE, _Y, _q, cursor, cylBase, part, pieceRecord, put } = K;
2670
2739
  function createWater(r, state) {
2671
- const H = r.utilities.plumbing, cap = H ? +H.capacityL || 0 : 0, ls = { dry: [], full: [] }, points = {}, itemPoint = {};
2740
+ const H = r.utilities?.plumbing, cap = H ? +H.capacityL || 0 : 0, ls = { dry: [], full: [] }, points = {}, itemPoint = {};
2672
2741
  if (H) for (const p of H.points) {
2673
2742
  points[p.id] = p;
2674
2743
  itemPoint[p.item] = p.id;
@@ -2757,14 +2826,14 @@ function installUtilitiesWater(K, shared) {
2757
2826
  }
2758
2827
  const _v3 = new THREE.Vector3();
2759
2828
  function waterPipes() {
2760
- const H = shared.ctx.r.utilities.plumbing;
2829
+ const H = shared.ctx.r.utilities?.plumbing;
2761
2830
  if (!H || !H.visibleRuns) return;
2762
2831
  const nA = shared.ctx.r.floors.length;
2763
2832
  const groupOf = (c) => c && c.floor >= 0 ? "f" + Math.min(c.floor, nA - 1) : "lot", xyz = (p) => [p[0], p[2], p[1]];
2764
2833
  for (const tr of H.visibleRuns) {
2765
2834
  const pts = tr.points.map(xyz), d = tr.diameter || 0.025;
2766
2835
  if (tr.exposed === "wall") {
2767
- const pt = H.points.find((p) => p.run === tr.id), com = shared.ctx.roomById[tr.to], g2 = groupOf(com || pt && { floor: pt.floor });
2836
+ const pt = H.points.find((p) => p.run === tr.id), com = tr.to != null ? shared.ctx.roomById[tr.to] : void 0, g2 = groupOf(com || pt && { floor: pt.floor });
2768
2837
  part("wall_pipe", [0, 0, 0], () => {
2769
2838
  for (let i = 0; i + 1 < pts.length; i++) pipe(pts[i], pts[i + 1], d, PIPE_COLOR);
2770
2839
  for (const p of pts) cylBase("plain", p[0], p[1] - d, p[2], d * 0.7, d * 2, PIPE_COLOR);
@@ -2786,7 +2855,8 @@ function installUtilitiesWater(K, shared) {
2786
2855
  cursor.pc = null;
2787
2856
  }
2788
2857
  }
2789
- Object.assign(K, { createWater, PIPE_COLOR, pipe, _v3, waterPipes });
2858
+ const defined = { createWater, PIPE_COLOR, pipe, _v3, waterPipes };
2859
+ Object.assign(K, defined);
2790
2860
  }
2791
2861
 
2792
2862
  // src/utilities/electrical.ts
@@ -2794,10 +2864,10 @@ function installUtilitiesElectrical(K, shared) {
2794
2864
  const { _Y, _q, _v3, bx, cursor, cylBase, pieceRecord, put } = K;
2795
2865
  const sh = (...a) => K.sh(...a);
2796
2866
  function electricalStructure() {
2797
- const E = shared.ctx.r.utilities.electrical;
2867
+ const R = shared.ctx.r, E = R.utilities?.electrical;
2798
2868
  shared.ctx.electricalInfo = null;
2799
2869
  if (!E) return;
2800
- const R = shared.ctx.r, nA = R.floors.length, lotGroup = R.lot ? "lot" : "f0", concreteColor = 11973547, iron = 4869200, wireRun = 1842206, info = { pole: null, meter: null, panel: null, conduits: [], outlets: [], switches: [], circuits: E.circuits || [], exposed: !!E.exposed };
2870
+ const nA = R.floors.length, lotGroup = R.lot ? "lot" : "f0", concreteColor = 11973547, iron = 4869200, wireRun = 1842206, info = { pole: null, meter: null, panel: null, conduits: [], outlets: [], switches: [], circuits: E.circuits || [], exposed: !!E.exposed };
2801
2871
  const en2 = E.serviceEntrance, KV = shared.ctx.iv ? shared.ctx.iv.plane : null;
2802
2872
  const wireL = (a, b, r_ = 8e-3) => {
2803
2873
  const L = Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
@@ -2902,7 +2972,8 @@ function installUtilitiesElectrical(K, shared) {
2902
2972
  _q.setFromUnitVectors(_Y, _v3.set(dx / L, dy / L, dz / L));
2903
2973
  put("plain", "cyl", (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2, _q, diameter, L, diameter, color);
2904
2974
  }
2905
- Object.assign(K, { electricalStructure, pipe2 });
2975
+ const defined = { electricalStructure, pipe2 };
2976
+ Object.assign(K, defined);
2906
2977
  }
2907
2978
 
2908
2979
  // src/house/baseboard.ts
@@ -2940,7 +3011,8 @@ function installHouseBaseboard(K, shared) {
2940
3011
  strip(W, y0, y0 + 0.045, 0, W, "sidewalk", cal);
2941
3012
  }
2942
3013
  }
2943
- Object.assign(K, { baseboardAndSidewalk });
3014
+ const defined = { baseboardAndSidewalk };
3015
+ Object.assign(K, defined);
2944
3016
  }
2945
3017
 
2946
3018
  // src/utilities/solar.ts
@@ -2955,6 +3027,7 @@ function installUtilitiesSolar(K, shared) {
2955
3027
  if (u >= a - 0.05 && u <= c + 0.05 && v >= b - 0.05 && v <= d + 0.05) y = Math.max(y == null ? -1e9 : y, rr.yb);
2956
3028
  continue;
2957
3029
  }
3030
+ if (!rr.exterior || rr.tp == null || rr.rm == null) continue;
2958
3031
  const [x0, z0, x1, z1] = rr.exterior;
2959
3032
  if (u < x0 || u > x1 || v < z0 || v > z1) continue;
2960
3033
  const dz = Math.min(v - z0, z1 - v), dx = Math.min(u - x0, x1 - u), dd = rr.gable ? rr.alongX ? dz : dx : Math.min(dx, dz), h = rr.yb + rr.tp * Math.min(dd, rr.rm);
@@ -2963,7 +3036,7 @@ function installUtilitiesSolar(K, shared) {
2963
3036
  return y;
2964
3037
  }
2965
3038
  function solar() {
2966
- const R = shared.ctx.r, S = R.utilities.solar;
3039
+ const R = shared.ctx.r, S = R.utilities?.solar;
2967
3040
  shared.ctx.solarInfo = null;
2968
3041
  if (!S || !S.panels || !S.panels.length) return;
2969
3042
  cursor.group = "roof";
@@ -3006,13 +3079,14 @@ function installUtilitiesSolar(K, shared) {
3006
3079
  bx("plain", iv.u - W * 0.6, y0 + 0.05, iv.v + fa0, iv.u + W * 0.6, y0 + 0.17, iv.v + fa1, 2106924);
3007
3080
  bx("emissive", iv.u - 0.03, y0 - 0.12, iv.v + fa0, iv.u + 0.03, y0 - 0.09, iv.v + fa1, 6479994);
3008
3081
  }
3009
- const top = Math.max(...(shared.ctx.roofRects || []).filter((t2) => t2.yb != null).map((t2) => t2.yb), Y0(fa) + 2.8);
3082
+ const top = Math.max(...(shared.ctx.roofRects || []).flatMap((t2) => t2.yb != null ? [t2.yb] : []), Y0(fa) + 2.8);
3010
3083
  cylBase("plain", iv.u, y0 + h / 2, iv.v, 0.016, Math.max(0.2, top - 0.2 - (y0 + h / 2)), 15262936);
3011
3084
  info.inverter = { id: iv.id, pos: [iv.u, y0, iv.v], side: iv.side, link: iv.link };
3012
3085
  }
3013
3086
  shared.ctx.solarInfo = info;
3014
3087
  }
3015
- Object.assign(K, { roofHeightAt, solar });
3088
+ const defined = { roofHeightAt, solar };
3089
+ Object.assign(K, defined);
3016
3090
  }
3017
3091
 
3018
3092
  // src/house/outbuildings.ts
@@ -3027,7 +3101,7 @@ function installHouseOutbuildings(K, shared) {
3027
3101
  counts.set(w.floor, i + 1);
3028
3102
  return w.id ? w : Object.assign({}, w, { id: `wall_${w.floor}_${i}` });
3029
3103
  }) });
3030
- const E = (r.outbuildings || []).filter((e) => e && e.walls && e.walls.length && e.interior && e.interior.length);
3104
+ const E = (r.outbuildings || []).filter((e) => !!(e && e.walls && e.walls.length && e.interior && e.interior.length));
3031
3105
  if (!E.length) return r;
3032
3106
  const rooms = r.rooms.slice(), walls = r.walls.slice(), doors = r.doors.slice(), windows = r.windows.slice(), items = r.items.filter((m) => m.type !== "outbuilding");
3033
3107
  for (const e of E) {
@@ -3041,7 +3115,22 @@ function installHouseOutbuildings(K, shared) {
3041
3115
  const alongU = p.axis === "u", below = p.pos < (alongU ? cz : cx);
3042
3116
  doors.push({ id: p.id, floor: 0, u: p.u, v: p.v, axis: p.axis, pos: p.pos, at: p.at, width: p.width, a: below ? "outside" : e.id, b: below ? e.id : "outside", opensTo: e.id, exterior: true, side: p.side, leaves: 1, model: "single", hinge: "start", zones: [], blocked: false, outbuilding: e.id });
3043
3117
  }
3044
- for (const j of e.windows || []) windows.push({ id: j.id, floor: 0, u: j.u, v: j.v, axis: j.axis, pos: j.pos, at: j.at, width: j.width, y0: j.y0, y1: j.y1, room: e.id, side: j.side, outbuilding: e.id });
3118
+ for (const j of e.windows || []) windows.push({
3119
+ id: j.id,
3120
+ floor: 0,
3121
+ u: j.u,
3122
+ v: j.v,
3123
+ axis: j.axis,
3124
+ pos: j.pos,
3125
+ at: j.at,
3126
+ width: j.width,
3127
+ y0: j.y0 ?? 1,
3128
+ y1: j.y1 ?? 2,
3129
+ /* the structure always gives a window its sill and head (1.0, 2.0) */
3130
+ room: e.id,
3131
+ side: j.side,
3132
+ outbuilding: e.id
3133
+ });
3045
3134
  (e.items || []).forEach((m, i) => items.push({ id: e.id + "." + m.type + i, type: m.type, category: m.category, x: m.u, z: m.v, ry: m.ry || 0, w: m.w, d: m.d, h: m.h, y: 0.04, frontU: m.frontU, frontV: m.frontV, room: e.id, floor: 0, outdoor: false, aabb: m.aabb, color: "wood" }));
3046
3135
  items.push({ id: e.id + ".ceiling_light", type: "ceiling_light", category: "ceiling_light", x: cx, z: cz, ry: 0, w: 0.35, d: 0.35, h: 0.1, y: pe - 0.1, room: e.id, floor: 0, outdoor: false, assembly: "ceiling", color: "metal", decor: true });
3047
3136
  }
@@ -3062,7 +3151,8 @@ function installHouseOutbuildings(K, shared) {
3062
3151
  }
3063
3152
  }
3064
3153
  }
3065
- Object.assign(K, { OUTBUILDING_USE, applyOutbuildings, outbuildings });
3154
+ const defined = { OUTBUILDING_USE, applyOutbuildings, outbuildings };
3155
+ Object.assign(K, defined);
3066
3156
  }
3067
3157
 
3068
3158
  // src/furniture/api.ts
@@ -3127,7 +3217,8 @@ function installFurnitureApi(K, _shared) {
3127
3217
  return { b: (mat, x, y, z, w, h, d, color, ry, rx, rz) => A.box(M, mat, x, y0 + y, z, w, h, d, color, ry || 0, rx || 0, rz || 0), c: (mat, x, y, z, r, h, color, rx, rz, seg) => A.cylinder(M, mat, x, y0 + y, z, r, h, color, rx || 0, rz || 0, seg), rnd: rngOf(M), wood: paletteColor(M, "wood", 8016948), met: paletteColor(M, "metal", 10133154) };
3128
3218
  }
3129
3219
  const PE = Math.PI / 2;
3130
- Object.assign(K, { MATERIAL_MAP, mm, LIGHTS, makeApi, sh, paletteColor, rngOf, kk, PE });
3220
+ const defined = { MATERIAL_MAP, mm, LIGHTS, makeApi, sh, paletteColor, rngOf, kk, PE };
3221
+ Object.assign(K, defined);
3131
3222
  }
3132
3223
 
3133
3224
  // src/furniture/builders.ts
@@ -3255,7 +3346,7 @@ function installFurnitureBuilders(K, _shared) {
3255
3346
  for (let s = 0; s < np; s++) lb("fabric", np === 1 ? 0 : (s ? 1 : -1) * w * 0.23, 0.5, -d / 2 + 0.3, w * (np === 1 ? 0.6 : 0.4), 0.12, 0.34, 15789798, (s ? 1 : -1) * 0.08);
3256
3347
  },
3257
3348
  wardrobe(M, A) {
3258
- const { b: lb } = kk(M, A), w = M.w, d = M.d, h = M.h, wood = M.color != null && false ? M.color : paletteColor(M, "wood", 5980208), np = Math.max(2, Math.round(w / 0.7));
3349
+ const { b: lb } = kk(M, A), w = M.w, d = M.d, h = M.h, wood = paletteColor(M, "wood", 5980208), np = Math.max(2, Math.round(w / 0.7));
3259
3350
  lb("wood", 0, 0.06, 0, w, h - 0.06, d, wood);
3260
3351
  lb("wood", 0, h, 0, w + 0.04, 0.04, d + 0.04, sh(wood, 0.8));
3261
3352
  lb("wood", 0, 0, 0, w - 0.04, 0.06, d - 0.04, sh(wood, 0.4));
@@ -3647,7 +3738,8 @@ function installFurnitureBuilders(K, _shared) {
3647
3738
  lb("metal", 0, h - 0.04, d / 2, w, 0.03, 0.03, 3815994);
3648
3739
  }
3649
3740
  };
3650
- Object.assign(K, { FURNITURE });
3741
+ const defined = { FURNITURE };
3742
+ Object.assign(K, defined);
3651
3743
  }
3652
3744
 
3653
3745
  // src/furniture/type-table.ts
@@ -3657,7 +3749,8 @@ function installFurnitureTypeTable(K, _shared) {
3657
3749
  function typeTable(props) {
3658
3750
  const B = props.builders, T = {};
3659
3751
  const mv = (type, id) => {
3660
- if (B[id || type]) T[type] = { f: B[id || type], source: "props3d" };
3752
+ const f = B[id || type];
3753
+ if (f) T[type] = { f, source: "props3d" };
3661
3754
  };
3662
3755
  const mine = (type, f, source = "game") => {
3663
3756
  T[type] = { f, source };
@@ -3796,7 +3889,8 @@ function installFurnitureTypeTable(K, _shared) {
3796
3889
  extraTypes(T, props);
3797
3890
  return T;
3798
3891
  }
3799
- Object.assign(K, { typeTable });
3892
+ const defined = { typeTable };
3893
+ Object.assign(K, defined);
3800
3894
  }
3801
3895
 
3802
3896
  // src/furniture/taps.ts
@@ -3860,7 +3954,8 @@ function installFurnitureTaps(K, shared) {
3860
3954
  }, { id: id + "_a", target: id, hidden: true, fluid: "water" });
3861
3955
  return id;
3862
3956
  }
3863
- Object.assign(K, { counterTap, wallTap });
3957
+ const defined = { counterTap, wallTap };
3958
+ Object.assign(K, defined);
3864
3959
  }
3865
3960
 
3866
3961
  // src/furniture/fixtures.ts
@@ -3973,7 +4068,7 @@ function installFurniturePlants(K, _shared) {
3973
4068
  const a = rnd() * 6.283, u = Math.sqrt(rnd()), ph = (rnd() - 0.2) * 1.2, dx = Math.cos(a) * u * R * 0.75, dz = Math.sin(a) * u * R * 0.75, dy = (o.flatten ? 0.35 : 0.55) * R * (Math.sin(ph) * 0.5 + 0.5) * 1.5 - R * 0.15;
3974
4069
  const r = R * (0.34 + rnd() * 0.22) * (1 - u * 0.25), alt = r * 2 * (o.flatten ? 0.75 : 0.95), f = 0.72 + Math.min(1, (dy + R * 0.2) / (R * 1.2)) * 0.32 + rnd() * 0.12;
3975
4070
  K2.e("plant", cx + dx, cy + dy + r * 0.5, cz + dz, r, alt, sh(green, f));
3976
- if (o.flower && rnd() < o.flower) {
4071
+ if (o.flower && o.flowers && rnd() < o.flower) {
3977
4072
  const fa = rnd() * 6.283;
3978
4073
  K2.e("plain", cx + dx + Math.cos(fa) * r * 0.78, cy + dy + r * 0.5 + rnd() * r * 0.5, cz + dz + Math.sin(fa) * r * 0.78, 0.028 + rnd() * 0.012, 0.05, o.flowers[rnd() * o.flowers.length | 0]);
3979
4074
  }
@@ -4086,7 +4181,8 @@ function installFurniturePlants(K, _shared) {
4086
4181
  else blobs(K2, x, bh - 0.05, z, 0.24 + rnd() * 0.08, 6, green, rnd, { flatten: true, flower: tp === "flower" ? 0.9 : 0.25, flowers: FLOWERS.slice(i % 3, i % 3 + 3) });
4087
4182
  }
4088
4183
  }
4089
- Object.assign(K, { GREENS, FLOWERS, blobs, potModel, arcLeaf, tuft, palm_tree, treeModel, shrubModel, potPlant, tablePot, planterModel });
4184
+ const defined = { GREENS, FLOWERS, blobs, potModel, arcLeaf, tuft, palm_tree, treeModel, shrubModel, potPlant, tablePot, planterModel };
4185
+ Object.assign(K, defined);
4090
4186
  }
4091
4187
 
4092
4188
  // src/furniture/yard.ts
@@ -4242,7 +4338,7 @@ function installFurnitureYard(K, shared) {
4242
4338
  };
4243
4339
  FURNITURE.mailbox = function(M, A) {
4244
4340
  const K2 = kit2(M, A, 0), w = M.w || 0.3, d = M.d || 0.22, h = M.h || 0.3, y = M.y != null && M.y > 0 ? M.y : 1, structure = STYLE(), pc = structure === "high" ? 2763824 : structure === "mid" ? 13676640 : 13126202, rnd = rngString(SEED() + "|" + seedKey(M.seed) + "|correio");
4245
- if (M.pole !== false && !(M.y > 0)) {
4341
+ if (M.pole !== false && !(M.y != null && M.y > 0)) {
4246
4342
  K2.b("plain", 0, 0, -d / 2 - 0.1, 0.12, y, 0.12, 12104874);
4247
4343
  }
4248
4344
  K2.b("metal", 0, y, 0, w, h * 0.78, d, pc);
@@ -4262,7 +4358,8 @@ function installFurnitureYard(K, shared) {
4262
4358
  );
4263
4359
  K2.b("plain", 0, y + h * 0.62, d / 2 + 4e-3, 0.08, 0.05, 4e-3, 15921386);
4264
4360
  };
4265
- Object.assign(K, { CLOTHES_COLORS, strip, garment });
4361
+ const defined = { CLOTHES_COLORS, strip, garment };
4362
+ Object.assign(K, defined);
4266
4363
  }
4267
4364
 
4268
4365
  // src/furniture/extra-types.ts
@@ -4322,7 +4419,8 @@ function installFurnitureExtraTypes(K, _shared) {
4322
4419
  tuft(K2, 0, 0, 0, Math.max(0.2, (M.w || 0.4) / 2), 16, 5212738, rnd);
4323
4420
  });
4324
4421
  }
4325
- Object.assign(K, { extraTypes });
4422
+ const defined = { extraTypes };
4423
+ Object.assign(K, defined);
4326
4424
  }
4327
4425
 
4328
4426
  // src/furniture/place-items.ts
@@ -4344,8 +4442,8 @@ function installFurniturePlaceItems(K, shared) {
4344
4442
  if (m.type === "stairs") continue;
4345
4443
  const exterior = m.outdoor || m.floor < 0, f = exterior ? -1 : Math.min(m.floor, R.floors.length - 1);
4346
4444
  cursor.group = exterior ? "lot" : "f" + f;
4347
- const com = shared.ctx.roomById[m.room], base = exterior ? 0 : Y0(f);
4348
- const M = { x: m.x, z: m.z, ry: m.ry || 0, w: m.w, d: m.d, h: m.h, y: m.y || 0, base, floor: exterior ? -1 : f, palette: shared.ctx.colors, color: m.category === "ground_cover" ? void 0 : colorOf(m.color) != null ? colorOf(m.color) : void 0, seed: m.id, room: m.room, typeWith: com ? com.type : null, ceiling: com ? com.ceiling : 2.9, on: shared.ctx.night, light: shared.ctx.night, lit: shared.ctx.night, open: !!m.doorOpen, overhead: m.overhead, assembly: m.assembly, hose: m.hose };
4445
+ const com = m.room != null ? shared.ctx.roomById[m.room] : void 0, base = exterior ? 0 : Y0(f);
4446
+ const M = { x: m.x, z: m.z, ry: m.ry || 0, w: m.w, d: m.d, h: m.h, y: m.y || 0, base, floor: exterior ? -1 : f, palette: shared.ctx.colors, color: m.category === "ground_cover" ? void 0 : colorOf(m.color) ?? void 0, seed: m.id, room: m.room, typeWith: com ? com.type : null, ceiling: com ? com.ceiling : 2.9, on: shared.ctx.night, light: shared.ctx.night, lit: shared.ctx.night, open: !!m.doorOpen, overhead: m.overhead, assembly: m.assembly, hose: m.hose };
4349
4447
  if (m.category === "ground_cover" && m.polygon) {
4350
4448
  const xs = m.polygon.map((p) => p[0]), zs = m.polygon.map((p) => p[1]);
4351
4449
  M.x = (Math.min(...xs) + Math.max(...xs)) / 2;
@@ -4422,10 +4520,12 @@ function installFurniturePlaceItems(K, shared) {
4422
4520
  boxC("plain", m.x, M.base + (m.y || 0) + h / 2, m.z, m.w, h, m.d, color, 0, m.ry || 0, 0);
4423
4521
  shared.ctx.labels.push({ pos: new THREE.Vector3(m.x, M.base + (m.y || 0) + h + 0.15, m.z), text: m.type, group, type: "no_model" });
4424
4522
  }
4425
- Object.assign(K, { houseItems, waterTankOfHouse, hashColor, labeledBox });
4523
+ const defined = { houseItems, waterTankOfHouse, hashColor, labeledBox };
4524
+ Object.assign(K, defined);
4426
4525
  }
4427
4526
 
4428
4527
  // src/vegetation/bridge.ts
4528
+ import { isMesh as isMesh2 } from "@adatechnology/game-shapes-three";
4429
4529
  function installVegetationBridge(K, shared) {
4430
4530
  const seedKey = (id) => K.seedKey(id);
4431
4531
  const { THREE, SEED, rngString } = K;
@@ -4457,7 +4557,7 @@ function installVegetationBridge(K, shared) {
4457
4557
  const ids = VEG_MAP[m.type], can = VEG_PLANTER[m.type];
4458
4558
  if (!ids && !can) return false;
4459
4559
  const rnd = rngString(SEED() + "|" + seedKey(m.id) + "|veg"), pick = (l) => l[Math.min(l.length - 1, rnd() * l.length | 0)], ok = (id) => {
4460
- if (V.ok.has(id)) return V.ok.get(id);
4560
+ if (V.ok.has(id)) return V.ok.get(id) === true;
4461
4561
  let r = true;
4462
4562
  try {
4463
4563
  V.S.toSpec(id);
@@ -4503,7 +4603,7 @@ function installVegetationBridge(K, shared) {
4503
4603
  obj.position.y = G.y;
4504
4604
  obj.name = "vegetation";
4505
4605
  obj.traverse((o) => {
4506
- if (o.isMesh) {
4606
+ if (isMesh2(o)) {
4507
4607
  o.castShadow = true;
4508
4608
  o.receiveShadow = true;
4509
4609
  o.name = "veg/" + o.name;
@@ -4518,10 +4618,12 @@ function installVegetationBridge(K, shared) {
4518
4618
  }
4519
4619
  shared.ctx.vegInfo = { plants: pl, triangles: tri, colliders: col, lodCounts: lod, materials: mats };
4520
4620
  }
4521
- Object.assign(K, { VEG_POT, VEG_CACTUS, VEG_MAP, VEG_PLANTER, vegItem, assembleVegetation });
4621
+ const defined = { VEG_POT, VEG_CACTUS, VEG_MAP, VEG_PLANTER, vegItem, assembleVegetation };
4622
+ Object.assign(K, defined);
4522
4623
  }
4523
4624
 
4524
4625
  // src/interaction/state.ts
4626
+ import { isMesh as isMesh3 } from "@adatechnology/game-shapes-three";
4525
4627
  function installInteractionState(K, shared) {
4526
4628
  const { THREE, cfg, colliderChanged, invalidateShadow, invalidate, UV_SCALE, applyPart, texture } = K;
4527
4629
  const ivRoomEffective = (...a) => K.ivRoomEffective(...a);
@@ -4586,12 +4688,14 @@ function installInteractionState(K, shared) {
4586
4688
  shared.inter.msg = { text, until: performance.now() + MESSAGE_MS };
4587
4689
  if (cfg.onMessage) cfg.onMessage(text);
4588
4690
  };
4589
- function definePiece(name, def) {
4691
+ const I = () => shared.inter;
4692
+ function definePiece(name, definition) {
4693
+ const def = definition;
4590
4694
  def.name = name;
4591
4695
  def.meshes = [];
4592
4696
  def.t = def.target = shared.partState.has(name) ? shared.partState.get(name) : def.t0 || 0;
4593
- shared.inter.defs.set(name, def);
4594
- shared.inter.pieces.push(def);
4697
+ I().defs.set(name, def);
4698
+ I().pieces.push(def);
4595
4699
  return def;
4596
4700
  }
4597
4701
  const localOf = (M, lx, lz) => {
@@ -4603,17 +4707,18 @@ function installInteractionState(K, shared) {
4603
4707
  return true;
4604
4708
  }
4605
4709
  function assembleInteractive(gs) {
4606
- for (const [name, def] of shared.inter.defs) {
4710
+ const inter = I();
4711
+ for (const [name, def] of inter.defs) {
4607
4712
  const g = gs[name];
4608
4713
  if (!g) continue;
4609
4714
  delete gs[name];
4610
4715
  const outer = new THREE.Group();
4611
- outer.position.set(...def.pivot);
4716
+ outer.position.fromArray(def.pivot);
4612
4717
  outer.rotation.y = def.ry || 0;
4613
4718
  outer.updateMatrix();
4614
- const inv = new THREE.Matrix4().compose(new THREE.Vector3(...def.pivot), new THREE.Quaternion().setFromAxisAngle(_EY, def.ry || 0), _UM3).invert();
4719
+ const inv = new THREE.Matrix4().compose(new THREE.Vector3().fromArray(def.pivot), new THREE.Quaternion().setFromAxisAngle(_EY, def.ry || 0), _UM3).invert();
4615
4720
  g.traverse((o) => {
4616
- if (o.isMesh) {
4721
+ if (isMesh3(o)) {
4617
4722
  o.geometry.applyMatrix4(inv);
4618
4723
  o.userData.piece = def;
4619
4724
  def.meshes.push(o);
@@ -4625,13 +4730,14 @@ function installInteractionState(K, shared) {
4625
4730
  const parent = def.leaf ? def.leaf.gs[def.k] : gs[def.parent] || (gs[def.parent] = new THREE.Group());
4626
4731
  if (parent) parent.add(outer);
4627
4732
  if (def.roomId) {
4628
- if (!shared.inter.lights.has(def.roomId)) shared.inter.lights.set(def.roomId, []);
4629
- shared.inter.lights.get(def.roomId).push(def);
4733
+ let lamps = inter.lights.get(def.roomId);
4734
+ if (!lamps) inter.lights.set(def.roomId, lamps = []);
4735
+ lamps.push(def);
4630
4736
  }
4631
4737
  applyPiece(def);
4632
4738
  }
4633
- for (const roomId of shared.inter.litRooms) applyLight(roomId);
4634
- shared.inter.defs.forEach((d) => {
4739
+ for (const roomId of inter.litRooms) applyLight(roomId);
4740
+ inter.defs.forEach((d) => {
4635
4741
  if (d.col) d.col.off = d.t > 0.5;
4636
4742
  });
4637
4743
  }
@@ -4639,6 +4745,7 @@ function installInteractionState(K, shared) {
4639
4745
  const n = p.inner;
4640
4746
  if (!n) return;
4641
4747
  switch (p.kind) {
4748
+ /* each kind always sets its dimensions (sgn, angle, travel, k, axis) */
4642
4749
  case "swing":
4643
4750
  n.rotation.y = p.sgn * p.t * p.angle;
4644
4751
  break;
@@ -4671,8 +4778,9 @@ function installInteractionState(K, shared) {
4671
4778
  }
4672
4779
  const DURATION = { swing: 0.55, drawer: 0.4, curtain: 0.9, gate_swing: 0.9, gate_tilt: 1.4, gate_slide: 1.6, lightSwitch: 0.12, part: 0.4 };
4673
4780
  function animateInteractive(dt) {
4674
- if (!shared.inter.anim.size) return;
4675
- for (const p of shared.inter.anim) {
4781
+ const inter = I();
4782
+ if (!inter.anim.size) return;
4783
+ for (const p of inter.anim) {
4676
4784
  const step = dt / (DURATION[p.kind] || 0.5), d = p.target - p.t;
4677
4785
  p.t = Math.abs(d) <= step ? p.target : p.t + Math.sign(d) * step;
4678
4786
  applyPiece(p);
@@ -4680,7 +4788,7 @@ function installInteractionState(K, shared) {
4680
4788
  p.col.off = p.target > 0.5;
4681
4789
  colliderChanged(p.col);
4682
4790
  }
4683
- if (p.t === p.target) shared.inter.anim.delete(p);
4791
+ if (p.t === p.target) inter.anim.delete(p);
4684
4792
  }
4685
4793
  invalidateShadow();
4686
4794
  }
@@ -4691,7 +4799,7 @@ function installInteractionState(K, shared) {
4691
4799
  p.col.off = p.target > 0.5;
4692
4800
  colliderChanged(p.col);
4693
4801
  }
4694
- shared.inter.anim.add(p);
4802
+ I().anim.add(p);
4695
4803
  }
4696
4804
  const lightBase = (roomId) => roomId == null ? true : shared.partState.has("light:" + roomId) ? !!shared.partState.get("light:" + roomId) : !!shared.ctx.night;
4697
4805
  const lightOn = (roomId) => {
@@ -4699,20 +4807,21 @@ function installInteractionState(K, shared) {
4699
4807
  return S ? S.ef : lightBase(roomId);
4700
4808
  };
4701
4809
  function applyLight(roomId) {
4702
- const on = lightOn(roomId);
4703
- for (const d of shared.inter.lights.get(roomId) || []) for (const m of d.meshes) if (m.name.endsWith("/emissive")) m.material = on ? shared.mats.emissive : shared.mats.off;
4704
- const sw = shared.inter.defs.get("ix:int:" + roomId);
4810
+ const on = lightOn(roomId), inter = I(), mats = shared.mats;
4811
+ for (const d of inter.lights.get(roomId) || []) for (const m of d.meshes) if (m.name.endsWith("/emissive")) m.material = on ? mats.emissive : mats.off;
4812
+ const sw = inter.defs.get("ix:int:" + roomId);
4705
4813
  if (sw) {
4706
4814
  sw.target = on ? 1 : 0;
4707
- if (sw.t !== sw.target) shared.inter.anim.add(sw);
4815
+ if (sw.t !== sw.target) inter.anim.add(sw);
4708
4816
  }
4709
4817
  invalidate();
4710
4818
  }
4711
4819
  function toggleLight(roomId) {
4712
4820
  const S = shared.ctx.iv && shared.ctx.iv.roomStates.get(roomId);
4713
4821
  if (S) {
4714
- ivRoomLight(shared.ctx.iv, roomId, !S.ef);
4715
- const ef = ivRoomEffective(shared.ctx.iv, S);
4822
+ const IV = shared.ctx.iv;
4823
+ ivRoomLight(IV, roomId, !S.ef);
4824
+ const ef = ivRoomEffective(IV, S);
4716
4825
  if (ef !== S.ef) {
4717
4826
  S.ef = ef;
4718
4827
  applyLight(roomId);
@@ -4724,11 +4833,13 @@ function installInteractionState(K, shared) {
4724
4833
  applyLight(roomId);
4725
4834
  if (cfg.onLight) cfg.onLight(roomId, lightOn(roomId));
4726
4835
  }
4727
- Object.assign(K, { newInteractiveState, MESSAGE_MS, createInteractiveMaterials, _EY, _UM3, hudMessage, definePiece, localOf, visibleChain, assembleInteractive, applyPiece, DURATION, animateInteractive, togglePiece, lightBase, lightOn, applyLight, toggleLight });
4836
+ const defined = { newInteractiveState, MESSAGE_MS, createInteractiveMaterials, _EY, _UM3, hudMessage, definePiece, localOf, visibleChain, assembleInteractive, applyPiece, DURATION, animateInteractive, togglePiece, lightBase, lightOn, applyLight, toggleLight };
4837
+ Object.assign(K, defined);
4728
4838
  }
4729
4839
 
4730
4840
  // src/interaction/collision.ts
4731
4841
  function installInteractionCollision(K, shared) {
4842
+ const inter = () => shared.inter;
4732
4843
  const NO_COLLIDE = /(^|_)(rug|floor|concrete|dirt|lawn|deck|ceiling_light|pendant|chandelier|spot|picture|curtain|blinds|wall_shelving|plank_shelf|wall_ac|ac_condenser|pool|soaking_tub|pergola|stairs|mirror)/;
4733
4844
  function registerCollision(m, M) {
4734
4845
  const h = m.h || 0, y = M.y || 0;
@@ -4738,7 +4849,7 @@ function installInteractionCollision(K, shared) {
4738
4849
  w = Math.min(w, 0.5);
4739
4850
  d = Math.min(d, 0.5);
4740
4851
  }
4741
- shared.inter.objs.push({ f: M.floor, cx: m.x, cz: m.z, c: Math.cos(M.ry), s: Math.sin(M.ry), hw: w / 2, hd: d / 2, type: m.type });
4852
+ inter().objs.push({ f: M.floor, cx: m.x, cz: m.z, c: Math.cos(M.ry), s: Math.sin(M.ry), hw: w / 2, hd: d / 2, type: m.type });
4742
4853
  }
4743
4854
  function objectDistance(o, x, z) {
4744
4855
  const dx = x - o.cx, dz = z - o.cz, lx = dx * o.c - dz * o.s, lz = dx * o.s + dz * o.c, ex = Math.abs(lx) - o.hw, ez = Math.abs(lz) - o.hd;
@@ -4746,7 +4857,7 @@ function installInteractionCollision(K, shared) {
4746
4857
  }
4747
4858
  function collideObject(x, z, fx, fz, floor) {
4748
4859
  const R = 0.2;
4749
- for (const o of shared.inter.objs) {
4860
+ for (const o of inter().objs) {
4750
4861
  if (o.f !== -1 ? o.f !== floor : floor !== 0) continue;
4751
4862
  const d1 = objectDistance(o, x, z);
4752
4863
  if (d1 < R && d1 < objectDistance(o, fx, fz) - 1e-6) return true;
@@ -4766,7 +4877,8 @@ function installInteractionCollision(K, shared) {
4766
4877
  const de = opt.from || [x + 1e4, z + 1e4];
4767
4878
  return collideObject(x, z, de[0], de[1], floor);
4768
4879
  }
4769
- Object.assign(K, { NO_COLLIDE, registerCollision, objectDistance, collideObject, collideAt });
4880
+ const defined = { NO_COLLIDE, registerCollision, objectDistance, collideObject, collideAt };
4881
+ Object.assign(K, defined);
4770
4882
  }
4771
4883
 
4772
4884
  // src/interaction/items.ts
@@ -4775,6 +4887,7 @@ function installInteractionItems(K, shared) {
4775
4887
  const DOOR_ITEM = /^(tv_unit|tv_unit_small|tv_unit_large|sideboard|china_cabinet|filing_cabinet|pantry|laundry_cabinet|wardrobe|wardrobe_small|wardrobe_large|closet_wardrobe|kitchen_cabinet|kitchen_cabinet_large|kitchen_cabinet_small|fridge|fridge_large|display_fridge_medium|display_fridge)$/;
4776
4888
  const DRAWER_ITEM = /^(console_table|dresser|nightstand|vanity_table)$/;
4777
4889
  const LIGHT_TYPES = /* @__PURE__ */ new Set(["ceiling_light", "pendant", "chandelier", "track_spot", "hanging_plant"]);
4890
+ const I = () => shared.inter;
4778
4891
  function objectName(type, drawer) {
4779
4892
  return drawer ? "drawer" : /^wardrobe/.test(type) ? "wardrobe" : /fridge|refrig|freezer/.test(type) ? "fridge" : /pantry/.test(type) ? "pantry" : "cabinet";
4780
4893
  }
@@ -4803,8 +4916,8 @@ function installInteractionItems(K, shared) {
4803
4916
  cursor.group = parent;
4804
4917
  }
4805
4918
  for (let i = n0; i < LIGHTS.length; i++) LIGHTS[i].roomId = m.room;
4806
- if (!shared.inter.defs.has(name)) definePiece(name, { kind: "light", pivot: [0, 0, 0], ry: 0, parent, roomId: m.room });
4807
- shared.inter.litRooms.add(m.room);
4919
+ if (!I().defs.has(name)) definePiece(name, { kind: "light", pivot: [0, 0, 0], ry: 0, parent, roomId: m.room });
4920
+ I().litRooms.add(m.room);
4808
4921
  }
4809
4922
  function curtainItem(m, M, ent, api, parent) {
4810
4923
  M.open = false;
@@ -4832,12 +4945,13 @@ function installInteractionItems(K, shared) {
4832
4945
  for (const c of body) api[c[0]](M, ...c[1]);
4833
4946
  if (!parts.length) return;
4834
4947
  const [ax, az] = localOf(M, 0, 0.2);
4835
- shared.inter.items.push({ type: "curtain", id: m.id, floor: M.floor, anchor: [ax, M.base + (M.y || 0) + (m.h || 2) * 0.5, az], range: 2.4, angle: 1, pieces: parts, text: () => t(parts[0].target > 0.5 ? "prompt.close" : "prompt.open", { what: t("what.curtain") }), action: () => {
4836
- const al = parts[0].target > 0.5 ? 0 : 1;
4948
+ const first = parts[0];
4949
+ I().items.push({ type: "curtain", id: m.id, floor: M.floor, anchor: [ax, M.base + (M.y || 0) + (m.h || 2) * 0.5, az], range: 2.4, angle: 1, pieces: parts, text: () => t(first.target > 0.5 ? "prompt.close" : "prompt.open", { what: t("what.curtain") }), action: () => {
4950
+ const al = first.target > 0.5 ? 0 : 1;
4837
4951
  for (const p of parts) {
4838
4952
  p.target = al;
4839
4953
  shared.partState.set(p.name, al);
4840
- shared.inter.anim.add(p);
4954
+ I().anim.add(p);
4841
4955
  }
4842
4956
  } });
4843
4957
  }
@@ -4858,7 +4972,7 @@ function installInteractionItems(K, shared) {
4858
4972
  calls.forEach((c, i) => {
4859
4973
  if (owner.has(i)) return;
4860
4974
  const a = c[1];
4861
- let x0, x1, y0, y1, ok = false, grip = 0, wide = false;
4975
+ let x0 = 0, x1 = 0, y0 = 0, y1 = 0, ok = false, grip = 0, wide = false;
4862
4976
  if (c[0] === "box") {
4863
4977
  const [mat, x, y, z, w, h, d, , ry, rx, rz] = a;
4864
4978
  if (ry || rx || rz || d > 0.05 || z + d / 2 < front - 5e-3 || w > M.w * 1.01) return;
@@ -4890,8 +5004,9 @@ function installInteractionItems(K, shared) {
4890
5004
  return;
4891
5005
  }
4892
5006
  candidate.sort((p, q) => overlap(x0, x1, q.x0, q.x1) - overlap(x0, x1, p.x0, p.x1));
4893
- owner.set(i, candidate[0]);
4894
- if (grip) candidate[0].grip = grip;
5007
+ const best = candidate[0];
5008
+ owner.set(i, best);
5009
+ if (grip) best.grip = grip;
4895
5010
  });
4896
5011
  const name = objectName(m.type, drawer), parts = [];
4897
5012
  panels.forEach((p, k) => {
@@ -4907,8 +5022,8 @@ function installInteractionItems(K, shared) {
4907
5022
  p.def = def;
4908
5023
  parts.push(def);
4909
5024
  const [ax, az] = localOf(M, cx, front + 0.08);
4910
- shared.inter.items.push({ type: drawer ? "drawer" : "cabinet", id: m.id, floor: M.floor, anchor: [ax, M.base + (M.y || 0) + (p.y0 + p.y1) / 2, az], range: 1.6, angle: 0.4, pieces: [def], text: () => t(def.target > 0.5 ? "prompt.close" : "prompt.open", { what: t("what." + name) }), action: () => togglePiece(def) });
4911
- def.item = shared.inter.items[shared.inter.items.length - 1];
5025
+ I().items.push({ type: drawer ? "drawer" : "cabinet", id: m.id, floor: M.floor, anchor: [ax, M.base + (M.y || 0) + (p.y0 + p.y1) / 2, az], range: 1.6, angle: 0.4, pieces: [def], text: () => t(def.target > 0.5 ? "prompt.close" : "prompt.open", { what: t("what." + name) }), action: () => togglePiece(def) });
5026
+ def.item = I().items[I().items.length - 1];
4912
5027
  });
4913
5028
  calls.forEach((c, i) => {
4914
5029
  const p = owner.get(i);
@@ -4922,14 +5037,17 @@ function installInteractionItems(K, shared) {
4922
5037
  }
4923
5038
  cursor.group = parent;
4924
5039
  }
4925
- Object.assign(K, { DOOR_ITEM, DRAWER_ITEM, LIGHT_TYPES, objectName, recordApi, buildItem, lightItem, curtainItem, furnitureItem });
5040
+ const defined = { DOOR_ITEM, DRAWER_ITEM, LIGHT_TYPES, objectName, recordApi, buildItem, lightItem, curtainItem, furnitureItem };
5041
+ Object.assign(K, defined);
4926
5042
  }
4927
5043
 
4928
5044
  // src/interaction/fittings.ts
4929
5045
  function installInteractionFittings(K, shared) {
4930
5046
  const { t, EPS, OPEN_AREA, Y0, applyPiece, bx, cursor, definePiece, gates, lightOn, roomAt, slideDirection, toggleLight, togglePiece } = K;
5047
+ const I = () => shared.inter;
5048
+ const house = () => shared.ctx.r;
4931
5049
  function gatesInteractive() {
4932
- const lt = shared.ctx.r.lot;
5050
+ const lt = house().lot;
4933
5051
  if (!lt) return;
4934
5052
  const cz0 = (lt.rect[1] + lt.rect[3]) / 2;
4935
5053
  const orig = K.getBx(), gs = lt.gates, opening = gs.map((g) => g.open), reg = gs.map((g) => {
@@ -4949,9 +5067,9 @@ function installInteractionFittings(K, shared) {
4949
5067
  return;
4950
5068
  }
4951
5069
  }
4952
- return orig(mat, x0, y0, z0, x1, y1, z1, color);
5070
+ orig(mat, x0, y0, z0, x1, y1, z1, color);
4953
5071
  });
4954
- const n0 = shared.ctx.colliders.length;
5072
+ const colliders = shared.ctx.colliders, n0 = colliders.length;
4955
5073
  try {
4956
5074
  gs.forEach((g) => {
4957
5075
  g.open = false;
@@ -4963,7 +5081,7 @@ function installInteractionFittings(K, shared) {
4963
5081
  g.open = opening[i];
4964
5082
  });
4965
5083
  }
4966
- const cols = shared.ctx.colliders.slice(n0), cz = (lt.rect[1] + lt.rect[3]) / 2, cu = (lt.rect[0] + lt.rect[2]) / 2;
5084
+ const cols = colliders.slice(n0), cz = (lt.rect[1] + lt.rect[3]) / 2, cu = (lt.rect[0] + lt.rect[2]) / 2;
4967
5085
  reg.forEach((r, i) => {
4968
5086
  const g = r.g;
4969
5087
  if (!isFinite(r.x0)) return;
@@ -4972,25 +5090,25 @@ function installInteractionFittings(K, shared) {
4972
5090
  const p = ped ? definePiece(name, Object.assign(base, { kind: "gate_swing", pivot: [r.x0, 0, g.v], angle: -sd * 1.65 })) : tilt ? definePiece(name, Object.assign(base, { kind: "gate_tilting", pivot: [(r.x0 + r.x1) / 2, r.y1, g.v], angle: -sd * 1.45 })) : definePiece(name, Object.assign(base, { kind: "gate_sliding", pivot: [r.x0, 0, r.zm], travel: r.dx * g.width }));
4973
5091
  if (p.col) p.col.off = p.target > 0.5;
4974
5092
  const text = () => t(p.target > 0.5 ? "prompt.close" : "prompt.open", { what: t(ped ? "what.pedestrianGate" : "what.garageGate") });
4975
- shared.inter.items.push({ type: "gate", id: g.id, floor: -1, anchor: [g.u, 1, g.v + sd * 0.4], range: 2.8, angle: 0.9, pieces: [p], text, action: () => togglePiece(p), noWall: true });
5093
+ I().items.push({ type: "gate", id: g.id, floor: -1, anchor: [g.u, 1, g.v + sd * 0.4], range: 2.8, angle: 0.9, pieces: [p], text, action: () => togglePiece(p), noWall: true });
4976
5094
  });
4977
5095
  }
4978
5096
  function mailboxInteractive() {
4979
- for (const m of shared.ctx.r.items) {
5097
+ for (const m of house().items) {
4980
5098
  if (m.type !== "mailbox") continue;
4981
5099
  const g = shared.ctx.parts && shared.ctx.parts["mailbox_" + m.id];
4982
5100
  if (!g) continue;
4983
5101
  const name = "ix:correio:" + m.id, def = definePiece(name, { kind: "part", pivot: [0, 0, 0], ry: 0, parent: "lot" });
4984
5102
  def.inner = g;
4985
5103
  const fx = Math.sin(m.ry || 0), fz = Math.cos(m.ry || 0), ay = (m.y || 1) + (m.h || 0.3) * 0.4;
4986
- shared.inter.items.push({ type: "mailbox", id: m.id, floor: -1, anchor: [m.x + fx * 0.2, ay, m.z + fz * 0.2], range: 2.2, angle: 0.7, pieces: [def], text: () => t(def.target > 0.5 ? "prompt.close" : "prompt.open", { what: t("what.mailbox") }), action: () => togglePiece(def), noWall: true });
5104
+ I().items.push({ type: "mailbox", id: m.id, floor: -1, anchor: [m.x + fx * 0.2, ay, m.z + fz * 0.2], range: 2.2, angle: 0.7, pieces: [def], text: () => t(def.target > 0.5 ? "prompt.close" : "prompt.open", { what: t("what.mailbox") }), action: () => togglePiece(def), noWall: true });
4987
5105
  applyPiece(def);
4988
5106
  }
4989
5107
  }
4990
5108
  function placeSwitches() {
4991
- const R = shared.ctx.r, used = /* @__PURE__ */ new Set();
5109
+ const R = house(), used = /* @__PURE__ */ new Set();
4992
5110
  for (const c of R.rooms) {
4993
- if (c.type === "void" || OPEN_AREA(c) || !shared.inter.litRooms.has(c.id) || used.has(c.id) || shared.ctx.iv && shared.ctx.iv.switchRooms.has(c.id)) continue;
5111
+ if (c.type === "void" || OPEN_AREA(c) || !I().litRooms.has(c.id) || used.has(c.id) || shared.ctx.iv && shared.ctx.iv.switchRooms.has(c.id)) continue;
4994
5112
  const doors = R.doors.filter((p) => p.floor === c.floor && (p.a === c.id || p.b === c.id));
4995
5113
  doors.sort((p, q) => ((q.exterior ? 1 : 0) - (p.exterior ? 1 : 0)) * (c.type === "living" ? 1 : -1));
4996
5114
  for (const p of doors) if (putSwitch(c, p)) {
@@ -5000,11 +5118,11 @@ function installInteractionFittings(K, shared) {
5000
5118
  }
5001
5119
  }
5002
5120
  function putSwitch(c, p) {
5003
- const R = shared.ctx.r, f = p.floor, alongU = p.axis === "u", L = p.pos, a = p.at - p.width / 2, b = p.at + p.width / 2;
5121
+ const R = house(), f = p.floor, alongU = p.axis === "u", L = p.pos, a = p.at - p.width / 2, b = p.at + p.width / 2;
5004
5122
  const wref = R.walls.find((w) => w.floor === f && w.axis === p.axis && Math.abs((alongU ? w.v0 : w.u0) - L) < EPS), th = wref ? wref.thickness || 0.15 : 0.15;
5005
5123
  const inside = (sd2) => {
5006
5124
  const cc = roomAt(f, alongU ? p.at : L + sd2 * 0.4, alongU ? L + sd2 * 0.4 : p.at);
5007
- return cc && cc.id === c.id;
5125
+ return !!cc && cc.id === c.id;
5008
5126
  };
5009
5127
  const sd = inside(1) ? 1 : inside(-1) ? -1 : 0;
5010
5128
  if (!sd) return false;
@@ -5027,19 +5145,22 @@ function installInteractionFittings(K, shared) {
5027
5145
  const piece = definePiece("ix:int:" + roomId, { kind: "light_switch", pivot: pv, ry: 0, parent: "f" + f, axis: alongU ? "x" : "z", sgn: alongU ? sd : -sd, t0: lightOn(roomId) ? 1 : 0 });
5028
5146
  piece.t = piece.target = lightOn(roomId) ? 1 : 0;
5029
5147
  const an = alongU ? [u, yc, face + sd * 0.12] : [face + sd * 0.12, yc, u];
5030
- shared.inter.items.push({ type: "light_switch", id: roomId, floor: f, anchor: an, range: 1.5, angle: 0.45, pieces: [piece], text: () => t(lightOn(roomId) ? "prompt.lightOff" : "prompt.lightOn"), action: () => toggleLight(roomId) });
5148
+ I().items.push({ type: "light_switch", id: roomId, floor: f, anchor: an, range: 1.5, angle: 0.45, pieces: [piece], text: () => t(lightOn(roomId) ? "prompt.lightOff" : "prompt.lightOn"), action: () => toggleLight(roomId) });
5031
5149
  return true;
5032
5150
  }
5033
5151
  return false;
5034
5152
  }
5035
- Object.assign(K, { gatesInteractive, mailboxInteractive, placeSwitches, putSwitch });
5153
+ const defined = { gatesInteractive, mailboxInteractive, placeSwitches, putSwitch };
5154
+ Object.assign(K, defined);
5036
5155
  }
5037
5156
 
5038
5157
  // src/interaction/doors.ts
5039
5158
  function installInteractionDoors(K, shared) {
5040
5159
  const { t, colliderChanged, invalidateShadow, applyPiece, hudMessage } = K;
5160
+ const leaves = () => shared.ctx.leaves;
5041
5161
  function linkDoorLeaves() {
5042
- for (const fo of shared.ctx.leaves) fo.handles = (fo.handleNames || []).map((n) => shared.inter.defs.get(n)).filter(Boolean);
5162
+ const I = shared.inter;
5163
+ for (const fo of leaves()) fo.handles = (fo.handleNames || []).map((n) => I.defs.get(n)).filter((d) => !!d);
5043
5164
  }
5044
5165
  function handleApply(fo) {
5045
5166
  for (const mc of fo.handles || []) {
@@ -5049,11 +5170,12 @@ function installInteractionDoors(K, shared) {
5049
5170
  }
5050
5171
  function toggleDoor(fo) {
5051
5172
  if (fo.phase === "rattle") return;
5173
+ const col = fo.col;
5052
5174
  if (fo.phase === "handle" || fo.phase === "swing") {
5053
5175
  fo.open = !fo.open;
5054
5176
  shared.doorState.set(fo.id, fo.open);
5055
- fo.col.off = fo.open;
5056
- colliderChanged(fo.col);
5177
+ col.off = fo.open;
5178
+ colliderChanged(col);
5057
5179
  fo.anim = true;
5058
5180
  fo.phase = "swing";
5059
5181
  return;
@@ -5067,8 +5189,8 @@ function installInteractionDoors(K, shared) {
5067
5189
  }
5068
5190
  fo.open = !fo.open;
5069
5191
  shared.doorState.set(fo.id, fo.open);
5070
- fo.col.off = fo.open;
5071
- colliderChanged(fo.col);
5192
+ col.off = fo.open;
5193
+ colliderChanged(col);
5072
5194
  fo.anim = true;
5073
5195
  shared.ctx.animateDoorsOn = true;
5074
5196
  if (fo.handles && fo.handles.length) {
@@ -5079,7 +5201,7 @@ function installInteractionDoors(K, shared) {
5079
5201
  function animateDoors(dt) {
5080
5202
  if (!shared.ctx.animateDoorsOn) return;
5081
5203
  let active = false;
5082
- for (const fo of shared.ctx.leaves) {
5204
+ for (const fo of leaves()) {
5083
5205
  if (!fo.phase) continue;
5084
5206
  active = true;
5085
5207
  if (fo.phase === "handle") {
@@ -5099,7 +5221,7 @@ function installInteractionDoors(K, shared) {
5099
5221
  handleApply(fo);
5100
5222
  if (fo.hT <= 0) fo.phase = null;
5101
5223
  } else if (fo.phase === "rattle") {
5102
- fo.jig -= dt;
5224
+ fo.jig = (fo.jig ?? 0) - dt;
5103
5225
  fo.hT = fo.jig > 0 ? 0.55 * Math.abs(Math.sin(fo.jig * 26)) : 0;
5104
5226
  handleApply(fo);
5105
5227
  if (fo.jig <= 0) {
@@ -5113,9 +5235,9 @@ function installInteractionDoors(K, shared) {
5113
5235
  invalidateShadow();
5114
5236
  }
5115
5237
  function wallBlocks(ex, ez, ax, az, floor) {
5116
- const n = shared.ctx.wallColliders != null ? shared.ctx.wallColliders : 0;
5238
+ const n = shared.ctx.wallColliders != null ? shared.ctx.wallColliders : 0, colliders = shared.ctx.colliders;
5117
5239
  for (let i = 0; i < n; i++) {
5118
- const c = shared.ctx.colliders[i];
5240
+ const c = colliders[i];
5119
5241
  if (c.f !== floor && !(c.f === -1 && floor === 0)) continue;
5120
5242
  let t0 = 0, t1 = 1;
5121
5243
  const dx = ax - ex, dz = az - ez;
@@ -5145,7 +5267,8 @@ function installInteractionDoors(K, shared) {
5145
5267
  g.updateMatrix();
5146
5268
  }
5147
5269
  }
5148
- Object.assign(K, { linkDoorLeaves, handleApply, toggleDoor, animateDoors, wallBlocks, doorText, applyLeaf });
5270
+ const defined = { linkDoorLeaves, handleApply, toggleDoor, animateDoors, wallBlocks, doorText, applyLeaf };
5271
+ Object.assign(K, defined);
5149
5272
  }
5150
5273
 
5151
5274
  // src/interaction/target.ts
@@ -5155,6 +5278,7 @@ function installInteractionTarget(K, shared) {
5155
5278
  function targetOf(o, opt) {
5156
5279
  if (!o) return null;
5157
5280
  opt = opt || {};
5281
+ const I = shared.inter;
5158
5282
  const ex = o.x, ey = o.y, ez = o.z, floor = o.floor, cp = Math.cos(o.pitch || 0), vx = Math.sin(o.yaw) * cp, vy = Math.sin(o.pitch || 0), vz = Math.cos(o.yaw) * cp;
5159
5283
  let best = null;
5160
5284
  const tries = (score, text, action, target) => {
@@ -5168,16 +5292,16 @@ function installInteractionTarget(K, shared) {
5168
5292
  if (angle > 1.35 && d > 0.9) continue;
5169
5293
  tries(angle * 1.6 + d * 0.5 + (angle < 0.25 ? 0 : 0.6), doorText(fo), () => toggleDoor(fo), fo);
5170
5294
  }
5171
- const vis = shared.inter.pieces.flatMap((p) => p.meshes).filter(visibleChain), hit = vis.length && opt.strike ? opt.strike(vis) : null;
5295
+ const vis = I.pieces.flatMap((p) => p.meshes).filter(visibleChain), hit = vis.length && opt.strike ? opt.strike(vis) : null;
5172
5296
  const kitA = shared.ctx.iv ? ivTarget(shared.ctx.iv, o, opt && opt.interactives) : null;
5173
5297
  const nearKit = kitA && hit && Math.hypot(kitA.target.pos[0] - ex, kitA.target.pos[1] - ey, kitA.target.pos[2] - ez) < hit.distance + 0.1;
5174
5298
  const pieceHit = hit && !nearKit && hit.object.userData.piece;
5175
- for (const it of shared.inter.items) {
5299
+ for (const it of I.items) {
5176
5300
  if (it.floor !== floor && !(it.floor === -1 && floor === 0)) continue;
5177
5301
  const [ax, ay, az] = it.anchor, dx = ax - ex, dy = ay - ey, dz = az - ez, d = Math.hypot(dx, dy, dz), dh = Math.hypot(dx, dz);
5178
5302
  if (dh > it.range + 0.4) continue;
5179
5303
  const angle = Math.acos(Math.max(-1, Math.min(1, (dx * vx + dy * vy + dz * vz) / (d || 1))));
5180
- const byRay = pieceHit && it.pieces.includes(pieceHit) && hit.distance <= it.range + 0.5;
5304
+ const byRay = !!hit && pieceHit && it.pieces.includes(pieceHit) && hit.distance <= it.range + 0.5;
5181
5305
  if (!byRay && !(dh <= it.range && angle <= it.angle)) continue;
5182
5306
  if (!it.noWall && wallBlocks(ex, ez, ax, az, it.floor < 0 ? 0 : it.floor)) continue;
5183
5307
  tries((byRay ? 0 : angle * 2) + d * 0.3 - (byRay ? 1.5 : 0), it.text(), it.action, it);
@@ -5185,10 +5309,12 @@ function installInteractionTarget(K, shared) {
5185
5309
  if (kitA) tries(kitA.score - (nearKit ? 0.5 : 0), kitA.text, kitA.action, kitA.target);
5186
5310
  return best;
5187
5311
  }
5188
- Object.assign(K, { targetOf });
5312
+ const defined = { targetOf };
5313
+ Object.assign(K, defined);
5189
5314
  }
5190
5315
 
5191
5316
  // src/interactables/bridge.ts
5317
+ import { isMesh as isMesh4 } from "@adatechnology/game-shapes-three";
5192
5318
  function installInteractablesBridge(K, shared) {
5193
5319
  const { t, THREE, invalidate, invalidateShadow, cfg, DOC, LIGHT_TYPES, _Y, _q, _v3, accFor, applyLight, cursor, hashString, hudMessage, lightBase, pieceRecord, put, rgbOf, sh, wallBlocks } = K;
5194
5320
  const enter = (...a) => K.enter(...a);
@@ -5242,7 +5368,8 @@ function installInteractablesBridge(K, shared) {
5242
5368
  function ivBuild(h, water) {
5243
5369
  const ik = K.IVK, r = shared.ctx.r, A = ik.A, world0 = null;
5244
5370
  void world0;
5245
- const plane = A.plan(r, { seed: r.seed });
5371
+ const source = r;
5372
+ const plane = A.plan(source, { seed: r.seed });
5246
5373
  const IV = { k: ik, plane, world: null, water, entries: /* @__PURE__ */ new Map(), roots: [], replace: /* @__PURE__ */ new Set(), roomStates: /* @__PURE__ */ new Map(), lampRoom: /* @__PURE__ */ new Map(), anim: /* @__PURE__ */ new Map(), screens: /* @__PURE__ */ new Map(), efx: null, items: null, itemsDirty: true, itemsT: 0, dirty: true, list: null, listT: 0, t: 0, circuits: [], switchRooms: /* @__PURE__ */ new Set(), warnings: [], tBuild: 0 };
5247
5374
  h.IV = IV;
5248
5375
  const t0 = performance.now();
@@ -5261,9 +5388,10 @@ function installInteractablesBridge(K, shared) {
5261
5388
  const wants = (roomId) => lightBase(roomId);
5262
5389
  const entById = new Map(plane.items.map((e) => [e.id, e]));
5263
5390
  const entByItem = new Map(plane.items.map((e) => [e.item, e]));
5264
- IV.mats = { plain: shared.mats.plain, metal: shared.mats.metal, wood: shared.mats.wood, glass: shared.mats.glass, fabric: shared.mats.fabric, plant: shared.mats.plant, water: shared.mats.water, emissive: shared.mats.emissive, atlas_picture: shared.mats.picture, atlas_floor: shared.mats.floor };
5391
+ const mats = shared.mats;
5392
+ IV.mats = { plain: mats.plain, metal: shared.mats.metal, wood: shared.mats.wood, glass: shared.mats.glass, fabric: shared.mats.fabric, plant: shared.mats.plant, water: shared.mats.water, emissive: shared.mats.emissive, atlas_picture: shared.mats.picture, atlas_floor: shared.mats.floor };
5265
5393
  const ev = (e) => ivEvent(h, e);
5266
- const world = IV.world = A.createWorld(r, { water, seed: r.seed, onEvent: ev });
5394
+ const world = IV.world = A.createWorld(source, { water, seed: r.seed, onEvent: ev });
5267
5395
  const add0 = world.add;
5268
5396
  world.add = (id, spec, tr) => {
5269
5397
  const e = entById.get(id);
@@ -5280,7 +5408,7 @@ function installInteractablesBridge(K, shared) {
5280
5408
  }
5281
5409
  return add0(id, spec, tr);
5282
5410
  };
5283
- const added = A.add(world, plane, { isBlocked: A.blockedOf(r), build: (type, item) => ivDraw(IV, entByItem.get(item), type, item) });
5411
+ const added = A.add(world, plane, { isBlocked: A.blockedOf(source), build: (type, item) => ivDraw(IV, entByItem.get(item), type, item) });
5284
5412
  world.add = add0;
5285
5413
  IV.warnings = added.warnings;
5286
5414
  IV.added = added;
@@ -5327,14 +5455,15 @@ function installInteractablesBridge(K, shared) {
5327
5455
  }
5328
5456
  function ivDraw(IV, ent, type, item) {
5329
5457
  const ik = IV.k, loc = Object.assign({}, item, { x: 0, z: 0, ry: 0 });
5458
+ const ix = item.x, iz = item.z, iry = item.ry;
5330
5459
  const mesh = ik.gfx.createMeshApi({ quality: "game", materials: IV.mats, shadows: true, mergeParts: true, swayAmplitude: 0.03 });
5331
5460
  const spec = ik.A.household.build(type, loc, mesh.api);
5332
5461
  const out = mesh.finish(spec);
5333
5462
  for (const l of out.lights) l.removeFromParent();
5334
5463
  const group = ivGroup(ent), g0 = cursor.group, root = new THREE.Group();
5335
5464
  root.name = "iv:" + ent.id;
5336
- root.position.set(item.x, ent.floorY, item.z);
5337
- root.rotation.y = item.ry;
5465
+ root.position.set(ix, ent.floorY, iz);
5466
+ root.rotation.y = iry;
5338
5467
  root.userData.iv = ent.id;
5339
5468
  const screen = spec.devices && spec.devices.some((d) => d.kind === "screen");
5340
5469
  let body = null;
@@ -5343,7 +5472,7 @@ function installInteractablesBridge(K, shared) {
5343
5472
  if (type === "gas_bottle") {
5344
5473
  cursor.pc = pieceRecord("gas_cylinder:" + ent.id, "steel", null, { floor: ent.floor, mass: 11, form: "cyl", thickness: 3e-3, fill: 0.03, contains: { fluid: "gas", liters: 13, pressurized: true }, explodes: { energy: 12e4, radius: 5, atC: 300 }, tags: ["gas_bottle"] });
5345
5474
  for (const m of out.group.children) if (!m.name.startsWith("static:")) m.traverse((o) => {
5346
- if (o.isMesh) {
5475
+ if (isMesh4(o)) {
5347
5476
  o.userData.destructionPart = cursor.pc.id;
5348
5477
  o.userData.destructionMaterial = "steel";
5349
5478
  }
@@ -5351,13 +5480,13 @@ function installInteractablesBridge(K, shared) {
5351
5480
  }
5352
5481
  try {
5353
5482
  for (const m of out.group.children.slice()) {
5354
- if (m.isMesh && m.name.startsWith("static:")) {
5483
+ if (isMesh4(m) && m.name.startsWith("static:")) {
5355
5484
  if (screen && m.userData.material === "emissive") {
5356
5485
  body = m;
5357
5486
  root.add(m);
5358
5487
  continue;
5359
5488
  }
5360
- ivAccumulate(IV_MATERIAL[m.userData.material] || "plain", m.geometry, item.x, ent.floorY, item.z, item.ry, null);
5489
+ ivAccumulate(IV_MATERIAL[m.userData.material] || "plain", m.geometry, ix, ent.floorY, iz, iry, null);
5361
5490
  m.geometry.dispose();
5362
5491
  } else root.add(m);
5363
5492
  }
@@ -5367,7 +5496,7 @@ function installInteractablesBridge(K, shared) {
5367
5496
  }
5368
5497
  const base = new Set(Object.values(IV.mats));
5369
5498
  root.traverse((o) => {
5370
- if (!o.isMesh) return;
5499
+ if (!isMesh4(o)) return;
5371
5500
  o.userData.iv = ent.id;
5372
5501
  if (o.castShadow) {
5373
5502
  if (!o.geometry.boundingSphere) o.geometry.computeBoundingSphere();
@@ -5378,7 +5507,7 @@ function installInteractablesBridge(K, shared) {
5378
5507
  roomLightMask(m);
5379
5508
  }
5380
5509
  });
5381
- const E = { id: ent.id, type, entry: ent, floor: ent.floor, group, root, parts: out.parts, spec, screen: body, pos: [item.x, ent.floorY, item.z], ry: item.ry, origin: ent.origin };
5510
+ const E = { id: ent.id, type, entry: ent, floor: ent.floor, group, root, parts: out.parts, spec, screen: body, pos: [ix, ent.floorY, iz], ry: iry, origin: ent.origin };
5382
5511
  IV.entries.set(ent.id, E);
5383
5512
  if (root.children.length) IV.roots.push(E);
5384
5513
  return spec;
@@ -5406,7 +5535,7 @@ function installInteractablesBridge(K, shared) {
5406
5535
  const wire = (spec.wires || []).find((x) => x.id === d.id + "_cord"), pts = (wire ? wire.points : [d.plug]).map((p) => wl(o, p));
5407
5536
  const sid = w.power.pluggedInto(E.id, d.id);
5408
5537
  if (sid) {
5409
- const cut = sid.indexOf(":"), so = w.get(sid.slice(0, cut)), sk = so && so.spec.sockets.find((s) => s.id === sid.slice(cut + 1));
5538
+ const cut = sid.indexOf(":"), so = w.get(sid.slice(0, cut)), sk = so && (so.spec.sockets || []).find((s) => s.id === sid.slice(cut + 1));
5410
5539
  if (so && sk) {
5411
5540
  const sp = wl(so, sk.pos), dir = [Math.sin(so.transform.ry), Math.cos(so.transform.ry)], last = pts[pts.length - 1];
5412
5541
  if (last[1] < 0.3 + E.pos[1]) {
@@ -5441,9 +5570,10 @@ function installInteractablesBridge(K, shared) {
5441
5570
  roomLightMask(sc.material);
5442
5571
  IV.screens.set(E.id, sc);
5443
5572
  }
5444
- E.screen.material = sc.material;
5445
- E.screen.castShadow = false;
5446
- E.screen.receiveShadow = false;
5573
+ const mesh = E.screen;
5574
+ mesh.material = sc.material;
5575
+ mesh.castShadow = false;
5576
+ mesh.receiveShadow = false;
5447
5577
  }
5448
5578
  function ivEvent(h, e) {
5449
5579
  const IV = h.IV;
@@ -5479,16 +5609,17 @@ function installInteractablesBridge(K, shared) {
5479
5609
  IV.itemsDirty = true;
5480
5610
  break;
5481
5611
  }
5482
- if (K.IVK.onEvent) {
5612
+ const ik = K.IVK;
5613
+ if (ik.onEvent) {
5483
5614
  try {
5484
- K.IVK.onEvent(e, h.IV.pub);
5615
+ ik.onEvent(e, IV.pub);
5485
5616
  } catch (err) {
5486
5617
  console.warn("interactables.onEvent", err);
5487
5618
  }
5488
5619
  }
5489
- if (e.type === "seat" && K.IVK.onSeat && e.actor === "player") {
5620
+ if (e.type === "seat" && ik.onSeat && e.actor === "player") {
5490
5621
  try {
5491
- K.IVK.onSeat(e.seated ? ivSeat(IV) : null, e);
5622
+ ik.onSeat(e.seated ? ivSeat(IV) : null, e);
5492
5623
  } catch (err) {
5493
5624
  console.warn("interactables.onSeat", err);
5494
5625
  }
@@ -5497,7 +5628,7 @@ function installInteractablesBridge(K, shared) {
5497
5628
  function ivSeat(IV) {
5498
5629
  const w = IV.world, s = w.seatOf("player");
5499
5630
  if (!s) return null;
5500
- const o = w.get(s.object), seat = o.spec.seats.find((q) => q.id === s.seat), L = IV.k.GI.localToWorld, tr = o.transform, E = IV.entries.get(s.object);
5631
+ const o = w.get(s.object), seat = (o.spec.seats || []).find((q) => q.id === s.seat), L = IV.k.GI.localToWorld, tr = o.transform, E = IV.entries.get(s.object);
5501
5632
  const eye = L(tr, [seat.pos[0], seat.pos[1] + (seat.eye === void 0 ? seat.pose === "lie" ? 0.18 : 0.62 : seat.eye), seat.pos[2]]);
5502
5633
  return { object: s.object, seatInfo: s.seat, pose: seat.pose, eye, yaw: tr.ry + seat.ry, pitch: seat.pose === "lie" ? 0.55 : -0.08, exitPoint: L(tr, seat.exit), floor: E ? E.floor : 0, type: E ? E.type : null };
5503
5634
  }
@@ -5539,18 +5670,19 @@ function installInteractablesBridge(K, shared) {
5539
5670
  }
5540
5671
  }
5541
5672
  const em = w.emitters();
5542
- if (em.length && !IV.efx && K.IVK.effects) {
5673
+ const ivk = K.IVK;
5674
+ if (em.length && !IV.efx && ivk.effects) {
5543
5675
  const g = h.houseGroup;
5544
- IV.efx = ik.gfx.createEffects(g, { maxParticles: 1400, seed: 11, document: DOC, ...K.IVK.effectSink ? { effects: K.IVK.effectSink } : {} });
5676
+ IV.efx = ik.gfx.createEffects(g, { maxParticles: 1400, seed: 11, document: DOC, ...ivk.effectSink ? { effects: ivk.effectSink } : {} });
5545
5677
  }
5546
5678
  if (IV.efx) {
5547
5679
  const alive = IV.efx.stats().alive;
5548
5680
  if (em.length || alive) {
5549
- IV.efx.update(dt, em, K.IVK.camera ? typeof K.IVK.camera === "function" ? K.IVK.camera() : K.IVK.camera : void 0);
5681
+ IV.efx.update(dt, em, ivk.camera ? typeof ivk.camera === "function" ? ivk.camera() : ivk.camera : void 0);
5550
5682
  invalidate();
5551
5683
  }
5552
5684
  }
5553
- if (K.IVK.items && IV.itemsDirty && IV.t - IV.itemsT > 0.1 && !IV.anim.size) ivItems(IV, h);
5685
+ if (ivk.items && IV.itemsDirty && IV.t - IV.itemsT > 0.1 && !IV.anim.size) ivItems(IV, h);
5554
5686
  }
5555
5687
  const IV_SHAPE = {
5556
5688
  can: [["cyl", 1, 1, 1, 0, 1]],
@@ -5585,7 +5717,8 @@ function installInteractablesBridge(K, shared) {
5585
5717
  if (c.access && w.partT(E.id, c.access) < 0.02) continue;
5586
5718
  const st = w.contents(E.id, c.id);
5587
5719
  for (let i = 0; i < st.length; i++) {
5588
- if (st[i] && items[st[i].type]) list.push([E, c.id, i, items[st[i].type]]);
5720
+ const stack = st[i];
5721
+ if (stack && items[stack.type]) list.push([E, c.id, i, items[stack.type]]);
5589
5722
  }
5590
5723
  }
5591
5724
  }
@@ -5614,12 +5747,13 @@ function installInteractablesBridge(K, shared) {
5614
5747
  gm.setIndex(new THREE.BufferAttribute(A.i.slice(0, A.ni), 1));
5615
5748
  gm.computeBoundingSphere();
5616
5749
  if (!IV.items) {
5617
- IV.items = new THREE.Mesh(gm, shared.mats.plain);
5618
- IV.items.name = "iv-items";
5619
- IV.items.castShadow = false;
5620
- IV.items.receiveShadow = true;
5621
- IV.items.frustumCulled = false;
5622
- h.houseGroup.add(IV.items);
5750
+ const mesh = new THREE.Mesh(gm, shared.mats.plain);
5751
+ IV.items = mesh;
5752
+ mesh.name = "iv-items";
5753
+ mesh.castShadow = false;
5754
+ mesh.receiveShadow = true;
5755
+ mesh.frustumCulled = false;
5756
+ h.houseGroup.add(mesh);
5623
5757
  } else {
5624
5758
  IV.items.geometry.dispose();
5625
5759
  IV.items.geometry = gm;
@@ -5753,7 +5887,8 @@ function installInteractablesBridge(K, shared) {
5753
5887
  };
5754
5888
  return IV.pub;
5755
5889
  }
5756
- Object.assign(K, { IV_MATERIAL, IV_WIRE, IV_DOOR, ivGroup, ivAccumulate, ivBuild, ivRoomEffective, ivDraw, ivCords, ivAssemble, ivScreen, ivEvent, ivSeat, ivUpdate, IV_SHAPE, ivItems, ivTarget, ivRoomLight, ivParts, ivDispose, ivPublish });
5890
+ const defined = { IV_MATERIAL, IV_WIRE, IV_DOOR, ivGroup, ivAccumulate, ivBuild, ivRoomEffective, ivDraw, ivCords, ivAssemble, ivScreen, ivEvent, ivSeat, ivUpdate, IV_SHAPE, ivItems, ivTarget, ivRoomLight, ivParts, ivDispose, ivPublish };
5891
+ Object.assign(K, defined);
5757
5892
  }
5758
5893
 
5759
5894
  // src/animation/clotheslines.ts
@@ -5778,7 +5913,8 @@ function installAnimationClotheslines(K, shared) {
5778
5913
  }
5779
5914
  invalidate();
5780
5915
  }
5781
- Object.assign(K, { WIND, animateClotheslines });
5916
+ const defined = { WIND, animateClotheslines };
5917
+ Object.assign(K, defined);
5782
5918
  }
5783
5919
 
5784
5920
  // src/build/instance.ts
@@ -5803,7 +5939,8 @@ function installBuildInstance(K, shared) {
5803
5939
  shared.quality = h.quality;
5804
5940
  }
5805
5941
  const tagDamage = (type) => ({ type, hp: HP[type], hpMax: HP[type] });
5806
- Object.assign(K, { props, TYPES, newState, enter, tagDamage });
5942
+ const defined = { props, TYPES, newState, enter, tagDamage };
5943
+ Object.assign(K, defined);
5807
5944
  }
5808
5945
 
5809
5946
  // src/interactables/kit.ts
@@ -5832,17 +5969,20 @@ function installInteractablesKit(K, shared) {
5832
5969
  for (const k of ["wood", "foliage", "flowers", "fruit", "spines"]) roomLightMask(m[k]);
5833
5970
  return m;
5834
5971
  })());
5835
- Object.assign(K, { IVK, VEG, vegMaterials });
5972
+ const defined = { IVK, VEG, vegMaterials };
5973
+ Object.assign(K, defined);
5836
5974
  }
5837
5975
 
5838
5976
  // src/lights/room-light.ts
5977
+ var newGroup = (k, house, exterior) => ({ k, house, ls: [], exterior, pos: [0, 0, 0], color: 0, n: 0, range: 0, rects: [], y: [0, 0], exclusion: null, lumens: 0, dist: 0, decay: 0, floor: 0, roomId: null, dm: 0, d: 0 });
5839
5978
  function installLightsRoomLight(K, shared) {
5840
5979
  const { THREE, rectsOf: rectsOf2, cfg } = K;
5841
5980
  const MAX_LIGHTS = 12, EMPTY = [1e9, 1e9, -1e9, -1e9];
5842
5981
  const LZU = { uRB0: { value: new Float32Array(MAX_LIGHTS * 4) }, uRB1: { value: new Float32Array(MAX_LIGHTS * 4) }, uRB2: { value: new Float32Array(MAX_LIGHTS * 4) }, uRBY: { value: new Float32Array(MAX_LIGHTS * 2) }, uREx: { value: new Float32Array(MAX_LIGHTS * 4) }, uIndK: { value: 0.06 } };
5843
5982
  for (let i = 0; i < MAX_LIGHTS; i++) for (const k of ["uRB0", "uRB1", "uRB2", "uREx"]) LZU[k].value.set(EMPTY, i * 4);
5844
- function roomLightMask(m) {
5845
- if (!m || m.userData && m.userData.roomLightMask || !(m.isMeshLambertMaterial || m.isMeshPhongMaterial || m.isMeshStandardMaterial || m.isMeshPhysicalMaterial)) return m;
5983
+ function roomLightMask(material) {
5984
+ const m = material;
5985
+ if (!m || m.userData && m.userData.roomLightMask || !(m.isMeshLambertMaterial || m.isMeshPhongMaterial || m.isMeshStandardMaterial || m.isMeshPhysicalMaterial)) return material;
5846
5986
  m.userData = m.userData || {};
5847
5987
  m.userData.roomLightMask = true;
5848
5988
  const prev = m.onBeforeCompile, pk = m.customProgramCacheKey;
@@ -5870,12 +6010,13 @@ function installLightsRoomLight(K, shared) {
5870
6010
  return (pk ? pk.call(this) : "") + "|rm1";
5871
6011
  };
5872
6012
  m.needsUpdate = true;
5873
- return m;
6013
+ return material;
5874
6014
  }
5875
- function lighting(o) {
5876
- o = o || {};
6015
+ function lighting(options) {
6016
+ const o = options || {};
5877
6017
  const scene = o.scene, N = Math.max(1, Math.min(MAX_LIGHTS, o.n || 6)), NS = Math.max(0, Math.min(N, o.shadows != null ? o.shadows : 2)), size = o.shadowSize || 512, MAX_EXTERNAL = o.external != null ? o.external : 2;
5878
- for (const k of Object.keys(shared.mats)) roomLightMask(shared.mats[k]);
6018
+ const mats = shared.mats;
6019
+ for (const k of Object.keys(mats)) roomLightMask(mats[k]);
5879
6020
  const budget = o.budget, lease = budget ? budget.lease({ owner: "floorplan.rooms", point: N, shadows: NS }) : null;
5880
6021
  if (budget && !lease) throw new Error("lighting: the LightBudget has no " + N + " free point slots (" + NS + " with shadow) for the rooms");
5881
6022
  if (budget) for (const [key, width] of [["uRB0", 4], ["uRB1", 4], ["uRB2", 4], ["uRBY", 2], ["uREx", 4]]) {
@@ -5926,9 +6067,8 @@ function installLightsRoomLight(K, shared) {
5926
6067
  }
5927
6068
  for (let i = 0; i < NS; i++) PL[i].shadow.needsUpdate = true;
5928
6069
  };
5929
- A.update = function(houses, focus, op) {
5930
- op = op || {};
5931
- houses = (Array.isArray(houses) ? houses : [houses]).filter(Boolean);
6070
+ A.update = function(houseOrList, focus, options2) {
6071
+ const op = options2 || {}, houses = (Array.isArray(houseOrList) ? houseOrList : [houseOrList]).filter((h) => !!h);
5932
6072
  _f.set(focus.x, focus.y, focus.z);
5933
6073
  const rooms = [], exterior = [];
5934
6074
  for (const house of houses) {
@@ -5940,7 +6080,7 @@ function installLightsRoomLight(K, shared) {
5940
6080
  if (!house.lightOn(l.roomId)) continue;
5941
6081
  const k = l.type === "outdoor" ? "ext:" + (l.id || exterior.length) : l.roomId != null ? l.roomId : l.room;
5942
6082
  let g = by.get(k);
5943
- if (!g) by.set(k, g = { k, house, ls: [], exterior: l.type === "outdoor" });
6083
+ if (!g) by.set(k, g = newGroup(k, house, l.type === "outdoor"));
5944
6084
  g.ls.push(l);
5945
6085
  }
5946
6086
  for (const g of by.values()) {
@@ -5975,9 +6115,10 @@ function installLightsRoomLight(K, shared) {
5975
6115
  }
5976
6116
  }
5977
6117
  g.exclusion = [x0 + 0.03, z0 + 0.03, x1 - 0.03, z1 - 0.03];
5978
- g.lumens = ls[0].lumens != null ? ls[0].lumens : 3.2;
5979
- g.dist = ls[0].dist != null ? ls[0].dist : 5.5;
5980
- g.decay = ls[0].decay != null ? ls[0].decay : 2;
6118
+ const l0 = ls[0];
6119
+ g.lumens = l0.lumens != null ? l0.lumens : 3.2;
6120
+ g.dist = l0.dist != null ? l0.dist : 5.5;
6121
+ g.decay = l0.decay != null ? l0.decay : 2;
5981
6122
  } else {
5982
6123
  const c = house.r.rooms.find((q) => q.id === g.k);
5983
6124
  if (!c) continue;
@@ -6078,8 +6219,8 @@ function installLightsRoomLight(K, shared) {
6078
6219
  }
6079
6220
  const effectsByBudget = /* @__PURE__ */ new WeakMap();
6080
6221
  const OPENING_REACH = 2.5, OPENING_SIDE = 0.6;
6081
- function effectLights(o) {
6082
- o = o || {};
6222
+ function effectLights(options) {
6223
+ const o = options || {};
6083
6224
  const budget = o.budget;
6084
6225
  if (!budget) throw new Error("effectLights: a LightBudget is required");
6085
6226
  const known = effectsByBudget.get(budget);
@@ -6157,7 +6298,7 @@ function installLightsRoomLight(K, shared) {
6157
6298
  const A = {
6158
6299
  /** Once per frame, after the budget's `present`: points the mask of every lit slot that is not the house's at the rooms its light reaches. */
6159
6300
  update(houses) {
6160
- const indoors = cfg.effectLightsIndoors !== false, list = (Array.isArray(houses) ? houses : [houses]).filter(Boolean), cache2 = /* @__PURE__ */ new Map();
6301
+ const indoors = cfg.effectLightsIndoors !== false, list = (Array.isArray(houses) ? houses : [houses]).filter((h) => !!h), cache2 = /* @__PURE__ */ new Map();
6161
6302
  for (let at = 0; at < size; at++) {
6162
6303
  if (ours.has(at)) continue;
6163
6304
  const light = budget.group.children[at];
@@ -6185,7 +6326,8 @@ function installLightsRoomLight(K, shared) {
6185
6326
  if (!o.ours) effectsByBudget.set(budget, A);
6186
6327
  return A;
6187
6328
  }
6188
- Object.assign(K, { MAX_LIGHTS, EMPTY, LZU, roomLightMask, lighting, effectLights });
6329
+ const defined = { MAX_LIGHTS, EMPTY, LZU, roomLightMask, lighting, effectLights };
6330
+ Object.assign(K, defined);
6189
6331
  }
6190
6332
 
6191
6333
  // src/destruction/pieces.ts
@@ -7377,10 +7519,11 @@ function installDestructionWorld(K, shared) {
7377
7519
 
7378
7520
  // src/build/build.ts
7379
7521
  import { markKitOrigin } from "@adatechnology/game-contracts";
7522
+ import { isMesh as isMesh5 } from "@adatechnology/game-shapes-three";
7380
7523
  function installBuildBuild(K, shared) {
7381
7524
  const { THREE, cfg, rectsOf: rectsOf2, invalidateShadow, colliderChanged, VERSION: VERSION2, CARS, EPS, LIGHTS, MIRRORS, Y0, animateClotheslines, animateDoors, animateInteractive, applyLeaf, applyOutbuildings, applyPart, applyPiece, assembleInteractive, baseboardAndSidewalk, buildStairs, building, carModel, chooseMirror, closeScene, collideAt, createWater, cursor, doorText, doors, electricalStructure, elevator, floorsAndSlabs, gatesInteractive, houseItems, ivAssemble, ivBuild, ivDispose, ivParts, ivPublish, ivUpdate, lightOn, linkDoorLeaves, mailboxInteractive, newInteractiveState, newMirrorState, outbuildings, paths, perimeter, placeSwitches, roofs, roomAt, solar, targetOf, terrain, toggleDoor, toggleLight, walls, waterPipes, windows, props, TYPES, IVK, VEG, vegMaterials, markGroups, assembleStructure, createHouseDestruction, newState, enter, tagDamage } = K;
7382
- function build(r0, opts) {
7383
- opts = opts || {};
7525
+ function build(r0, options) {
7526
+ const opts = options || {};
7384
7527
  const r = applyOutbuildings(r0);
7385
7528
  const t0 = performance.now();
7386
7529
  const h = { ctx: { mv: props, types: TYPES }, inter: newInteractiveState(), state: opts.state || newState(), mirrors: newMirrorState(), quality: opts.quality === "game" || opts.quality === "high" ? opts.quality : cfg.quality === "game" ? "game" : "high", lodCurrent: 0, lodMin: 0 };
@@ -7401,7 +7544,7 @@ function installBuildBuild(K, shared) {
7401
7544
  shared.ctx.pieces = /* @__PURE__ */ new Map();
7402
7545
  shared.ctx.pieceObjects = /* @__PURE__ */ new Map();
7403
7546
  shared.ctx.structureIndex = {};
7404
- for (const e of r0.structure && r0.structure.parts || []) shared.ctx.structureIndex[e.id] = e;
7547
+ for (const e of r0.structure?.parts || []) shared.ctx.structureIndex[e.id] = e;
7405
7548
  {
7406
7549
  const view = shared.ctx.panelView = panelViewOf(r0.structure, !!cfg.destruction);
7407
7550
  shared.ctx.panelsOf = /* @__PURE__ */ new Map();
@@ -7413,7 +7556,7 @@ function installBuildBuild(K, shared) {
7413
7556
  else shared.ctx.panelsOf.set(e.slab, [e]);
7414
7557
  }
7415
7558
  }
7416
- shared.ctx.panes = r0.roof && r0.roof.panes || [];
7559
+ shared.ctx.panes = r0.roof?.panes || [];
7417
7560
  shared.ctx.noPiece = false;
7418
7561
  cursor.separate = opts.pieces === "meshes";
7419
7562
  cursor.pc = null;
@@ -7424,7 +7567,7 @@ function installBuildBuild(K, shared) {
7424
7567
  shared.ctx.pu = Math.max(0, pr.unit != null ? pr.unit : 0);
7425
7568
  shared.ctx.showBuilding = shared.ctx.apartment && (pr.showIt == null ? true : !!pr.showIt);
7426
7569
  shared.ctx.limits = { x0: -2, z0: -2, x1: r.w + 2, z1: r.d + 2 };
7427
- shared.ctx.veg = VEG ? { G: VEG.G, S: VEG.S, mats: vegMaterials, groups: /* @__PURE__ */ new Map(), ok: /* @__PURE__ */ new Map(), opts: shared.quality === "game" ? { quality: "game" } : { lod: 0, triangleBudget: 6e4 } } : null;
7570
+ shared.ctx.veg = VEG ? { G: VEG.G, S: VEG.S, mats: vegMaterials, groups: /* @__PURE__ */ new Map(), ok: /* @__PURE__ */ new Map(), opts: shared.quality === "game" ? { quality: "game" } : { quality: "high", lod: 0, triangleBudget: 6e4 } } : null;
7428
7571
  shared.ctx.vegInfo = null;
7429
7572
  terrain();
7430
7573
  if (r.lot) {
@@ -7474,7 +7617,7 @@ function installBuildBuild(K, shared) {
7474
7617
  const g = gs[gd.name];
7475
7618
  if (!g) continue;
7476
7619
  delete gs[gd.name];
7477
- g.position.set(...gd.pos);
7620
+ g.position.fromArray(gd.pos);
7478
7621
  parent.add(g);
7479
7622
  fo.gs.push(g);
7480
7623
  }
@@ -7489,7 +7632,7 @@ function installBuildBuild(K, shared) {
7489
7632
  root.add(house);
7490
7633
  shared.mirrors.house = house;
7491
7634
  if (shared.ctx.apartment) {
7492
- const u = r.building.units[Math.min(shared.ctx.pu, r.building.units.length - 1)];
7635
+ const units = r.building.units, u = units[Math.min(shared.ctx.pu, units.length - 1)];
7493
7636
  house.position.set(u.u, shared.ctx.showBuilding ? 0 : -r.floors[0].y0, u.v);
7494
7637
  house.rotation.y = u.ry;
7495
7638
  shared.ctx.unitRy = u.ry;
@@ -7605,7 +7748,8 @@ function installBuildBuild(K, shared) {
7605
7748
  const wallAt = (f, axis, L) => r.walls.find((w) => w.floor === f && w.axis === axis && Math.abs((axis === "u" ? w.v0 : w.u0) - L) < EPS);
7606
7749
  for (const j of r.windows) {
7607
7750
  const alongU = j.axis === "u", y0 = Y0(j.floor), a = j.at - j.width / 2, b = j.at + j.width / 2, w = wallAt(j.floor, j.axis, j.pos), th = w ? w.thickness || 0.15 : 0.15, L = j.pos, id = "window:" + j.id;
7608
- parts[id] = { id, type: "window", group: null, virtual: true, floor: j.floor, aabb: alongU ? [a, y0 + j.y0, L - th / 2, b, y0 + j.y1, L + th / 2] : [L - th / 2, y0 + j.y0, a, L + th / 2, y0 + j.y1, b], damageable: tagDamage("glass"), opens: () => {
7751
+ const jy0 = j.y0, jy1 = j.y1;
7752
+ parts[id] = { id, type: "window", group: null, virtual: true, floor: j.floor, aabb: alongU ? [a, y0 + jy0, L - th / 2, b, y0 + jy1, L + th / 2] : [L - th / 2, y0 + jy0, a, L + th / 2, y0 + jy1, b], damageable: tagDamage("glass"), opens: () => {
7609
7753
  }, t: 0 };
7610
7754
  }
7611
7755
  for (const E of mirrorsCopy) {
@@ -7648,7 +7792,7 @@ function installBuildBuild(K, shared) {
7648
7792
  const countDraw = () => {
7649
7793
  let n = 0, t = 0;
7650
7794
  root.traverseVisible((o) => {
7651
- if (o.isMesh) {
7795
+ if (isMesh5(o)) {
7652
7796
  n++;
7653
7797
  t += (o.geometry.index ? o.geometry.index.count : o.geometry.attributes.position.count) / 3;
7654
7798
  }
@@ -7662,8 +7806,8 @@ function installBuildBuild(K, shared) {
7662
7806
  const budget = opts.drawCallBudget != null ? opts.drawCallBudget : cfg.drawCallBudget;
7663
7807
  const stats = { quality: h.quality, drawCalls: s0.n, drawCallsLOD1: s1.n, triangles: s0.t, trianglesLod1: s1.t, budget: budget || null, overBudget: !!budget && s0.n > budget, tBuild: performance.now() - t0 };
7664
7808
  shared.ctx.tBuild = stats.tBuild;
7665
- const applyLod = (n) => {
7666
- n = Math.max(0, Math.min(2, n | 0));
7809
+ const applyLod = (level) => {
7810
+ const n = Math.max(0, Math.min(2, level | 0));
7667
7811
  if (n === h.lodCurrent) return;
7668
7812
  h.lodCurrent = n;
7669
7813
  for (const o of lodObjects) o.visible = n < 1;
@@ -7740,7 +7884,7 @@ function installBuildBuild(K, shared) {
7740
7884
  lights: (() => {
7741
7885
  const by = {};
7742
7886
  for (const l of shared.ctx.lights) {
7743
- const k = l.roomId != null ? l.roomId : l.room;
7887
+ const k = String(l.roomId != null ? l.roomId : l.room);
7744
7888
  (by[k] || (by[k] = [])).push(l);
7745
7889
  }
7746
7890
  return { list: shared.ctx.lights, byRoom: by };
@@ -7780,9 +7924,9 @@ function installBuildBuild(K, shared) {
7780
7924
  applyLod(Math.max(n, h.lodMin));
7781
7925
  }
7782
7926
  },
7783
- show(o) {
7927
+ show(options2) {
7784
7928
  enter(h);
7785
- o = o || {};
7929
+ const o = options2 || {};
7786
7930
  const rr = shared.ctx.r, nA = rr.floors.length, a = o.floor == null ? -1 : o.floor, sel = a >= nA ? -1 : a, cut = !!o.cut;
7787
7931
  for (const [k, g] of Object.entries(gs)) {
7788
7932
  let v = true;
@@ -7802,7 +7946,7 @@ function installBuildBuild(K, shared) {
7802
7946
  enter(h);
7803
7947
  const a = targetOf(o, opt);
7804
7948
  if (!a) return false;
7805
- return actOn(a.target && a.target.pub ? a.target.pub : { id: a.target && a.target.id || a.text, type: a.target && a.target.kit ? a.target.type : "door", label: a.text, ref: a.target, _action: a.action }, a);
7949
+ return actOn(a.target && a.target.pub ? a.target.pub : { id: a.target && a.target.id || a.text, type: a.target && a.target.kit ? a.target.type : "door", label: a.text, ref: a.target, _action: a.action, floor: 0, pos: [], radius: 0 }, a);
7806
7950
  },
7807
7951
  message() {
7808
7952
  return shared.inter.msg && performance.now() < shared.inter.msg.until ? shared.inter.msg.text : null;
@@ -7859,13 +8003,13 @@ function installBuildBuild(K, shared) {
7859
8003
  }
7860
8004
  return null;
7861
8005
  },
7862
- partAt(p, tol) {
7863
- tol = tol || 0.05;
8006
+ partAt(p, tolerance) {
8007
+ const tol = tolerance || 0.05;
7864
8008
  let m = null;
7865
8009
  for (const k in parts) {
7866
- const a = parts[k].aabb;
8010
+ const part = parts[k], a = part.aabb;
7867
8011
  if (a && p.x >= a[0] - tol && p.x <= a[3] + tol && p.y >= a[1] - tol && p.y <= a[4] + tol && p.z >= a[2] - tol && p.z <= a[5] + tol) {
7868
- m = parts[k];
8012
+ m = part;
7869
8013
  break;
7870
8014
  }
7871
8015
  }
@@ -7876,8 +8020,8 @@ function installBuildBuild(K, shared) {
7876
8020
  destruction.deactivate();
7877
8021
  if (h.IV) ivDispose(h);
7878
8022
  root.traverse((o) => {
7879
- if (o.isMesh && o.geometry && !o.geometry.userData.shared) o.geometry.dispose();
7880
- if (o.type === "Reflector" && o.dispose) o.dispose();
8023
+ if (isMesh5(o) && o.geometry && !o.geometry.userData.shared) o.geometry.dispose();
8024
+ if (o.type === "Reflector" && "dispose" in o && typeof o.dispose === "function") o.dispose();
7881
8025
  });
7882
8026
  root.removeFromParent();
7883
8027
  },
@@ -7885,7 +8029,8 @@ function installBuildBuild(K, shared) {
7885
8029
  };
7886
8030
  return res;
7887
8031
  }
7888
- Object.assign(K, { build });
8032
+ const defined = { build };
8033
+ Object.assign(K, defined);
7889
8034
  }
7890
8035
 
7891
8036
  // src/build/api.ts
@@ -7907,11 +8052,13 @@ function buildApi(K, shared) {
7907
8052
  lighting,
7908
8053
  effectLights,
7909
8054
  setNight(n) {
7910
- shared.mats.glass.emissive.set(n ? 9067040 : 0);
7911
- shared.mats.glass.opacity = n ? 0.4 : 0.24;
8055
+ const glass = shared.mats.glass;
8056
+ glass.emissive.set(n ? 9067040 : 0);
8057
+ glass.opacity = n ? 0.4 : 0.24;
7912
8058
  },
7913
8059
  /** The chipped-plaster painting of every house of this renderer as a `DeferredQueue` for a frame budget (id `floorplan.breach-paint`); asking for it changes nothing. */
7914
8060
  deferredQueue: () => K.breachPaintQueue,
8061
+ /* the destruction side is typed with the breach */
7915
8062
  cars: { model: carModel, group: carGroup, info: (k, seed) => {
7916
8063
  const m = carModel(k, seed);
7917
8064
  return m && { parts: m.parts.length, tris: m.tris, L: m.L, W: m.W, H: m.H };
@@ -8176,7 +8323,7 @@ function createHouseScenarios(text, at = SPECIMEN_AT) {
8176
8323
  const stopListening = () => {
8177
8324
  for (const off of listening.splice(0)) off?.();
8178
8325
  };
8179
- const collapsed = (list) => list.filter((e) => e.type === "collapse").flatMap((e) => e.parts.map((p) => p.id || p));
8326
+ const collapsed = (list) => list.flatMap((e) => e.type === "collapse" ? e.parts.map((p) => p.id || p) : []);
8180
8327
  const whole = (room, oid, pid) => {
8181
8328
  const p = room.world.part(oid, pid);
8182
8329
  return !!p && p.status !== "broken" && !p.stripped;
@@ -8537,9 +8684,10 @@ function createFloorplanTestModule(options = {}) {
8537
8684
  return best;
8538
8685
  };
8539
8686
  const eyeOf = (p) => {
8687
+ const T = THREE;
8540
8688
  const camera = host?.camera;
8541
8689
  const at = toLocal(p, camera.position.x, camera.position.y, camera.position.z);
8542
- const forward = new THREE.Vector3(0, 0, -1).applyQuaternion(camera.quaternion).transformDirection(new THREE.Matrix4().copy(p.house.group.matrixWorld).invert());
8690
+ const forward = new T.Vector3(0, 0, -1).applyQuaternion(camera.quaternion).transformDirection(new T.Matrix4().copy(p.house.group.matrixWorld).invert());
8543
8691
  return { x: at.x, y: at.y, z: at.z, floor: floorOf(p, camera.position.y), yaw: Math.atan2(forward.x, forward.z), pitch: Math.asin(Math.max(-1, Math.min(1, forward.y))) };
8544
8692
  };
8545
8693
  const blocked = (x, z, radius) => {
@@ -8555,8 +8703,9 @@ function createFloorplanTestModule(options = {}) {
8555
8703
  const standAt = (p, u, v, floor, lookU, lookV) => {
8556
8704
  if (!host?.bench) return;
8557
8705
  const y = p.house.y0(floor) + EYE;
8558
- const eye = p.house.group.localToWorld(new THREE.Vector3(u, y, v));
8559
- const target = p.house.group.localToWorld(new THREE.Vector3(lookU, y - 0.1, lookV));
8706
+ const T = THREE;
8707
+ const eye = p.house.group.localToWorld(new T.Vector3(u, y, v));
8708
+ const target = p.house.group.localToWorld(new T.Vector3(lookU, y - 0.1, lookV));
8560
8709
  host.bench.look([eye.x, eye.y, eye.z], [target.x, target.y, target.z]);
8561
8710
  floorNow = floor;
8562
8711
  };
@@ -8606,16 +8755,17 @@ function createFloorplanTestModule(options = {}) {
8606
8755
  host?.log(fill(text.steps.door, { text: String(target.text) }));
8607
8756
  };
8608
8757
  const doorReach = (p, fo) => {
8758
+ const T = THREE;
8609
8759
  const g = fo.gs[0];
8610
8760
  const pivot = fo.handles[0].pivot;
8611
8761
  const at = (angle) => {
8612
8762
  const c = Math.cos(angle);
8613
8763
  const s = Math.sin(angle);
8614
- const v = new THREE.Vector3(pivot[0] * c + pivot[2] * s, pivot[1], -pivot[0] * s + pivot[2] * c).add(g.position);
8764
+ const v = new T.Vector3(pivot[0] * c + pivot[2] * s, pivot[1], -pivot[0] * s + pivot[2] * c).add(g.position);
8615
8765
  return g.parent ? g.parent.localToWorld(v) : v;
8616
8766
  };
8617
8767
  const camera = host?.camera;
8618
- const eye = new THREE.Vector3(camera.position.x, 0, camera.position.z);
8768
+ const eye = new T.Vector3(camera.position.x, 0, camera.position.z);
8619
8769
  const flat = (v) => Math.hypot(v.x - eye.x, v.z - eye.z);
8620
8770
  const closed = at(0);
8621
8771
  const open = at(fo.rot);
@@ -8623,9 +8773,9 @@ function createFloorplanTestModule(options = {}) {
8623
8773
  return {
8624
8774
  handle: () => {
8625
8775
  g.updateMatrixWorld(true);
8626
- return g.localToWorld(new THREE.Vector3(pivot[0], pivot[1], pivot[2])).toArray();
8776
+ return g.localToWorld(new T.Vector3(pivot[0], pivot[1], pivot[2])).toArray();
8627
8777
  },
8628
- hinge: () => g.getWorldPosition(new THREE.Vector3()).toArray(),
8778
+ hinge: () => g.getWorldPosition(new T.Vector3()).toArray(),
8629
8779
  seconds: fo.locked || fo.blockedFlag ? 0.6 : 0.55,
8630
8780
  pull: opening ? flat(open) <= flat(closed) : flat(closed) <= flat(open),
8631
8781
  locked: !!(fo.locked || fo.blockedFlag)
@@ -8959,4 +9109,4 @@ export {
8959
9109
  FLOORPLAN_AREA_ID,
8960
9110
  createFloorplanTestModule
8961
9111
  };
8962
- //# sourceMappingURL=chunk-7XVCZF6H.js.map
9112
+ //# sourceMappingURL=chunk-Y3Y7NYOL.js.map