@adatechnology/game-vegetation-three 0.2.8 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -41,7 +41,7 @@ var GameVegetationThree = (() => {
41
41
  scatterLot: () => scatterLot
42
42
  });
43
43
 
44
- // ../game-shapes/dist/chunk-R4RY23RH.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;
@@ -1429,6 +1429,64 @@ var GameVegetationThree = (() => {
1429
1429
  custom: { fields: { generator: str, params: () => null }, required: ["generator"] }
1430
1430
  };
1431
1431
 
1432
+ // ../game-contracts/dist/index.js
1433
+ var DEFAULT_COST_ALLOCATION_BYTES = 1024 * 1024;
1434
+ var DEFERRED_QUEUE_ID = {
1435
+ DESTRUCTION_EVENTS: "destruction.events",
1436
+ BREACH_PAINT: "floorplan.breach-paint",
1437
+ AUDIO_VOICES: "audio.voices",
1438
+ VEHICLE_CREASE: "vehicles.crease"
1439
+ };
1440
+ var DEFERRED_PRIORITY = {
1441
+ [DEFERRED_QUEUE_ID.DESTRUCTION_EVENTS]: { priority: 300, phase: "present" },
1442
+ [DEFERRED_QUEUE_ID.BREACH_PAINT]: { priority: 250, phase: "present" },
1443
+ [DEFERRED_QUEUE_ID.AUDIO_VOICES]: { priority: 200, phase: "idle", reserveMs: 1 },
1444
+ [DEFERRED_QUEUE_ID.VEHICLE_CREASE]: { priority: 100, phase: "idle" }
1445
+ };
1446
+ var KIT_ORIGIN_KEY = "kitOrigin";
1447
+ function markKitOrigin(object2, origin) {
1448
+ const node = object2;
1449
+ node.userData = node.userData ?? {};
1450
+ node.userData[KIT_ORIGIN_KEY] = { ...origin };
1451
+ return object2;
1452
+ }
1453
+ var SURFACE_IDS = ["concrete", "asphalt", "wood", "tile", "dirt", "grass", "gravel", "sand", "metal", "water", "glass", "carpet"];
1454
+ var GAIT_IDS = ["walk", "run"];
1455
+ var LANDING_IDS = ["light", "heavy"];
1456
+ var BODY_SOUND_IDS = [
1457
+ "jump",
1458
+ "cloth_rustle",
1459
+ "body_fall",
1460
+ "fall_damage",
1461
+ "player_hurt",
1462
+ "player_breath_run",
1463
+ "player_death",
1464
+ "bite",
1465
+ "grab",
1466
+ "punch_swing",
1467
+ "punch_hit_body",
1468
+ "punch_hit_face",
1469
+ "punch_hit_object",
1470
+ "kick_swing",
1471
+ "kick_hit",
1472
+ "kick_hit_object",
1473
+ "shove_two_hands",
1474
+ "knife_swing",
1475
+ "knife_stab",
1476
+ "knife_slash",
1477
+ "knife_hit_object",
1478
+ "blunt_swing",
1479
+ "blunt_hit",
1480
+ "blunt_hit_object",
1481
+ "axe_swing",
1482
+ "axe_chop",
1483
+ "axe_hit_object"
1484
+ ];
1485
+ var footstepSoundId = (surface, gait) => `footstep_${surface}_${gait}`;
1486
+ var FOOTSTEP_SOUND_IDS = SURFACE_IDS.flatMap((surface) => GAIT_IDS.map((gait) => footstepSoundId(surface, gait)));
1487
+ var LAND_SOUND_IDS = SURFACE_IDS.flatMap((surface) => LANDING_IDS.map((landing) => `land_${surface}_${landing}`));
1488
+ var BODY_FOLEY_IDS = [...FOOTSTEP_SOUND_IDS, ...LAND_SOUND_IDS, ...BODY_SOUND_IDS];
1489
+
1432
1490
  // ../game-shapes-three/dist/index.js
1433
1491
  var UV_BEFORE_NORMAL = /* @__PURE__ */ new Set(["LatheGeometry", "ExtrudeGeometry"]);
1434
1492
  var INDEX_FIRST = /* @__PURE__ */ new Set(["BoxGeometry", "CylinderGeometry", "ConeGeometry", "SphereGeometry", "PlaneGeometry", "CircleGeometry", "RingGeometry", "LatheGeometry", "TorusGeometry"]);
@@ -1663,7 +1721,7 @@ var GameVegetationThree = (() => {
1663
1721
  validateSpec: () => validateSpec
1664
1722
  });
1665
1723
 
1666
- // ../game-vegetation/dist/chunk-WNYTFZR4.js
1724
+ // ../game-vegetation/dist/chunk-CJRLKDWB.js
1667
1725
  var __defProp2 = Object.defineProperty;
1668
1726
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1669
1727
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -9444,6 +9502,7 @@ gl_Position = projectionMatrix * mvPosition;
9444
9502
  }
