@energy8platform/platform-core 0.16.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/README.md +482 -0
- package/bin/simulate.ts +139 -0
- package/dist/dev-bridge.cjs.js +237 -0
- package/dist/dev-bridge.cjs.js.map +1 -0
- package/dist/dev-bridge.d.ts +141 -0
- package/dist/dev-bridge.esm.js +235 -0
- package/dist/dev-bridge.esm.js.map +1 -0
- package/dist/index.cjs.js +569 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +439 -0
- package/dist/index.esm.js +560 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/loading.cjs.js +190 -0
- package/dist/loading.cjs.js.map +1 -0
- package/dist/loading.d.ts +86 -0
- package/dist/loading.esm.js +185 -0
- package/dist/loading.esm.js.map +1 -0
- package/dist/lua.cjs.js +1129 -0
- package/dist/lua.cjs.js.map +1 -0
- package/dist/lua.d.ts +319 -0
- package/dist/lua.esm.js +1119 -0
- package/dist/lua.esm.js.map +1 -0
- package/dist/simulation.cjs.js +374 -0
- package/dist/simulation.cjs.js.map +1 -0
- package/dist/simulation.d.ts +190 -0
- package/dist/simulation.esm.js +368 -0
- package/dist/simulation.esm.js.map +1 -0
- package/dist/vite.cjs.js +179 -0
- package/dist/vite.cjs.js.map +1 -0
- package/dist/vite.d.ts +13 -0
- package/dist/vite.esm.js +176 -0
- package/dist/vite.esm.js.map +1 -0
- package/package.json +100 -0
- package/scripts/install-simulate.mjs +101 -0
- package/src/EventEmitter.ts +55 -0
- package/src/PlatformSession.ts +156 -0
- package/src/dev-bridge/DevBridge.ts +305 -0
- package/src/dev-bridge/index.ts +2 -0
- package/src/index.ts +98 -0
- package/src/loading/CSSPreloader.ts +129 -0
- package/src/loading/index.ts +3 -0
- package/src/loading/logo.ts +95 -0
- package/src/lua/ActionRouter.ts +132 -0
- package/src/lua/LuaEngine.ts +412 -0
- package/src/lua/LuaEngineAPI.ts +314 -0
- package/src/lua/PersistentState.ts +80 -0
- package/src/lua/SessionManager.ts +227 -0
- package/src/lua/SimulationRunner.ts +192 -0
- package/src/lua/fengari.d.ts +10 -0
- package/src/lua/index.ts +28 -0
- package/src/lua/types.ts +149 -0
- package/src/simulation/NativeSimulationRunner.ts +367 -0
- package/src/simulation/ParallelSimulationRunner.ts +156 -0
- package/src/simulation/SimulationWorker.ts +44 -0
- package/src/simulation/index.ts +21 -0
- package/src/types.ts +85 -0
- package/src/vite/index.ts +196 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
|
|
3
|
+
// ─── DevBridge Plugin ────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Vite plugin that auto-injects the DevBridge mock-host bootstrapper
|
|
7
|
+
* into the HTML during development, so the game can communicate with
|
|
8
|
+
* a mock casino host without manual setup.
|
|
9
|
+
*
|
|
10
|
+
* Pair with `luaPlugin` to also enable `.lua` raw imports and serve a
|
|
11
|
+
* Lua execution endpoint at POST /__lua-play.
|
|
12
|
+
*/
|
|
13
|
+
const VIRTUAL_ID = '/@dev-bridge-entry.js';
|
|
14
|
+
|
|
15
|
+
export function devBridgePlugin(configPath: string): Plugin {
|
|
16
|
+
let entrySrc = '';
|
|
17
|
+
let viteRoot = '';
|
|
18
|
+
let resolvedConfigPath = configPath;
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
name: 'platform-core:dev-bridge',
|
|
22
|
+
apply: 'serve', // dev only
|
|
23
|
+
enforce: 'pre',
|
|
24
|
+
|
|
25
|
+
configResolved(config) {
|
|
26
|
+
viteRoot = config.root;
|
|
27
|
+
// Resolve relative config path against Vite root so the virtual
|
|
28
|
+
// module can import it with an absolute path.
|
|
29
|
+
if (configPath.startsWith('.')) {
|
|
30
|
+
resolvedConfigPath = config.root + '/' + configPath.replace(/^\.\//, '');
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
resolveId(id) {
|
|
35
|
+
if (id === VIRTUAL_ID) return id;
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
load(id) {
|
|
39
|
+
if (id === VIRTUAL_ID) {
|
|
40
|
+
// This goes through Vite's pipeline so bare imports are resolved
|
|
41
|
+
return `
|
|
42
|
+
import { DevBridge } from '@energy8platform/platform-core/dev-bridge';
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const mod = await import('${resolvedConfigPath}');
|
|
46
|
+
const config = mod.default ?? mod.config ?? mod;
|
|
47
|
+
new DevBridge(config).start();
|
|
48
|
+
} catch (e) {
|
|
49
|
+
console.warn('[DevBridge] Failed to load config:', e);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
await import('${entrySrc}');
|
|
53
|
+
`;
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
transformIndexHtml(html) {
|
|
58
|
+
// Find the app's entry module script (skip Vite internal /@... scripts)
|
|
59
|
+
const scriptRegex = /<script\s+type="module"\s+src="((?!\/@)[^"]+)"\s*>\s*<\/script>/;
|
|
60
|
+
const match = html.match(scriptRegex);
|
|
61
|
+
|
|
62
|
+
if (!match) {
|
|
63
|
+
console.warn('[DevBridge] Could not find entry module script in index.html');
|
|
64
|
+
return html;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
entrySrc = match[1];
|
|
68
|
+
if (entrySrc.startsWith('.')) {
|
|
69
|
+
entrySrc = viteRoot + '/' + entrySrc.replace(/^\.\//, '');
|
|
70
|
+
} else if (entrySrc.startsWith('/')) {
|
|
71
|
+
entrySrc = viteRoot + entrySrc;
|
|
72
|
+
}
|
|
73
|
+
return html.replace(match[0], `<script type="module" src="${VIRTUAL_ID}"></script>`);
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ─── Lua Plugin ─────────────────────────────────────────
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Vite plugin that:
|
|
82
|
+
* 1. Enables importing `.lua` files as raw strings with HMR
|
|
83
|
+
* 2. Runs a LuaEngine on the Vite dev server (Node.js) via POST /__lua-play
|
|
84
|
+
*
|
|
85
|
+
* fengari runs server-side only — no browser shims needed.
|
|
86
|
+
*/
|
|
87
|
+
export function luaPlugin(configPath: string): Plugin {
|
|
88
|
+
let luaEngine: any = null;
|
|
89
|
+
let viteServer: any = null;
|
|
90
|
+
|
|
91
|
+
async function initEngine() {
|
|
92
|
+
if (!viteServer) return;
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
// Invalidate cached modules so HMR picks up changes
|
|
96
|
+
const root = viteServer.config.root;
|
|
97
|
+
const fullConfigPath = configPath.startsWith('.')
|
|
98
|
+
? root + '/' + configPath.replace(/^\.\//, '')
|
|
99
|
+
: configPath;
|
|
100
|
+
|
|
101
|
+
// Invalidate the config module and its dependencies
|
|
102
|
+
const configMod = viteServer.moduleGraph.getModuleById(fullConfigPath);
|
|
103
|
+
if (configMod) viteServer.moduleGraph.invalidateModule(configMod);
|
|
104
|
+
|
|
105
|
+
// ssrLoadModule handles TS transpilation and resolves all imports
|
|
106
|
+
const mod = await viteServer.ssrLoadModule(fullConfigPath);
|
|
107
|
+
const config = mod.default ?? mod.config ?? mod;
|
|
108
|
+
|
|
109
|
+
if (!config.luaScript || !config.gameDefinition) {
|
|
110
|
+
console.log('[LuaPlugin] No luaScript/gameDefinition in config — Lua server disabled');
|
|
111
|
+
luaEngine = null;
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Load LuaEngine via SSR (fengari runs natively in Node.js)
|
|
116
|
+
const luaMod = await viteServer.ssrLoadModule('@energy8platform/platform-core/lua');
|
|
117
|
+
const { LuaEngine } = luaMod;
|
|
118
|
+
|
|
119
|
+
if (luaEngine) luaEngine.destroy();
|
|
120
|
+
luaEngine = new LuaEngine({
|
|
121
|
+
script: config.luaScript,
|
|
122
|
+
gameDefinition: config.gameDefinition,
|
|
123
|
+
seed: config.luaSeed,
|
|
124
|
+
});
|
|
125
|
+
console.log('[LuaPlugin] LuaEngine initialized (server-side)');
|
|
126
|
+
} catch (e: any) {
|
|
127
|
+
console.warn('[LuaPlugin] Failed to initialize LuaEngine:', e.message);
|
|
128
|
+
luaEngine = null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
name: 'platform-core:lua',
|
|
134
|
+
apply: 'serve',
|
|
135
|
+
|
|
136
|
+
async configureServer(server) {
|
|
137
|
+
viteServer = server;
|
|
138
|
+
await initEngine();
|
|
139
|
+
|
|
140
|
+
// POST /__lua-play — execute Lua on the server
|
|
141
|
+
server.middlewares.use('/__lua-play', (req: any, res: any) => {
|
|
142
|
+
if (req.method !== 'POST') {
|
|
143
|
+
res.statusCode = 405;
|
|
144
|
+
res.end('Method Not Allowed');
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
let body = '';
|
|
149
|
+
req.on('data', (chunk: string) => { body += chunk; });
|
|
150
|
+
req.on('end', () => {
|
|
151
|
+
try {
|
|
152
|
+
if (!luaEngine) {
|
|
153
|
+
res.statusCode = 503;
|
|
154
|
+
res.setHeader('Content-Type', 'application/json');
|
|
155
|
+
res.end(JSON.stringify({ error: 'LuaEngine not initialized' }));
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const params = JSON.parse(body);
|
|
160
|
+
const result = luaEngine.execute(params);
|
|
161
|
+
|
|
162
|
+
res.statusCode = 200;
|
|
163
|
+
res.setHeader('Content-Type', 'application/json');
|
|
164
|
+
res.end(JSON.stringify(result));
|
|
165
|
+
} catch (e: any) {
|
|
166
|
+
res.statusCode = 500;
|
|
167
|
+
res.setHeader('Content-Type', 'application/json');
|
|
168
|
+
res.end(JSON.stringify({ error: e.message }));
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
transform(code: string, id: string) {
|
|
175
|
+
if (id.endsWith('.lua')) {
|
|
176
|
+
return {
|
|
177
|
+
code: `export default ${JSON.stringify(code)};`,
|
|
178
|
+
map: null,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
async handleHotUpdate({ file, server }: { file: string; server: any }) {
|
|
184
|
+
if (file.endsWith('.lua') || file.includes('dev.config')) {
|
|
185
|
+
console.log('[LuaPlugin] Reloading LuaEngine...');
|
|
186
|
+
|
|
187
|
+
// Invalidate all SSR modules so ssrLoadModule picks up fresh code
|
|
188
|
+
server.moduleGraph.invalidateAll();
|
|
189
|
+
|
|
190
|
+
await initEngine();
|
|
191
|
+
server.ws.send({ type: 'full-reload' });
|
|
192
|
+
return [];
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
}
|