@bitmagic/cli 0.1.52-dev.1 → 0.1.52-dev.11
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 +217 -11
- package/dist/assets/add.d.ts +40 -0
- package/dist/assets/add.js +229 -0
- package/dist/assets/add.js.map +1 -0
- package/dist/assets/entry.d.ts +44 -0
- package/dist/assets/entry.js +71 -0
- package/dist/assets/entry.js.map +1 -0
- package/dist/assets/file-kind.d.ts +61 -0
- package/dist/assets/file-kind.js +195 -0
- package/dist/assets/file-kind.js.map +1 -0
- package/dist/assets/list.d.ts +27 -0
- package/dist/assets/list.js +50 -0
- package/dist/assets/list.js.map +1 -0
- package/dist/assets/remove.d.ts +50 -0
- package/dist/assets/remove.js +91 -0
- package/dist/assets/remove.js.map +1 -0
- package/dist/assets/voxelize-glb.d.ts +37 -0
- package/dist/assets/voxelize-glb.js +65 -0
- package/dist/assets/voxelize-glb.js.map +1 -0
- package/dist/assets/vxl-summary.d.ts +32 -0
- package/dist/assets/vxl-summary.js +118 -0
- package/dist/assets/vxl-summary.js.map +1 -0
- package/dist/bin.js +25 -0
- package/dist/bin.js.map +1 -1
- package/dist/cli.d.ts +12 -0
- package/dist/cli.js +15 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/assets.d.ts +56 -0
- package/dist/commands/assets.js +328 -0
- package/dist/commands/assets.js.map +1 -0
- package/dist/commands/cover.js +2 -3
- package/dist/commands/cover.js.map +1 -1
- package/dist/commands/forge.d.ts +2 -9
- package/dist/commands/forge.js +2 -13
- package/dist/commands/forge.js.map +1 -1
- package/dist/commands/generate.d.ts +41 -9
- package/dist/commands/generate.js +234 -54
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/judge.d.ts +7 -7
- package/dist/commands/judge.js +53 -25
- package/dist/commands/judge.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/commands/number-flag.d.ts +7 -0
- package/dist/commands/number-flag.js +38 -0
- package/dist/commands/number-flag.js.map +1 -0
- package/dist/commands/publish.d.ts +6 -1
- package/dist/commands/publish.js +42 -15
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/run-deps.d.ts +27 -0
- package/dist/commands/run-deps.js +43 -0
- package/dist/commands/run-deps.js.map +1 -0
- package/dist/commands/verify.d.ts +4 -0
- package/dist/commands/verify.js +94 -51
- package/dist/commands/verify.js.map +1 -1
- package/dist/editor/journal.d.ts +48 -1
- package/dist/editor/journal.js +44 -0
- package/dist/editor/journal.js.map +1 -1
- package/dist/editor/previews.d.ts +6 -0
- package/dist/editor/previews.js +16 -0
- package/dist/editor/previews.js.map +1 -1
- package/dist/editor/server.js +228 -53
- package/dist/editor/server.js.map +1 -1
- package/dist/editor/shell-page.js +221 -116
- package/dist/editor/shell-page.js.map +1 -1
- package/dist/editor/voxel-save.d.ts +47 -0
- package/dist/editor/voxel-save.js +49 -0
- package/dist/editor/voxel-save.js.map +1 -0
- package/dist/errors.d.ts +10 -0
- package/dist/errors.js +16 -0
- package/dist/errors.js.map +1 -1
- package/dist/forge/apply-modifications.d.ts +18 -1
- package/dist/forge/apply-modifications.js +15 -32
- package/dist/forge/apply-modifications.js.map +1 -1
- package/dist/forge/browser-host.js +9 -4
- package/dist/forge/browser-host.js.map +1 -1
- package/dist/forge/voxelize-session.d.ts +61 -0
- package/dist/forge/voxelize-session.js +137 -0
- package/dist/forge/voxelize-session.js.map +1 -0
- package/dist/generate/model.d.ts +36 -0
- package/dist/generate/model.js +90 -0
- package/dist/generate/model.js.map +1 -0
- package/dist/generate/prop.d.ts +52 -4
- package/dist/generate/prop.js +169 -102
- 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/generate/vehicle.js +5 -85
- package/dist/generate/vehicle.js.map +1 -1
- package/dist/http/signed-upload.d.ts +55 -0
- package/dist/http/signed-upload.js +168 -0
- package/dist/http/signed-upload.js.map +1 -0
- package/dist/judge/facts.js +72 -57
- package/dist/judge/facts.js.map +1 -1
- package/dist/judge/record.d.ts +3 -0
- package/dist/judge/record.js +3 -0
- package/dist/judge/record.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/project/jobs.d.ts +1 -1
- package/dist/project/jobs.js.map +1 -1
- package/dist/project/platform-declaration.d.ts +51 -0
- package/dist/project/platform-declaration.js +81 -0
- package/dist/project/platform-declaration.js.map +1 -0
- package/dist/publish/client.d.ts +13 -0
- package/dist/publish/client.js +13 -34
- package/dist/publish/client.js.map +1 -1
- package/dist/publish/platform.d.ts +42 -0
- package/dist/publish/platform.js +58 -0
- package/dist/publish/platform.js.map +1 -0
- package/dist/scaffold/project-files.js +124 -22
- package/dist/scaffold/project-files.js.map +1 -1
- package/dist/verify/artifacts.d.ts +19 -0
- package/dist/verify/artifacts.js +34 -0
- package/dist/verify/artifacts.js.map +1 -0
- package/dist/verify/browser.d.ts +10 -0
- package/dist/verify/browser.js +79 -9
- package/dist/verify/browser.js.map +1 -1
- package/dist/verify/classify.d.ts +37 -1
- package/dist/verify/classify.js +66 -2
- package/dist/verify/classify.js.map +1 -1
- package/dist/verify/device.d.ts +43 -0
- package/dist/verify/device.js +59 -0
- package/dist/verify/device.js.map +1 -0
- package/dist/verify/iterate.d.ts +21 -2
- package/dist/verify/iterate.js +43 -36
- package/dist/verify/iterate.js.map +1 -1
- package/dist/verify/mobile-parity.d.ts +42 -0
- package/dist/verify/mobile-parity.js +84 -0
- package/dist/verify/mobile-parity.js.map +1 -0
- package/dist/verify/platform.d.ts +47 -0
- package/dist/verify/platform.js +89 -0
- package/dist/verify/platform.js.map +1 -0
- package/dist/verify/result.d.ts +90 -6
- package/dist/verify/result.js +89 -10
- package/dist/verify/result.js.map +1 -1
- package/dist/verify/url.d.ts +9 -1
- package/dist/verify/url.js +10 -2
- package/dist/verify/url.js.map +1 -1
- package/package.json +4 -4
package/dist/commands/judge.js
CHANGED
|
@@ -27,11 +27,15 @@ import { resolveEnvironmentForCommand, resolveAuth0ClientId } from '../config/en
|
|
|
27
27
|
import { getAccessToken } from '../auth/session.js';
|
|
28
28
|
import { computeFingerprint } from '../publish/fingerprint.js';
|
|
29
29
|
import { readVerifyRecord } from '../verify/result.js';
|
|
30
|
+
import { verifyArtifactPaths } from '../verify/artifacts.js';
|
|
31
|
+
import { parseJudgePlatformArg, resolveJudgePlatform } from '../verify/platform.js';
|
|
32
|
+
import { readPlatformDeclaration } from '../project/platform-declaration.js';
|
|
30
33
|
import { requestJudge } from '../judge/stream.js';
|
|
31
34
|
import { buildSceneFacts, buildVerifyContext } from '../judge/facts.js';
|
|
32
35
|
import { judgeRecordPath, writeJudgeRecord } from '../judge/record.js';
|
|
33
36
|
import { GAME_DESIGN_FILE } from './cover.js';
|
|
34
37
|
import { createOutput } from '../output.js';
|
|
38
|
+
import { commandRunDeps } from './run-deps.js';
|
|
35
39
|
/** Where `bitmagic verify` writes its artifacts — see `commands/verify.ts`. */
|
|
36
40
|
function verifyArtifactDir(root) {
|
|
37
41
|
return path.join(root, '.bitmagic', 'verify');
|
|
@@ -53,15 +57,14 @@ function parseMinScoreArg(raw) {
|
|
|
53
57
|
}
|
|
54
58
|
return value;
|
|
55
59
|
}
|
|
56
|
-
function readConsoleTail(
|
|
57
|
-
let raw;
|
|
60
|
+
function readConsoleTail(consolePath) {
|
|
58
61
|
try {
|
|
59
|
-
raw = fs.readFileSync(
|
|
62
|
+
const raw = fs.readFileSync(consolePath, 'utf-8');
|
|
63
|
+
return raw.split('\n').slice(-CONSOLE_TAIL_LINES).join('\n');
|
|
60
64
|
}
|
|
61
65
|
catch {
|
|
62
66
|
return null;
|
|
63
67
|
}
|
|
64
|
-
return raw.split('\n').slice(-CONSOLE_TAIL_LINES).join('\n');
|
|
65
68
|
}
|
|
66
69
|
/** GAME-DESIGN.md's content, or empty — the rubric degrades gracefully without one. */
|
|
67
70
|
function readDesignText(root) {
|
|
@@ -72,6 +75,21 @@ function readDesignText(root) {
|
|
|
72
75
|
return '';
|
|
73
76
|
}
|
|
74
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Engine ground truth from world.json, read fresh because it is shared ground
|
|
80
|
+
* with the human's editor (see AGENTS.md). Undefined when it is missing or
|
|
81
|
+
* unreadable: the judge then grades from pixels alone, as it did before scene
|
|
82
|
+
* facts existed.
|
|
83
|
+
*/
|
|
84
|
+
function readSceneFacts(root) {
|
|
85
|
+
try {
|
|
86
|
+
const world = JSON.parse(fs.readFileSync(path.join(root, 'src', 'work', 'world.json'), 'utf-8'));
|
|
87
|
+
return buildSceneFacts(world) ?? undefined;
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
75
93
|
function renderScorecard(scorecard, model, sparks, log) {
|
|
76
94
|
log(`Judge verdict: ${scorecard.overall}/10 overall (${model}, ${sparks} sparks)`);
|
|
77
95
|
for (const dimension of scorecard.dimensions) {
|
|
@@ -82,17 +100,15 @@ function renderScorecard(scorecard, model, sparks, log) {
|
|
|
82
100
|
return;
|
|
83
101
|
}
|
|
84
102
|
log('Top findings:');
|
|
85
|
-
scorecard.topFindings.
|
|
103
|
+
for (const [index, finding] of scorecard.topFindings.entries()) {
|
|
86
104
|
log(` ${index + 1}. [${finding.severity}] ${finding.title}`);
|
|
87
105
|
log(` ${finding.detail}`);
|
|
88
|
-
}
|
|
106
|
+
}
|
|
89
107
|
}
|
|
90
108
|
function defaultDeps(json) {
|
|
91
109
|
const output = createOutput(json);
|
|
92
110
|
return {
|
|
93
|
-
|
|
94
|
-
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
95
|
-
log: output.info,
|
|
111
|
+
...commandRunDeps(json),
|
|
96
112
|
result: output.result,
|
|
97
113
|
request: requestJudge,
|
|
98
114
|
};
|
|
@@ -103,14 +119,20 @@ export async function runJudge(args, deps = defaultDeps(args.json === true)) {
|
|
|
103
119
|
const minScore = parseMinScoreArg(args['min-score']);
|
|
104
120
|
const genre = args.genre?.trim() || undefined;
|
|
105
121
|
const artifactDir = verifyArtifactDir(root);
|
|
106
|
-
const
|
|
122
|
+
const declaration = readPlatformDeclaration(root);
|
|
123
|
+
const platform = resolveJudgePlatform(parseJudgePlatformArg(args.platform), declaration, fs.existsSync(verifyArtifactPaths(artifactDir, 'mobile').screenshotPath));
|
|
124
|
+
const paths = verifyArtifactPaths(artifactDir, platform);
|
|
125
|
+
const screenshotFile = paths.screenshotPath;
|
|
107
126
|
let screenshot;
|
|
108
127
|
try {
|
|
109
128
|
screenshot = fs.readFileSync(screenshotFile);
|
|
110
129
|
}
|
|
111
130
|
catch {
|
|
131
|
+
// Name the command that produces THIS frame: telling someone whose phone game has no mobile
|
|
132
|
+
// screenshot to "run bitmagic verify" is advice that produces the wrong file.
|
|
133
|
+
const verifyCommand = platform === 'mobile' ? 'bitmagic verify --platform mobile' : 'bitmagic verify';
|
|
112
134
|
throw new CliError(`No verify screenshot at ${screenshotFile}. The judge grades the frame \`bitmagic verify\` ` +
|
|
113
|
-
|
|
135
|
+
`captures, so run \`${verifyCommand}\` first — without --fast, which skips the screenshot.`);
|
|
114
136
|
}
|
|
115
137
|
// Staleness is a warning, not a refusal: judging yesterday's frame is
|
|
116
138
|
// sometimes exactly what was asked for, but it must never pass silently as
|
|
@@ -122,18 +144,13 @@ export async function runJudge(args, deps = defaultDeps(args.json === true)) {
|
|
|
122
144
|
deps.log('The project has changed since this screenshot was taken — the verdict is about the older ' +
|
|
123
145
|
'build. Re-run `bitmagic verify` first for a current one.');
|
|
124
146
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
catch {
|
|
133
|
-
sceneFacts = undefined;
|
|
134
|
-
}
|
|
135
|
-
const rubric = buildJudgeRubric({ designText: readDesignText(root), genre, sceneFacts });
|
|
136
|
-
const verifyContext = buildVerifyContext(verifyRecord, readConsoleTail(artifactDir));
|
|
147
|
+
const rubric = buildJudgeRubric({
|
|
148
|
+
designText: readDesignText(root),
|
|
149
|
+
genre,
|
|
150
|
+
platform,
|
|
151
|
+
sceneFacts: readSceneFacts(root),
|
|
152
|
+
});
|
|
153
|
+
const verifyContext = buildVerifyContext(verifyRecord, readConsoleTail(paths.consolePath));
|
|
137
154
|
const environment = resolveEnvironmentForCommand({ cwd: root, baseDir: deps.baseDir });
|
|
138
155
|
const clientId = resolveAuth0ClientId(environment);
|
|
139
156
|
const token = await getAccessToken(environment, clientId, { fetch: deps.fetch, sleep: deps.sleep, now: deps.now }, deps.baseDir);
|
|
@@ -143,8 +160,11 @@ export async function runJudge(args, deps = defaultDeps(args.json === true)) {
|
|
|
143
160
|
...(verifyContext !== null ? { verifyContext } : {}),
|
|
144
161
|
images: [{ dataBase64: screenshot.toString('base64'), mediaType: 'image/png' }],
|
|
145
162
|
};
|
|
146
|
-
|
|
147
|
-
|
|
163
|
+
// The label names the frame, so `.bitmagic/jobs/` shows WHICH screen was graded — two judges
|
|
164
|
+
// of the same game on different platforms are otherwise indistinguishable in that list.
|
|
165
|
+
const label = `Quality judge (${[platform, genre].filter(Boolean).join(', ')})`;
|
|
166
|
+
await withJobRecord({ root, kind: 'judge', label, log: deps.log }, async (log) => {
|
|
167
|
+
log(`Judging the ${platform} frame of game ${context.metadata.gameId} from ${path.relative(root, screenshotFile) || screenshotFile}...`);
|
|
148
168
|
const outcome = await deps.request(environment, token, body, {
|
|
149
169
|
fetch: deps.fetch,
|
|
150
170
|
onProgress: log,
|
|
@@ -158,6 +178,7 @@ export async function runJudge(args, deps = defaultDeps(args.json === true)) {
|
|
|
158
178
|
at: new Date().toISOString(),
|
|
159
179
|
model: outcome.model,
|
|
160
180
|
screenshotPath: path.relative(root, screenshotFile),
|
|
181
|
+
platform,
|
|
161
182
|
...(genre !== undefined ? { genre } : {}),
|
|
162
183
|
});
|
|
163
184
|
renderScorecard(outcome.scorecard, outcome.model, outcome.sparks, log);
|
|
@@ -171,6 +192,7 @@ export async function runJudge(args, deps = defaultDeps(args.json === true)) {
|
|
|
171
192
|
}
|
|
172
193
|
deps.result({
|
|
173
194
|
ok: true,
|
|
195
|
+
platform,
|
|
174
196
|
scorecard: outcome.scorecard,
|
|
175
197
|
judgePath: judgeRecordPath(root),
|
|
176
198
|
fingerprintStale,
|
|
@@ -189,6 +211,11 @@ export const judgeCommand = defineCommand({
|
|
|
189
211
|
type: 'string',
|
|
190
212
|
description: 'Genre hint for the rubric: platformer, racing, shooter, combat, driving, tower-defense.',
|
|
191
213
|
},
|
|
214
|
+
platform: {
|
|
215
|
+
type: 'string',
|
|
216
|
+
description: 'Which frame to grade: desktop or mobile. Defaults to mobile when '
|
|
217
|
+
+ 'src/work/game.json declares primaryPlatform "mobile" and a mobile screenshot exists.',
|
|
218
|
+
},
|
|
192
219
|
'min-score': {
|
|
193
220
|
type: 'string',
|
|
194
221
|
description: `Fail (exit ${EXIT_BELOW_MIN_SCORE}) when the overall score is below this 1-10 bar. Without it the judge informs and exits 0.`,
|
|
@@ -201,6 +228,7 @@ export const judgeCommand = defineCommand({
|
|
|
201
228
|
async run({ args }) {
|
|
202
229
|
await runJudge({
|
|
203
230
|
genre: args.genre,
|
|
231
|
+
platform: args.platform,
|
|
204
232
|
'min-score': args['min-score'],
|
|
205
233
|
json: args.json,
|
|
206
234
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"judge.js","sourceRoot":"","sources":["../../src/commands/judge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAuB,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,4BAA4B,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAC/F,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"judge.js","sourceRoot":"","sources":["../../src/commands/judge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type CommandRunDeps } from './run-deps.js';
|
|
2
|
+
import { type LevelRow } from '../levels/registry.js';
|
|
3
|
+
export interface LevelsRunDeps extends CommandRunDeps {
|
|
4
|
+
}
|
|
5
|
+
export declare function formatLevelTable(rows: LevelRow[]): string;
|
|
6
|
+
export declare function runLevelsList(options: {
|
|
7
|
+
json: boolean;
|
|
8
|
+
deps?: LevelsRunDeps;
|
|
9
|
+
}): Promise<LevelRow[]>;
|
|
10
|
+
export declare function runLevelsSetStart(options: {
|
|
11
|
+
levelId: string;
|
|
12
|
+
json: boolean;
|
|
13
|
+
deps?: LevelsRunDeps;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
export declare function runLevelsRename(options: {
|
|
16
|
+
levelId: string;
|
|
17
|
+
name: string;
|
|
18
|
+
json: boolean;
|
|
19
|
+
deps?: LevelsRunDeps;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
export declare function runLevelsAdd(options: {
|
|
22
|
+
vwldAssetId: string;
|
|
23
|
+
name?: string;
|
|
24
|
+
makeStart: boolean;
|
|
25
|
+
json: boolean;
|
|
26
|
+
deps?: LevelsRunDeps;
|
|
27
|
+
}): Promise<void>;
|
|
28
|
+
export declare function runLevelsRemove(options: {
|
|
29
|
+
levelId: string;
|
|
30
|
+
json: boolean;
|
|
31
|
+
deps?: LevelsRunDeps;
|
|
32
|
+
}): Promise<void>;
|
|
33
|
+
export declare const levelsCommand: import("citty").CommandDef<import("citty").ArgsDef>;
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `bitmagic levels list | add | rename | set-start | remove` — manage the levels `forge` creates.
|
|
3
|
+
*
|
|
4
|
+
* `forge` could make levels but not manage them, so fixing a wrong start level, renaming one, or
|
|
5
|
+
* deleting one meant opening the web Creator. The registry is a local file in the pro lane, so
|
|
6
|
+
* these are direct surgical `world.json` edits — no server call, no sparks, no login.
|
|
7
|
+
*
|
|
8
|
+
* The rules live in `levels/registry.ts`; this file is flags and output.
|
|
9
|
+
*/
|
|
10
|
+
import { defineCommand } from 'citty';
|
|
11
|
+
import { createOutput } from '../output.js';
|
|
12
|
+
import { commandRunDeps, decoratedError } from './run-deps.js';
|
|
13
|
+
import { loadProjectContext } from '../project/context.js';
|
|
14
|
+
import { readWorldJson } from '../project/world-json.js';
|
|
15
|
+
import { applyModificationsToWorld } from '../forge/apply-modifications.js';
|
|
16
|
+
import { projectWorldJsonPath } from '../forge/run-pipeline.js';
|
|
17
|
+
import { EditorJournal } from '../editor/journal.js';
|
|
18
|
+
import { listLevels, planAdd, planRemove, planRename, planSetStart, } from '../levels/registry.js';
|
|
19
|
+
const defaultDeps = (json) => commandRunDeps(json);
|
|
20
|
+
/** Appends the unchanged-world guarantee unless the message already makes it. */
|
|
21
|
+
function unchanged(message) {
|
|
22
|
+
return message.includes('world.json is unchanged') ? message : `${message} world.json is unchanged.`;
|
|
23
|
+
}
|
|
24
|
+
/** Resolve the project and read its world.json, with every failure carrying the guarantee. */
|
|
25
|
+
function readProject(runDeps) {
|
|
26
|
+
try {
|
|
27
|
+
const context = loadProjectContext(runDeps.startDir);
|
|
28
|
+
return { context, world: readWorldJson(projectWorldJsonPath(context.root)) };
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
throw decoratedError(error, unchanged);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Apply a plan, journal it, and report.
|
|
36
|
+
*
|
|
37
|
+
* The journal entry is what makes this visible to the creator's agent: a level change moves one id
|
|
38
|
+
* and a url, which is exactly the kind of edit a diff of placed objects cannot explain.
|
|
39
|
+
*/
|
|
40
|
+
function commit(context, plan, subject, journalLine, runDeps) {
|
|
41
|
+
const worldPath = projectWorldJsonPath(context.root);
|
|
42
|
+
let applied;
|
|
43
|
+
try {
|
|
44
|
+
applied = applyModificationsToWorld(worldPath, plan.modifications, { subject }).applied;
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
throw decoratedError(error, unchanged);
|
|
48
|
+
}
|
|
49
|
+
// After the write, never before: an agent reading the line must be able to trust world.json.
|
|
50
|
+
new EditorJournal({ root: context.root }).append(journalLine);
|
|
51
|
+
for (const note of plan.notes)
|
|
52
|
+
runDeps.log(`note: ${note}`);
|
|
53
|
+
return applied;
|
|
54
|
+
}
|
|
55
|
+
function reloadHint(runDeps) {
|
|
56
|
+
runDeps.log('A running `bitmagic dev` reloads the browser by itself to show it.');
|
|
57
|
+
}
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// list
|
|
60
|
+
// ============================================================================
|
|
61
|
+
export function formatLevelTable(rows) {
|
|
62
|
+
if (rows.length === 0) {
|
|
63
|
+
return 'This game has no levels. `bitmagic forge` bakes one, or `bitmagic levels add <vwldAssetId>`\n'
|
|
64
|
+
+ 'registers a bake you already have.';
|
|
65
|
+
}
|
|
66
|
+
const header = { id: 'ID', name: 'NAME', start: '', spawns: 'SPAWNS', placed: 'PLACED', note: '' };
|
|
67
|
+
const cells = rows.map((row) => ({
|
|
68
|
+
id: row.id,
|
|
69
|
+
name: row.name,
|
|
70
|
+
start: row.start ? 'START' : '',
|
|
71
|
+
spawns: String(row.spawnPoints),
|
|
72
|
+
placed: String(row.placed),
|
|
73
|
+
note: row.missingAsset ? 'missing .vwld asset' : '',
|
|
74
|
+
}));
|
|
75
|
+
const width = (key) => Math.max(header[key].length, ...cells.map((cell) => cell[key].length));
|
|
76
|
+
const w = { id: width('id'), name: width('name'), start: width('start'), spawns: width('spawns'), placed: width('placed') };
|
|
77
|
+
const line = (cell) => `${cell.id.padEnd(w.id)} ${cell.name.padEnd(w.name)} ${cell.start.padEnd(w.start)} `
|
|
78
|
+
+ `${cell.spawns.padStart(w.spawns)} ${cell.placed.padStart(w.placed)} ${cell.note}`.trimEnd();
|
|
79
|
+
return [line(header), ...cells.map(line)].join('\n');
|
|
80
|
+
}
|
|
81
|
+
export async function runLevelsList(options) {
|
|
82
|
+
const output = createOutput(options.json);
|
|
83
|
+
const runDeps = options.deps ?? defaultDeps(options.json);
|
|
84
|
+
const { world } = readProject(runDeps);
|
|
85
|
+
const rows = listLevels(world);
|
|
86
|
+
if (options.json)
|
|
87
|
+
output.result({ ok: true, count: rows.length, levels: rows });
|
|
88
|
+
else
|
|
89
|
+
runDeps.log(formatLevelTable(rows));
|
|
90
|
+
return rows;
|
|
91
|
+
}
|
|
92
|
+
// ============================================================================
|
|
93
|
+
// the four writes
|
|
94
|
+
// ============================================================================
|
|
95
|
+
export async function runLevelsSetStart(options) {
|
|
96
|
+
const output = createOutput(options.json);
|
|
97
|
+
const runDeps = options.deps ?? defaultDeps(options.json);
|
|
98
|
+
const { context, world } = readProject(runDeps);
|
|
99
|
+
const plan = planSetStart(world, options.levelId);
|
|
100
|
+
const name = listLevels(world).find((row) => row.id === options.levelId)?.name ?? options.levelId;
|
|
101
|
+
commit(context, plan, 'The start level', {
|
|
102
|
+
event: 'levels.changed', action: 'set-start', levelId: options.levelId, name,
|
|
103
|
+
}, runDeps);
|
|
104
|
+
runDeps.log(`"${name}" is now the start level — the game boots into it.`);
|
|
105
|
+
output.result({ ok: true, kind: 'levels', action: 'set-start', levelId: options.levelId, name });
|
|
106
|
+
reloadHint(runDeps);
|
|
107
|
+
}
|
|
108
|
+
export async function runLevelsRename(options) {
|
|
109
|
+
const output = createOutput(options.json);
|
|
110
|
+
const runDeps = options.deps ?? defaultDeps(options.json);
|
|
111
|
+
const { context, world } = readProject(runDeps);
|
|
112
|
+
const plan = planRename(world, options.levelId, options.name);
|
|
113
|
+
const previous = listLevels(world).find((row) => row.id === options.levelId)?.name ?? options.levelId;
|
|
114
|
+
commit(context, plan, 'The level name', {
|
|
115
|
+
event: 'levels.changed', action: 'rename', levelId: options.levelId, name: options.name.trim(),
|
|
116
|
+
}, runDeps);
|
|
117
|
+
runDeps.log(`Renamed "${previous}" to "${options.name.trim()}".`);
|
|
118
|
+
output.result({
|
|
119
|
+
ok: true, kind: 'levels', action: 'rename', levelId: options.levelId, name: options.name.trim(), previous,
|
|
120
|
+
});
|
|
121
|
+
reloadHint(runDeps);
|
|
122
|
+
}
|
|
123
|
+
export async function runLevelsAdd(options) {
|
|
124
|
+
const output = createOutput(options.json);
|
|
125
|
+
const runDeps = options.deps ?? defaultDeps(options.json);
|
|
126
|
+
const { context, world } = readProject(runDeps);
|
|
127
|
+
const plan = planAdd(world, options.vwldAssetId, {
|
|
128
|
+
...(options.name !== undefined ? { name: options.name } : {}),
|
|
129
|
+
makeStart: options.makeStart,
|
|
130
|
+
});
|
|
131
|
+
commit(context, plan, 'The new level', {
|
|
132
|
+
event: 'levels.changed', action: 'add', levelId: plan.level.id, name: plan.level.name,
|
|
133
|
+
}, runDeps);
|
|
134
|
+
runDeps.log(`Added level "${plan.level.name}" (${plan.level.id}).`);
|
|
135
|
+
output.result({
|
|
136
|
+
ok: true, kind: 'levels', action: 'add', levelId: plan.level.id, name: plan.level.name,
|
|
137
|
+
vwldAssetId: options.vwldAssetId, converted: plan.converted,
|
|
138
|
+
});
|
|
139
|
+
reloadHint(runDeps);
|
|
140
|
+
}
|
|
141
|
+
export async function runLevelsRemove(options) {
|
|
142
|
+
const output = createOutput(options.json);
|
|
143
|
+
const runDeps = options.deps ?? defaultDeps(options.json);
|
|
144
|
+
const { context, world } = readProject(runDeps);
|
|
145
|
+
const plan = planRemove(world, options.levelId);
|
|
146
|
+
commit(context, plan, 'Removing the level', {
|
|
147
|
+
event: 'levels.changed', action: 'remove', levelId: options.levelId, name: plan.level.name,
|
|
148
|
+
}, runDeps);
|
|
149
|
+
runDeps.log(`Removed level "${plan.level.name}" (${options.levelId}). Its .vwld asset stays in the project.`);
|
|
150
|
+
output.result({
|
|
151
|
+
ok: true, kind: 'levels', action: 'remove', levelId: options.levelId, name: plan.level.name,
|
|
152
|
+
placedRemoved: plan.placedRemoved,
|
|
153
|
+
});
|
|
154
|
+
reloadHint(runDeps);
|
|
155
|
+
}
|
|
156
|
+
// ============================================================================
|
|
157
|
+
// Subcommands
|
|
158
|
+
// ============================================================================
|
|
159
|
+
const JSON_FLAG = {
|
|
160
|
+
type: 'boolean',
|
|
161
|
+
description: 'Print the result as JSON on stdout; all progress goes to stderr.',
|
|
162
|
+
};
|
|
163
|
+
const listCommand = defineCommand({
|
|
164
|
+
meta: { name: 'list', description: 'List the game\'s levels: id, name, which one boots, spawn and object counts.' },
|
|
165
|
+
args: { json: JSON_FLAG },
|
|
166
|
+
async run({ args }) {
|
|
167
|
+
await runLevelsList({ json: args.json === true });
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
const setStartCommand = defineCommand({
|
|
171
|
+
meta: { name: 'set-start', description: 'Make a level the one the game boots into.' },
|
|
172
|
+
args: {
|
|
173
|
+
'level-id': { type: 'positional', required: true, description: 'The level id (see `bitmagic levels list`).' },
|
|
174
|
+
json: JSON_FLAG,
|
|
175
|
+
},
|
|
176
|
+
async run({ args }) {
|
|
177
|
+
await runLevelsSetStart({ levelId: args['level-id'], json: args.json === true });
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
const renameCommand = defineCommand({
|
|
181
|
+
meta: { name: 'rename', description: 'Rename a level. Names are for humans; ids are what code uses.' },
|
|
182
|
+
args: {
|
|
183
|
+
'level-id': { type: 'positional', required: true, description: 'The level id (see `bitmagic levels list`).' },
|
|
184
|
+
name: { type: 'positional', required: true, description: 'The new name.' },
|
|
185
|
+
json: JSON_FLAG,
|
|
186
|
+
},
|
|
187
|
+
async run({ args }) {
|
|
188
|
+
await runLevelsRename({ levelId: args['level-id'], name: args.name, json: args.json === true });
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
const addCommand = defineCommand({
|
|
192
|
+
meta: { name: 'add', description: 'Register a baked .vwld asset as a level.' },
|
|
193
|
+
args: {
|
|
194
|
+
'vwld-asset-id': {
|
|
195
|
+
type: 'positional',
|
|
196
|
+
required: true,
|
|
197
|
+
description: 'Id of a .vwld asset already in the project (see `bitmagic assets list`).',
|
|
198
|
+
},
|
|
199
|
+
name: { type: 'string', description: 'Level name; defaults to the asset\'s name.' },
|
|
200
|
+
'make-start': {
|
|
201
|
+
type: 'boolean',
|
|
202
|
+
description: 'Also make it the level the game boots into. A game\'s first level becomes the start anyway.',
|
|
203
|
+
},
|
|
204
|
+
json: JSON_FLAG,
|
|
205
|
+
},
|
|
206
|
+
async run({ args }) {
|
|
207
|
+
await runLevelsAdd({
|
|
208
|
+
vwldAssetId: args['vwld-asset-id'],
|
|
209
|
+
...(args.name !== undefined ? { name: args.name } : {}),
|
|
210
|
+
makeStart: args['make-start'] === true,
|
|
211
|
+
json: args.json === true,
|
|
212
|
+
});
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
const removeCommand = defineCommand({
|
|
216
|
+
meta: {
|
|
217
|
+
name: 'remove',
|
|
218
|
+
description: 'Remove a level and the objects belonging to it. The .vwld asset stays in the project.',
|
|
219
|
+
},
|
|
220
|
+
args: {
|
|
221
|
+
'level-id': { type: 'positional', required: true, description: 'The level id (see `bitmagic levels list`).' },
|
|
222
|
+
json: JSON_FLAG,
|
|
223
|
+
},
|
|
224
|
+
async run({ args }) {
|
|
225
|
+
await runLevelsRemove({ levelId: args['level-id'], json: args.json === true });
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
export const levelsCommand = defineCommand({
|
|
229
|
+
meta: {
|
|
230
|
+
name: 'levels',
|
|
231
|
+
description: 'Manage the levels `bitmagic forge` creates: list, add, rename, set-start, remove.',
|
|
232
|
+
},
|
|
233
|
+
subCommands: {
|
|
234
|
+
list: listCommand,
|
|
235
|
+
add: addCommand,
|
|
236
|
+
rename: renameCommand,
|
|
237
|
+
'set-start': setStartCommand,
|
|
238
|
+
remove: removeCommand,
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
//# sourceMappingURL=levels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"levels.js","sourceRoot":"","sources":["../../src/commands/levels.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAuB,MAAM,eAAe,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAuB,MAAM,uBAAuB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAmB,MAAM,0BAA0B,CAAC;AAC1E,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EACL,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,GAC1D,MAAM,uBAAuB,CAAC;AAI/B,MAAM,WAAW,GAAG,CAAC,IAAa,EAAiB,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AAE3E,iFAAiF;AACjF,SAAS,SAAS,CAAC,OAAe;IAChC,OAAO,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,2BAA2B,CAAC;AACvG,CAAC;AAED,8FAA8F;AAC9F,SAAS,WAAW,CAAC,OAAsB;IACzC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACrD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,CAAC,oBAAoB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;IAC/E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,cAAc,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACzC,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,MAAM,CACb,OAAuB,EACvB,IAAe,EACf,OAAe,EACf,WAAuF,EACvF,OAAsB;IAEtB,MAAM,SAAS,GAAG,oBAAoB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,yBAAyB,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC;IAC1F,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,cAAc,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACzC,CAAC;IACD,6FAA6F;IAC7F,IAAI,aAAa,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC9D,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IAC5D,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,UAAU,CAAC,OAAsB;IACxC,OAAO,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAC;AACpF,CAAC;AAED,+EAA+E;AAC/E,OAAO;AACP,+EAA+E;AAE/E,MAAM,UAAU,gBAAgB,CAAC,IAAgB;IAC/C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,+FAA+F;cAClG,oCAAoC,CAAC;IAC3C,CAAC;IACD,MAAM,MAAM,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IACnG,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC/B,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;QAC/B,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC;QAC/B,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;QAC1B,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAAE;KACpD,CAAC,CAAC,CAAC;IACJ,MAAM,KAAK,GAAG,CAAC,GAAwB,EAAU,EAAE,CACjD,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACzE,MAAM,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC5H,MAAM,IAAI,GAAG,CAAC,IAAmB,EAAU,EAAE,CAC3C,GAAG,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;UACrF,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;IACnG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAgD;IAClF,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,OAAO,CAAC,IAAI;QAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;;QAC3E,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;IACzC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,+EAA+E;AAC/E,kBAAkB;AAClB,+EAA+E;AAE/E,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAiE;IACvG,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAClG,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE;QACvC,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI;KAC7E,EAAE,OAAO,CAAC,CAAC;IACZ,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,oDAAoD,CAAC,CAAC;IAC1E,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACjG,UAAU,CAAC,OAAO,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAA+E;IAE/E,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IACtG,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE;QACtC,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE;KAC/F,EAAE,OAAO,CAAC,CAAC;IACZ,OAAO,CAAC,GAAG,CAAC,YAAY,QAAQ,SAAS,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAClE,MAAM,CAAC,MAAM,CAAC;QACZ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ;KAC1G,CAAC,CAAC;IACH,UAAU,CAAC,OAAO,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAwG;IAExG,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,EAAE;QAC/C,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC,CAAC;IACH,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE;QACrC,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;KACtF,EAAE,OAAO,CAAC,CAAC;IACZ,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,CAAC,KAAK,CAAC,IAAI,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;IACpE,MAAM,CAAC,MAAM,CAAC;QACZ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;QACtF,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS;KAC5D,CAAC,CAAC;IACH,UAAU,CAAC,OAAO,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAiE;IACrG,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,oBAAoB,EAAE;QAC1C,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;KAC3F,EAAE,OAAO,CAAC,CAAC;IACZ,OAAO,CAAC,GAAG,CACT,kBAAkB,IAAI,CAAC,KAAK,CAAC,IAAI,MAAM,OAAO,CAAC,OAAO,0CAA0C,CACjG,CAAC;IACF,MAAM,CAAC,MAAM,CAAC;QACZ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;QAC3F,aAAa,EAAE,IAAI,CAAC,aAAa;KAClC,CAAC,CAAC;IACH,UAAU,CAAC,OAAO,CAAC,CAAC;AACtB,CAAC;AAED,+EAA+E;AAC/E,cAAc;AACd,+EAA+E;AAE/E,MAAM,SAAS,GAAG;IAChB,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,kEAAkE;CACvE,CAAC;AAEX,MAAM,WAAW,GAAG,aAAa,CAAC;IAChC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,8EAA8E,EAAE;IACnH,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;IACzB,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAChB,MAAM,aAAa,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,eAAe,GAAG,aAAa,CAAC;IACpC,IAAI,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,2CAA2C,EAAE;IACrF,IAAI,EAAE;QACJ,UAAU,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4CAA4C,EAAE;QAC7G,IAAI,EAAE,SAAS;KAChB;IACD,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAChB,MAAM,iBAAiB,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC;IACnF,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,aAAa,CAAC;IAClC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+DAA+D,EAAE;IACtG,IAAI,EAAE;QACJ,UAAU,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4CAA4C,EAAE;QAC7G,IAAI,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,eAAe,EAAE;QAC1E,IAAI,EAAE,SAAS;KAChB;IACD,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAChB,MAAM,eAAe,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC;IAClG,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,aAAa,CAAC;IAC/B,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,0CAA0C,EAAE;IAC9E,IAAI,EAAE;QACJ,eAAe,EAAE;YACf,IAAI,EAAE,YAAY;YAClB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,0EAA0E;SACxF;QACD,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,4CAA4C,EAAE;QACnF,YAAY,EAAE;YACZ,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,6FAA6F;SAC3G;QACD,IAAI,EAAE,SAAS;KAChB;IACD,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAChB,MAAM,YAAY,CAAC;YACjB,WAAW,EAAE,IAAI,CAAC,eAAe,CAAC;YAClC,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvD,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,KAAK,IAAI;YACtC,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,IAAI;SACzB,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,aAAa,CAAC;IAClC,IAAI,EAAE;QACJ,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,uFAAuF;KACrG;IACD,IAAI,EAAE;QACJ,UAAU,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4CAA4C,EAAE;QAC7G,IAAI,EAAE,SAAS;KAChB;IACD,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAChB,MAAM,eAAe,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC;IACjF,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC;IACzC,IAAI,EAAE;QACJ,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,mFAAmF;KACjG;IACD,WAAW,EAAE;QACX,IAAI,EAAE,WAAW;QACjB,GAAG,EAAE,UAAU;QACf,MAAM,EAAE,aAAa;QACrB,WAAW,EAAE,eAAe;QAC5B,MAAM,EAAE,aAAa;KACtB;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface NumberFlagOptions {
|
|
2
|
+
min?: number;
|
|
3
|
+
max?: number;
|
|
4
|
+
/** Only for flags whose generator schema declares `.int()` (image width/height). */
|
|
5
|
+
integer?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function parseNumberFlag(flagName: string, raw: string | undefined, options?: NumberFlagOptions): number | undefined;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one numeric-flag parser every command uses.
|
|
3
|
+
*
|
|
4
|
+
* It exists because `verify.ts --timeout` once shipped a bug where an unparseable value silently
|
|
5
|
+
* became `NaN` and produced a false failure pointing nowhere near the real cause. Every numeric
|
|
6
|
+
* flag goes through here so a typo is rejected up front, naming the flag.
|
|
7
|
+
*
|
|
8
|
+
* It is SHARED because a second copy re-opened that exact hazard: `commands/assets.ts` was written
|
|
9
|
+
* with a stricter version while `commands/generate.ts` kept the lax one, so `generate model
|
|
10
|
+
* --height 0x10` quietly scaled a model to 16 metres — `Number()` accepts hex, binary, exponents
|
|
11
|
+
* and surrounding whitespace, and `Number('')` is 0. One decimal-only grammar, one place.
|
|
12
|
+
*/
|
|
13
|
+
import { CliError } from '../errors.js';
|
|
14
|
+
/** A decimal number and nothing else — no `0x10`, no `1e3`, no `''`. */
|
|
15
|
+
const DECIMAL = /^-?\d+(\.\d+)?$/;
|
|
16
|
+
export function parseNumberFlag(flagName, raw, options = {}) {
|
|
17
|
+
if (raw === undefined)
|
|
18
|
+
return undefined;
|
|
19
|
+
const trimmed = raw.trim();
|
|
20
|
+
if (!DECIMAL.test(trimmed)) {
|
|
21
|
+
throw new CliError(`--${flagName} must be a decimal number, got ${JSON.stringify(raw)}. world.json is unchanged.`);
|
|
22
|
+
}
|
|
23
|
+
const value = Number(trimmed);
|
|
24
|
+
if (!Number.isFinite(value)) {
|
|
25
|
+
throw new CliError(`--${flagName} must be a number, got ${JSON.stringify(raw)}. world.json is unchanged.`);
|
|
26
|
+
}
|
|
27
|
+
if (options.integer && !Number.isInteger(value)) {
|
|
28
|
+
throw new CliError(`--${flagName} must be a whole number, got ${JSON.stringify(raw)}. world.json is unchanged.`);
|
|
29
|
+
}
|
|
30
|
+
if (options.min !== undefined && value < options.min) {
|
|
31
|
+
throw new CliError(`--${flagName} must be at least ${options.min}, got ${value}. world.json is unchanged.`);
|
|
32
|
+
}
|
|
33
|
+
if (options.max !== undefined && value > options.max) {
|
|
34
|
+
throw new CliError(`--${flagName} must be at most ${options.max}, got ${value}. world.json is unchanged.`);
|
|
35
|
+
}
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=number-flag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"number-flag.js","sourceRoot":"","sources":["../../src/commands/number-flag.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AASxC,wEAAwE;AACxE,MAAM,OAAO,GAAG,iBAAiB,CAAC;AAElC,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,GAAuB,EACvB,UAA6B,EAAE;IAE/B,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,QAAQ,CAAC,KAAK,QAAQ,kCAAkC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IACrH,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,QAAQ,CAAC,KAAK,QAAQ,0BAA0B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC7G,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,QAAQ,CAAC,KAAK,QAAQ,gCAAgC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IACnH,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QACrD,MAAM,IAAI,QAAQ,CAAC,KAAK,QAAQ,qBAAqB,OAAO,CAAC,GAAG,SAAS,KAAK,4BAA4B,CAAC,CAAC;IAC9G,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QACrD,MAAM,IAAI,QAAQ,CAAC,KAAK,QAAQ,oBAAoB,OAAO,CAAC,GAAG,SAAS,KAAK,4BAA4B,CAAC,CAAC;IAC7G,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -52,7 +52,12 @@ interface ThumbnailSource {
|
|
|
52
52
|
* screenshot remains the fallback rather than being retired, because `bitmagic cover` costs sparks
|
|
53
53
|
* and is optional — a creator who never runs it must still be able to publish.
|
|
54
54
|
*
|
|
55
|
-
*
|
|
55
|
+
* Between the two screenshots, the one matching the game's OWN platform wins: `bitmagic verify`
|
|
56
|
+
* boots a mobile-primary game as a phone by default and then writes only `screenshot.mobile.png`,
|
|
57
|
+
* so preferring the desktop file would both pick a picture the game is not about and, on a
|
|
58
|
+
* mobile-only project, find nothing at all.
|
|
59
|
+
*
|
|
60
|
+
* Returns null when none of the three exists, which the caller turns into exit 3.
|
|
56
61
|
*/
|
|
57
62
|
export declare function resolveThumbnailSource(root: string, readFile?: (file: string) => Buffer): ThumbnailSource | null;
|
|
58
63
|
/**
|