@adatechnology/game-vegetation-three 0.3.0 → 0.3.2

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.
@@ -41,7 +41,7 @@ var GameVegetationThree = (() => {
41
41
  scatterLot: () => scatterLot
42
42
  });
43
43
 
44
- // ../game-shapes/dist/chunk-IFXQIDSA.js
44
+ // ../game-shapes/dist/chunk-M5N2SHNL.js
45
45
  function canonicalJson(value) {
46
46
  if (value === null) return "null";
47
47
  if (typeof value === "number") return Object.is(value, -0) ? "-0" : Number.isFinite(value) ? String(value) : JSON.stringify(String(value));
@@ -1288,8 +1288,8 @@ var GameVegetationThree = (() => {
1288
1288
  groups: []
1289
1289
  };
1290
1290
  }
1291
- function make(kind, p) {
1292
- switch (kind) {
1291
+ function make(p) {
1292
+ switch (p.kind) {
1293
1293
  case "box": {
1294
1294
  const size = p.size ?? [1, 1, 1];
1295
1295
  const segments = p.segments ?? [1, 1, 1];
@@ -1318,7 +1318,7 @@ var GameVegetationThree = (() => {
1318
1318
  case "mesh":
1319
1319
  return mesh(p);
1320
1320
  default:
1321
- throw new Error(`game-shapes: unknown primitive kind "${String(kind)}"`);
1321
+ throw new Error(`game-shapes: unknown primitive kind "${String(p.kind)}"`);
1322
1322
  }
1323
1323
  }
1324
1324
  var templates = /* @__PURE__ */ new Map();
@@ -1326,7 +1326,7 @@ var GameVegetationThree = (() => {
1326
1326
  var stats = { hits: 0, misses: 0 };
1327
1327
  function buildPrimitive(node, options = {}) {
1328
1328
  const parameters = primitiveParameters(node, options);
1329
- if (node.kind === "mesh" || templateLimit === 0) return make(node.kind, parameters);
1329
+ if (node.kind === "mesh" || templateLimit === 0) return make({ ...node, ...parameters });
1330
1330
  const key = `${node.kind}:${canonicalJson(parameters)}`;
1331
1331
  const cached = templates.get(key);
1332
1332
  if (cached) {
@@ -1336,7 +1336,7 @@ var GameVegetationThree = (() => {
1336
1336
  return cached;
1337
1337
  }
1338
1338
  stats.misses++;
1339
- const built = make(node.kind, parameters);
1339
+ const built = make({ ...node, ...parameters });
1340
1340
  templates.set(key, built);
1341
1341
  if (templates.size > templateLimit) templates.delete(templates.keys().next().value);
1342
1342
  return built;
@@ -1430,6 +1430,7 @@ var GameVegetationThree = (() => {
1430
1430
  };
1431
1431
 
1432
1432
  // ../game-contracts/dist/index.js
1433
+ var DEFAULT_BLAST_IMPULSE = { bodyArea: 0.7, lift: 0.15, minSpeed: 0.3, tntPerJoule: 0.24 / 2e5 };
1433
1434
  var DEFAULT_COST_ALLOCATION_BYTES = 1024 * 1024;
1434
1435
  var DEFERRED_QUEUE_ID = {
1435
1436
  DESTRUCTION_EVENTS: "destruction.events",
@@ -1721,7 +1722,7 @@ var GameVegetationThree = (() => {
1721
1722
  validateSpec: () => validateSpec
1722
1723
  });
1723
1724
 
1724
- // ../game-vegetation/dist/chunk-WNYTFZR4.js
1725
+ // ../game-vegetation/dist/chunk-CJRLKDWB.js
1725
1726
  var __defProp2 = Object.defineProperty;
1726
1727
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1727
1728
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -9502,6 +9503,7 @@ gl_Position = projectionMatrix * mvPosition;
9502
9503
  }
9503
9504
 
9504
9505
  // src/test-area/nursery.ts
9506
+ var isMesh = (o) => o.isMesh === true;
9505
9507
  var LOT = { W: 12, D: 20 };
9506
9508
  var HOUSE = { x0: 2.5, x1: 9.5, z0: 6.5, z1: 13 };
9507
9509
  var WAY = [[6, 1.2], [6, 5.4], [10.8, 5.4], [10.8, 14.2], [8, 18.6], [3, 18.6], [1.2, 14.2], [1.2, 5.4], [4, 3.2], [8, 3.2]];
@@ -9593,14 +9595,14 @@ gl_Position = projectionMatrix * mvPosition;
9593
9595
  let attached = false;
9594
9596
  const disposeObject = (object2) => {
9595
9597
  object2.traverse((child) => {
9596
- child.geometry?.dispose?.();
9598
+ if (isMesh(child)) child.geometry?.dispose?.();
9597
9599
  });
9598
9600
  };
9599
9601
  const clearGroup = (g) => {
9600
9602
  for (const child of [...g.children]) {
9601
9603
  g.remove(child);
9602
9604
  disposeObject(child);
9603
- child.material?.dispose?.();
9605
+ if (isMesh(child) && !Array.isArray(child.material)) child.material?.dispose?.();
9604
9606
  }
9605
9607
  };
9606
9608
  const ensure = () => {
@@ -9657,7 +9659,7 @@ gl_Position = projectionMatrix * mvPosition;
9657
9659
  const buildMs = Date.now() - t0;
9658
9660
  lotObject = sdk.createLotObject(THREE, data, materials);
9659
9661
  lotObject.traverse((c) => {
9660
- if (c.isMesh) {
9662
+ if (isMesh(c)) {
9661
9663
  c.castShadow = true;
9662
9664
  c.receiveShadow = true;
9663
9665
  }
@@ -9832,7 +9834,7 @@ gl_Position = projectionMatrix * mvPosition;
9832
9834
  return root;
9833
9835
  }
9834
9836
  function buildSpec(root, def) {
9835
- const meshes = root.children.filter((c) => c.isMesh && c.userData.veg);
9837
+ const meshes = root.children.filter((c) => c.isMesh === true && Boolean(c.userData.veg));
9836
9838
  const byId2 = {};
9837
9839
  for (const m of meshes) byId2[m.userData.veg.id] = m;
9838
9840
  const parts = [];
@@ -9961,6 +9963,7 @@ gl_Position = projectionMatrix * mvPosition;
9961
9963
  id: def.id,
9962
9964
  name: def.name ? def.name[loc === "en" ? 1 : 0] : species2.name(def.base ?? def.id, loc),
9963
9965
  build: (THREE) => buildObject(THREE, def),
9966
+ // the room hands its three.js namespace
9964
9967
  spec: (root) => {
9965
9968
  const spec = buildSpec(root, def);
9966
9969
  root.userData.vegSpec = spec;
@@ -10038,11 +10041,12 @@ gl_Position = projectionMatrix * mvPosition;
10038
10041
  };
10039
10042
  const crownsOf = (so) => specOf(so).parts.filter((p) => /^(s\d+_)?crown\d*$/.test(p.id)).map((p) => p.id);
10040
10043
  const jointPos = (so, jid) => {
10041
- const j = specOf(so).joints.filter((x) => x.id === jid)[0];
10044
+ const j = (specOf(so).joints ?? []).filter((x) => x.id === jid)[0];
10042
10045
  const a = partSpec(so, j.a);
10043
10046
  const b = partSpec(so, j.b);
10044
10047
  const box2 = (p) => {
10045
- const h = p.shape.kind === "box" ? p.shape.size.map((s) => s / 2) : [p.shape.radius, p.shape.height / 2, p.shape.radius];
10048
+ const sh = p.shape;
10049
+ const h = sh.kind === "box" ? [sh.size[0] / 2, sh.size[1] / 2, sh.size[2] / 2] : [sh.radius, (sh.kind === "cylinder" ? sh.height : sh.radius * 2) / 2, sh.radius];
10046
10050
  const r = p.rotation || [0, 0, 0];
10047
10051
  const cx = Math.cos(r[0]), sx = Math.sin(r[0]), cz = Math.cos(r[2]), sz = Math.sin(r[2]);
10048
10052
  const mn = [Infinity, Infinity, Infinity];
@@ -10069,6 +10073,16 @@ gl_Position = projectionMatrix * mvPosition;
10069
10073
  if (!p) return null;
10070
10074
  return { status: p.status, hp: p.hp, maxHp: p.maxHp, temperature: p.temperature, burning: p.burning, char: p.char || 0, fuel: p.fuel, holes: (p.holes || []).length, material: p.material };
10071
10075
  };
10076
+ const snapAt = (room, so, pid) => {
10077
+ const p = snap(room, so, pid);
10078
+ if (!p) throw new Error(`game-vegetation-three: no part "${pid}" in ${so.objectId}`);
10079
+ return p;
10080
+ };
10081
+ const stateAt = (room, id) => {
10082
+ const st = room.world.state(id);
10083
+ if (!st) throw new Error(`game-vegetation-three: no object ${id} in the world`);
10084
+ return st;
10085
+ };
10072
10086
  const logCount = (room, so, type) => room.log.entries({ type, objectId: so.objectId }).length;
10073
10087
  const jointsOpened = (room, so) => {
10074
10088
  let n = 0;
@@ -10080,7 +10094,11 @@ gl_Position = projectionMatrix * mvPosition;
10080
10094
  const spawn = (room, id, x, z) => room.spawn(id, [x, 0, z], 0);
10081
10095
  const split = (room, so) => {
10082
10096
  const home = room.world.snapshot(so.objectId);
10083
- const loose = room.world.ids().filter((i) => /^obj_/.test(i)).map((i) => ({ id: i, st: room.world.snapshot(i) }));
10097
+ if (!home) throw new Error(`game-vegetation-three: no object ${so.objectId} in the world`);
10098
+ const loose = room.world.ids().filter((i) => /^obj_/.test(i)).flatMap((i) => {
10099
+ const st = room.world.snapshot(i);
10100
+ return st ? [{ id: i, st }] : [];
10101
+ });
10084
10102
  const anchored = {};
10085
10103
  for (const p of specOf(so).parts) if (p.anchored) anchored[p.id] = true;
10086
10104
  const rooted = [];
@@ -10092,7 +10110,8 @@ gl_Position = projectionMatrix * mvPosition;
10092
10110
  const fell = (room, ctx, so, max) => {
10093
10111
  take(room, "axe");
10094
10112
  let swings = 0;
10095
- const h = partSpec(so, "trunk").shape.height;
10113
+ const trunkShape = partSpec(so, "trunk").shape;
10114
+ const h = trunkShape.kind === "cylinder" ? trunkShape.height : trunkShape.kind === "box" ? trunkShape.size[1] : trunkShape.radius * 2;
10096
10115
  for (let i = 0; i < max; i++) {
10097
10116
  aimPart(room, so, "trunk", 0.5, [0, Math.min(0.9, h / 3), 0]);
10098
10117
  room.use();
@@ -10101,7 +10120,7 @@ gl_Position = projectionMatrix * mvPosition;
10101
10120
  if (lost(room.world.part(so.objectId, "trunk"))) break;
10102
10121
  }
10103
10122
  ctx.step(5);
10104
- return { swings, trunk: snap(room, so, "trunk") };
10123
+ return { swings, trunk: snapAt(room, so, "trunk") };
10105
10124
  };
10106
10125
  const sc = (id, ptName, enName, run) => ({ id: `veg_${id}`, name: L(ptName, enName), run });
10107
10126
  const pct = (x) => `${Math.round((x || 0) * 100)}%`;
@@ -10117,7 +10136,7 @@ gl_Position = projectionMatrix * mvPosition;
10117
10136
  const r = fell(room, ctx, so, 60);
10118
10137
  const sp = split(room, so);
10119
10138
  const crownGone = lost(room.world.part(so.objectId, "crown")) || !sp.inHome("crown") || sp.rooted.indexOf("crown") < 0;
10120
- const branches = specOf(so).parts.filter((p) => p.tags.indexOf("branch") >= 0).map((p) => p.id);
10139
+ const branches = specOf(so).parts.filter((p) => (p.tags ?? []).indexOf("branch") >= 0).map((p) => p.id);
10121
10140
  const branchesFree = branches.every((b) => sp.rooted.indexOf(b) < 0);
10122
10141
  const detach = jointsOpened(room, so);
10123
10142
  ctx.expect(r.trunk.status === "broken" && r.swings >= 8 && r.swings <= 15, L(`Machado no tronco de 15 cm (hp ${Math.round(r.trunk.maxHp)}): tronco ${r.trunk.status} depois de ${r.swings} golpes (esperado: broken em 8 a 15 golpes)`, `Axe on a 15 cm trunk (hp ${Math.round(r.trunk.maxHp)}): trunk ${r.trunk.status} after ${r.swings} swings (expected: broken in 8 to 15 swings)`), { swings: r.swings, status: r.trunk.status, maxHp: r.trunk.maxHp });
@@ -10147,7 +10166,7 @@ gl_Position = projectionMatrix * mvPosition;
10147
10166
  detached = detachedJoint(room, so, jid);
10148
10167
  }
10149
10168
  ctx.step(3);
10150
- const trunk = snap(room, so, "trunk");
10169
+ const trunk = snapAt(room, so, "trunk");
10151
10170
  const sp = split(room, so);
10152
10171
  const branchOff = sp.inLoose("branch1") && !sp.inHome("branch1");
10153
10172
  const restStays = sp.inHome("trunk") && sp.rooted.indexOf("trunk") >= 0;
@@ -10165,7 +10184,7 @@ gl_Position = projectionMatrix * mvPosition;
10165
10184
  ctx.step(0.4);
10166
10185
  shots++;
10167
10186
  }
10168
- const trunk = snap(room, so, "trunk");
10187
+ const trunk = snapAt(room, so, "trunk");
10169
10188
  const sp = split(room, so);
10170
10189
  ctx.expect(trunk.status !== "broken" && trunk.hp > 0, L(`${shots} tiros de 9 mm no tronco de 15 cm: tronco ${trunk.status}, hp ${Math.round(trunk.hp)}/${Math.round(trunk.maxHp)} (esperado: n\xE3o quebrado)`, `${shots} 9 mm shots on the 15 cm trunk: trunk ${trunk.status}, hp ${Math.round(trunk.hp)}/${Math.round(trunk.maxHp)} (expected: not broken)`), { shots, hp: trunk.hp });
10171
10190
  ctx.expect(sp.loose.length === 0 && sp.inHome("trunk") && sp.rooted.indexOf("crown") >= 0, L(`A \xE1rvore continua de p\xE9: peda\xE7os soltos ${sp.loose.length}, copa presa ao ch\xE3o ${yn(sp.rooted.indexOf("crown") >= 0)} (esperado: 0, sim)`, `The tree still stands: loose pieces ${sp.loose.length}, crown rooted ${yn(sp.rooted.indexOf("crown") >= 0)} (expected: 0, yes)`), {});
@@ -10195,21 +10214,21 @@ gl_Position = projectionMatrix * mvPosition;
10195
10214
  take(room, "lighter");
10196
10215
  const a = aimPart(room, so, crownsOf(so), 0.08);
10197
10216
  room.use(6);
10198
- const crown = snap(room, so, a.pid);
10217
+ const crown = snapAt(room, so, a.pid);
10199
10218
  const lit = crown.burning || crown.temperature > 300;
10200
10219
  let peak = 0;
10201
10220
  let charMax = 0;
10202
10221
  for (let t = 0; t < 18; t++) {
10203
10222
  ctx.step(5);
10204
- for (const p of room.world.state(so.objectId).parts) {
10223
+ for (const p of stateAt(room, so.objectId).parts) {
10205
10224
  if (p.material === "green_wood") {
10206
10225
  peak = Math.max(peak, p.temperature);
10207
10226
  charMax = Math.max(charMax, p.char || 0);
10208
10227
  }
10209
10228
  }
10210
10229
  }
10211
- const st = room.world.state(so.objectId);
10212
- const burnt = st.parts.filter((p) => p.material === "foliage" && (p.burning || p.char > 0 || p.status === "ashes")).length;
10230
+ const st = stateAt(room, so.objectId);
10231
+ const burnt = st.parts.filter((p) => p.material === "foliage" && (p.burning || (p.char ?? 0) > 0 || p.status === "ashes")).length;
10213
10232
  ctx.expect(lit, L(`Isqueiro na copa: folhagem acesa ou acima de 300 \xB0C = ${yn(lit)} (${Math.round(crown.temperature)} \xB0C; esperado: sim)`, `Lighter on the crown: foliage lit or above 300 C = ${yn(lit)} (${Math.round(crown.temperature)} C; expected: yes)`), { temperature: crown.temperature });
10214
10233
  ctx.expect(burnt > 0, L(`Depois de 90 s: ${burnt} pe\xE7a(s) de folhagem queimando, carbonizada(s) ou em cinza (esperado: 1 ou mais)`, `After 90 s: ${burnt} foliage piece(s) burning, charred or ash (expected: 1+)`), { burnt });
10215
10234
  ctx.expect(peak > 150 || charMax > 0, L(`O fogo da folhagem passa para a madeira verde (tronco e galhos): pico de ${Math.round(peak)} \xB0C, carboniza\xE7\xE3o m\xE1xima ${pct(charMax)} (esperado: pico acima de 150 \xB0C ou carboniza\xE7\xE3o acima de 0; a madeira verde s\xF3 pega fogo acima de 400 \xB0C)`, `Foliage fire reaches the green wood (trunk and branches): peak ${Math.round(peak)} C, max char ${pct(charMax)} (expected: peak above 150 C or char above 0; green wood only ignites above 400 C)`), { peak, charMax });
@@ -10220,13 +10239,13 @@ gl_Position = projectionMatrix * mvPosition;
10220
10239
  const so = spawn(room, "mango_tree", 0, -6);
10221
10240
  take(room, "pistol_9mm");
10222
10241
  const tgt = aimPart(room, so, crownsOf(so), 2.5).pid;
10223
- const before = snap(room, so, tgt);
10242
+ const before = snapAt(room, so, tgt);
10224
10243
  for (let i = 0; i < 3; i++) {
10225
10244
  aimPart(room, so, tgt, 2.5);
10226
10245
  room.use();
10227
10246
  ctx.step(0.6);
10228
10247
  }
10229
- const crown = snap(room, so, tgt);
10248
+ const crown = snapAt(room, so, tgt);
10230
10249
  const leaves = room.log.entries({ type: "debris", objectId: so.objectId }).filter((e) => e.data && e.data.kind === "leaves").length;
10231
10250
  const hurt = crown.hp < before.hp || crown.status === "broken";
10232
10251
  ctx.expect(hurt && crown.status !== "intact", L(`Tr\xEAs tiros na copa: hp ${Math.round(before.hp)} para ${Math.round(crown.hp)}, estado ${crown.status} (esperado: hp menor, n\xE3o intacta)`, `Three shots into the crown: hp ${Math.round(before.hp)} to ${Math.round(crown.hp)}, status ${crown.status} (expected: lower hp, not intact)`), { hp: crown.hp });
@@ -10283,8 +10302,8 @@ gl_Position = projectionMatrix * mvPosition;
10283
10302
  const a = snap(room, so, arm);
10284
10303
  const sp = split(room, so);
10285
10304
  const armOff = !a || a.status === "broken" || sp.inLoose(arm) && !sp.inHome(arm);
10286
- const stemOk = sp.inHome("stem") && sp.rooted.indexOf("stem") >= 0 && room.world.part(so.objectId, "stem").status !== "broken";
10287
- const spines = specOf(so).parts.filter((p) => p.tags.indexOf("thorns") >= 0);
10305
+ const stemOk = sp.inHome("stem") && sp.rooted.indexOf("stem") >= 0 && room.world.part(so.objectId, "stem")?.status !== "broken";
10306
+ const spines = specOf(so).parts.filter((p) => (p.tags ?? []).indexOf("thorns") >= 0);
10288
10307
  const thorny = so.root.userData.thorny === true && spines.length > 0;
10289
10308
  const spinesOff = !sp.rooted.some((pid) => pid.indexOf(`${arm}_spines`) === 0);
10290
10309
  ctx.expect(armOff, L(`Machete na junta ${jid}: bra\xE7o ${a ? a.status : "solto como objeto pr\xF3prio"} depois de ${swings} golpe(s) (esperado: solto do caule pela junta)`, `Machete on joint ${jid}: arm ${a ? a.status : "loose as its own object"} after ${swings} swing(s) (expected: off the stem through the joint)`), { swings });
@@ -10319,11 +10338,11 @@ gl_Position = projectionMatrix * mvPosition;
10319
10338
  aimPart(room, so, "trunk", 0.08, [0, 0.8, 0]);
10320
10339
  room.use(8);
10321
10340
  }
10322
- const d0 = snap(room, dead, "trunk");
10323
- const l0 = snap(room, live, "trunk");
10341
+ const d0 = snapAt(room, dead, "trunk");
10342
+ const l0 = snapAt(room, live, "trunk");
10324
10343
  ctx.step(120);
10325
- const d = snap(room, dead, "trunk");
10326
- const l = snap(room, live, "trunk");
10344
+ const d = snapAt(room, dead, "trunk");
10345
+ const l = snapAt(room, live, "trunk");
10327
10346
  const score = (p) => p ? Math.max(p.char, p.burning ? 0.01 : 0, (p.temperature - 20) / 2e3) : 0;
10328
10347
  ctx.expect(d0.material === "wood_soft" && l0.material === "green_wood", L(`Materiais do tronco: \xE1rvore morta ${d0.material}, viva ${l0.material} (esperado: wood_soft, green_wood)`, `Trunk materials: dead tree ${d0.material}, living ${l0.material} (expected: wood_soft, green_wood)`), { dead: d0.material, live: l0.material });
10329
10348
  ctx.expect(score(d) > score(l), L(`Depois de 8 s de isqueiro e 120 s de espera: morta queimando ${yn(d.burning)}, ${Math.round(d.temperature)} \xB0C, carboniza\xE7\xE3o ${pct(d.char)}; viva queimando ${yn(l.burning)}, ${Math.round(l.temperature)} \xB0C, carboniza\xE7\xE3o ${pct(l.char)} (esperado: a morta mais queimada)`, `After 8 s of lighter and 120 s of waiting: dead burning ${yn(d.burning)}, ${Math.round(d.temperature)} C, char ${pct(d.char)}; living burning ${yn(l.burning)}, ${Math.round(l.temperature)} C, char ${pct(l.char)} (expected: dead burns more)`), { dead: score(d), live: score(l) });
@@ -10353,7 +10372,7 @@ gl_Position = projectionMatrix * mvPosition;
10353
10372
  const tuft = spawn(room, "lawn_tuft", 0, -3);
10354
10373
  const tree = spawn(room, "mango_tree", 4, -3);
10355
10374
  const noBlock = !tuft.root.userData.collider;
10356
- const treeBlock = !!(tree.root.userData.collider && tree.root.userData.collider.kind);
10375
+ const treeBlock = !!tree.root.userData.collider?.kind;
10357
10376
  ctx.expect(noBlock && treeBlock, L(`Colisor do SDK: touceira ${noBlock ? "nenhum" : "tem"}, tronco da mangueira ${treeBlock ? "tem" : "nenhum"} (esperado: nenhum, tem)`, `SDK collider: tuft ${noBlock ? "none" : "has one"}, mango trunk ${treeBlock ? "has one" : "none"} (expected: none, has one)`), {});
10358
10377
  room.look([0, 1.7, -0.5], [0, 1.7, -6]);
10359
10378
  const before = room.camera.position.z;
@@ -10437,6 +10456,7 @@ gl_Position = projectionMatrix * mvPosition;
10437
10456
  "veg_hedge_cut_pieces",
10438
10457
  "veg_walk_on_grass"
10439
10458
  ];
10459
+ var isMesh2 = (o) => o.isMesh === true;
10440
10460
  var defaultSdk = () => ({ ...dist_exports, ...three_exports });
10441
10461
  var AXIS_COLOURS = { trunk: 14254635, branch: 15057019, arm: 7327599, stem: 7327639, pad: 7321551 };
10442
10462
  function createVegetationTestModule(options = {}) {
@@ -10494,7 +10514,7 @@ gl_Position = projectionMatrix * mvPosition;
10494
10514
  }
10495
10515
  for (const mesh2 of root.children) {
10496
10516
  const v = mesh2.userData?.veg;
10497
- if (!v || !mesh2.geometry) continue;
10517
+ if (!v || !isMesh2(mesh2) || !mesh2.geometry) continue;
10498
10518
  if (host.bench.layer("piece_boxes")) {
10499
10519
  mesh2.geometry.computeBoundingBox();
10500
10520
  const box2 = mesh2.geometry.boundingBox.clone().translate(mesh2.position);
@@ -10598,7 +10618,7 @@ gl_Position = projectionMatrix * mvPosition;
10598
10618
  let pieces = 0;
10599
10619
  for (const entry of placed.values()) {
10600
10620
  entry.root.traverse((mesh2) => {
10601
- if (!mesh2.isMesh || mesh2.userData.helper) return;
10621
+ if (!isMesh2(mesh2) || mesh2.userData.helper) return;
10602
10622
  for (let p = mesh2; p; p = p.parent) if (p.visible === false) return;
10603
10623
  drawCalls += 1;
10604
10624
  if (mesh2.userData.veg) pieces += 1;
@@ -10611,7 +10631,7 @@ gl_Position = projectionMatrix * mvPosition;
10611
10631
  const lotCalls = () => {
10612
10632
  let calls = 0;
10613
10633
  nursery?.group.traverse((o) => {
10614
- if (o.isMesh && o.visible) calls += 1;
10634
+ if (isMesh2(o) && o.visible) calls += 1;
10615
10635
  });
10616
10636
  return calls;
10617
10637
  };