@bitmagic/cli 0.1.64-dev.1 → 0.1.64-dev.10
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 +80 -5
- package/assets/blender-level/README.md +25 -0
- package/assets/blender-level/audit.py +232 -0
- package/assets/blender-level/bmlevel/__init__.py +294 -0
- package/assets/blender-level/bmlevel/core.py +438 -0
- package/assets/blender-level/bmlevel/scene_bpy.py +186 -0
- package/assets/blender-level/bmlevel/scene_null.py +44 -0
- package/assets/blender-level/example_level.py +80 -0
- package/assets/blender-level/find_blender.py +62 -0
- package/assets/blender-level/review.py +117 -0
- package/assets/blender-level/sync_world.py +85 -0
- package/assets/blender-level/tests/test_core.py +189 -0
- package/dist/assets/keep-glb.d.ts +20 -0
- package/dist/assets/keep-glb.js +45 -0
- package/dist/assets/keep-glb.js.map +1 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/assets.d.ts +3 -0
- package/dist/commands/assets.js +33 -3
- package/dist/commands/assets.js.map +1 -1
- package/dist/commands/cover.js +7 -1
- package/dist/commands/cover.js.map +1 -1
- package/dist/commands/forge.js +70 -11
- package/dist/commands/forge.js.map +1 -1
- package/dist/commands/generate.d.ts +88 -1
- package/dist/commands/generate.js +400 -21
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/init.js +33 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/judge.d.ts +0 -11
- package/dist/commands/judge.js +15 -2
- package/dist/commands/judge.js.map +1 -1
- package/dist/commands/levels.d.ts +1 -1
- package/dist/commands/levels.js +14 -3
- package/dist/commands/levels.js.map +1 -1
- package/dist/commands/reference.js +5 -1
- package/dist/commands/reference.js.map +1 -1
- package/dist/commands/reset-account.js +2 -11
- package/dist/commands/reset-account.js.map +1 -1
- package/dist/commands/tools.d.ts +1 -0
- package/dist/commands/tools.js +73 -0
- package/dist/commands/tools.js.map +1 -0
- package/dist/commands/trailer.js +18 -4
- package/dist/commands/trailer.js.map +1 -1
- package/dist/editor/asset-detail-panel.d.ts +8 -3
- package/dist/editor/asset-detail-panel.js +11 -1
- package/dist/editor/asset-detail-panel.js.map +1 -1
- package/dist/editor/hud-replay-page.js +317 -22
- package/dist/editor/hud-replay-page.js.map +1 -1
- package/dist/editor/shell-page.js +117 -7
- package/dist/editor/shell-page.js.map +1 -1
- package/dist/forge/apply-modifications.js +70 -2
- package/dist/forge/apply-modifications.js.map +1 -1
- package/dist/forge/progress.d.ts +10 -0
- package/dist/forge/progress.js +7 -6
- package/dist/forge/progress.js.map +1 -1
- package/dist/forge/run-pipeline.d.ts +8 -0
- package/dist/forge/run-pipeline.js +37 -2
- package/dist/forge/run-pipeline.js.map +1 -1
- package/dist/forge/stream.d.ts +7 -1
- package/dist/forge/stream.js +5 -2
- package/dist/forge/stream.js.map +1 -1
- package/dist/forge/two-d-gate.d.ts +72 -0
- package/dist/forge/two-d-gate.js +198 -0
- package/dist/forge/two-d-gate.js.map +1 -0
- package/dist/generate/animation-from-video.d.ts +11 -3
- package/dist/generate/animation-from-video.js +12 -2
- package/dist/generate/animation-from-video.js.map +1 -1
- package/dist/generate/model.d.ts +11 -0
- package/dist/generate/model.js +41 -1
- package/dist/generate/model.js.map +1 -1
- package/dist/generate/prop.d.ts +9 -0
- package/dist/generate/prop.js +59 -9
- package/dist/generate/prop.js.map +1 -1
- package/dist/generate/video-review.d.ts +28 -0
- package/dist/generate/video-review.js +120 -0
- package/dist/generate/video-review.js.map +1 -0
- package/dist/project/art-style.d.ts +34 -0
- package/dist/project/art-style.js +63 -0
- package/dist/project/art-style.js.map +1 -0
- package/dist/prompt.d.ts +9 -0
- package/dist/prompt.js +36 -0
- package/dist/prompt.js.map +1 -0
- package/dist/publish/bundle.d.ts +12 -0
- package/dist/publish/bundle.js +32 -0
- package/dist/publish/bundle.js.map +1 -1
- package/dist/render/qr-png.d.ts +6 -3
- package/dist/render/qr-png.js +8 -8
- package/dist/render/qr-png.js.map +1 -1
- package/dist/scaffold/blender-level-skill-files.d.ts +26 -0
- package/dist/scaffold/blender-level-skill-files.js +570 -0
- package/dist/scaffold/blender-level-skill-files.js.map +1 -0
- package/dist/scaffold/claude-settings.js +2 -0
- package/dist/scaffold/claude-settings.js.map +1 -1
- package/dist/scaffold/project-files.d.ts +2 -1
- package/dist/scaffold/project-files.js +125 -42
- package/dist/scaffold/project-files.js.map +1 -1
- package/dist/scaffold/project.d.ts +9 -0
- package/dist/scaffold/project.js +29 -3
- package/dist/scaffold/project.js.map +1 -1
- package/dist/scaffold/reference-guidance.d.ts +1 -1
- package/dist/scaffold/reference-guidance.js +2 -1
- package/dist/scaffold/reference-guidance.js.map +1 -1
- package/dist/scaffold/skill-files.js +3 -1
- package/dist/scaffold/skill-files.js.map +1 -1
- package/dist/scaffold/unity-skill-files.js +1 -2
- package/dist/scaffold/unity-skill-files.js.map +1 -1
- package/dist/tools/bundles.d.ts +21 -0
- package/dist/tools/bundles.js +67 -0
- package/dist/tools/bundles.js.map +1 -0
- package/dist/trailer/ffmpeg.d.ts +10 -0
- package/dist/trailer/ffmpeg.js +51 -6
- package/dist/trailer/ffmpeg.js.map +1 -1
- package/dist/trailer/hud-raster.d.ts +12 -12
- package/dist/trailer/hud-raster.js +85 -32
- package/dist/trailer/hud-raster.js.map +1 -1
- package/dist/trailer/hud-state.d.ts +75 -4
- package/dist/trailer/hud-state.js +132 -17
- package/dist/trailer/hud-state.js.map +1 -1
- package/dist/trailer/io.d.ts +2 -0
- package/dist/trailer/io.js +6 -1
- package/dist/trailer/io.js.map +1 -1
- package/dist/trailer/link.d.ts +1 -0
- package/dist/trailer/link.js +15 -0
- package/dist/trailer/link.js.map +1 -0
- package/dist/trailer/make.d.ts +2 -0
- package/dist/trailer/make.js +1 -0
- package/dist/trailer/make.js.map +1 -1
- package/dist/trailer/merge.js +32 -11
- package/dist/trailer/merge.js.map +1 -1
- package/dist/trailer/music-beats.js +4 -39
- package/dist/trailer/music-beats.js.map +1 -1
- package/dist/trailer/render.d.ts +2 -0
- package/dist/trailer/render.js +94 -48
- package/dist/trailer/render.js.map +1 -1
- package/dist/trailer/timeline-types.d.ts +19 -0
- package/dist/trailer/timeline-types.js +42 -2
- package/dist/trailer/timeline-types.js.map +1 -1
- package/dist/trailer/title-raster.js +2 -1
- package/dist/trailer/title-raster.js.map +1 -1
- package/dist/trailer/titles.js +6 -1
- package/dist/trailer/titles.js.map +1 -1
- package/dist/trailer/video-chain.d.ts +96 -8
- package/dist/trailer/video-chain.js +183 -0
- package/dist/trailer/video-chain.js.map +1 -1
- package/dist/verify/browser.js +4 -1
- package/dist/verify/browser.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Looking at the clip `bitmagic generate video` just paid for.
|
|
3
|
+
*
|
|
4
|
+
* A generated clip was the one asset the CLI could produce but not show: the command printed a URL,
|
|
5
|
+
* and checking whether the rider actually jumps meant a curl and a hand-written ffmpeg tile filter.
|
|
6
|
+
* Both facts that decide whether a clip is usable are cheap to read off the file, so both are read
|
|
7
|
+
* here and printed with the result:
|
|
8
|
+
*
|
|
9
|
+
* - a contact sheet, 8 frames spread across the clip, written into `.bitmagic/` as a PNG the
|
|
10
|
+
* agent (or the creator) can open;
|
|
11
|
+
* - whether the file carries an audio track, which is what decides if the cutscene needs a music
|
|
12
|
+
* bed under it. Today's generator produces silent clips, but that is the generator's property,
|
|
13
|
+
* not a promise — so it is probed, never assumed.
|
|
14
|
+
*
|
|
15
|
+
* Every step is best-effort by design, exactly as `cover.ts` downloads its image: the clip is
|
|
16
|
+
* generated, billed and already in world.json by the time this runs, so nothing here may turn a
|
|
17
|
+
* successful generation into a failed command. ffmpeg is not a dependency of this CLI's core lane
|
|
18
|
+
* either, so its absence is one note, not an error.
|
|
19
|
+
*/
|
|
20
|
+
import * as fs from 'fs';
|
|
21
|
+
import * as path from 'path';
|
|
22
|
+
import { captureFfmpegTool, missingFfmpegTool, runFfmpeg } from '../trailer/ffmpeg.js';
|
|
23
|
+
/** Frames in the sheet, and the grid they are tiled into. 4x2 fits a 16:9 clip on one screen. */
|
|
24
|
+
const SHEET_COLUMNS = 4;
|
|
25
|
+
const SHEET_ROWS = 2;
|
|
26
|
+
const SHEET_FRAMES = SHEET_COLUMNS * SHEET_ROWS;
|
|
27
|
+
/** Per-frame width in the sheet. 4 across is ~1280px total — readable, and a small PNG. */
|
|
28
|
+
const FRAME_WIDTH = 320;
|
|
29
|
+
/** Where a reviewed clip's frames land. Gitignored, and outside the publish fingerprint. */
|
|
30
|
+
export function contactSheetPath(root, assetId) {
|
|
31
|
+
return path.join(root, '.bitmagic', 'videos', `${safeFileStem(assetId)}.png`);
|
|
32
|
+
}
|
|
33
|
+
/** Asset ids come from `--asset-id` too, so they are not trusted to be a safe filename. */
|
|
34
|
+
function safeFileStem(assetId) {
|
|
35
|
+
const cleaned = assetId.replace(/[^A-Za-z0-9_-]/g, '-').slice(0, 96);
|
|
36
|
+
return cleaned.length > 0 ? cleaned : 'clip';
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Download the clip, tile frames from it, and report whether it has sound.
|
|
40
|
+
*
|
|
41
|
+
* The mp4 itself is deliberately not kept: it is several MB per generation, the URL is printed
|
|
42
|
+
* beside the sheet, and the dev view plays the clip when a creator wants to watch it move.
|
|
43
|
+
*/
|
|
44
|
+
export async function reviewGeneratedClip(options) {
|
|
45
|
+
const missing = missingFfmpegTool(['ffmpeg', 'ffprobe']);
|
|
46
|
+
if (missing !== null) {
|
|
47
|
+
return {
|
|
48
|
+
sheetPath: null,
|
|
49
|
+
hasAudioTrack: null,
|
|
50
|
+
notes: [`${missing} is not on PATH, so no frames were grabbed (macOS: brew install ffmpeg).`],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const sheetPath = contactSheetPath(options.root, options.assetId);
|
|
54
|
+
const clipPath = `${sheetPath}.download`;
|
|
55
|
+
fs.mkdirSync(path.dirname(sheetPath), { recursive: true });
|
|
56
|
+
try {
|
|
57
|
+
const response = await options.fetch(options.videoUrl);
|
|
58
|
+
if (!response.ok) {
|
|
59
|
+
return { sheetPath: null, hasAudioTrack: null, notes: [`could not download the clip to look at it (HTTP ${response.status}).`] };
|
|
60
|
+
}
|
|
61
|
+
fs.writeFileSync(clipPath, Buffer.from(await response.arrayBuffer()));
|
|
62
|
+
const notes = [];
|
|
63
|
+
const hasAudioTrack = await probeHasAudioTrack(clipPath).catch((error) => {
|
|
64
|
+
notes.push(`could not read the clip's streams: ${messageOf(error)}`);
|
|
65
|
+
return null;
|
|
66
|
+
});
|
|
67
|
+
const written = await writeContactSheet(clipPath, sheetPath, options.durationSeconds)
|
|
68
|
+
.then(() => true)
|
|
69
|
+
.catch((error) => {
|
|
70
|
+
notes.push(`could not grab frames from the clip: ${messageOf(error)}`);
|
|
71
|
+
return false;
|
|
72
|
+
});
|
|
73
|
+
return { sheetPath: written ? sheetPath : null, hasAudioTrack, notes };
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
return { sheetPath: null, hasAudioTrack: null, notes: [`could not download the clip to look at it: ${messageOf(error)}`] };
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
try {
|
|
80
|
+
fs.rmSync(clipPath, { force: true });
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// A leftover download in .bitmagic/ is not worth a word to the creator.
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/** True when the container holds at least one audio stream. Empty ffprobe output means none. */
|
|
88
|
+
async function probeHasAudioTrack(clipPath) {
|
|
89
|
+
const stdout = await captureFfmpegTool('ffprobe', [
|
|
90
|
+
'-v', 'error',
|
|
91
|
+
'-select_streams', 'a',
|
|
92
|
+
'-show_entries', 'stream=codec_type',
|
|
93
|
+
'-of', 'csv=p=0',
|
|
94
|
+
clipPath,
|
|
95
|
+
]);
|
|
96
|
+
return stdout.toString('utf-8').trim().length > 0;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Tile `SHEET_FRAMES` frames spread evenly across the clip into one PNG.
|
|
100
|
+
*
|
|
101
|
+
* `fps` rather than `select='not(mod(n,N))'`: the sample rate follows the clip's length, so a 3 s
|
|
102
|
+
* and a 10 s clip both come back as a full grid instead of one dense row and one sparse one.
|
|
103
|
+
*/
|
|
104
|
+
async function writeContactSheet(clipPath, sheetPath, durationSeconds) {
|
|
105
|
+
const seconds = Math.max(durationSeconds, 0.5);
|
|
106
|
+
const fps = (SHEET_FRAMES / seconds).toFixed(6);
|
|
107
|
+
await runFfmpeg([
|
|
108
|
+
'-v', 'error',
|
|
109
|
+
'-nostdin',
|
|
110
|
+
'-y',
|
|
111
|
+
'-i', clipPath,
|
|
112
|
+
'-vf', `fps=${fps},scale=${FRAME_WIDTH}:-1,tile=${SHEET_COLUMNS}x${SHEET_ROWS}`,
|
|
113
|
+
'-frames:v', '1',
|
|
114
|
+
sheetPath,
|
|
115
|
+
]);
|
|
116
|
+
}
|
|
117
|
+
function messageOf(error) {
|
|
118
|
+
return error instanceof Error ? error.message : String(error);
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=video-review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video-review.js","sourceRoot":"","sources":["../../src/generate/video-review.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a project DECLARES about its art style: `artStyle` at the top level of `src/work/game.json`,
|
|
3
|
+
* `voxel` or `low-poly`, absent meaning `voxel` — every game made before the field existed.
|
|
4
|
+
*
|
|
5
|
+
* One reader, the `platform-declaration.ts` shape, because six commands act on the same field
|
|
6
|
+
* and must never disagree about it: `cover` and `reference make` choose their prompt lead by it,
|
|
7
|
+
* `assets add` and `generate model|prop|character` choose whether a mesh is kept or voxelized,
|
|
8
|
+
* and `judge` uses it as the art direction when GAME-DESIGN.md has no heading for one.
|
|
9
|
+
*
|
|
10
|
+
* Best effort throughout: a missing or unreadable file means "declares nothing" (voxel), never
|
|
11
|
+
* an error. A value that is present but not one of the two lands in `rejected` so the caller can
|
|
12
|
+
* say so once — a typo'd `"lowpoly"` silently voxelizing a Blender level is the failure this
|
|
13
|
+
* exists to make visible.
|
|
14
|
+
*/
|
|
15
|
+
import { type ArtStyle } from '@bitmagic/asset-core/art-style';
|
|
16
|
+
export type { ArtStyle } from '@bitmagic/asset-core/art-style';
|
|
17
|
+
export interface ArtStyleDeclaration {
|
|
18
|
+
/** `undefined` means the project declares nothing — which every consumer treats as `voxel`. */
|
|
19
|
+
artStyle?: ArtStyle;
|
|
20
|
+
/** Present but not an accepted value, verbatim, for the caller's message. */
|
|
21
|
+
rejected?: unknown;
|
|
22
|
+
/** Whether game.json could be read at all. */
|
|
23
|
+
workCopyReadable: boolean;
|
|
24
|
+
}
|
|
25
|
+
/** The exact declaration, for callers that must tell "says nothing" from "says voxel". */
|
|
26
|
+
export declare function readArtStyleDeclaration(root: string): ArtStyleDeclaration;
|
|
27
|
+
/**
|
|
28
|
+
* The style every command acts on. A rejected value is reported through `log` (once per call —
|
|
29
|
+
* commands call this once) and treated as voxel, the same as absent: refusing the command would
|
|
30
|
+
* turn a typo in a field most creators never touch into a blocked cover.
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveArtStyle(root: string, log?: (line: string) => void): ArtStyle;
|
|
33
|
+
/** One line for a command's output, so a transcript shows which style drove it. */
|
|
34
|
+
export declare function describeArtStyleSource(root: string): string;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a project DECLARES about its art style: `artStyle` at the top level of `src/work/game.json`,
|
|
3
|
+
* `voxel` or `low-poly`, absent meaning `voxel` — every game made before the field existed.
|
|
4
|
+
*
|
|
5
|
+
* One reader, the `platform-declaration.ts` shape, because six commands act on the same field
|
|
6
|
+
* and must never disagree about it: `cover` and `reference make` choose their prompt lead by it,
|
|
7
|
+
* `assets add` and `generate model|prop|character` choose whether a mesh is kept or voxelized,
|
|
8
|
+
* and `judge` uses it as the art direction when GAME-DESIGN.md has no heading for one.
|
|
9
|
+
*
|
|
10
|
+
* Best effort throughout: a missing or unreadable file means "declares nothing" (voxel), never
|
|
11
|
+
* an error. A value that is present but not one of the two lands in `rejected` so the caller can
|
|
12
|
+
* say so once — a typo'd `"lowpoly"` silently voxelizing a Blender level is the failure this
|
|
13
|
+
* exists to make visible.
|
|
14
|
+
*/
|
|
15
|
+
import * as fs from 'node:fs';
|
|
16
|
+
import * as path from 'node:path';
|
|
17
|
+
import { DEFAULT_ART_STYLE, parseArtStyle } from '@bitmagic/asset-core/art-style';
|
|
18
|
+
import { aliasSourceDir } from '../scaffold/aliases.js';
|
|
19
|
+
/** The exact declaration, for callers that must tell "says nothing" from "says voxel". */
|
|
20
|
+
export function readArtStyleDeclaration(root) {
|
|
21
|
+
const gamePath = path.join(root, aliasSourceDir('work'), 'game.json');
|
|
22
|
+
let game = null;
|
|
23
|
+
try {
|
|
24
|
+
if (fs.existsSync(gamePath)) {
|
|
25
|
+
const parsed = JSON.parse(fs.readFileSync(gamePath, 'utf-8'));
|
|
26
|
+
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
|
|
27
|
+
game = parsed;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
game = null;
|
|
33
|
+
}
|
|
34
|
+
const declaration = { workCopyReadable: game !== null };
|
|
35
|
+
const declared = game?.artStyle;
|
|
36
|
+
const parsed = parseArtStyle(declared);
|
|
37
|
+
if (parsed !== undefined)
|
|
38
|
+
declaration.artStyle = parsed;
|
|
39
|
+
else if (declared !== undefined)
|
|
40
|
+
declaration.rejected = declared;
|
|
41
|
+
return declaration;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The style every command acts on. A rejected value is reported through `log` (once per call —
|
|
45
|
+
* commands call this once) and treated as voxel, the same as absent: refusing the command would
|
|
46
|
+
* turn a typo in a field most creators never touch into a blocked cover.
|
|
47
|
+
*/
|
|
48
|
+
export function resolveArtStyle(root, log) {
|
|
49
|
+
const declaration = readArtStyleDeclaration(root);
|
|
50
|
+
if (declaration.rejected !== undefined && log) {
|
|
51
|
+
log(`note: game.json says artStyle ${JSON.stringify(declaration.rejected)}, which is not "voxel" or `
|
|
52
|
+
+ `"low-poly" — treating it as voxel.`);
|
|
53
|
+
}
|
|
54
|
+
return declaration.artStyle ?? DEFAULT_ART_STYLE;
|
|
55
|
+
}
|
|
56
|
+
/** One line for a command's output, so a transcript shows which style drove it. */
|
|
57
|
+
export function describeArtStyleSource(root) {
|
|
58
|
+
const declaration = readArtStyleDeclaration(root);
|
|
59
|
+
return declaration.artStyle !== undefined
|
|
60
|
+
? `Art style: ${declaration.artStyle} (game.json)`
|
|
61
|
+
: 'Art style: voxel (game.json declares none)';
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=art-style.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"art-style.js","sourceRoot":"","sources":["../../src/project/art-style.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAiB,MAAM,gCAAgC,CAAC;AACjG,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAaxD,0FAA0F;AAC1F,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC;IACtE,IAAI,IAAI,GAAmC,IAAI,CAAC;IAChD,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;YACvE,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5E,IAAI,GAAG,MAAiC,CAAC;YAC3C,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,IAAI,CAAC;IACd,CAAC;IACD,MAAM,WAAW,GAAwB,EAAE,gBAAgB,EAAE,IAAI,KAAK,IAAI,EAAE,CAAC;IAC7E,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,CAAC;IAChC,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,MAAM,KAAK,SAAS;QAAE,WAAW,CAAC,QAAQ,GAAG,MAAM,CAAC;SACnD,IAAI,QAAQ,KAAK,SAAS;QAAE,WAAW,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACjE,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,GAA4B;IACxE,MAAM,WAAW,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAClD,IAAI,WAAW,CAAC,QAAQ,KAAK,SAAS,IAAI,GAAG,EAAE,CAAC;QAC9C,GAAG,CACD,iCAAiC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,4BAA4B;cAC/F,oCAAoC,CACvC,CAAC;IACJ,CAAC;IACD,OAAO,WAAW,CAAC,QAAQ,IAAI,iBAAiB,CAAC;AACnD,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,MAAM,WAAW,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAClD,OAAO,WAAW,CAAC,QAAQ,KAAK,SAAS;QACvC,CAAC,CAAC,cAAc,WAAW,CAAC,QAAQ,cAAc;QAClD,CAAC,CAAC,4CAA4C,CAAC;AACnD,CAAC"}
|
package/dist/prompt.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Whether a person is at the keyboard, as opposed to a pipe, an agent or CI. */
|
|
2
|
+
export declare function isInteractive(): boolean;
|
|
3
|
+
/** One line of answer, trimmed. The question is written to stderr. */
|
|
4
|
+
export declare function askOnStdin(question: string): Promise<string>;
|
|
5
|
+
/**
|
|
6
|
+
* `y` / `yes`, case-insensitive. Everything else is no — including an empty line, so
|
|
7
|
+
* hitting return on a `[y/N]` prompt declines rather than spends.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isAffirmative(answer: string): boolean;
|
package/dist/prompt.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asking the person at the keyboard a question.
|
|
3
|
+
*
|
|
4
|
+
* The question goes to STDERR, never stdout. stdout carries the `--json` result document
|
|
5
|
+
* (see output.ts), and a prompt written there corrupts it — the same rule `output.info`
|
|
6
|
+
* follows for progress lines.
|
|
7
|
+
*
|
|
8
|
+
* `isInteractive` is separate from `ask` because callers need them separately: a command
|
|
9
|
+
* has to know whether asking is possible at all before it asks. Blocking on a stdin that
|
|
10
|
+
* is a closed pipe, or one carrying data (`generate --spec -` reads a document from fd 0),
|
|
11
|
+
* hangs forever instead of prompting.
|
|
12
|
+
*/
|
|
13
|
+
import { createInterface } from 'readline/promises';
|
|
14
|
+
/** Whether a person is at the keyboard, as opposed to a pipe, an agent or CI. */
|
|
15
|
+
export function isInteractive() {
|
|
16
|
+
return process.stdin.isTTY === true;
|
|
17
|
+
}
|
|
18
|
+
/** One line of answer, trimmed. The question is written to stderr. */
|
|
19
|
+
export async function askOnStdin(question) {
|
|
20
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
21
|
+
try {
|
|
22
|
+
return (await rl.question(question)).trim();
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
rl.close();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* `y` / `yes`, case-insensitive. Everything else is no — including an empty line, so
|
|
30
|
+
* hitting return on a `[y/N]` prompt declines rather than spends.
|
|
31
|
+
*/
|
|
32
|
+
export function isAffirmative(answer) {
|
|
33
|
+
const normalized = answer.trim().toLowerCase();
|
|
34
|
+
return normalized === 'y' || normalized === 'yes';
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,iFAAiF;AACjF,MAAM,UAAU,aAAa;IAC3B,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC;AACtC,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7E,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/C,OAAO,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,KAAK,CAAC;AACpD,CAAC"}
|
package/dist/publish/bundle.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type RapierFlavor } from '@bitmagic/world-forger/physics-mode.js';
|
|
1
2
|
/**
|
|
2
3
|
* The configs the scaffold vendors alongside `engine/`, one per bundle mode.
|
|
3
4
|
*
|
|
@@ -9,6 +10,17 @@ export declare const VITE_PUBLISH_CONFIG = "vite.publish.config.js";
|
|
|
9
10
|
export declare const VITE_PUBLISH_STANDALONE_CONFIG = "vite.publish-standalone.config.js";
|
|
10
11
|
/** The vendored config a build of this mode loads. */
|
|
11
12
|
export declare function publishConfigFor(singleFile: boolean): string;
|
|
13
|
+
/**
|
|
14
|
+
* The single Rapier flavor this project's bundle ships — the game's EFFECTIVE
|
|
15
|
+
* physics mode (src/work/game.json genre + physicsMode + physics2d, clamped
|
|
16
|
+
* exactly the way the engine clamps at boot), not the raw declared value.
|
|
17
|
+
*
|
|
18
|
+
* A build ships exactly one physics engine, never both: a game.json that
|
|
19
|
+
* cannot be read fails the build here, before `tsc` runs, rather than guessing
|
|
20
|
+
* which engine to drop. (The vendored config applies the same rule itself when
|
|
21
|
+
* the variable is unset, so a hand-run `vite build` is single-flavor too.)
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveRapierFlavor(root: string): RapierFlavor;
|
|
12
24
|
/**
|
|
13
25
|
* What was built, and from what.
|
|
14
26
|
*
|
package/dist/publish/bundle.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from 'crypto';
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import * as path from 'path';
|
|
4
|
+
import { rapierFlavorForGame } from '@bitmagic/world-forger/physics-mode.js';
|
|
4
5
|
import { CliError } from '../errors.js';
|
|
5
6
|
import { projectBin } from '../project/context.js';
|
|
6
7
|
import { spawnBinSync } from '../project/spawn-bin.js';
|
|
@@ -18,6 +19,30 @@ export const VITE_PUBLISH_STANDALONE_CONFIG = 'vite.publish-standalone.config.js
|
|
|
18
19
|
export function publishConfigFor(singleFile) {
|
|
19
20
|
return singleFile ? VITE_PUBLISH_STANDALONE_CONFIG : VITE_PUBLISH_CONFIG;
|
|
20
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* The single Rapier flavor this project's bundle ships — the game's EFFECTIVE
|
|
24
|
+
* physics mode (src/work/game.json genre + physicsMode + physics2d, clamped
|
|
25
|
+
* exactly the way the engine clamps at boot), not the raw declared value.
|
|
26
|
+
*
|
|
27
|
+
* A build ships exactly one physics engine, never both: a game.json that
|
|
28
|
+
* cannot be read fails the build here, before `tsc` runs, rather than guessing
|
|
29
|
+
* which engine to drop. (The vendored config applies the same rule itself when
|
|
30
|
+
* the variable is unset, so a hand-run `vite build` is single-flavor too.)
|
|
31
|
+
*/
|
|
32
|
+
export function resolveRapierFlavor(root) {
|
|
33
|
+
const file = path.join(root, 'src', 'work', 'game.json');
|
|
34
|
+
let raw;
|
|
35
|
+
try {
|
|
36
|
+
raw = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
throw new CliError(`Cannot decide which physics engine to bundle: ${path.relative(root, file)} is unreadable ` +
|
|
40
|
+
`(${err instanceof Error ? err.message : String(err)}). A build ships exactly one Rapier flavor, ` +
|
|
41
|
+
"chosen from the game's physicsMode.", 1);
|
|
42
|
+
}
|
|
43
|
+
const gameGenre = typeof raw.gameGenre === 'string' ? raw.gameGenre : '';
|
|
44
|
+
return rapierFlavorForGame(gameGenre, raw.physicsMode, raw.physics2d === true);
|
|
45
|
+
}
|
|
21
46
|
export function buildBundlePaths(root) {
|
|
22
47
|
const dir = path.join(root, '.bitmagic', 'build');
|
|
23
48
|
return { dir, htmlPath: path.join(dir, 'index.html'), manifestPath: path.join(dir, 'manifest.json') };
|
|
@@ -90,9 +115,16 @@ export function runBuild(root, engineVersion, options = {}) {
|
|
|
90
115
|
const { dir, htmlPath } = buildBundlePaths(root);
|
|
91
116
|
fs.mkdirSync(dir, { recursive: true });
|
|
92
117
|
const vite = projectBin(root, 'vite');
|
|
118
|
+
// Covers `bitmagic build`, `bitmagic publish` and `bitmagic ios` in one
|
|
119
|
+
// place: the vendored configs read BUNDLE_RAPIER_FLAVOR and stub the Rapier
|
|
120
|
+
// flavor this game does not run, so the bundle ships exactly one. The
|
|
121
|
+
// variable is OWNED here — an inherited value from the caller's shell never
|
|
122
|
+
// overrides the game's own physics mode.
|
|
123
|
+
const bundleEnv = { ...process.env, BUNDLE_RAPIER_FLAVOR: resolveRapierFlavor(root) };
|
|
93
124
|
const bundle = spawnBinSync(vite, ['build', '--config', configFile, '--outDir', dir, '--emptyOutDir'], {
|
|
94
125
|
cwd: root,
|
|
95
126
|
stdio: 'inherit',
|
|
127
|
+
env: bundleEnv,
|
|
96
128
|
});
|
|
97
129
|
if (bundle.error)
|
|
98
130
|
throw new CliError(`Could not run vite: ${bundle.error.message}`, 1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../src/publish/bundle.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../src/publish/bundle.ts"],"names":[],"mappings":"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"}
|
package/dist/render/qr-png.d.ts
CHANGED
|
@@ -15,11 +15,14 @@
|
|
|
15
15
|
*
|
|
16
16
|
* Two other hand-rolled PNG encoders exist in this repo — `world-forger-internal`'s vehicle atlas
|
|
17
17
|
* and `game-play-agent`'s solid-colour tile — and neither is reachable from here: the first is in a
|
|
18
|
-
* `private: true` package the CLI does not depend on, the second is server code.
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* `private: true` package the CLI does not depend on, the second is server code. Within the CLI the
|
|
19
|
+
* chunk/CRC/signature primitives are exported from here and shared with the trailer's transparent
|
|
20
|
+
* frame filler (trailer/video-chain.ts); `ios/icon.ts` predates that and keeps its own.
|
|
21
21
|
*/
|
|
22
22
|
import { Buffer } from 'buffer';
|
|
23
|
+
export declare const PNG_SIGNATURE: Buffer<ArrayBuffer>;
|
|
24
|
+
/** One PNG chunk: length, type, data, and the CRC over type+data (never over the length). */
|
|
25
|
+
export declare function pngChunk(type: string, data: Buffer): Buffer;
|
|
23
26
|
export interface QrPngOptions {
|
|
24
27
|
/** Pixels per module. Defaults to `MODULE_PIXELS`. */
|
|
25
28
|
scale?: number;
|
package/dist/render/qr-png.js
CHANGED
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
*
|
|
16
16
|
* Two other hand-rolled PNG encoders exist in this repo — `world-forger-internal`'s vehicle atlas
|
|
17
17
|
* and `game-play-agent`'s solid-colour tile — and neither is reachable from here: the first is in a
|
|
18
|
-
* `private: true` package the CLI does not depend on, the second is server code.
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* `private: true` package the CLI does not depend on, the second is server code. Within the CLI the
|
|
19
|
+
* chunk/CRC/signature primitives are exported from here and shared with the trailer's transparent
|
|
20
|
+
* frame filler (trailer/video-chain.ts); `ios/icon.ts` predates that and keeps its own.
|
|
21
21
|
*/
|
|
22
22
|
import { Buffer } from 'buffer';
|
|
23
23
|
import * as zlib from 'zlib';
|
|
@@ -28,7 +28,7 @@ const MODULE_PIXELS = 8;
|
|
|
28
28
|
* uses — that one is trading margin for terminal columns, and a file has no such constraint.
|
|
29
29
|
*/
|
|
30
30
|
const QUIET_MODULES = 4;
|
|
31
|
-
const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
31
|
+
export const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
32
32
|
/** The standard CRC-32 table (PNG spec annex D), built once. */
|
|
33
33
|
function buildCrcTable() {
|
|
34
34
|
const table = new Uint32Array(256);
|
|
@@ -50,7 +50,7 @@ function crc32(bytes) {
|
|
|
50
50
|
return (crc ^ 0xffffffff) >>> 0;
|
|
51
51
|
}
|
|
52
52
|
/** One PNG chunk: length, type, data, and the CRC over type+data (never over the length). */
|
|
53
|
-
function
|
|
53
|
+
export function pngChunk(type, data) {
|
|
54
54
|
const length = Buffer.alloc(4);
|
|
55
55
|
length.writeUInt32BE(data.length, 0);
|
|
56
56
|
const typeAndData = Buffer.concat([Buffer.from(type, 'ascii'), data]);
|
|
@@ -101,11 +101,11 @@ export function encodeQrPng(matrix, options = {}) {
|
|
|
101
101
|
ihdr[12] = 0; // interlace: none
|
|
102
102
|
return Buffer.concat([
|
|
103
103
|
PNG_SIGNATURE,
|
|
104
|
-
|
|
104
|
+
pngChunk('IHDR', ihdr),
|
|
105
105
|
// deflateSync, not fflate's — fflate's `deflateSync` emits RAW deflate with no zlib header,
|
|
106
106
|
// and an IDAT must carry the zlib wrapper. (fflate's `zlibSync` would also do.)
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
pngChunk('IDAT', zlib.deflateSync(raw)),
|
|
108
|
+
pngChunk('IEND', Buffer.alloc(0)),
|
|
109
109
|
]);
|
|
110
110
|
}
|
|
111
111
|
//# sourceMappingURL=qr-png.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qr-png.js","sourceRoot":"","sources":["../../src/render/qr-png.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,2FAA2F;AAC3F,MAAM,aAAa,GAAG,CAAC,CAAC;AAExB;;;GAGG;AACH,MAAM,aAAa,GAAG,CAAC,CAAC;AAExB,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"qr-png.js","sourceRoot":"","sources":["../../src/render/qr-png.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `building-levels-in-blender` skill: a hand-designed low-poly world written as a Python script
|
|
3
|
+
* against the shipped `bmlevel` library, built by Blender into one GLB plus the collider / door /
|
|
4
|
+
* light / landmark JSON, audited with ray casts, reviewed from rendered stills, and loaded by the
|
|
5
|
+
* engine's `MeshLevel`. Distilled from a creator's space-station game whose agent installed Blender
|
|
6
|
+
* and hand-rolled every part of this — the build vocabulary, the audits, the review renders, the
|
|
7
|
+
* level loader — and hit the two failures the skill now names up front (a GLB fetched from a local
|
|
8
|
+
* path that 404s after publish; NPC spawns routed into an absent voxel grid).
|
|
9
|
+
*
|
|
10
|
+
* Same contract as `unity-skill-files.ts`: pure functions returning file contents, registered in
|
|
11
|
+
* `SHIPPED_SKILLS` (project.ts). The Python and Blender scripts ship in the package's
|
|
12
|
+
* `assets/blender-level/` (see `files` in package.json) rather than being rendered into every
|
|
13
|
+
* project; the skill's step 1 copies them into `tools/blender-level/`.
|
|
14
|
+
*
|
|
15
|
+
* The skill's first section is the gate: the path is for frontier models with Blender available,
|
|
16
|
+
* and everything else goes to `bitmagic forge`. The CLI cannot tell which model drives it, so the
|
|
17
|
+
* gate is the agent's own call — stated once, plainly, where the planning skill sends it.
|
|
18
|
+
*
|
|
19
|
+
* Backticks and `${` are escaped for the template literal; `project-files.test.ts` checks the
|
|
20
|
+
* rendered frontmatter and that no escape leaks into the output.
|
|
21
|
+
*/
|
|
22
|
+
export declare function renderBlenderLevelsSkill(): string;
|
|
23
|
+
export declare function renderBlenderConventionsReference(): string;
|
|
24
|
+
export declare function renderBlenderAuditsReference(): string;
|
|
25
|
+
export declare function renderBlenderPassesReference(): string;
|
|
26
|
+
export declare function renderBlenderEngineHandoffReference(): string;
|