@bitmagic/world-forger 0.1.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/dist/artifact-types.d.ts +295 -0
- package/dist/artifact-types.d.ts.map +1 -0
- package/dist/artifact-types.js +17 -0
- package/dist/artifact-types.js.map +1 -0
- package/dist/forge-constants.d.ts +106 -0
- package/dist/forge-constants.d.ts.map +1 -0
- package/dist/forge-constants.js +111 -0
- package/dist/forge-constants.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/log.d.ts +26 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +14 -0
- package/dist/log.js.map +1 -0
- package/dist/pipeline/archetype-skips.d.ts +57 -0
- package/dist/pipeline/archetype-skips.d.ts.map +1 -0
- package/dist/pipeline/archetype-skips.js +51 -0
- package/dist/pipeline/archetype-skips.js.map +1 -0
- package/dist/pipeline/artifact-store.d.ts +4 -0
- package/dist/pipeline/artifact-store.d.ts.map +1 -0
- package/dist/pipeline/artifact-store.js +10 -0
- package/dist/pipeline/artifact-store.js.map +1 -0
- package/dist/pipeline/asset-catalog.d.ts +27 -0
- package/dist/pipeline/asset-catalog.d.ts.map +1 -0
- package/dist/pipeline/asset-catalog.js +47 -0
- package/dist/pipeline/asset-catalog.js.map +1 -0
- package/dist/pipeline/create-level-archetypes.d.ts +45 -0
- package/dist/pipeline/create-level-archetypes.d.ts.map +1 -0
- package/dist/pipeline/create-level-archetypes.js +197 -0
- package/dist/pipeline/create-level-archetypes.js.map +1 -0
- package/dist/pipeline/deps.d.ts +72 -0
- package/dist/pipeline/deps.d.ts.map +1 -0
- package/dist/pipeline/deps.js +2 -0
- package/dist/pipeline/deps.js.map +1 -0
- package/dist/pipeline/errors.d.ts +10 -0
- package/dist/pipeline/errors.d.ts.map +1 -0
- package/dist/pipeline/errors.js +13 -0
- package/dist/pipeline/errors.js.map +1 -0
- package/dist/pipeline/forged-work-store.d.ts +46 -0
- package/dist/pipeline/forged-work-store.d.ts.map +1 -0
- package/dist/pipeline/forged-work-store.js +69 -0
- package/dist/pipeline/forged-work-store.js.map +1 -0
- package/dist/pipeline/index.d.ts +36 -0
- package/dist/pipeline/index.d.ts.map +1 -0
- package/dist/pipeline/index.js +36 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/job-types.d.ts +145 -0
- package/dist/pipeline/job-types.d.ts.map +1 -0
- package/dist/pipeline/job-types.js +2 -0
- package/dist/pipeline/job-types.js.map +1 -0
- package/dist/pipeline/level-registry.d.ts +57 -0
- package/dist/pipeline/level-registry.d.ts.map +1 -0
- package/dist/pipeline/level-registry.js +108 -0
- package/dist/pipeline/level-registry.js.map +1 -0
- package/dist/pipeline/model-types.d.ts +51 -0
- package/dist/pipeline/model-types.d.ts.map +1 -0
- package/dist/pipeline/model-types.js +2 -0
- package/dist/pipeline/model-types.js.map +1 -0
- package/dist/pipeline/persist-level.d.ts +82 -0
- package/dist/pipeline/persist-level.d.ts.map +1 -0
- package/dist/pipeline/persist-level.js +201 -0
- package/dist/pipeline/persist-level.js.map +1 -0
- package/dist/pipeline/place-and-persist-level.d.ts +83 -0
- package/dist/pipeline/place-and-persist-level.d.ts.map +1 -0
- package/dist/pipeline/place-and-persist-level.js +405 -0
- package/dist/pipeline/place-and-persist-level.js.map +1 -0
- package/dist/pipeline/request-id.d.ts +7 -0
- package/dist/pipeline/request-id.d.ts.map +1 -0
- package/dist/pipeline/request-id.js +10 -0
- package/dist/pipeline/request-id.js.map +1 -0
- package/dist/pipeline/spawn-points.d.ts +47 -0
- package/dist/pipeline/spawn-points.d.ts.map +1 -0
- package/dist/pipeline/spawn-points.js +100 -0
- package/dist/pipeline/spawn-points.js.map +1 -0
- package/dist/pipeline/starter-scatter.d.ts +34 -0
- package/dist/pipeline/starter-scatter.d.ts.map +1 -0
- package/dist/pipeline/starter-scatter.js +49 -0
- package/dist/pipeline/starter-scatter.js.map +1 -0
- package/dist/pipeline/storage-types.d.ts +48 -0
- package/dist/pipeline/storage-types.d.ts.map +1 -0
- package/dist/pipeline/storage-types.js +19 -0
- package/dist/pipeline/storage-types.js.map +1 -0
- package/dist/pipeline/transport-types.d.ts +35 -0
- package/dist/pipeline/transport-types.d.ts.map +1 -0
- package/dist/pipeline/transport-types.js +2 -0
- package/dist/pipeline/transport-types.js.map +1 -0
- package/dist/pipeline/voxelize-level.d.ts +24 -0
- package/dist/pipeline/voxelize-level.d.ts.map +1 -0
- package/dist/pipeline/voxelize-level.js +63 -0
- package/dist/pipeline/voxelize-level.js.map +1 -0
- package/dist/pipeline/world-json-source.d.ts +78 -0
- package/dist/pipeline/world-json-source.d.ts.map +1 -0
- package/dist/pipeline/world-json-source.js +2 -0
- package/dist/pipeline/world-json-source.js.map +1 -0
- package/dist/pipeline/world-json-types.d.ts +104 -0
- package/dist/pipeline/world-json-types.d.ts.map +1 -0
- package/dist/pipeline/world-json-types.js +15 -0
- package/dist/pipeline/world-json-types.js.map +1 -0
- package/dist/terrain-height-grid.d.ts +45 -0
- package/dist/terrain-height-grid.d.ts.map +1 -0
- package/dist/terrain-height-grid.js +50 -0
- package/dist/terrain-height-grid.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The forged-artifact SCHEMA — the data shapes that cross from the private
|
|
3
|
+
* design/geometry half of the forger into the publishable half that drives the
|
|
4
|
+
* browser (archetype bakes, the level bake, instance placement and persist).
|
|
5
|
+
*
|
|
6
|
+
* These are declarations, not algorithms: a client that consumes a forge
|
|
7
|
+
* artifact at all has to know its shape, so the schema is public and the code
|
|
8
|
+
* that produces it is not. Each type is DEFINED here and re-exported from the
|
|
9
|
+
* module it used to live in (`forge-world.ts`, `derive-settings.ts`,
|
|
10
|
+
* `dungeon/dressing.ts`, `course.ts`, `dungeon/fixture-parts.ts`), so there is
|
|
11
|
+
* still exactly one definition of each and every historic import site keeps
|
|
12
|
+
* working.
|
|
13
|
+
*
|
|
14
|
+
* This file imports nothing.
|
|
15
|
+
*/
|
|
16
|
+
export interface WorldMarker {
|
|
17
|
+
name: string;
|
|
18
|
+
/** Position in GLB/spec space (origin at level center). */
|
|
19
|
+
glb: {
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
z: number;
|
|
23
|
+
};
|
|
24
|
+
/** Position in baked world space (world min corner is the origin). */
|
|
25
|
+
world: {
|
|
26
|
+
x: number;
|
|
27
|
+
y: number;
|
|
28
|
+
z: number;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export interface ForgedPlacement {
|
|
32
|
+
archetype: string;
|
|
33
|
+
/** WORLD-space position (object origin / base on the ground). */
|
|
34
|
+
position: {
|
|
35
|
+
x: number;
|
|
36
|
+
y: number;
|
|
37
|
+
z: number;
|
|
38
|
+
};
|
|
39
|
+
rotationYDeg: number;
|
|
40
|
+
scale: number;
|
|
41
|
+
/** Per-axis scale (overrides uniform `scale` when present); city buildings. */
|
|
42
|
+
scaleXYZ?: {
|
|
43
|
+
x: number;
|
|
44
|
+
y: number;
|
|
45
|
+
z: number;
|
|
46
|
+
};
|
|
47
|
+
collision: boolean;
|
|
48
|
+
/** Loose prop: placed as an individual dynamic rigid body that settles under
|
|
49
|
+
* gravity and sleeps until pushed (wrecks, barrels) — not a static batch. */
|
|
50
|
+
dynamic?: boolean;
|
|
51
|
+
/** Authored mass in kg for `dynamic` placements (omitted → engine estimate). */
|
|
52
|
+
mass?: number;
|
|
53
|
+
}
|
|
54
|
+
/** How an object's geometry collides in the bake. */
|
|
55
|
+
export type ColliderKind = 'trimesh' | 'voxel' | 'none';
|
|
56
|
+
/** One line of the forge's object report (the summary the caller reads). */
|
|
57
|
+
export interface ForgedObjectSummary {
|
|
58
|
+
name: string;
|
|
59
|
+
kind: 'level' | 'asset';
|
|
60
|
+
triangles: number;
|
|
61
|
+
instances?: number;
|
|
62
|
+
smooth: boolean;
|
|
63
|
+
collider: ColliderKind;
|
|
64
|
+
}
|
|
65
|
+
/** A terrain LOD band the forger chose (node name -> lodOffset), for reporting. */
|
|
66
|
+
export interface ForgedTerrainBand {
|
|
67
|
+
name: string;
|
|
68
|
+
lodOffset: number;
|
|
69
|
+
}
|
|
70
|
+
export interface CoursePoint {
|
|
71
|
+
x: number;
|
|
72
|
+
y: number;
|
|
73
|
+
z: number;
|
|
74
|
+
}
|
|
75
|
+
export interface CourseCheckpoint extends CoursePoint {
|
|
76
|
+
/** Arc-length fraction along the course (0 = start, 1 = finish/lap). */
|
|
77
|
+
t: number;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* A declared runtime behavior (ski lift, elevator, door) with its anchors
|
|
81
|
+
* resolved to world coordinates — the handoff the game's coding agent
|
|
82
|
+
* implements with engine systems. The level bakes geometry; features carry
|
|
83
|
+
* the intent the geometry alone cannot.
|
|
84
|
+
*/
|
|
85
|
+
export interface ResolvedFeature {
|
|
86
|
+
kind: string;
|
|
87
|
+
name: string;
|
|
88
|
+
description: string;
|
|
89
|
+
/** Single-point anchors: props, markers and structures — one entry each. */
|
|
90
|
+
anchors: Array<{
|
|
91
|
+
name: string;
|
|
92
|
+
x: number;
|
|
93
|
+
y: number;
|
|
94
|
+
z: number;
|
|
95
|
+
}>;
|
|
96
|
+
/**
|
|
97
|
+
* Instanced sets this feature is about — a scatter archetype ("CoconutPalms")
|
|
98
|
+
* or a city building type, where the intent is EVERY instance, not one of them.
|
|
99
|
+
*
|
|
100
|
+
* Per-instance positions are deliberately NOT inlined. A real level places up
|
|
101
|
+
* to ~640 instances of a single archetype, and these features are rendered
|
|
102
|
+
* verbatim into the coding agent's prompt AND persisted into world.json — so
|
|
103
|
+
* inlining would make both scale with instance count. The positions are already
|
|
104
|
+
* reachable: resolve `name` → `asset_id` through `library_assets`, then read
|
|
105
|
+
* world.json `environmentObjects`. This payload stays O(archetypes).
|
|
106
|
+
*/
|
|
107
|
+
archetypeAnchors?: Array<{
|
|
108
|
+
name: string;
|
|
109
|
+
instances: number;
|
|
110
|
+
centroid: {
|
|
111
|
+
x: number;
|
|
112
|
+
y: number;
|
|
113
|
+
z: number;
|
|
114
|
+
};
|
|
115
|
+
}>;
|
|
116
|
+
points: Array<{
|
|
117
|
+
x: number;
|
|
118
|
+
y: number;
|
|
119
|
+
z: number;
|
|
120
|
+
}>;
|
|
121
|
+
/** Open structured parameters carried verbatim to the game's coding agent (e.g. lock id,
|
|
122
|
+
* timing, spawn-candidate metadata). `points` are world-resolved; `params` is opaque. */
|
|
123
|
+
params?: Record<string, unknown>;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Auto-emitted for every designed path: the level's intended flow as ordered
|
|
127
|
+
* world-space control points (dense through sharp turns, at most ~8 m apart
|
|
128
|
+
* on straights) with start/finish/checkpoints. The designed path is
|
|
129
|
+
* authoritative intent — game code should consume this rather than derive a
|
|
130
|
+
* line from the baked surface (which is lossy and closed-loop-only).
|
|
131
|
+
*/
|
|
132
|
+
export interface ResolvedPathFeature extends ResolvedFeature {
|
|
133
|
+
kind: 'path';
|
|
134
|
+
/** Ribbon width in meters (world space). */
|
|
135
|
+
widthM: number;
|
|
136
|
+
/** True for circuits: the last point connects back to the first. */
|
|
137
|
+
closed: boolean;
|
|
138
|
+
/** 3D arc length of the control polyline (m). */
|
|
139
|
+
lengthM: number;
|
|
140
|
+
/** First control point — the intended start of travel. */
|
|
141
|
+
start: CoursePoint;
|
|
142
|
+
/** Last control point (the lap point itself for closed circuits). */
|
|
143
|
+
finish: CoursePoint;
|
|
144
|
+
/** Evenly spaced by arc length, strictly between start and finish. */
|
|
145
|
+
checkpoints: CourseCheckpoint[];
|
|
146
|
+
/** Ribbon node name when its surface is queryable via the named-trimesh API. */
|
|
147
|
+
surfaceObjectName?: string;
|
|
148
|
+
}
|
|
149
|
+
/** Mirror of the engine handler's `options` payload. */
|
|
150
|
+
export interface LevelVoxelizeOptions {
|
|
151
|
+
levelSizeX: number;
|
|
152
|
+
levelSizeZ: number;
|
|
153
|
+
/**
|
|
154
|
+
* NEVER set by the forger. A present `levelSizeY` switches the engine's
|
|
155
|
+
* `applyLevelSizeTransform` to a NON-uniform Y scale, while
|
|
156
|
+
* `marker-transform.ts` — the agent-side mirror every marker, door, key,
|
|
157
|
+
* spawn, water and nav Y is mapped through — assumes the uniform scale. The
|
|
158
|
+
* engine's `worldExtentY` already auto-sizes the level box from geometry,
|
|
159
|
+
* which is what a dungeon hanging under the terrain plate needs.
|
|
160
|
+
*/
|
|
161
|
+
levelSizeY?: number;
|
|
162
|
+
chunkSize: number;
|
|
163
|
+
minVoxelSize: number;
|
|
164
|
+
maxVoxelSize: number;
|
|
165
|
+
fillInterior: boolean;
|
|
166
|
+
additionalLods?: Array<{
|
|
167
|
+
minVoxelSize: number;
|
|
168
|
+
maxVoxelSize: number;
|
|
169
|
+
distance?: number;
|
|
170
|
+
}>;
|
|
171
|
+
objectLodOffsets?: Record<string, number>;
|
|
172
|
+
objectLodPins?: Record<string, true>;
|
|
173
|
+
objectTrimeshColliders?: Record<string, true>;
|
|
174
|
+
objectNoColliders?: Record<string, true>;
|
|
175
|
+
objectCollisionOnlyNodes?: Record<string, true>;
|
|
176
|
+
objectDisplacementAxes?: Record<string, 'x' | 'y' | 'z'>;
|
|
177
|
+
/**
|
|
178
|
+
* Objects EXCLUDED from the level bake — they are library-asset instance
|
|
179
|
+
* groups (tagged in the GLB) placed as environment objects instead.
|
|
180
|
+
*/
|
|
181
|
+
objectAssetInstances?: Record<string, true>;
|
|
182
|
+
/**
|
|
183
|
+
* Per-object GROUND TYPE names (see the engine's `vxlscene/GroundTypes.ts`
|
|
184
|
+
* registry, mirrored in `city/ground-style.ts`). The bake rasterizes the
|
|
185
|
+
* tagged nodes' triangles into the level's ground mask, which drives the
|
|
186
|
+
* runtime cobble domes and grass ground cover.
|
|
187
|
+
*/
|
|
188
|
+
objectGroundTypes?: Record<string, string>;
|
|
189
|
+
/**
|
|
190
|
+
* Authored `#RRGGBB` → emissive strength (16..255). The bake matches these
|
|
191
|
+
* against the palette colors it actually produces and writes the matching
|
|
192
|
+
* cells into the level's emissive block, so glowing runes, lava seams and
|
|
193
|
+
* crystal veins light up at zero light-budget cost. Dungeon palettes are the
|
|
194
|
+
* only producer today.
|
|
195
|
+
*/
|
|
196
|
+
emissiveByColor?: Record<string, number>;
|
|
197
|
+
}
|
|
198
|
+
export type DoorAnimation = 'hinge' | 'slide' | 'dissolve';
|
|
199
|
+
export interface DungeonLightConfig {
|
|
200
|
+
color: string;
|
|
201
|
+
intensity: number;
|
|
202
|
+
distance: number;
|
|
203
|
+
flicker: boolean;
|
|
204
|
+
offset?: {
|
|
205
|
+
x: number;
|
|
206
|
+
y: number;
|
|
207
|
+
z: number;
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Spec-space mirrors of `DoorDefinition` / `KeyItemDefinition` in
|
|
212
|
+
* `game/src/types/game.ts`, minus the fields the PIPELINE owns: `levelId`
|
|
213
|
+
* (assigned at persist) and `assetId` (assigned once the archetype is baked).
|
|
214
|
+
* Mirrored rather than imported — the agent project does not compile the game
|
|
215
|
+
* project's sources — so any field added there must be added here too.
|
|
216
|
+
*/
|
|
217
|
+
export interface DungeonDoorDef {
|
|
218
|
+
id: string;
|
|
219
|
+
/** Closed-pose CENTRE of the leaf. */
|
|
220
|
+
position: {
|
|
221
|
+
x: number;
|
|
222
|
+
y: number;
|
|
223
|
+
z: number;
|
|
224
|
+
};
|
|
225
|
+
/** Yaw in RADIANS. Door-local X is the width, Z the thickness. */
|
|
226
|
+
rotationY: number;
|
|
227
|
+
width: number;
|
|
228
|
+
height: number;
|
|
229
|
+
thickness: number;
|
|
230
|
+
kind: 'plain' | 'locked';
|
|
231
|
+
keyId?: string;
|
|
232
|
+
animation: DoorAnimation;
|
|
233
|
+
/** Explicit for forged hinge doors; the engine retains 100° when omitted. */
|
|
234
|
+
maxOpenAngleDeg?: number;
|
|
235
|
+
/** Fallback box-leaf tint used until an asset is wired. */
|
|
236
|
+
color?: string;
|
|
237
|
+
autoOpenRadius?: number;
|
|
238
|
+
}
|
|
239
|
+
export interface DungeonKeyItemDef {
|
|
240
|
+
id: string;
|
|
241
|
+
keyId: string;
|
|
242
|
+
name: string;
|
|
243
|
+
position: {
|
|
244
|
+
x: number;
|
|
245
|
+
y: number;
|
|
246
|
+
z: number;
|
|
247
|
+
};
|
|
248
|
+
color?: string;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* A NARROWED view of the designed scene spec (`scene-spec.ts`'s
|
|
252
|
+
* `WorldSceneSpec`, which stays private): exactly the fields the persist step
|
|
253
|
+
* reads, plus the identity it echoes back in the summary. The full validated
|
|
254
|
+
* spec is what actually travels — it is written verbatim onto the level asset
|
|
255
|
+
* record as `worldForgerSpec` — this type just declares the part any consumer
|
|
256
|
+
* of a forge artifact is entitled to depend on.
|
|
257
|
+
*
|
|
258
|
+
* Narrowing rather than restating is what keeps it honest: the private
|
|
259
|
+
* `WorldSceneSpec` is widened into this view in ONE place, so a field renamed
|
|
260
|
+
* or dropped over there fails to compile rather than drifting. That check only
|
|
261
|
+
* bites for the REQUIRED fields, though — `dungeon` and `city` are optional
|
|
262
|
+
* here, so renaming either away on the private side would still compile and
|
|
263
|
+
* would silently stop a dungeon getting its atmosphere. The producer therefore
|
|
264
|
+
* names both fields explicitly rather than relying on a bare assignment; see
|
|
265
|
+
* `toForgedSpecView` in the private half's `forge-and-upload-level.ts`.
|
|
266
|
+
*/
|
|
267
|
+
export interface ForgedSpecMaterialView {
|
|
268
|
+
name: string;
|
|
269
|
+
role: string;
|
|
270
|
+
color: string;
|
|
271
|
+
emissive?: {
|
|
272
|
+
strength: number;
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
/** The dungeon plan's palette — all the level atmosphere is derived from. */
|
|
276
|
+
export interface ForgedDungeonView {
|
|
277
|
+
materials: ForgedSpecMaterialView[];
|
|
278
|
+
}
|
|
279
|
+
/** The city plan's zones — the persist step only asks whether any is water. */
|
|
280
|
+
export interface ForgedCityView {
|
|
281
|
+
zones?: Array<{
|
|
282
|
+
kind: string;
|
|
283
|
+
}>;
|
|
284
|
+
}
|
|
285
|
+
export interface ForgedSpecView {
|
|
286
|
+
name: string;
|
|
287
|
+
size: {
|
|
288
|
+
x: number;
|
|
289
|
+
z: number;
|
|
290
|
+
};
|
|
291
|
+
/** Present iff the level is a dungeon (drives spawn clearance + atmosphere). */
|
|
292
|
+
dungeon?: ForgedDungeonView;
|
|
293
|
+
city?: ForgedCityView;
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=artifact-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-types.d.ts","sourceRoot":"","sources":["../src/artifact-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The forged-artifact SCHEMA — the data shapes that cross from the private
|
|
3
|
+
* design/geometry half of the forger into the publishable half that drives the
|
|
4
|
+
* browser (archetype bakes, the level bake, instance placement and persist).
|
|
5
|
+
*
|
|
6
|
+
* These are declarations, not algorithms: a client that consumes a forge
|
|
7
|
+
* artifact at all has to know its shape, so the schema is public and the code
|
|
8
|
+
* that produces it is not. Each type is DEFINED here and re-exported from the
|
|
9
|
+
* module it used to live in (`forge-world.ts`, `derive-settings.ts`,
|
|
10
|
+
* `dungeon/dressing.ts`, `course.ts`, `dungeon/fixture-parts.ts`), so there is
|
|
11
|
+
* still exactly one definition of each and every historic import site keeps
|
|
12
|
+
* working.
|
|
13
|
+
*
|
|
14
|
+
* This file imports nothing.
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=artifact-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-types.js","sourceRoot":"","sources":["../src/artifact-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The dependency-free leaf: every constant and pure predicate that BOTH halves
|
|
3
|
+
* of the world forger need.
|
|
4
|
+
*
|
|
5
|
+
* The forger splits in two — the private design/geometry half (`forge-world.ts`,
|
|
6
|
+
* `scene-spec.ts`, the geometry tree, the designer and the director) and the
|
|
7
|
+
* publishable half that drives the browser steps (archetype bakes, the level
|
|
8
|
+
* bake, instance placement + persist). A handful of numbers and one predicate
|
|
9
|
+
* are genuinely shared. Left where they were, importing them would drag
|
|
10
|
+
* `forge-world.ts` (700+ lines, and through it `build-scene`, `glb-write`,
|
|
11
|
+
* `dungeon/nav-compile`, `marker-transform` and `heightfield`) or `city/zones.ts`
|
|
12
|
+
* (`geometry`, `street-graph`, `ground-style`) — and therefore three.js — into
|
|
13
|
+
* the publishable half for the sake of three numbers.
|
|
14
|
+
*
|
|
15
|
+
* So this file imports NOTHING, and every previous home re-exports from here so
|
|
16
|
+
* each symbol still has exactly one definition. Add to it only what both halves
|
|
17
|
+
* actually need; it is a boundary, not a junk drawer.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Absolute LOD0 leaf ceiling for one archetype bake — the bake loop re-bakes at
|
|
21
|
+
* doubled voxel sizes until the count fits. Per-archetype TARGETS below are what
|
|
22
|
+
* actually size the bake; this is only the runaway backstop.
|
|
23
|
+
*/
|
|
24
|
+
export declare const ASSET_LOD0_VOXEL_BUDGET = 500000;
|
|
25
|
+
/**
|
|
26
|
+
* The LOD0 leaf TARGET for an ordinary (non-landmark) archetype — what actually
|
|
27
|
+
* sizes a standard bake. Its landmark sibling stays in derive-settings.ts, which
|
|
28
|
+
* is the only thing that reads it; this one crosses because the pipeline's own
|
|
29
|
+
* bake-loop tests assert against it.
|
|
30
|
+
*/
|
|
31
|
+
export declare const ASSET_STANDARD_LOD0_TARGET = 50000;
|
|
32
|
+
/**
|
|
33
|
+
* Spawn this far above the marker so the player drops onto the surface —
|
|
34
|
+
* outdoors only. A dungeon spawn instead is authored with clearance 0: the
|
|
35
|
+
* entrance cell's Y (see `dressing.ts` — "FLOOR TRUTH", taken from the floor
|
|
36
|
+
* grid, never from `room.floorY`) already IS the true floor, so `player_0` is
|
|
37
|
+
* written exactly there. The engine (`game/src/engine/loaders/PlayerLoader.ts`)
|
|
38
|
+
* seats the capsule on the floor beneath a configured interior spawn itself (a
|
|
39
|
+
* bounded downward search) rather than lifting an authored point, so the
|
|
40
|
+
* forger no longer needs to predict engine lift constants or bake-regime floor
|
|
41
|
+
* heights. See the `clearanceM` choice in `place-and-persist-level.ts`.
|
|
42
|
+
*/
|
|
43
|
+
export declare const SPAWN_CLEARANCE_M = 1.5;
|
|
44
|
+
/** Sea level (world Y) the engine renders the water surface at — just below the land base so the
|
|
45
|
+
* land occludes the plane and only the dug basins (floor at -WATER_DEPTH) reveal the see-through sea. */
|
|
46
|
+
export declare const WATER_SURFACE_Y = -2;
|
|
47
|
+
/** Bake pitch of a wall module. Every relief feature is a whole multiple of it. */
|
|
48
|
+
export declare const VOXEL_M = 0.0625;
|
|
49
|
+
/** Modules bake at this pitch, pinned rather than left to the archetype
|
|
50
|
+
* budget's clamp — a coarser bake silently deletes ALL relief. */
|
|
51
|
+
export declare const MODULE_MIN_VOXEL_M = 0.0625;
|
|
52
|
+
/** Top-level GLB node-name prefix. The bake and structural fail-fast path both
|
|
53
|
+
* branch on it; used modules are never dropped or degraded to shell. */
|
|
54
|
+
export declare const MODULE_NAME_PREFIX = "Mod_";
|
|
55
|
+
/**
|
|
56
|
+
* Question: MIGHT this archetype's instance group be a module kit's, and so
|
|
57
|
+
* bloat the world GLB the way the kit's groups do? Deliberately loose — the
|
|
58
|
+
* reserved `Mod_` name prefix (module-kit.ts) and nothing else.
|
|
59
|
+
*
|
|
60
|
+
* Fails safe by OVER-matching. A false positive drops one redundant
|
|
61
|
+
* self-description copy of an object from a file only a manual GLB viewer and
|
|
62
|
+
* the Assets-tab bake fallback ever read; the archetype's own asset and every
|
|
63
|
+
* placement are written elsewhere and are untouched. A false negative puts a
|
|
64
|
+
* several-hundred-instance group back into the world GLB — the measured case
|
|
65
|
+
* was 567 module placements replaying a shared mesh for 23.7M effective
|
|
66
|
+
* triangles, which burned the full 20-minute bake timeout on a level that
|
|
67
|
+
* forged in 95 s without them. Over-matching costs a viewer copy;
|
|
68
|
+
* under-matching costs the run.
|
|
69
|
+
*/
|
|
70
|
+
export declare function isModuleNamedArchetype(name: string): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Question: IS this archetype really one of the kit's own pieces, so its bake
|
|
73
|
+
* may be PINNED to the kit's voxel size and its interior left unfilled? The
|
|
74
|
+
* reserved prefix AND the non-colliding decorative flag `dungeon-expand.ts`'s
|
|
75
|
+
* `moduleArchetype` sets on every piece — the same pair `archetype-skips.ts`'s
|
|
76
|
+
* `isCladdingModule` requires.
|
|
77
|
+
*
|
|
78
|
+
* Fails safe by UNDER-matching, the opposite direction from the predicate
|
|
79
|
+
* above, which is why the two must stay separate rather than share one test. A
|
|
80
|
+
* false negative costs nothing today: every real kit piece is small enough that
|
|
81
|
+
* `deriveArchetypeVoxelBake` floor-clamps to this same value anyway, so the pin
|
|
82
|
+
* is a guarantee against future kit or budget changes, not a live behaviour
|
|
83
|
+
* change. A false positive is the expensive direction, and the pin is the only
|
|
84
|
+
* branch here with a live effect at all: `bake.minVoxelSize` is already floored
|
|
85
|
+
* at ASSET_MIN_VOXEL_SIZE, which IS MODULE_MIN_VOXEL_M, so pinning can only
|
|
86
|
+
* make a bake FINER, never coarser. `scene-spec.ts`'s `nodeName` lets an LLM
|
|
87
|
+
* legally name any object `Mod_*` in any genre and nothing in the repo reserves
|
|
88
|
+
* the prefix, so a prefix-only pin would bake, say, a `Mod_Tower` in a city
|
|
89
|
+
* forge at roughly 13x the surface cells — and that timeout is FATAL, because
|
|
90
|
+
* `archetype-skips.ts`'s `isCladdingModule` would (correctly) refuse to class a
|
|
91
|
+
* colliding object as droppable. Nothing downstream rescues it either: the
|
|
92
|
+
* pipeline's coarsen-rebake loop, which used to double a misfired pin back out
|
|
93
|
+
* of trouble, now leaves modules at their pinned size precisely so a REAL
|
|
94
|
+
* module's relief survives. Same mechanism, opposite roles — with that net
|
|
95
|
+
* gone, this narrowing is the guard.
|
|
96
|
+
*
|
|
97
|
+
* This lives in the leaf rather than in `forge-world.ts` because BOTH halves
|
|
98
|
+
* decide with it: the forger pins the bake resolution here, and the pipeline's
|
|
99
|
+
* `isCladdingModule` classifies the same archetype the same way. Restating it
|
|
100
|
+
* on one side would silently mis-resolve bakes with every test still green.
|
|
101
|
+
*/
|
|
102
|
+
export declare function isKitModuleArchetype(archetype: {
|
|
103
|
+
name: string;
|
|
104
|
+
collision: boolean;
|
|
105
|
+
}): boolean;
|
|
106
|
+
//# sourceMappingURL=forge-constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forge-constants.d.ts","sourceRoot":"","sources":["../src/forge-constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,SAAU,CAAC;AAE/C;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,QAAS,CAAC;AAIjD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAIrC;0GAC0G;AAC1G,eAAO,MAAM,eAAe,KAAK,CAAC;AAIlC,mFAAmF;AACnF,eAAO,MAAM,OAAO,SAAS,CAAC;AAE9B;mEACmE;AACnE,eAAO,MAAM,kBAAkB,SAAU,CAAC;AAE1C;yEACyE;AACzE,eAAO,MAAM,kBAAkB,SAAS,CAAC;AAEzC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAE7F"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The dependency-free leaf: every constant and pure predicate that BOTH halves
|
|
3
|
+
* of the world forger need.
|
|
4
|
+
*
|
|
5
|
+
* The forger splits in two — the private design/geometry half (`forge-world.ts`,
|
|
6
|
+
* `scene-spec.ts`, the geometry tree, the designer and the director) and the
|
|
7
|
+
* publishable half that drives the browser steps (archetype bakes, the level
|
|
8
|
+
* bake, instance placement + persist). A handful of numbers and one predicate
|
|
9
|
+
* are genuinely shared. Left where they were, importing them would drag
|
|
10
|
+
* `forge-world.ts` (700+ lines, and through it `build-scene`, `glb-write`,
|
|
11
|
+
* `dungeon/nav-compile`, `marker-transform` and `heightfield`) or `city/zones.ts`
|
|
12
|
+
* (`geometry`, `street-graph`, `ground-style`) — and therefore three.js — into
|
|
13
|
+
* the publishable half for the sake of three numbers.
|
|
14
|
+
*
|
|
15
|
+
* So this file imports NOTHING, and every previous home re-exports from here so
|
|
16
|
+
* each symbol still has exactly one definition. Add to it only what both halves
|
|
17
|
+
* actually need; it is a boundary, not a junk drawer.
|
|
18
|
+
*/
|
|
19
|
+
// ── Archetype bake budgets (derive-settings.ts) ──────────────────────────────
|
|
20
|
+
/**
|
|
21
|
+
* Absolute LOD0 leaf ceiling for one archetype bake — the bake loop re-bakes at
|
|
22
|
+
* doubled voxel sizes until the count fits. Per-archetype TARGETS below are what
|
|
23
|
+
* actually size the bake; this is only the runaway backstop.
|
|
24
|
+
*/
|
|
25
|
+
export const ASSET_LOD0_VOXEL_BUDGET = 500000;
|
|
26
|
+
/**
|
|
27
|
+
* The LOD0 leaf TARGET for an ordinary (non-landmark) archetype — what actually
|
|
28
|
+
* sizes a standard bake. Its landmark sibling stays in derive-settings.ts, which
|
|
29
|
+
* is the only thing that reads it; this one crosses because the pipeline's own
|
|
30
|
+
* bake-loop tests assert against it.
|
|
31
|
+
*/
|
|
32
|
+
export const ASSET_STANDARD_LOD0_TARGET = 50000;
|
|
33
|
+
// ── Spawn (forge-world.ts) ───────────────────────────────────────────────────
|
|
34
|
+
/**
|
|
35
|
+
* Spawn this far above the marker so the player drops onto the surface —
|
|
36
|
+
* outdoors only. A dungeon spawn instead is authored with clearance 0: the
|
|
37
|
+
* entrance cell's Y (see `dressing.ts` — "FLOOR TRUTH", taken from the floor
|
|
38
|
+
* grid, never from `room.floorY`) already IS the true floor, so `player_0` is
|
|
39
|
+
* written exactly there. The engine (`game/src/engine/loaders/PlayerLoader.ts`)
|
|
40
|
+
* seats the capsule on the floor beneath a configured interior spawn itself (a
|
|
41
|
+
* bounded downward search) rather than lifting an authored point, so the
|
|
42
|
+
* forger no longer needs to predict engine lift constants or bake-regime floor
|
|
43
|
+
* heights. See the `clearanceM` choice in `place-and-persist-level.ts`.
|
|
44
|
+
*/
|
|
45
|
+
export const SPAWN_CLEARANCE_M = 1.5;
|
|
46
|
+
// ── Water (city/zones.ts) ────────────────────────────────────────────────────
|
|
47
|
+
/** Sea level (world Y) the engine renders the water surface at — just below the land base so the
|
|
48
|
+
* land occludes the plane and only the dug basins (floor at -WATER_DEPTH) reveal the see-through sea. */
|
|
49
|
+
export const WATER_SURFACE_Y = -2;
|
|
50
|
+
// ── Dungeon module kit (dungeon/module-stone.ts, dungeon/module-kit.ts) ──────
|
|
51
|
+
/** Bake pitch of a wall module. Every relief feature is a whole multiple of it. */
|
|
52
|
+
export const VOXEL_M = 0.0625;
|
|
53
|
+
/** Modules bake at this pitch, pinned rather than left to the archetype
|
|
54
|
+
* budget's clamp — a coarser bake silently deletes ALL relief. */
|
|
55
|
+
export const MODULE_MIN_VOXEL_M = VOXEL_M;
|
|
56
|
+
/** Top-level GLB node-name prefix. The bake and structural fail-fast path both
|
|
57
|
+
* branch on it; used modules are never dropped or degraded to shell. */
|
|
58
|
+
export const MODULE_NAME_PREFIX = 'Mod_';
|
|
59
|
+
/**
|
|
60
|
+
* Question: MIGHT this archetype's instance group be a module kit's, and so
|
|
61
|
+
* bloat the world GLB the way the kit's groups do? Deliberately loose — the
|
|
62
|
+
* reserved `Mod_` name prefix (module-kit.ts) and nothing else.
|
|
63
|
+
*
|
|
64
|
+
* Fails safe by OVER-matching. A false positive drops one redundant
|
|
65
|
+
* self-description copy of an object from a file only a manual GLB viewer and
|
|
66
|
+
* the Assets-tab bake fallback ever read; the archetype's own asset and every
|
|
67
|
+
* placement are written elsewhere and are untouched. A false negative puts a
|
|
68
|
+
* several-hundred-instance group back into the world GLB — the measured case
|
|
69
|
+
* was 567 module placements replaying a shared mesh for 23.7M effective
|
|
70
|
+
* triangles, which burned the full 20-minute bake timeout on a level that
|
|
71
|
+
* forged in 95 s without them. Over-matching costs a viewer copy;
|
|
72
|
+
* under-matching costs the run.
|
|
73
|
+
*/
|
|
74
|
+
export function isModuleNamedArchetype(name) {
|
|
75
|
+
return name.startsWith(MODULE_NAME_PREFIX);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Question: IS this archetype really one of the kit's own pieces, so its bake
|
|
79
|
+
* may be PINNED to the kit's voxel size and its interior left unfilled? The
|
|
80
|
+
* reserved prefix AND the non-colliding decorative flag `dungeon-expand.ts`'s
|
|
81
|
+
* `moduleArchetype` sets on every piece — the same pair `archetype-skips.ts`'s
|
|
82
|
+
* `isCladdingModule` requires.
|
|
83
|
+
*
|
|
84
|
+
* Fails safe by UNDER-matching, the opposite direction from the predicate
|
|
85
|
+
* above, which is why the two must stay separate rather than share one test. A
|
|
86
|
+
* false negative costs nothing today: every real kit piece is small enough that
|
|
87
|
+
* `deriveArchetypeVoxelBake` floor-clamps to this same value anyway, so the pin
|
|
88
|
+
* is a guarantee against future kit or budget changes, not a live behaviour
|
|
89
|
+
* change. A false positive is the expensive direction, and the pin is the only
|
|
90
|
+
* branch here with a live effect at all: `bake.minVoxelSize` is already floored
|
|
91
|
+
* at ASSET_MIN_VOXEL_SIZE, which IS MODULE_MIN_VOXEL_M, so pinning can only
|
|
92
|
+
* make a bake FINER, never coarser. `scene-spec.ts`'s `nodeName` lets an LLM
|
|
93
|
+
* legally name any object `Mod_*` in any genre and nothing in the repo reserves
|
|
94
|
+
* the prefix, so a prefix-only pin would bake, say, a `Mod_Tower` in a city
|
|
95
|
+
* forge at roughly 13x the surface cells — and that timeout is FATAL, because
|
|
96
|
+
* `archetype-skips.ts`'s `isCladdingModule` would (correctly) refuse to class a
|
|
97
|
+
* colliding object as droppable. Nothing downstream rescues it either: the
|
|
98
|
+
* pipeline's coarsen-rebake loop, which used to double a misfired pin back out
|
|
99
|
+
* of trouble, now leaves modules at their pinned size precisely so a REAL
|
|
100
|
+
* module's relief survives. Same mechanism, opposite roles — with that net
|
|
101
|
+
* gone, this narrowing is the guard.
|
|
102
|
+
*
|
|
103
|
+
* This lives in the leaf rather than in `forge-world.ts` because BOTH halves
|
|
104
|
+
* decide with it: the forger pins the bake resolution here, and the pipeline's
|
|
105
|
+
* `isCladdingModule` classifies the same archetype the same way. Restating it
|
|
106
|
+
* on one side would silently mis-resolve bakes with every test still green.
|
|
107
|
+
*/
|
|
108
|
+
export function isKitModuleArchetype(archetype) {
|
|
109
|
+
return isModuleNamedArchetype(archetype.name) && archetype.collision === false;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=forge-constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forge-constants.js","sourceRoot":"","sources":["../src/forge-constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,gFAAgF;AAEhF;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAO,CAAC;AAE/C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,KAAM,CAAC;AAEjD,gFAAgF;AAEhF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAErC,gFAAgF;AAEhF;0GAC0G;AAC1G,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,CAAC;AAElC,gFAAgF;AAEhF,mFAAmF;AACnF,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC;AAE9B;mEACmE;AACnE,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAE1C;yEACyE;AACzE,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAEzC;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,OAAO,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAA+C;IAClF,OAAO,sBAAsB,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,SAAS,KAAK,KAAK,CAAC;AACjF,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@bitmagic/world-forger` — the CLIENT half of the world forger.
|
|
3
|
+
*
|
|
4
|
+
* The forger runs in two halves. The DESIGN and GEOMETRY half (an LLM designs a
|
|
5
|
+
* level, deterministic code builds its meshes) is private, is not published, and
|
|
6
|
+
* stays server-side. This package is everything a host needs to consume what
|
|
7
|
+
* that half produces:
|
|
8
|
+
*
|
|
9
|
+
* - the forged-level ARTIFACT SCHEMA (artifact-types.ts, pipeline/job-types.ts)
|
|
10
|
+
* — placements, markers, resolved gameplay features, dungeon doors/keys/
|
|
11
|
+
* lights, the terrain height grid and the level bake options,
|
|
12
|
+
* - the HOST SEAMS the pipeline runs behind (storage, model, transport,
|
|
13
|
+
* world.json, logger — see pipeline/deps.ts),
|
|
14
|
+
* - the three BROWSER STEPS themselves: create the archetype library assets,
|
|
15
|
+
* bake the level, place the instances and plan the world.json write.
|
|
16
|
+
*
|
|
17
|
+
* Nothing here touches geometry, and it deliberately has no three.js — the steps
|
|
18
|
+
* orchestrate a browser that does the heavy work, and the artifact that reaches
|
|
19
|
+
* them is already plain JSON.
|
|
20
|
+
*
|
|
21
|
+
* The pipeline is reachable as `@bitmagic/world-forger/pipeline/index.js`;
|
|
22
|
+
* every module is reachable by its own subpath (e.g.
|
|
23
|
+
* `@bitmagic/world-forger/pipeline/transport-types.js`).
|
|
24
|
+
*/
|
|
25
|
+
export * from './artifact-types.js';
|
|
26
|
+
export * from './forge-constants.js';
|
|
27
|
+
export * from './terrain-height-grid.js';
|
|
28
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@bitmagic/world-forger` — the CLIENT half of the world forger.
|
|
3
|
+
*
|
|
4
|
+
* The forger runs in two halves. The DESIGN and GEOMETRY half (an LLM designs a
|
|
5
|
+
* level, deterministic code builds its meshes) is private, is not published, and
|
|
6
|
+
* stays server-side. This package is everything a host needs to consume what
|
|
7
|
+
* that half produces:
|
|
8
|
+
*
|
|
9
|
+
* - the forged-level ARTIFACT SCHEMA (artifact-types.ts, pipeline/job-types.ts)
|
|
10
|
+
* — placements, markers, resolved gameplay features, dungeon doors/keys/
|
|
11
|
+
* lights, the terrain height grid and the level bake options,
|
|
12
|
+
* - the HOST SEAMS the pipeline runs behind (storage, model, transport,
|
|
13
|
+
* world.json, logger — see pipeline/deps.ts),
|
|
14
|
+
* - the three BROWSER STEPS themselves: create the archetype library assets,
|
|
15
|
+
* bake the level, place the instances and plan the world.json write.
|
|
16
|
+
*
|
|
17
|
+
* Nothing here touches geometry, and it deliberately has no three.js — the steps
|
|
18
|
+
* orchestrate a browser that does the heavy work, and the artifact that reaches
|
|
19
|
+
* them is already plain JSON.
|
|
20
|
+
*
|
|
21
|
+
* The pipeline is reachable as `@bitmagic/world-forger/pipeline/index.js`;
|
|
22
|
+
* every module is reachable by its own subpath (e.g.
|
|
23
|
+
* `@bitmagic/world-forger/pipeline/transport-types.js`).
|
|
24
|
+
*/
|
|
25
|
+
export * from './artifact-types.js';
|
|
26
|
+
export * from './forge-constants.js';
|
|
27
|
+
export * from './terrain-height-grid.js';
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC"}
|
package/dist/log.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal dependency-free logger for this package. `shared/world-forger` must
|
|
3
|
+
* stay free of game-play-agent's pino/fs-backed logger (`src/utils/logger.ts`)
|
|
4
|
+
* — see the package README-equivalent purity rule in the extraction task —
|
|
5
|
+
* so this mirrors just the pino call shape `city-expand.ts` uses
|
|
6
|
+
* (`log.warn(context, message)` / `log.info(context, message)`) over plain
|
|
7
|
+
* console output.
|
|
8
|
+
*
|
|
9
|
+
* This is NOT a general injectable-logger seam, and deliberately stays that
|
|
10
|
+
* way. Two modules use it — `pipeline/asset-catalog.ts` and
|
|
11
|
+
* `pipeline/forged-work-store.ts` — and both log housekeeping detail (a
|
|
12
|
+
* skipped catalog entry, a store read) that no host has ever needed to route
|
|
13
|
+
* anywhere. Everything a host DOES care about already goes through the real
|
|
14
|
+
* seam: `ForgeDeps.logger` (see pipeline/deps.ts), which every pipeline step
|
|
15
|
+
* logs through and which the web lane points at pino and the CLI lane at the
|
|
16
|
+
* creator's terminal. Adding a second injectable logger for these two call
|
|
17
|
+
* sites would duplicate that seam rather than complete it.
|
|
18
|
+
*/
|
|
19
|
+
export interface Logger {
|
|
20
|
+
info(context: Record<string, unknown>, message: string): void;
|
|
21
|
+
warn(context: Record<string, unknown>, message: string): void;
|
|
22
|
+
error(context: Record<string, unknown>, message: string): void;
|
|
23
|
+
debug(context: Record<string, unknown>, message: string): void;
|
|
24
|
+
}
|
|
25
|
+
export declare function createLogger(name: string): Logger;
|
|
26
|
+
//# sourceMappingURL=log.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9D,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9D,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAChE;AAQD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOjD"}
|