@forgeax/game 0.3.4 → 0.3.5
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 +9 -3
- package/dist/main.js +44 -10
- package/docs/release-0.3.5.md +32 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ runtime.
|
|
|
10
10
|
|
|
11
11
|
> [!IMPORTANT]
|
|
12
12
|
> The published package carries `forgeax-game` and scoped `game` binary aliases and resolves the exact
|
|
13
|
-
> `@forgeax/engine-sdk@0.1.
|
|
13
|
+
> `@forgeax/engine-sdk@0.1.26` and `pnpm@11.7.0` dependencies. It has no
|
|
14
14
|
> `@forgeax/game-runtime` dependency and no static Preview fallback.
|
|
15
15
|
|
|
16
16
|
## Supported flow
|
|
@@ -44,9 +44,11 @@ cd ./empty-game-directory
|
|
|
44
44
|
npx -y @forgeax/game init
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
The first command writes
|
|
47
|
+
The first command writes the `forgeax` MCP member in the canonical Codex,
|
|
48
48
|
Cursor, and Claude Code user configs. It preserves unrelated bytes and values,
|
|
49
49
|
reports `CURRENT` on an idempotent rerun, and says which host must restart or reload.
|
|
50
|
+
Existing older package-owned Asset3D MCP entries are also refreshed; absent or
|
|
51
|
+
custom Asset3D entries are not added or overwritten.
|
|
50
52
|
The second command must run from the intended blank directory. It creates the Engine
|
|
51
53
|
game there, binds the exact release identity, and reports the canonical root and
|
|
52
54
|
host-skill result. Existing exact games are read back and bound without recreation;
|
|
@@ -60,9 +62,13 @@ npx -y @forgeax/game@latest update --ide codex
|
|
|
60
62
|
```
|
|
61
63
|
|
|
62
64
|
`update` reports the configured transition, for example
|
|
63
|
-
`plugin 0.3.
|
|
65
|
+
`plugin 0.3.4 -> 0.3.5`. It refreshes configuration, skills, and routing from the
|
|
64
66
|
package being executed; it does not independently fetch another package.
|
|
65
67
|
|
|
68
|
+
See [0.3.5 compatibility notes](docs/release-0.3.5.md) before upgrading games pinned
|
|
69
|
+
to older Engine versions. This release recognizes strict v2 manifests without
|
|
70
|
+
requiring the removed `entry` field, but does not migrate game dependencies.
|
|
71
|
+
|
|
66
72
|
> [!NOTE]
|
|
67
73
|
> Asset3D is optional and **disabled by default**. The two commands above never contact
|
|
68
74
|
> the internal asset catalog, provision the bundled platform Provider, or add
|
package/dist/main.js
CHANGED
|
@@ -342,7 +342,7 @@ function engineGameId(root) {
|
|
|
342
342
|
try {
|
|
343
343
|
const manifest = JSON.parse(readFileSync(join2(root, "forge.json"), "utf8"));
|
|
344
344
|
const pkg = JSON.parse(readFileSync(join2(root, "package.json"), "utf8"));
|
|
345
|
-
return typeof manifest.id === "string" && SLUG_RE.test(manifest.id) && typeof manifest.entry === "string" && typeof pkg.dependencies?.["@forgeax/engine"] === "string" ? manifest.id : undefined;
|
|
345
|
+
return typeof manifest.id === "string" && SLUG_RE.test(manifest.id) && (manifest.schemaVersion === "2.0.0" ? typeof manifest.defaultScene === "string" && /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i.test(manifest.defaultScene) : (manifest.schemaVersion === undefined || manifest.schemaVersion === "1.0.0") && typeof manifest.entry === "string") && typeof pkg.dependencies?.["@forgeax/engine"] === "string" ? manifest.id : undefined;
|
|
346
346
|
} catch {
|
|
347
347
|
return;
|
|
348
348
|
}
|
|
@@ -710,8 +710,8 @@ import { existsSync as existsSync3, lstatSync as lstatSync3, readFileSync as rea
|
|
|
710
710
|
import { isAbsolute as isAbsolute2, relative as relative3, resolve as resolve4, sep as sep2 } from "node:path";
|
|
711
711
|
|
|
712
712
|
// src/engine/constants.ts
|
|
713
|
-
var ENGINE_VERSION = "0.1.
|
|
714
|
-
var ENGINE_COMMIT = "
|
|
713
|
+
var ENGINE_VERSION = "0.1.26";
|
|
714
|
+
var ENGINE_COMMIT = "f3d0db12405e168e4204e32a9cde32e0df8d87ae";
|
|
715
715
|
var ENGINE_SDK_PACKAGE = "@forgeax/engine-sdk";
|
|
716
716
|
var PNPM_VERSION = "11.7.0";
|
|
717
717
|
|
|
@@ -732,7 +732,7 @@ import { createRequire } from "node:module";
|
|
|
732
732
|
import { basename, delimiter, dirname as dirname4, isAbsolute, relative as relative2, resolve as resolve3, sep } from "node:path";
|
|
733
733
|
import { tmpdir } from "node:os";
|
|
734
734
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
735
|
-
var SDK_MANIFEST_SCHEMA = "1.
|
|
735
|
+
var SDK_MANIFEST_SCHEMA = "1.7.0";
|
|
736
736
|
var SDK_CLI_RELATIVE = ["bin", "forgeax.mjs"];
|
|
737
737
|
var CARRIER_ENVIRONMENT_ALLOWLIST = [
|
|
738
738
|
"HOME",
|
|
@@ -1690,7 +1690,7 @@ async function startEnginePreview(projectRoot, gameRoot, options = {}) {
|
|
|
1690
1690
|
}
|
|
1691
1691
|
const token = randomBytes(32).toString("hex");
|
|
1692
1692
|
const previewInstanceId = randomUUID();
|
|
1693
|
-
const child = spawn(process.execPath, [release.cliPath, "preview", "--json"], {
|
|
1693
|
+
const child = spawn(process.execPath, [release.cliPath, "preview", "--port", "0", "--json"], {
|
|
1694
1694
|
cwd: release.gameRoot,
|
|
1695
1695
|
detached: true,
|
|
1696
1696
|
env: { ...process.env, FORGEAX_PREVIEW_INSTANCE_TOKEN: token },
|
|
@@ -2946,12 +2946,12 @@ var RELEASE_IDENTITY_MIME = "application/vnd.forgeax.game-release-identity+json"
|
|
|
2946
2946
|
var RELEASE_IDENTITY = Object.freeze({
|
|
2947
2947
|
schema: RELEASE_IDENTITY_SCHEMA,
|
|
2948
2948
|
gamePackage: "@forgeax/game",
|
|
2949
|
-
gameVersion: "0.3.
|
|
2949
|
+
gameVersion: "0.3.5",
|
|
2950
2950
|
gameBin: "forgeax-game",
|
|
2951
2951
|
engineSdkPackage: ENGINE_SDK_PACKAGE,
|
|
2952
2952
|
engineSdkVersion: ENGINE_VERSION,
|
|
2953
2953
|
engineSourceCommit: ENGINE_COMMIT,
|
|
2954
|
-
carrierIntegrity: "sha512-
|
|
2954
|
+
carrierIntegrity: "sha512-G5ovsbdzkWWeMfFy3MxVk0qcAvWnZxJnlypMGgxFUDaKr3Wv9uVuhPV88LZ1A9mhFJJSfrE1d5R3WvHgulygRQ==",
|
|
2955
2955
|
sdkManifestDigest: `sha256:${"0".repeat(64)}`,
|
|
2956
2956
|
sdkTreeDigest: `sha256:${"0".repeat(64)}`,
|
|
2957
2957
|
fullZipDigest: `sha256:${"0".repeat(64)}`,
|
|
@@ -3356,7 +3356,7 @@ function launchSpec(mode) {
|
|
|
3356
3356
|
}
|
|
3357
3357
|
return {
|
|
3358
3358
|
command: "npx",
|
|
3359
|
-
args: ["-y", "-p", "@forgeax/game@0.3.
|
|
3359
|
+
args: ["-y", "-p", "@forgeax/game@0.3.5", "forgeax-game", "mcp"]
|
|
3360
3360
|
};
|
|
3361
3361
|
}
|
|
3362
3362
|
function asset3dLaunchSpec(mode) {
|
|
@@ -5872,7 +5872,7 @@ async function runDormantAsset3dMcp() {
|
|
|
5872
5872
|
result: {
|
|
5873
5873
|
protocolVersion,
|
|
5874
5874
|
capabilities: { tools: {} },
|
|
5875
|
-
serverInfo: { name: "asset3d-search", version: "0.3.
|
|
5875
|
+
serverInfo: { name: "asset3d-search", version: "0.3.5" }
|
|
5876
5876
|
}
|
|
5877
5877
|
};
|
|
5878
5878
|
} else if (request2.method === "tools/list") {
|
|
@@ -6086,6 +6086,38 @@ async function runAsset3dMcpProxy(projectRoot, launch) {
|
|
|
6086
6086
|
});
|
|
6087
6087
|
}
|
|
6088
6088
|
|
|
6089
|
+
// src/asset3d/host-config.ts
|
|
6090
|
+
function inspectAsset3dHost(client, root) {
|
|
6091
|
+
const launch = asset3dLaunchSpec("npx");
|
|
6092
|
+
const status = inspectConfig(client, root, launch, ASSET3D_SERVER_KEY);
|
|
6093
|
+
if (status.state !== "different")
|
|
6094
|
+
return status;
|
|
6095
|
+
const previous = configuredGameVersion(client, root, ASSET3D_SERVER_KEY);
|
|
6096
|
+
const current = launch.args.find((arg) => arg.startsWith("@forgeax/game@"))?.slice("@forgeax/game@".length);
|
|
6097
|
+
if (!previous || !current || !/^\d+\.\d+\.\d+$/.test(previous) || !/^\d+\.\d+\.\d+$/.test(current))
|
|
6098
|
+
return status;
|
|
6099
|
+
const oldParts = previous.split(".").map(Number);
|
|
6100
|
+
const newParts = current.split(".").map(Number);
|
|
6101
|
+
const differing = oldParts.findIndex((part, index) => part !== newParts[index]);
|
|
6102
|
+
if (differing < 0 || oldParts[differing] >= newParts[differing])
|
|
6103
|
+
return status;
|
|
6104
|
+
const oldLaunch = { ...launch, args: launch.args.map((arg) => arg === `@forgeax/game@${current}` ? `@forgeax/game@${previous}` : arg) };
|
|
6105
|
+
if (inspectConfig(client, root, oldLaunch, ASSET3D_SERVER_KEY).state !== "current")
|
|
6106
|
+
return status;
|
|
6107
|
+
return { ...status, state: "outdated" };
|
|
6108
|
+
}
|
|
6109
|
+
function refreshAsset3dHost(client, root) {
|
|
6110
|
+
const status = inspectAsset3dHost(client, root);
|
|
6111
|
+
if (status.state === "outdated") {
|
|
6112
|
+
const result = applyConfig(client, root, asset3dLaunchSpec("npx"), ASSET3D_SERVER_KEY);
|
|
6113
|
+
process.stdout.write(`UPDATED ${client.label} Asset3D bridge: ${result.path}
|
|
6114
|
+
`);
|
|
6115
|
+
} else if (status.state === "different" || status.state === "invalid") {
|
|
6116
|
+
process.stderr.write(`WARN ${client.label}: existing ${ASSET3D_SERVER_KEY} configuration was preserved; it is not a recognized older package launcher.
|
|
6117
|
+
`);
|
|
6118
|
+
}
|
|
6119
|
+
}
|
|
6120
|
+
|
|
6089
6121
|
// src/cli/dispatch.ts
|
|
6090
6122
|
var HELP = `ForgeaX game development plugin
|
|
6091
6123
|
|
|
@@ -6190,6 +6222,7 @@ async function installCommand(args) {
|
|
|
6190
6222
|
}
|
|
6191
6223
|
try {
|
|
6192
6224
|
const result = applyConfig(client, project.root ?? process.cwd(), launch);
|
|
6225
|
+
refreshAsset3dHost(client, project.root ?? process.cwd());
|
|
6193
6226
|
process.stdout.write(`${result.changed ? "UPDATED" : "CURRENT"} ${client.label}: ${result.path}${result.backup ? ` (backup: ${result.backup})` : ""}
|
|
6194
6227
|
`);
|
|
6195
6228
|
if (client.postInstallNote)
|
|
@@ -6569,6 +6602,7 @@ async function updateCommand(args) {
|
|
|
6569
6602
|
for (const client of configured) {
|
|
6570
6603
|
const previousVersion = configuredGameVersion(client, root);
|
|
6571
6604
|
const result = applyConfig(client, root, launch);
|
|
6605
|
+
refreshAsset3dHost(client, root);
|
|
6572
6606
|
process.stdout.write(`${result.changed ? "UPDATED" : "CURRENT"} ${client.label}: ${result.path} (plugin ${formatVersionTransition(previousVersion)})
|
|
6573
6607
|
`);
|
|
6574
6608
|
}
|
|
@@ -6691,7 +6725,7 @@ async function asset3dCommand(args) {
|
|
|
6691
6725
|
const client = findClient(id);
|
|
6692
6726
|
if (!client)
|
|
6693
6727
|
throw new Error(`asset3d_client_invalid: ${id}`);
|
|
6694
|
-
const state =
|
|
6728
|
+
const state = inspectAsset3dHost(client, projectRoot);
|
|
6695
6729
|
if (state.state === "different") {
|
|
6696
6730
|
throw new Error(`asset3d_client_server_conflict: ${client.label} already has a different ${ASSET3D_SERVER_KEY} entry`);
|
|
6697
6731
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# @forgeax/game 0.3.5
|
|
2
|
+
|
|
3
|
+
## Compatibility repair
|
|
4
|
+
|
|
5
|
+
| Boundary | Release behavior |
|
|
6
|
+
|:--|:--|
|
|
7
|
+
| Engine SDK | Exact dependency 0.1.26, commit `f3d0db12405e168e4204e32a9cde32e0df8d87ae` |
|
|
8
|
+
| Project discovery | Recognizes strict `forge.json` v2 with `defaultScene`; does not inject the forbidden legacy `entry` field |
|
|
9
|
+
| SDK manifest | Validates the released 1.7.0 manifest and exact Engine/DevKit identities |
|
|
10
|
+
| Preview | Uses Engine-owned `--port 0` allocation instead of conflicting with another game on port 5173 |
|
|
11
|
+
| Asset3D upgrade | Refreshes existing older package-owned bridges during install/update; preserves custom configurations |
|
|
12
|
+
|
|
13
|
+
## Install or update
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx -y @forgeax/game@0.3.5 install --ide codex,cursor,claude
|
|
17
|
+
# In a genuinely empty game directory:
|
|
18
|
+
npx -y @forgeax/game@0.3.5 init
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
For an existing Engine 0.1.26 project, run `update --ide codex` with this package,
|
|
22
|
+
then restart the host session. Asset3D remains opt-in with `asset3d enable`.
|
|
23
|
+
|
|
24
|
+
> [!IMPORTANT]
|
|
25
|
+
> This release pins Engine 0.1.26. It does not silently migrate games using Engine
|
|
26
|
+
> 0.1.7. Keep those games on plugin 0.3.4 until deliberately migrating through the
|
|
27
|
+
> Engine-supported workflow. Do not add `entry` to a v2 manifest to work around the
|
|
28
|
+
> old plugin's project detection.
|
|
29
|
+
|
|
30
|
+
The plugin must return Engine-owned Preview readiness and matching root/build
|
|
31
|
+
identity. A direct Engine CLI preview or a listening port alone is not MCP
|
|
32
|
+
acceptance. Asset search/import and visible gameplay require separate verification.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"packageManager": "bun@1.3.14",
|
|
3
3
|
"name": "@forgeax/game",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.5",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
7
7
|
"description": "@forgeax/game — an MCP/CLI connector for exact released ForgeaX Engine games and Engine-owned Preview.",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"docs/release-0.3.2.md",
|
|
27
27
|
"docs/release-0.3.3.md",
|
|
28
28
|
"docs/release-0.3.4.md",
|
|
29
|
+
"docs/release-0.3.5.md",
|
|
29
30
|
"README.md"
|
|
30
31
|
],
|
|
31
32
|
"scripts": {
|
|
@@ -51,7 +52,7 @@
|
|
|
51
52
|
],
|
|
52
53
|
"license": "MIT",
|
|
53
54
|
"dependencies": {
|
|
54
|
-
"@forgeax/engine-sdk": "0.1.
|
|
55
|
+
"@forgeax/engine-sdk": "0.1.26",
|
|
55
56
|
"pnpm": "11.7.0"
|
|
56
57
|
},
|
|
57
58
|
"devDependencies": {
|