@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.
- package/dist/{chunk-4RHCXAUC.js → chunk-2DJB2FIT.js} +48 -29
- package/dist/chunk-2DJB2FIT.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.global.js +55 -35
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/testing.d.ts +55 -17
- package/dist/testing.js +1 -1
- package/package.json +5 -5
- package/dist/chunk-4RHCXAUC.js.map +0 -1
|
@@ -7,6 +7,7 @@ import * as GameVegetationSpeciesMain from "@adatechnology/game-vegetation-speci
|
|
|
7
7
|
|
|
8
8
|
// src/test-area/nursery.ts
|
|
9
9
|
import { shapeGeometries } from "@adatechnology/game-shapes-three";
|
|
10
|
+
var isMesh = (o) => o.isMesh === true;
|
|
10
11
|
var LOT = { W: 12, D: 20 };
|
|
11
12
|
var HOUSE = { x0: 2.5, x1: 9.5, z0: 6.5, z1: 13 };
|
|
12
13
|
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]];
|
|
@@ -98,14 +99,14 @@ function createNursery(sdk, species, THREE, materials, parent, origin) {
|
|
|
98
99
|
let attached = false;
|
|
99
100
|
const disposeObject = (object) => {
|
|
100
101
|
object.traverse((child) => {
|
|
101
|
-
child.geometry?.dispose?.();
|
|
102
|
+
if (isMesh(child)) child.geometry?.dispose?.();
|
|
102
103
|
});
|
|
103
104
|
};
|
|
104
105
|
const clearGroup = (g) => {
|
|
105
106
|
for (const child of [...g.children]) {
|
|
106
107
|
g.remove(child);
|
|
107
108
|
disposeObject(child);
|
|
108
|
-
child.material?.dispose?.();
|
|
109
|
+
if (isMesh(child) && !Array.isArray(child.material)) child.material?.dispose?.();
|
|
109
110
|
}
|
|
110
111
|
};
|
|
111
112
|
const ensure = () => {
|
|
@@ -162,7 +163,7 @@ function createNursery(sdk, species, THREE, materials, parent, origin) {
|
|
|
162
163
|
const buildMs = Date.now() - t0;
|
|
163
164
|
lotObject = sdk.createLotObject(THREE, data, materials);
|
|
164
165
|
lotObject.traverse((c) => {
|
|
165
|
-
if (c
|
|
166
|
+
if (isMesh(c)) {
|
|
166
167
|
c.castShadow = true;
|
|
167
168
|
c.receiveShadow = true;
|
|
168
169
|
}
|
|
@@ -338,7 +339,7 @@ function createPlants(sdk, species, materials, seed = PLANT_SEED) {
|
|
|
338
339
|
return root;
|
|
339
340
|
}
|
|
340
341
|
function buildSpec(root, def) {
|
|
341
|
-
const meshes = root.children.filter((c) => c.isMesh && c.userData.veg);
|
|
342
|
+
const meshes = root.children.filter((c) => c.isMesh === true && Boolean(c.userData.veg));
|
|
342
343
|
const byId = {};
|
|
343
344
|
for (const m of meshes) byId[m.userData.veg.id] = m;
|
|
344
345
|
const parts = [];
|
|
@@ -467,6 +468,7 @@ function createPlants(sdk, species, materials, seed = PLANT_SEED) {
|
|
|
467
468
|
id: def.id,
|
|
468
469
|
name: def.name ? def.name[loc === "en" ? 1 : 0] : species.name(def.base ?? def.id, loc),
|
|
469
470
|
build: (THREE) => buildObject(THREE, def),
|
|
471
|
+
// the room hands its three.js namespace
|
|
470
472
|
spec: (root) => {
|
|
471
473
|
const spec = buildSpec(root, def);
|
|
472
474
|
root.userData.vegSpec = spec;
|
|
@@ -544,11 +546,12 @@ function createScenarios(locale) {
|
|
|
544
546
|
};
|
|
545
547
|
const crownsOf = (so) => specOf(so).parts.filter((p) => /^(s\d+_)?crown\d*$/.test(p.id)).map((p) => p.id);
|
|
546
548
|
const jointPos = (so, jid) => {
|
|
547
|
-
const j = specOf(so).joints.filter((x) => x.id === jid)[0];
|
|
549
|
+
const j = (specOf(so).joints ?? []).filter((x) => x.id === jid)[0];
|
|
548
550
|
const a = partSpec(so, j.a);
|
|
549
551
|
const b = partSpec(so, j.b);
|
|
550
552
|
const box = (p) => {
|
|
551
|
-
const
|
|
553
|
+
const sh = p.shape;
|
|
554
|
+
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];
|
|
552
555
|
const r = p.rotation || [0, 0, 0];
|
|
553
556
|
const cx = Math.cos(r[0]), sx = Math.sin(r[0]), cz = Math.cos(r[2]), sz = Math.sin(r[2]);
|
|
554
557
|
const mn = [Infinity, Infinity, Infinity];
|
|
@@ -575,6 +578,16 @@ function createScenarios(locale) {
|
|
|
575
578
|
if (!p) return null;
|
|
576
579
|
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 };
|
|
577
580
|
};
|
|
581
|
+
const snapAt = (room, so, pid) => {
|
|
582
|
+
const p = snap(room, so, pid);
|
|
583
|
+
if (!p) throw new Error(`game-vegetation-three: no part "${pid}" in ${so.objectId}`);
|
|
584
|
+
return p;
|
|
585
|
+
};
|
|
586
|
+
const stateAt = (room, id) => {
|
|
587
|
+
const st = room.world.state(id);
|
|
588
|
+
if (!st) throw new Error(`game-vegetation-three: no object ${id} in the world`);
|
|
589
|
+
return st;
|
|
590
|
+
};
|
|
578
591
|
const logCount = (room, so, type) => room.log.entries({ type, objectId: so.objectId }).length;
|
|
579
592
|
const jointsOpened = (room, so) => {
|
|
580
593
|
let n = 0;
|
|
@@ -586,7 +599,11 @@ function createScenarios(locale) {
|
|
|
586
599
|
const spawn = (room, id, x, z) => room.spawn(id, [x, 0, z], 0);
|
|
587
600
|
const split = (room, so) => {
|
|
588
601
|
const home = room.world.snapshot(so.objectId);
|
|
589
|
-
|
|
602
|
+
if (!home) throw new Error(`game-vegetation-three: no object ${so.objectId} in the world`);
|
|
603
|
+
const loose = room.world.ids().filter((i) => /^obj_/.test(i)).flatMap((i) => {
|
|
604
|
+
const st = room.world.snapshot(i);
|
|
605
|
+
return st ? [{ id: i, st }] : [];
|
|
606
|
+
});
|
|
590
607
|
const anchored = {};
|
|
591
608
|
for (const p of specOf(so).parts) if (p.anchored) anchored[p.id] = true;
|
|
592
609
|
const rooted = [];
|
|
@@ -598,7 +615,8 @@ function createScenarios(locale) {
|
|
|
598
615
|
const fell = (room, ctx, so, max) => {
|
|
599
616
|
take(room, "axe");
|
|
600
617
|
let swings = 0;
|
|
601
|
-
const
|
|
618
|
+
const trunkShape = partSpec(so, "trunk").shape;
|
|
619
|
+
const h = trunkShape.kind === "cylinder" ? trunkShape.height : trunkShape.kind === "box" ? trunkShape.size[1] : trunkShape.radius * 2;
|
|
602
620
|
for (let i = 0; i < max; i++) {
|
|
603
621
|
aimPart(room, so, "trunk", 0.5, [0, Math.min(0.9, h / 3), 0]);
|
|
604
622
|
room.use();
|
|
@@ -607,7 +625,7 @@ function createScenarios(locale) {
|
|
|
607
625
|
if (lost(room.world.part(so.objectId, "trunk"))) break;
|
|
608
626
|
}
|
|
609
627
|
ctx.step(5);
|
|
610
|
-
return { swings, trunk:
|
|
628
|
+
return { swings, trunk: snapAt(room, so, "trunk") };
|
|
611
629
|
};
|
|
612
630
|
const sc = (id, ptName, enName, run) => ({ id: `veg_${id}`, name: L(ptName, enName), run });
|
|
613
631
|
const pct = (x) => `${Math.round((x || 0) * 100)}%`;
|
|
@@ -623,7 +641,7 @@ function createScenarios(locale) {
|
|
|
623
641
|
const r = fell(room, ctx, so, 60);
|
|
624
642
|
const sp = split(room, so);
|
|
625
643
|
const crownGone = lost(room.world.part(so.objectId, "crown")) || !sp.inHome("crown") || sp.rooted.indexOf("crown") < 0;
|
|
626
|
-
const branches = specOf(so).parts.filter((p) => p.tags.indexOf("branch") >= 0).map((p) => p.id);
|
|
644
|
+
const branches = specOf(so).parts.filter((p) => (p.tags ?? []).indexOf("branch") >= 0).map((p) => p.id);
|
|
627
645
|
const branchesFree = branches.every((b) => sp.rooted.indexOf(b) < 0);
|
|
628
646
|
const detach = jointsOpened(room, so);
|
|
629
647
|
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 });
|
|
@@ -653,7 +671,7 @@ function createScenarios(locale) {
|
|
|
653
671
|
detached = detachedJoint(room, so, jid);
|
|
654
672
|
}
|
|
655
673
|
ctx.step(3);
|
|
656
|
-
const trunk =
|
|
674
|
+
const trunk = snapAt(room, so, "trunk");
|
|
657
675
|
const sp = split(room, so);
|
|
658
676
|
const branchOff = sp.inLoose("branch1") && !sp.inHome("branch1");
|
|
659
677
|
const restStays = sp.inHome("trunk") && sp.rooted.indexOf("trunk") >= 0;
|
|
@@ -671,7 +689,7 @@ function createScenarios(locale) {
|
|
|
671
689
|
ctx.step(0.4);
|
|
672
690
|
shots++;
|
|
673
691
|
}
|
|
674
|
-
const trunk =
|
|
692
|
+
const trunk = snapAt(room, so, "trunk");
|
|
675
693
|
const sp = split(room, so);
|
|
676
694
|
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 });
|
|
677
695
|
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)`), {});
|
|
@@ -701,21 +719,21 @@ function createScenarios(locale) {
|
|
|
701
719
|
take(room, "lighter");
|
|
702
720
|
const a = aimPart(room, so, crownsOf(so), 0.08);
|
|
703
721
|
room.use(6);
|
|
704
|
-
const crown =
|
|
722
|
+
const crown = snapAt(room, so, a.pid);
|
|
705
723
|
const lit = crown.burning || crown.temperature > 300;
|
|
706
724
|
let peak = 0;
|
|
707
725
|
let charMax = 0;
|
|
708
726
|
for (let t = 0; t < 18; t++) {
|
|
709
727
|
ctx.step(5);
|
|
710
|
-
for (const p of room
|
|
728
|
+
for (const p of stateAt(room, so.objectId).parts) {
|
|
711
729
|
if (p.material === "green_wood") {
|
|
712
730
|
peak = Math.max(peak, p.temperature);
|
|
713
731
|
charMax = Math.max(charMax, p.char || 0);
|
|
714
732
|
}
|
|
715
733
|
}
|
|
716
734
|
}
|
|
717
|
-
const st = room
|
|
718
|
-
const burnt = st.parts.filter((p) => p.material === "foliage" && (p.burning || p.char > 0 || p.status === "ashes")).length;
|
|
735
|
+
const st = stateAt(room, so.objectId);
|
|
736
|
+
const burnt = st.parts.filter((p) => p.material === "foliage" && (p.burning || (p.char ?? 0) > 0 || p.status === "ashes")).length;
|
|
719
737
|
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 });
|
|
720
738
|
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 });
|
|
721
739
|
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 });
|
|
@@ -726,13 +744,13 @@ function createScenarios(locale) {
|
|
|
726
744
|
const so = spawn(room, "mango_tree", 0, -6);
|
|
727
745
|
take(room, "pistol_9mm");
|
|
728
746
|
const tgt = aimPart(room, so, crownsOf(so), 2.5).pid;
|
|
729
|
-
const before =
|
|
747
|
+
const before = snapAt(room, so, tgt);
|
|
730
748
|
for (let i = 0; i < 3; i++) {
|
|
731
749
|
aimPart(room, so, tgt, 2.5);
|
|
732
750
|
room.use();
|
|
733
751
|
ctx.step(0.6);
|
|
734
752
|
}
|
|
735
|
-
const crown =
|
|
753
|
+
const crown = snapAt(room, so, tgt);
|
|
736
754
|
const leaves = room.log.entries({ type: "debris", objectId: so.objectId }).filter((e) => e.data && e.data.kind === "leaves").length;
|
|
737
755
|
const hurt = crown.hp < before.hp || crown.status === "broken";
|
|
738
756
|
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 });
|
|
@@ -789,8 +807,8 @@ function createScenarios(locale) {
|
|
|
789
807
|
const a = snap(room, so, arm);
|
|
790
808
|
const sp = split(room, so);
|
|
791
809
|
const armOff = !a || a.status === "broken" || sp.inLoose(arm) && !sp.inHome(arm);
|
|
792
|
-
const stemOk = sp.inHome("stem") && sp.rooted.indexOf("stem") >= 0 && room.world.part(so.objectId, "stem")
|
|
793
|
-
const spines = specOf(so).parts.filter((p) => p.tags.indexOf("thorns") >= 0);
|
|
810
|
+
const stemOk = sp.inHome("stem") && sp.rooted.indexOf("stem") >= 0 && room.world.part(so.objectId, "stem")?.status !== "broken";
|
|
811
|
+
const spines = specOf(so).parts.filter((p) => (p.tags ?? []).indexOf("thorns") >= 0);
|
|
794
812
|
const thorny = so.root.userData.thorny === true && spines.length > 0;
|
|
795
813
|
const spinesOff = !sp.rooted.some((pid) => pid.indexOf(`${arm}_spines`) === 0);
|
|
796
814
|
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 });
|
|
@@ -825,11 +843,11 @@ function createScenarios(locale) {
|
|
|
825
843
|
aimPart(room, so, "trunk", 0.08, [0, 0.8, 0]);
|
|
826
844
|
room.use(8);
|
|
827
845
|
}
|
|
828
|
-
const d0 =
|
|
829
|
-
const l0 =
|
|
846
|
+
const d0 = snapAt(room, dead, "trunk");
|
|
847
|
+
const l0 = snapAt(room, live, "trunk");
|
|
830
848
|
ctx.step(120);
|
|
831
|
-
const d =
|
|
832
|
-
const l =
|
|
849
|
+
const d = snapAt(room, dead, "trunk");
|
|
850
|
+
const l = snapAt(room, live, "trunk");
|
|
833
851
|
const score = (p) => p ? Math.max(p.char, p.burning ? 0.01 : 0, (p.temperature - 20) / 2e3) : 0;
|
|
834
852
|
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 });
|
|
835
853
|
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) });
|
|
@@ -859,7 +877,7 @@ function createScenarios(locale) {
|
|
|
859
877
|
const tuft = spawn(room, "lawn_tuft", 0, -3);
|
|
860
878
|
const tree = spawn(room, "mango_tree", 4, -3);
|
|
861
879
|
const noBlock = !tuft.root.userData.collider;
|
|
862
|
-
const treeBlock = !!
|
|
880
|
+
const treeBlock = !!tree.root.userData.collider?.kind;
|
|
863
881
|
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)`), {});
|
|
864
882
|
room.look([0, 1.7, -0.5], [0, 1.7, -6]);
|
|
865
883
|
const before = room.camera.position.z;
|
|
@@ -943,6 +961,7 @@ var VEGETATION_SCENARIO_IDS = [
|
|
|
943
961
|
"veg_hedge_cut_pieces",
|
|
944
962
|
"veg_walk_on_grass"
|
|
945
963
|
];
|
|
964
|
+
var isMesh2 = (o) => o.isMesh === true;
|
|
946
965
|
var defaultSdk = () => ({ ...GameVegetationMain, ...GameVegetationAdapter });
|
|
947
966
|
var AXIS_COLOURS = { trunk: 14254635, branch: 15057019, arm: 7327599, stem: 7327639, pad: 7321551 };
|
|
948
967
|
function createVegetationTestModule(options = {}) {
|
|
@@ -1000,7 +1019,7 @@ function createVegetationTestModule(options = {}) {
|
|
|
1000
1019
|
}
|
|
1001
1020
|
for (const mesh of root.children) {
|
|
1002
1021
|
const v = mesh.userData?.veg;
|
|
1003
|
-
if (!v || !mesh.geometry) continue;
|
|
1022
|
+
if (!v || !isMesh2(mesh) || !mesh.geometry) continue;
|
|
1004
1023
|
if (host.bench.layer("piece_boxes")) {
|
|
1005
1024
|
mesh.geometry.computeBoundingBox();
|
|
1006
1025
|
const box = mesh.geometry.boundingBox.clone().translate(mesh.position);
|
|
@@ -1104,7 +1123,7 @@ function createVegetationTestModule(options = {}) {
|
|
|
1104
1123
|
let pieces = 0;
|
|
1105
1124
|
for (const entry of placed.values()) {
|
|
1106
1125
|
entry.root.traverse((mesh) => {
|
|
1107
|
-
if (!mesh
|
|
1126
|
+
if (!isMesh2(mesh) || mesh.userData.helper) return;
|
|
1108
1127
|
for (let p = mesh; p; p = p.parent) if (p.visible === false) return;
|
|
1109
1128
|
drawCalls += 1;
|
|
1110
1129
|
if (mesh.userData.veg) pieces += 1;
|
|
@@ -1117,7 +1136,7 @@ function createVegetationTestModule(options = {}) {
|
|
|
1117
1136
|
const lotCalls = () => {
|
|
1118
1137
|
let calls = 0;
|
|
1119
1138
|
nursery?.group.traverse((o) => {
|
|
1120
|
-
if (o
|
|
1139
|
+
if (isMesh2(o) && o.visible) calls += 1;
|
|
1121
1140
|
});
|
|
1122
1141
|
return calls;
|
|
1123
1142
|
};
|
|
@@ -1223,4 +1242,4 @@ export {
|
|
|
1223
1242
|
createVegetationTestModule,
|
|
1224
1243
|
loadVegetationTestModule
|
|
1225
1244
|
};
|
|
1226
|
-
//# sourceMappingURL=chunk-
|
|
1245
|
+
//# sourceMappingURL=chunk-2DJB2FIT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/test-area/module.ts","../src/test-area/nursery.ts","../src/test-area/plants.ts","../src/test-area/scenarios.ts","../src/test-area/text.ts"],"sourcesContent":["import type * as THREE_NS from 'three'\nimport { discardObject3D } from '@adatechnology/game-shapes-three'\nimport type { BenchChange, ModuleArea, ModuleControl, ModuleHost, ModuleLayer, ModuleMetric, ModuleScenario, TestableItem, TestableModule, Vec3 } from '@adatechnology/game-contracts'\nimport { shapeGeometries } from '@adatechnology/game-shapes-three'\nimport * as GameVegetationMain from '@adatechnology/game-vegetation'\nimport * as GameVegetationAdapter from '@adatechnology/game-vegetation/three'\nimport * as GameVegetationSpeciesMain from '@adatechnology/game-vegetation-species'\nimport type { Condition, Lod, Season } from '@adatechnology/game-vegetation'\n\nimport { createNursery } from './nursery'\nimport type { Nursery } from './nursery'\nimport { createPlants, PLANT_DEFS, PLANT_SEED } from './plants'\nimport type { PieceMeta } from './plants'\nimport { createScenarios } from './scenarios'\nimport { fill, TEXT } from './text'\nimport type { MaterialsLike, SpeciesSdk, VegetationContext, VegetationSdk, VegetationTestOptions } from './types'\n\nexport const VEGETATION_AREA_ID = 'vegetation'\n\n/** The 18 item ids of the Viveiro's module, in its order. */\nexport const VEGETATION_ITEM_IDS: readonly string[] = PLANT_DEFS.map((def) => def.id)\n\n/** The ids of the 13 scenarios (the ids of the Viveiro's page, `veg_*`). */\nexport const VEGETATION_SCENARIO_IDS: readonly string[] = [\n 'veg_axe_fells_crown',\n 'veg_axe_fells_30cm',\n 'veg_axe_cuts_branch_joint',\n 'veg_shot_cannot_fell',\n 'veg_saw_cuts_branch',\n 'veg_lighter_ignites_foliage',\n 'veg_shot_strips_leaves',\n 'veg_shot_breaks_pot',\n 'veg_machete_arm',\n 'veg_pad_pulled',\n 'veg_dead_burns_faster',\n 'veg_hedge_cut_pieces',\n 'veg_walk_on_grass',\n]\n\ntype Three = typeof THREE_NS\n\n/** A mesh, as three marks one (`isMesh`). */\nconst isMesh = (o: THREE_NS.Object3D): o is THREE_NS.Mesh => (o as THREE_NS.Mesh).isMesh === true\ntype Placed = { readonly root: THREE_NS.Object3D; helpers: THREE_NS.Object3D[] }\n\nconst defaultSdk = (): VegetationSdk => ({ ...GameVegetationMain, ...GameVegetationAdapter }) as VegetationSdk\nconst AXIS_COLOURS: Record<string, number> = { trunk: 0xd9822b, branch: 0xe5c07b, arm: 0x6fcf6f, stem: 0x6fcf97, pad: 0x6fb7cf }\n\n/**\n * The vegetation test area as a `TestableModule`: the 18 plants of the Viveiro (mango trees of three sizes, ipe, palm, banana, araucaria, dead tree, hibiscus, hedge, rose, sunflower, three\n * cacti, two pots, a lawn tuft) as items of the default destruction world, each piece a mesh with its spec (shape from the real wood thickness, joints, anchors, tags, sway clip), and the 13\n * scenarios of that page (literal). The bench plants the nursery lot (12 x 20 m, with house, walls and path, by `scatterRulesFor`) with its seed, quality, detail, condition and season, sets\n * the wind and starts the walker that bends the plants; its layers show the colliders, the boxes of the pieces and the axes of the wood; its metrics read triangles, pieces and draw calls.\n */\nexport function createVegetationTestModule(options: VegetationTestOptions = {}): TestableModule<VegetationContext> & { readonly placed: ReadonlyMap<string, unknown>; materials(THREE?: unknown): MaterialsLike; tick(t: number): void; readonly itemIds: readonly string[] } {\n const locale = options.locale ?? 'pt-BR'\n const text = TEXT[locale.toLowerCase().startsWith('en') ? 'en' : 'pt-BR'] as (typeof TEXT)[string]\n const sdk: VegetationSdk = options.GameVegetation ?? defaultSdk()\n const species: SpeciesSdk = options.GameVegetationSpecies ?? (GameVegetationSpeciesMain as SpeciesSdk)\n let mats: MaterialsLike | null = options.materials ?? null\n let three = null as unknown as Three // the room's three.js: set by the first build or by attach, before anything is drawn\n let host: ModuleHost | null = null\n const materials = (THREE?: unknown): MaterialsLike => {\n if (!mats) mats = sdk.createVegetationMaterials((THREE ?? three) as never) as unknown as MaterialsLike\n return mats\n }\n const plants = createPlants(sdk, species, (THREE) => materials(THREE), options.seed ?? PLANT_SEED)\n const placed = new Map<string, Placed>()\n const settings = { seed: 1, quality: 'high' as 'high' | 'game', lod: 0 as Lod, condition: 'healthy' as Condition, season: 'spring' as Season, wind: 0.35, gust: 0.15 }\n let nursery: Nursery | null = null\n let clock = 0\n let helpersShown = ''\n\n const item = (base: TestableItem): TestableItem => ({\n ...base,\n build: (THREE: unknown) => {\n three = THREE as Three // the room hands its three.js namespace\n const root = base.build(THREE) as THREE_NS.Object3D\n placed.set(root.uuid, { root, helpers: [] })\n return root\n },\n })\n\n // ---- the layers ---------------------------------------------------------------------------------------------------------------------------\n const clearHelpers = (): void => {\n for (const entry of placed.values()) {\n discardObject3D(entry.helpers)\n entry.helpers = []\n }\n helpersShown = ''\n }\n const boxKey = (): string => `${host?.bench?.layer('colliders')}|${host?.bench?.layer('piece_boxes')}|${host?.bench?.layer('wood_axes')}|${placed.size}`\n const refreshLayers = (): void => {\n if (!host?.bench || !three) return\n clearHelpers()\n nursery?.showColliders(host.bench.layer('colliders'))\n for (const entry of placed.values()) {\n const root = entry.root\n if (!root.parent) continue\n const mark = (helper: THREE_NS.Object3D): void => {\n helper.userData.helper = true\n root.add(helper)\n entry.helpers.push(helper)\n }\n if (host.bench.layer('colliders') && root.userData.collider && root.userData.collider.kind) {\n const c = root.userData.collider\n const wire = new three.Mesh(new (shapeGeometries(three)).CylinderGeometry(c.radius, c.radius, c.height, 14, 1, true), new three.MeshBasicMaterial({ color: root.userData.thorny ? 0xff7a1a : 0xe5251d, wireframe: true }))\n wire.position.set(0, c.height / 2, 0)\n mark(wire)\n }\n for (const mesh of root.children) {\n const v = mesh.userData?.veg as PieceMeta | undefined\n if (!v || !isMesh(mesh) || !mesh.geometry) continue\n if (host.bench.layer('piece_boxes')) {\n mesh.geometry.computeBoundingBox()\n const box = mesh.geometry.boundingBox!.clone().translate(mesh.position)\n mark(new three.Box3Helper(box, 0x66ccff))\n }\n if (host.bench.layer('wood_axes') && v.radius !== undefined && v.length !== undefined && v.axis && !v.sub) {\n // the base of the piece is in plant space; the section of a hedge stands `dx` to the side\n const base = pieceBase(root, v)\n if (base) {\n const from = new three.Vector3(base[0] + v.dx, base[1], base[2])\n const to = from.clone().add(new three.Vector3(v.axis[0], v.axis[1], v.axis[2]).multiplyScalar(v.length))\n const line = new three.Line(new three.BufferGeometry().setFromPoints([from, to]), new three.LineBasicMaterial({ color: AXIS_COLOURS[v.kind] ?? 0xffffff }))\n mark(line)\n }\n }\n }\n }\n helpersShown = boxKey()\n }\n // the `base` of a wood piece is recorded on the destruction part of its mesh by the SDK; the module keeps it in `userData.destructionPart` of the mesh\n const pieceBase = (root: THREE_NS.Object3D, v: PieceMeta): Vec3 | null => {\n const mesh = root.children.find((c) => (c.userData?.veg as PieceMeta | undefined)?.id === v.id)\n const base = mesh?.userData?.destructionPart?.base\n return Array.isArray(base) ? (base as Vec3) : null\n }\n\n // ---- the nursery ----------------------------------------------------------------------------------------------------------------------------\n const nurseryOf = (): Nursery | null => {\n if (!host || !three) return null\n if (!nursery) nursery = createNursery(sdk, species, three, materials(three), host.scene as THREE_NS.Object3D, options.nurseryOrigin ?? [-6, 14])\n return nursery\n }\n const plantLot = (): void => {\n const n = nurseryOf()\n if (!n || !host) return\n const stats = n.plant(settings)\n n.showColliders(Boolean(host.bench?.layer('colliders')))\n host.log(fill(text.lot.planted, stats.plants, stats.triangles, stats.colliders), { plants: stats.plants, triangles: stats.triangles })\n }\n const replant = (): void => {\n if (nursery?.planted) plantLot()\n }\n\n // ---- the bench ---------------------------------------------------------------------------------------------------------------------------------\n const applyWind = (): void => {\n if (mats) mats.setWind({ strength: settings.wind, gust: settings.gust })\n }\n const onChange = (change: BenchChange): void => {\n if (change.kind === 'layer') return refreshLayers()\n if (change.kind === 'action') {\n if (change.id === 'plant_lot') plantLot()\n else if (change.id === 'clear_lot') {\n nursery?.clear()\n host?.log(text.lot.cleared)\n } else if (change.id === 'toggle_walker') {\n const n = nurseryOf()\n if (!n) return\n if (!n.planted) plantLot()\n n.setWalker(!n.walking)\n host?.log(n.walking ? text.lot.walker_on : text.lot.walker_off)\n }\n return\n }\n switch (change.id) {\n case 'seed': settings.seed = Number(change.value); replant(); break\n case 'quality': settings.quality = String(change.value) as 'high' | 'game'; replant(); break\n case 'lod': settings.lod = Number(change.value) as Lod; replant(); break\n case 'condition': settings.condition = String(change.value) as Condition; replant(); break\n case 'season': settings.season = String(change.value) as Season; replant(); break\n case 'wind': settings.wind = Number(change.value); applyWind(); break\n case 'gust': settings.gust = Number(change.value); applyWind(); break\n default: break\n }\n }\n\n const frame = (dt: number): void => {\n clock += dt\n if (mats) mats.update(clock)\n for (const [id, entry] of placed) if (!entry.root.parent) placed.delete(id)\n if (host?.bench && boxKey() !== helpersShown && (host.bench.layer('colliders') || host.bench.layer('piece_boxes') || host.bench.layer('wood_axes') || helpersShown !== '')) refreshLayers()\n nursery?.step(dt)\n }\n\n const count = (): { drawCalls: number; triangles: number; pieces: number } => {\n let drawCalls = 0\n let triangles = 0\n let pieces = 0\n for (const entry of placed.values()) {\n entry.root.traverse((mesh) => {\n if (!isMesh(mesh) || mesh.userData.helper) return\n for (let p: THREE_NS.Object3D | null = mesh; p; p = p.parent) if (p.visible === false) return\n drawCalls += 1\n if (mesh.userData.veg) pieces += 1\n const g = mesh.geometry\n triangles += (g.index ? g.index.count : g.attributes.position.count) / 3\n })\n }\n return { drawCalls, triangles: Math.round(triangles), pieces }\n }\n const lotCalls = (): number => {\n let calls = 0\n nursery?.group.traverse((o) => {\n if (isMesh(o) && o.visible) calls += 1\n })\n return calls\n }\n\n return {\n id: VEGETATION_AREA_ID,\n name: text.name,\n ground: { surface: 'lawn' },\n group: text.group,\n get placed() {\n return placed\n },\n itemIds: VEGETATION_ITEM_IDS,\n materials,\n tick: (t: number) => {\n if (mats) mats.update(t)\n },\n items: (loc: string) => plants.items(loc || locale).map(item),\n scenarios: (loc: string): ModuleScenario<VegetationContext>[] => createScenarios(loc || locale),\n area: (): ModuleArea => {\n // three rows by size, each plant given room by its width: the small ones in front, the middle ones behind them, the trees at the back\n const rows: { z: number; ids: readonly string[] }[] = [\n { z: -4, ids: ['hibiscus_shrub', 'rose_bush_red', 'sunflower', 'mandacaru', 'prickly_pear', 'crown_cactus'] },\n { z: -9, ids: ['banana_with_bunch', 'dead_tree', 'boxwood_hedge', 'potted_fern', 'potted_cactus', 'lawn_tuft'] },\n { z: -16, ids: ['mango_tree', 'yellow_ipe', 'coconut_palm', 'araucaria', 'mango_young_30', 'mango_young_15'] },\n ]\n const widths: Record<string, number> = { mango_tree: 5, yellow_ipe: 5, coconut_palm: 4.5, araucaria: 4, mango_young_30: 3, mango_young_15: 2.6, banana_with_bunch: 3.5, dead_tree: 3.5, boxwood_hedge: 5.5, hibiscus_shrub: 2, rose_bush_red: 1.6, sunflower: 1.4, mandacaru: 2.2, prickly_pear: 2, crown_cactus: 1.8, potted_fern: 1.4, potted_cactus: 1.2, lawn_tuft: 1.2 }\n const gap = 1.2\n const placements = rows.flatMap((row) => {\n const total = row.ids.reduce((sum, id) => sum + (widths[id] ?? 2) + gap, -gap)\n let cursor = -total / 2\n return row.ids.map((id) => {\n const width = widths[id] ?? 2\n const x = cursor + width / 2\n cursor += width + gap\n return { item: id, position: [x, 0, row.z] as Vec3, rotationY: 0 }\n })\n })\n return { placements, view: { eye: [0, 6, 8], target: [0, 1.8, -10] } }\n },\n controls: (): ModuleControl[] => [\n { kind: 'number', id: 'seed', name: text.controls.seed, hint: text.hints.seed, min: 0, max: 99999, step: 1, default: 1 },\n { kind: 'choice', id: 'quality', name: text.controls.quality, hint: text.hints.quality, options: (['high', 'game'] as const).map((id) => ({ id, name: text.options.quality[id] as string })), default: 'high' },\n { kind: 'choice', id: 'lod', name: text.controls.lod, hint: text.hints.lod, options: (['0', '1', '2'] as const).map((id) => ({ id, name: text.options.lod[id] as string })), default: '0' },\n { kind: 'choice', id: 'condition', name: text.controls.condition, hint: text.hints.condition, options: (['healthy', 'dry', 'dead', 'overgrown'] as const).map((id) => ({ id, name: text.options.condition[id] as string })), default: 'healthy' },\n { kind: 'choice', id: 'season', name: text.controls.season, hint: text.hints.season, options: (['spring', 'summer', 'autumn', 'winter'] as const).map((id) => ({ id, name: text.options.season[id] as string })), default: 'spring' },\n { kind: 'number', id: 'wind', name: text.controls.wind, hint: text.hints.wind, min: 0, max: 1, step: 0.05, default: 0.35 },\n { kind: 'number', id: 'gust', name: text.controls.gust, hint: text.hints.gust, min: 0, max: 1, step: 0.05, default: 0.15 },\n { kind: 'action', id: 'plant_lot', name: text.actions.plant_lot, slow: true },\n { kind: 'action', id: 'clear_lot', name: text.actions.clear_lot },\n { kind: 'action', id: 'toggle_walker', name: text.actions.toggle_walker, slow: true },\n ],\n layers: (): ModuleLayer[] => (['colliders', 'piece_boxes', 'wood_axes'] as const).map((id) => ({ id, name: text.layers[id], default: false })),\n metrics: (): ModuleMetric[] => [\n { id: 'plants', name: text.metrics.plants, read: () => placed.size },\n { id: 'pieces', name: text.metrics.pieces, read: () => count().pieces },\n { id: 'triangles', name: text.metrics.triangles, read: () => count().triangles },\n { id: 'draw_calls', name: text.metrics.draw_calls, read: () => count().drawCalls + lotCalls() },\n { id: 'lot_triangles', name: text.metrics.lot_triangles, read: () => nursery?.stats?.triangles ?? 0 },\n { id: 'lot_plants', name: text.metrics.lot_plants, read: () => nursery?.stats?.plants ?? 0 },\n { id: 'lot_colliders', name: text.metrics.lot_colliders, read: () => nursery?.stats?.colliders ?? 0 },\n { id: 'lot_lod0', name: text.metrics.lot_lod0, read: () => nursery?.stats?.lod[0] ?? 0 },\n { id: 'lot_lod1', name: text.metrics.lot_lod1, read: () => nursery?.stats?.lod[1] ?? 0 },\n { id: 'lot_lod2', name: text.metrics.lot_lod2, read: () => nursery?.stats?.lod[2] ?? 0 },\n { id: 'lot_ms', name: text.metrics.lot_ms, unit: 'ms', read: () => nursery?.stats?.buildMs ?? 0 },\n ],\n attach(lent) {\n host = lent\n three = lent.THREE as Three\n const stopChange = lent.bench?.onChange(onChange)\n const stopFrame = lent.onFrame(frame)\n applyWind()\n return () => {\n stopChange?.()\n stopFrame()\n clearHelpers()\n nursery?.clear()\n nursery = null\n host = null\n }\n },\n }\n}\n\n/** What `loadVegetationTestModule` needs of a room: `TestRoom.loadModule` has it. */\nexport type ModuleRoomLike = { loadModule(module: never): unknown }\n\n/** Loads the vegetation module into a room. */\nexport function loadVegetationTestModule<Room extends ModuleRoomLike>(room: Room, options: VegetationTestOptions = {}): ReturnType<Room['loadModule']> {\n return room.loadModule(createVegetationTestModule(options) as never) as ReturnType<Room['loadModule']>\n}\n","import type * as THREE_NS from 'three'\nimport type { Condition, Lod, Placement, Season } from '@adatechnology/game-vegetation'\nimport type { ScatterRulesOptions } from '@adatechnology/game-vegetation-species'\nimport { shapeGeometries } from '@adatechnology/game-shapes-three'\n\nimport type { MaterialsLike, SpeciesSdk, VegetationSdk } from './types'\n\ntype Three = typeof THREE_NS\n\n/** A mesh, as three marks one (`isMesh`). */\nconst isMesh = (o: THREE_NS.Object3D): o is THREE_NS.Mesh => (o as THREE_NS.Mesh).isMesh === true\n\n/** The plot of the Viveiro's lot demo, in metres: the corner at (0, 0), the street on the negative z side. */\nexport const LOT = { W: 12, D: 20 } as const\nexport const HOUSE = { x0: 2.5, x1: 9.5, z0: 6.5, z1: 13 } as const\n/** The walker's route (x, z). */\nexport const WAY: readonly (readonly [number, number])[] = [[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]]\n\ntype Rect = { rect: { x: number; z: number; w: number; d: number } }\nexport const EX_HOUSE: Rect = { rect: { x: HOUSE.x0 - 0.7, z: HOUSE.z0 - 0.7, w: HOUSE.x1 - HOUSE.x0 + 1.4, d: HOUSE.z1 - HOUSE.z0 + 1.4 } }\nexport const EX_PATH: Rect = { rect: { x: 5.1, z: 0, w: 1.8, d: HOUSE.z0 } }\n/** Where each kind of planting goes. */\nexport const AREAS: Readonly<Record<'front_yard' | 'backyard' | 'sides' | 'sidewalk_tree', Rect[]>> = {\n front_yard: [{ rect: { x: 0.5, z: 0.5, w: 11, d: 5.6 } }],\n backyard: [{ rect: { x: 0.5, z: 13.7, w: 11, d: 5.8 } }],\n sides: [{ rect: { x: 0.5, z: 6.2, w: 1.3, d: 7.4 } }, { rect: { x: 10.2, z: 6.2, w: 1.3, d: 7.4 } }],\n sidewalk_tree: [{ rect: { x: 0.8, z: -1.9, w: 10.4, d: 1.2 } }],\n}\n\n/** The four plantings of the lot: the context of the regional table, where, how many of each group, and the tag of the scatter seed. */\nexport type Planting = { context: string; areas: Rect[]; options: ScatterRulesOptions & { n: number }; tag: string }\nexport const PLANTINGS: readonly Planting[] = [\n { context: 'front_yard', areas: AREAS.front_yard, options: { n: 12, noLarge: true, maxCount: { trees: 1, hedges: 10, mid: 14, ground: 40 } }, tag: 'f' },\n { context: 'backyard', areas: AREAS.backyard, options: { n: 14, maxCount: { trees: 3, hedges: 4, mid: 12, ground: 50 } }, tag: 'b' },\n { context: 'front_yard', areas: AREAS.sides, options: { n: 8, noLarge: true, maxCount: { trees: 0, hedges: 4, mid: 6, ground: 14 } }, tag: 's' },\n { context: 'sidewalk_tree', areas: AREAS.sidewalk_tree, options: { n: 4, treeDensity: 0.3, maxCount: { trees: 2, hedges: 0, mid: 0, ground: 0 } }, tag: 'c' },\n]\n\nexport type NurserySettings = { seed: number; quality: 'high' | 'game'; lod: Lod; condition: Condition; season: Season }\n\nexport type LotStats = { triangles: number; plants: number; colliders: number; meshes: number; lod: [number, number, number]; buildMs: number; species: number }\n\n/**\n * The scatter of the lot: the same picks, rules and placements as the Viveiro's `buildLotVeg`. Every planting draws its species from the regional table of its context, splits\n * them into trees, hedges, middle layer and ground cover, and scatters each group over the areas of the plot without touching the house or the path.\n */\nexport function scatterLot(sdk: VegetationSdk, species: SpeciesSdk, seedNumber: number, plantings: readonly Planting[] = PLANTINGS): { placements: Placement[]; used: Set<string> } {\n const seed = `quintal-${seedNumber}`\n const placements: Placement[] = []\n const used = new Set<string>()\n for (const planting of plantings) {\n const { rules, picks } = species.scatterRulesFor(species.regions.br, planting.context, seed, planting.options)\n for (const p of picks) used.add(p.id)\n planting.areas.forEach((area, i) => {\n const exclude = [EX_HOUSE, EX_PATH]\n const perArea = rules.map((rule) => ({ ...rule, maxCount: Math.max(1, Math.ceil((rule.maxCount as number) / planting.areas.length)) }))\n placements.push(...sdk.scatter(area as never, perArea, { seed: `${seed}:${planting.tag}:${i}`, exclude: exclude as never }))\n })\n }\n return { placements, used }\n}\n\n/** The static scenery of the plot: ground, street, sidewalk, path, house and walls. Simple boxes; the room's own floor is under it. */\nfunction buildScenery(THREE: Three): THREE_NS.Group {\n const g = new THREE.Group()\n g.name = 'nursery-scenery'\n const material = (color: number, roughness = 0.9): THREE_NS.MeshStandardMaterial => new THREE.MeshStandardMaterial({ color, roughness, metalness: 0 })\n const mats = { ground: material(0x5f7d45), asphalt: material(0x3a3d42), concrete: material(0xb7b3a8), house: material(0xe3d6bd), roof: material(0x9a4d38), door: material(0x6b4a2f), glass: material(0x9fc7dd, 0.2), wall: material(0xc9c2b2) }\n const box = (w: number, h: number, d: number, m: THREE_NS.Material, x: number, y: number, z: number): THREE_NS.Mesh => {\n const mesh = new THREE.Mesh(new THREE.BoxGeometry(w, h, d), m)\n mesh.position.set(x, y, z)\n mesh.castShadow = mesh.receiveShadow = true\n g.add(mesh)\n return mesh\n }\n const yard = new THREE.Mesh(new THREE.PlaneGeometry(LOT.W, LOT.D), mats.ground)\n yard.rotation.x = -Math.PI / 2\n yard.position.set(6, 0.01, 10)\n yard.receiveShadow = true\n g.add(yard)\n box(30, 0.04, 4.6, mats.asphalt, 6, 0.0, -4.6) // street\n box(30, 0.1, 2.2, mats.concrete, 6, 0.04, -1.1) // sidewalk\n box(1.6, 0.03, 6.6, mats.concrete, 6, 0.02, 3.2) // path to the door\n const hw = HOUSE.x1 - HOUSE.x0\n const hd = HOUSE.z1 - HOUSE.z0\n const hcx = (HOUSE.x0 + HOUSE.x1) / 2\n const hcz = (HOUSE.z0 + HOUSE.z1) / 2\n box(hw, 2.8, hd, mats.house, hcx, 1.4, hcz)\n const roof = new THREE.Mesh(new THREE.ConeGeometry(1, 1.5, 4), mats.roof)\n roof.rotation.y = Math.PI / 4\n roof.scale.set((hw + 1.2) / Math.SQRT2, 1, (hd + 1.2) / Math.SQRT2)\n roof.position.set(hcx, 2.8 + 0.75, hcz)\n roof.castShadow = roof.receiveShadow = true\n g.add(roof)\n box(1.1, 2.1, 0.08, mats.door, 6, 1.05, HOUSE.z0 - 0.04)\n box(1.6, 1.1, 0.08, mats.glass, 3.8, 1.5, HOUSE.z0 - 0.04)\n box(1.6, 1.1, 0.08, mats.glass, 8.2, 1.5, HOUSE.z0 - 0.04)\n // walls\n box(5, 1.4, 0.2, mats.wall, 2.5, 0.7, 0)\n box(5, 1.4, 0.2, mats.wall, 9.5, 0.7, 0)\n box(0.2, 1.8, LOT.D, mats.wall, 0, 0.9, 10)\n box(0.2, 1.8, LOT.D, mats.wall, LOT.W, 0.9, 10)\n box(LOT.W, 1.8, 0.2, mats.wall, 6, 0.9, LOT.D)\n return g\n}\n\n/**\n * The nursery: the 12 x 20 m plot of the Viveiro's lot demo (house, walls, street, path) planted by `scatterRulesFor` + `scatter` + `buildLot`, and the walker that crosses it and bends\n * the plants (the wind shader's actors). The module owns it; `plant` builds it, `clear` takes it away.\n */\nexport function createNursery(sdk: VegetationSdk, species: SpeciesSdk, THREE: Three, materials: MaterialsLike, parent: THREE_NS.Object3D, origin: readonly [number, number]) {\n // three with its primitive geometries made by game-shapes (bit-identical, cached by parameters)\n const T = shapeGeometries(THREE) as Three\n const group = new THREE.Group()\n group.name = 'nursery'\n group.position.set(origin[0], 0, origin[1])\n const dynamic = new THREE.Group()\n const colliders = new THREE.Group()\n colliders.visible = false\n let scenery: THREE_NS.Group | null = null\n let lotObject: THREE_NS.Object3D | null = null\n let data: ReturnType<VegetationSdk['buildLot']> | null = null\n let stats: LotStats | null = null\n let actor: THREE_NS.Mesh | null = null\n const walker = { x: WAY[0]![0], z: WAY[0]![1], waypoint: 0, on: false }\n const actors = [{ x: 0, y: 0.8, z: 0, radius: 1.5 }]\n let attached = false\n\n const disposeObject = (object: THREE_NS.Object3D): void => {\n object.traverse((child) => {\n if (isMesh(child)) child.geometry?.dispose?.()\n })\n }\n const clearGroup = (g: THREE_NS.Object3D): void => {\n for (const child of [...g.children]) {\n g.remove(child)\n disposeObject(child)\n if (isMesh(child) && !Array.isArray(child.material)) child.material?.dispose?.()\n }\n }\n const ensure = (): void => {\n if (attached) return\n attached = true\n scenery = buildScenery(T)\n // a capsule where this three.js has one (r139+), else a cylinder of the same size\n const body = T.CapsuleGeometry ? new T.CapsuleGeometry(0.28, 1.0, 4, 10) : new T.CylinderGeometry(0.28, 0.28, 1.56, 10)\n actor = new THREE.Mesh(body, new THREE.MeshStandardMaterial({ color: 0xd9822b, roughness: 0.7 }))\n actor.castShadow = true\n actor.position.set(walker.x, 0.78, walker.z)\n actor.visible = false\n group.add(scenery, dynamic, colliders, actor)\n parent.add(group)\n }\n\n const blocked = (x: number, z: number): boolean => {\n if (x < 0.55 || x > LOT.W - 0.55 || z < 0.55 || z > LOT.D - 0.55) return true\n if (x > HOUSE.x0 - 0.4 && x < HOUSE.x1 + 0.4 && z > HOUSE.z0 - 0.4 && z < HOUSE.z1 + 0.4) return true\n if (data) {\n for (const c of data.colliders) {\n const dx = x - c.x\n const dz = z - c.z\n const r = c.r + 0.3\n if (dx * dx + dz * dz < r * r) return true\n }\n }\n return false\n }\n\n return {\n group,\n get stats(): LotStats | null {\n return stats\n },\n get planted(): boolean {\n return lotObject !== null\n },\n get walking(): boolean {\n return walker.on\n },\n get position(): { x: number; z: number } {\n return { x: walker.x, z: walker.z }\n },\n /** Plants the lot with the settings (replaces the one standing). */\n plant(settings: NurserySettings): LotStats {\n ensure()\n if (lotObject) {\n dynamic.remove(lotObject)\n disposeObject(lotObject)\n lotObject = null\n }\n clearGroup(colliders)\n const { placements, used } = scatterLot(sdk, species, settings.seed)\n const t0 = Date.now()\n data = sdk.buildLot(placements, (id) => species.toSpec(id), { seed: `quintal-${settings.seed}`, quality: settings.quality, lod: settings.lod, condition: settings.condition, season: settings.season })\n const buildMs = Date.now() - t0\n lotObject = sdk.createLotObject(THREE, data, materials as never)\n lotObject.traverse((c) => {\n if (isMesh(c)) {\n c.castShadow = true\n c.receiveShadow = true\n }\n })\n dynamic.add(lotObject)\n for (const c of data.colliders) {\n const m = new THREE.Mesh(new T.CylinderGeometry(c.r, c.r, c.h, 14, 1, true), new THREE.MeshBasicMaterial({ color: c.damage ? 0xff7a1a : 0xe5251d, wireframe: true }))\n m.position.set(c.x, c.h / 2, c.z)\n colliders.add(m)\n }\n stats = { triangles: data.triangleCount, plants: data.plantCount, colliders: data.colliders.length, meshes: Object.keys(data.meshes).length, lod: data.lodCounts, buildMs, species: used.size }\n return stats\n },\n /** The colliders of the lot as wire cylinders. */\n showColliders(on: boolean): void {\n colliders.visible = on\n },\n /** Starts or stops the walker that crosses the lot along `WAY`, bending the plants. */\n setWalker(on: boolean): void {\n ensure()\n walker.on = on\n actor!.visible = on // ensure() made it\n if (!on) {\n actors[0]!.radius = 0\n materials.setActors(actors)\n } else actors[0]!.radius = 1.5\n },\n step(dt: number): void {\n if (!attached || !walker.on) return\n const target = WAY[walker.waypoint]!\n const ddx = target[0] - walker.x\n const ddz = target[1] - walker.z\n const d = Math.hypot(ddx, ddz)\n let dx = 0\n let dz = 0\n if (d < 0.25) walker.waypoint = (walker.waypoint + 1) % WAY.length\n else {\n dx = ddx / d\n dz = ddz / d\n }\n if (dx || dz) {\n const sp = 2.0 * dt\n const nx = walker.x + dx * sp\n const nz = walker.z + dz * sp\n if (!blocked(nx, walker.z)) walker.x = nx\n if (!blocked(walker.x, nz)) walker.z = nz\n if (blocked(nx, nz)) walker.waypoint = (walker.waypoint + 1) % WAY.length\n actor!.rotation.y = Math.atan2(dx, dz)\n }\n actor!.position.set(walker.x, 0.78, walker.z)\n const a = actors[0]!\n a.x = origin[0] + walker.x\n a.z = origin[1] + walker.z\n a.y = 0.8\n materials.setActors(actors)\n },\n /** Takes the lot, the walker and the scenery away. */\n clear(): void {\n if (walker.on) this.setWalker(false)\n if (lotObject) {\n dynamic.remove(lotObject)\n disposeObject(lotObject)\n lotObject = null\n }\n clearGroup(colliders)\n if (attached) {\n parent.remove(group)\n clearGroup(group)\n attached = false\n scenery = null\n actor = null\n }\n data = null\n stats = null\n walker.x = WAY[0]![0]\n walker.z = WAY[0]![1]\n walker.waypoint = 0\n },\n }\n}\n\nexport type Nursery = ReturnType<typeof createNursery>\n","import type * as THREE_NS from 'three'\nimport { markKitOrigin } from '@adatechnology/game-contracts'\nimport type { AnimationClipSpec, DestructibleSpec, JointSpec, PartSpec, TestableItem } from '@adatechnology/game-contracts'\nimport type { Condition, PlantMesh, PlantSpec } from '@adatechnology/game-vegetation'\n\nimport type { MaterialsLike, SpeciesSdk, VegetationSdk } from './types'\n\n/** The seed of every plant of the area (the Viveiro's module fixes it, so the plants are the same in every run). */\nexport const PLANT_SEED = 3\n\nexport type PlantDefKind = 'tree' | 'shrub' | 'hedge' | 'flower' | 'cactus' | 'pot' | 'tuft'\n\n/** One item of the area: a species of the pack (or a variant of it) and how it is built. */\nexport type PlantDef = {\n readonly id: string\n /** The species the plant is generated from (default: `id`). */\n readonly base?: string\n readonly kind: PlantDefKind\n readonly sway: boolean\n /** Fields of the species spec replaced for this item. */\n readonly over?: Readonly<Record<string, number>>\n /** The name, `[pt-BR, en]`, when the species name does not fit the variant. */\n readonly name?: readonly [string, string]\n readonly condition?: Condition\n /** Plants side by side (a hedge is 4 sections joined by their stems). */\n readonly segments?: number\n readonly movable?: boolean\n}\n\n/** The 18 items of the Viveiro's module, in its order. */\nexport const PLANT_DEFS: readonly PlantDef[] = [\n { id: 'mango_tree', kind: 'tree', sway: true },\n // young mango trees (same species, thin trunk): the 15 and 30 cm trunks on which the SDK documents the number of axe swings\n { id: 'mango_young_15', base: 'mango_tree', kind: 'tree', sway: true, over: { height: 1.7, trunkRadius: 0.1, crownRadius: 1.0 }, name: ['Mangueira jovem (tronco de 15 cm)', 'Young mango tree (15 cm trunk)'] },\n { id: 'mango_young_30', base: 'mango_tree', kind: 'tree', sway: true, over: { height: 1.7, trunkRadius: 0.17, crownRadius: 1.2 }, name: ['Mangueira jovem (tronco de 30 cm)', 'Young mango tree (30 cm trunk)'] },\n { id: 'yellow_ipe', kind: 'tree', sway: true },\n { id: 'coconut_palm', kind: 'tree', sway: true },\n { id: 'banana_with_bunch', kind: 'tree', sway: true },\n { id: 'araucaria', kind: 'tree', sway: true },\n { id: 'dead_tree', kind: 'tree', sway: true, condition: 'dead' },\n { id: 'hibiscus_shrub', kind: 'shrub', sway: true },\n { id: 'boxwood_hedge', kind: 'hedge', sway: true, segments: 4 },\n { id: 'rose_bush_red', kind: 'shrub', sway: true },\n { id: 'sunflower', kind: 'flower', sway: true },\n { id: 'mandacaru', kind: 'cactus', sway: false },\n { id: 'prickly_pear', kind: 'cactus', sway: false },\n { id: 'crown_cactus', kind: 'cactus', sway: false },\n { id: 'potted_fern', kind: 'pot', sway: true, movable: true },\n { id: 'potted_cactus', kind: 'pot', sway: false, movable: true },\n { id: 'lawn_tuft', kind: 'tuft', sway: true },\n]\n\n/** The id of a mesh or a joint: lower case, runs of other characters turned into one `_` (`crown:flowers` becomes `crown_flowers`). */\nexport const sanitize = (s: string): string => String(s).toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '')\n\n/** What `buildObject` records in `userData.veg` of each piece mesh. */\nexport type PieceMeta = {\n id: string\n piece: string\n kind: string\n sub: string | null\n base: string\n parent: string | null\n seg: number\n materialKey: string\n radius?: number\n length?: number\n axis?: [number, number, number]\n /** Where the plant of this section stands along x in the object (sections of a hedge are side by side). */\n dx: number\n}\n\ntype Three = typeof THREE_NS\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] }\n\n/** Fraction of the volume of the shape that is solid, by destruction material (what the spec reports as `fill`). */\nconst FILL: Record<string, number> = { green_wood: 0.5, wood_soft: 0.5, foliage: 0.035, flowers: 0.03, flesh_fruit: 0.8, ceramic: 0.2, soil: 0.7, cactus: 0.5 }\n/** Radians of sway, by kind of piece. */\nconst SWAY_AMPLITUDE: Record<string, number> = { trunk: 0.004, branch: 0.012, crown: 0.03, fruit: 0.04, stem: 0.025, arm: 0, pad: 0, pot: 0, soil: 0 }\n\nexport function createPlants(sdk: VegetationSdk, species: SpeciesSdk, materials: (THREE: Three) => MaterialsLike, seed = PLANT_SEED) {\n const defs = new Map(PLANT_DEFS.map((def) => [def.id, def]))\n const specFor = (def: PlantDef): PlantSpec => {\n const spec = species.toSpec(def.base ?? def.id)\n return def.over ? ({ ...spec, ...def.over } as PlantSpec) : spec\n }\n const cache = new Map<string, PlantMesh>()\n const plantFor = (def: PlantDef, segment: number): PlantMesh => {\n const key = `${def.id}:${segment}`\n let plant = cache.get(key)\n if (!plant) {\n plant = sdk.generate(specFor(def), { seed: seed + segment * 7, ...(def.condition ? { condition: def.condition } : {}) })\n cache.set(key, plant)\n }\n return plant\n }\n\n // ---- the 3D object ----------------------------------------------------------------------------------------------------------------------\n function buildObject(THREE: Three, def: PlantDef): THREE_NS.Object3D {\n const root = markKitOrigin(new THREE.Group(), { owner: 'game-vegetation-three', kind: 'plant', id: def.base ?? def.id })\n root.name = def.id\n const segments = def.segments ?? 1\n let spacing = 0\n for (let s = 0; s < segments; s++) {\n const plant = plantFor(def, s)\n const object = sdk.createPlantObject(THREE, plant, materials(THREE), { separable: true })\n const prefix = segments > 1 ? `s${s}_` : ''\n const children = object.children.slice()\n if (s === 0 && segments > 1) {\n const g0 = (children[0] as THREE_NS.Mesh).geometry // a plant object is made of meshes\n g0.computeBoundingBox()\n spacing = (g0.boundingBox!.max.x - g0.boundingBox!.min.x) * 0.9\n }\n for (const mesh of children) {\n const piece = mesh.userData.destructionPart\n const bits = String(piece.id).split(':')\n const id = prefix + sanitize(piece.id)\n mesh.name = id\n const dx = (s - (segments - 1) / 2) * spacing\n const meta: PieceMeta = {\n id,\n piece: piece.id,\n kind: piece.kind,\n sub: bits[1] ?? null,\n base: prefix + sanitize(bits[0] as string),\n parent: piece.parent ? prefix + sanitize(piece.parent) : null,\n seg: s,\n materialKey: piece.materialKey,\n radius: piece.radius,\n length: piece.length,\n axis: piece.axis,\n dx,\n }\n mesh.userData.veg = meta\n mesh.position.x += dx\n mesh.castShadow = true\n root.add(mesh)\n }\n if (s === 0) {\n root.userData.collider = plant.collider || null\n root.userData.thorny = !!plant.thorny\n }\n }\n root.userData.speciesId = def.id\n root.userData.separable = true\n root.userData.segments = segments\n return root\n }\n\n // ---- the destruction spec -----------------------------------------------------------------------------------------------------------------\n function buildSpec(root: THREE_NS.Object3D, def: PlantDef): DestructibleSpec {\n const meshes = root.children.filter((c): c is THREE_NS.Mesh => (c as THREE_NS.Mesh).isMesh === true && Boolean(c.userData.veg))\n const byId: Record<string, THREE_NS.Mesh> = {}\n for (const m of meshes) byId[(m.userData.veg as PieceMeta).id] = m\n const parts: Mutable<PartSpec>[] = []\n for (const m of meshes) {\n const v = m.userData.veg as PieceMeta\n const g = m.geometry\n if (!g.boundingBox) g.computeBoundingBox()\n const b = g.boundingBox!\n const mn = [b.min.x + m.position.x, b.min.y + m.position.y, b.min.z + m.position.z]\n const mx = [b.max.x + m.position.x, b.max.y + m.position.y, b.max.z + m.position.z]\n const size: [number, number, number] = [Math.max(mx[0]! - mn[0]!, 0.02), Math.max(mx[1]! - mn[1]!, 0.02), Math.max(mx[2]! - mn[2]!, 0.02)]\n const c: [number, number, number] = [(mn[0]! + mx[0]!) / 2, (mn[1]! + mx[1]!) / 2, (mn[2]! + mx[2]!) / 2]\n const material = m.userData.destructionMaterial as string\n const round = v.kind === 'trunk' || v.kind === 'pot'\n let shape: PartSpec['shape'] = round ? { kind: 'cylinder', radius: Math.max(size[0], size[2]) / 2, height: size[1] } : { kind: 'box', size }\n // wood pieces: the real thickness of the SDK (2 x radius by the length along the axis) instead of the bounding box, which overstates leaning trunks, flared bases and curved pieces\n let rotation: [number, number, number] | null = null\n if (!v.sub && (v.radius ?? 0) > 0 && (v.length ?? 0) > 0 && (v.kind === 'trunk' || v.kind === 'branch' || v.kind === 'arm' || v.kind === 'stem')) {\n const rr = Math.max(v.radius as number, 0.01)\n const ll = Math.max(v.length as number, 0.02)\n shape = v.kind === 'trunk' ? { kind: 'cylinder', radius: rr, height: ll } : { kind: 'box', size: [rr * 2, ll, rr * 2] }\n if (v.axis) {\n // the y axis of the shape along the axis of the piece (Euler XYZ: x = atan2(az, ay), z = -asin(ax))\n const ax = v.axis\n const tilt = Math.hypot(ax[0], ax[2])\n if (tilt > 0.02 && ax[1] > -0.99) rotation = [Math.atan2(ax[2], ax[1]), 0, -Math.asin(Math.max(-1, Math.min(1, ax[0])))]\n }\n }\n const tags: string[] = []\n const p: Mutable<PartSpec> = { id: v.id, material, shape, position: c, tags }\n if (rotation) p.rotation = rotation\n p.fill = v.sub === 'spines' ? 0.02 : v.sub === 'flowers' ? 0.01 : v.kind === 'trunk' ? 0.8 : v.kind === 'branch' ? 0.1 : v.kind === 'arm' ? 0.12 : v.kind === 'pad' ? 0.3 : (FILL[material] ?? 0.5)\n if (v.kind === 'fruit' || v.sub === 'wood') p.mass = 15\n if (v.kind === 'trunk') {\n p.grain = 'y'\n tags.push('trunk')\n }\n if (v.kind === 'branch') tags.push('branch')\n if (material === 'foliage' || v.sub === 'foliage') tags.push('leaf')\n if (v.sub === 'flowers') tags.push('flower')\n if (v.sub === 'spines') tags.push('thorns')\n if (v.kind === 'fruit') tags.push('fruit')\n if (v.kind === 'arm') tags.push('arm')\n if (v.kind === 'pad') tags.push('pad')\n if (v.kind === 'pot') {\n // explicit hp: a terracotta pot breaks in 1 to 3 shots of 9 mm\n p.mass = 2.4\n p.hp = 25\n tags.push('pot')\n }\n if (v.kind === 'soil') {\n p.mass = 3.2\n tags.push('soil')\n }\n if (def.kind === 'pot' && v.kind === 'stem' && !v.sub) p.mass = 0.4\n if (def.kind === 'pot' && v.sub) p.mass = 0.05\n // the root piece is fixed to the ground (a loose pot anchors nothing)\n const isRoot = !v.parent && !v.sub && (v.kind === 'trunk' || v.kind === 'pad' || (v.kind === 'stem' && def.kind !== 'pot'))\n if (isRoot && !def.movable) p.anchored = true\n parts.push(p)\n }\n\n const joints: JointSpec[] = []\n const seen = new Set<string>()\n const add = (a: string | null, b: string, kind: JointSpec['kind'], extra?: Partial<JointSpec>): void => {\n if (!a || !b || a === b || !byId[a] || !byId[b]) return\n const id = `${a}~${b}`\n if (seen.has(id)) return\n seen.add(id)\n joints.push({ id, a, b, kind, ...extra })\n }\n const firstOf = (seg: number, kind: string): string | null => {\n for (const m of meshes) {\n const v = m.userData.veg as PieceMeta\n if (v.seg === seg && v.kind === kind && !v.sub) return v.id\n }\n return null\n }\n for (const m of meshes) {\n const v = m.userData.veg as PieceMeta\n if (v.sub) {\n add(v.base, v.id, 'tie')\n continue\n }\n if (v.kind === 'soil') {\n add(v.parent, v.id, 'resting')\n continue\n }\n if (v.parent) {\n add(v.parent, v.id, 'stem', v.kind === 'arm' ? { strength: 60 } : undefined)\n continue\n }\n if (v.kind === 'fruit') {\n add(firstOf(v.seg, 'crown') || firstOf(v.seg, 'pad') || firstOf(v.seg, 'stem') || firstOf(v.seg, 'trunk'), v.id, 'stem')\n continue\n }\n if (def.kind === 'pot' && v.kind === 'stem') add(firstOf(v.seg, 'soil'), v.id, 'tie')\n }\n // hedge: neighbouring sections held by their stems\n const segments = def.segments ?? 1\n if (segments > 1) for (let s = 0; s + 1 < segments; s++) add(`s${s}_stem`, `s${s + 1}_stem`, 'stem')\n return { name: def.id, parts, joints, tags: ['plant'] }\n }\n\n // ---- the wind -----------------------------------------------------------------------------------------------------------------------------\n function swayClip(def: PlantDef): AnimationClipSpec {\n const plant = plantFor(def, 0)\n const segments = def.segments ?? 1\n const keys: { t: number; parts: Record<string, { rotation: [number, number, number] }> }[] = []\n const N = 8\n const D = 4\n for (let k = 0; k <= N; k++) {\n const ph = (k / N) * Math.PI * 2\n const parts: Record<string, { rotation: [number, number, number] }> = {}\n for (let s = 0; s < segments; s++) {\n const prefix = segments > 1 ? `s${s}_` : ''\n for (const pc of plant.pieces) {\n const a = SWAY_AMPLITUDE[pc.kind] || 0\n if (!a) continue\n if (pc.kind === 'stem' && /(^|:)wood$/.test(pc.id)) continue\n if (def.kind === 'pot' && pc.kind === 'stem' && pc.id.indexOf(':') < 0 && def.id === 'potted_cactus') continue\n const f = pc.id.indexOf(':flowers') > 0 ? 1.6 : 1\n parts[prefix + sanitize(pc.id)] = { rotation: [Math.sin(ph + s) * a * f * 0.6, 0, Math.sin(ph * 1 + 0.7 + s) * a * f] }\n }\n }\n keys.push({ t: (k / N) * D, parts: k === 0 || k === N ? {} : parts })\n }\n return { id: 'sway', duration: D, keys, events: [{ t: 0.2, type: 'sound', data: { key: 'leaves_rustle' } }] } as AnimationClipSpec\n }\n\n // ---- the items ----------------------------------------------------------------------------------------------------------------------------\n function items(locale: string, defsToUse: readonly PlantDef[] = PLANT_DEFS): TestableItem[] {\n const loc = String(locale || 'pt-BR').toLowerCase().indexOf('en') === 0 ? 'en' : 'pt-BR'\n return defsToUse.map((def) => {\n const item: Mutable<TestableItem> = {\n id: def.id,\n name: def.name ? (def.name[loc === 'en' ? 1 : 0] as string) : species.name(def.base ?? def.id, loc),\n build: (THREE: unknown) => buildObject(THREE as Three, def), // the room hands its three.js namespace\n spec: (root: unknown) => {\n const spec = buildSpec(root as THREE_NS.Object3D, def)\n ;(root as { userData: Record<string, unknown> }).userData.vegSpec = spec\n return spec\n },\n movable: !!def.movable,\n }\n if (def.sway) item.animations = [swayClip(def)]\n return item\n })\n }\n\n return { defs, specFor, plantFor, buildObject, buildSpec, swayClip, items }\n}\n\nexport type Plants = ReturnType<typeof createPlants>\n","import type { DestructibleSpec, ModuleScenario, PartSpec } from '@adatechnology/game-contracts'\n\nimport type { SpawnedPlant, VegetationContext, VegetationRoom, WorldObjectState, WorldPartState } from './types'\n\ntype V3 = [number, number, number]\ntype Spawned = SpawnedPlant\n/** A piece at an instant (`snap`). */\ntype PartSnap = { status: string; hp: number; maxHp: number; temperature: number; burning: boolean; char: number; fuel: number; holes: number; material: string }\ntype Hit = NonNullable<ReturnType<VegetationRoom['world']['raycast']>>\n\n/**\n * The 13 scenarios of the Viveiro's vegetation module, literal (same objects, same tools, same sentences, in both languages). `veg_*` are the ids of the page.\n * A tool is taken with `setTool`; the room gives every tool its draw time, so each one waits for it (`room.waitUntilReady`) where the page's room used it at once.\n */\nexport function createScenarios(locale: string): ModuleScenario<VegetationContext>[] {\n const en = String(locale || 'pt-BR').toLowerCase().indexOf('en') === 0\n const L = (pt: string, e: string): string => (en ? e : pt)\n const yn = (b: unknown): string => (b ? L('sim', 'yes') : L('não', 'no'))\n\n const specOf = (so: Spawned): DestructibleSpec => so.root.userData.vegSpec as DestructibleSpec // set by the module's spec()\n const partSpec = (so: Spawned, pid: string): PartSpec => specOf(so).parts.filter((p) => p.id === pid)[0] as PartSpec\n const world = (so: Spawned, local: V3): V3 => {\n const r = so.root\n return [r.position.x + local[0], r.position.y + local[1], r.position.z + local[2]]\n }\n const norm = (v: V3): V3 => {\n const l = Math.hypot(v[0], v[1], v[2]) || 1\n return [v[0] / l, v[1] / l, v[2] / l]\n }\n const dist = (a: V3, b: V3): number => Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2])\n const DIRS: V3[] = [[0, 0, -1], [1, 0, 0], [-1, 0, 0], [0, 0, 1], [0.7, 0, -0.7], [-0.7, 0, -0.7], [0.7, 0, 0.7], [-0.7, 0, 0.7], [0, -1, 0]]\n\n const center = (so: Spawned, pid: string): V3 => world(so, partSpec(so, pid).position)\n\n // Joint tools (saw, knife): the camera position from which the ray hits something within 0.45 m of the joint asked for. Aims the camera.\n const aim = (room: VegetationRoom, so: Spawned, target: V3, standoff: number, opt: { beyond?: number; joint?: string; jointRange?: number } = {}): { score: number; origin: V3; target: V3; hit: Hit | null } => {\n let best: { score: number; origin: V3; target: V3; hit: Hit | null } | null = null\n for (const dir of DIRS) {\n const d = norm(dir)\n const origin: V3 = [target[0] - d[0] * standoff, target[1] - d[1] * standoff, target[2] - d[2] * standoff]\n if (origin[1] < 0.25) continue\n const hit = room.world.raycast(origin, d, standoff + (opt.beyond == null ? 0.6 : opt.beyond))\n if (!hit || hit.object !== so.objectId) continue\n let score = dist(hit.point, target)\n if (opt.joint) {\n const nj = room.world.nearestJoint(so.objectId, hit.point, opt.jointRange || 0.45)\n if (!nj || nj.id !== opt.joint) score += 20\n }\n if (!best || score < best.score) best = { score, origin, target, hit }\n }\n if (!best) best = { score: 99, origin: [target[0], target[1], target[2] + standoff], target, hit: null }\n room.look(best.origin, best.target)\n return best\n }\n // Weapons and fire: finds a horizontal (or from above) direction from which the first hit of the ray is the piece `pid`, and puts the camera `gap` metres from the surface\n // (blade stroke: 0.5; lighter: 0.08; shot: 2.5). `at` changes the aimed point (object local).\n const AIMDIRS: V3[] = [[0, 0, -1], [0.7, 0, -0.7], [-0.7, 0, -0.7], [1, 0, 0], [-1, 0, 0], [0, -1, 0], [0.7, 0, 0.7], [-0.7, 0, 0.7], [0, 0, 1]]\n const aimPart = (room: VegetationRoom, so: Spawned, pidsIn: string | string[], gap: number, at?: V3): { origin: V3; point: V3; found: boolean; pid: string } => {\n const pids = typeof pidsIn === 'string' ? [pidsIn] : pidsIn\n let best: { score: number; d: V3; hit: { point: V3 }; pid: string } | null = null\n for (const pid of pids) {\n const c = at ? world(so, at) : center(so, pid)\n for (const dir of AIMDIRS) {\n const d = norm(dir)\n const far = 8\n const origin: V3 = [c[0] - d[0] * far, c[1] - d[1] * far, c[2] - d[2] * far]\n if (origin[1] < 0.3) continue\n const hit = room.world.raycast(origin, d, far + 3)\n if (!hit || hit.object !== so.objectId || hit.part !== pid) continue\n const score = dist(hit.point, c)\n if (!best || score < best.score) best = { score, d, hit, pid }\n }\n }\n if (!best) best = { score: 99, d: [0, 0, -1], hit: { point: center(so, pids[0] as string) }, pid: pids[0] as string }\n const H = best.hit.point\n const from: V3 = [H[0] - best.d[0] * gap, H[1] - best.d[1] * gap, H[2] - best.d[2] * gap]\n if (from[1] < 0.3) from[1] = 0.3\n room.look(from, [H[0] + best.d[0] * 0.3, H[1] + best.d[1] * 0.3, H[2] + best.d[2] * 0.3])\n return { origin: from, point: H, found: best.score < 99, pid: best.pid }\n }\n const crownsOf = (so: Spawned): string[] => specOf(so).parts.filter((p) => /^(s\\d+_)?crown\\d*$/.test(p.id)).map((p) => p.id)\n const jointPos = (so: Spawned, jid: string): V3 => {\n const j = (specOf(so).joints ?? []).filter((x) => x.id === jid)[0]!\n const a = partSpec(so, j.a)\n const b = partSpec(so, j.b)\n const box = (p: PartSpec): { min: V3; max: V3 } => {\n const sh = p.shape\n const h: V3 = 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]\n const r = p.rotation || [0, 0, 0] // only x and z (see buildSpec): Euler XYZ = Rx * Rz\n const cx = Math.cos(r[0]), sx = Math.sin(r[0]), cz = Math.cos(r[2]), sz = Math.sin(r[2])\n const mn: V3 = [Infinity, Infinity, Infinity]\n const mx: V3 = [-Infinity, -Infinity, -Infinity]\n for (let i = 0; i < 8; i++) {\n const x = (i & 1 ? 1 : -1) * h[0], y = (i & 2 ? 1 : -1) * h[1], z = (i & 4 ? 1 : -1) * h[2]\n const x1 = x * cz - y * sz, y1 = x * sz + y * cz\n const w = [x1, y1 * cx - z * sx, y1 * sx + z * cx]\n for (let k = 0; k < 3; k++) {\n mn[k] = Math.min(mn[k] as number, p.position[k] + (w[k] as number))\n mx[k] = Math.max(mx[k] as number, p.position[k] + (w[k] as number))\n }\n }\n return { min: mn, max: mx }\n }\n const A_ = box(a)\n const B_ = box(b)\n return world(so, [0, 1, 2].map((k) => (Math.max(A_.min[k] as number, B_.min[k] as number) + Math.min(A_.max[k] as number, B_.max[k] as number)) / 2) as V3)\n }\n const lost = (p: WorldPartState | PartSnap | null | undefined): boolean => !p || p.status === 'broken' || p.status === 'ashes' || p.status === 'melted'\n // The state of a piece at an instant: world.snapshot(id) gives a copy (state() / part() are live views).\n const snap = (room: VegetationRoom, so: Spawned, pid: string): PartSnap | null => {\n const st = room.world.snapshot(so.objectId)\n const p = st && st.parts.filter((x) => x.id === pid)[0]\n if (!p) return null\n 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 }\n }\n /** `snap` of a piece the scenario needs to be there (a missing one is a broken scenario, not a result). */\n const snapAt = (room: VegetationRoom, so: Spawned, pid: string): PartSnap => {\n const p = snap(room, so, pid)\n if (!p) throw new Error(`game-vegetation-three: no part \"${pid}\" in ${so.objectId}`)\n return p\n }\n /** The world's live state of an object the scenario spawned. */\n const stateAt = (room: VegetationRoom, id: string): WorldObjectState => {\n const st = room.world.state(id)\n if (!st) throw new Error(`game-vegetation-three: no object ${id} in the world`)\n return st\n }\n const logCount = (room: VegetationRoom, so: Spawned, type: string): number => room.log.entries({ type, objectId: so.objectId }).length\n // Joints opened in the log: 'detach' lines (one per joint, or several in one) plus those the 'fracture' event sums up in jointsOpened.\n const jointsOpened = (room: VegetationRoom, so: Spawned): number => {\n let n = 0\n for (const e of room.log.entries({ type: 'detach', objectId: so.objectId })) n += e.data && e.data.joints ? e.data.joints.length : 1\n for (const e of room.log.entries({ type: 'fracture', objectId: so.objectId })) n += (e.data && e.data.jointsOpened) || 0\n return n\n }\n const detachedJoint = (room: VegetationRoom, so: Spawned, jid: string): boolean =>\n room.log.entries({ type: 'detach', objectId: so.objectId }).some((e) => e.data && (e.data.joint === jid || (e.data.joints || []).indexOf(jid) >= 0))\n const spawn = (room: VegetationRoom, id: string, x: number, z: number): Spawned => room.spawn(id, [x, 0, z], 0)\n // When a group comes loose, the world moves it to a new object (`obj_N`). `home` is the original object, `loose` the ones that came off.\n const split = (room: VegetationRoom, so: Spawned) => {\n const home = room.world.snapshot(so.objectId)\n if (!home) throw new Error(`game-vegetation-three: no object ${so.objectId} in the world`)\n const loose = room.world.ids().filter((i) => /^obj_/.test(i)).flatMap((i) => {\n const st = room.world.snapshot(i)\n return st ? [{ id: i, st }] : []\n })\n const anchored: Record<string, boolean> = {}\n for (const p of specOf(so).parts) if (p.anchored) anchored[p.id] = true\n const rooted: string[] = []\n for (const g of home.groups) if (g.some((pid) => anchored[pid])) for (const pid of g) rooted.push(pid)\n const inLoose = (pid: string): boolean => loose.some((o) => o.st.parts.some((p) => p.id === pid && !lost(p)))\n const inHome = (pid: string): boolean => home.parts.some((p) => p.id === pid && !lost(p))\n return { home, loose, rooted, inLoose, inHome, sections: home.groups.length + loose.length }\n }\n\n // Axe on the trunk until it breaks (at most `max` swings); gives the count and the state of the trunk.\n const fell = (room: VegetationRoom, ctx: VegetationContext, so: Spawned, max: number): { swings: number; trunk: PartSnap } => {\n take(room, 'axe')\n let swings = 0\n const trunkShape = partSpec(so, 'trunk').shape\n const h = trunkShape.kind === 'cylinder' ? trunkShape.height : trunkShape.kind === 'box' ? trunkShape.size[1] : trunkShape.radius * 2\n for (let i = 0; i < max; i++) {\n aimPart(room, so, 'trunk', 0.5, [0, Math.min(0.9, h / 3), 0])\n room.use()\n ctx.step(1.5)\n swings++\n if (lost(room.world.part(so.objectId, 'trunk'))) break\n }\n ctx.step(5)\n return { swings, trunk: snapAt(room, so, 'trunk') }\n }\n\n const sc = (id: string, ptName: string, enName: string, run: (ctx: VegetationContext) => void): ModuleScenario<VegetationContext> => ({ id: `veg_${id}`, name: L(ptName, enName), run })\n const pct = (x: number): string => `${Math.round((x || 0) * 100)}%`\n // the room gives every tool its draw time; the page's room used the tool the moment it was taken\n const take = (room: VegetationRoom, id: string): void => {\n room.setTool(id)\n room.waitUntilReady()\n }\n\n return [\n // 1 ---------------------------------------------------------------------------------------------------------------\n sc('axe_fells_crown', 'Machado no tronco de 15 cm derruba a copa (8 a 15 golpes)', 'Axe on a 15 cm trunk fells the crown (8 to 15 swings)', (ctx) => {\n const room = ctx.room\n const so = spawn(room, 'mango_young_15', 0, -6)\n const r = fell(room, ctx, so, 60)\n const sp = split(room, so)\n const crownGone = lost(room.world.part(so.objectId, 'crown')) || !sp.inHome('crown') || sp.rooted.indexOf('crown') < 0\n const branches: string[] = specOf(so).parts.filter((p) => (p.tags ?? []).indexOf('branch') >= 0).map((p) => p.id)\n const branchesFree = branches.every((b) => sp.rooted.indexOf(b) < 0)\n const detach = jointsOpened(room, so)\n 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 })\n ctx.expect(sp.rooted.length === 0 && crownGone && branchesFree, L(`Nada da copa continua preso ao chão: peças ainda enraizadas ${sp.rooted.length}, copa solta ${yn(crownGone)}, ${branches.length} galhos soltos ${yn(branchesFree)} (esperado: 0, sim, sim)`, `Nothing of the crown stays rooted: rooted pieces ${sp.rooted.length}, crown free ${yn(crownGone)}, ${branches.length} branches free ${yn(branchesFree)} (expected: 0, yes, yes)`), { rooted: sp.rooted.length })\n ctx.expect(detach > 0 && sp.loose.length > 0, L(`Registro: ${detach} soltura(s) de junta (as juntas se abrem quando o tronco se perde) e ${sp.loose.length} pedaço(s) caindo como objeto próprio (esperado: 1 ou mais de cada)`, `Log: ${detach} joint detach(es) (joints open when the trunk is lost) and ${sp.loose.length} piece(s) falling as their own object (expected: 1+ each)`), { detach, loose: sp.loose.length })\n }),\n sc('axe_fells_30cm', 'Machado no tronco de 30 cm (25 a 40 golpes)', 'Axe on a 30 cm trunk (25 to 40 swings)', (ctx) => {\n const room = ctx.room\n const so = spawn(room, 'mango_young_30', 0, -6)\n const r = fell(room, ctx, so, 90)\n const sp = split(room, so)\n ctx.expect(r.trunk.status === 'broken' && r.swings >= 25 && r.swings <= 40, L(`Machado no tronco de 30 cm (hp ${Math.round(r.trunk.maxHp)}): tronco ${r.trunk.status} depois de ${r.swings} golpes (esperado: broken em 25 a 40 golpes)`, `Axe on a 30 cm trunk (hp ${Math.round(r.trunk.maxHp)}): trunk ${r.trunk.status} after ${r.swings} swings (expected: broken in 25 to 40 swings)`), { swings: r.swings, status: r.trunk.status, maxHp: r.trunk.maxHp })\n ctx.expect(sp.rooted.length === 0, L(`Árvore caída: peças ainda presas ao chão ${sp.rooted.length} (esperado: 0)`, `Fallen tree: pieces still rooted ${sp.rooted.length} (expected: 0)`), { rooted: sp.rooted.length })\n }),\n sc('axe_cuts_branch_joint', 'Machado passa pela junta tronco-galho', 'Axe works through the trunk-branch joint', (ctx) => {\n const room = ctx.room\n const so = spawn(room, 'mango_tree', 0, -6)\n const jid = 'trunk~branch1'\n take(room, 'axe')\n let swings = 0\n let detached = false\n for (let i = 0; i < 60 && !detached; i++) {\n aim(room, so, jointPos(so, jid), 0.5, { joint: jid, beyond: 0.3 })\n room.use()\n ctx.step(1.5)\n swings++\n detached = detachedJoint(room, so, jid)\n }\n ctx.step(3)\n const trunk = snapAt(room, so, 'trunk')\n const sp = split(room, so)\n const branchOff = sp.inLoose('branch1') && !sp.inHome('branch1')\n const restStays = sp.inHome('trunk') && sp.rooted.indexOf('trunk') >= 0\n ctx.expect(detached && branchOff, L(`Machado na junta ${jid}: galho solto ${yn(branchOff)} depois de ${swings} golpe(s), com o tronco ${trunk.status} (esperado: sim)`, `Axe on joint ${jid}: branch detached ${yn(branchOff)} after ${swings} swing(s), trunk ${trunk.status} (expected: yes)`), { swings })\n ctx.expect(trunk.status !== 'broken' && restStays, L(`A junta cedeu antes do tronco: tronco ${trunk.status}, tronco de pé e preso ao chão ${yn(restStays)} (esperado: não quebrado, sim)`, `The joint gave way before the trunk: trunk ${trunk.status}, trunk standing and rooted ${yn(restStays)} (expected: not broken, yes)`), {})\n }),\n sc('shot_cannot_fell', 'Tiro de 9 mm não derruba a árvore', 'A 9 mm shot never fells a tree', (ctx) => {\n const room = ctx.room\n const so = spawn(room, 'mango_young_15', 0, -6)\n take(room, 'pistol_9mm')\n let shots = 0\n for (let i = 0; i < 30; i++) {\n aimPart(room, so, 'trunk', 2.5, [0, 0.5, 0])\n room.use()\n ctx.step(0.4)\n shots++\n }\n const trunk = snapAt(room, so, 'trunk')\n const sp = split(room, so)\n 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ão 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 })\n ctx.expect(sp.loose.length === 0 && sp.inHome('trunk') && sp.rooted.indexOf('crown') >= 0, L(`A árvore continua de pé: pedaços soltos ${sp.loose.length}, copa presa ao chão ${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)`), {})\n }),\n // 2 ---------------------------------------------------------------------------------------------------------------\n sc('saw_cuts_branch', 'Serra no galho', 'Saw on a branch', (ctx) => {\n const room = ctx.room\n const so = spawn(room, 'yellow_ipe', 0, -6)\n const jid = 'trunk~branch1'\n take(room, 'hacksaw')\n aim(room, so, jointPos(so, jid), 0.45, { joint: jid })\n room.use(4)\n ctx.step(1)\n const sp = split(room, so)\n const movedBranch = sp.inLoose('branch1') && !sp.inHome('branch1')\n const movedCrown = sp.inLoose('crown1')\n const restStays = ['trunk', 'branch0', 'branch2', 'branch3', 'crown'].every((pid) => sp.inHome(pid) && sp.rooted.indexOf(pid) >= 0)\n const detach = logCount(room, so, 'detach')\n ctx.expect(movedBranch && detach > 0, L(`Serra na junta tronco-galho 1: galho solto do tronco ${yn(movedBranch)}, ${detach} linha(s) de soltura no log (esperado: sim, 1)`, `Saw on the trunk-branch 1 joint: branch detached ${yn(movedBranch)}, ${detach} detach line(s) in the log (expected: yes, 1)`), { detach })\n ctx.expect(movedCrown, L(`A folhagem do galho cortado foi junto: ${yn(movedCrown)} (esperado: sim)`, `The foliage of the cut branch went with it: ${yn(movedCrown)} (expected: yes)`), {})\n ctx.expect(restStays, L(`O resto da árvore (tronco, outros galhos e copa) continua inteiro e preso ao chão: ${yn(restStays)} (esperado: sim)`, `The rest of the tree (trunk, other branches, crown) stays whole and rooted: ${yn(restStays)} (expected: yes)`), {})\n }),\n // 3 ---------------------------------------------------------------------------------------------------------------\n sc('lighter_ignites_foliage', 'Isqueiro na folhagem pega fogo', 'Lighter on the foliage catches fire', (ctx) => {\n const room = ctx.room\n const so = spawn(room, 'mango_tree', 0, -6)\n take(room, 'lighter')\n const a = aimPart(room, so, crownsOf(so), 0.08)\n room.use(6)\n const crown = snapAt(room, so, a.pid)\n const lit = crown.burning || crown.temperature > 300\n let peak = 0\n let charMax = 0\n for (let t = 0; t < 18; t++) {\n ctx.step(5)\n for (const p of stateAt(room, so.objectId).parts) {\n if (p.material === 'green_wood') {\n peak = Math.max(peak, p.temperature)\n charMax = Math.max(charMax, p.char || 0)\n }\n }\n }\n const st = stateAt(room, so.objectId)\n const burnt = st.parts.filter((p) => p.material === 'foliage' && (p.burning || (p.char ?? 0) > 0 || p.status === 'ashes')).length\n ctx.expect(lit, L(`Isqueiro na copa: folhagem acesa ou acima de 300 °C = ${yn(lit)} (${Math.round(crown.temperature)} °C; esperado: sim)`, `Lighter on the crown: foliage lit or above 300 C = ${yn(lit)} (${Math.round(crown.temperature)} C; expected: yes)`), { temperature: crown.temperature })\n ctx.expect(burnt > 0, L(`Depois de 90 s: ${burnt} peça(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 })\n ctx.expect(peak > 150 || charMax > 0, L(`O fogo da folhagem passa para a madeira verde (tronco e galhos): pico de ${Math.round(peak)} °C, carbonização máxima ${pct(charMax)} (esperado: pico acima de 150 °C ou carbonização acima de 0; a madeira verde só pega fogo acima de 400 °C)`, `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 })\n }),\n // 4 ---------------------------------------------------------------------------------------------------------------\n sc('shot_strips_leaves', 'Tiro na copa arranca folhas', 'A shot into the crown strips leaves', (ctx) => {\n const room = ctx.room\n const so = spawn(room, 'mango_tree', 0, -6)\n take(room, 'pistol_9mm')\n const tgt = aimPart(room, so, crownsOf(so), 2.5).pid\n const before = snapAt(room, so, tgt)\n for (let i = 0; i < 3; i++) {\n aimPart(room, so, tgt, 2.5)\n room.use()\n ctx.step(0.6)\n }\n const crown = snapAt(room, so, tgt)\n const leaves = room.log.entries({ type: 'debris', objectId: so.objectId }).filter((e) => e.data && e.data.kind === 'leaves').length\n const hurt = crown.hp < before.hp || crown.status === 'broken'\n ctx.expect(hurt && crown.status !== 'intact', L(`Três tiros na copa: hp ${Math.round(before.hp)} para ${Math.round(crown.hp)}, estado ${crown.status} (esperado: hp menor, não 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 })\n ctx.expect(leaves > 0 || crown.holes > 0, L(`Folhas arrancadas: ${leaves} linha(s) de folhas voando, ${crown.holes} furo(s) na copa (esperado: 1 ou mais)`, `Leaves torn off: ${leaves} flying-leaf line(s), ${crown.holes} hole(s) in the crown (expected: 1+)`), { leaves, holes: crown.holes })\n }),\n // 5 ---------------------------------------------------------------------------------------------------------------\n sc('shot_breaks_pot', 'Tiros quebram o vaso e a terra se espalha', 'Shots break the pot and the soil spills', (ctx) => {\n const room = ctx.room\n const so = room.spawn('potted_fern', [0, 0, -4], 0)\n take(room, 'pistol_9mm')\n // terracotta pot with an explicit hp of 25: it breaks in 1 to 3 shots of 9 mm; the pot-soil joint bursts and the soil comes loose\n let shots = 0\n for (let i = 0; i < 12; i++) {\n const cur = snap(room, so, 'pot')\n if (!cur) break // the pot already left the original object\n aimPart(room, so, 'pot', 1.5)\n room.use()\n ctx.step(0.5)\n shots++\n const after = snap(room, so, 'pot')\n if (after && (after.status === 'broken' || after.hp <= 0)) break // broke\n }\n ctx.step(3)\n const sp = split(room, so)\n let potNow: PartSnap | WorldPartState | null = snap(room, so, 'pot')\n for (const o of sp.loose) {\n const q = o.st.parts.filter((x) => x.id === 'pot')[0]\n if (q) potNow = q\n }\n const soilOut = sp.inLoose('soil') || !sp.inHome('soil')\n const soilApart = !sp.home.groups.some((g: string[]) => g.indexOf('soil') >= 0 && g.indexOf('pot') >= 0)\n const cracks = room.log.entries({ type: 'crack', objectId: so.objectId }).length\n const dt = jointsOpened(room, so)\n ctx.expect(!!potNow && (potNow.status === 'broken' || potNow.hp <= 0) && shots >= 1 && shots <= 4, L(`Tiros no vaso: o vaso quebra: cerâmica ${potNow && potNow.status} com hp ${potNow ? `${Math.round(potNow.hp)}/${Math.round(potNow.maxHp)}` : '?'} e ${cracks} trinca(s) depois de ${shots} tiro(s) de 9 mm (esperado: vaso quebrado em 1 a 4 tiros)`, `Shots into the pot: the pot breaks: ceramic ${potNow && potNow.status} with hp ${potNow ? `${Math.round(potNow.hp)}/${Math.round(potNow.maxHp)}` : '?'} and ${cracks} crack(s) after ${shots} 9 mm shot(s) (expected: pot broken in 1 to 4 shots)`), { status: potNow && potNow.status, shots, cracks })\n ctx.expect(soilApart || soilOut, L(`A terra saiu do vaso e caiu junto com a planta: ${yn(soilApart || soilOut)} (esperado: sim)`, `The soil left the pot and fell with the plant: ${yn(soilApart || soilOut)} (expected: yes)`), {})\n ctx.expect(dt > 0, L(`Registro: ${dt} soltura(s) de junta (esperado: 1 ou mais)`, `Log: ${dt} joint detach(es) (expected: 1+)`), { detach: dt })\n }),\n // 6 ---------------------------------------------------------------------------------------------------------------\n sc('machete_arm', 'Machete na junta do braço do mandacaru', 'Machete on the mandacaru arm joint', (ctx) => {\n const room = ctx.room\n const so = spawn(room, 'mandacaru', 0, -5)\n take(room, 'machete')\n const arm = 'arm0'\n const jid = `stem~${arm}`\n let swings = 0\n let detached = false\n for (let i = 0; i < 40 && !detached; i++) {\n aim(room, so, jointPos(so, jid), 0.55, { joint: jid, beyond: 0.3 })\n room.use()\n ctx.step(1.2)\n swings++\n detached = detachedJoint(room, so, jid) || lost(room.world.part(so.objectId, arm))\n }\n ctx.step(3)\n const a = snap(room, so, arm)\n const sp = split(room, so)\n const armOff = !a || a.status === 'broken' || (sp.inLoose(arm) && !sp.inHome(arm))\n const stemOk = sp.inHome('stem') && sp.rooted.indexOf('stem') >= 0 && room.world.part(so.objectId, 'stem')?.status !== 'broken'\n const spines = specOf(so).parts.filter((p) => (p.tags ?? []).indexOf('thorns') >= 0)\n const thorny = so.root.userData.thorny === true && spines.length > 0\n const spinesOff = !sp.rooted.some((pid: string) => pid.indexOf(`${arm}_spines`) === 0)\n ctx.expect(armOff, L(`Machete na junta ${jid}: braço ${a ? a.status : 'solto como objeto próprio'} 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 })\n ctx.expect(stemOk, L(`O caule principal continua de pé e preso ao chão: ${yn(stemOk)} (esperado: sim)`, `The main stem stays standing and rooted: ${yn(stemOk)} (expected: yes)`), {})\n ctx.expect(thorny && spinesOff, L(`Espinhos: cacto marcado como espinhoso (userData.thorny, ${spines.length} peças de espinho) ${yn(thorny)}, espinhos do braço saíram junto ${yn(spinesOff)} (esperado: sim, sim)`, `Thorns: cactus flagged thorny (userData.thorny, ${spines.length} spine pieces) ${yn(thorny)}, the arm spines went with it ${yn(spinesOff)} (expected: yes, yes)`), { spines: spines.length })\n }),\n // 7 ---------------------------------------------------------------------------------------------------------------\n sc('pad_pulled', 'Palma arrancada', 'Prickly pear pad pulled off', (ctx) => {\n const room = ctx.room\n const so = spawn(room, 'prickly_pear', 0, -4)\n const jid = 'pad0~pad1'\n take(room, 'utility_knife')\n aim(room, so, jointPos(so, jid), 0.25, { joint: jid, beyond: 0.3 })\n room.use(1.7)\n ctx.step(1)\n const sp = split(room, so)\n const padOff = sp.inLoose('pad1') && !sp.inHome('pad1')\n const childWith = sp.inLoose('pad3')\n const spinesWith = sp.inLoose('pad1_spines')\n const motherOk = sp.inHome('pad0') && sp.rooted.indexOf('pad0') >= 0 && sp.inHome('pad2')\n ctx.expect(padOff, L(`Raquete 1 cortada da planta-mãe na junta ${jid}: ${yn(padOff)} (esperado: sim)`, `Pad 1 cut off the mother plant at joint ${jid}: ${yn(padOff)} (expected: yes)`), {})\n ctx.expect(childWith && spinesWith, L(`A raquete filha (3) e os espinhos da raquete 1 vão junto: ${yn(childWith && spinesWith)} (esperado: sim)`, `The child pad (3) and the spines of pad 1 go with it: ${yn(childWith && spinesWith)} (expected: yes)`), {})\n ctx.expect(motherOk, L(`A planta-mãe (raquetes 0 e 2) fica presa ao chão: ${yn(motherOk)} (esperado: sim)`, `The mother plant (pads 0 and 2) stays rooted: ${yn(motherOk)} (expected: yes)`), {})\n }),\n // 8 ---------------------------------------------------------------------------------------------------------------\n sc('dead_burns_faster', 'Árvore morta queima mais rápido que viva', 'A dead tree burns faster than a living one', (ctx) => {\n const room = ctx.room\n const dead = spawn(room, 'dead_tree', -4, -6)\n const live = spawn(room, 'mango_tree', 4, -6)\n take(room, 'lighter')\n for (const so of [dead, live]) {\n aimPart(room, so, 'trunk', 0.08, [0, 0.8, 0])\n room.use(8)\n }\n const d0 = snapAt(room, dead, 'trunk')\n const l0 = snapAt(room, live, 'trunk')\n ctx.step(120)\n const d = snapAt(room, dead, 'trunk')\n const l = snapAt(room, live, 'trunk')\n const score = (p: PartSnap): number => (p ? Math.max(p.char, p.burning ? 0.01 : 0, (p.temperature - 20) / 2000) : 0)\n ctx.expect(d0.material === 'wood_soft' && l0.material === 'green_wood', L(`Materiais do tronco: árvore 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 })\n 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)} °C, carbonização ${pct(d.char)}; viva queimando ${yn(l.burning)}, ${Math.round(l.temperature)} °C, carbonização ${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) })\n }),\n // 9 ---------------------------------------------------------------------------------------------------------------\n sc('hedge_cut_pieces', 'Cerca viva cortada em partes', 'Hedge cut into sections', (ctx) => {\n const room = ctx.room\n const so = spawn(room, 'boxwood_hedge', 0, -5)\n take(room, 'hacksaw')\n for (const jid of ['s0_stem~s1_stem', 's2_stem~s3_stem']) {\n aim(room, so, jointPos(so, jid), 0.45, { joint: jid })\n room.use(1.7)\n ctx.step(0.3)\n }\n ctx.step(1)\n const sp = split(room, so)\n const all: WorldPartState[] = [...sp.home.parts]\n for (const o of sp.loose) all.push(...o.st.parts)\n const alive = all.filter((p) => !lost(p)).length\n const total = specOf(so).parts.length\n ctx.expect(sp.sections === 3, L(`Duas serradas na cerca viva: ${sp.sections} parte(s) separada(s) (esperado: 3)`, `Two saw cuts in the hedge: ${sp.sections} separate section(s) (expected: 3)`), { sections: sp.sections })\n ctx.expect(alive === total, L(`Nenhuma seção foi destruída, só separada: ${alive} de ${total} peças inteiras (esperado: todas)`, `No section was destroyed, only separated: ${alive} of ${total} pieces intact (expected: all)`), { alive, total })\n }),\n // 10 --------------------------------------------------------------------------------------------------------------\n sc('walk_on_grass', 'Pisar na grama não colide', 'Walking on grass does not collide', (ctx) => {\n const room = ctx.room\n const tuft = spawn(room, 'lawn_tuft', 0, -3)\n const tree = spawn(room, 'mango_tree', 4, -3)\n const noBlock = !tuft.root.userData.collider\n const treeBlock = !!((tree.root.userData.collider as { kind?: string } | undefined)?.kind)\n 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)`), {})\n // really walks: room.walk(to, seconds) moves the player through the room's own loop (ctx.step advances the simulation, with no host loop)\n room.look([0, 1.7, -0.5], [0, 1.7, -6])\n const before = room.camera.position.z\n room.walk([0, 1.7, -6], 3)\n ctx.step(3.2)\n const after = room.camera.position.z\n const tp = snap(room, tuft, 'stem')\n ctx.expect(after < -3.3 && !!tp && tp.status === 'intact', L(`Andando para a frente (room.walk): z foi de ${before.toFixed(1)} a ${after.toFixed(1)}, atravessou a touceira ${yn(after < -3.3)}, touceira ${tp && tp.status} (esperado: atravessou, intacta)`, `Walking forward (room.walk): z went from ${before.toFixed(1)} to ${after.toFixed(1)}, crossed the tuft ${yn(after < -3.3)}, tuft ${tp && tp.status} (expected: crossed, intact)`), { before, after })\n }),\n ]\n}\n","/** Words of the vegetation area's bench. */\nexport type VegetationText = {\n group: string\n name: string\n controls: Record<'seed' | 'quality' | 'lod' | 'condition' | 'season' | 'wind' | 'gust', string>\n hints: Record<'seed' | 'quality' | 'lod' | 'condition' | 'season' | 'wind' | 'gust', string>\n options: { quality: Record<string, string>; lod: Record<string, string>; condition: Record<string, string>; season: Record<string, string> }\n actions: Record<'plant_lot' | 'clear_lot' | 'toggle_walker', string>\n layers: Record<'colliders' | 'piece_boxes' | 'wood_axes', string>\n metrics: Record<'plants' | 'pieces' | 'triangles' | 'draw_calls' | 'lot_triangles' | 'lot_plants' | 'lot_colliders' | 'lot_lod0' | 'lot_lod1' | 'lot_lod2' | 'lot_ms', string>\n lot: Record<'planted' | 'cleared' | 'walker_on' | 'walker_off', string>\n}\n\nexport const TEXT: Record<string, VegetationText> = {\n en: {\n group: 'Trees, plants and flowers',\n name: 'Vegetation',\n controls: { seed: 'Lot seed', quality: 'Lot quality', lod: 'Lot detail (LOD)', condition: 'Condition', season: 'Season', wind: 'Wind', gust: 'Gusts' },\n hints: {\n seed: 'The seed of the nursery lot: the same seed plants the same yard',\n quality: 'High: every plant at the detail below. Game: one level for all plants and small ones cheaper, with a triangle budget',\n lod: 'Level of detail of the plants of the lot (0 the most detailed)',\n condition: 'How the lot plants look: healthy, dry, dead or overgrown (decides green or dry wood for the destruction)',\n season: 'Season of the lot (flowers and leaf colours)',\n wind: 'Strength of the wind that sways the leaves, flowers and grass',\n gust: 'Slowly varying extra push on top of the wind',\n },\n options: {\n quality: { high: 'High', game: 'Game' },\n lod: { '0': 'LOD 0', '1': 'LOD 1', '2': 'LOD 2' },\n condition: { healthy: 'Healthy', dry: 'Dry', dead: 'Dead', overgrown: 'Overgrown' },\n season: { spring: 'Spring', summer: 'Summer', autumn: 'Autumn', winter: 'Winter' },\n },\n actions: { plant_lot: 'Plant the nursery lot', clear_lot: 'Remove the nursery lot', toggle_walker: 'Start or stop the walker' },\n layers: { colliders: 'Colliders (trunks and cactus bodies)', piece_boxes: 'Boxes of the pieces', wood_axes: 'Wood axes (radius, length, axis)' },\n metrics: { plants: 'Plants placed', pieces: 'Pieces', triangles: 'Triangles', draw_calls: 'Draw calls', lot_triangles: 'Lot triangles', lot_plants: 'Lot plants', lot_colliders: 'Lot colliders', lot_lod0: 'Lot plants at LOD 0', lot_lod1: 'Lot plants at LOD 1', lot_lod2: 'Lot plants at LOD 2', lot_ms: 'Lot build time' },\n lot: { planted: 'Nursery lot planted: {0} plants, {1} triangles, {2} colliders', cleared: 'Nursery lot removed', walker_on: 'The walker crosses the lot and bends the plants', walker_off: 'The walker stopped' },\n },\n 'pt-BR': {\n group: 'Árvores, plantas e flores',\n name: 'Vegetação',\n controls: { seed: 'Semente do canteiro', quality: 'Qualidade do canteiro', lod: 'Detalhe do canteiro (LOD)', condition: 'Condição', season: 'Estação', wind: 'Vento', gust: 'Rajadas' },\n hints: {\n seed: 'A semente do canteiro: a mesma semente planta o mesmo quintal',\n quality: 'Alta: todas as plantas no detalhe abaixo. Jogo: um nível para todas e as pequenas mais baratas, com orçamento de triângulos',\n lod: 'Nível de detalhe das plantas do canteiro (0 o mais detalhado)',\n condition: 'Como ficam as plantas do canteiro: saudável, seca, morta ou malcuidada (decide madeira verde ou seca na destruição)',\n season: 'Estação do canteiro (flores e cor das folhas)',\n wind: 'Força do vento que balança folhas, flores e grama',\n gust: 'Empurrão extra que varia devagar, somado ao vento',\n },\n options: {\n quality: { high: 'Alta', game: 'Jogo' },\n lod: { '0': 'LOD 0', '1': 'LOD 1', '2': 'LOD 2' },\n condition: { healthy: 'Saudável', dry: 'Seca', dead: 'Morta', overgrown: 'Malcuidada' },\n season: { spring: 'Primavera', summer: 'Verão', autumn: 'Outono', winter: 'Inverno' },\n },\n actions: { plant_lot: 'Plantar o canteiro', clear_lot: 'Tirar o canteiro', toggle_walker: 'Ligar ou desligar o caminhante' },\n layers: { colliders: 'Colisores (troncos e corpos de cacto)', piece_boxes: 'Caixas das peças', wood_axes: 'Eixos da madeira (raio, comprimento, eixo)' },\n metrics: { plants: 'Plantas postas', pieces: 'Peças', triangles: 'Triângulos', draw_calls: 'Chamadas de desenho', lot_triangles: 'Triângulos do canteiro', lot_plants: 'Plantas do canteiro', lot_colliders: 'Colisores do canteiro', lot_lod0: 'Plantas do canteiro em LOD 0', lot_lod1: 'Plantas do canteiro em LOD 1', lot_lod2: 'Plantas do canteiro em LOD 2', lot_ms: 'Tempo de montagem do canteiro' },\n lot: { planted: 'Canteiro plantado: {0} plantas, {1} triângulos, {2} colisores', cleared: 'Canteiro retirado', walker_on: 'O caminhante cruza o canteiro e dobra as plantas', walker_off: 'O caminhante parou' },\n },\n}\n\nexport const fill = (template: string, ...values: readonly unknown[]): string => template.replace(/\\{(\\d+)\\}/g, (_m, i: string) => String(values[Number(i)]))\n"],"mappings":"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","names":["shapeGeometries","isMesh","shapeGeometries"]}
|
package/dist/index.d.ts
CHANGED