9445
9503
 
9446
9504
  // src/test-area/nursery.ts
9505
+ var isMesh = (o) => o.isMesh === true;
9447
9506
  var LOT = { W: 12, D: 20 };
9448
9507
  var HOUSE = { x0: 2.5, x1: 9.5, z0: 6.5, z1: 13 };
9449
9508
  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]];
@@ -9535,14 +9594,14 @@ gl_Position = projectionMatrix * mvPosition;
9535
9594
  let attached = false;
9536
9595
  const disposeObject = (object2) => {
9537
9596
  object2.traverse((child) => {
9538
- child.geometry?.dispose?.();
9597
+ if (isMesh(child)) child.geometry?.dispose?.();
9539
9598
  });
9540
9599
  };
9541
9600
  const clearGroup = (g) => {
9542
9601
  for (const child of [...g.children]) {
9543
9602
  g.remove(child);
9544
9603
  disposeObject(child);
9545
- child.material?.dispose?.();
9604
+ if (isMesh(child) && !Array.isArray(child.material)) child.material?.dispose?.();
9546
9605
  }
9547
9606
  };
9548
9607
  const ensure = () => {
@@ -9599,7 +9658,7 @@ gl_Position = projectionMatrix * mvPosition;
9599
9658
  const buildMs = Date.now() - t0;
9600
9659
  lotObject = sdk.createLotObject(THREE, data, materials);
9601
9660
  lotObject.traverse((c) => {
9602
- if (c.isMesh) {
9661
+ if (isMesh(c)) {
9603
9662
  c.castShadow = true;
9604
9663
  c.receiveShadow = true;
9605
9664
  }
@@ -9681,15 +9740,6 @@ gl_Position = projectionMatrix * mvPosition;
9681
9740
  };
9682
9741
  }
9683
9742
 
9684
- // ../game-contracts/dist/index.js
9685
- var KIT_ORIGIN_KEY = "kitOrigin";
9686
- function markKitOrigin(object2, origin) {
9687
- const node = object2;
9688
- node.userData = node.userData ?? {};
9689
- node.userData[KIT_ORIGIN_KEY] = { ...origin };
9690
- return object2;
9691
- }
9692
-
9693
9743
  // src/test-area/plants.ts
9694
9744
  var PLANT_SEED = 3;
9695
9745
  var PLANT_DEFS = [
@@ -9783,7 +9833,7 @@ gl_Position = projectionMatrix * mvPosition;
9783
9833
  return root;
9784
9834
  }
9785
9835
  function buildSpec(root, def) {
9786
- const meshes = root.children.filter((c) => c.isMesh && c.userData.veg);
9836
+ const meshes = root.children.filter((c) => c.isMesh === true && Boolean(c.userData.veg));
9787
9837
  const byId2 = {};
9788
9838
  for (const m of meshes) byId2[m.userData.veg.id] = m;
9789
9839
  const parts = [];
@@ -9912,6 +9962,7 @@ gl_Position = projectionMatrix * mvPosition;
9912
9962
  id: def.id,
9913
9963
  name: def.name ? def.name[loc === "en" ? 1 : 0] : species2.name(def.base ?? def.id, loc),
9914
9964
  build: (THREE) => buildObject(THREE, def),
9965
+ // the room hands its three.js namespace
9915
9966
  spec: (root) => {
9916
9967
  const spec = buildSpec(root, def);
9917
9968
  root.userData.vegSpec = spec;
@@ -9989,11 +10040,12 @@ gl_Position = projectionMatrix * mvPosition;
9989
10040
  };
9990
10041
  const crownsOf = (so) => specOf(so).parts.filter((p) => /^(s\d+_)?crown\d*$/.test(p.id)).map((p) => p.id);
9991
10042
  const jointPos = (so, jid) => {
9992
- const j = specOf(so).joints.filter((x) => x.id === jid)[0];
10043
+ const j = (specOf(so).joints ?? []).filter((x) => x.id === jid)[0];
9993
10044
  const a = partSpec(so, j.a);
9994
10045
  const b = partSpec(so, j.b);
9995
10046
  const box2 = (p) => {
9996
- const h = p.shape.kind === "box" ? p.shape.size.map((s) => s / 2) : [p.shape.radius, p.shape.height / 2, p.shape.radius];
10047
+ const sh = p.shape;
10048
+ 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];
9997
10049
  const r = p.rotation || [0, 0, 0];
9998
10050
  const cx = Math.cos(r[0]), sx = Math.sin(r[0]), cz = Math.cos(r[2]), sz = Math.sin(r[2]);
9999
10051
  const mn = [Infinity, Infinity, Infinity];
@@ -10020,6 +10072,16 @@ gl_Position = projectionMatrix * mvPosition;
10020
10072
  if (!p) return null;
10021
10073
  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 };
10022
10074
  };
10075
+ const snapAt = (room, so, pid) => {
10076
+ const p = snap(room, so, pid);
10077
+ if (!p) throw new Error(`game-vegetation-three: no part "${pid}" in ${so.objectId}`);
10078
+ return p;
10079
+ };
10080
+ const stateAt = (room, id) => {
10081
+ const st = room.world.state(id);
10082
+ if (!st) throw new Error(`game-vegetation-three: no object ${id} in the world`);
10083
+ return st;
10084
+ };
10023
10085
  const logCount = (room, so, type) => room.log.entries({ type, objectId: so.objectId }).length;
10024
10086
  const jointsOpened = (room, so) => {
10025
10087
  let n = 0;
@@ -10031,7 +10093,11 @@ gl_Position = projectionMatrix * mvPosition;
10031
10093
  const spawn = (room, id, x, z) => room.spawn(id, [x, 0, z], 0);
10032
10094
  const split = (room, so) => {
10033
10095
  const home = room.world.snapshot(so.objectId);
10034
- const loose = room.world.ids().filter((i) => /^obj_/.test(i)).map((i) => ({ id: i, st: room.world.snapshot(i) }));
10096
+ if (!home) throw new Error(`game-vegetation-three: no object ${so.objectId} in the world`);
10097
+ const loose = room.world.ids().filter((i) => /^obj_/.test(i)).flatMap((i) => {
10098
+ const st = room.world.snapshot(i);
10099
+ return st ? [{ id: i, st }] : [];
10100
+ });
10035
10101
  const anchored = {};
10036
10102
  for (const p of specOf(so).parts) if (p.anchored) anchored[p.id] = true;
10037
10103
  const rooted = [];
@@ -10043,7 +10109,8 @@ gl_Position = projectionMatrix * mvPosition;
10043
10109
  const fell = (room, ctx, so, max) => {
10044
10110
  take(room, "axe");
10045
10111
  let swings = 0;
10046
- const h = partSpec(so, "trunk").shape.height;
10112
+ const trunkShape = partSpec(so, "trunk").shape;
10113
+ const h = trunkShape.kind === "cylinder" ? trunkShape.height : trunkShape.kind === "box" ? trunkShape.size[1] : trunkShape.radius * 2;
10047
10114
  for (let i = 0; i < max; i++) {
10048
10115
  aimPart(room, so, "trunk", 0.5, [0, Math.min(0.9, h / 3), 0]);
10049
10116
  room.use();
@@ -10052,7 +10119,7 @@ gl_Position = projectionMatrix * mvPosition;
10052
10119
  if (lost(room.world.part(so.objectId, "trunk"))) break;
10053
10120
  }
10054
10121
  ctx.step(5);
10055
- return { swings, trunk: snap(room, so, "trunk") };
10122
+ return { swings, trunk: snapAt(room, so, "trunk") };
10056
10123
  };
10057
10124
  const sc = (id, ptName, enName, run) => ({ id: `veg_${id}`, name: L(ptName, enName), run });
10058
10125
  const pct = (x) => `${Math.round((x || 0) * 100)}%`;
@@ -10068,7 +10135,7 @@ gl_Position = projectionMatrix * mvPosition;
10068
10135
  const r = fell(room, ctx, so, 60);
10069
10136
  const sp = split(room, so);
10070
10137
  const crownGone = lost(room.world.part(so.objectId, "crown")) || !sp.inHome("crown") || sp.rooted.indexOf("crown") < 0;
10071
- const branches = specOf(so).parts.filter((p) => p.tags.indexOf("branch") >= 0).map((p) => p.id);
10138
+ const branches = specOf(so).parts.filter((p) => (p.tags ?? []).indexOf("branch") >= 0).map((p) => p.id);
10072
10139
  const branchesFree = branches.every((b) => sp.rooted.indexOf(b) < 0);
10073
10140
  const detach = jointsOpened(room, so);
10074
10141
  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 });
@@ -10098,7 +10165,7 @@ gl_Position = projectionMatrix * mvPosition;
10098
10165
  detached = detachedJoint(room, so, jid);
10099
10166
  }
10100
10167
  ctx.step(3);
10101
- const trunk = snap(room, so, "trunk");
10168
+ const trunk = snapAt(room, so, "trunk");
10102
10169
  const sp = split(room, so);
10103
10170
  const branchOff = sp.inLoose("branch1") && !sp.inHome("branch1");
10104
10171
  const restStays = sp.inHome("trunk") && sp.rooted.indexOf("trunk") >= 0;
@@ -10116,7 +10183,7 @@ gl_Position = projectionMatrix * mvPosition;
10116
10183
  ctx.step(0.4);
10117
10184
  shots++;
10118
10185
  }
