@jgengine/core 0.8.0 → 0.9.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/CHANGELOG.md +16 -0
- package/dist/ai/flock.d.ts +36 -0
- package/dist/ai/flock.js +182 -0
- package/dist/ai/groupAssist.d.ts +19 -0
- package/dist/ai/groupAssist.js +59 -0
- package/dist/ai/laneSelect.d.ts +21 -0
- package/dist/ai/laneSelect.js +37 -0
- package/dist/ai/mobBrain.d.ts +68 -0
- package/dist/ai/mobBrain.js +115 -0
- package/dist/ai/spawnDirector.js +1 -1
- package/dist/ai/threat.d.ts +2 -0
- package/dist/ai/threat.js +34 -0
- package/dist/cartridge/runtime.d.ts +15 -0
- package/dist/cartridge/runtime.js +556 -0
- package/dist/cartridge/spec.d.ts +188 -0
- package/dist/cartridge/spec.js +19 -0
- package/dist/cartridge/validate.d.ts +2 -0
- package/dist/cartridge/validate.js +78 -0
- package/dist/combat/abilityKit.d.ts +17 -2
- package/dist/combat/abilityKit.js +62 -13
- package/dist/combat/castRunner.d.ts +40 -0
- package/dist/combat/castRunner.js +56 -0
- package/dist/combat/comboPoints.d.ts +14 -0
- package/dist/combat/comboPoints.js +52 -0
- package/dist/combat/defensiveWindow.d.ts +1 -1
- package/dist/combat/defensiveWindow.js +5 -3
- package/dist/combat/projectiles.d.ts +33 -12
- package/dist/combat/projectiles.js +201 -129
- package/dist/combat/resistance.d.ts +16 -4
- package/dist/combat/resistance.js +43 -7
- package/dist/combat/resourcePool.d.ts +20 -0
- package/dist/combat/resourcePool.js +55 -0
- package/dist/combat/shotOrigin.d.ts +40 -0
- package/dist/combat/shotOrigin.js +57 -0
- package/dist/combat/telegraph.d.ts +25 -0
- package/dist/combat/telegraph.js +47 -0
- package/dist/crafting/recipe.js +4 -1
- package/dist/devtools/devtools.d.ts +72 -24
- package/dist/devtools/devtools.js +449 -101
- package/dist/devtools/transformTunables.js +3 -3
- package/dist/devtools/tunableSchema.d.ts +140 -0
- package/dist/devtools/tunableSchema.js +476 -0
- package/dist/faction/factions.d.ts +33 -0
- package/dist/faction/factions.js +76 -0
- package/dist/faction/reputation.d.ts +32 -0
- package/dist/faction/reputation.js +82 -0
- package/dist/game/chat.d.ts +2 -0
- package/dist/game/chat.js +9 -1
- package/dist/game/chatFilter.d.ts +15 -0
- package/dist/game/chatFilter.js +55 -0
- package/dist/game/controlGate.d.ts +4 -0
- package/dist/game/controlGate.js +7 -0
- package/dist/game/defineGame.d.ts +2 -0
- package/dist/game/events.d.ts +10 -0
- package/dist/game/gamePhase.d.ts +20 -0
- package/dist/game/gamePhase.js +21 -0
- package/dist/game/lootTable.d.ts +10 -1
- package/dist/game/lootTable.js +27 -7
- package/dist/game/playableGame.d.ts +50 -1
- package/dist/game/playableGame.js +1 -1
- package/dist/game/quest.d.ts +7 -3
- package/dist/game/quest.js +17 -8
- package/dist/game/race.d.ts +39 -1
- package/dist/game/race.js +96 -11
- package/dist/game/recordBook.d.ts +29 -0
- package/dist/game/recordBook.js +86 -0
- package/dist/game/talents.d.ts +47 -0
- package/dist/game/talents.js +140 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/input/axisInput.d.ts +26 -3
- package/dist/input/axisInput.js +44 -4
- package/dist/input/bindingOverrides.d.ts +25 -0
- package/dist/input/bindingOverrides.js +95 -0
- package/dist/input/pointerAxis.d.ts +30 -0
- package/dist/input/pointerAxis.js +31 -0
- package/dist/input/touchScheme.d.ts +6 -0
- package/dist/input/touchScheme.js +45 -7
- package/dist/meta/changelog.d.ts +1 -1
- package/dist/meta/changelog.js +23 -1
- package/dist/movement/dash.d.ts +3 -0
- package/dist/movement/dash.js +19 -5
- package/dist/movement/glideModel.d.ts +44 -0
- package/dist/movement/glideModel.js +54 -0
- package/dist/movement/grappleSwing.d.ts +34 -0
- package/dist/movement/grappleSwing.js +56 -0
- package/dist/movement/leaderTrail.d.ts +29 -0
- package/dist/movement/leaderTrail.js +67 -0
- package/dist/movement/steering.d.ts +27 -0
- package/dist/movement/steering.js +40 -0
- package/dist/multiplayer/feedWriteGate.d.ts +10 -0
- package/dist/multiplayer/feedWriteGate.js +12 -0
- package/dist/multiplayer/presenceModel.d.ts +14 -2
- package/dist/multiplayer/presenceModel.js +15 -3
- package/dist/nav/corridors.d.ts +30 -0
- package/dist/nav/corridors.js +69 -0
- package/dist/nav/navGrid.js +30 -4
- package/dist/nav/railGraph.d.ts +66 -0
- package/dist/nav/railGraph.js +129 -0
- package/dist/nav/timetable.d.ts +41 -0
- package/dist/nav/timetable.js +94 -0
- package/dist/physics/buoyancy.d.ts +6 -0
- package/dist/physics/buoyancy.js +14 -0
- package/dist/physics/flowTube.d.ts +32 -0
- package/dist/physics/flowTube.js +64 -0
- package/dist/physics/forceVolume.d.ts +27 -0
- package/dist/physics/forceVolume.js +38 -0
- package/dist/physics/kinematicVehicle.d.ts +52 -0
- package/dist/physics/kinematicVehicle.js +81 -0
- package/dist/physics/physicsWorld.d.ts +13 -6
- package/dist/physics/physicsWorld.js +169 -40
- package/dist/physics/ragdoll.js +1 -1
- package/dist/physics/vehicleBody.js +2 -1
- package/dist/random/seedLink.d.ts +5 -0
- package/dist/random/seedLink.js +35 -0
- package/dist/runtime/cameraDirector.d.ts +6 -1
- package/dist/runtime/cameraDirector.js +6 -0
- package/dist/runtime/commandRunner.d.ts +2 -2
- package/dist/runtime/commandRunner.js +2 -2
- package/dist/runtime/gameContext.d.ts +21 -0
- package/dist/runtime/gameContext.js +184 -9
- package/dist/runtime/gameRuntime.d.ts +5 -1
- package/dist/runtime/gameRuntime.js +13 -12
- package/dist/runtime/hostPersistence.d.ts +9 -1
- package/dist/runtime/hostPersistence.js +23 -8
- package/dist/runtime/inputSnapshot.d.ts +5 -0
- package/dist/runtime/inputSnapshot.js +5 -0
- package/dist/runtime/motionIntents.d.ts +14 -6
- package/dist/runtime/motionIntents.js +20 -2
- package/dist/runtime/snapshot.d.ts +1 -0
- package/dist/runtime/snapshot.js +1 -1
- package/dist/runtime/visibility.d.ts +74 -0
- package/dist/runtime/visibility.js +127 -0
- package/dist/scene/colliders.d.ts +44 -0
- package/dist/scene/colliders.js +77 -0
- package/dist/scene/entityStore.d.ts +22 -5
- package/dist/scene/entityStore.js +59 -12
- package/dist/scene/objectQuery.d.ts +13 -2
- package/dist/scene/objectQuery.js +34 -2
- package/dist/scene/objectStore.d.ts +2 -0
- package/dist/scene/objectStore.js +31 -12
- package/dist/scene/sceneRaycast.d.ts +80 -0
- package/dist/scene/sceneRaycast.js +284 -0
- package/dist/scene/spatial.d.ts +11 -16
- package/dist/scene/spatial.js +99 -38
- package/dist/sensor/recordingBuffer.d.ts +6 -0
- package/dist/sensor/recordingBuffer.js +7 -0
- package/dist/sensor/replayLoop.d.ts +39 -0
- package/dist/sensor/replayLoop.js +64 -0
- package/dist/sensor/visionCone.d.ts +31 -0
- package/dist/sensor/visionCone.js +72 -0
- package/dist/session/extraction.d.ts +2 -2
- package/dist/session/extraction.js +13 -2
- package/dist/settings/settingsModel.d.ts +97 -0
- package/dist/settings/settingsModel.js +100 -0
- package/dist/stats/statModifiers.d.ts +5 -2
- package/dist/stats/statModifiers.js +32 -14
- package/dist/store/observableKeyedStore.js +8 -2
- package/dist/survival/decayMeter.d.ts +1 -1
- package/dist/survival/decayMeter.js +0 -1
- package/dist/time/beatClock.d.ts +18 -0
- package/dist/time/beatClock.js +24 -0
- package/dist/time/idleProgress.d.ts +29 -0
- package/dist/time/idleProgress.js +31 -0
- package/dist/time/serverTick.d.ts +7 -1
- package/dist/time/serverTick.js +27 -4
- package/dist/time/stateSchedule.d.ts +57 -0
- package/dist/time/stateSchedule.js +121 -0
- package/dist/turn/commit.d.ts +2 -2
- package/dist/turn/commit.js +2 -2
- package/dist/ui/hudLayout.d.ts +58 -0
- package/dist/ui/hudLayout.js +207 -0
- package/dist/ui/hudScale.d.ts +44 -0
- package/dist/ui/hudScale.js +55 -0
- package/dist/visibility/assetStreaming.d.ts +66 -0
- package/dist/visibility/assetStreaming.js +201 -0
- package/dist/visibility/bounds.d.ts +66 -0
- package/dist/visibility/bounds.js +113 -0
- package/dist/visibility/camera.d.ts +21 -0
- package/dist/visibility/camera.js +3 -0
- package/dist/visibility/config.d.ts +21 -0
- package/dist/visibility/config.js +1 -0
- package/dist/visibility/diagnostics.d.ts +26 -0
- package/dist/visibility/diagnostics.js +36 -0
- package/dist/visibility/distance.d.ts +11 -0
- package/dist/visibility/distance.js +30 -0
- package/dist/visibility/frustum.d.ts +47 -0
- package/dist/visibility/frustum.js +186 -0
- package/dist/visibility/occlusion.d.ts +36 -0
- package/dist/visibility/occlusion.js +45 -0
- package/dist/visibility/settings.d.ts +75 -0
- package/dist/visibility/settings.js +49 -0
- package/dist/visibility/simulationCulling.d.ts +34 -0
- package/dist/visibility/simulationCulling.js +36 -0
- package/dist/visibility/spatialIndex.d.ts +45 -0
- package/dist/visibility/spatialIndex.js +198 -0
- package/dist/visibility/visibilitySystem.d.ts +90 -0
- package/dist/visibility/visibilitySystem.js +257 -0
- package/dist/world/buildings.d.ts +6 -0
- package/dist/world/buildings.js +152 -0
- package/dist/world/carve.d.ts +7 -2
- package/dist/world/carve.js +17 -7
- package/dist/world/cellStates.d.ts +45 -0
- package/dist/world/cellStates.js +103 -0
- package/dist/world/environmentSummary.d.ts +10 -2
- package/dist/world/environmentSummary.js +11 -2
- package/dist/world/features.d.ts +56 -8
- package/dist/world/features.js +24 -3
- package/dist/world/gridInstances.d.ts +7 -8
- package/dist/world/gridInstances.js +145 -7
- package/dist/world/lod.d.ts +17 -0
- package/dist/world/lod.js +66 -0
- package/dist/world/mapLayers.d.ts +60 -0
- package/dist/world/mapLayers.js +44 -0
- package/dist/world/massing.d.ts +45 -0
- package/dist/world/massing.js +581 -0
- package/dist/world/minimap.d.ts +13 -1
- package/dist/world/minimap.js +21 -2
- package/dist/world/terrain.d.ts +42 -3
- package/dist/world/terrain.js +197 -16
- package/dist/world/water.d.ts +7 -0
- package/dist/world/water.js +19 -4
- package/dist/world/weather.d.ts +3 -18
- package/dist/world/weather.js +4 -17
- package/dist/world/windZones.d.ts +47 -0
- package/dist/world/windZones.js +59 -0
- package/llms.txt +2585 -1704
- package/package.json +12 -2
package/dist/world/buildings.js
CHANGED
|
@@ -33,6 +33,158 @@ export const DEFAULT_BUILDING_CONFIG = {
|
|
|
33
33
|
probabilities: DEFAULT_PROBABILITIES,
|
|
34
34
|
variants: DEFAULT_VARIANTS,
|
|
35
35
|
};
|
|
36
|
+
export const DEFAULT_BUILDING_STYLE = "generic";
|
|
37
|
+
export const BUILDING_STYLE_PALETTES = {
|
|
38
|
+
generic: {
|
|
39
|
+
wall: "#83766a",
|
|
40
|
+
window: "#8ecae6",
|
|
41
|
+
awning: "#c2410c",
|
|
42
|
+
airConditioner: "#d4d4d8",
|
|
43
|
+
clothesline: "#facc15",
|
|
44
|
+
storefront: "#3f3f46",
|
|
45
|
+
shutter: "#52525b",
|
|
46
|
+
storeSign: "#f97316",
|
|
47
|
+
roof: "#57534e",
|
|
48
|
+
roofProp: "#14b8a6",
|
|
49
|
+
guardrail: "#a8a29e",
|
|
50
|
+
corner: "#6b6258",
|
|
51
|
+
},
|
|
52
|
+
capital: {
|
|
53
|
+
wall: "#cfc5ad",
|
|
54
|
+
window: "#33506e",
|
|
55
|
+
awning: "#7a1f2b",
|
|
56
|
+
airConditioner: "#b9b3a4",
|
|
57
|
+
clothesline: "#d9cfae",
|
|
58
|
+
storefront: "#4a3f33",
|
|
59
|
+
shutter: "#5d5647",
|
|
60
|
+
storeSign: "#d4af37",
|
|
61
|
+
roof: "#3b4252",
|
|
62
|
+
roofProp: "#8c7a4e",
|
|
63
|
+
guardrail: "#a89f88",
|
|
64
|
+
corner: "#b3a98d",
|
|
65
|
+
},
|
|
66
|
+
village: {
|
|
67
|
+
wall: "#b59e7a",
|
|
68
|
+
window: "#e9c46a",
|
|
69
|
+
awning: "#7f5539",
|
|
70
|
+
airConditioner: "#a8a29e",
|
|
71
|
+
clothesline: "#e07a5f",
|
|
72
|
+
storefront: "#5c4a36",
|
|
73
|
+
shutter: "#6e5a40",
|
|
74
|
+
storeSign: "#c8894a",
|
|
75
|
+
roof: "#8a5a3b",
|
|
76
|
+
roofProp: "#97724d",
|
|
77
|
+
guardrail: "#8f8271",
|
|
78
|
+
corner: "#8d7354",
|
|
79
|
+
},
|
|
80
|
+
desert: {
|
|
81
|
+
wall: "#c9a877",
|
|
82
|
+
window: "#3f6f6b",
|
|
83
|
+
awning: "#a3512e",
|
|
84
|
+
airConditioner: "#c9bfa8",
|
|
85
|
+
clothesline: "#d9b16f",
|
|
86
|
+
storefront: "#6e5233",
|
|
87
|
+
shutter: "#7d6140",
|
|
88
|
+
storeSign: "#b8742f",
|
|
89
|
+
roof: "#b5946a",
|
|
90
|
+
roofProp: "#9a7648",
|
|
91
|
+
guardrail: "#b09b77",
|
|
92
|
+
corner: "#a98c5d",
|
|
93
|
+
},
|
|
94
|
+
industrial: {
|
|
95
|
+
wall: "#6b7280",
|
|
96
|
+
window: "#9fb3c8",
|
|
97
|
+
awning: "#f97316",
|
|
98
|
+
airConditioner: "#9ca3af",
|
|
99
|
+
clothesline: "#eab308",
|
|
100
|
+
storefront: "#374151",
|
|
101
|
+
shutter: "#4b5563",
|
|
102
|
+
storeSign: "#f59e0b",
|
|
103
|
+
roof: "#374151",
|
|
104
|
+
roofProp: "#ef4444",
|
|
105
|
+
guardrail: "#d1d5db",
|
|
106
|
+
corner: "#52596b",
|
|
107
|
+
},
|
|
108
|
+
coastal: {
|
|
109
|
+
wall: "#e8e2d2",
|
|
110
|
+
window: "#7cc3d8",
|
|
111
|
+
awning: "#e76f51",
|
|
112
|
+
airConditioner: "#cfd8dc",
|
|
113
|
+
clothesline: "#f2cc8f",
|
|
114
|
+
storefront: "#35526b",
|
|
115
|
+
shutter: "#3a7ca5",
|
|
116
|
+
storeSign: "#ee6c4d",
|
|
117
|
+
roof: "#4f6d7a",
|
|
118
|
+
roofProp: "#62b6cb",
|
|
119
|
+
guardrail: "#c5ccc2",
|
|
120
|
+
corner: "#cfc5ab",
|
|
121
|
+
},
|
|
122
|
+
neon: {
|
|
123
|
+
wall: "#1b1b26",
|
|
124
|
+
window: "#22d3ee",
|
|
125
|
+
awning: "#ff2d95",
|
|
126
|
+
airConditioner: "#3f3f50",
|
|
127
|
+
clothesline: "#a78bfa",
|
|
128
|
+
storefront: "#12121a",
|
|
129
|
+
shutter: "#2a2a3a",
|
|
130
|
+
storeSign: "#f0abfc",
|
|
131
|
+
roof: "#14141d",
|
|
132
|
+
roofProp: "#34d399",
|
|
133
|
+
guardrail: "#52525f",
|
|
134
|
+
corner: "#24242f",
|
|
135
|
+
},
|
|
136
|
+
ruin: {
|
|
137
|
+
wall: "#6b6156",
|
|
138
|
+
window: "#1c1917",
|
|
139
|
+
awning: "#4a4238",
|
|
140
|
+
airConditioner: "#57534e",
|
|
141
|
+
clothesline: "#6b7f4f",
|
|
142
|
+
storefront: "#292524",
|
|
143
|
+
shutter: "#44403c",
|
|
144
|
+
storeSign: "#78716c",
|
|
145
|
+
roof: "#4a443e",
|
|
146
|
+
roofProp: "#6b7f4f",
|
|
147
|
+
guardrail: "#7c7268",
|
|
148
|
+
corner: "#57503f",
|
|
149
|
+
},
|
|
150
|
+
frontier: {
|
|
151
|
+
wall: "#7f5539",
|
|
152
|
+
window: "#d9ae62",
|
|
153
|
+
awning: "#6e3f1f",
|
|
154
|
+
airConditioner: "#8d8072",
|
|
155
|
+
clothesline: "#c98a5e",
|
|
156
|
+
storefront: "#4a3220",
|
|
157
|
+
shutter: "#5c3d26",
|
|
158
|
+
storeSign: "#b3702f",
|
|
159
|
+
roof: "#9c4a1a",
|
|
160
|
+
roofProp: "#7d6b52",
|
|
161
|
+
guardrail: "#937b5f",
|
|
162
|
+
corner: "#66492f",
|
|
163
|
+
},
|
|
164
|
+
aerial: {
|
|
165
|
+
wall: "#dfe7ec",
|
|
166
|
+
window: "#67c3cc",
|
|
167
|
+
awning: "#4d7ea8",
|
|
168
|
+
airConditioner: "#b8c4cc",
|
|
169
|
+
clothesline: "#9fd8df",
|
|
170
|
+
storefront: "#5c7684",
|
|
171
|
+
shutter: "#7b95a3",
|
|
172
|
+
storeSign: "#3aa7b8",
|
|
173
|
+
roof: "#aebcc4",
|
|
174
|
+
roofProp: "#e0f2f5",
|
|
175
|
+
guardrail: "#98a8b0",
|
|
176
|
+
corner: "#c3d0d7",
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
export function resolveBuildingPalette(style = DEFAULT_BUILDING_STYLE, overrides) {
|
|
180
|
+
const preset = BUILDING_STYLE_PALETTES[style];
|
|
181
|
+
if (preset === undefined) {
|
|
182
|
+
throw new Error(`Unknown building style "${style}". Valid styles: ${Object.keys(BUILDING_STYLE_PALETTES).join(", ")}. Use palette: { wall, window, ... } for a custom look.`);
|
|
183
|
+
}
|
|
184
|
+
if (overrides === undefined)
|
|
185
|
+
return preset;
|
|
186
|
+
return { ...preset, ...overrides };
|
|
187
|
+
}
|
|
36
188
|
function hashU32(input) {
|
|
37
189
|
let hash = 2166136261;
|
|
38
190
|
for (let index = 0; index < input.length; index += 1) {
|
package/dist/world/carve.d.ts
CHANGED
|
@@ -95,11 +95,16 @@ export declare class CarvableField implements TerrainField {
|
|
|
95
95
|
readonly sampleNormal: TerrainField["sampleNormal"];
|
|
96
96
|
private readonly base;
|
|
97
97
|
private readonly edits;
|
|
98
|
+
private nextEditId;
|
|
98
99
|
constructor(base: TerrainField);
|
|
99
100
|
get editCount(): number;
|
|
100
101
|
sampleHeight(x: number, z: number): number;
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
/** Digs a bowl; the returned id undoes just this crater via `removeEdit` (#284.7). */
|
|
103
|
+
carve(op: CraterOp): number;
|
|
104
|
+
/** Raises a mound; the returned id undoes just this mound via `removeEdit` (#284.7). */
|
|
105
|
+
deposit(op: MoundOp): number;
|
|
106
|
+
/** Removes one edit by the id `carve`/`deposit` returned — capped-history destructibles evict without rebuilding the field. */
|
|
107
|
+
removeEdit(editId: number): boolean;
|
|
103
108
|
clear(): void;
|
|
104
109
|
}
|
|
105
110
|
export declare function carvableTerrain(base: TerrainField): CarvableField;
|
package/dist/world/carve.js
CHANGED
|
@@ -135,7 +135,8 @@ export class CarvableField {
|
|
|
135
135
|
waterLevel;
|
|
136
136
|
sampleNormal;
|
|
137
137
|
base;
|
|
138
|
-
edits =
|
|
138
|
+
edits = new Map();
|
|
139
|
+
nextEditId = 1;
|
|
139
140
|
constructor(base) {
|
|
140
141
|
this.base = base;
|
|
141
142
|
if (base.bounds !== undefined)
|
|
@@ -145,12 +146,11 @@ export class CarvableField {
|
|
|
145
146
|
this.sampleNormal = withNormal((x, z) => this.sampleHeight(x, z));
|
|
146
147
|
}
|
|
147
148
|
get editCount() {
|
|
148
|
-
return this.edits.
|
|
149
|
+
return this.edits.size;
|
|
149
150
|
}
|
|
150
151
|
sampleHeight(x, z) {
|
|
151
152
|
let h = this.base.sampleHeight(x, z);
|
|
152
|
-
for (
|
|
153
|
-
const e = this.edits[i];
|
|
153
|
+
for (const e of this.edits.values()) {
|
|
154
154
|
const dx = x - e.x;
|
|
155
155
|
const dz = z - e.z;
|
|
156
156
|
const d = Math.sqrt(dx * dx + dz * dz);
|
|
@@ -160,14 +160,24 @@ export class CarvableField {
|
|
|
160
160
|
}
|
|
161
161
|
return h;
|
|
162
162
|
}
|
|
163
|
+
/** Digs a bowl; the returned id undoes just this crater via `removeEdit` (#284.7). */
|
|
163
164
|
carve(op) {
|
|
164
|
-
|
|
165
|
+
const id = this.nextEditId++;
|
|
166
|
+
this.edits.set(id, { x: op.x, z: op.z, radius: op.radius, delta: -op.depth });
|
|
167
|
+
return id;
|
|
165
168
|
}
|
|
169
|
+
/** Raises a mound; the returned id undoes just this mound via `removeEdit` (#284.7). */
|
|
166
170
|
deposit(op) {
|
|
167
|
-
|
|
171
|
+
const id = this.nextEditId++;
|
|
172
|
+
this.edits.set(id, { x: op.x, z: op.z, radius: op.radius, delta: op.height });
|
|
173
|
+
return id;
|
|
174
|
+
}
|
|
175
|
+
/** Removes one edit by the id `carve`/`deposit` returned — capped-history destructibles evict without rebuilding the field. */
|
|
176
|
+
removeEdit(editId) {
|
|
177
|
+
return this.edits.delete(editId);
|
|
168
178
|
}
|
|
169
179
|
clear() {
|
|
170
|
-
this.edits.
|
|
180
|
+
this.edits.clear();
|
|
171
181
|
}
|
|
172
182
|
}
|
|
173
183
|
export function carvableTerrain(base) {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export interface CellStateGridConfig<TState extends string> {
|
|
2
|
+
cols: number;
|
|
3
|
+
rows: number;
|
|
4
|
+
/** The ordered escalation ladder; every cell starts at `states[0]`. */
|
|
5
|
+
states: readonly TState[];
|
|
6
|
+
/** World-space center of cell (0, 0), for `cellOf` world→cell mapping. Default `[0, 0]`. */
|
|
7
|
+
origin?: readonly [number, number];
|
|
8
|
+
/** World units per cell, for `cellOf`. Default `1`. */
|
|
9
|
+
cellSize?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface CellRef {
|
|
12
|
+
col: number;
|
|
13
|
+
row: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A uniform world grid whose cells step through a discrete state ladder — pristine → cracked →
|
|
17
|
+
* burning → ruined — driven by whatever world events the game routes in (#284.8). Pure storage plus
|
|
18
|
+
* ladder mechanics; the game decides *when* to escalate, the grid guarantees ordered, clamped steps
|
|
19
|
+
* and cheap queries. `version()` bumps on every change for dirty-checked rendering.
|
|
20
|
+
*/
|
|
21
|
+
export interface CellStateGrid<TState extends string> {
|
|
22
|
+
readonly cols: number;
|
|
23
|
+
readonly rows: number;
|
|
24
|
+
readonly states: readonly TState[];
|
|
25
|
+
stateAt(col: number, row: number): TState | null;
|
|
26
|
+
/** Ladder index at a cell; `-1` outside the grid. */
|
|
27
|
+
indexAt(col: number, row: number): number;
|
|
28
|
+
/** Step a cell up the ladder (clamped at the last state); returns the new state or `null` outside the grid. */
|
|
29
|
+
escalate(col: number, row: number, steps?: number): TState | null;
|
|
30
|
+
/** Step a cell back down (clamped at the first state). */
|
|
31
|
+
regress(col: number, row: number, steps?: number): TState | null;
|
|
32
|
+
set(col: number, row: number, state: TState): boolean;
|
|
33
|
+
/** Escalate every cell the predicate matches; returns how many changed. */
|
|
34
|
+
escalateWhere(predicate: (col: number, row: number, state: TState) => boolean, steps?: number): number;
|
|
35
|
+
cellsIn(state: TState): CellRef[];
|
|
36
|
+
counts(): Record<TState, number>;
|
|
37
|
+
/** World position → cell, using `origin`/`cellSize`; `null` outside the grid. */
|
|
38
|
+
cellOf(x: number, z: number): CellRef | null;
|
|
39
|
+
/** World-space center of a cell. */
|
|
40
|
+
centerOf(col: number, row: number): readonly [number, number];
|
|
41
|
+
/** Bumps on every state change — key re-renders/dirty checks off it. */
|
|
42
|
+
version(): number;
|
|
43
|
+
reset(): void;
|
|
44
|
+
}
|
|
45
|
+
export declare function createCellStateGrid<TState extends string>(config: CellStateGridConfig<TState>): CellStateGrid<TState>;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
export function createCellStateGrid(config) {
|
|
2
|
+
if (config.states.length === 0)
|
|
3
|
+
throw new Error("cell state grid needs at least one state");
|
|
4
|
+
if (!(config.cols > 0) || !(config.rows > 0)) {
|
|
5
|
+
throw new Error(`cell state grid needs positive dimensions, got ${config.cols}x${config.rows}`);
|
|
6
|
+
}
|
|
7
|
+
const stateIndex = new Map();
|
|
8
|
+
config.states.forEach((state, index) => {
|
|
9
|
+
if (stateIndex.has(state))
|
|
10
|
+
throw new Error(`duplicate cell state: ${state}`);
|
|
11
|
+
stateIndex.set(state, index);
|
|
12
|
+
});
|
|
13
|
+
const [originX, originZ] = config.origin ?? [0, 0];
|
|
14
|
+
const cellSize = config.cellSize ?? 1;
|
|
15
|
+
const cells = new Int32Array(config.cols * config.rows);
|
|
16
|
+
let version = 0;
|
|
17
|
+
function inBounds(col, row) {
|
|
18
|
+
return Number.isInteger(col) && Number.isInteger(row) && col >= 0 && col < config.cols && row >= 0 && row < config.rows;
|
|
19
|
+
}
|
|
20
|
+
function indexOf(col, row) {
|
|
21
|
+
return row * config.cols + col;
|
|
22
|
+
}
|
|
23
|
+
function step(col, row, steps) {
|
|
24
|
+
if (!inBounds(col, row))
|
|
25
|
+
return null;
|
|
26
|
+
const at = indexOf(col, row);
|
|
27
|
+
const next = Math.max(0, Math.min(config.states.length - 1, cells[at] + steps));
|
|
28
|
+
if (next !== cells[at]) {
|
|
29
|
+
cells[at] = next;
|
|
30
|
+
version += 1;
|
|
31
|
+
}
|
|
32
|
+
return config.states[next];
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
cols: config.cols,
|
|
36
|
+
rows: config.rows,
|
|
37
|
+
states: config.states,
|
|
38
|
+
stateAt: (col, row) => (inBounds(col, row) ? config.states[cells[indexOf(col, row)]] : null),
|
|
39
|
+
indexAt: (col, row) => (inBounds(col, row) ? cells[indexOf(col, row)] : -1),
|
|
40
|
+
escalate: (col, row, steps = 1) => step(col, row, Math.max(0, steps)),
|
|
41
|
+
regress: (col, row, steps = 1) => step(col, row, -Math.max(0, steps)),
|
|
42
|
+
set(col, row, state) {
|
|
43
|
+
const target = stateIndex.get(state);
|
|
44
|
+
if (target === undefined || !inBounds(col, row))
|
|
45
|
+
return false;
|
|
46
|
+
const at = indexOf(col, row);
|
|
47
|
+
if (cells[at] !== target) {
|
|
48
|
+
cells[at] = target;
|
|
49
|
+
version += 1;
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
},
|
|
53
|
+
escalateWhere(predicate, steps = 1) {
|
|
54
|
+
let changed = 0;
|
|
55
|
+
for (let row = 0; row < config.rows; row += 1) {
|
|
56
|
+
for (let col = 0; col < config.cols; col += 1) {
|
|
57
|
+
const at = indexOf(col, row);
|
|
58
|
+
if (!predicate(col, row, config.states[cells[at]]))
|
|
59
|
+
continue;
|
|
60
|
+
const next = Math.min(config.states.length - 1, cells[at] + Math.max(0, steps));
|
|
61
|
+
if (next !== cells[at]) {
|
|
62
|
+
cells[at] = next;
|
|
63
|
+
changed += 1;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (changed > 0)
|
|
68
|
+
version += 1;
|
|
69
|
+
return changed;
|
|
70
|
+
},
|
|
71
|
+
cellsIn(state) {
|
|
72
|
+
const target = stateIndex.get(state);
|
|
73
|
+
const refs = [];
|
|
74
|
+
if (target === undefined)
|
|
75
|
+
return refs;
|
|
76
|
+
for (let row = 0; row < config.rows; row += 1) {
|
|
77
|
+
for (let col = 0; col < config.cols; col += 1) {
|
|
78
|
+
if (cells[indexOf(col, row)] === target)
|
|
79
|
+
refs.push({ col, row });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return refs;
|
|
83
|
+
},
|
|
84
|
+
counts() {
|
|
85
|
+
const result = Object.fromEntries(config.states.map((state) => [state, 0]));
|
|
86
|
+
for (let at = 0; at < cells.length; at += 1) {
|
|
87
|
+
result[config.states[cells[at]]] += 1;
|
|
88
|
+
}
|
|
89
|
+
return result;
|
|
90
|
+
},
|
|
91
|
+
cellOf(x, z) {
|
|
92
|
+
const col = Math.round((x - originX) / cellSize);
|
|
93
|
+
const row = Math.round((z - originZ) / cellSize);
|
|
94
|
+
return inBounds(col, row) ? { col, row } : null;
|
|
95
|
+
},
|
|
96
|
+
centerOf: (col, row) => [originX + col * cellSize, originZ + row * cellSize],
|
|
97
|
+
version: () => version,
|
|
98
|
+
reset() {
|
|
99
|
+
cells.fill(0);
|
|
100
|
+
version += 1;
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { type GeneratedBuilding } from "./buildings.js";
|
|
1
|
+
import { type BuildingPalette, type BuildingStyle, type GeneratedBuilding } from "./buildings.js";
|
|
2
2
|
import type { BuildingEnvironmentDescriptor, EnvironmentWorldFeature, WorldBounds } from "./features.js";
|
|
3
3
|
import type { Aabb } from "./geometry.js";
|
|
4
|
+
import { type TerrainPalette } from "./terrain.js";
|
|
4
5
|
export declare function resolveStructureBuildings(descriptor: BuildingEnvironmentDescriptor): GeneratedBuilding[];
|
|
5
6
|
export interface TerrainHeightStats {
|
|
6
7
|
min: number;
|
|
@@ -11,10 +12,12 @@ export interface TerrainHeightStats {
|
|
|
11
12
|
export interface TerrainSummary {
|
|
12
13
|
bounds: WorldBounds;
|
|
13
14
|
height: TerrainHeightStats;
|
|
15
|
+
palette: TerrainPalette;
|
|
14
16
|
waterLevel?: number;
|
|
15
17
|
}
|
|
16
18
|
export interface StructureSummary {
|
|
17
|
-
style:
|
|
19
|
+
style: BuildingStyle;
|
|
20
|
+
palette: BuildingPalette;
|
|
18
21
|
requested: number;
|
|
19
22
|
buildings: number;
|
|
20
23
|
parts: number;
|
|
@@ -34,6 +37,7 @@ export interface WeatherSummary {
|
|
|
34
37
|
}
|
|
35
38
|
export interface EnvironmentCounts {
|
|
36
39
|
terrain: number;
|
|
40
|
+
islands: number;
|
|
37
41
|
structureGroups: number;
|
|
38
42
|
buildings: number;
|
|
39
43
|
buildingParts: number;
|
|
@@ -41,8 +45,12 @@ export interface EnvironmentCounts {
|
|
|
41
45
|
waterBodies: number;
|
|
42
46
|
weatherSystems: number;
|
|
43
47
|
}
|
|
48
|
+
export interface IslandSummary extends TerrainSummary {
|
|
49
|
+
origin: readonly [number, number];
|
|
50
|
+
}
|
|
44
51
|
export interface EnvironmentSummary {
|
|
45
52
|
terrain?: TerrainSummary;
|
|
53
|
+
islands: readonly IslandSummary[];
|
|
46
54
|
structures: readonly StructureSummary[];
|
|
47
55
|
vegetation: readonly VegetationSummary[];
|
|
48
56
|
water: readonly WaterSummary[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { generateBuildingDistrict } from "./buildings.js";
|
|
2
|
-
import { resolveTerrainField } from "./terrain.js";
|
|
1
|
+
import { generateBuildingDistrict, resolveBuildingPalette, } from "./buildings.js";
|
|
2
|
+
import { resolveTerrainField, resolveTerrainPalette } from "./terrain.js";
|
|
3
3
|
export function resolveStructureBuildings(descriptor) {
|
|
4
4
|
const columns = Math.max(1, Math.ceil(Math.sqrt(descriptor.count)));
|
|
5
5
|
const rows = Math.max(1, Math.ceil(descriptor.count / columns));
|
|
@@ -74,6 +74,7 @@ function summarizeStructures(descriptor) {
|
|
|
74
74
|
const buildings = resolveStructureBuildings(descriptor);
|
|
75
75
|
return {
|
|
76
76
|
style: descriptor.style,
|
|
77
|
+
palette: resolveBuildingPalette(descriptor.style, descriptor.palette),
|
|
77
78
|
requested: descriptor.count,
|
|
78
79
|
buildings: buildings.length,
|
|
79
80
|
parts: buildings.reduce((sum, building) => sum + building.parts.length, 0),
|
|
@@ -84,11 +85,16 @@ function summarizeTerrain(descriptor) {
|
|
|
84
85
|
return {
|
|
85
86
|
bounds: descriptor.bounds,
|
|
86
87
|
height: sampleTerrainHeights(descriptor),
|
|
88
|
+
palette: resolveTerrainPalette(descriptor),
|
|
87
89
|
...(descriptor.waterLevel === undefined ? {} : { waterLevel: descriptor.waterLevel }),
|
|
88
90
|
};
|
|
89
91
|
}
|
|
90
92
|
export function summarizeEnvironment(feature) {
|
|
91
93
|
const terrain = feature.terrain === undefined ? undefined : summarizeTerrain(feature.terrain);
|
|
94
|
+
const islands = (feature.islands ?? []).map((entry) => ({
|
|
95
|
+
...summarizeTerrain({ ...entry, kind: "terrain" }),
|
|
96
|
+
origin: entry.origin,
|
|
97
|
+
}));
|
|
92
98
|
const structures = (feature.structures ?? []).map(summarizeStructures);
|
|
93
99
|
const vegetation = (feature.vegetation ?? []).map((entry) => ({
|
|
94
100
|
area: entry.area,
|
|
@@ -105,6 +111,7 @@ export function summarizeEnvironment(feature) {
|
|
|
105
111
|
const buildings = structures.reduce((sum, entry) => sum + entry.buildings, 0);
|
|
106
112
|
const counts = {
|
|
107
113
|
terrain: terrain === undefined ? 0 : 1,
|
|
114
|
+
islands: islands.length,
|
|
108
115
|
structureGroups: structures.length,
|
|
109
116
|
buildings,
|
|
110
117
|
buildingParts: structures.reduce((sum, entry) => sum + entry.parts, 0),
|
|
@@ -113,12 +120,14 @@ export function summarizeEnvironment(feature) {
|
|
|
113
120
|
weatherSystems: weather.length,
|
|
114
121
|
};
|
|
115
122
|
const isEmpty = counts.terrain === 0 &&
|
|
123
|
+
counts.islands === 0 &&
|
|
116
124
|
buildings === 0 &&
|
|
117
125
|
counts.vegetationFields === 0 &&
|
|
118
126
|
counts.waterBodies === 0 &&
|
|
119
127
|
counts.weatherSystems === 0;
|
|
120
128
|
return {
|
|
121
129
|
...(terrain === undefined ? {} : { terrain }),
|
|
130
|
+
islands,
|
|
122
131
|
structures,
|
|
123
132
|
vegetation,
|
|
124
133
|
water,
|
package/dist/world/features.d.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import type { BuildingPaletteOverrides, BuildingStyle } from "./buildings.js";
|
|
1
2
|
export interface WorldBounds {
|
|
2
3
|
w: number;
|
|
3
4
|
d: number;
|
|
4
5
|
}
|
|
6
|
+
export type TerrainMaterial = "grass" | "sand" | "snow" | "rock" | "ash" | "highland" | "slate";
|
|
5
7
|
export type EnvironmentVec2 = readonly [number, number];
|
|
6
8
|
export interface EnvironmentArea extends WorldBounds {
|
|
7
9
|
h?: number;
|
|
10
|
+
/** World-space center of the area; default `[0, 0]` (the world origin). Sites a weather/vegetation band away from the origin, like `building()`/`ocean()` `position`. */
|
|
11
|
+
position?: EnvironmentVec2;
|
|
8
12
|
}
|
|
9
13
|
export interface TerrainColors {
|
|
10
14
|
low?: string;
|
|
@@ -19,14 +23,32 @@ export interface TerrainFlattenMask {
|
|
|
19
23
|
/** Extra blend-ring width outside `radius` where the flat height smoothsteps back to the noise value; default `radius * 0.5`. */
|
|
20
24
|
falloff?: number;
|
|
21
25
|
}
|
|
26
|
+
/** A circular palette zone painted over the base terrain palette — snow caps, ash wastes, sand shores on one heightfield. */
|
|
27
|
+
export interface TerrainMaterialRegion {
|
|
28
|
+
center: EnvironmentVec2;
|
|
29
|
+
radius: number;
|
|
30
|
+
/** Named palette preset for this region (see `TERRAIN_MATERIAL_PALETTES` in `world/terrain`); overridden field-by-field by `colors`. */
|
|
31
|
+
material?: TerrainMaterial;
|
|
32
|
+
colors?: TerrainColors;
|
|
33
|
+
/** Blend-ring width outside `radius` back to the surrounding palette; default `radius * 0.5`. */
|
|
34
|
+
falloff?: number;
|
|
35
|
+
}
|
|
22
36
|
export interface TerrainEnvironmentConfig {
|
|
23
37
|
bounds?: WorldBounds;
|
|
24
38
|
height?: number;
|
|
25
39
|
heightMap?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Game-supplied height function replacing the built-in noise field — banded biomes, ridge walls,
|
|
42
|
+
* terracing, anything expressible as `(x, z) => y`. `flatten` masks still carve into it, and both
|
|
43
|
+
* the rendered ground and `ctx.world.ground` sample it. A function doesn't serialize; keep it pure.
|
|
44
|
+
*/
|
|
45
|
+
heightField?: (x: number, z: number) => number;
|
|
26
46
|
/** Named palette preset (see `TERRAIN_MATERIAL_PALETTES` in `world/terrain`); default "grass". Overridden field-by-field by `colors`. */
|
|
27
|
-
material?:
|
|
47
|
+
material?: TerrainMaterial;
|
|
28
48
|
/** Explicit low/high/waterline hex colors; any field left unset falls back to the resolved `material` preset. */
|
|
29
49
|
colors?: TerrainColors;
|
|
50
|
+
/** Palette zones blended over the base `material`/`colors` for multi-biome readability. */
|
|
51
|
+
materialRegions?: readonly TerrainMaterialRegion[];
|
|
30
52
|
segments?: number;
|
|
31
53
|
seed?: string;
|
|
32
54
|
frequency?: number;
|
|
@@ -55,7 +77,7 @@ export interface SnowEnvironmentConfig {
|
|
|
55
77
|
color?: string;
|
|
56
78
|
}
|
|
57
79
|
export interface GrassEnvironmentConfig {
|
|
58
|
-
area?:
|
|
80
|
+
area?: EnvironmentArea;
|
|
59
81
|
density?: number;
|
|
60
82
|
bladeHeight?: readonly [number, number];
|
|
61
83
|
bladeWidth?: number;
|
|
@@ -67,7 +89,15 @@ export interface OceanEnvironmentConfig {
|
|
|
67
89
|
bounds?: WorldBounds;
|
|
68
90
|
position?: EnvironmentVec2;
|
|
69
91
|
level?: number;
|
|
92
|
+
/**
|
|
93
|
+
* Scheduled water level as a function of game-time seconds — tides, floods, draining chambers.
|
|
94
|
+
* Wins over `level` (which stays the initial/static value); `waterSurfaceFromDescriptor` bakes it
|
|
95
|
+
* into `WaterSurface.height`, and the shell repositions the rendered ocean from it every frame.
|
|
96
|
+
* A function doesn't serialize; keep it pure and deterministic (compose with `time/stateSchedule`).
|
|
97
|
+
*/
|
|
98
|
+
levelAt?: (time: number) => number;
|
|
70
99
|
waveHeight?: number;
|
|
100
|
+
/** Primary Gerstner wavelength in world units (shared with shell Ocean `waveScale`; default 18). */
|
|
71
101
|
waveScale?: number;
|
|
72
102
|
waveSpeed?: number;
|
|
73
103
|
color?: string;
|
|
@@ -94,7 +124,10 @@ export interface BuildingEnvironmentConfig {
|
|
|
94
124
|
stories?: readonly [number, number];
|
|
95
125
|
storyHeight?: number;
|
|
96
126
|
spacing?: number;
|
|
97
|
-
|
|
127
|
+
/** Named palette archetype (see `BUILDING_STYLE_PALETTES` in `world/buildings`); default "generic". Overridden part-by-part by `palette`. */
|
|
128
|
+
style?: BuildingStyle;
|
|
129
|
+
/** Explicit per-part-kind hex colors; any part left unset falls back to the resolved `style` palette. */
|
|
130
|
+
palette?: BuildingPaletteOverrides;
|
|
98
131
|
seed?: string;
|
|
99
132
|
}
|
|
100
133
|
export type PadSize = readonly [number, number] | {
|
|
@@ -103,8 +136,10 @@ export type PadSize = readonly [number, number] | {
|
|
|
103
136
|
export interface PadEnvironmentConfig {
|
|
104
137
|
center: EnvironmentVec2;
|
|
105
138
|
size: PadSize;
|
|
106
|
-
/** Surface offset above the terrain height at `center`; default `0.05` — just proud of the ground. */
|
|
139
|
+
/** Surface offset above the terrain height at `center`; default `0.05` — just proud of the ground. Ignored when `elevation` is set. */
|
|
107
140
|
height?: number;
|
|
141
|
+
/** Absolute world-space Y for the pad surface — a landing pad on a rooftop, a floating platform. Skips the implicit terrain flatten (there's no ground to flatten toward). */
|
|
142
|
+
elevation?: number;
|
|
108
143
|
color?: string;
|
|
109
144
|
/** Rotation applied to rectangular pads; ignored for circular pads. */
|
|
110
145
|
rotationY?: number;
|
|
@@ -112,6 +147,15 @@ export interface PadEnvironmentConfig {
|
|
|
112
147
|
export type TerrainEnvironmentDescriptor = {
|
|
113
148
|
kind: "terrain";
|
|
114
149
|
} & Required<Pick<TerrainEnvironmentConfig, "bounds" | "height">> & Omit<TerrainEnvironmentConfig, "bounds" | "height">;
|
|
150
|
+
/** A bounded terrain patch floating at its own altitude — sky islands, arena platforms, split landmasses with void between. */
|
|
151
|
+
export interface TerrainIslandConfig extends TerrainEnvironmentConfig {
|
|
152
|
+
/** World-space center of the island; its `bounds` rect surrounds this point. */
|
|
153
|
+
origin: EnvironmentVec2;
|
|
154
|
+
}
|
|
155
|
+
export type TerrainIslandDescriptor = Omit<TerrainEnvironmentDescriptor, "kind"> & {
|
|
156
|
+
kind: "island";
|
|
157
|
+
origin: EnvironmentVec2;
|
|
158
|
+
};
|
|
115
159
|
export type RainEnvironmentDescriptor = {
|
|
116
160
|
kind: "rain";
|
|
117
161
|
} & Required<Pick<RainEnvironmentConfig, "area" | "density" | "speed" | "dropLength" | "wind" | "color">>;
|
|
@@ -123,13 +167,13 @@ export type GrassEnvironmentDescriptor = {
|
|
|
123
167
|
} & Required<Pick<GrassEnvironmentConfig, "area" | "density" | "bladeHeight" | "bladeWidth" | "windStrength" | "colors">> & Pick<GrassEnvironmentConfig, "seed">;
|
|
124
168
|
export type OceanEnvironmentDescriptor = {
|
|
125
169
|
kind: "ocean";
|
|
126
|
-
} & Required<Pick<OceanEnvironmentConfig, "bounds" | "level" | "waveHeight" | "waveScale" | "waveSpeed" | "color">> & Pick<OceanEnvironmentConfig, "position">;
|
|
170
|
+
} & Required<Pick<OceanEnvironmentConfig, "bounds" | "level" | "waveHeight" | "waveScale" | "waveSpeed" | "color">> & Pick<OceanEnvironmentConfig, "position" | "levelAt">;
|
|
127
171
|
export type BuildingEnvironmentDescriptor = {
|
|
128
172
|
kind: "building";
|
|
129
|
-
} & Required<Pick<BuildingEnvironmentConfig, "count" | "footprint" | "stories" | "storyHeight" | "spacing" | "style">> & Pick<BuildingEnvironmentConfig, "seed" | "position">;
|
|
173
|
+
} & Required<Pick<BuildingEnvironmentConfig, "count" | "footprint" | "stories" | "storyHeight" | "spacing" | "style">> & Pick<BuildingEnvironmentConfig, "seed" | "position" | "palette">;
|
|
130
174
|
export type PadEnvironmentDescriptor = {
|
|
131
175
|
kind: "pad";
|
|
132
|
-
} & Required<Pick<PadEnvironmentConfig, "center" | "size" | "height" | "color">> & Pick<PadEnvironmentConfig, "rotationY">;
|
|
176
|
+
} & Required<Pick<PadEnvironmentConfig, "center" | "size" | "height" | "color">> & Pick<PadEnvironmentConfig, "rotationY" | "elevation">;
|
|
133
177
|
export type SkyEnvironmentDescriptor = {
|
|
134
178
|
kind: "sky";
|
|
135
179
|
} & Required<Pick<SkyEnvironmentConfig, "preset" | "timeOfDay">> & Omit<SkyEnvironmentConfig, "preset" | "timeOfDay">;
|
|
@@ -140,6 +184,8 @@ export type StructureEnvironmentDescriptor = BuildingEnvironmentDescriptor;
|
|
|
140
184
|
export type EnvironmentDescriptorList<T> = T | readonly T[];
|
|
141
185
|
export interface EnvironmentWorldConfig {
|
|
142
186
|
terrain?: TerrainEnvironmentDescriptor;
|
|
187
|
+
/** Disconnected landmasses at independent altitudes over the base `terrain` (or over void without one) — see `island()`. */
|
|
188
|
+
islands?: readonly TerrainIslandDescriptor[];
|
|
143
189
|
sky?: SkyEnvironmentDescriptor;
|
|
144
190
|
weather?: EnvironmentDescriptorList<WeatherEnvironmentDescriptor>;
|
|
145
191
|
vegetation?: EnvironmentDescriptorList<VegetationEnvironmentDescriptor>;
|
|
@@ -151,6 +197,7 @@ export interface EnvironmentWorldConfig {
|
|
|
151
197
|
export interface EnvironmentWorldFeature {
|
|
152
198
|
kind: "environment";
|
|
153
199
|
terrain?: TerrainEnvironmentDescriptor;
|
|
200
|
+
islands?: readonly TerrainIslandDescriptor[];
|
|
154
201
|
sky?: SkyEnvironmentDescriptor;
|
|
155
202
|
weather?: readonly WeatherEnvironmentDescriptor[];
|
|
156
203
|
vegetation?: readonly VegetationEnvironmentDescriptor[];
|
|
@@ -206,7 +253,7 @@ export type WorldFeature = ({
|
|
|
206
253
|
} & TilemapWorldConfig) | EnvironmentWorldFeature | {
|
|
207
254
|
kind: "flat";
|
|
208
255
|
};
|
|
209
|
-
/** Derives implicit `TerrainFlattenMask`s carving each pad's footprint into the terrain beneath it. */
|
|
256
|
+
/** Derives implicit `TerrainFlattenMask`s carving each pad's footprint into the terrain beneath it. Elevated pads (absolute `elevation`) float free and carve nothing. */
|
|
210
257
|
export declare function padFlattenMasks(pads: readonly PadEnvironmentDescriptor[]): readonly TerrainFlattenMask[];
|
|
211
258
|
export declare function environment(config?: EnvironmentWorldConfig): EnvironmentWorldFeature;
|
|
212
259
|
export declare function terrain(config?: TerrainEnvironmentConfig): TerrainEnvironmentDescriptor;
|
|
@@ -215,6 +262,7 @@ export declare function rain(config?: RainEnvironmentConfig): RainEnvironmentDes
|
|
|
215
262
|
export declare function snow(config?: SnowEnvironmentConfig): SnowEnvironmentDescriptor;
|
|
216
263
|
export declare function grass(config?: GrassEnvironmentConfig): GrassEnvironmentDescriptor;
|
|
217
264
|
export declare function ocean(config?: OceanEnvironmentConfig): OceanEnvironmentDescriptor;
|
|
265
|
+
export declare function island(config: TerrainIslandConfig): TerrainIslandDescriptor;
|
|
218
266
|
export declare function building(config?: BuildingEnvironmentConfig): BuildingEnvironmentDescriptor;
|
|
219
267
|
export declare function pad(config: PadEnvironmentConfig): PadEnvironmentDescriptor;
|
|
220
268
|
export declare function biomes(config: BiomesWorldConfig): WorldFeature;
|