gamemindpilot 3.3.0 → 3.5.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.
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.blenderManager = void 0;
7
+ const child_process_1 = require("child_process");
8
+ const util_1 = require("util");
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const logger_1 = require("./logger");
12
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
13
+ exports.blenderManager = {
14
+ detect: async () => {
15
+ const commonPaths = [
16
+ 'blender', // If in PATH
17
+ 'C:\\Program Files\\Blender Foundation\\Blender\\blender.exe',
18
+ 'C:\\Program Files\\Blender Foundation\\Blender 3.6\\blender.exe',
19
+ 'C:\\Program Files\\Blender Foundation\\Blender 4.0\\blender.exe',
20
+ '/Applications/Blender.app/Contents/MacOS/Blender',
21
+ '/usr/bin/blender'
22
+ ];
23
+ for (const p of commonPaths) {
24
+ try {
25
+ await execAsync(`${p.includes(' ') ? `"${p}"` : p} --version`);
26
+ return p;
27
+ }
28
+ catch (e) {
29
+ continue;
30
+ }
31
+ }
32
+ return null;
33
+ },
34
+ render3D: async (pythonScript, outputFile) => {
35
+ const blenderPath = await exports.blenderManager.detect();
36
+ if (!blenderPath) {
37
+ logger_1.logger.warn('Blender not detected on this system.');
38
+ logger_1.logger.info('💡 TIP: For 3D Asset Forge, install Blender: https://www.blender.org/download/');
39
+ return false;
40
+ }
41
+ const scriptPath = path_1.default.join(process.cwd(), '.gmpilot', 'temp_blender_script.py');
42
+ fs_1.default.writeFileSync(scriptPath, pythonScript);
43
+ try {
44
+ logger_1.logger.info('🚀 Launching Headless Blender Forge...');
45
+ const command = `"${blenderPath}" --background --python "${scriptPath}"`;
46
+ await execAsync(command);
47
+ logger_1.logger.success(`3D Asset generated successfully: ${outputFile}`);
48
+ return true;
49
+ }
50
+ catch (err) {
51
+ logger_1.logger.error(`Blender Forge Error: ${err.message}`);
52
+ return false;
53
+ }
54
+ finally {
55
+ if (fs_1.default.existsSync(scriptPath))
56
+ fs_1.default.unlinkSync(scriptPath);
57
+ }
58
+ }
59
+ };
60
+ //# sourceMappingURL=blender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blender.js","sourceRoot":"","sources":["../../src/utils/blender.ts"],"names":[],"mappings":";;;;;;AAAA,iDAAqC;AACrC,+BAAiC;AACjC,4CAAoB;AACpB,gDAAwB;AACxB,qCAAkC;AAElC,MAAM,SAAS,GAAG,IAAA,gBAAS,EAAC,oBAAI,CAAC,CAAC;AAErB,QAAA,cAAc,GAAG;IAC5B,MAAM,EAAE,KAAK,IAA4B,EAAE;QACzC,MAAM,WAAW,GAAG;YAClB,SAAS,EAAE,aAAa;YACxB,6DAA6D;YAC7D,iEAAiE;YACjE,iEAAiE;YACjE,kDAAkD;YAClD,kBAAkB;SACnB,CAAC;QAEF,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACH,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;gBAC/D,OAAO,CAAC,CAAC;YACX,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,SAAS;YACX,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,QAAQ,EAAE,KAAK,EAAE,YAAoB,EAAE,UAAkB,EAAoB,EAAE;QAC7E,MAAM,WAAW,GAAG,MAAM,sBAAc,CAAC,MAAM,EAAE,CAAC;QAClD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,eAAM,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;YACpD,eAAM,CAAC,IAAI,CAAC,gFAAgF,CAAC,CAAC;YAC9F,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,wBAAwB,CAAC,CAAC;QAClF,YAAE,CAAC,aAAa,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QAE3C,IAAI,CAAC;YACH,eAAM,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;YACtD,MAAM,OAAO,GAAG,IAAI,WAAW,4BAA4B,UAAU,GAAG,CAAC;YACzE,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;YACzB,eAAM,CAAC,OAAO,CAAC,oCAAoC,UAAU,EAAE,CAAC,CAAC;YACjE,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,eAAM,CAAC,KAAK,CAAC,wBAAwB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YACpD,OAAO,KAAK,CAAC;QACf,CAAC;gBAAS,CAAC;YACT,IAAI,YAAE,CAAC,UAAU,CAAC,UAAU,CAAC;gBAAE,YAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;CACF,CAAC"}
@@ -0,0 +1,4 @@
1
+ import http from 'http';
2
+ export declare const bridgeManager: {
3
+ start: (port?: number) => http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
4
+ };
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.bridgeManager = void 0;
7
+ const http_1 = __importDefault(require("http"));
8
+ const logger_1 = require("./logger");
9
+ const project_1 = require("./project");
10
+ exports.bridgeManager = {
11
+ start: (port = 4242) => {
12
+ logger_1.logger.info(`🌐 Starting Engine Bridge on port ${port}...`);
13
+ const server = http_1.default.createServer((req, res) => {
14
+ // Set CORS for engine editors
15
+ res.setHeader('Access-Control-Allow-Origin', '*');
16
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
17
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
18
+ if (req.method === 'OPTIONS') {
19
+ res.writeHead(200);
20
+ res.end();
21
+ return;
22
+ }
23
+ if (req.url === '/sync' && req.method === 'GET') {
24
+ const status = {
25
+ projectName: project_1.projectManager.getSummary(),
26
+ timestamp: Date.now(),
27
+ connected: true,
28
+ status: 'online'
29
+ };
30
+ res.writeHead(200, { 'Content-Type': 'application/json' });
31
+ res.end(JSON.stringify(status));
32
+ }
33
+ else if (req.url === '/push' && req.method === 'POST') {
34
+ let body = '';
35
+ req.on('data', chunk => { body += chunk; });
36
+ req.on('end', () => {
37
+ logger_1.logger.info(`📥 Engine Sync Received: ${body.substring(0, 50)}...`);
38
+ project_1.projectManager.addEntry('Engine Live Sync', body);
39
+ res.writeHead(200);
40
+ res.end('OK');
41
+ });
42
+ }
43
+ else {
44
+ res.writeHead(404);
45
+ res.end();
46
+ }
47
+ });
48
+ server.listen(port, () => {
49
+ logger_1.logger.success(`🚀 Engine Bridge live at http://localhost:${port}`);
50
+ logger_1.logger.info('💡 Connect your Unity/Godot plugin to this endpoint for live sync.');
51
+ });
52
+ return server;
53
+ }
54
+ };
55
+ //# sourceMappingURL=bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/utils/bridge.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AACxB,qCAAkC;AAClC,uCAA2C;AAE9B,QAAA,aAAa,GAAG;IAC3B,KAAK,EAAE,CAAC,OAAe,IAAI,EAAE,EAAE;QAC7B,eAAM,CAAC,IAAI,CAAC,qCAAqC,IAAI,KAAK,CAAC,CAAC;QAE5D,MAAM,MAAM,GAAG,cAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YAC5C,8BAA8B;YAC9B,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;YAClD,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,oBAAoB,CAAC,CAAC;YACpE,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAC;YAE9D,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC7B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;gBACnB,GAAG,CAAC,GAAG,EAAE,CAAC;gBACV,OAAO;YACT,CAAC;YAED,IAAI,GAAG,CAAC,GAAG,KAAK,OAAO,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;gBAChD,MAAM,MAAM,GAAG;oBACb,WAAW,EAAE,wBAAc,CAAC,UAAU,EAAE;oBACxC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;oBACrB,SAAS,EAAE,IAAI;oBACf,MAAM,EAAE,QAAQ;iBACjB,CAAC;gBACF,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;gBAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;YAClC,CAAC;iBAAM,IAAI,GAAG,CAAC,GAAG,KAAK,OAAO,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBACxD,IAAI,IAAI,GAAG,EAAE,CAAC;gBACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5C,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;oBACjB,eAAM,CAAC,IAAI,CAAC,4BAA4B,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;oBACpE,wBAAc,CAAC,QAAQ,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;oBAClD,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;oBACnB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAChB,CAAC,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;gBACnB,GAAG,CAAC,GAAG,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;YACvB,eAAM,CAAC,OAAO,CAAC,6CAA6C,IAAI,EAAE,CAAC,CAAC;YACpE,eAAM,CAAC,IAAI,CAAC,oEAAoE,CAAC,CAAC;QACpF,CAAC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC"}
@@ -8,6 +8,7 @@ export interface Config {
8
8
  user?: string;
9
9
  telemetry?: boolean;
10
10
  analyticsKey?: string;
11
+ elevenLabsKey?: string;
11
12
  }
