@bitmagic/cli 0.1.52-dev.7 → 0.1.52-dev.9
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/README.md +40 -0
- package/dist/bin.js +25 -0
- package/dist/bin.js.map +1 -1
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +13 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/levels.d.ts +33 -0
- package/dist/commands/levels.js +241 -0
- package/dist/commands/levels.js.map +1 -0
- package/dist/editor/journal.d.ts +17 -1
- package/dist/editor/journal.js +2 -0
- package/dist/editor/journal.js.map +1 -1
- package/dist/editor/server.js +75 -92
- package/dist/editor/server.js.map +1 -1
- package/dist/editor/shell-page.js +119 -114
- package/dist/editor/shell-page.js.map +1 -1
- package/dist/editor/voxel-save.js +8 -12
- package/dist/editor/voxel-save.js.map +1 -1
- package/dist/generate/prop.d.ts +52 -4
- package/dist/generate/prop.js +167 -46
- package/dist/generate/prop.js.map +1 -1
- package/dist/generate/stream.d.ts +7 -0
- package/dist/generate/stream.js +2 -1
- package/dist/generate/stream.js.map +1 -1
- package/dist/levels/registry.d.ts +88 -0
- package/dist/levels/registry.js +309 -0
- package/dist/levels/registry.js.map +1 -0
- package/dist/messages/check.d.ts +30 -0
- package/dist/messages/check.js +119 -0
- package/dist/messages/check.js.map +1 -0
- package/dist/messages/notice.d.ts +58 -0
- package/dist/messages/notice.js +54 -0
- package/dist/messages/notice.js.map +1 -0
- package/dist/messages/refresh.d.ts +19 -0
- package/dist/messages/refresh.js +42 -0
- package/dist/messages/refresh.js.map +1 -0
- package/dist/scaffold/project-files.js +3 -1
- package/dist/scaffold/project-files.js.map +1 -1
- package/package.json +4 -4
package/dist/generate/prop.js
CHANGED
|
@@ -8,19 +8,32 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Three steps, mirroring `game-play-agent/src/mastra/utils/hq-asset-jobs.ts` — the proven chain:
|
|
10
10
|
*
|
|
11
|
-
* 1. Ask api-server for
|
|
12
|
-
* live there and never reach this machine, which is the whole reason the editor
|
|
13
|
-
* the agent rather than doing it inline.
|
|
14
|
-
* 2.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
11
|
+
* 1. Ask api-server for the source (`POST /api/cli/v1/assets/<type>/stream`). Asset Forger
|
|
12
|
+
* credentials live there and never reach this machine, which is the whole reason the editor
|
|
13
|
+
* hands this to the agent rather than doing it inline.
|
|
14
|
+
* 2. Bake it in a browser, constrained to the asset's recorded `fitBox`. Only the engine can do
|
|
15
|
+
* this, so the CLI drives its own headless Chrome — `forge/voxelize-session.ts`, shared with
|
|
16
|
+
* `generate vehicle` and `assets add`.
|
|
17
17
|
* 3. Upsert the result into `assets[]` under the SAME id, which is what upgrades every already
|
|
18
18
|
* placed instance instead of adding a second asset beside them.
|
|
19
19
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
20
|
+
* Step 1 has two sources, and which one is used depends on the environment:
|
|
21
|
+
*
|
|
22
|
+
* - `prop` returns a GLB. The engine then voxelizes it and throws the mesh away — which is all
|
|
23
|
+
* a 50-100 MB textured model was ever for here.
|
|
24
|
+
* - `prop-voxel` returns an HFVX voxel master directly from TRELLIS.2's own voxel field, no mesh
|
|
25
|
+
* at any point. Measured on staging: 219 KB and ~8.5s warm, against minutes and megabytes.
|
|
26
|
+
*
|
|
27
|
+
* `prop-voxel` is used in the `dev` environment ONLY, and only when the project's vendored engine
|
|
28
|
+
* has the handler for it. Everywhere else this is exactly the command it has always been. The
|
|
29
|
+
* newer path is the better one; it is gated because it is newer, not because it is lesser, and
|
|
30
|
+
* `prod` graduates when there is reason to.
|
|
31
|
+
*
|
|
32
|
+
* The generated source survives a failure in steps 2-3: it is reported in the error so a retry can
|
|
33
|
+
* be pointed at it rather than paying for the generation twice.
|
|
22
34
|
*/
|
|
23
35
|
import * as fs from 'fs';
|
|
36
|
+
import * as path from 'path';
|
|
24
37
|
import { CliError } from '../errors.js';
|
|
25
38
|
import { applyModificationsToWorld } from '../forge/apply-modifications.js';
|
|
26
39
|
import { projectWorldJsonPath } from '../forge/run-pipeline.js';
|
|
@@ -33,6 +46,28 @@ import { requestGeneration } from './stream.js';
|
|
|
33
46
|
*/
|
|
34
47
|
const MIN_VOXEL_SIZE = 0.1;
|
|
35
48
|
const MAX_VOXEL_SIZE = 0.5;
|
|
49
|
+
/** The api-server generator types this command can ask for. */
|
|
50
|
+
const MESH_GENERATOR_TYPE = 'prop';
|
|
51
|
+
const VOXEL_GENERATOR_TYPE = 'prop-voxel';
|
|
52
|
+
/**
|
|
53
|
+
* Whether this project's engine can bake a voxel master.
|
|
54
|
+
*
|
|
55
|
+
* A capability probe, not a version comparison. `withVoxelizeSession` runs the project's OWN
|
|
56
|
+
* vendored engine, and `CREATE_ASSET_FROM_VXL_MASTER` only exists in engines from 2026-08-02 —
|
|
57
|
+
* but the failure mode of guessing wrong is what makes this worth checking rather than trying:
|
|
58
|
+
* an engine with no handler for a message does not answer, so the request stalls for the full
|
|
59
|
+
* VOXELIZE_TIMEOUT_MS (10 minutes) and then again on the retry, after which the paid generation
|
|
60
|
+
* is thrown away. Reading a version string is the indirect way to ask; the file is the answer.
|
|
61
|
+
*
|
|
62
|
+
* `engine` resolves to `engine/engine` — see scaffold/aliases.ts.
|
|
63
|
+
*/
|
|
64
|
+
export function engineSupportsVxlMaster(projectRoot) {
|
|
65
|
+
return fs.existsSync(path.join(projectRoot, 'engine', 'engine', 'template', 'VxlMasterAssetHandler.ts'));
|
|
66
|
+
}
|
|
67
|
+
/** A thrown CliError's message, without letting a non-Error stringify to "[object Object]". */
|
|
68
|
+
function messageOf(error) {
|
|
69
|
+
return error instanceof Error ? error.message : String(error);
|
|
70
|
+
}
|
|
36
71
|
function isRecord(value) {
|
|
37
72
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
38
73
|
}
|
|
@@ -94,66 +129,152 @@ export function shouldFillInterior(fitBox) {
|
|
|
94
129
|
*/
|
|
95
130
|
export async function generateAndInstallProp(options) {
|
|
96
131
|
const { context, environment, token, assetId, prompt, log } = options;
|
|
132
|
+
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
97
133
|
// Before anything is spent: a mistyped id or an asset with no fitBox costs nothing.
|
|
98
134
|
findPropAsset(readWorld(projectWorldJsonPath(context.root)), assetId);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
135
|
+
// A retry with `--glb-url` skips generation entirely and is always the mesh path — the caller
|
|
136
|
+
// has a mesh in hand and asked for it to be used.
|
|
137
|
+
if (options.glbUrl !== undefined) {
|
|
138
|
+
log(`Reusing the mesh at ${options.glbUrl} — skipping generation.`);
|
|
139
|
+
const reused = await voxelizeAndInstall({
|
|
140
|
+
context, environment, token, assetId, prompt,
|
|
141
|
+
source: { kind: 'glb', glbUrl: options.glbUrl },
|
|
142
|
+
log, ...(options.session ? { session: options.session } : {}),
|
|
143
|
+
});
|
|
144
|
+
return { ...reused, glbUrl: options.glbUrl };
|
|
145
|
+
}
|
|
146
|
+
if (environment.name === 'dev' && engineSupportsVxlMaster(context.root)) {
|
|
147
|
+
const viaVoxels = await tryVoxelMasterPath({ ...options, fetchImpl });
|
|
148
|
+
if (viaVoxels)
|
|
149
|
+
return viaVoxels;
|
|
150
|
+
// Only a GENERATION failure falls through — a bake failure throws out of tryVoxelMasterPath,
|
|
151
|
+
// because re-generating would pay twice for a source we already have.
|
|
152
|
+
log('Falling back to the mesh path.');
|
|
109
153
|
}
|
|
110
|
-
|
|
111
|
-
|
|
154
|
+
const outcome = await requestGeneration(environment, token, MESH_GENERATOR_TYPE, { gameId: context.metadata.gameId, prompt }, { fetch: fetchImpl, onProgress: log });
|
|
155
|
+
if (!outcome.success)
|
|
156
|
+
throw new CliError(`${outcome.message} world.json is unchanged.`);
|
|
157
|
+
if (!outcome.glbUrl) {
|
|
158
|
+
throw new CliError('The generator reported success but returned no mesh. world.json is unchanged.');
|
|
112
159
|
}
|
|
160
|
+
const glbUrl = outcome.glbUrl;
|
|
161
|
+
log(`Mesh generated: ${glbUrl}`);
|
|
113
162
|
const result = await voxelizeAndInstall({
|
|
114
|
-
context, environment, token, assetId, prompt,
|
|
163
|
+
context, environment, token, assetId, prompt,
|
|
164
|
+
source: { kind: 'glb', glbUrl },
|
|
165
|
+
log, ...(options.session ? { session: options.session } : {}),
|
|
115
166
|
});
|
|
116
167
|
return { ...result, glbUrl };
|
|
117
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* The dev-only path: a voxel master instead of a mesh.
|
|
171
|
+
*
|
|
172
|
+
* Returns null when GENERATION failed, so the caller can fall back to the mesh path. Bake failures
|
|
173
|
+
* throw instead: the master exists and was paid for, so the useful answer is "here is what is
|
|
174
|
+
* kept", not another generation. That is the same split the mesh path has always made with
|
|
175
|
+
* `--glb-url`.
|
|
176
|
+
*/
|
|
177
|
+
async function tryVoxelMasterPath(options) {
|
|
178
|
+
const { context, environment, token, assetId, prompt, log, fetchImpl } = options;
|
|
179
|
+
let outcome;
|
|
180
|
+
try {
|
|
181
|
+
outcome = await requestGeneration(environment, token, VOXEL_GENERATOR_TYPE, { gameId: context.metadata.gameId, prompt }, { fetch: fetchImpl, onProgress: log });
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
// A non-2xx THROWS rather than returning an unsuccessful outcome, so catching is not belt and
|
|
185
|
+
// braces — it is the whole fallback for the most likely failure of all. An api-server that
|
|
186
|
+
// does not know `prop-voxel` answers 400, which is exactly what a dev deployment looks like
|
|
187
|
+
// before this feature reaches it. Without this the command would die there instead of doing
|
|
188
|
+
// what it has always done.
|
|
189
|
+
log(`Direct voxel generation is unavailable (${messageOf(error)}).`);
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
const masterUrl = outcome.success ? outcome.masterUrl : undefined;
|
|
193
|
+
if (!masterUrl) {
|
|
194
|
+
// Said out loud, including the cost: the generator bills the moment the Forger accepts the
|
|
195
|
+
// job, so a failure here may already have spent sparks and the mesh attempt will spend more.
|
|
196
|
+
// A silent fallback is how a doubled bill becomes a mystery.
|
|
197
|
+
log(`Direct voxel generation did not produce a master (${outcome.message}). `
|
|
198
|
+
+ 'If the generator had already accepted the job, that attempt was still billed.');
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
log(`Voxels generated: ${masterUrl}`);
|
|
202
|
+
const result = await voxelizeAndInstall({
|
|
203
|
+
context, environment, token, assetId, prompt,
|
|
204
|
+
source: { kind: 'master', masterUrl },
|
|
205
|
+
log, ...(options.session ? { session: options.session } : {}),
|
|
206
|
+
});
|
|
207
|
+
return { ...result, masterUrl };
|
|
208
|
+
}
|
|
118
209
|
/**
|
|
119
210
|
* Steps 2 and 3. Split from the command so the browser work is callable directly on a retry that
|
|
120
211
|
* already has a GLB, and so the command file stays about flags and output.
|
|
121
212
|
*/
|
|
122
213
|
export async function voxelizeAndInstall(options) {
|
|
123
|
-
const { context, environment, token, assetId, prompt,
|
|
214
|
+
const { context, environment, token, assetId, prompt, source, log } = options;
|
|
215
|
+
const runSession = options.session ?? withVoxelizeSession;
|
|
124
216
|
const worldPath = projectWorldJsonPath(context.root);
|
|
125
217
|
const world = readWorld(worldPath);
|
|
126
218
|
const { asset, fitBox } = findPropAsset(world, assetId);
|
|
127
219
|
const assetName = typeof asset.name === 'string' ? asset.name : assetId;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
220
|
+
// What was generated, what it cost, and how to reuse it — the three things every failure below
|
|
221
|
+
// has to say, and the only part of those messages that differs between the two sources.
|
|
222
|
+
const kept = source.kind === 'glb'
|
|
223
|
+
? {
|
|
224
|
+
subject: 'the mesh',
|
|
225
|
+
what: `The generated mesh is kept at ${source.glbUrl}`,
|
|
226
|
+
retry: ' — retry with `--glb-url` to skip the paid generation step.',
|
|
227
|
+
}
|
|
228
|
+
: {
|
|
229
|
+
subject: 'the voxels',
|
|
230
|
+
// No --master-url retry flag exists yet; saying so beats implying one.
|
|
231
|
+
what: `The generated voxel master is kept at ${source.masterUrl}`,
|
|
232
|
+
retry: '. Re-run to generate again, or bake it by hand from that URL.',
|
|
233
|
+
};
|
|
234
|
+
return runSession({
|
|
235
|
+
context, environment, token, log, subject: kept.subject, retryHint: `${kept.what}${kept.retry}`,
|
|
132
236
|
}, async ({ host, port }) => {
|
|
133
|
-
log(`
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
237
|
+
log(`Baking "${assetName}" to its recorded fitBox…`);
|
|
238
|
+
// Both messages are answered on the GLB reply channel: the engine does that deliberately so
|
|
239
|
+
// the Creator's persist-and-reload watcher fires for either. `hq-asset-jobs.ts` picks between
|
|
240
|
+
// exactly these two shapes — this is that fork, not a third one.
|
|
241
|
+
const request = source.kind === 'glb'
|
|
242
|
+
? {
|
|
243
|
+
type: 'CREATE_ASSET_FROM_GLB_URL',
|
|
244
|
+
requestId: `prop-${assetId}-${port}`,
|
|
245
|
+
name: assetName,
|
|
246
|
+
glbUrl: source.glbUrl,
|
|
247
|
+
// The SAME id, which is what makes this an upgrade of every placed instance rather than
|
|
248
|
+
// a new asset sitting beside them.
|
|
249
|
+
assetId,
|
|
250
|
+
options: {
|
|
251
|
+
minVoxelSize: MIN_VOXEL_SIZE,
|
|
252
|
+
maxVoxelSize: MAX_VOXEL_SIZE,
|
|
253
|
+
fitBox,
|
|
254
|
+
fillInterior: shouldFillInterior(fitBox),
|
|
255
|
+
placeholder: false,
|
|
256
|
+
},
|
|
257
|
+
}
|
|
258
|
+
: {
|
|
259
|
+
type: 'CREATE_ASSET_FROM_VXL_MASTER',
|
|
260
|
+
requestId: `prop-${assetId}-${port}`,
|
|
261
|
+
name: assetName,
|
|
262
|
+
masterUrl: source.masterUrl,
|
|
263
|
+
assetId,
|
|
264
|
+
// No fillInterior: a master already carries the occupancy the mesh path has to infer.
|
|
265
|
+
options: {
|
|
266
|
+
minVoxelSize: MIN_VOXEL_SIZE,
|
|
267
|
+
maxVoxelSize: MAX_VOXEL_SIZE,
|
|
268
|
+
fitBox,
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
const result = await host.transport.sendAndWait(request, 'ASSET_FROM_GLB_URL_RESULT', VOXELIZE_TIMEOUT_MS, { maxRetries: 1 });
|
|
150
272
|
if (!result) {
|
|
151
|
-
throw new CliError(`
|
|
152
|
-
+ '`--glb-url` to skip the paid generation step.');
|
|
273
|
+
throw new CliError(`Baking "${assetName}" timed out. ${kept.what}${kept.retry}`);
|
|
153
274
|
}
|
|
154
275
|
if (result.success === false || !isRecord(result.asset)) {
|
|
155
276
|
const reason = typeof result.error === 'string' ? result.error : 'unknown error';
|
|
156
|
-
throw new CliError(`
|
|
277
|
+
throw new CliError(`Baking "${assetName}" failed: ${reason}. ${kept.what}.`);
|
|
157
278
|
}
|
|
158
279
|
const engineAsset = result.asset;
|
|
159
280
|
// The voxelize handler reads `description` from the GLB's scene extras, which the world-forger
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prop.js","sourceRoot":"","sources":["../../src/generate/prop.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"prop.js","sourceRoot":"","sources":["../../src/generate/prop.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,13 @@ export interface GenerationOutcome {
|
|
|
11
11
|
* for them this, not `patches`, is the result that matters. Absent for every other type.
|
|
12
12
|
*/
|
|
13
13
|
glbUrl?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Only the `prop-voxel` type sets this: an HFVX voxel master, generated with no mesh at any
|
|
16
|
+
* point. The same half-made-asset story as `glbUrl` — the caller bakes it in a browser before
|
|
17
|
+
* there is anything to write — but the bake takes a different engine message, so which field
|
|
18
|
+
* came back is what tells the caller which one to send.
|
|
19
|
+
*/
|
|
20
|
+
masterUrl?: string;
|
|
14
21
|
/**
|
|
15
22
|
* Only the `vehicle` type sets this: the bake settings its GLB was authored for. `minVoxelSize`
|
|
16
23
|
* is derived from the vehicle's own proportions rather than fixed, so the CLI cannot pick it —
|
package/dist/generate/stream.js
CHANGED
|
@@ -39,7 +39,7 @@ function asVehicleOutcome(value) {
|
|
|
39
39
|
function asGenerationOutcome(data) {
|
|
40
40
|
if (!isRecord(data))
|
|
41
41
|
return null;
|
|
42
|
-
const { success, message, patches, glbUrl, vehicle } = data;
|
|
42
|
+
const { success, message, patches, glbUrl, masterUrl, vehicle } = data;
|
|
43
43
|
if (typeof success !== 'boolean' || typeof message !== 'string' || !Array.isArray(patches)) {
|
|
44
44
|
return null;
|
|
45
45
|
}
|
|
@@ -49,6 +49,7 @@ function asGenerationOutcome(data) {
|
|
|
49
49
|
message,
|
|
50
50
|
patches: patches,
|
|
51
51
|
...(typeof glbUrl === 'string' ? { glbUrl } : {}),
|
|
52
|
+
...(typeof masterUrl === 'string' ? { masterUrl } : {}),
|
|
52
53
|
...(vehicleOutcome ? { vehicle: vehicleOutcome } : {}),
|
|
53
54
|
};
|
|
54
55
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/generate/stream.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACxG,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAQnE,gGAAgG;AAChG,gGAAgG;AAChG,qCAAqC;AACrC,OAAO,EAAE,cAAc,EAAiB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/generate/stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `bitmagic levels` — the level registry in `worldProfileData.levels`, without the web Creator.
|
|
3
|
+
*
|
|
4
|
+
* `forge` can CREATE levels but never could manage them: only a game's first forge becomes the
|
|
5
|
+
* start level (or `forge --make-start` at creation), so fixing a wrong start, renaming, or deleting
|
|
6
|
+
* a level meant opening the Creator.
|
|
7
|
+
*
|
|
8
|
+
* ── The invariant this file exists to respect ────────────────────────────────────────────────
|
|
9
|
+
*
|
|
10
|
+
* `worldProfileData` keeps three LEGACY MIRRORS — `voxelUrl`, `spawnPoints` and
|
|
11
|
+
* `playerSpawnPosition` — describing the START level, because frozen genre and work-template code
|
|
12
|
+
* boots from those rather than from the registry (see `WorldLevel` in game/src/types/game.ts).
|
|
13
|
+
*
|
|
14
|
+
* Nothing self-heals on the normal boot path. `applyBootLevelOverride` does recompute them, but
|
|
15
|
+
* only when the main screen's level chooser passes a `bootLevelId`. So a `startLevelId` moved
|
|
16
|
+
* without its mirrors boots the NEW level's objects, lighting and navmesh over the OLD level's
|
|
17
|
+
* terrain, and nothing throws. That is the failure this module exists to prevent.
|
|
18
|
+
*
|
|
19
|
+
* The mirrors come from `buildStartLevelMirrors` in `@bitmagic/world-forger`, deliberately rather
|
|
20
|
+
* than reimplemented — the same function the forge uses, carrying a subtlety worth not
|
|
21
|
+
* rediscovering: spawn mirrors are written ONLY when the level owns spawn points, because a level
|
|
22
|
+
* without its own inherits the globals, which are then already correct.
|
|
23
|
+
*
|
|
24
|
+
* Pure: it computes modifications and never applies them.
|
|
25
|
+
*/
|
|
26
|
+
import { type LevelEntry, type WorldJsonModification } from '@bitmagic/world-forger/pipeline/index.js';
|
|
27
|
+
import { type JsonObject } from '../project/world-json.js';
|
|
28
|
+
export interface LevelRow {
|
|
29
|
+
id: string;
|
|
30
|
+
name: string;
|
|
31
|
+
vwldAssetId: string;
|
|
32
|
+
/** The `.vwld` asset is absent from `assets[]`, so this level has nothing to load. */
|
|
33
|
+
missingAsset: boolean;
|
|
34
|
+
start: boolean;
|
|
35
|
+
spawnPoints: number;
|
|
36
|
+
/** Placed objects tagged to this level. Untagged ones are global and belong to none. */
|
|
37
|
+
placed: number;
|
|
38
|
+
}
|
|
39
|
+
export declare function listLevels(world: JsonObject): LevelRow[];
|
|
40
|
+
export interface LevelPlan {
|
|
41
|
+
modifications: WorldJsonModification[];
|
|
42
|
+
/** Said after the write. Never a reason to refuse. */
|
|
43
|
+
notes: string[];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Make `levelId` the level the game boots into — registry AND mirrors, together.
|
|
47
|
+
*
|
|
48
|
+
* Refused when the level's `.vwld` asset is missing or has no url: the mirrors are what actually
|
|
49
|
+
* boot the game, so writing `startLevelId` alone would leave `voxelUrl` describing the previous
|
|
50
|
+
* level, and the registry and the thing that loads would disagree with no error anywhere.
|
|
51
|
+
*/
|
|
52
|
+
export declare function planSetStart(world: JsonObject, levelId: string): LevelPlan;
|
|
53
|
+
export declare function planRename(world: JsonObject, levelId: string, name: string): LevelPlan;
|
|
54
|
+
export interface AddPlan extends LevelPlan {
|
|
55
|
+
level: LevelEntry;
|
|
56
|
+
/** True when this made the game multi-level for the first time. */
|
|
57
|
+
converted: boolean;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Register an existing `.vwld` asset as a level.
|
|
61
|
+
*
|
|
62
|
+
* Start-level policy matches `forge`'s: a game's FIRST level becomes the start, later ones do not,
|
|
63
|
+
* and `--make-start` overrides. Stealing the start from a working game because someone registered
|
|
64
|
+
* a second level would be the surprising outcome.
|
|
65
|
+
*/
|
|
66
|
+
export declare function planAdd(world: JsonObject, vwldAssetId: string, options: {
|
|
67
|
+
name?: string;
|
|
68
|
+
makeStart: boolean;
|
|
69
|
+
}): AddPlan;
|
|
70
|
+
export interface RemovePlan extends LevelPlan {
|
|
71
|
+
level: LevelEntry;
|
|
72
|
+
/** Placed instances tagged to this level, which go with it. */
|
|
73
|
+
placedRemoved: number;
|
|
74
|
+
/** Doors and key items scoped to it, which also go. */
|
|
75
|
+
scopedRemoved: string[];
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Remove a level from the registry.
|
|
79
|
+
*
|
|
80
|
+
* Two refusals, matching the agent's `manage-levels delete` so the two lanes cannot disagree:
|
|
81
|
+
* the last level, and the START level. The second matters most — `startLevelId` naming nothing
|
|
82
|
+
* falls back to `levels[0]` at boot while the mirrors still describe the deleted level, which is
|
|
83
|
+
* the silent stale-mirror failure. Move the start first, deliberately.
|
|
84
|
+
*
|
|
85
|
+
* The `.vwld` asset is left alone: it may be large, nothing here deletes uploaded bytes, and a
|
|
86
|
+
* re-add is then free.
|
|
87
|
+
*/
|
|
88
|
+
export declare function planRemove(world: JsonObject, levelId: string): RemovePlan;
|