@adatechnology/game-vegetation-three 0.0.0-stage → 0.2.0
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/LICENSE +21 -0
- package/README.md +39 -2
- package/dist/index.d.ts +237 -0
- package/dist/index.global.js +10558 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +1222 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Anderson Fernandes
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,40 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @adatechnology/game-vegetation-three
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The vegetation test module for the shared test room: the 18 plants of the Viveiro as destructible items, their 13 scenarios and the nursery lot. A literal port of the team's `vegetation-module.js`.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { loadVegetationTestModule } from '@adatechnology/game-vegetation-three'
|
|
7
|
+
|
|
8
|
+
loadVegetationTestModule(room, { locale: 'en' }) // or room.loadModule(createVegetationTestModule(options))
|
|
9
|
+
room.openArea('vegetation')
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Without options the module uses `@adatechnology/game-vegetation` (with its three.js adapter) and `@adatechnology/game-vegetation-species`; a game that brings its own build passes `GameVegetation` and `GameVegetationSpecies`.
|
|
13
|
+
|
|
14
|
+
## Items
|
|
15
|
+
|
|
16
|
+
`mango_tree`, `mango_young_15`, `mango_young_30`, `yellow_ipe`, `coconut_palm`, `banana_with_bunch`, `araucaria`, `dead_tree`, `hibiscus_shrub`, `boxwood_hedge`, `rose_bush_red`, `sunflower`, `mandacaru`, `prickly_pear`, `crown_cactus`, `potted_fern`, `potted_cactus`, `lawn_tuft`. Each piece of a plant (trunk, branch, crown, fruit, arm, pad, spines, pot, soil) is one mesh named after the piece, with its destruction spec: the shape from the real thickness of the wood (`radius`, `length` and `axis` that `generate` gives each wood piece), the joints (`stem` between a branch and the trunk, `tie` for leaves, flowers and spines, `resting` for the soil in a pot), the fixed root piece, tags, mass and `fill`, and a `sway` clip for the wind. The young mango trees are the 15 and 30 cm trunks on which the SDK documents the number of axe swings; the terracotta pot has 25 hp, so 1 to 3 shots of 9 mm break it.
|
|
17
|
+
|
|
18
|
+
## Scenarios
|
|
19
|
+
|
|
20
|
+
The 13 of the page, with its ids: `veg_axe_fells_crown`, `veg_axe_fells_30cm`, `veg_axe_cuts_branch_joint`, `veg_shot_cannot_fell`, `veg_saw_cuts_branch`, `veg_lighter_ignites_foliage`, `veg_shot_strips_leaves`, `veg_shot_breaks_pot`, `veg_machete_arm`, `veg_pad_pulled`, `veg_dead_burns_faster`, `veg_hedge_cut_pieces`, `veg_walk_on_grass`. The room gives every tool a draw time that the team's page did not know, so each scenario waits for the tool to be ready.
|
|
21
|
+
|
|
22
|
+
## Bench
|
|
23
|
+
|
|
24
|
+
- Controls: the seed, quality (high or game), detail (LOD 0 to 2), condition and season of the nursery lot, the wind and the gusts. Actions: plant the lot, remove it, start or stop the walker. Changing a lot control plants the lot again.
|
|
25
|
+
- The nursery is the 12 x 20 m plot of the Viveiro's lot demo (house, walls, street, sidewalk, path), planted by `scatterRulesFor` of `@adatechnology/game-vegetation-species` over the front yard, the backyard, the side strips and the sidewalk tree, and built by `buildLot`. The walker crosses it along `WAY`, stays out of the house and the trunks, and bends the plants through the wind shader's actors.
|
|
26
|
+
- Layers: `colliders` (the trunks and cactus bodies as wire cylinders), `piece_boxes` (the box of every piece) and `wood_axes` (a line along the centreline of each wood piece).
|
|
27
|
+
- Metrics: plants, pieces, triangles and draw calls of the items, and the triangles, plants, colliders, plants by LOD and build time of the lot.
|
|
28
|
+
|
|
29
|
+
The module draws no particles and asks for no effects: leaves, sap and fire come from the events of the default destruction world, which the room shows.
|
|
30
|
+
|
|
31
|
+
## Tests
|
|
32
|
+
|
|
33
|
+
`tests/team-golden-module.test.ts` runs the module of the Viveiro artifact against the kit's room and compares it with this one: the 18 items (names in both languages, meshes, specs, clips) and the 13 scenarios (the same checks and the same count of every log line). `tests/team-golden-nursery.test.ts` cuts `buildLotVeg` from the page and compares the placements, triangles, plants, colliders and species for 8 seeds. `examples/vegetation-test-area` loads the module, and so does `examples/interactables-test-area`.
|
|
34
|
+
|
|
35
|
+
## Geometry
|
|
36
|
+
|
|
37
|
+
The nursery's scenery (ground, street, walls, house and roof), its colliders and walker, and the colliders layer are made through
|
|
38
|
+
`shapeGeometries(THREE)` of `@adatechnology/game-shapes-three`: the same bytes as three's constructors
|
|
39
|
+
(`tests/exact-golden.test.ts`), cached by parameters. The plants themselves are `@adatechnology/game-vegetation`'s own buffers (`PlantMesh`,
|
|
40
|
+
with the per-vertex `sway` of the wind), drawn by its adapter.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { Vec3, TestableModule, DestructibleSpec, AnimationClipSpec, TestableItem } from '@adatechnology/game-contracts';
|
|
2
|
+
import * as GameVegetationMain from '@adatechnology/game-vegetation';
|
|
3
|
+
import { Condition, PlantSpec, PlantMesh, Lod, Season, Placement } from '@adatechnology/game-vegetation';
|
|
4
|
+
import * as GameVegetationAdapter from '@adatechnology/game-vegetation/three';
|
|
5
|
+
import * as GameVegetationSpeciesMain from '@adatechnology/game-vegetation-species';
|
|
6
|
+
import { ScatterRulesOptions } from '@adatechnology/game-vegetation-species';
|
|
7
|
+
|
|
8
|
+
/** The vegetation engine with its three.js adapter, as the `GameVegetation` global of the IIFE build has it. */
|
|
9
|
+
type VegetationSdk = typeof GameVegetationMain & typeof GameVegetationAdapter;
|
|
10
|
+
/** The species pack. */
|
|
11
|
+
type SpeciesSdk = typeof GameVegetationSpeciesMain;
|
|
12
|
+
/** The shared materials of the plants (wind and the actors that bend them). */
|
|
13
|
+
type MaterialsLike = GameVegetationAdapter.VegetationMaterials;
|
|
14
|
+
type VegetationTestOptions = {
|
|
15
|
+
/** `en` or `pt-BR` (default). The room asks `items(locale)` and `scenarios(locale)` itself; this is the language of the bench and of the lines the module writes. */
|
|
16
|
+
readonly locale?: string;
|
|
17
|
+
/** The vegetation engine (default: `@adatechnology/game-vegetation` with its three adapter). A game that brings its own build of it passes it here. */
|
|
18
|
+
readonly GameVegetation?: VegetationSdk;
|
|
19
|
+
/** The species pack (default: `@adatechnology/game-vegetation-species`). */
|
|
20
|
+
readonly GameVegetationSpecies?: SpeciesSdk;
|
|
21
|
+
/** The materials of the plants, when the game already has them (default: made from the first three.js namespace the module is built with). */
|
|
22
|
+
readonly materials?: MaterialsLike;
|
|
23
|
+
/** Seed of the plants (the Viveiro's module uses 3, so the items are the same in every run). */
|
|
24
|
+
readonly seed?: number;
|
|
25
|
+
/** Where the nursery lot stands in the room, the corner of its 12 x 20 m plot: `[x, z]` (default `[-6, 14]`). */
|
|
26
|
+
readonly nurseryOrigin?: readonly [number, number];
|
|
27
|
+
};
|
|
28
|
+
/** The part of the test room the scenarios use (the room's `ScenarioContext.room` has all of it). */
|
|
29
|
+
type VegetationRoom = {
|
|
30
|
+
spawn(item: string, position?: Vec3, rotationY?: number): {
|
|
31
|
+
objectId: string;
|
|
32
|
+
root: {
|
|
33
|
+
userData: Record<string, any>;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
setTool(weaponId: string): void;
|
|
37
|
+
/** Lets the tool in hand finish its draw time (the room's rule: a tool cannot be used the moment it is taken). */
|
|
38
|
+
waitUntilReady(): void;
|
|
39
|
+
look(position: Vec3, target: Vec3): void;
|
|
40
|
+
use(hold?: number): void;
|
|
41
|
+
walk(to: Vec3, seconds: number): void;
|
|
42
|
+
camera: {
|
|
43
|
+
position: {
|
|
44
|
+
x: number;
|
|
45
|
+
y: number;
|
|
46
|
+
z: number;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
world: {
|
|
50
|
+
raycast(origin: Vec3, direction: Vec3, max: number): {
|
|
51
|
+
object: string;
|
|
52
|
+
part?: string;
|
|
53
|
+
point: Vec3;
|
|
54
|
+
} | null;
|
|
55
|
+
nearestJoint(object: string, point: Vec3, range: number, tool?: string): {
|
|
56
|
+
id: string;
|
|
57
|
+
} | null;
|
|
58
|
+
snapshot(object: string): any;
|
|
59
|
+
state(object: string): any;
|
|
60
|
+
part(object: string, part: string): any;
|
|
61
|
+
ids(): string[];
|
|
62
|
+
};
|
|
63
|
+
log: {
|
|
64
|
+
entries(filter: {
|
|
65
|
+
type?: string;
|
|
66
|
+
objectId?: string;
|
|
67
|
+
}): readonly any[];
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
/** What a scenario needs of the room: the pass/fail line, time, and the room for the ones that shoot, cut and burn. */
|
|
71
|
+
type VegetationContext = {
|
|
72
|
+
room: VegetationRoom;
|
|
73
|
+
expect(condition: boolean, label: string, data?: Record<string, unknown>): void;
|
|
74
|
+
step(seconds: number): void;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
declare const VEGETATION_AREA_ID = "vegetation";
|
|
78
|
+
/** The 18 item ids of the Viveiro's module, in its order. */
|
|
79
|
+
declare const VEGETATION_ITEM_IDS: readonly string[];
|
|
80
|
+
/** The ids of the 13 scenarios (the ids of the Viveiro's page, `veg_*`). */
|
|
81
|
+
declare const VEGETATION_SCENARIO_IDS: readonly string[];
|
|
82
|
+
/**
|
|
83
|
+
* 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
|
|
84
|
+
* 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
|
|
85
|
+
* 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
|
|
86
|
+
* 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.
|
|
87
|
+
*/
|
|
88
|
+
declare function createVegetationTestModule(options?: VegetationTestOptions): TestableModule<VegetationContext> & {
|
|
89
|
+
readonly placed: ReadonlyMap<string, unknown>;
|
|
90
|
+
materials(THREE?: unknown): MaterialsLike;
|
|
91
|
+
tick(t: number): void;
|
|
92
|
+
readonly itemIds: readonly string[];
|
|
93
|
+
};
|
|
94
|
+
/** What `loadVegetationTestModule` needs of a room: `TestRoom.loadModule` has it. */
|
|
95
|
+
type ModuleRoomLike = {
|
|
96
|
+
loadModule(module: never): unknown;
|
|
97
|
+
};
|
|
98
|
+
/** Loads the vegetation module into a room. */
|
|
99
|
+
declare function loadVegetationTestModule<Room extends ModuleRoomLike>(room: Room, options?: VegetationTestOptions): ReturnType<Room['loadModule']>;
|
|
100
|
+
|
|
101
|
+
/** The seed of every plant of the area (the Viveiro's module fixes it, so the plants are the same in every run). */
|
|
102
|
+
declare const PLANT_SEED = 3;
|
|
103
|
+
type PlantDefKind = 'tree' | 'shrub' | 'hedge' | 'flower' | 'cactus' | 'pot' | 'tuft';
|
|
104
|
+
/** One item of the area: a species of the pack (or a variant of it) and how it is built. */
|
|
105
|
+
type PlantDef = {
|
|
106
|
+
readonly id: string;
|
|
107
|
+
/** The species the plant is generated from (default: `id`). */
|
|
108
|
+
readonly base?: string;
|
|
109
|
+
readonly kind: PlantDefKind;
|
|
110
|
+
readonly sway: boolean;
|
|
111
|
+
/** Fields of the species spec replaced for this item. */
|
|
112
|
+
readonly over?: Readonly<Record<string, number>>;
|
|
113
|
+
/** The name, `[pt-BR, en]`, when the species name does not fit the variant. */
|
|
114
|
+
readonly name?: readonly [string, string];
|
|
115
|
+
readonly condition?: Condition;
|
|
116
|
+
/** Plants side by side (a hedge is 4 sections joined by their stems). */
|
|
117
|
+
readonly segments?: number;
|
|
118
|
+
readonly movable?: boolean;
|
|
119
|
+
};
|
|
120
|
+
/** The 18 items of the Viveiro's module, in its order. */
|
|
121
|
+
declare const PLANT_DEFS: readonly PlantDef[];
|
|
122
|
+
/** The id of a mesh or a joint: lower case, runs of other characters turned into one `_` (`crown:flowers` becomes `crown_flowers`). */
|
|
123
|
+
declare const sanitize: (s: string) => string;
|
|
124
|
+
/** What `buildObject` records in `userData.veg` of each piece mesh. */
|
|
125
|
+
type PieceMeta = {
|
|
126
|
+
id: string;
|
|
127
|
+
piece: string;
|
|
128
|
+
kind: string;
|
|
129
|
+
sub: string | null;
|
|
130
|
+
base: string;
|
|
131
|
+
parent: string | null;
|
|
132
|
+
seg: number;
|
|
133
|
+
materialKey: string;
|
|
134
|
+
radius?: number;
|
|
135
|
+
length?: number;
|
|
136
|
+
axis?: [number, number, number];
|
|
137
|
+
/** Where the plant of this section stands along x in the object (sections of a hedge are side by side). */
|
|
138
|
+
dx: number;
|
|
139
|
+
};
|
|
140
|
+
type Three$1 = any;
|
|
141
|
+
declare function createPlants(sdk: VegetationSdk, species: SpeciesSdk, materials: (THREE: Three$1) => MaterialsLike, seed?: number): {
|
|
142
|
+
defs: Map<string, PlantDef>;
|
|
143
|
+
specFor: (def: PlantDef) => PlantSpec;
|
|
144
|
+
plantFor: (def: PlantDef, segment: number) => PlantMesh;
|
|
145
|
+
buildObject: (THREE: Three$1, def: PlantDef) => any;
|
|
146
|
+
buildSpec: (root: any, def: PlantDef) => DestructibleSpec;
|
|
147
|
+
swayClip: (def: PlantDef) => AnimationClipSpec;
|
|
148
|
+
items: (locale: string, defsToUse?: readonly PlantDef[]) => TestableItem[];
|
|
149
|
+
};
|
|
150
|
+
type Plants = ReturnType<typeof createPlants>;
|
|
151
|
+
|
|
152
|
+
type Three = any;
|
|
153
|
+
/** The plot of the Viveiro's lot demo, in metres: the corner at (0, 0), the street on the negative z side. */
|
|
154
|
+
declare const LOT: {
|
|
155
|
+
readonly W: 12;
|
|
156
|
+
readonly D: 20;
|
|
157
|
+
};
|
|
158
|
+
declare const HOUSE: {
|
|
159
|
+
readonly x0: 2.5;
|
|
160
|
+
readonly x1: 9.5;
|
|
161
|
+
readonly z0: 6.5;
|
|
162
|
+
readonly z1: 13;
|
|
163
|
+
};
|
|
164
|
+
/** The walker's route (x, z). */
|
|
165
|
+
declare const WAY: readonly (readonly [number, number])[];
|
|
166
|
+
type Rect = {
|
|
167
|
+
rect: {
|
|
168
|
+
x: number;
|
|
169
|
+
z: number;
|
|
170
|
+
w: number;
|
|
171
|
+
d: number;
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
declare const EX_HOUSE: Rect;
|
|
175
|
+
declare const EX_PATH: Rect;
|
|
176
|
+
/** Where each kind of planting goes. */
|
|
177
|
+
declare const AREAS: Readonly<Record<'front_yard' | 'backyard' | 'sides' | 'sidewalk_tree', Rect[]>>;
|
|
178
|
+
/** 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. */
|
|
179
|
+
type Planting = {
|
|
180
|
+
context: string;
|
|
181
|
+
areas: Rect[];
|
|
182
|
+
options: ScatterRulesOptions & {
|
|
183
|
+
n: number;
|
|
184
|
+
};
|
|
185
|
+
tag: string;
|
|
186
|
+
};
|
|
187
|
+
declare const PLANTINGS: readonly Planting[];
|
|
188
|
+
type NurserySettings = {
|
|
189
|
+
seed: number;
|
|
190
|
+
quality: 'high' | 'game';
|
|
191
|
+
lod: Lod;
|
|
192
|
+
condition: Condition;
|
|
193
|
+
season: Season;
|
|
194
|
+
};
|
|
195
|
+
type LotStats = {
|
|
196
|
+
triangles: number;
|
|
197
|
+
plants: number;
|
|
198
|
+
colliders: number;
|
|
199
|
+
meshes: number;
|
|
200
|
+
lod: [number, number, number];
|
|
201
|
+
buildMs: number;
|
|
202
|
+
species: number;
|
|
203
|
+
};
|
|
204
|
+
/**
|
|
205
|
+
* 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
|
|
206
|
+
* 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.
|
|
207
|
+
*/
|
|
208
|
+
declare function scatterLot(sdk: VegetationSdk, species: SpeciesSdk, seedNumber: number, plantings?: readonly Planting[]): {
|
|
209
|
+
placements: Placement[];
|
|
210
|
+
used: Set<string>;
|
|
211
|
+
};
|
|
212
|
+
/**
|
|
213
|
+
* 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
|
|
214
|
+
* the plants (the wind shader's actors). The module owns it; `plant` builds it, `clear` takes it away.
|
|
215
|
+
*/
|
|
216
|
+
declare function createNursery(sdk: VegetationSdk, species: SpeciesSdk, THREE: Three, materials: MaterialsLike, parent: any, origin: readonly [number, number]): {
|
|
217
|
+
group: any;
|
|
218
|
+
readonly stats: LotStats | null;
|
|
219
|
+
readonly planted: boolean;
|
|
220
|
+
readonly walking: boolean;
|
|
221
|
+
readonly position: {
|
|
222
|
+
x: number;
|
|
223
|
+
z: number;
|
|
224
|
+
};
|
|
225
|
+
/** Plants the lot with the settings (replaces the one standing). */
|
|
226
|
+
plant(settings: NurserySettings): LotStats;
|
|
227
|
+
/** The colliders of the lot as wire cylinders. */
|
|
228
|
+
showColliders(on: boolean): void;
|
|
229
|
+
/** Starts or stops the walker that crosses the lot along `WAY`, bending the plants. */
|
|
230
|
+
setWalker(on: boolean): void;
|
|
231
|
+
step(dt: number): void;
|
|
232
|
+
/** Takes the lot, the walker and the scenery away. */
|
|
233
|
+
clear(): void;
|
|
234
|
+
};
|
|
235
|
+
type Nursery = ReturnType<typeof createNursery>;
|
|
236
|
+
|
|
237
|
+
export { AREAS, EX_HOUSE, EX_PATH, HOUSE, LOT, type LotStats, type MaterialsLike, type ModuleRoomLike, type Nursery, type NurserySettings, PLANTINGS, PLANT_DEFS, PLANT_SEED, type PieceMeta, type PlantDef, type PlantDefKind, type Planting, type Plants, type SpeciesSdk, VEGETATION_AREA_ID, VEGETATION_ITEM_IDS, VEGETATION_SCENARIO_IDS, type VegetationContext, type VegetationRoom, type VegetationSdk, type VegetationTestOptions, WAY, createNursery, createPlants, createVegetationTestModule, loadVegetationTestModule, sanitize, scatterLot };
|