12
13
  export declare const configManager: {
13
14
  init: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AACxB,4CAAoB;AAEpB,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;AACvD,MAAM,WAAW,GAAG,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAc5C,QAAA,aAAa,GAAG;IAC3B,IAAI,EAAE,GAAG,EAAE;QACT,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/B,YAAE,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC3B,CAAC;QACD,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAChC,YAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,GAAG,EAAE,GAAW,EAAE;QAChB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,YAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,GAAG,EAAE,CAAC,SAA0B,EAAE,EAAE;QAClC,MAAM,OAAO,GAAG,qBAAa,CAAC,GAAG,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,SAAS,EAAE,CAAC;QAC7C,YAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,EAAE,GAAG,EAAE;QACV,YAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7D,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AACxB,4CAAoB;AAEpB,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;AACvD,MAAM,WAAW,GAAG,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAe5C,QAAA,aAAa,GAAG;IAC3B,IAAI,EAAE,GAAG,EAAE;QACT,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/B,YAAE,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC3B,CAAC;QACD,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAChC,YAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,GAAG,EAAE,GAAW,EAAE;QAChB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,YAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,GAAG,EAAE,CAAC,SAA0B,EAAE,EAAE;QAClC,MAAM,OAAO,GAAG,qBAAa,CAAC,GAAG,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,SAAS,EAAE,CAAC;QAC7C,YAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,EAAE,GAAG,EAAE;QACV,YAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7D,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare const economyManager: {
2
+ analyze: (narrativeContext: string) => Promise<string>;
3
+ };
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.economyManager = void 0;
7
+ const ai_service_1 = require("./ai-service");
8
+ const project_1 = require("./project");
9
+ const logger_1 = require("./logger");
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const path_1 = __importDefault(require("path"));
12
+ exports.economyManager = {
13
+ analyze: async (narrativeContext) => {
14
+ logger_1.logger.info('🧠 AI Economists at work... Analyzing game loops...');
15
+ const summary = project_1.projectManager.getSummary();
16
+ const prompt = `As a Senior Game Economy Designer, analyze this game project's summary and specific context:
17
+
18
+ Project Summary: ${summary}
19
+ Current Focus: ${narrativeContext}
20
+
21
+ Task:
22
+ 1. Identify 3 critical "Monetization Nodes" (where players feel value).
23
+ 2. Suggest an IAP (In-App Purchase) strategy that respects player agency.
24
+ 3. Analyze potential "Hyper-Casual" vs "Hardcore" monetization balance.
25
+ 4. Propose a "Season Pass" or "Battle Pass" tier structure if applicable.
26
+
27
+ Format the response as a professional Technical Report.`;
28
+ const report = await ai_service_1.AIService.chat(prompt);
29
+ if (!fs_1.default.existsSync('.gmpilot/analysis')) {
30
+ fs_1.default.mkdirSync('.gmpilot/analysis', { recursive: true });
31
+ }
32
+ const filename = path_1.default.join('.gmpilot/analysis', `economy_report_${Date.now()}.md`);
33
+ fs_1.default.writeFileSync(filename, report);
34
+ return report;
35
+ }
36
+ };
37
+ //# sourceMappingURL=economy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"economy.js","sourceRoot":"","sources":["../../src/utils/economy.ts"],"names":[],"mappings":";;;;;;AAAA,6CAAyC;AACzC,uCAA2C;AAC3C,qCAAkC;AAClC,4CAAoB;AACpB,gDAAwB;AAEX,QAAA,cAAc,GAAG;IAC5B,OAAO,EAAE,KAAK,EAAE,gBAAwB,EAAmB,EAAE;QAC3D,eAAM,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;QAEnE,MAAM,OAAO,GAAG,wBAAc,CAAC,UAAU,EAAE,CAAC;QAC5C,MAAM,MAAM,GAAG;;uBAEI,OAAO;qBACT,gBAAgB;;;;;;;;4DAQuB,CAAC;QAEzD,MAAM,MAAM,GAAG,MAAM,sBAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE5C,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;YACxC,YAAE,CAAC,SAAS,CAAC,mBAAmB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,CAAC;QAED,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,kBAAkB,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACnF,YAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAEnC,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gamemindpilot",
3
- "version": "3.3.0",
3
+ "version": "3.5.0",
4
4
  "description": "AI-powered CLI for game developers - Design, Asset Gen, Analysis & Optimization",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -4,6 +4,8 @@ import { logger } from '../utils/logger';
4
4
  import fs from 'fs';
5
5
  import path from 'path';
6
6
  import { projectManager } from '../utils/project';
7
+ import { blenderManager } from '../utils/blender';
8
+ import { audioManager } from '../utils/audio';
7
9
 
8
10
  export const assetCommands = {
9
11
  script: async (engine: string = 'unity') => {
@@ -172,4 +174,98 @@ export const assetCommands = {
172
174
  logger.error(err.message);
173
175
  }
174
176
  },
177
+
178
+ forge3d: async (prompt: string) => {
179
+ const spinner = ora(`Forging 3D Asset: ${prompt}...`).start();
180
+ try {
181
+ const aiPrompt = `As a Senior Blender Technical Artist, write a Blender Python (bpy) script to create a 3D model: "${prompt}".
182
+ Requirements:
183
+ 1. Create the mesh procedurally.
184
+ 2. Export the result as '.glb' to a file named 'output.glb' in the current directory.
185
+ 3. ONLY return the raw Python code. No explanations, no markdown code blocks.`;
186
+
187
+ const pythonScript = await AIService.chat(aiPrompt);
188
+ spinner.text = 'AI script received. Launching Blender Processor...';
189
+
190
+ if (!fs.existsSync('.gmpilot/assets')) {
191
+ fs.mkdirSync('.gmpilot/assets', { recursive: true });
192
+ }
193
+
194
+ const timestamp = Date.now();
195
+ const outputFile = path.join(process.cwd(), '.gmpilot', 'assets', `forge_${timestamp}.glb`);
196
+
197
+ // We need to modify the script slightly to ensure it exports to the correct absolute path
198
+ const modifiedScript = pythonScript + `\nimport bpy\nimport os\nbpy.ops.export_scene.gltf(filepath=r"${outputFile}")`;
199
+
200
+ const success = await blenderManager.render3D(modifiedScript, outputFile);
201
+ spinner.stop();
202
+
203
+ if (success) {
204
+ logger.success(`3D Forge Complete: ${outputFile}`);
205
+ projectManager.addEntry('3D Forge', `Generated 3D Asset for: ${prompt}. Saved to: ${outputFile}`);
206
+ } else {
207
+ logger.error('3D Forge failed. Ensure Blender is installed and accessible.');
208
+ }
209
+ } catch (err: any) {
210
+ spinner.stop();
211
+ logger.error(`Forge Error: ${err.message}`);
212
+ }
213
+ },
214
+
215
+ character: async (prompt: string) => {
216
+ const spinner = ora(`Designing Character Sheet: ${prompt}...`).start();
217
+ try {
218
+ const response = await AIService.chat(`Generate a professional 2D Character Concept Sheet description for: "${prompt}".
219
+ Include:
220
+ 1. Front, Side, and Back view descriptions.
221
+ 2. Color Palette (HEX).
222
+ 3. Key Equipment & Accessories.
223
+ 4. Unique visual motifs.`);
224
+
225
+ spinner.stop();
226
+ logger.bold('\n--- 🎨 Character Concept Sheet ---');
227
+ console.log(response);
228
+
229
+ if (!fs.existsSync('.gmpilot/assets')) {
230
+ fs.mkdirSync('.gmpilot/assets', { recursive: true });
231
+ }
232
+ const filename = `.gmpilot/assets/char_${prompt.replace(/\s+/g, '_')}_${Date.now()}.md`;
233
+ fs.writeFileSync(filename, response);
234
+ logger.success(`Character sheet saved to: ${filename}`);
235
+ projectManager.addEntry('Character Design', response);
236
+ } catch (err: any) {
237
+ spinner.stop();
238
+ logger.error(err.message);
239
+ }
240
+ },
241
+
242
+ voice: async (text: string) => {
243
+ const spinner = ora('Forging AI Voice...').start();
244
+ try {
245
+ const filename = await audioManager.generateVoice(text);
246
+ spinner.stop();
247
+ if (filename) {
248
+ logger.success(`Voice-over generated: ${filename}`);
249
+ projectManager.addEntry('Voice Gen', `Text: ${text}. Saved to: ${filename}`);
250
+ }
251
+ } catch (err: any) {
252
+ spinner.stop();
253
+ logger.error(err.message);
254
+ }
255
+ },
256
+
257
+ music: async (prompt: string) => {
258
+ const spinner = ora('Architecting Soundscape...').start();
259
+ try {
260
+ const filename = await audioManager.generateSound(prompt);
261
+ spinner.stop();
262
+ if (filename) {
263
+ logger.success(`Soundscape prompt/metadata archived: ${filename}`);
264
+ projectManager.addEntry('Sound Gen', `Prompt: ${prompt}. Saved to: ${filename}`);
265
+ }
266
+ } catch (err: any) {
267
+ spinner.stop();
268
+ logger.error(err.message);
269
+ }
270
+ },
175
271
  };
@@ -2,6 +2,7 @@ import inquirer from 'inquirer';
2
2
  import { logger } from '../utils/logger';
3
3
  import { configManager } from '../utils/config';
4
4
  import { projectManager } from '../utils/project';
5
+ import { blenderManager } from '../utils/blender';
5
6
 
6
7
  export const initCommand = async () => {
7
8
  logger.bold('--- Initializing GameMindPilot Project ---');
@@ -27,5 +28,11 @@ export const initCommand = async () => {
27
28
  projectManager.init(answers.projectName, answers.author);
28
29
 
29
30
  logger.success(`Project "${answers.projectName}" initialized for ${answers.author}!`);
31
+
32
+ const blenderPath = await blenderManager.detect();
33
+ if (!blenderPath) {
34
+ logger.info('💡 TIP: For 3D Asset Forge capabilities, we recommend installing Blender (https://www.blender.org/)');
35
+ }
36
+
30
37
  logger.info('Run "gmpilot --help" to see available features.');
31
38
  };
@@ -11,6 +11,8 @@ import { assetCommands } from './assets';
11
11
  import fs from 'fs';
12
12
  import path from 'path';
13
13
  import { projectManager } from '../utils/project';
14
+ import { economyManager } from '../utils/economy';
15
+ import { bridgeManager } from '../utils/bridge';
14
16
 
15
17
  export const utilityCommands = {
16
18
  update: async () => {
@@ -241,9 +243,8 @@ Run \`gmpilot --help\` for a full list of commands.
241
243
  },
242
244
 
243
245
  liveSync: async () => {
244
- logger.info('Initializing Engine Bridge (Live Link)...');
245
- logger.info('Waiting for connection from Unity/Unreal plugin on port 8080...');
246
- logger.warn('Bridge active. CLI commands will now reflect in the engine editor.');
246
+ logger.bold('\n--- 🚀 Launching Engine Live Bridge ---');
247
+ bridgeManager.start();
247
248
  },
248
249
 
249
250
  runTestBots: async (count: number = 10) => {
@@ -882,5 +883,45 @@ Run \`gmpilot --help\` for a full list of commands.
882
883
  logger.info('Testing hyper-inflation... Simulating rare drop exploits...');
883
884
  logger.warn('[Alert]: Economy broke after 1000 simulated days. Adjust drop rates in Monetization-Sim.');
884
885
  logger.success('Eco-chaos report generated.');
885
- }
886
+ },
887
+
888
+ economy: async (prompt: string) => {
889
+ const spinner = ora('Analyzing Game Economy & Monetization...').start();
890
+ try {
891
+ const report = await economyManager.analyze(prompt);
892
+ spinner.stop();
893
+ logger.bold('\n--- 💎 Monetization Strategy Report ---');
894
+ console.log(report);
895
+ logger.success(`Report saved to .gmpilot/analysis/`);
896
+ } catch (err: any) {
897
+ spinner.stop();
898
+ logger.error(err.message);
899
+ }
900
+ },
901
+
902
+ netCode: async (prompt: string) => {
903
+ const spinner = ora('Generating Multiplayer Net-Code...').start();
904
+ try {
905
+ const response = await AIService.chat(`As a Senior Network Engineer, generate a multiplayer synchronization script for: "${prompt}".
906
+ Requirements:
907
+ 1. Use a modern networking library (e.g., Unity Netcode for GameObjects, Photon, or Mirror).
908
+ 2. Implement State Synchronization and RPCs.
909
+ 3. Include comments explaining client-side prediction and server reconciliation.`);
910
+
911
+ spinner.stop();
912
+ logger.bold('\n--- 🌐 Multiplayer Net-Code ---');
913
+ console.log(response);
914
+
915
+ const netDir = path.join('.gmpilot', 'assets', 'netcode');
916
+ if (!fs.existsSync(netDir)) fs.mkdirSync(netDir, { recursive: true });
917
+
918
+ const filename = path.join(netDir, `netcode_${Date.now()}.cs`);
919
+ fs.writeFileSync(filename, response);
920
+ logger.success(`Net-code saved to: ${filename}`);
921
+ projectManager.addEntry('Net-Code Gen', response);
922
+ } catch (err: any) {
923
+ spinner.stop();
924
+ logger.error(err.message);
925
+ }
926
+ },
886
927
  };
package/src/index.ts CHANGED
@@ -12,7 +12,7 @@ const program = new Command();
12
12
  program
13
13
  .name('gmpilot')
14
14
  .description('GameMindPilot CLI - Your AI Game Development Assistant')
15
- .version('3.3.0');
15
+ .version('3.5.0');
16
16
 
17
17
  import { loginCommand, logoutCommand } from './commands/login';
18
18
  import { chatCommand } from './commands/chat';
@@ -138,6 +138,26 @@ assets
138
138
  .description('Generate a complete asset suite (Mastery Level)')
139
139
  .action(assetCommands.all);
140
140
 
141
+ assets
142
+ .command('forge3d <prompt>')
143
+ .description('Autonomous 3D Asset Forge (Requires Blender)')
144
+ .action((prompt) => assetCommands.forge3d(prompt));
145
+
146
+ assets
147
+ .command('character <prompt>')
148
+ .description('Generate a detailed 2D Character Concept Sheet')
149
+ .action((prompt) => assetCommands.character(prompt));
150
+
151
+ assets
152
+ .command('voice <text>')
153
+ .description('Generate AI Voice-over (Requires ElevenLabs Key)')
154
+ .action((text) => assetCommands.voice(text));
155
+
156
+ assets
157
+ .command('music <prompt>')
158
+ .description('Generate AI Soundscape metadata/prompts')
159
+ .action((prompt) => assetCommands.music(prompt));
160
+
141
161
  program
142
162
  .command('script')
143
163
  .description('Generate code for Unity, Unreal, Godot')
@@ -583,6 +603,16 @@ program
583
603
  .description('Extreme stress-test for virtual game economies')
584
604
  .action(utilityCommands.ecoChaos);
585
605
 
606
+ program
607
+ .command('economy <prompt>')
608
+ .description('AI Monetization Strategist: Generate an economic report')
609
+ .action((prompt) => utilityCommands.economy(prompt));
610
+
611
+ program
612
+ .command('net-code <prompt>')
613
+ .description('AI Multiplayer Architect: Generate networking logic')
614
+ .action((prompt) => utilityCommands.netCode(prompt));
615
+
586
616
  // Default action: Dashboard
587
617
  if (!process.argv.slice(2).length || (process.argv[2] && !program.commands.map(c => c.name()).includes(process.argv[2]) && !process.argv[2].startsWith('-'))) {
588
618
  utilityCommands.interactiveDashboard();
@@ -0,0 +1,54 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import axios from 'axios';
4
+ import { logger } from './logger';
5
+ import { configManager } from './config';
6
+
7
+ export const audioManager = {
8
+ generateVoice: async (text: string, voiceId: string = 'adam'): Promise<string | null> => {
9
+ logger.info(`🎙️ Generating AI Voice for: "${text.substring(0, 30)}..."`);
10
+
11
+ // Check for API Key (ElevenLabs placeholder)
12
+ const apiKey = configManager.get().elevenLabsKey;
13
+ if (!apiKey) {
14
+ logger.warn('ElevenLabs API Key missing.');
15
+ logger.info('💡 TIP: Set your key using "gmpilot login" or integrate it in config.');
16
+ return null;
17
+ }
18
+
19
+ try {
20
+ const response = await axios({
21
+ method: 'POST',
22
+ url: `https://api.elevenlabs.io/v1/text-to-speech/${voiceId}`,
23
+ data: { text, model_id: 'eleven_monolingual_v1' },
24
+ headers: { 'xi-api-key': apiKey, 'Content-Type': 'application/json' },
25
+ responseType: 'arraybuffer'
26
+ });
27
+
28
+ const audioDir = path.join(process.cwd(), '.gmpilot', 'assets', 'audio');
29
+ if (!fs.existsSync(audioDir)) fs.mkdirSync(audioDir, { recursive: true });
30
+
31
+ const filename = path.join(audioDir, `voice_${Date.now()}.mp3`);
32
+ fs.writeFileSync(filename, Buffer.from(response.data as any));
33
+ return filename;
34
+ } catch (err: any) {
35
+ logger.error(`Voice Generation Error: ${err.message}`);
36
+ return null;
37
+ }
38
+ },
39
+
40
+ generateSound: async (prompt: string): Promise<string | null> => {
41
+ logger.info(`🎵 Generating Soundscape for: "${prompt}"`);
42
+ // NOTE: Sound generation usually requires a diff API like Stable Audio or Suno.
43
+ // For now, we generate the Technical Metadata/Prompt for external tools.
44
+
45
+ const audioDir = path.join(process.cwd(), '.gmpilot', 'assets', 'audio');
46
+ if (!fs.existsSync(audioDir)) fs.mkdirSync(audioDir, { recursive: true });
47
+
48
+ const filename = path.join(audioDir, `sound_prompt_${Date.now()}.md`);
49
+ const content = `# Audio Generation Prompt\n**Subject**: ${prompt}\n\n**AI Prompt**: "High-quality, immersive sound effect for ${prompt}, professional game audio, 44.1kHz, clear spatiality."`;
50
+
51
+ fs.writeFileSync(filename, content);
52
+ return filename;
53
+ }
54
+ };
@@ -0,0 +1,55 @@
1
+ import { exec } from 'child_process';
2
+ import { promisify } from 'util';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { logger } from './logger';
6
+
7
+ const execAsync = promisify(exec);
8
+
9
+ export const blenderManager = {
10
+ detect: async (): Promise<string | null> => {
11
+ const commonPaths = [
12
+ 'blender', // If in PATH
13
+ 'C:\\Program Files\\Blender Foundation\\Blender\\blender.exe',
14
+ 'C:\\Program Files\\Blender Foundation\\Blender 3.6\\blender.exe',
15
+ 'C:\\Program Files\\Blender Foundation\\Blender 4.0\\blender.exe',
16
+ '/Applications/Blender.app/Contents/MacOS/Blender',
17
+ '/usr/bin/blender'
18
+ ];
19
+
20
+ for (const p of commonPaths) {
21
+ try {
22
+ await execAsync(`${p.includes(' ') ? `"${p}"` : p} --version`);
23
+ return p;
24
+ } catch (e) {
25
+ continue;
26
+ }
27
+ }
28
+ return null;
29
+ },
30
+
31
+ render3D: async (pythonScript: string, outputFile: string): Promise<boolean> => {
32
+ const blenderPath = await blenderManager.detect();
33
+ if (!blenderPath) {
34
+ logger.warn('Blender not detected on this system.');
35
+ logger.info('💡 TIP: For 3D Asset Forge, install Blender: https://www.blender.org/download/');
36
+ return false;
37
+ }
38
+
39
+ const scriptPath = path.join(process.cwd(), '.gmpilot', 'temp_blender_script.py');
40
+ fs.writeFileSync(scriptPath, pythonScript);
41
+
42
+ try {
43
+ logger.info('🚀 Launching Headless Blender Forge...');
44
+ const command = `"${blenderPath}" --background --python "${scriptPath}"`;
45
+ await execAsync(command);
46
+ logger.success(`3D Asset generated successfully: ${outputFile}`);
47
+ return true;
48
+ } catch (err: any) {
49
+ logger.error(`Blender Forge Error: ${err.message}`);
50
+ return false;
51
+ } finally {
52
+ if (fs.existsSync(scriptPath)) fs.unlinkSync(scriptPath);
53
+ }
54
+ }
55
+ };
@@ -0,0 +1,52 @@
1
+ import http from 'http';
2
+ import { logger } from './logger';
3
+ import { projectManager } from './project';
4
+
5
+ export const bridgeManager = {
6
+ start: (port: number = 4242) => {
7
+ logger.info(`🌐 Starting Engine Bridge on port ${port}...`);
8
+
9
+ const server = http.createServer((req, res) => {
10
+ // Set CORS for engine editors
11
+ res.setHeader('Access-Control-Allow-Origin', '*');
12
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
13
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
14
+
15
+ if (req.method === 'OPTIONS') {
16
+ res.writeHead(200);
17
+ res.end();
18
+ return;
19
+ }
20
+
21
+ if (req.url === '/sync' && req.method === 'GET') {
22
+ const status = {
23
+ projectName: projectManager.getSummary(),
24
+ timestamp: Date.now(),
25
+ connected: true,
26
+ status: 'online'
27
+ };
28
+ res.writeHead(200, { 'Content-Type': 'application/json' });
29
+ res.end(JSON.stringify(status));
30
+ } else if (req.url === '/push' && req.method === 'POST') {
31
+ let body = '';
32
+ req.on('data', chunk => { body += chunk; });
33
+ req.on('end', () => {
34
+ logger.info(`📥 Engine Sync Received: ${body.substring(0, 50)}...`);
35
+ projectManager.addEntry('Engine Live Sync', body);
36
+ res.writeHead(200);
37
+ res.end('OK');
38
+ });
39
+ } else {
40
+ res.writeHead(404);
41
+ res.end();
42
+ }
43
+ });
44
+
45
+ server.listen(port, () => {
46
+ logger.success(`🚀 Engine Bridge live at http://localhost:${port}`);
47
+ logger.info('💡 Connect your Unity/Godot plugin to this endpoint for live sync.');
48
+ });
49
+
50
+ return server;
51
+ }
52
+ };
@@ -15,6 +15,7 @@ export interface Config {
15
15
  user?: string;
16
16
  telemetry?: boolean;
17
17
  analyticsKey?: string;
18
+ elevenLabsKey?: string;
18
19
  }
