@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.
- package/dist/chunk-2DJB2FIT.js +1245 -0
- package/dist/chunk-2DJB2FIT.js.map +1 -0
- package/dist/index.d.ts +6 -237
- package/dist/index.global.js +112 -44
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +20 -1204
- package/dist/index.js.map +1 -1
- package/dist/testing.d.ts +275 -0
- package/dist/testing.js +41 -0
- package/dist/testing.js.map +1 -0
- package/package.json +10 -6
package/dist/index.global.js
CHANGED
|
@@ -41,7 +41,7 @@ var GameVegetationThree = (() => {
|
|
|
41
41
|
scatterLot: () => scatterLot
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
// ../game-shapes/dist/chunk-
|
|
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(
|
|
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
|
|
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
|
|
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-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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:
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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")
|
|
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 =
|
|
10274
|
-
const l0 =
|
|
10340
|
+
const d0 = snapAt(room, dead, "trunk");
|
|
10341
|
+
const l0 = snapAt(room, live, "trunk");
|
|
10275
10342
|
ctx.step(120);
|
|
10276
|
-
const d =
|
|
10277
|
-
const l =
|
|
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 = !!
|
|
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
|
|
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
|
|
10633
|
+
if (isMesh2(o) && o.visible) calls += 1;
|
|
10566
10634
|
});
|
|
10567
10635
|
return calls;
|
|
10568
10636
|
};
|