spawnpack 0.1.23 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +41 -52
- package/dist/spawnpack.js +489 -764
- package/package.json +2 -4
- package/templates/AGENTS.md +0 -51
- package/templates/filters/typegen/main.js +0 -86
package/dist/spawnpack.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
1
|
// @bun
|
|
3
2
|
var __create = Object.create;
|
|
4
3
|
var __getProtoOf = Object.getPrototypeOf;
|
|
@@ -1224,23 +1223,25 @@ ${c}
|
|
|
1224
1223
|
// src/index.ts
|
|
1225
1224
|
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
1226
1225
|
|
|
1227
|
-
// src/engine/generator.ts
|
|
1228
|
-
import { mkdir, writeFile } from "fs/promises";
|
|
1229
|
-
import { join } from "path";
|
|
1230
|
-
|
|
1231
1226
|
// src/config.ts
|
|
1232
1227
|
var VERSIONS = {
|
|
1233
|
-
minEngineVersion: [1, 26, 0],
|
|
1234
1228
|
manifestFormat: 2,
|
|
1235
|
-
rolldown: "^1.
|
|
1236
|
-
esToolkit: "^1.
|
|
1237
|
-
jsoncParser: "^3.3.1"
|
|
1229
|
+
rolldown: "^1.3.0",
|
|
1230
|
+
esToolkit: "^1.53.2",
|
|
1231
|
+
jsoncParser: "^3.3.1",
|
|
1232
|
+
dprint: "^0.64.3",
|
|
1233
|
+
typescript: "^7.0.2"
|
|
1234
|
+
};
|
|
1235
|
+
var DPRINT_PLUGIN_URLS = {
|
|
1236
|
+
typescript: "https://plugins.dprint.dev/typescript-0.99.1.wasm",
|
|
1237
|
+
json: "https://plugins.dprint.dev/json-0.26.0.wasm",
|
|
1238
|
+
markdown: "https://plugins.dprint.dev/markdown-0.29.0.wasm"
|
|
1238
1239
|
};
|
|
1239
1240
|
var DEFAULT_MINECRAFT_DEPENDENCY_VERSIONS = {
|
|
1240
|
-
server: "2.
|
|
1241
|
-
serverUi: "2.
|
|
1242
|
-
vanillaData: "1.26.
|
|
1243
|
-
math: "2.4.
|
|
1241
|
+
server: "2.11.0",
|
|
1242
|
+
serverUi: "2.3.0",
|
|
1243
|
+
vanillaData: "1.26.60",
|
|
1244
|
+
math: "2.4.1"
|
|
1244
1245
|
};
|
|
1245
1246
|
var DEFAULT_SCRIPT_PACKAGES = {
|
|
1246
1247
|
server: true,
|
|
@@ -1266,88 +1267,6 @@ function getScriptDirectorySegments(config) {
|
|
|
1266
1267
|
function getScriptEntryPath(config) {
|
|
1267
1268
|
return [...getScriptDirectorySegments(config), "main.js"].join("/");
|
|
1268
1269
|
}
|
|
1269
|
-
function getAiDocFilename(aiSetup) {
|
|
1270
|
-
if (aiSetup === "claude") {
|
|
1271
|
-
return "CLAUDE.md";
|
|
1272
|
-
}
|
|
1273
|
-
if (aiSetup === "other") {
|
|
1274
|
-
return "AGENTS.md";
|
|
1275
|
-
}
|
|
1276
|
-
return null;
|
|
1277
|
-
}
|
|
1278
|
-
|
|
1279
|
-
// src/engine/manifests.ts
|
|
1280
|
-
var PACK_VERSION = [1, 0, 0];
|
|
1281
|
-
function getAuthors(author) {
|
|
1282
|
-
return author.trim() === "" ? [] : [author];
|
|
1283
|
-
}
|
|
1284
|
-
function getManifestScriptDependencies(config, versions) {
|
|
1285
|
-
const dependencies = [];
|
|
1286
|
-
if (config.scriptPackages.server) {
|
|
1287
|
-
dependencies.push({ module_name: "@minecraft/server", version: versions.server });
|
|
1288
|
-
}
|
|
1289
|
-
if (config.scriptPackages.serverUi) {
|
|
1290
|
-
dependencies.push({ module_name: "@minecraft/server-ui", version: versions.serverUi });
|
|
1291
|
-
}
|
|
1292
|
-
return dependencies;
|
|
1293
|
-
}
|
|
1294
|
-
function getBpModules(config) {
|
|
1295
|
-
const modules = [{ type: "data", uuid: crypto.randomUUID(), version: PACK_VERSION }];
|
|
1296
|
-
if (config.scripting !== "none") {
|
|
1297
|
-
modules.push({
|
|
1298
|
-
type: "script",
|
|
1299
|
-
uuid: crypto.randomUUID(),
|
|
1300
|
-
version: PACK_VERSION,
|
|
1301
|
-
language: "javascript",
|
|
1302
|
-
entry: getScriptEntryPath(config)
|
|
1303
|
-
});
|
|
1304
|
-
}
|
|
1305
|
-
return modules;
|
|
1306
|
-
}
|
|
1307
|
-
function generateBpManifest(config, bpUuid, rpUuid, versions) {
|
|
1308
|
-
const dependencies = [{ uuid: rpUuid, version: PACK_VERSION }];
|
|
1309
|
-
if (config.scripting !== "none") {
|
|
1310
|
-
dependencies.push(...getManifestScriptDependencies(config, versions));
|
|
1311
|
-
}
|
|
1312
|
-
return {
|
|
1313
|
-
format_version: VERSIONS.manifestFormat,
|
|
1314
|
-
metadata: {
|
|
1315
|
-
authors: getAuthors(config.author),
|
|
1316
|
-
product_type: "addon"
|
|
1317
|
-
},
|
|
1318
|
-
header: {
|
|
1319
|
-
name: "pack.name",
|
|
1320
|
-
description: "pack.description",
|
|
1321
|
-
pack_scope: "world",
|
|
1322
|
-
uuid: bpUuid,
|
|
1323
|
-
version: PACK_VERSION,
|
|
1324
|
-
min_engine_version: VERSIONS.minEngineVersion
|
|
1325
|
-
},
|
|
1326
|
-
capabilities: ["pbr"],
|
|
1327
|
-
modules: getBpModules(config),
|
|
1328
|
-
dependencies
|
|
1329
|
-
};
|
|
1330
|
-
}
|
|
1331
|
-
function generateRpManifest(config, rpUuid, bpUuid) {
|
|
1332
|
-
return {
|
|
1333
|
-
format_version: VERSIONS.manifestFormat,
|
|
1334
|
-
metadata: {
|
|
1335
|
-
authors: getAuthors(config.author),
|
|
1336
|
-
product_type: "addon"
|
|
1337
|
-
},
|
|
1338
|
-
header: {
|
|
1339
|
-
name: "pack.name",
|
|
1340
|
-
description: "pack.description",
|
|
1341
|
-
pack_scope: "world",
|
|
1342
|
-
uuid: rpUuid,
|
|
1343
|
-
version: PACK_VERSION,
|
|
1344
|
-
min_engine_version: VERSIONS.minEngineVersion
|
|
1345
|
-
},
|
|
1346
|
-
capabilities: ["pbr"],
|
|
1347
|
-
modules: [{ type: "resources", uuid: crypto.randomUUID(), version: PACK_VERSION }],
|
|
1348
|
-
dependencies: [{ uuid: bpUuid, version: PACK_VERSION }]
|
|
1349
|
-
};
|
|
1350
|
-
}
|
|
1351
1270
|
|
|
1352
1271
|
// src/engine/minecraft-package-versions.ts
|
|
1353
1272
|
var PACKAGE_NAMES = {
|
|
@@ -1415,8 +1334,179 @@ async function getMinecraftDependencyVersions() {
|
|
|
1415
1334
|
return await cachedVersionsPromise;
|
|
1416
1335
|
}
|
|
1417
1336
|
|
|
1337
|
+
// src/engine/json.ts
|
|
1338
|
+
function stringifyJson(value) {
|
|
1339
|
+
return `${JSON.stringify(value, null, "\t")}
|
|
1340
|
+
`;
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
// src/engine/manifests.ts
|
|
1344
|
+
var PACK_VERSION = [1, 0, 0];
|
|
1345
|
+
function getAuthors(author) {
|
|
1346
|
+
return author.trim() === "" ? [] : [author];
|
|
1347
|
+
}
|
|
1348
|
+
function getMinEngineVersion(versions) {
|
|
1349
|
+
const [major = 1, minor = 0, patch = 0] = versions.vanillaData.split(/[.-]/).map(Number).filter(Number.isFinite);
|
|
1350
|
+
return [major, minor, patch];
|
|
1351
|
+
}
|
|
1352
|
+
function getManifestScriptDependencies(config, versions) {
|
|
1353
|
+
const dependencies = [];
|
|
1354
|
+
if (config.scriptPackages.server) {
|
|
1355
|
+
dependencies.push({ module_name: "@minecraft/server", version: versions.server });
|
|
1356
|
+
}
|
|
1357
|
+
if (config.scriptPackages.serverUi) {
|
|
1358
|
+
dependencies.push({ module_name: "@minecraft/server-ui", version: versions.serverUi });
|
|
1359
|
+
}
|
|
1360
|
+
return dependencies;
|
|
1361
|
+
}
|
|
1362
|
+
function getBpModules(config) {
|
|
1363
|
+
const modules = [{ type: "data", uuid: crypto.randomUUID(), version: PACK_VERSION }];
|
|
1364
|
+
if (config.scripting === "typescript") {
|
|
1365
|
+
modules.push({
|
|
1366
|
+
type: "script",
|
|
1367
|
+
uuid: crypto.randomUUID(),
|
|
1368
|
+
version: PACK_VERSION,
|
|
1369
|
+
language: "javascript",
|
|
1370
|
+
entry: getScriptEntryPath(config)
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1373
|
+
return modules;
|
|
1374
|
+
}
|
|
1375
|
+
function getHeaderPackFields(uuid, versions) {
|
|
1376
|
+
return {
|
|
1377
|
+
name: "pack.name",
|
|
1378
|
+
description: "pack.description",
|
|
1379
|
+
pack_scope: "world",
|
|
1380
|
+
uuid,
|
|
1381
|
+
version: PACK_VERSION,
|
|
1382
|
+
min_engine_version: getMinEngineVersion(versions)
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1385
|
+
function generateBpManifest(config, bpUuid, rpUuid, versions) {
|
|
1386
|
+
const dependencies = [{ uuid: rpUuid, version: PACK_VERSION }];
|
|
1387
|
+
if (config.scripting === "typescript") {
|
|
1388
|
+
dependencies.push(...getManifestScriptDependencies(config, versions));
|
|
1389
|
+
}
|
|
1390
|
+
return {
|
|
1391
|
+
format_version: VERSIONS.manifestFormat,
|
|
1392
|
+
metadata: {
|
|
1393
|
+
authors: getAuthors(config.author),
|
|
1394
|
+
product_type: "addon"
|
|
1395
|
+
},
|
|
1396
|
+
header: getHeaderPackFields(bpUuid, versions),
|
|
1397
|
+
modules: getBpModules(config),
|
|
1398
|
+
dependencies
|
|
1399
|
+
};
|
|
1400
|
+
}
|
|
1401
|
+
function generateRpManifest(config, rpUuid, bpUuid, versions) {
|
|
1402
|
+
return {
|
|
1403
|
+
format_version: VERSIONS.manifestFormat,
|
|
1404
|
+
metadata: {
|
|
1405
|
+
authors: getAuthors(config.author),
|
|
1406
|
+
product_type: "addon"
|
|
1407
|
+
},
|
|
1408
|
+
header: getHeaderPackFields(rpUuid, versions),
|
|
1409
|
+
capabilities: ["pbr"],
|
|
1410
|
+
modules: [{ type: "resources", uuid: crypto.randomUUID(), version: PACK_VERSION }],
|
|
1411
|
+
dependencies: [{ uuid: bpUuid, version: PACK_VERSION }]
|
|
1412
|
+
};
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
// templates/AGENTS.md
|
|
1416
|
+
var AGENTS_default = "## Project layout\n\n- When the project has scripts, TypeScript source lives in `data/scripts/`: `main.ts` is the entry, `lib/` holds shared helpers imported as `~/lib/...`, and `modules/<feature>/` holds features imported by `main.ts`.\n- rgl builds the add-on from `config.json`: the `typegen` filter writes `data/scripts/generated_types.ts`, and the `rolldown` filter bundles `data/scripts/` into the exported behavior pack's `scripts/` folder. Never edit generated output by hand; edit the source or the filter.\n- Inspect build output through `.regolith/tmp` without resolving its symlinks.\n\n## Documentation lookup\n\n- Before relying on version-sensitive or unfamiliar Minecraft Bedrock behavior, verify the relevant current documentation for the project's target Minecraft and Script API versions and stable/preview status. This includes Script API, BP/RP JSON formats, components, events, schemas, MoLang, manifests, commands, animations, and pack behavior.\n- Prefer Bedrock-specific tools when the harness provides them, such as documentation search, Script API or component lookup, and vanilla examples. Otherwise use web search.\n- Prefer current Microsoft Creator documentation and versioned references on `bedrock.dev`. For Script API, also use `https://jaylydev.github.io/scriptapi-docs/latest/`. Use `wiki.bedrock.dev` for established concepts and proven implementation patterns.\n- For other libraries, SDKs, APIs, and CLI tools, verify current official documentation before relying on unfamiliar or version-sensitive behavior.\n\n## Technical judgment\n\n- Do not assume the user or the agent is correct. Verify assumptions against current documentation, repository evidence, established patterns, or a working project sample.\n- If those sources do not resolve a choice that materially affects the result, ask the user for a reference, pattern, or sample project.\n- If evidence shows the requested approach is incorrect, unsafe, incompatible, unnecessarily complex, or slower than a supported alternative, explain why and recommend the better implementation. Follow the user's final choice unless it violates safety or repository constraints.\n\n## Verification\n\n- After TypeScript changes, run the project's `typecheck` script.\n- After BP/RP changes, validate the packs with the harness's pack validator or a Bedrock Dedicated Server load when available; otherwise check them against the project's configured Bedrock schemas.\n- Do not create or run tests unless the user asks or an existing repository policy requires them.\n- If a check is unavailable or fails for a pre-existing reason, say so plainly. Never claim a check you did not run.\n\n## Code rules\n\n- Do not write comments in code. Use clear naming and straightforward structure so the code is self-explanatory.\n- Validate predictable invalid states before calling an API. Use `try-catch` only for a documented or observed unguardable failure when the catch performs meaningful recovery, cleanup, translation, or contextual rethrow. Keep the `try` block narrow; never silently swallow errors.\n\n## Minecraft Bedrock conventions\n\n- Guard before Script API calls that can throw: check `entity.isValid` (players are valid only while loaded) before `getComponent`/`getComponents`; confirm the chunk is loaded before `dimension.getBlock`/`spawnEntity`; and use containers only after re-fetching them from a current block or entity rather than holding a stale reference. Defer world-mutating work from read-only or early-execution callbacks with `system.run`. Reserve `try-catch` for calls whose validity cannot be checked in advance, such as `runCommand` throwing `CommandError`.\n- Prefer `@minecraft/vanilla-data` typed identifiers over raw component, entity, block, item, and effect strings, and the generated `BlockId`/`EntityId`/`ItemId` enums for this add-on's own content.\n- Check `@minecraft/math` before writing vector, matrix, clamp, lerp, or similar math helpers.\n- Never reference another add-on's content IDs in data-driven JSON such as `minecraft:break_blocks`; Bedrock validates those IDs at pack load and errors when that add-on is absent. Handle optional cross-add-on content in scripts.\n\n## Performance preferences\n\n- Before adding `system.runInterval` polling, check the project's Script API version and current documentation for a matching event. Prefer the event when it provides the required data and timing, such as `PlayerInventoryItemChangeAfterEventSignal` instead of repeatedly scanning every player's inventory or hotbar. Poll only when no suitable event exists; then minimize the frequency, players, slots, and work performed.\n- In hot loops, iterate maps directly with `for (const value of map.values())`. Do not spread maps into temporary arrays or iterate entry pairs when values or keys are enough.\n- Cache stable configuration in memory and persist only when values actually change.\n\n## Repository hygiene\n\n- Never discard, overwrite, or revert unrelated user changes.\n- Do not create repository files for agent memory, lessons, session notes, plans, or debugging logs.\n- Do not create or update documentation, changelogs, or generated artifacts unless requested or required by the changed contract.\n- Do not commit, push, publish, or delete unrelated files unless explicitly requested.\n- Commit messages, when requested, use short natural subjects without Conventional Commit prefixes, AI/tool attribution, or structured report trailers. Split unrelated logical changes into separate commits.\n\n## Communication\n\n- Be direct and concise. State assumptions only when they materially affect the implementation.\n- After changes, report what changed, the verification evidence, and any real blocker or residual risk. Do not add ritual sections for untouched files.\n";
|
|
1417
|
+
|
|
1418
|
+
// templates/filters/typegen/main.js
|
|
1419
|
+
var main_default = `import { pascalCase } from "es-toolkit";
|
|
1420
|
+
import * as JSONC from "jsonc-parser";
|
|
1421
|
+
import { glob, readFile, writeFile } from "node:fs/promises";
|
|
1422
|
+
import { matchesGlob } from "node:path";
|
|
1423
|
+
|
|
1424
|
+
const entries = [
|
|
1425
|
+
{
|
|
1426
|
+
type: "BlockId",
|
|
1427
|
+
pattern: "BP/blocks/**/*.json",
|
|
1428
|
+
jsonPath: ["minecraft:block", "description", "identifier"],
|
|
1429
|
+
identifiers: [],
|
|
1430
|
+
},
|
|
1431
|
+
{
|
|
1432
|
+
type: "EntityId",
|
|
1433
|
+
pattern: "BP/entities/**/*.json",
|
|
1434
|
+
jsonPath: ["minecraft:entity", "description", "identifier"],
|
|
1435
|
+
identifiers: [],
|
|
1436
|
+
},
|
|
1437
|
+
{
|
|
1438
|
+
type: "ItemId",
|
|
1439
|
+
pattern: "BP/items/**/*.json",
|
|
1440
|
+
jsonPath: ["minecraft:item", "description", "identifier"],
|
|
1441
|
+
identifiers: [],
|
|
1442
|
+
},
|
|
1443
|
+
];
|
|
1444
|
+
|
|
1445
|
+
for (const dir of ["BP", "RP"]) {
|
|
1446
|
+
for await (const path of glob(\`\${dir}/**/*.json\`)) {
|
|
1447
|
+
const entry = entries.find((f) => matchesGlob(path, f.pattern));
|
|
1448
|
+
if (!entry) continue;
|
|
1449
|
+
|
|
1450
|
+
let found = false;
|
|
1451
|
+
const text = await readFile(path, "utf8");
|
|
1452
|
+
JSONC.visit(text, {
|
|
1453
|
+
onArrayBegin() {
|
|
1454
|
+
return !found;
|
|
1455
|
+
},
|
|
1456
|
+
onObjectBegin() {
|
|
1457
|
+
return !found;
|
|
1458
|
+
},
|
|
1459
|
+
onLiteralValue(value, _offset, _length, _startLine, _startCharacter, pathSupplier) {
|
|
1460
|
+
if (typeof value !== "string") return;
|
|
1461
|
+
if (!pathSupplier().every((segment, i) => segment === entry.jsonPath[i])) return;
|
|
1462
|
+
|
|
1463
|
+
found = true;
|
|
1464
|
+
entry.identifiers.push(value);
|
|
1465
|
+
},
|
|
1466
|
+
});
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
const lines = ["// Auto-generated file. DO NOT EDIT MANUALLY!\\n"];
|
|
1471
|
+
|
|
1472
|
+
for (const entry of entries) {
|
|
1473
|
+
if (entry.identifiers.length === 0) continue;
|
|
1474
|
+
|
|
1475
|
+
lines.push(\`export const enum \${entry.type} {\`);
|
|
1476
|
+
for (const id of entry.identifiers) {
|
|
1477
|
+
const colIndex = id.indexOf(":");
|
|
1478
|
+
if (colIndex === -1) {
|
|
1479
|
+
console.warn(\`Invalid identifier: \${id}\`);
|
|
1480
|
+
continue;
|
|
1481
|
+
}
|
|
1482
|
+
const name = id.slice(colIndex + 1).trim();
|
|
1483
|
+
if (name === "") {
|
|
1484
|
+
console.warn(\`Invalid identifier: \${id}\`);
|
|
1485
|
+
continue;
|
|
1486
|
+
}
|
|
1487
|
+
lines.push(\`\\t\${pascalCase(name)} = "\${id}",\`);
|
|
1488
|
+
}
|
|
1489
|
+
lines.push(\`}\\n\`);
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
const res = lines.join("\\n");
|
|
1493
|
+
|
|
1494
|
+
const ROOT_DIR = process.env.ROOT_DIR;
|
|
1495
|
+
|
|
1496
|
+
const current = await readFile(\`\${ROOT_DIR}/data/scripts/generated_types.ts\`, "utf8")
|
|
1497
|
+
.catch(() => null);
|
|
1498
|
+
|
|
1499
|
+
if (current !== res) {
|
|
1500
|
+
await Promise.all([
|
|
1501
|
+
writeFile(\`\${ROOT_DIR}/data/scripts/generated_types.ts\`, res),
|
|
1502
|
+
writeFile("./data/scripts/generated_types.ts", res),
|
|
1503
|
+
]);
|
|
1504
|
+
}
|
|
1505
|
+
`;
|
|
1506
|
+
|
|
1418
1507
|
// src/engine/templates.ts
|
|
1419
1508
|
var PACK_VERSION2 = "1.0.0";
|
|
1509
|
+
var BINARY_EXTENSIONS = ["png", "jpg", "jpeg", "tga", "ogg", "wav", "mp3", "fsb"];
|
|
1420
1510
|
function getSelectedScriptDependencies(config, versions) {
|
|
1421
1511
|
const dependencies = {};
|
|
1422
1512
|
if (config.scriptPackages.server) {
|
|
@@ -1433,65 +1523,35 @@ function getSelectedScriptDependencies(config, versions) {
|
|
|
1433
1523
|
}
|
|
1434
1524
|
return dependencies;
|
|
1435
1525
|
}
|
|
1526
|
+
var RGL_WORKFLOW_SECTION = `## Build workflow
|
|
1527
|
+
|
|
1528
|
+
- \`rgl watch\` rebuilds the script bundle and exports the add-on while you work.
|
|
1529
|
+
- \`rgl run\` builds a development export once.
|
|
1530
|
+
- \`rgl run build\` creates a production build.
|
|
1531
|
+
- \`typegen\` writes typed custom IDs (\`BlockId\`, \`EntityId\`, \`ItemId\`) to \`data/scripts/generated_types.ts\` on every build.
|
|
1532
|
+
- \`rolldown\` bundles \`data/scripts/main.ts\` and everything it imports into the behavior pack.
|
|
1533
|
+
|
|
1534
|
+
`;
|
|
1436
1535
|
function generatePackageJson(config, versions) {
|
|
1437
|
-
|
|
1438
|
-
if (config.scripting === "typescript") {
|
|
1439
|
-
if (!config.useRgl) {
|
|
1440
|
-
scripts.build = "tsc --project tsconfig.json";
|
|
1441
|
-
}
|
|
1442
|
-
scripts.typecheck = config.useRgl ? "tsc --project data/scripts/tsconfig.json --noEmit" : "tsc --project tsconfig.json --noEmit";
|
|
1443
|
-
scripts.format = "dprint fmt";
|
|
1444
|
-
}
|
|
1445
|
-
if (config.scripting === "javascript") {
|
|
1446
|
-
scripts.check = "bun --smol packs/BP/scripts";
|
|
1447
|
-
}
|
|
1448
|
-
const packageJson = {
|
|
1536
|
+
return stringifyJson({
|
|
1449
1537
|
name: `${config.identifier}-${config.projectId}`,
|
|
1450
1538
|
version: PACK_VERSION2,
|
|
1451
1539
|
private: true,
|
|
1452
|
-
...config.useRgl ? { workspaces: ["./filters/*"] } : {},
|
|
1453
1540
|
type: "module",
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
}
|
|
1465
|
-
function generateTsConfig(config) {
|
|
1466
|
-
const compilerOptions = {
|
|
1467
|
-
target: "ES2020",
|
|
1468
|
-
module: "ES2020",
|
|
1469
|
-
moduleResolution: "bundler",
|
|
1470
|
-
strict: true,
|
|
1471
|
-
noImplicitAny: true,
|
|
1472
|
-
strictNullChecks: true,
|
|
1473
|
-
noImplicitReturns: true,
|
|
1474
|
-
noFallthroughCasesInSwitch: true,
|
|
1475
|
-
noUnusedLocals: true,
|
|
1476
|
-
noUnusedParameters: true,
|
|
1477
|
-
isolatedModules: true,
|
|
1478
|
-
skipLibCheck: true,
|
|
1479
|
-
forceConsistentCasingInFileNames: true,
|
|
1480
|
-
rootDir: "data/scripts",
|
|
1481
|
-
types: []
|
|
1482
|
-
};
|
|
1483
|
-
if (config.useRgl) {
|
|
1484
|
-
compilerOptions.noEmit = true;
|
|
1485
|
-
} else {
|
|
1486
|
-
compilerOptions.outDir = `packs/BP/${getScriptEntryPath(config).replace(/\/main\.js$/, "")}`;
|
|
1487
|
-
}
|
|
1488
|
-
return {
|
|
1489
|
-
compilerOptions,
|
|
1490
|
-
include: ["data/scripts/**/*.ts"]
|
|
1491
|
-
};
|
|
1541
|
+
workspaces: ["./filters/*"],
|
|
1542
|
+
scripts: {
|
|
1543
|
+
typecheck: "tsc --project data/scripts/tsconfig.json --noEmit",
|
|
1544
|
+
format: "dprint fmt"
|
|
1545
|
+
},
|
|
1546
|
+
dependencies: getSelectedScriptDependencies(config, versions),
|
|
1547
|
+
devDependencies: {
|
|
1548
|
+
dprint: VERSIONS.dprint,
|
|
1549
|
+
typescript: VERSIONS.typescript
|
|
1550
|
+
}
|
|
1551
|
+
});
|
|
1492
1552
|
}
|
|
1493
1553
|
function generateDprintConfig() {
|
|
1494
|
-
return {
|
|
1554
|
+
return stringifyJson({
|
|
1495
1555
|
typescript: {
|
|
1496
1556
|
deno: true,
|
|
1497
1557
|
lineWidth: 100,
|
|
@@ -1505,14 +1565,21 @@ function generateDprintConfig() {
|
|
|
1505
1565
|
},
|
|
1506
1566
|
excludes: ["**/node_modules", "**/*-lock.json"],
|
|
1507
1567
|
plugins: [
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1568
|
+
DPRINT_PLUGIN_URLS.typescript,
|
|
1569
|
+
DPRINT_PLUGIN_URLS.json,
|
|
1570
|
+
DPRINT_PLUGIN_URLS.markdown
|
|
1511
1571
|
]
|
|
1512
|
-
};
|
|
1572
|
+
});
|
|
1573
|
+
}
|
|
1574
|
+
function generateVscodeExtensions(config) {
|
|
1575
|
+
const recommendations = ["rockide.rockide-vscode"];
|
|
1576
|
+
if (config.scripting === "typescript") {
|
|
1577
|
+
recommendations.push("dprint.dprint");
|
|
1578
|
+
}
|
|
1579
|
+
return stringifyJson({ recommendations });
|
|
1513
1580
|
}
|
|
1514
1581
|
function generateRglConfig(config) {
|
|
1515
|
-
return {
|
|
1582
|
+
return stringifyJson({
|
|
1516
1583
|
$schema: "https://raw.githubusercontent.com/ink0rr/rgl-schemas/main/config/v1.1.json",
|
|
1517
1584
|
author: config.author,
|
|
1518
1585
|
name: config.projectName,
|
|
@@ -1555,7 +1622,7 @@ function generateRglConfig(config) {
|
|
|
1555
1622
|
}
|
|
1556
1623
|
}
|
|
1557
1624
|
}
|
|
1558
|
-
};
|
|
1625
|
+
});
|
|
1559
1626
|
}
|
|
1560
1627
|
function getRolldownExternalModules(config) {
|
|
1561
1628
|
return ["@minecraft/server", ...config.scriptPackages.serverUi ? ["@minecraft/server-ui"] : []];
|
|
@@ -1590,17 +1657,17 @@ await build(config);
|
|
|
1590
1657
|
`;
|
|
1591
1658
|
}
|
|
1592
1659
|
function generateRolldownFilterPackageJson() {
|
|
1593
|
-
return {
|
|
1660
|
+
return stringifyJson({
|
|
1594
1661
|
name: "rolldown-filter",
|
|
1595
1662
|
private: true,
|
|
1596
1663
|
type: "module",
|
|
1597
1664
|
dependencies: {
|
|
1598
1665
|
rolldown: VERSIONS.rolldown
|
|
1599
1666
|
}
|
|
1600
|
-
};
|
|
1667
|
+
});
|
|
1601
1668
|
}
|
|
1602
1669
|
function generateTypegenFilterPackageJson() {
|
|
1603
|
-
return {
|
|
1670
|
+
return stringifyJson({
|
|
1604
1671
|
name: "typegen",
|
|
1605
1672
|
private: true,
|
|
1606
1673
|
type: "module",
|
|
@@ -1608,21 +1675,19 @@ function generateTypegenFilterPackageJson() {
|
|
|
1608
1675
|
"es-toolkit": VERSIONS.esToolkit,
|
|
1609
1676
|
"jsonc-parser": VERSIONS.jsoncParser
|
|
1610
1677
|
}
|
|
1611
|
-
};
|
|
1678
|
+
});
|
|
1612
1679
|
}
|
|
1613
|
-
function
|
|
1614
|
-
return
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
});
|
|
1619
|
-
`;
|
|
1680
|
+
function generateTypegenFilterMain() {
|
|
1681
|
+
return main_default;
|
|
1682
|
+
}
|
|
1683
|
+
function generateAgentsDoc() {
|
|
1684
|
+
return AGENTS_default;
|
|
1620
1685
|
}
|
|
1621
|
-
function
|
|
1686
|
+
function generateMainTs(config) {
|
|
1622
1687
|
return `import { world } from "@minecraft/server";
|
|
1623
1688
|
|
|
1624
1689
|
world.afterEvents.worldLoad.subscribe(() => {
|
|
1625
|
-
|
|
1690
|
+
world.sendMessage("[${config.identifier}:${config.projectId}] Addon loaded!");
|
|
1626
1691
|
});
|
|
1627
1692
|
`;
|
|
1628
1693
|
}
|
|
@@ -1633,7 +1698,7 @@ pack.description=Generated with Spawnpack
|
|
|
1633
1698
|
`;
|
|
1634
1699
|
}
|
|
1635
1700
|
function generateScriptsTsConfig() {
|
|
1636
|
-
return {
|
|
1701
|
+
return stringifyJson({
|
|
1637
1702
|
compilerOptions: {
|
|
1638
1703
|
lib: [
|
|
1639
1704
|
"ES2015",
|
|
@@ -1688,108 +1753,137 @@ function generateScriptsTsConfig() {
|
|
|
1688
1753
|
noUnusedParameters: true,
|
|
1689
1754
|
paths: { "~/*": ["./*"] }
|
|
1690
1755
|
}
|
|
1691
|
-
};
|
|
1756
|
+
});
|
|
1692
1757
|
}
|
|
1693
1758
|
function generateGitignore(config) {
|
|
1694
1759
|
const lines = ["node_modules/", "dist/", ".logs/", "*.zip"];
|
|
1695
|
-
if (config.
|
|
1696
|
-
lines.push("/.regolith", "/build");
|
|
1697
|
-
}
|
|
1698
|
-
if (config.useRgl && config.scripting === "typescript") {
|
|
1699
|
-
lines.push("data/scripts/generated_types.ts");
|
|
1760
|
+
if (config.scripting === "typescript") {
|
|
1761
|
+
lines.push("/.regolith", "/build", "data/scripts/generated_types.ts");
|
|
1700
1762
|
}
|
|
1701
1763
|
return `${lines.join(`
|
|
1702
1764
|
`)}
|
|
1703
1765
|
`;
|
|
1704
1766
|
}
|
|
1767
|
+
function generateGitattributes() {
|
|
1768
|
+
return ["* text=auto eol=lf", ...BINARY_EXTENSIONS.map((extension) => `*.${extension} binary`)].join(`
|
|
1769
|
+
`) + `
|
|
1770
|
+
`;
|
|
1771
|
+
}
|
|
1705
1772
|
function generateReadme(config) {
|
|
1706
|
-
const
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
const buildSteps = config.scripting === "none" ? "2. Edit your BP/RP JSON files directly inside `packs/`." : config.useRgl ? "2. Run `rgl watch` while developing to rebuild and export your add-on automatically.\n3. Run `rgl run build` when you want a production build." : config.scripting === "typescript" ? "2. Write your gameplay scripts in `data/scripts/`.\n3. Run `bun run build` or `npm run build` to compile TypeScript into `packs/BP/scripts/`." : "2. Write your gameplay scripts in `packs/BP/scripts/` and let Minecraft copy the pack into `com.mojang`.";
|
|
1710
|
-
const aiDocFilename = getAiDocFilename(config.aiSetup);
|
|
1711
|
-
const ponytailAiLine = config.installPonytail ? config.aiSetup === "other" ? "Ponytail is enabled via `opencode.json`.\n\n" : "To enable ponytail in Claude Code, run `/plugin marketplace add DietrichGebert/ponytail` then `/plugin install ponytail@ponytail`.\n\n" : "";
|
|
1712
|
-
const aiSection = aiDocFilename !== null ? `## AI Tooling
|
|
1773
|
+
const scopeSection = config.useMarketplaceStructure ? `## Marketplace structure
|
|
1774
|
+
|
|
1775
|
+
Content that Minecraft resolves by bare path is namespaced under \`${getMarketplaceScopeLabel(config)}\` inside the resource pack only:
|
|
1713
1776
|
|
|
1714
|
-
|
|
1777
|
+
- \`packs/RP/textures/${getMarketplaceScopeLabel(config)}/\` for block, entity, and item textures
|
|
1778
|
+
- \`packs/RP/sounds/${getMarketplaceScopeLabel(config)}/\` for sound files
|
|
1715
1779
|
|
|
1716
|
-
|
|
1780
|
+
Behavior pack content stays flat, and resource pack JSON still references namespaced textures and paths relative to \`packs/RP/\`.
|
|
1717
1781
|
|
|
1718
|
-
|
|
1719
|
-
const
|
|
1782
|
+
` : "";
|
|
1783
|
+
const agentsSection = config.generateAgentsDoc ? `## AI tooling
|
|
1720
1784
|
|
|
1721
|
-
|
|
1785
|
+
\`AGENTS.md\` holds the working rules this project gives to coding agents.
|
|
1722
1786
|
|
|
1723
1787
|
` : "";
|
|
1788
|
+
if (config.scripting === "none") {
|
|
1789
|
+
return `# ${config.projectName}
|
|
1790
|
+
|
|
1791
|
+
## Overview
|
|
1792
|
+
|
|
1793
|
+
- Behavior Pack: \`packs/BP\`
|
|
1794
|
+
- Resource Pack: \`packs/RP\`
|
|
1795
|
+
- Script API setup: none
|
|
1796
|
+
|
|
1797
|
+
## Getting started
|
|
1798
|
+
|
|
1799
|
+
Edit the pack JSON directly inside \`packs/BP\` and \`packs/RP\`, then copy or export both packs into Minecraft. The scaffold has no build step and no npm dependencies.
|
|
1800
|
+
|
|
1801
|
+
## Project layout
|
|
1802
|
+
|
|
1803
|
+
- \`packs/BP/manifest.json\` pairs the behavior pack with the resource pack through their UUIDs.
|
|
1804
|
+
- \`packs/BP/texts/en_US.lang\` defines \`pack.name\` and \`pack.description\` for the behavior pack.
|
|
1805
|
+
- \`packs/RP/manifest.json\` pairs the resource pack with the behavior pack.
|
|
1806
|
+
- \`packs/RP/textures/item_texture.json\` and \`terrain_texture.json\` register item and block texture atlases.
|
|
1807
|
+
- \`packs/RP/sounds/sound_definitions.json\` registers sound events.
|
|
1808
|
+
- \`.vscode/extensions.json\` recommends the Rockide extension for pack JSON validation.
|
|
1809
|
+
|
|
1810
|
+
${scopeSection}${agentsSection}---
|
|
1811
|
+
|
|
1812
|
+
<sub>Generated with Spawnpack</sub>
|
|
1813
|
+
`;
|
|
1814
|
+
}
|
|
1724
1815
|
return `# ${config.projectName}
|
|
1725
1816
|
|
|
1726
1817
|
## Overview
|
|
1727
1818
|
|
|
1728
1819
|
- Behavior Pack: \`packs/BP\`
|
|
1729
1820
|
- Resource Pack: \`packs/RP\`
|
|
1730
|
-
- Script
|
|
1731
|
-
-
|
|
1732
|
-
- Runtime entry: ${runtimeEntry}
|
|
1821
|
+
- Script source: \`data/scripts\`
|
|
1822
|
+
- Bundle entry: \`packs/BP/${getScriptEntryPath(config)}\`
|
|
1733
1823
|
|
|
1734
|
-
## Getting
|
|
1824
|
+
## Getting started
|
|
1735
1825
|
|
|
1736
|
-
|
|
1737
|
-
|
|
1826
|
+
1. Install rgl if you have not already: \`curl -fsSL rgl.ink0rr.dev/install.sh | sh\` on macOS or Linux, \`irm rgl.ink0rr.dev/install.ps1 | iex\` in PowerShell on Windows.
|
|
1827
|
+
2. Install dependencies with \`bun install\` or \`npm install\`.
|
|
1828
|
+
3. Run \`rgl watch\` while you work to rebuild and export the add-on automatically.
|
|
1829
|
+
4. Run \`rgl run build\` for a production build.
|
|
1738
1830
|
|
|
1739
|
-
##
|
|
1831
|
+
## Project layout
|
|
1740
1832
|
|
|
1741
|
-
|
|
1742
|
-
-
|
|
1743
|
-
-
|
|
1744
|
-
-
|
|
1745
|
-
-
|
|
1833
|
+
- \`data/scripts/main.ts\` is the script entrypoint.
|
|
1834
|
+
- \`data/scripts/lib/\` holds shared helpers, imported as \`~/lib/...\`.
|
|
1835
|
+
- \`data/scripts/modules/<feature>/\` holds feature modules imported by \`main.ts\`.
|
|
1836
|
+
- \`data/scripts/tsconfig.json\` sets the \`~/*\` path alias and type-checks without emitting.
|
|
1837
|
+
- \`filters/typegen/\` writes typed custom IDs to \`data/scripts/generated_types.ts\`.
|
|
1838
|
+
- \`filters/rolldown/\` bundles \`data/scripts/\` into \`packs/BP/scripts/\`.
|
|
1839
|
+
- \`config.json\` defines the rgl filters and the \`default\`, \`build\`, and \`preview\` profiles.
|
|
1840
|
+
- \`dprint.json\` formats TypeScript, JSON, and Markdown with tabs and a 100-column width.
|
|
1841
|
+
- \`packs/BP/manifest.json\` pairs the packs and declares the script module.
|
|
1842
|
+
- \`packs/RP/manifest.json\` pairs the resource pack with the behavior pack and enables PBR capabilities.
|
|
1843
|
+
- \`.vscode/extensions.json\` recommends the Rockide extension and dprint.
|
|
1746
1844
|
|
|
1747
|
-
${
|
|
1845
|
+
${RGL_WORKFLOW_SECTION}## Script packages
|
|
1748
1846
|
|
|
1749
|
-
|
|
1750
|
-
- \`rgl run\` builds a development export once.
|
|
1751
|
-
- \`rgl run build\` creates a production-ready build.
|
|
1752
|
-
- \`typegen\` auto-generates typed custom IDs (\`BlockId\`/\`EntityId\`/\`ItemId\`) into \`data/scripts/generated_types.ts\` on each build.
|
|
1847
|
+
Packages in \`package.json\` supply imports for your scripts. Only runtime Script API modules such as \`@minecraft/server\` and \`@minecraft/server-ui\` are declared in \`packs/BP/manifest.json\`; npm-only libraries such as \`@minecraft/vanilla-data\` and \`@minecraft/math\` are imported and bundled by rolldown.
|
|
1753
1848
|
|
|
1754
|
-
|
|
1849
|
+
## Commands
|
|
1755
1850
|
|
|
1756
|
-
|
|
1851
|
+
- \`bun run typecheck\` or \`npm run typecheck\` checks the TypeScript source.
|
|
1852
|
+
- \`bun run format\` or \`npm run format\` formats with dprint.
|
|
1853
|
+
|
|
1854
|
+
${scopeSection}${agentsSection}---
|
|
1757
1855
|
|
|
1758
1856
|
<sub>Generated with Spawnpack</sub>
|
|
1759
1857
|
`;
|
|
1760
1858
|
}
|
|
1761
1859
|
function generateBlocksJson() {
|
|
1762
|
-
return { format_version: "1.21.40" };
|
|
1860
|
+
return stringifyJson({ format_version: "1.21.40" });
|
|
1763
1861
|
}
|
|
1764
1862
|
function generateSoundsJson() {
|
|
1765
|
-
return { entity_sounds: {} };
|
|
1863
|
+
return stringifyJson({ entity_sounds: {} });
|
|
1766
1864
|
}
|
|
1767
1865
|
function generateSoundDefinitions() {
|
|
1768
|
-
return { format_version: "1.14.0", sound_definitions: {} };
|
|
1866
|
+
return stringifyJson({ format_version: "1.14.0", sound_definitions: {} });
|
|
1769
1867
|
}
|
|
1770
|
-
function generateItemTexture(
|
|
1771
|
-
return {
|
|
1772
|
-
resource_pack_name:
|
|
1868
|
+
function generateItemTexture() {
|
|
1869
|
+
return stringifyJson({
|
|
1870
|
+
resource_pack_name: "pack.name",
|
|
1773
1871
|
texture_name: "atlas.items",
|
|
1774
1872
|
texture_data: {}
|
|
1775
|
-
};
|
|
1873
|
+
});
|
|
1776
1874
|
}
|
|
1777
|
-
function generateTerrainTexture(
|
|
1778
|
-
return {
|
|
1779
|
-
resource_pack_name:
|
|
1875
|
+
function generateTerrainTexture() {
|
|
1876
|
+
return stringifyJson({
|
|
1877
|
+
resource_pack_name: "pack.name",
|
|
1780
1878
|
texture_name: "atlas.terrain",
|
|
1781
1879
|
texture_data: {},
|
|
1782
1880
|
num_mip_levels: 4,
|
|
1783
1881
|
padding: 8
|
|
1784
|
-
};
|
|
1882
|
+
});
|
|
1785
1883
|
}
|
|
1786
1884
|
|
|
1787
|
-
// src/engine/
|
|
1788
|
-
var
|
|
1789
|
-
new URL("../../templates/filters/typegen/main.js", import.meta.url),
|
|
1790
|
-
new URL("../templates/filters/typegen/main.js", import.meta.url)
|
|
1791
|
-
];
|
|
1792
|
-
var BP_NAMESPACED_DIRECTORIES = [
|
|
1885
|
+
// src/engine/plan.ts
|
|
1886
|
+
var BP_DIRECTORIES = [
|
|
1793
1887
|
"animation_controllers",
|
|
1794
1888
|
"animations",
|
|
1795
1889
|
"blocks",
|
|
@@ -1799,381 +1893,118 @@ var BP_NAMESPACED_DIRECTORIES = [
|
|
|
1799
1893
|
"recipes",
|
|
1800
1894
|
"spawn_rules",
|
|
1801
1895
|
"structures",
|
|
1896
|
+
"texts",
|
|
1802
1897
|
"trading"
|
|
1803
1898
|
];
|
|
1804
|
-
var
|
|
1899
|
+
var RP_DIRECTORIES = [
|
|
1805
1900
|
"animation_controllers",
|
|
1806
1901
|
"animations",
|
|
1807
1902
|
"attachables",
|
|
1808
1903
|
"entity",
|
|
1809
1904
|
"fogs",
|
|
1905
|
+
"models",
|
|
1906
|
+
"models/entity",
|
|
1810
1907
|
"particles",
|
|
1811
1908
|
"render_controllers",
|
|
1812
1909
|
"sounds",
|
|
1910
|
+
"texts",
|
|
1911
|
+
"textures",
|
|
1813
1912
|
"ui"
|
|
1814
1913
|
];
|
|
1815
|
-
var
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1914
|
+
var RP_TEXTURE_DIRECTORIES = ["blocks", "entity", "items"];
|
|
1915
|
+
var TYPESCRIPT_DIRECTORIES = [
|
|
1916
|
+
"data/scripts",
|
|
1917
|
+
"data/scripts/lib",
|
|
1918
|
+
"data/scripts/modules",
|
|
1919
|
+
"filters",
|
|
1920
|
+
"filters/rolldown",
|
|
1921
|
+
"filters/typegen"
|
|
1820
1922
|
];
|
|
1821
|
-
function
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
}
|
|
1828
|
-
async function writeTextFile(filePath, value) {
|
|
1829
|
-
await writeFile(filePath, value, "utf8");
|
|
1830
|
-
}
|
|
1831
|
-
async function createTypegenFilterMain() {
|
|
1832
|
-
for (const templateUrl of TYPEGEN_FILTER_TEMPLATE_URLS) {
|
|
1833
|
-
const templateFile = Bun.file(templateUrl);
|
|
1834
|
-
const exists = await templateFile.exists().then((value) => value, () => false);
|
|
1835
|
-
if (exists) {
|
|
1836
|
-
return await templateFile.text();
|
|
1837
|
-
}
|
|
1923
|
+
function planProject(config, versions) {
|
|
1924
|
+
const directories = new Set(["packs", "packs/BP", "packs/RP"]);
|
|
1925
|
+
const files = [];
|
|
1926
|
+
const marketplaceScope = getMarketplaceScopeSegments(config).join("/");
|
|
1927
|
+
for (const directory of BP_DIRECTORIES) {
|
|
1928
|
+
directories.add(`packs/BP/${directory}`);
|
|
1838
1929
|
}
|
|
1839
|
-
|
|
1840
|
-
}
|
|
1841
|
-
function getScopedContentDirectory(basePath, folder, config) {
|
|
1842
|
-
return join(basePath, folder, ...getMarketplaceScopeSegments(config));
|
|
1843
|
-
}
|
|
1844
|
-
function getScopedNestedContentDirectory(basePath, segments, config) {
|
|
1845
|
-
return join(basePath, ...segments, ...getMarketplaceScopeSegments(config));
|
|
1846
|
-
}
|
|
1847
|
-
function shouldCreateDirectory(directory) {
|
|
1848
|
-
return directory !== "." && directory !== "./" && directory !== ".\\";
|
|
1849
|
-
}
|
|
1850
|
-
async function generateProject(config) {
|
|
1851
|
-
const destination = config.destination;
|
|
1852
|
-
const bpPath = join(destination, "packs", "BP");
|
|
1853
|
-
const rpPath = join(destination, "packs", "RP");
|
|
1854
|
-
const bpScriptPath = join(bpPath, ...getScriptDirectorySegments(config));
|
|
1855
|
-
const dataScriptsPath = join(destination, "data", "scripts");
|
|
1856
|
-
const directories = [
|
|
1857
|
-
destination,
|
|
1858
|
-
join(destination, "packs"),
|
|
1859
|
-
bpPath,
|
|
1860
|
-
join(bpPath, "animation_controllers"),
|
|
1861
|
-
join(bpPath, "animations"),
|
|
1862
|
-
join(bpPath, "blocks"),
|
|
1863
|
-
join(bpPath, "entities"),
|
|
1864
|
-
join(bpPath, "items"),
|
|
1865
|
-
join(bpPath, "loot_tables"),
|
|
1866
|
-
join(bpPath, "recipes"),
|
|
1867
|
-
join(bpPath, "spawn_rules"),
|
|
1868
|
-
join(bpPath, "structures"),
|
|
1869
|
-
join(bpPath, "texts"),
|
|
1870
|
-
join(bpPath, "trading"),
|
|
1871
|
-
rpPath,
|
|
1872
|
-
join(rpPath, "animation_controllers"),
|
|
1873
|
-
join(rpPath, "animations"),
|
|
1874
|
-
join(rpPath, "attachables"),
|
|
1875
|
-
join(rpPath, "entity"),
|
|
1876
|
-
join(rpPath, "fogs"),
|
|
1877
|
-
join(rpPath, "models"),
|
|
1878
|
-
join(rpPath, "models", "entity"),
|
|
1879
|
-
join(rpPath, "particles"),
|
|
1880
|
-
join(rpPath, "render_controllers"),
|
|
1881
|
-
join(rpPath, "sounds"),
|
|
1882
|
-
join(rpPath, "texts"),
|
|
1883
|
-
join(rpPath, "textures"),
|
|
1884
|
-
join(rpPath, "textures", "blocks"),
|
|
1885
|
-
join(rpPath, "textures", "entity"),
|
|
1886
|
-
join(rpPath, "textures", "items"),
|
|
1887
|
-
join(rpPath, "ui")
|
|
1888
|
-
];
|
|
1889
|
-
if (config.useMarketplaceStructure) {
|
|
1890
|
-
directories.push(...BP_NAMESPACED_DIRECTORIES.map((folder) => getScopedContentDirectory(bpPath, folder, config)), ...RP_NAMESPACED_DIRECTORIES.map((folder) => getScopedContentDirectory(rpPath, folder, config)), ...RP_NAMESPACED_NESTED_DIRECTORIES.map((segments) => getScopedNestedContentDirectory(rpPath, segments, config)));
|
|
1930
|
+
for (const directory of RP_DIRECTORIES) {
|
|
1931
|
+
directories.add(`packs/RP/${directory}`);
|
|
1891
1932
|
}
|
|
1892
|
-
if (config.
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
directories.
|
|
1897
|
-
|
|
1898
|
-
|
|
1933
|
+
if (config.useMarketplaceStructure) {
|
|
1934
|
+
for (const directory of RP_TEXTURE_DIRECTORIES) {
|
|
1935
|
+
directories.add(`packs/RP/textures/${marketplaceScope}/${directory}`);
|
|
1936
|
+
}
|
|
1937
|
+
directories.add(`packs/RP/sounds/${marketplaceScope}`);
|
|
1938
|
+
} else {
|
|
1939
|
+
for (const directory of RP_TEXTURE_DIRECTORIES) {
|
|
1940
|
+
directories.add(`packs/RP/textures/${directory}`);
|
|
1899
1941
|
}
|
|
1900
1942
|
}
|
|
1901
|
-
if (config.useRgl && config.scripting !== "none") {
|
|
1902
|
-
directories.push(join(destination, "filters"), join(destination, "filters", "rolldown"), join(destination, "filters", "typegen"));
|
|
1903
|
-
}
|
|
1904
|
-
await Promise.all(directories.filter(shouldCreateDirectory).map((directory) => mkdir(directory, { recursive: true })));
|
|
1905
1943
|
const bpUuid = crypto.randomUUID();
|
|
1906
1944
|
const rpUuid = crypto.randomUUID();
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
writeJsonFile(join(rpPath, "manifest.json"), generateRpManifest(config, rpUuid, bpUuid)),
|
|
1911
|
-
writeTextFile(join(bpPath, "texts", "en_US.lang"), generateLangFile(config.projectName, "behavior")),
|
|
1912
|
-
writeTextFile(join(rpPath, "texts", "en_US.lang"), generateLangFile(config.projectName, "resource")),
|
|
1913
|
-
writeJsonFile(join(rpPath, "blocks.json"), generateBlocksJson()),
|
|
1914
|
-
writeJsonFile(join(rpPath, "sounds.json"), generateSoundsJson()),
|
|
1915
|
-
writeJsonFile(join(rpPath, "sounds", "sound_definitions.json"), generateSoundDefinitions()),
|
|
1916
|
-
writeJsonFile(join(rpPath, "textures", "item_texture.json"), generateItemTexture(config)),
|
|
1917
|
-
writeJsonFile(join(rpPath, "textures", "terrain_texture.json"), generateTerrainTexture(config)),
|
|
1918
|
-
writeJsonFile(join(rpPath, "textures", "flipbook_textures.json"), []),
|
|
1919
|
-
writeJsonFile(join(bpPath, "texts", "languages.json"), ["en_US"]),
|
|
1920
|
-
writeJsonFile(join(rpPath, "texts", "languages.json"), ["en_US"]),
|
|
1921
|
-
writeTextFile(join(destination, ".gitignore"), generateGitignore(config)),
|
|
1922
|
-
writeTextFile(join(destination, "README.md"), generateReadme(config))
|
|
1923
|
-
];
|
|
1924
|
-
if (config.scripting !== "none") {
|
|
1925
|
-
writes.push(writeJsonFile(join(destination, "package.json"), generatePackageJson(config, versions)));
|
|
1926
|
-
}
|
|
1927
|
-
if (config.scripting === "javascript") {
|
|
1928
|
-
writes.push(writeTextFile(join(bpScriptPath, "main.js"), generateMainJs(config)));
|
|
1945
|
+
files.push({ path: "packs/BP/manifest.json", content: stringifyJson(generateBpManifest(config, bpUuid, rpUuid, versions)) }, { path: "packs/RP/manifest.json", content: stringifyJson(generateRpManifest(config, rpUuid, bpUuid, versions)) }, { path: "packs/BP/texts/en_US.lang", content: generateLangFile(config.projectName, "behavior") }, { path: "packs/BP/texts/languages.json", content: stringifyJson(["en_US"]) }, { path: "packs/RP/texts/en_US.lang", content: generateLangFile(config.projectName, "resource") }, { path: "packs/RP/texts/languages.json", content: stringifyJson(["en_US"]) }, { path: "packs/RP/blocks.json", content: generateBlocksJson() }, { path: "packs/RP/sounds.json", content: generateSoundsJson() }, { path: "packs/RP/sounds/sound_definitions.json", content: generateSoundDefinitions() }, { path: "packs/RP/textures/item_texture.json", content: generateItemTexture() }, { path: "packs/RP/textures/terrain_texture.json", content: generateTerrainTexture() }, { path: "packs/RP/textures/flipbook_textures.json", content: stringifyJson([]) }, { path: ".gitignore", content: generateGitignore(config) }, { path: ".gitattributes", content: generateGitattributes() }, { path: ".vscode/extensions.json", content: generateVscodeExtensions(config) }, { path: "README.md", content: generateReadme(config) });
|
|
1946
|
+
if (config.generateAgentsDoc) {
|
|
1947
|
+
files.push({ path: "AGENTS.md", content: generateAgentsDoc() });
|
|
1929
1948
|
}
|
|
1930
1949
|
if (config.scripting === "typescript") {
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
}
|
|
1934
|
-
if (config.scripting !== "none" && config.useRgl) {
|
|
1935
|
-
writes.push(writeJsonFile(join(destination, "config.json"), generateRglConfig(config)), writeTextFile(join(destination, "filters", "rolldown", "main.js"), generateRolldownFilterMain(config)), writeJsonFile(join(destination, "filters", "rolldown", "package.json"), generateRolldownFilterPackageJson()), writeJsonFile(join(destination, "filters", "typegen", "package.json"), generateTypegenFilterPackageJson()), writeTextFile(join(destination, "filters", "typegen", "main.js"), await createTypegenFilterMain()));
|
|
1936
|
-
}
|
|
1937
|
-
await Promise.all(writes);
|
|
1938
|
-
}
|
|
1939
|
-
|
|
1940
|
-
// src/provisioning/ai.ts
|
|
1941
|
-
import { mkdir as mkdir2 } from "fs/promises";
|
|
1942
|
-
import { join as join3 } from "path";
|
|
1943
|
-
|
|
1944
|
-
// src/provisioning/mcp.ts
|
|
1945
|
-
import { join as join2 } from "path";
|
|
1946
|
-
function buildMcpServers() {
|
|
1947
|
-
return {
|
|
1948
|
-
exa: {
|
|
1949
|
-
url: "https://mcp.exa.ai/mcp"
|
|
1950
|
-
},
|
|
1951
|
-
grep_app: {
|
|
1952
|
-
command: "npx",
|
|
1953
|
-
args: ["-y", "grep-mcp"]
|
|
1954
|
-
},
|
|
1955
|
-
context7: {
|
|
1956
|
-
command: "npx",
|
|
1957
|
-
args: ["-y", "@upstash/context7-mcp"]
|
|
1958
|
-
}
|
|
1959
|
-
};
|
|
1960
|
-
}
|
|
1961
|
-
async function generateMcpConfig(projectPath) {
|
|
1962
|
-
const mcpPath = join2(projectPath, ".mcp.json");
|
|
1963
|
-
const config = { mcpServers: buildMcpServers() };
|
|
1964
|
-
await Bun.write(mcpPath, JSON.stringify(config, null, 2) + `
|
|
1965
|
-
`).then(() => {
|
|
1966
|
-
return;
|
|
1967
|
-
}, () => {
|
|
1968
|
-
return;
|
|
1969
|
-
});
|
|
1970
|
-
}
|
|
1971
|
-
|
|
1972
|
-
// src/provisioning/ai.ts
|
|
1973
|
-
var AI_EXCLUDE_LINES = [
|
|
1974
|
-
"# AI tool files",
|
|
1975
|
-
"/CLAUDE.md",
|
|
1976
|
-
"/AGENTS.md",
|
|
1977
|
-
"/.mcp.json",
|
|
1978
|
-
"/opencode.json",
|
|
1979
|
-
"/.claude/"
|
|
1980
|
-
];
|
|
1981
|
-
function getTemplateUrls() {
|
|
1982
|
-
return [
|
|
1983
|
-
new URL("../templates/AGENTS.md", import.meta.url),
|
|
1984
|
-
new URL("../../templates/AGENTS.md", import.meta.url)
|
|
1985
|
-
];
|
|
1986
|
-
}
|
|
1987
|
-
async function createAiDocContent() {
|
|
1988
|
-
const templateUrls = getTemplateUrls();
|
|
1989
|
-
for (const templateUrl of templateUrls) {
|
|
1990
|
-
const templateFile = Bun.file(templateUrl);
|
|
1991
|
-
const exists = await templateFile.exists().then((value) => value, () => false);
|
|
1992
|
-
if (exists) {
|
|
1993
|
-
return await templateFile.text();
|
|
1950
|
+
for (const directory of TYPESCRIPT_DIRECTORIES) {
|
|
1951
|
+
directories.add(directory);
|
|
1994
1952
|
}
|
|
1953
|
+
files.push({ path: "package.json", content: generatePackageJson(config, versions) }, { path: "config.json", content: generateRglConfig(config) }, { path: "dprint.json", content: generateDprintConfig() }, { path: "data/scripts/main.ts", content: generateMainTs(config) }, { path: "data/scripts/tsconfig.json", content: generateScriptsTsConfig() }, { path: "filters/rolldown/main.js", content: generateRolldownFilterMain(config) }, { path: "filters/rolldown/package.json", content: generateRolldownFilterPackageJson() }, { path: "filters/typegen/main.js", content: generateTypegenFilterMain() }, { path: "filters/typegen/package.json", content: generateTypegenFilterPackageJson() });
|
|
1995
1954
|
}
|
|
1996
|
-
return
|
|
1997
|
-
}
|
|
1998
|
-
async function generateAiDoc(projectPath, aiSetup) {
|
|
1999
|
-
const filename = getAiDocFilename(aiSetup);
|
|
2000
|
-
if (filename === null) {
|
|
2001
|
-
return;
|
|
2002
|
-
}
|
|
2003
|
-
const outputPath = join3(projectPath, filename);
|
|
2004
|
-
const content = await createAiDocContent();
|
|
2005
|
-
await Bun.write(outputPath, content).then(() => {
|
|
2006
|
-
return;
|
|
2007
|
-
}, () => {
|
|
2008
|
-
return;
|
|
2009
|
-
});
|
|
2010
|
-
}
|
|
2011
|
-
async function setupGitExcludes(projectPath) {
|
|
2012
|
-
const gitInfoPath = join3(projectPath, ".git", "info");
|
|
2013
|
-
const excludePath = join3(gitInfoPath, "exclude");
|
|
2014
|
-
const directoryReady = await mkdir2(gitInfoPath, { recursive: true }).then(() => true, () => false);
|
|
2015
|
-
if (!directoryReady) {
|
|
2016
|
-
return;
|
|
2017
|
-
}
|
|
2018
|
-
const excludeFile = Bun.file(excludePath);
|
|
2019
|
-
const excludeExists = await excludeFile.exists().then((exists) => exists, () => false);
|
|
2020
|
-
const existingContent = excludeExists ? await excludeFile.text().then((content) => content, () => "") : "";
|
|
2021
|
-
const existingLines = new Set(existingContent.split(/\r?\n/));
|
|
2022
|
-
const missingLines = AI_EXCLUDE_LINES.filter((line) => !existingLines.has(line));
|
|
2023
|
-
if (missingLines.length === 0) {
|
|
2024
|
-
return;
|
|
2025
|
-
}
|
|
2026
|
-
const separator = existingContent.length > 0 && !existingContent.endsWith(`
|
|
2027
|
-
`) ? `
|
|
2028
|
-
` : "";
|
|
2029
|
-
const nextContent = `${existingContent}${separator}${missingLines.join(`
|
|
2030
|
-
`)}
|
|
2031
|
-
`;
|
|
2032
|
-
await Bun.write(excludePath, nextContent).then(() => {
|
|
2033
|
-
return;
|
|
2034
|
-
}, () => {
|
|
2035
|
-
return;
|
|
2036
|
-
});
|
|
2037
|
-
}
|
|
2038
|
-
async function writeOpencodePluginConfig(projectPath) {
|
|
2039
|
-
const configPath = join3(projectPath, "opencode.json");
|
|
2040
|
-
const pluginId = "@dietrichgebert/ponytail";
|
|
2041
|
-
const file = Bun.file(configPath);
|
|
2042
|
-
const exists = await file.exists().then((value) => value, () => false);
|
|
2043
|
-
let nextConfig = {
|
|
2044
|
-
$schema: "https://opencode.ai/config.json",
|
|
2045
|
-
plugin: [pluginId]
|
|
2046
|
-
};
|
|
2047
|
-
if (exists) {
|
|
2048
|
-
try {
|
|
2049
|
-
const parsed = await file.json();
|
|
2050
|
-
const plugins = Array.isArray(parsed.plugin) ? [...parsed.plugin] : [];
|
|
2051
|
-
if (!plugins.includes(pluginId)) {
|
|
2052
|
-
plugins.push(pluginId);
|
|
2053
|
-
}
|
|
2054
|
-
nextConfig = { ...parsed, plugin: plugins };
|
|
2055
|
-
} catch {}
|
|
2056
|
-
}
|
|
2057
|
-
await Bun.write(configPath, `${JSON.stringify(nextConfig, null, 4)}
|
|
2058
|
-
`).then(() => {
|
|
2059
|
-
return;
|
|
2060
|
-
}, () => {
|
|
2061
|
-
return;
|
|
2062
|
-
});
|
|
1955
|
+
return { directories: [...directories].sort(), files };
|
|
2063
1956
|
}
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
1957
|
+
|
|
1958
|
+
// src/engine/writer.ts
|
|
1959
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
1960
|
+
import { dirname, join, resolve } from "path";
|
|
1961
|
+
async function writeProject(plan, destination) {
|
|
1962
|
+
const root = resolve(destination);
|
|
1963
|
+
await mkdir(root, { recursive: true });
|
|
1964
|
+
for (const directory of plan.directories) {
|
|
1965
|
+
await mkdir(join(root, directory), { recursive: true });
|
|
2067
1966
|
}
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
await writeOpencodePluginConfig(projectPath);
|
|
1967
|
+
for (const file of plan.files) {
|
|
1968
|
+
const filePath = join(root, file.path);
|
|
1969
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
1970
|
+
await writeFile(filePath, file.content, "utf8");
|
|
2073
1971
|
}
|
|
2074
1972
|
}
|
|
2075
1973
|
|
|
2076
1974
|
// src/provisioning/tools.ts
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
return runCommand(lookupCommand);
|
|
2089
|
-
}
|
|
2090
|
-
async function installRgl() {
|
|
2091
|
-
if (await isCommandAvailable("rgl")) {
|
|
2092
|
-
return true;
|
|
2093
|
-
}
|
|
2094
|
-
if (process.platform !== "win32") {
|
|
2095
|
-
return false;
|
|
2096
|
-
}
|
|
2097
|
-
const installed = await runCommand([
|
|
2098
|
-
"powershell",
|
|
2099
|
-
"-Command",
|
|
2100
|
-
"irm rgl.ink0rr.dev/install.ps1 | iex"
|
|
2101
|
-
]);
|
|
2102
|
-
if (!installed) {
|
|
1975
|
+
async function runCommand(command, cwd) {
|
|
1976
|
+
try {
|
|
1977
|
+
const child = Bun.spawn({
|
|
1978
|
+
cmd: command,
|
|
1979
|
+
cwd,
|
|
1980
|
+
stdout: "ignore",
|
|
1981
|
+
stderr: "ignore"
|
|
1982
|
+
});
|
|
1983
|
+
const exitCode = await child.exited;
|
|
1984
|
+
return exitCode === 0;
|
|
1985
|
+
} catch {
|
|
2103
1986
|
return false;
|
|
2104
1987
|
}
|
|
2105
|
-
return isCommandAvailable("rgl");
|
|
2106
1988
|
}
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
return runCommand([
|
|
2110
|
-
"code",
|
|
2111
|
-
"--install-extension",
|
|
2112
|
-
"rockide.rockide-vscode"
|
|
2113
|
-
]);
|
|
2114
|
-
}
|
|
2115
|
-
if (await isCommandAvailable("cursor")) {
|
|
2116
|
-
return runCommand([
|
|
2117
|
-
"cursor",
|
|
2118
|
-
"--install-extension",
|
|
2119
|
-
"rockide.rockide-vscode"
|
|
2120
|
-
]);
|
|
2121
|
-
}
|
|
2122
|
-
return false;
|
|
1989
|
+
function hasRgl() {
|
|
1990
|
+
return Bun.which("rgl") !== null;
|
|
2123
1991
|
}
|
|
2124
1992
|
async function installDependencies(projectPath) {
|
|
2125
|
-
const
|
|
2126
|
-
|
|
2127
|
-
if (!pkgExists) {
|
|
2128
|
-
return true;
|
|
2129
|
-
}
|
|
2130
|
-
const command = await isCommandAvailable("bun") ? ["bun", "install"] : ["npm", "install"];
|
|
2131
|
-
return runCommand(command, projectPath);
|
|
2132
|
-
}
|
|
2133
|
-
async function runProvisioning(config) {
|
|
2134
|
-
const results = {
|
|
2135
|
-
rgl: null,
|
|
2136
|
-
rockide: null,
|
|
2137
|
-
dependencies: null
|
|
2138
|
-
};
|
|
2139
|
-
if (config.useRgl) {
|
|
2140
|
-
results.rgl = await installRgl();
|
|
2141
|
-
}
|
|
2142
|
-
if (config.installRockide) {
|
|
2143
|
-
results.rockide = await installRockide();
|
|
2144
|
-
}
|
|
2145
|
-
if (config.scripting !== "none") {
|
|
2146
|
-
results.dependencies = await installDependencies(config.destination);
|
|
2147
|
-
}
|
|
2148
|
-
return results;
|
|
1993
|
+
const command = Bun.which("bun") === null ? ["npm", "install"] : ["bun", "install"];
|
|
1994
|
+
return await runCommand(command, projectPath);
|
|
2149
1995
|
}
|
|
2150
1996
|
|
|
2151
1997
|
// src/tui/display.ts
|
|
2152
1998
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
1999
|
+
|
|
2000
|
+
// src/tui/theme.ts
|
|
2153
2001
|
var teal = (value) => `\x1B[38;2;47;208;181m${value}\x1B[39m`;
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
return bgTeal(`\x1B[97m${value}\x1B[39m`);
|
|
2159
|
-
}
|
|
2002
|
+
var bgTeal = (value) => `\x1B[48;2;47;208;181m${value}\x1B[49m`;
|
|
2003
|
+
var whiteOnTeal = (value) => bgTeal(`\x1B[97m${value}\x1B[39m`);
|
|
2004
|
+
|
|
2005
|
+
// src/tui/display.ts
|
|
2160
2006
|
function getScriptingLabel(choice) {
|
|
2161
|
-
|
|
2162
|
-
return "TypeScript";
|
|
2163
|
-
}
|
|
2164
|
-
if (choice === "javascript") {
|
|
2165
|
-
return "JavaScript";
|
|
2166
|
-
}
|
|
2167
|
-
return "None";
|
|
2168
|
-
}
|
|
2169
|
-
function getAiSetupLabel(choice) {
|
|
2170
|
-
if (choice === "claude") {
|
|
2171
|
-
return "Claude";
|
|
2172
|
-
}
|
|
2173
|
-
if (choice === "other") {
|
|
2174
|
-
return "Other";
|
|
2175
|
-
}
|
|
2176
|
-
return "None";
|
|
2007
|
+
return choice === "typescript" ? "TypeScript" : "None";
|
|
2177
2008
|
}
|
|
2178
2009
|
function getSelectedPackages(scriptPackages) {
|
|
2179
2010
|
const packages = [];
|
|
@@ -2207,172 +2038,103 @@ function getTreeRoot(config) {
|
|
|
2207
2038
|
}
|
|
2208
2039
|
return destination.replace(/[\\/]+$/, "");
|
|
2209
2040
|
}
|
|
2210
|
-
function
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
const
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
pushScopedFolder(lines, "\u2502 \u2502 \u251C\u2500 ", "\u2502 \u2502 \u2502 \u2514\u2500 ", "blocks", config);
|
|
2223
|
-
pushScopedFolder(lines, "\u2502 \u2502 \u251C\u2500 ", "\u2502 \u2502 \u2502 \u2514\u2500 ", "entities", config);
|
|
2224
|
-
pushScopedFolder(lines, "\u2502 \u2502 \u251C\u2500 ", "\u2502 \u2502 \u2502 \u2514\u2500 ", "items", config);
|
|
2225
|
-
pushScopedFolder(lines, "\u2502 \u2502 \u251C\u2500 ", "\u2502 \u2502 \u2502 \u2514\u2500 ", "loot_tables", config);
|
|
2226
|
-
pushScopedFolder(lines, "\u2502 \u2502 \u251C\u2500 ", "\u2502 \u2502 \u2502 \u2514\u2500 ", "recipes", config);
|
|
2227
|
-
pushScopedFolder(lines, "\u2502 \u2502 \u251C\u2500 ", "\u2502 \u2502 \u2502 \u2514\u2500 ", "spawn_rules", config);
|
|
2228
|
-
pushScopedFolder(lines, "\u2502 \u2502 \u251C\u2500 ", "\u2502 \u2502 \u2502 \u2514\u2500 ", "structures", config);
|
|
2229
|
-
lines.push(import_picocolors.default.dim("\u2502 \u2502 \u251C\u2500 texts/"));
|
|
2230
|
-
pushScopedFolder(lines, "\u2502 \u2502 \u251C\u2500 ", "\u2502 \u2502 \u2502 \u2514\u2500 ", "trading", config);
|
|
2231
|
-
if (config.scripting === "javascript" || config.scripting === "typescript" && !config.useRgl) {
|
|
2232
|
-
lines.push(import_picocolors.default.dim(`\u2502 \u2502 \u251C\u2500 scripts/${config.identifier}/${config.projectId}/`));
|
|
2233
|
-
}
|
|
2234
|
-
lines.push(import_picocolors.default.dim("\u2502 \u2502 \u2514\u2500 manifest.json"));
|
|
2235
|
-
lines.push(import_picocolors.default.dim("\u2502 \u2514\u2500 RP/"));
|
|
2236
|
-
pushScopedFolder(lines, "\u2502 \u251C\u2500 ", "\u2502 \u2502 \u2514\u2500 ", "animation_controllers", config);
|
|
2237
|
-
pushScopedFolder(lines, "\u2502 \u251C\u2500 ", "\u2502 \u2502 \u2514\u2500 ", "animations", config);
|
|
2238
|
-
pushScopedFolder(lines, "\u2502 \u251C\u2500 ", "\u2502 \u2502 \u2514\u2500 ", "attachables", config);
|
|
2239
|
-
pushScopedFolder(lines, "\u2502 \u251C\u2500 ", "\u2502 \u2502 \u2514\u2500 ", "entity", config);
|
|
2240
|
-
pushScopedFolder(lines, "\u2502 \u251C\u2500 ", "\u2502 \u2502 \u2514\u2500 ", "fogs", config);
|
|
2241
|
-
lines.push(import_picocolors.default.dim("\u2502 \u251C\u2500 models/entity/"));
|
|
2242
|
-
if (config.useMarketplaceStructure) {
|
|
2243
|
-
lines.push(import_picocolors.default.dim(`\u2502 \u2502 \u2514\u2500 ${getMarketplaceScopeLabel(config)}/`));
|
|
2244
|
-
}
|
|
2245
|
-
pushScopedFolder(lines, "\u2502 \u251C\u2500 ", "\u2502 \u2502 \u2514\u2500 ", "particles", config);
|
|
2246
|
-
pushScopedFolder(lines, "\u2502 \u251C\u2500 ", "\u2502 \u2502 \u2514\u2500 ", "render_controllers", config);
|
|
2247
|
-
pushScopedFolder(lines, "\u2502 \u251C\u2500 ", "\u2502 \u2502 \u2514\u2500 ", "sounds", config);
|
|
2248
|
-
lines.push(import_picocolors.default.dim("\u2502 \u251C\u2500 texts/"));
|
|
2249
|
-
lines.push(import_picocolors.default.dim("\u2502 \u251C\u2500 textures/blocks/"));
|
|
2250
|
-
if (config.useMarketplaceStructure) {
|
|
2251
|
-
lines.push(import_picocolors.default.dim(`\u2502 \u2502 \u2514\u2500 ${getMarketplaceScopeLabel(config)}/`));
|
|
2252
|
-
}
|
|
2253
|
-
lines.push(import_picocolors.default.dim("\u2502 \u251C\u2500 textures/entity/"));
|
|
2254
|
-
if (config.useMarketplaceStructure) {
|
|
2255
|
-
lines.push(import_picocolors.default.dim(`\u2502 \u2502 \u2514\u2500 ${getMarketplaceScopeLabel(config)}/`));
|
|
2256
|
-
}
|
|
2257
|
-
lines.push(import_picocolors.default.dim("\u2502 \u251C\u2500 textures/items/"));
|
|
2258
|
-
if (config.useMarketplaceStructure) {
|
|
2259
|
-
lines.push(import_picocolors.default.dim(`\u2502 \u2502 \u2514\u2500 ${getMarketplaceScopeLabel(config)}/`));
|
|
2260
|
-
}
|
|
2261
|
-
pushScopedFolder(lines, "\u2502 \u251C\u2500 ", "\u2502 \u2502 \u2514\u2500 ", "ui", config);
|
|
2262
|
-
lines.push(import_picocolors.default.dim("\u2502 \u251C\u2500 blocks.json"));
|
|
2263
|
-
lines.push(import_picocolors.default.dim("\u2502 \u251C\u2500 sounds.json"));
|
|
2264
|
-
lines.push(import_picocolors.default.dim("\u2502 \u251C\u2500 sound_definitions.json"));
|
|
2265
|
-
lines.push(import_picocolors.default.dim("\u2502 \u251C\u2500 item_texture.json"));
|
|
2266
|
-
lines.push(import_picocolors.default.dim("\u2502 \u251C\u2500 terrain_texture.json"));
|
|
2267
|
-
lines.push(import_picocolors.default.dim("\u2502 \u251C\u2500 flipbook_textures.json"));
|
|
2268
|
-
lines.push(import_picocolors.default.dim("\u2502 \u2514\u2500 manifest.json"));
|
|
2269
|
-
if (config.scripting === "typescript") {
|
|
2270
|
-
lines.push(import_picocolors.default.dim("\u251C\u2500 data/scripts/"));
|
|
2271
|
-
if (config.useRgl) {
|
|
2272
|
-
lines.push(import_picocolors.default.dim("\u2502 \u251C\u2500 main.ts"));
|
|
2273
|
-
lines.push(import_picocolors.default.dim("\u2502 \u2514\u2500 tsconfig.json"));
|
|
2274
|
-
lines.push(import_picocolors.default.dim("\u251C\u2500 filters/"));
|
|
2275
|
-
lines.push(import_picocolors.default.dim("\u2502 \u251C\u2500 rolldown/"));
|
|
2276
|
-
lines.push(import_picocolors.default.dim("\u2502 \u2502 \u251C\u2500 main.js"));
|
|
2277
|
-
lines.push(import_picocolors.default.dim("\u2502 \u2502 \u2514\u2500 package.json"));
|
|
2278
|
-
lines.push(import_picocolors.default.dim("\u2502 \u2514\u2500 typegen/"));
|
|
2279
|
-
lines.push(import_picocolors.default.dim("\u2502 \u251C\u2500 main.js"));
|
|
2280
|
-
lines.push(import_picocolors.default.dim("\u2502 \u2514\u2500 package.json"));
|
|
2281
|
-
} else {
|
|
2282
|
-
lines.push(import_picocolors.default.dim("\u2502 \u2514\u2500 main.ts"));
|
|
2283
|
-
lines.push(import_picocolors.default.dim("\u251C\u2500 tsconfig.json"));
|
|
2041
|
+
function createTreeNode() {
|
|
2042
|
+
return { directories: new Map, files: [] };
|
|
2043
|
+
}
|
|
2044
|
+
function addPlanPath(root, path, isDirectory) {
|
|
2045
|
+
const segments = path.split("/").filter((segment) => segment.length > 0);
|
|
2046
|
+
const directorySegments = isDirectory ? segments : segments.slice(0, -1);
|
|
2047
|
+
let current = root;
|
|
2048
|
+
for (const segment of directorySegments) {
|
|
2049
|
+
let child = current.directories.get(segment);
|
|
2050
|
+
if (child === undefined) {
|
|
2051
|
+
child = createTreeNode();
|
|
2052
|
+
current.directories.set(segment, child);
|
|
2284
2053
|
}
|
|
2285
|
-
|
|
2286
|
-
}
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
const
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
lines.push(import_picocolors.default.dim("\u251C\u2500 .
|
|
2300
|
-
if (
|
|
2301
|
-
lines.push(
|
|
2054
|
+
current = child;
|
|
2055
|
+
}
|
|
2056
|
+
const fileName = isDirectory ? undefined : segments.at(-1);
|
|
2057
|
+
if (fileName !== undefined) {
|
|
2058
|
+
current.files.push(fileName);
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
function renderTreeNode(node, prefix) {
|
|
2062
|
+
const directoryEntries = [...node.directories.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([name, child]) => ({ label: `${name}/`, child }));
|
|
2063
|
+
const fileEntries = [...node.files].sort((left, right) => left.localeCompare(right)).map((fileName) => ({ label: fileName, child: undefined }));
|
|
2064
|
+
const entries = [...directoryEntries, ...fileEntries];
|
|
2065
|
+
const lines = [];
|
|
2066
|
+
entries.forEach((entry, index) => {
|
|
2067
|
+
const isLast = index === entries.length - 1;
|
|
2068
|
+
lines.push(import_picocolors.default.dim(`${prefix}${isLast ? "\u2514\u2500 " : "\u251C\u2500 "}${entry.label}`));
|
|
2069
|
+
if (entry.child !== undefined) {
|
|
2070
|
+
lines.push(...renderTreeNode(entry.child, `${prefix}${isLast ? " " : "\u2502 "}`));
|
|
2302
2071
|
}
|
|
2072
|
+
});
|
|
2073
|
+
return lines;
|
|
2074
|
+
}
|
|
2075
|
+
function renderPlanTree(plan, rootLabel) {
|
|
2076
|
+
const root = createTreeNode();
|
|
2077
|
+
for (const directory of plan.directories) {
|
|
2078
|
+
addPlanPath(root, directory, true);
|
|
2303
2079
|
}
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2080
|
+
for (const file of plan.files) {
|
|
2081
|
+
addPlanPath(root, file.path, false);
|
|
2082
|
+
}
|
|
2083
|
+
return [import_picocolors.default.bold(import_picocolors.default.white(rootLabel)), ...renderTreeNode(root, "")].join(`
|
|
2307
2084
|
`);
|
|
2308
2085
|
}
|
|
2309
|
-
function showReview(config) {
|
|
2086
|
+
function showReview(config, plan) {
|
|
2310
2087
|
const border = teal("\u2502");
|
|
2311
|
-
const packages =
|
|
2088
|
+
const packages = getSelectedPackages(config.scriptPackages);
|
|
2089
|
+
const scriptingRows = config.scripting === "typescript" && packages.length > 0 ? [
|
|
2090
|
+
`${border} ${import_picocolors.default.dim(padLabel("Scripting:"))} ${formatValue(getScriptingLabel(config.scripting))}`,
|
|
2091
|
+
`${border} ${import_picocolors.default.dim(padLabel("Packages:"))} ${formatValue(packages.join(", "))}`
|
|
2092
|
+
] : [`${border} ${import_picocolors.default.dim(padLabel("Scripting:"))} ${formatValue(getScriptingLabel(config.scripting))}`];
|
|
2093
|
+
const scopeRows = config.useMarketplaceStructure ? [
|
|
2094
|
+
`${border} ${import_picocolors.default.dim(padLabel("Publisher ID:"))} ${formatValue(config.identifier)}`,
|
|
2095
|
+
`${border} ${import_picocolors.default.dim(padLabel("Project ID:"))} ${formatValue(config.projectId)}`,
|
|
2096
|
+
`${border} ${import_picocolors.default.dim(padLabel("Marketplace structure:"))} ${formatValue(getMarketplaceScopeLabel(config))}`
|
|
2097
|
+
] : [`${border} ${import_picocolors.default.dim(padLabel("Marketplace structure:"))} ${import_picocolors.default.dim("Disabled")}`];
|
|
2312
2098
|
const lines = [
|
|
2313
2099
|
`${whiteOnTeal(" Spawnpack ")} ${import_picocolors.default.dim("Review your Bedrock addon scaffold")}`,
|
|
2314
2100
|
"",
|
|
2315
2101
|
`${border} ${import_picocolors.default.dim(padLabel("Project:"))} ${formatValue(config.projectName)}`,
|
|
2316
2102
|
`${border} ${import_picocolors.default.dim(padLabel("Author:"))} ${config.author ? formatValue(config.author) : import_picocolors.default.dim("\u2014")}`,
|
|
2317
|
-
...
|
|
2318
|
-
`${border} ${import_picocolors.default.dim(padLabel("Publisher ID:"))} ${formatValue(config.identifier)}`,
|
|
2319
|
-
`${border} ${import_picocolors.default.dim(padLabel("Project ID:"))} ${formatValue(config.projectId)}`,
|
|
2320
|
-
`${border} ${import_picocolors.default.dim(padLabel("Marketplace structure:"))} ${formatValue(getMarketplaceScopeLabel(config))}`
|
|
2321
|
-
] : [
|
|
2322
|
-
`${border} ${import_picocolors.default.dim(padLabel("Marketplace structure:"))} ${import_picocolors.default.dim("Disabled")}`
|
|
2323
|
-
],
|
|
2103
|
+
...scopeRows,
|
|
2324
2104
|
`${border} ${import_picocolors.default.dim(padLabel("Destination:"))} ${formatValue(config.destination)}`,
|
|
2325
|
-
|
|
2326
|
-
`${border} ${import_picocolors.default.dim(padLabel("
|
|
2327
|
-
`${border} ${import_picocolors.default.dim(padLabel("rgl:"))} ${formatToggle(config.useRgl)}`,
|
|
2328
|
-
`${border} ${import_picocolors.default.dim(padLabel("Rockide:"))} ${formatToggle(config.installRockide)}`,
|
|
2329
|
-
`${border} ${import_picocolors.default.dim(padLabel("AI Setup:"))} ${formatValue(getAiSetupLabel(config.aiSetup))}`,
|
|
2330
|
-
...config.aiSetup !== "none" ? [`${border} ${import_picocolors.default.dim(padLabel("Ponytail:"))} ${formatToggle(config.installPonytail)}`] : [],
|
|
2105
|
+
...scriptingRows,
|
|
2106
|
+
`${border} ${import_picocolors.default.dim(padLabel("AGENTS.md:"))} ${formatToggle(config.generateAgentsDoc)}`,
|
|
2331
2107
|
"",
|
|
2332
2108
|
`${border} ${teal(import_picocolors.default.bold("Planned structure"))}`,
|
|
2333
|
-
...
|
|
2109
|
+
...renderPlanTree(plan, getTreeRoot(config)).split(`
|
|
2334
2110
|
`).map((line) => `${border} ${line}`)
|
|
2335
2111
|
];
|
|
2336
2112
|
O2.message(lines.join(`
|
|
2337
2113
|
`), { symbol: teal("\u25C6") });
|
|
2338
2114
|
}
|
|
2339
|
-
function showPostGeneration(config) {
|
|
2115
|
+
function showPostGeneration(config, state) {
|
|
2340
2116
|
const nextSteps = [teal(import_picocolors.default.bold("Next steps"))];
|
|
2117
|
+
const usefulCommands = [teal(import_picocolors.default.bold("Useful commands"))];
|
|
2341
2118
|
if (config.destination !== "." && config.destination !== "./") {
|
|
2342
2119
|
nextSteps.push(` ${import_picocolors.default.cyan("cd")} ${formatValue(config.destination)}`);
|
|
2343
2120
|
}
|
|
2344
|
-
if (config.scripting
|
|
2345
|
-
|
|
2346
|
-
}
|
|
2347
|
-
|
|
2121
|
+
if (config.scripting === "typescript") {
|
|
2122
|
+
if (state.dependenciesInstalled === false) {
|
|
2123
|
+
nextSteps.push(` ${import_picocolors.default.yellow("Dependency install failed.")} Run ${import_picocolors.default.cyan("bun install")} ${import_picocolors.default.dim("or")} ${import_picocolors.default.cyan("npm install")} in the project folder.`);
|
|
2124
|
+
}
|
|
2125
|
+
if (!state.rglAvailable) {
|
|
2126
|
+
nextSteps.push(` ${import_picocolors.default.yellow("rgl was not found on your PATH.")} Install it with ${import_picocolors.default.cyan("curl -fsSL rgl.ink0rr.dev/install.sh | sh")} ${import_picocolors.default.dim("(Windows:")} ${import_picocolors.default.cyan("irm rgl.ink0rr.dev/install.ps1 | iex")}${import_picocolors.default.dim(")")}`);
|
|
2127
|
+
}
|
|
2348
2128
|
nextSteps.push(` ${import_picocolors.default.cyan("rgl watch")} ${import_picocolors.default.dim("Watch files and rebuild/export while you work")}`);
|
|
2349
|
-
}
|
|
2350
|
-
const usefulCommands = [teal(import_picocolors.default.bold("Useful commands"))];
|
|
2351
|
-
if (config.useRgl) {
|
|
2352
2129
|
usefulCommands.push(` ${import_picocolors.default.cyan("rgl run")} ${import_picocolors.default.dim("Build for development")}`);
|
|
2353
2130
|
usefulCommands.push(` ${import_picocolors.default.cyan("rgl run build")} ${import_picocolors.default.dim("Build for distribution")}`);
|
|
2354
|
-
}
|
|
2355
|
-
if (config.scripting === "typescript") {
|
|
2356
2131
|
usefulCommands.push(` ${import_picocolors.default.cyan("bun run typecheck")} ${import_picocolors.default.dim("or")} ${import_picocolors.default.cyan("npm run typecheck")} ${import_picocolors.default.dim("Check TypeScript types")}`);
|
|
2132
|
+
usefulCommands.push(` ${import_picocolors.default.cyan("bun run format")} ${import_picocolors.default.dim("or")} ${import_picocolors.default.cyan("npm run format")} ${import_picocolors.default.dim("Format with dprint")}`);
|
|
2133
|
+
} else {
|
|
2134
|
+
nextSteps.push(` ${import_picocolors.default.dim("No dependency install or build step is required. Edit the pack JSON in packs/.")}`);
|
|
2357
2135
|
}
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
}
|
|
2361
|
-
if (config.aiSetup !== "none") {
|
|
2362
|
-
usefulCommands.push("");
|
|
2363
|
-
usefulCommands.push(`${teal(import_picocolors.default.bold("Note"))} ${import_picocolors.default.dim(".mcp.json is ready to use \u2014 the configured MCP servers need no API keys.")}`);
|
|
2364
|
-
}
|
|
2365
|
-
if (config.installPonytail) {
|
|
2366
|
-
usefulCommands.push("");
|
|
2367
|
-
if (config.aiSetup === "claude") {
|
|
2368
|
-
usefulCommands.push(`${teal(import_picocolors.default.bold("Ponytail"))} ${import_picocolors.default.dim("Run inside Claude Code:")}`);
|
|
2369
|
-
usefulCommands.push(` ${import_picocolors.default.cyan("/plugin marketplace add DietrichGebert/ponytail")}`);
|
|
2370
|
-
usefulCommands.push(` ${import_picocolors.default.cyan("/plugin install ponytail@ponytail")}`);
|
|
2371
|
-
} else {
|
|
2372
|
-
usefulCommands.push(`${teal(import_picocolors.default.bold("Ponytail"))} ${import_picocolors.default.dim("Added to opencode.json \u2014 installs on next opencode run.")}`);
|
|
2373
|
-
}
|
|
2374
|
-
}
|
|
2375
|
-
O2.message([...nextSteps, "", ...usefulCommands].join(`
|
|
2136
|
+
const sections = usefulCommands.length > 1 ? [...nextSteps, "", ...usefulCommands] : nextSteps;
|
|
2137
|
+
O2.message(sections.join(`
|
|
2376
2138
|
`), {
|
|
2377
2139
|
symbol: teal("\u25B2")
|
|
2378
2140
|
});
|
|
@@ -2380,12 +2142,6 @@ function showPostGeneration(config) {
|
|
|
2380
2142
|
|
|
2381
2143
|
// src/tui/wizard.ts
|
|
2382
2144
|
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
2383
|
-
var teal2 = (value) => `\x1B[38;2;47;208;181m${value}\x1B[39m`;
|
|
2384
|
-
var bgTeal2 = (value) => `\x1B[48;2;47;208;181m${value}\x1B[49m`;
|
|
2385
|
-
function abortWizard() {
|
|
2386
|
-
pt(import_picocolors2.default.red("Spawnpack cancelled."));
|
|
2387
|
-
return null;
|
|
2388
|
-
}
|
|
2389
2145
|
function toScriptPackages(selected) {
|
|
2390
2146
|
return {
|
|
2391
2147
|
server: selected.includes("server"),
|
|
@@ -2394,8 +2150,12 @@ function toScriptPackages(selected) {
|
|
|
2394
2150
|
math: selected.includes("math")
|
|
2395
2151
|
};
|
|
2396
2152
|
}
|
|
2153
|
+
function abortWizard() {
|
|
2154
|
+
pt(import_picocolors2.default.red("Spawnpack cancelled."));
|
|
2155
|
+
return null;
|
|
2156
|
+
}
|
|
2397
2157
|
async function runWizard() {
|
|
2398
|
-
mt(`${
|
|
2158
|
+
mt(`${whiteOnTeal(import_picocolors2.default.bold(" Spawnpack "))} ${teal("Initialize your Minecraft Bedrock addon")}`);
|
|
2399
2159
|
const projectName = await Ot({
|
|
2400
2160
|
message: import_picocolors2.default.bold("Project name"),
|
|
2401
2161
|
placeholder: "My Cool Addon",
|
|
@@ -2426,7 +2186,7 @@ async function runWizard() {
|
|
|
2426
2186
|
return abortWizard();
|
|
2427
2187
|
}
|
|
2428
2188
|
const useMarketplaceStructure = await ot2({
|
|
2429
|
-
message: `${import_picocolors2.default.bold("Marketplace Add-On structure?")} ${import_picocolors2.default.dim("Nest
|
|
2189
|
+
message: `${import_picocolors2.default.bold("Marketplace Add-On structure?")} ${import_picocolors2.default.dim("Nest RP textures and sounds under publisher_id/project_id")}`,
|
|
2430
2190
|
initialValue: false
|
|
2431
2191
|
});
|
|
2432
2192
|
if (q(useMarketplaceStructure)) {
|
|
@@ -2460,16 +2220,15 @@ async function runWizard() {
|
|
|
2460
2220
|
message: import_picocolors2.default.bold("Scripting API"),
|
|
2461
2221
|
initialValue: "typescript",
|
|
2462
2222
|
options: [
|
|
2463
|
-
{ value: "none", label: "None", hint: "manifest-only addon
|
|
2464
|
-
{ value: "
|
|
2465
|
-
{ value: "typescript", label: "TypeScript", hint: "recommended" }
|
|
2223
|
+
{ value: "none", label: "None", hint: "manifest-only addon, no build step" },
|
|
2224
|
+
{ value: "typescript", label: "TypeScript", hint: "recommended, built with rgl" }
|
|
2466
2225
|
]
|
|
2467
2226
|
});
|
|
2468
2227
|
if (q(scripting)) {
|
|
2469
2228
|
return abortWizard();
|
|
2470
2229
|
}
|
|
2471
2230
|
if (useMarketplaceStructure || scripting !== "none") {
|
|
2472
|
-
const publisherHint = useMarketplaceStructure ? "used for
|
|
2231
|
+
const publisherHint = useMarketplaceStructure ? "used for marketplace folders like publisher_id/project_id" : "used for script output paths and package naming";
|
|
2473
2232
|
const publisherId = await Ot({
|
|
2474
2233
|
message: `${import_picocolors2.default.bold("Publisher ID")} ${import_picocolors2.default.dim(publisherHint)}`,
|
|
2475
2234
|
placeholder: defaultPublisherId,
|
|
@@ -2507,7 +2266,6 @@ async function runWizard() {
|
|
|
2507
2266
|
projectIdValue = projectId.trim();
|
|
2508
2267
|
}
|
|
2509
2268
|
let scriptPackages = { ...DEFAULT_SCRIPT_PACKAGES };
|
|
2510
|
-
let useRgl = false;
|
|
2511
2269
|
if (scripting !== "none") {
|
|
2512
2270
|
const selectedPackages = await yt({
|
|
2513
2271
|
message: import_picocolors2.default.bold("Script packages"),
|
|
@@ -2524,46 +2282,15 @@ async function runWizard() {
|
|
|
2524
2282
|
return abortWizard();
|
|
2525
2283
|
}
|
|
2526
2284
|
scriptPackages = toScriptPackages(Array.from(new Set(["server", ...selectedPackages])));
|
|
2527
|
-
const rglChoice = await ot2({
|
|
2528
|
-
message: `${import_picocolors2.default.bold("Use rgl?")} ${import_picocolors2.default.dim("fast Bedrock addon compiler, 16x faster than Regolith")}`,
|
|
2529
|
-
initialValue: true
|
|
2530
|
-
});
|
|
2531
|
-
if (q(rglChoice)) {
|
|
2532
|
-
return abortWizard();
|
|
2533
|
-
}
|
|
2534
|
-
useRgl = rglChoice;
|
|
2535
2285
|
}
|
|
2536
|
-
const
|
|
2537
|
-
message: `${import_picocolors2.default.bold("
|
|
2286
|
+
const generateAgentsDoc = await ot2({
|
|
2287
|
+
message: `${import_picocolors2.default.bold("Generate AGENTS.md?")} ${import_picocolors2.default.dim("working rules for AI coding agents")}`,
|
|
2538
2288
|
initialValue: true
|
|
2539
2289
|
});
|
|
2540
|
-
if (q(
|
|
2541
|
-
return abortWizard();
|
|
2542
|
-
}
|
|
2543
|
-
const aiSetup = await _t({
|
|
2544
|
-
message: import_picocolors2.default.bold("AI setup"),
|
|
2545
|
-
initialValue: "none",
|
|
2546
|
-
options: [
|
|
2547
|
-
{ value: "none", label: "None", hint: "No AI configuration setup" },
|
|
2548
|
-
{ value: "claude", label: "Claude", hint: "generate CLAUDE.md and .mcp.json" },
|
|
2549
|
-
{ value: "other", label: "Other", hint: "generate AGENTS.md and .mcp.json" }
|
|
2550
|
-
]
|
|
2551
|
-
});
|
|
2552
|
-
if (q(aiSetup)) {
|
|
2290
|
+
if (q(generateAgentsDoc)) {
|
|
2553
2291
|
return abortWizard();
|
|
2554
2292
|
}
|
|
2555
|
-
|
|
2556
|
-
if (aiSetup !== "none") {
|
|
2557
|
-
const ponytailChoice = await ot2({
|
|
2558
|
-
message: `${import_picocolors2.default.bold("Install ponytail plugin?")} ${import_picocolors2.default.dim("Makes your AI agent think like the laziest senior dev in the room. The best code is the code you never wrote. https://github.com/DietrichGebert/ponytail")}`,
|
|
2559
|
-
initialValue: true
|
|
2560
|
-
});
|
|
2561
|
-
if (q(ponytailChoice)) {
|
|
2562
|
-
return abortWizard();
|
|
2563
|
-
}
|
|
2564
|
-
installPonytail = ponytailChoice;
|
|
2565
|
-
}
|
|
2566
|
-
const config = {
|
|
2293
|
+
return {
|
|
2567
2294
|
projectName: trimmedProjectName,
|
|
2568
2295
|
author: author.trim(),
|
|
2569
2296
|
identifier: identifierValue,
|
|
@@ -2572,41 +2299,39 @@ async function runWizard() {
|
|
|
2572
2299
|
scripting,
|
|
2573
2300
|
scriptPackages: scripting === "none" ? { ...DEFAULT_SCRIPT_PACKAGES } : scriptPackages,
|
|
2574
2301
|
useMarketplaceStructure,
|
|
2575
|
-
|
|
2576
|
-
aiSetup,
|
|
2577
|
-
installRockide,
|
|
2578
|
-
installPonytail
|
|
2302
|
+
generateAgentsDoc
|
|
2579
2303
|
};
|
|
2580
|
-
showReview(config);
|
|
2581
|
-
const shouldGenerate = await ot2({
|
|
2582
|
-
message: `${import_picocolors2.default.bold("Generate addon scaffold?")} ${import_picocolors2.default.dim("create the project files now")}`,
|
|
2583
|
-
initialValue: true
|
|
2584
|
-
});
|
|
2585
|
-
if (q(shouldGenerate) || !shouldGenerate) {
|
|
2586
|
-
return abortWizard();
|
|
2587
|
-
}
|
|
2588
|
-
return config;
|
|
2589
2304
|
}
|
|
2590
2305
|
|
|
2591
2306
|
// src/index.ts
|
|
2592
|
-
var teal3 = (value) => `\x1B[38;2;47;208;181m${value}\x1B[39m`;
|
|
2593
2307
|
var args = new Set(process.argv.slice(2));
|
|
2594
2308
|
if (args.has("-v") || args.has("--version")) {
|
|
2595
2309
|
const packageJson = await Bun.file(new URL("../package.json", import.meta.url)).json();
|
|
2596
2310
|
console.log(packageJson.version);
|
|
2597
2311
|
process.exit(0);
|
|
2598
2312
|
}
|
|
2313
|
+
getMinecraftDependencyVersions();
|
|
2599
2314
|
var config = await runWizard();
|
|
2600
2315
|
if (config === null) {
|
|
2601
2316
|
process.exit(0);
|
|
2602
2317
|
}
|
|
2603
|
-
var
|
|
2604
|
-
|
|
2605
|
-
await
|
|
2606
|
-
|
|
2607
|
-
|
|
2318
|
+
var plan = planProject(config, await getMinecraftDependencyVersions());
|
|
2319
|
+
showReview(config, plan);
|
|
2320
|
+
var shouldGenerate = await ot2({
|
|
2321
|
+
message: `${import_picocolors3.default.bold("Generate addon scaffold?")} ${import_picocolors3.default.dim("create the project files now")}`,
|
|
2322
|
+
initialValue: true
|
|
2323
|
+
});
|
|
2324
|
+
if (q(shouldGenerate) || !shouldGenerate) {
|
|
2325
|
+
abortWizard();
|
|
2326
|
+
process.exit(0);
|
|
2608
2327
|
}
|
|
2609
|
-
|
|
2328
|
+
var generation = fe();
|
|
2329
|
+
generation.start(teal("Generating your Bedrock addon scaffold..."));
|
|
2330
|
+
await writeProject(plan, config.destination);
|
|
2331
|
+
var dependenciesInstalled = config.scripting === "typescript" ? await installDependencies(config.destination) : null;
|
|
2610
2332
|
generation.stop(import_picocolors3.default.green("Spawnpack scaffold generated."));
|
|
2611
|
-
showPostGeneration(config
|
|
2612
|
-
|
|
2333
|
+
showPostGeneration(config, {
|
|
2334
|
+
dependenciesInstalled,
|
|
2335
|
+
rglAvailable: hasRgl()
|
|
2336
|
+
});
|
|
2337
|
+
gt(teal("Your addon is ready."));
|