19
20
 
20
21
  export const configManager = {
@@ -0,0 +1,36 @@
1
+ import { AIService } from './ai-service';
2
+ import { projectManager } from './project';
3
+ import { logger } from './logger';
4
+ import fs from 'fs';
5
+ import path from 'path';
6
+
7
+ export const economyManager = {
8
+ analyze: async (narrativeContext: string): Promise<string> => {
9
+ logger.info('🧠 AI Economists at work... Analyzing game loops...');
10
+
11
+ const summary = projectManager.getSummary();
12
+ const prompt = `As a Senior Game Economy Designer, analyze this game project's summary and specific context:
13
+
14
+ Project Summary: ${summary}
15
+ Current Focus: ${narrativeContext}
16
+
17
+ Task:
18
+ 1. Identify 3 critical "Monetization Nodes" (where players feel value).
19
+ 2. Suggest an IAP (In-App Purchase) strategy that respects player agency.
20
+ 3. Analyze potential "Hyper-Casual" vs "Hardcore" monetization balance.
21
+ 4. Propose a "Season Pass" or "Battle Pass" tier structure if applicable.
22
+
23
+ Format the response as a professional Technical Report.`;
24
+
25
+ const report = await AIService.chat(prompt);
26
+
27
+ if (!fs.existsSync('.gmpilot/analysis')) {
28
+ fs.mkdirSync('.gmpilot/analysis', { recursive: true });
29
+ }
30
+
31
+ const filename = path.join('.gmpilot/analysis', `economy_report_${Date.now()}.md`);
32
+ fs.writeFileSync(filename, report);
33
+
34
+ return report;
35
+ }
36
+ };