@idosgames/mcp 0.1.38 → 0.1.39
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/dist/cli.js +40 -9
- package/package.json +1 -1
- package/registry/host.json +1 -1
- package/registry/index.json +17 -18
- package/registry/modules/hero-run.json +18 -19
- package/registry/modules/idle-rpg.json +5 -5
- package/registry/modules/video-studio.json +40 -40
- package/registry/modules/voxelcraft.json +4 -4
- package/registry/skills/hero-run.json +2 -2
- package/registry/skills/video-studio.json +1 -1
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"name": "iDos Games",
|
|
47
47
|
"url": "https://idosgames.com"
|
|
48
48
|
},
|
|
49
|
-
"version": "0.4.
|
|
49
|
+
"version": "0.4.2",
|
|
50
50
|
"events": {
|
|
51
51
|
"emits": [
|
|
52
52
|
{
|
|
@@ -75,14 +75,14 @@
|
|
|
75
75
|
}
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@idosgames/characters": "0.1.
|
|
78
|
+
"@idosgames/characters": "0.1.1",
|
|
79
79
|
"@idosgames/core": "0.23.0",
|
|
80
80
|
"@idosgames/module-sdk": "0.13.0",
|
|
81
81
|
"@idosgames/react": "0.6.0",
|
|
82
82
|
"phaser": "4.2.1",
|
|
83
83
|
"react": "19.2.7"
|
|
84
84
|
},
|
|
85
|
-
"contentHash": "
|
|
85
|
+
"contentHash": "3bb2350ea232f151853a4e0b69db86ae95285851a91e03d04e2c46349f8524ba",
|
|
86
86
|
"files": [
|
|
87
87
|
{
|
|
88
88
|
"path": "character/index.ts",
|
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
},
|
|
139
139
|
{
|
|
140
140
|
"path": "game/IdleRpgController.ts",
|
|
141
|
-
"content": "import Phaser from \"phaser\";\nimport { BattleScene } from \"../phaser/BattleScene\";\nimport type { IdleSession } from \"./session\";\n\n/**\n * Owns the Phaser game that draws the session's fight. Created on mount (Phaser needs the host\n * element), destroyed with the mode — the session (and with it the fight and the progress) lives on.\n */\nexport class IdleRpgController {\n private readonly game: Phaser.Game;\n\n constructor(\n parent: HTMLElement,\n readonly session: IdleSession,\n ) {\n this.game = new Phaser.Game({\n type: Phaser.AUTO,\n parent,\n width: parent.clientWidth || 480,\n height: parent.clientHeight || 800,\n backgroundColor: \"#7ec8ff\",\n scene: new BattleScene(session),\n scale: {\n // The canvas fills the full-bleed host; the scene draws the field into its top part and the\n // module's panel covers the rest (layout.ts).\n mode: Phaser.Scale.RESIZE,\n },\n });\n\n // Makes the game observable in the AI Coder's live preview, which reads this exact global.\n //\n // Phaser sets it itself — but only in its debug build (`Game.boot` guards it behind\n // WEBGL_DEBUG), and the release build shipped by npm has that branch stripped. So a Phaser game\n // is invisible to any outside observer unless it hands itself over, which is this one line.\n // Verified live: without it the preview reports no engine; with it, scenes, object counts,\n // camera and loop fps all come through.\n (globalThis as unknown as Record<string, unknown>).PHASER_GAME = this.game;\n }\n\n /** Whether the Phaser loop is running (the agent's \"am I even running\" flag). */\n get running(): boolean {\n return this.game.loop.running;\n }\n\n /** Pause/resume the Phaser RAF loop. The host calls this so a suspended mode stops ticking\n * (the Mode Router invariant: only the active mode runs) — and the fight with it. */\n setRunning(running: boolean): void {\n if (running) this.game.loop.wake();\n else this.game.loop.sleep();\n }\n\n /**\n * Один кадр игры для платформенной кнопки «поделиться снимком».\n *\n * ⚠ Через `renderer.snapshot`, а НЕ `canvas.toBlob`. У WebGL-рендерера Phaser (как и у любого\n * другого) буфер отрисовки очищен к моменту, когда до канвы доберётся посторонний код, и чтение\n * снаружи отдаёт ЧЁРНЫЙ прямоугольник, ничем не пожаловавшись — проверено живьём на стенде,\n * ровно так этот модуль и снимался, пока снимал его общий запасной путь хоста. `snapshot`\n * встроен в Phaser именно для этого: он забирает пиксели сразу после следующей отрисовки.\n *\n * Поэтому же сначала `wake()`: у остановленного цикла (режим только что был скрыт) следующей\n * отрисовки не случится вовсе, и обещание висело бы до таймаута.\n */\n capture(): Promise<Blob | null> {\n return new Promise<Blob | null>((resolve) => {\n let settled = false;\n const finish = (value: Blob | null) => {\n if (settled) return;\n settled = true;\n resolve(value);\n };\n\n // Кадр не пришёл (контекст потерян, игра уничтожена между вызовом и отрисовкой) — отвечаем\n // «нет», а не висим: у вызывающего за нами стоит следующий способ снять игру.\n setTimeout(() => finish(null), 1500);\n\n try {\n this.game.loop.wake();\n this.game.renderer.snapshot((result) => {\n if (!(result instanceof HTMLImageElement)) return finish(null);\n const canvas = document.createElement(\"canvas\");\n canvas.width = result.naturalWidth || result.width;\n canvas.height = result.naturalHeight || result.height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return finish(null);\n ctx.drawImage(result, 0, 0);\n canvas.toBlob(finish, \"image/png\");\n });\n } catch {\n finish(null);\n }\n });\n }\n\n destroy(): void {\n this.game.destroy(true);\n // Drop the debug global with the game itself: the Mode Router destroys a suspended mode, and a\n // stale reference here would show an observer a game that no longer exists.\n const globals = globalThis as unknown as Record<string, unknown>;\n if (globals[\"PHASER_GAME\"] === this.game) delete globals[\"PHASER_GAME\"];\n }\n}\n"
|
|
141
|
+
"content": "import Phaser from \"phaser\";\nimport { BattleScene } from \"../phaser/BattleScene\";\nimport type { IdleSession } from \"./session\";\n\n/**\n * Owns the Phaser game that draws the session's fight. Created on mount (Phaser needs the host\n * element), destroyed with the mode — the session (and with it the fight and the progress) lives on.\n */\nexport class IdleRpgController {\n private readonly game: Phaser.Game;\n private readonly sizeWatch: ResizeObserver | null;\n\n constructor(\n parent: HTMLElement,\n readonly session: IdleSession,\n ) {\n this.game = new Phaser.Game({\n type: Phaser.AUTO,\n parent,\n width: parent.clientWidth || 480,\n height: parent.clientHeight || 800,\n backgroundColor: \"#7ec8ff\",\n scene: new BattleScene(session),\n scale: {\n // The canvas fills the full-bleed host; the scene draws the field into its top part and the\n // module's panel covers the rest (layout.ts).\n mode: Phaser.Scale.RESIZE,\n },\n });\n\n // Makes the game observable in the AI Coder's live preview, which reads this exact global.\n //\n // Phaser sets it itself — but only in its debug build (`Game.boot` guards it behind\n // WEBGL_DEBUG), and the release build shipped by npm has that branch stripped. So a Phaser game\n // is invisible to any outside observer unless it hands itself over, which is this one line.\n // Verified live: without it the preview reports no engine; with it, scenes, object counts,\n // camera and loop fps all come through.\n (globalThis as unknown as Record<string, unknown>).PHASER_GAME = this.game;\n\n // The canvas follows its host, not only the window: the lobby lays its header and tabs around the\n // game after it mounts (and Phaser's own first measure can come before that), and a canvas left\n // at another size overflows the frame — which then scrolls, the field sliding up under the HUD.\n const fit = () => {\n const w = parent.clientWidth;\n const h = parent.clientHeight;\n if (\n w > 0 &&\n h > 0 &&\n (w !== this.game.scale.width || h !== this.game.scale.height)\n )\n this.game.scale.resize(w, h);\n };\n this.sizeWatch =\n typeof ResizeObserver === \"undefined\" ? null : new ResizeObserver(fit);\n this.sizeWatch?.observe(parent);\n this.game.scale.on(\"resize\", () => queueMicrotask(fit));\n this.game.events.once(\"ready\", fit);\n }\n\n /** Whether the Phaser loop is running (the agent's \"am I even running\" flag). */\n get running(): boolean {\n return this.game.loop.running;\n }\n\n /** Pause/resume the Phaser RAF loop. The host calls this so a suspended mode stops ticking\n * (the Mode Router invariant: only the active mode runs) — and the fight with it. */\n setRunning(running: boolean): void {\n if (running) this.game.loop.wake();\n else this.game.loop.sleep();\n }\n\n /**\n * Один кадр игры для платформенной кнопки «поделиться снимком».\n *\n * ⚠ Через `renderer.snapshot`, а НЕ `canvas.toBlob`. У WebGL-рендерера Phaser (как и у любого\n * другого) буфер отрисовки очищен к моменту, когда до канвы доберётся посторонний код, и чтение\n * снаружи отдаёт ЧЁРНЫЙ прямоугольник, ничем не пожаловавшись — проверено живьём на стенде,\n * ровно так этот модуль и снимался, пока снимал его общий запасной путь хоста. `snapshot`\n * встроен в Phaser именно для этого: он забирает пиксели сразу после следующей отрисовки.\n *\n * Поэтому же сначала `wake()`: у остановленного цикла (режим только что был скрыт) следующей\n * отрисовки не случится вовсе, и обещание висело бы до таймаута.\n */\n capture(): Promise<Blob | null> {\n return new Promise<Blob | null>((resolve) => {\n let settled = false;\n const finish = (value: Blob | null) => {\n if (settled) return;\n settled = true;\n resolve(value);\n };\n\n // Кадр не пришёл (контекст потерян, игра уничтожена между вызовом и отрисовкой) — отвечаем\n // «нет», а не висим: у вызывающего за нами стоит следующий способ снять игру.\n setTimeout(() => finish(null), 1500);\n\n try {\n this.game.loop.wake();\n this.game.renderer.snapshot((result) => {\n if (!(result instanceof HTMLImageElement)) return finish(null);\n const canvas = document.createElement(\"canvas\");\n canvas.width = result.naturalWidth || result.width;\n canvas.height = result.naturalHeight || result.height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return finish(null);\n ctx.drawImage(result, 0, 0);\n canvas.toBlob(finish, \"image/png\");\n });\n } catch {\n finish(null);\n }\n });\n }\n\n destroy(): void {\n this.sizeWatch?.disconnect();\n this.game.destroy(true);\n // Drop the debug global with the game itself: the Mode Router destroys a suspended mode, and a\n // stale reference here would show an observer a game that no longer exists.\n const globals = globalThis as unknown as Record<string, unknown>;\n if (globals[\"PHASER_GAME\"] === this.game) delete globals[\"PHASER_GAME\"];\n }\n}\n"
|
|
142
142
|
},
|
|
143
143
|
{
|
|
144
144
|
"path": "game/session.ts",
|
|
@@ -226,7 +226,7 @@
|
|
|
226
226
|
},
|
|
227
227
|
{
|
|
228
228
|
"path": "module.meta.json",
|
|
229
|
-
"content": "{\n \"id\": \"idle-rpg\",\n \"type\": \"template\",\n \"uses\": [\"character\", \"lootboxes\", \"store\"],\n \"summary\": \"Idle RPG in the style of Legend Slime: the hero auto-battles waves and bosses, gold flows in online and offline, stats are enhanced for gold.\",\n \"description\": \"A Legend Slime-style idle auto-battler on Phaser with a React screen. The selected hero (the Heroes system — character:hero-selected@1) stands on the left — a layered 2D character (src/character: its own chibi skeleton with bending meshes and IK played by its own runtime, parts as skins with vector SVG art, colours, ten animations of its own plus ranged attacks; dressed from its class and worn gear by src/character/looks, the attack swing timed to the shot; the same hero is drawn on the Heroes screen through ctx.characterArt — src/heroArt.ts, a live WebGL canvas, a new weapon swung once) — and marches along the road (Obsidian Knight style: the hero runs, its feet in step with the road, the world scrolls past in painted parallax layers per chapter theme; shadows under everyone; a fallen hero leaves the enemies standing) to the enemies standing in line ahead — people on the hero's own rig dressed in the maker's looks; brawlers fight one at a time face to face, shooters fire once the hero is in their range; a melee weapon hits only at the enemy, a bow, gun or staff from afar: crits, multi-shot, HP regen, three skills with cooldowns and an Auto switch. Stages come in chapters of ten (Chapter-Stage, themes meadow → volcano, difficulty loops); each stage is four waves and a boss with a 30-second timer — a failed boss drops back to farming until the player taps \\\"Boss!\\\". The hero's fight numbers are the server's character stats (ValueCurve, RankCurve, RankStatCurve, gear flat/percent bonuses — a mirror of PvPBattleEngine.CalculateStats). Gold is the title's idle accrual (Reward → IdleAccruals, rate = base + PowerCoefficient × the strongest hero's Power), collected every 15 s while playing and on entry with a \\\"while you were away\\\" popup; coins from kills draw that stream. Enhance: the hero's stats with level, value, next value and price, ×1 / ×10 / MAX and hold-to-repeat (one request in flight per stat, taps added up). A quest strip shows the next guide quest with Claim. The bottom bar opens the Heroes hub, gear summons, quests and the shop through ctx.features. Stage progress is saved in the player's private custom data (idle_rpg_progress); cleared stages and enhanced levels are reported to quests that count stage_cleared / stat_enhanced. Ships title-seed.json: GOLD/GEMS, three heroes on the engine's standard stat ids, twelve pieces of gear, the idle_gold accrual, a gear summon, a shop and a guide quest chain.\",\n \"provides\": [\n \"auto-battling hero vs waves of monsters\",\n \"stages, chapters and timed bosses\",\n \"idle gold income online and offline (server accrual)\",\n \"stat enhance for gold with x1 / x10 / MAX and hold\",\n \"skills with cooldowns and auto-cast\",\n \"guide quest strip\",\n \"bottom bar to heroes, summons, quests and shop\",\n \"2D procedural art (Phaser)\",\n \"layered 2D character: skeleton, swappable parts (skins), colours, 10 animations + ranged attacks (own runtime, vector art)\"\n ],\n \"tags\": [\n \"idle\",\n \"rpg\",\n \"incremental\",\n \"auto-battler\",\n \"legend-slime\",\n \"phaser\",\n \"2d\",\n \"character-customization\",\n \"skeletal-animation\"\n ],\n \"media\": {\n \"image\": \"https://cloud.idosgames.com/drive/modules/idle-rpg/cover.png\",\n \"video\": \"https://cloud.idosgames.com/drive/modules/idle-rpg/demo.mp4\"\n },\n \"demoUrl\": \"https://cloud.idosgames.com/drive/modules/idle-rpg/demo/\",\n \"author\": {\n \"name\": \"iDos Games\",\n \"url\": \"https://idosgames.com\"\n },\n \"version\": \"0.4.
|
|
229
|
+
"content": "{\n \"id\": \"idle-rpg\",\n \"type\": \"template\",\n \"uses\": [\"character\", \"lootboxes\", \"store\"],\n \"summary\": \"Idle RPG in the style of Legend Slime: the hero auto-battles waves and bosses, gold flows in online and offline, stats are enhanced for gold.\",\n \"description\": \"A Legend Slime-style idle auto-battler on Phaser with a React screen. The selected hero (the Heroes system — character:hero-selected@1) stands on the left — a layered 2D character (src/character: its own chibi skeleton with bending meshes and IK played by its own runtime, parts as skins with vector SVG art, colours, ten animations of its own plus ranged attacks; dressed from its class and worn gear by src/character/looks, the attack swing timed to the shot; the same hero is drawn on the Heroes screen through ctx.characterArt — src/heroArt.ts, a live WebGL canvas, a new weapon swung once) — and marches along the road (Obsidian Knight style: the hero runs, its feet in step with the road, the world scrolls past in painted parallax layers per chapter theme; shadows under everyone; a fallen hero leaves the enemies standing) to the enemies standing in line ahead — people on the hero's own rig dressed in the maker's looks; brawlers fight one at a time face to face, shooters fire once the hero is in their range; a melee weapon hits only at the enemy, a bow, gun or staff from afar: crits, multi-shot, HP regen, three skills with cooldowns and an Auto switch. Stages come in chapters of ten (Chapter-Stage, themes meadow → volcano, difficulty loops); each stage is four waves and a boss with a 30-second timer — a failed boss drops back to farming until the player taps \\\"Boss!\\\". The hero's fight numbers are the server's character stats (ValueCurve, RankCurve, RankStatCurve, gear flat/percent bonuses — a mirror of PvPBattleEngine.CalculateStats). Gold is the title's idle accrual (Reward → IdleAccruals, rate = base + PowerCoefficient × the strongest hero's Power), collected every 15 s while playing and on entry with a \\\"while you were away\\\" popup; coins from kills draw that stream. Enhance: the hero's stats with level, value, next value and price, ×1 / ×10 / MAX and hold-to-repeat (one request in flight per stat, taps added up). A quest strip shows the next guide quest with Claim. The bottom bar opens the Heroes hub, gear summons, quests and the shop through ctx.features. Stage progress is saved in the player's private custom data (idle_rpg_progress); cleared stages and enhanced levels are reported to quests that count stage_cleared / stat_enhanced. Ships title-seed.json: GOLD/GEMS, three heroes on the engine's standard stat ids, twelve pieces of gear, the idle_gold accrual, a gear summon, a shop and a guide quest chain.\",\n \"provides\": [\n \"auto-battling hero vs waves of monsters\",\n \"stages, chapters and timed bosses\",\n \"idle gold income online and offline (server accrual)\",\n \"stat enhance for gold with x1 / x10 / MAX and hold\",\n \"skills with cooldowns and auto-cast\",\n \"guide quest strip\",\n \"bottom bar to heroes, summons, quests and shop\",\n \"2D procedural art (Phaser)\",\n \"layered 2D character: skeleton, swappable parts (skins), colours, 10 animations + ranged attacks (own runtime, vector art)\"\n ],\n \"tags\": [\n \"idle\",\n \"rpg\",\n \"incremental\",\n \"auto-battler\",\n \"legend-slime\",\n \"phaser\",\n \"2d\",\n \"character-customization\",\n \"skeletal-animation\"\n ],\n \"media\": {\n \"image\": \"https://cloud.idosgames.com/drive/modules/idle-rpg/cover.png\",\n \"video\": \"https://cloud.idosgames.com/drive/modules/idle-rpg/demo.mp4\"\n },\n \"demoUrl\": \"https://cloud.idosgames.com/drive/modules/idle-rpg/demo/\",\n \"author\": {\n \"name\": \"iDos Games\",\n \"url\": \"https://idosgames.com\"\n },\n \"version\": \"0.4.2\",\n \"events\": {\n \"emits\": [\n {\n \"topic\": \"idle-rpg:character-upgraded@1\",\n \"when\": \"a hero's rank went up (client.character.upgradeCharacterLevel, from any screen)\",\n \"payload\": {\n \"characterId\": \"string\",\n \"level\": \"number\"\n }\n },\n {\n \"topic\": \"idle-rpg:stage-cleared@1\",\n \"when\": \"the hero beat a stage's boss; chapter-stage is the stage just cleared\",\n \"payload\": {\n \"chapter\": \"number\",\n \"stage\": \"number\"\n }\n }\n ],\n \"listens\": [\n {\n \"topic\": \"character:hero-selected@1\",\n \"why\": \"fields the hero picked on the Heroes screen (optional — without it the strongest hero fights)\"\n }\n ]\n }\n}\n"
|
|
230
230
|
}
|
|
231
231
|
]
|
|
232
232
|
}
|