10119
- const trunk = snap(room, so, "trunk");
10186
+ const trunk = snapAt(room, so, "trunk");
10120
10187
  const sp = split(room, so);
10121
10188
  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 });
10122
10189
  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)`), {});
@@ -10146,21 +10213,21 @@ gl_Position = projectionMatrix * mvPosition;
10146
10213
  take(room, "lighter");
10147
10214
  const a = aimPart(room, so, crownsOf(so), 0.08);
10148
10215
  room.use(6);
10149
- const crown = snap(room, so, a.pid);
10216
+ const crown = snapAt(room, so, a.pid);
10150
10217
  const lit = crown.burning || crown.temperature > 300;
10151
10218
  let peak = 0;
10152
10219
  let charMax = 0;
10153
10220
  for (let t = 0; t < 18; t++) {
10154
10221
  ctx.step(5);
10155
- for (const p of room.world.state(so.objectId).parts) {
10222
+ for (const p of stateAt(room, so.objectId).parts) {
10156
10223
  if (p.material === "green_wood") {
10157
10224
  peak = Math.max(peak, p.temperature);
10158
10225
  charMax = Math.max(charMax, p.char || 0);
10159
10226
  }
10160
10227
  }
10161
10228
  }
10162
- const st = room.world.state(so.objectId);
10163
- const burnt = st.parts.filter((p) => p.material === "foliage" && (p.burning || p.char > 0 || p.status === "ashes")).length;
10229
+ const st = stateAt(room, so.objectId);
10230
+ const burnt = st.parts.filter((p) => p.material === "foliage" && (p.burning || (p.char ?? 0) > 0 || p.status === "ashes")).length;
10164
10231
  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 });
10165
10232
  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 });
10166
10233
  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 });
@@ -10171,13 +10238,13 @@ gl_Position = projectionMatrix * mvPosition;
10171
10238
  const so = spawn(room, "mango_tree", 0, -6);
10172
10239
  take(room, "pistol_9mm");
10173
10240
  const tgt = aimPart(room, so, crownsOf(so), 2.5).pid;
10174
- const before = snap(room, so, tgt);
10241
+ const before = snapAt(room, so, tgt);
10175
10242
  for (let i = 0; i < 3; i++) {
10176
10243
  aimPart(room, so, tgt, 2.5);
10177
10244
  room.use();
10178
10245
  ctx.step(0.6);
10179
10246
  }
10180
- const crown = snap(room, so, tgt);
10247
+ const crown = snapAt(room, so, tgt);
10181
10248
  const leaves = room.log.entries({ type: "debris", objectId: so.objectId }).filter((e) => e.data && e.data.kind === "leaves").length;
10182
10249
  const hurt = crown.hp < before.hp || crown.status === "broken";
10183
10250
  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 });
@@ -10234,8 +10301,8 @@ gl_Position = projectionMatrix * mvPosition;
10234
10301
  const a = snap(room, so, arm);
10235
10302
  const sp = split(room, so);
10236
10303
  const armOff = !a || a.status === "broken" || sp.inLoose(arm) && !sp.inHome(arm);
10237
- const stemOk = sp.inHome("stem") && sp.rooted.indexOf("stem") >= 0 && room.world.part(so.objectId, "stem").status !== "broken";
10238
- const spines = specOf(so).parts.filter((p) => p.tags.indexOf("thorns") >= 0);
10304
+ const stemOk = sp.inHome("stem") && sp.rooted.indexOf("stem") >= 0 && room.world.part(so.objectId, "stem")?.status !== "broken";
10305
+ const spines = specOf(so).parts.filter((p) => (p.tags ?? []).indexOf("thorns") >= 0);
10239
10306
  const thorny = so.root.userData.thorny === true && spines.length > 0;
10240
10307
  const spinesOff = !sp.rooted.some((pid) => pid.indexOf(`${arm}_spines`) === 0);
10241
10308
  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 });
@@ -10270,11 +10337,11 @@ gl_Position = projectionMatrix * mvPosition;
10270
10337
  aimPart(room, so, "trunk", 0.08, [0, 0.8, 0]);
10271
10338
  room.use(8);
10272
10339
  }
10273
- const d0 = snap(room, dead, "trunk");
10274
- const l0 = snap(room, live, "trunk");
10340
+ const d0 = snapAt(room, dead, "trunk");
10341
+ const l0 = snapAt(room, live, "trunk");
10275
10342
  ctx.step(120);
10276
- const d = snap(room, dead, "trunk");
10277
- const l = snap(room, live, "trunk");
10343
+ const d = snapAt(room, dead, "trunk");
10344
+ const l = snapAt(room, live, "trunk");
10278
10345
  const score = (p) => p ? Math.max(p.char, p.burning ? 0.01 : 0, (p.temperature - 20) / 2e3) : 0;
10279
10346
  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 });
10280
10347
  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) });
@@ -10304,7 +10371,7 @@ gl_Position = projectionMatrix * mvPosition;
10304
10371
  const tuft = spawn(room, "lawn_tuft", 0, -3);
10305
10372
  const tree = spawn(room, "mango_tree", 4, -3);
10306
10373
  const noBlock = !tuft.root.userData.collider;
10307
- const treeBlock = !!(tree.root.userData.collider && tree.root.userData.collider.kind);
10374
+ const treeBlock = !!tree.root.userData.collider?.kind;
10308
10375
  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)`), {});
