diff --git a/bun.lock b/bun.lock index 9999971..04c81b2 100644 --- a/bun.lock +++ b/bun.lock @@ -19,6 +19,15 @@ "typescript": "^5.3.3", }, }, + "plugins/gamemaker": { + "name": "@game-ci/gamemaker", + "version": "0.0.1", + "devDependencies": { + "@types/node": "^17.0.23", + "typescript": "4.7.4", + "vitest": "^4", + }, + }, "plugins/orchestrator": { "name": "@game-ci/orchestrator", "version": "1.0.0", @@ -337,6 +346,8 @@ "@fastify/busboy": ["@fastify/busboy@2.1.1", "", {}, "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA=="], + "@game-ci/gamemaker": ["@game-ci/gamemaker@workspace:plugins/gamemaker"], + "@game-ci/orchestrator": ["@game-ci/orchestrator@workspace:plugins/orchestrator"], "@game-ci/steam-deploy": ["@game-ci/steam-deploy@workspace:plugins/steam-deploy"], @@ -1565,6 +1576,8 @@ "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "@game-ci/gamemaker/typescript": ["typescript@4.7.4", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ=="], + "@game-ci/orchestrator/typescript": ["typescript@4.7.4", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ=="], "@game-ci/steam-deploy/typescript": ["typescript@4.7.4", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ=="], diff --git a/plugins/gamemaker/README.md b/plugins/gamemaker/README.md new file mode 100644 index 0000000..055c37c --- /dev/null +++ b/plugins/gamemaker/README.md @@ -0,0 +1,40 @@ +# @game-ci/gamemaker (draft) + +GameMaker Studio engine plugin. **Not functional yet** - this is a structural +skeleton: a real, correctly-typed `GameCIPlugin` conforming to game-ci/cli's +plugin interface, registered the same way any other plugin is (dynamically, +via `PluginLoader.load('@game-ci/gamemaker')` or `--plugin @game-ci/gamemaker` + +- it is deliberately **not** wired into core's default load list, unlike + `orchestrator` and `steam-deploy`, since its build logic doesn't work yet). + +## Why GameMaker + +Large, underserved indie audience. GameMaker ships an official CLI (`Igor`) +that the Editor itself calls for builds - this plugin wraps that, the same +way `godot-plugin.ts` wraps `godot --headless --export-release`. + +## What's real vs. TODO + +- Plugin registration shape (engine detector + command dispatch): real, + follows the exact pattern of `src/plugin/builtin/godot-plugin.ts`. +- Project detection (`*.yyp` file presence): stubbed, returns `false` + unconditionally. +- Build command: throws immediately, pointing here. + +## Remaining work before this is real + +1. Verify Igor's actual CLI invocation shape against a real GameMaker + install - flags for runtime/license selection, target platform, output + path. Do not guess this; it needs to be checked against real GameMaker + documentation/behavior, the same way this repo's other engine plugins + were verified against real source before shipping. +2. Parse the GameMaker/runtime version out of the project for + `engineVersion` (GameMaker's project format should expose this + somewhere in the `.yyp` or a sibling options file - needs checking). +3. Decide the Docker story: does Igor need a licensed GameMaker install + inside a container (like Unreal), or can it run against a + community-buildable image (like Godot)? This affects whether the + plugin needs a `--customImage` requirement or ships a default image. +4. Tests mirroring `godot-plugin.test.ts` / the build-command test pattern + once the above is real. diff --git a/plugins/gamemaker/package.json b/plugins/gamemaker/package.json new file mode 100644 index 0000000..9c87e47 --- /dev/null +++ b/plugins/gamemaker/package.json @@ -0,0 +1,32 @@ +{ + "name": "@game-ci/gamemaker", + "version": "0.0.1", + "description": "GameMaker Studio engine plugin (draft). Wraps GameMaker's official Igor CLI for project builds.", + "license": "MIT", + "repository": "git@github.com:game-ci/cli.git", + "files": [ + "dist" + ], + "main": "dist/index.js", + "types": "dist/index.d.ts", + "exports": { + ".": { + "bun": "./src/index.ts", + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "scripts": { + "build": "tsc", + "test": "vitest run", + "typecheck": "tsc --noEmit" + }, + "devDependencies": { + "@types/node": "^17.0.23", + "typescript": "4.7.4", + "vitest": "^4" + }, + "engines": { + "node": ">=18.x" + } +} diff --git a/plugins/gamemaker/src/index.ts b/plugins/gamemaker/src/index.ts new file mode 100644 index 0000000..fb8c3a0 --- /dev/null +++ b/plugins/gamemaker/src/index.ts @@ -0,0 +1,55 @@ +/** + * GameMaker Studio engine plugin - DRAFT. + * + * Plan: detect a GameMaker project via a *.yyp file, and build via + * GameMaker's official Igor CLI (the same command line tool the Editor + * itself calls). Igor's actual invocation shape (runtime/license + * selection quirks, `igor.exe -uf -c -j 8 ` + * style arguments) needs real verification against a GameMaker install + * before this is functional - left as TODOs rather than guessed, per + * this repo's own convention of not shipping unverified domain logic. + */ + +export interface GameMakerVersionDetector { + isGameMakerProject(projectPath: string): boolean; +} + +// TODO: detect a .yyp file in projectPath (GameMaker's project manifest). +function isGameMakerProject(_projectPath: string): boolean { + return false; +} + +export const gamemakerPlugin = { + name: "gamemaker", + version: "0.0.1", + + engineDetectors: [ + { + name: "gamemaker", + detect(projectPath: string) { + if (isGameMakerProject(projectPath)) { + // TODO: read the actual GameMaker/Igor version once detection is real. + return { engine: "gamemaker", engineVersion: "unknown" }; + } + return null; + }, + }, + ], + + commands: [ + { + engine: "gamemaker", + createCommand(command: string, _subCommands: string[]) { + if (command === "build") { + throw new Error( + "GameMaker build support is not implemented yet (draft plugin). " + + "See plugins/gamemaker/README.md for the planned Igor CLI invocation shape.", + ); + } + return null; + }, + }, + ], +}; + +export default gamemakerPlugin; diff --git a/plugins/gamemaker/tsconfig.json b/plugins/gamemaker/tsconfig.json new file mode 100644 index 0000000..fb2218a --- /dev/null +++ b/plugins/gamemaker/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "es2022", + "lib": ["es2022"], + "module": "commonjs", + "moduleResolution": "node", + "declaration": true, + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "noImplicitAny": false, + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "types": ["node"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "**/*.test.ts", "dist"] +}