10309
10376
  room.look([0, 1.7, -0.5], [0, 1.7, -6]);
10310
10377
  const before = room.camera.position.z;
@@ -10388,6 +10455,7 @@ gl_Position = projectionMatrix * mvPosition;
10388
10455
  "veg_hedge_cut_pieces",
10389
10456
  "veg_walk_on_grass"
10390
10457
  ];
10458
+ var isMesh2 = (o) => o.isMesh === true;
10391
10459
  var defaultSdk = () => ({ ...dist_exports, ...three_exports });
10392
10460
  var AXIS_COLOURS = { trunk: 14254635, branch: 15057019, arm: 7327599, stem: 7327639, pad: 7321551 };
10393
10461
  function createVegetationTestModule(options = {}) {
@@ -10445,7 +10513,7 @@ gl_Position = projectionMatrix * mvPosition;
10445
10513
  }
10446
10514
  for (const mesh2 of root.children) {
10447
10515
  const v = mesh2.userData?.veg;
10448
- if (!v || !mesh2.geometry) continue;
10516
+ if (!v || !isMesh2(mesh2) || !mesh2.geometry) continue;
10449
10517
  if (host.bench.layer("piece_boxes")) {
10450
10518
  mesh2.geometry.computeBoundingBox();
10451
10519
  const box2 = mesh2.geometry.boundingBox.clone().translate(mesh2.position);
@@ -10549,7 +10617,7 @@ gl_Position = projectionMatrix * mvPosition;
10549
10617
  let pieces = 0;
10550
10618
  for (const entry of placed.values()) {
10551
10619
  entry.root.traverse((mesh2) => {
10552
- if (!mesh2.isMesh || mesh2.userData.helper) return;
10620
+ if (!isMesh2(mesh2) || mesh2.userData.helper) return;
10553
10621
  for (let p = mesh2; p; p = p.parent) if (p.visible === false) return;
10554
10622
  drawCalls += 1;
10555
10623
  if (mesh2.userData.veg) pieces += 1;
@@ -10562,7 +10630,7 @@ gl_Position = projectionMatrix * mvPosition;
10562
10630
  const lotCalls = () => {
10563
10631
  let calls = 0;
10564
10632
  nursery?.group.traverse((o) => {
10565
- if (o.isMesh && o.visible) calls += 1;
10633
+ if (isMesh2(o) && o.visible) calls += 1;
10566
10634
  });
10567
10635
  return calls;
10568
10636
  };