@energy8platform/platform-core 0.28.3 → 0.29.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 +127 -150
- package/bin/simulate.ts +35 -98
- package/dist/dev-bridge.cjs.js +3 -3
- package/dist/dev-bridge.cjs.js.map +1 -1
- package/dist/dev-bridge.d.ts +2 -2
- package/dist/dev-bridge.esm.js +3 -3
- package/dist/dev-bridge.esm.js.map +1 -1
- package/dist/game-spec.cjs.js +59 -59
- package/dist/game-spec.cjs.js.map +1 -1
- package/dist/game-spec.d.ts +24 -23
- package/dist/game-spec.esm.js +57 -56
- package/dist/game-spec.esm.js.map +1 -1
- package/dist/index.cjs.js +3 -3
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +21 -2
- package/dist/index.esm.js +3 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/lua.cjs.js +0 -1234
- package/dist/lua.cjs.js.map +1 -1
- package/dist/lua.d.ts +1 -206
- package/dist/lua.esm.js +0 -1225
- package/dist/lua.esm.js.map +1 -1
- package/dist/simulation.cjs.js +48 -179
- package/dist/simulation.cjs.js.map +1 -1
- package/dist/simulation.d.ts +26 -60
- package/dist/simulation.esm.js +48 -178
- package/dist/simulation.esm.js.map +1 -1
- package/dist/vite.cjs.js +323 -109
- package/dist/vite.cjs.js.map +1 -1
- package/dist/vite.d.ts +19 -9
- package/dist/vite.esm.js +322 -109
- package/dist/vite.esm.js.map +1 -1
- package/package.json +6 -5
- package/scripts/install-e8.mjs +113 -0
- package/src/dev-bridge/DevBridge.ts +3 -3
- package/src/game-spec/defineGame.ts +2 -2
- package/src/game-spec/derive.ts +39 -16
- package/src/game-spec/export.ts +23 -39
- package/src/game-spec/index.ts +3 -3
- package/src/game-spec/types.ts +2 -1
- package/src/index.ts +6 -12
- package/src/lua/index.ts +4 -11
- package/src/simulation/NativeSimulationRunner.ts +71 -45
- package/src/simulation/index.ts +2 -4
- package/src/vite/index.ts +4 -121
- package/src/vite/spinPlugin.ts +338 -0
- package/scripts/install-simulate.mjs +0 -101
- package/src/lua/ActionRouter.ts +0 -132
- package/src/lua/LuaEngine.ts +0 -520
- package/src/lua/LuaEngineAPI.ts +0 -314
- package/src/lua/PersistentState.ts +0 -80
- package/src/lua/SessionManager.ts +0 -249
- package/src/lua/SimulationRunner.ts +0 -190
- package/src/lua/fengari.d.ts +0 -10
- package/src/simulation/ParallelSimulationRunner.ts +0 -156
- package/src/simulation/SimulationWorker.ts +0 -44
package/dist/vite.esm.js
CHANGED
|
@@ -1,11 +1,330 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { mkdtempSync, writeFileSync, accessSync, constants } from 'node:fs';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { tmpdir } from 'node:os';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* spinPlugin — dev-путь фронта поверх e8-server (SpinML, домен-API раундов).
|
|
10
|
+
*
|
|
11
|
+
* Замена luaPlugin для spin-рантайма: тот же роут POST /__lua-play и тот же
|
|
12
|
+
* ответ — DevBridge не меняется. Плагин ТОНКИЙ: машину раунда (сессии /
|
|
13
|
+
* очереди / unlimited / globals / идемпотентность) ведёт сам e8-server
|
|
14
|
+
* (--sessions memory), плагин лишь переводит протокол и держит history для
|
|
15
|
+
* HUD. Горячая перезагрузка .spin — у сервера (--watch): правка файла =
|
|
16
|
+
* новая версия, открытые раунды доигрываются старой.
|
|
17
|
+
*
|
|
18
|
+
* Источник истины протокола: casino-platform/e8/crates/e8-server/proto/
|
|
19
|
+
* engine.proto (репо движка); ниже — синхронизированная копия.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Поиск бинаря e8-server в порядке их NativeSimulationRunner:
|
|
23
|
+
* явный binPath → env E8_SERVER_BINARY →
|
|
24
|
+
* node_modules/@energy8platform/platform-core/bin/e8-server-<platform>-<arch>
|
|
25
|
+
* (его качает install-e8.mjs postinstall'ом) → голый "e8-server" из PATH.
|
|
26
|
+
*/
|
|
27
|
+
function resolveServerBinary(explicit) {
|
|
28
|
+
const ok = (p) => {
|
|
29
|
+
try {
|
|
30
|
+
accessSync(p, constants.X_OK);
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
if (explicit)
|
|
38
|
+
return explicit;
|
|
39
|
+
const env = process.env.E8_SERVER_BINARY;
|
|
40
|
+
if (env && ok(env))
|
|
41
|
+
return env;
|
|
42
|
+
const arch = process.arch === 'x64' ? 'amd64' : process.arch;
|
|
43
|
+
const platform = process.platform === 'win32' ? 'windows' : process.platform;
|
|
44
|
+
const ext = process.platform === 'win32' ? '.exe' : '';
|
|
45
|
+
const name = `e8-server-${platform}-${arch}${ext}`;
|
|
46
|
+
// бинарь этого пакета (его качает scripts/install-e8.mjs); раскладки
|
|
47
|
+
// src/vite/*.ts и dist/vite.esm.js отличаются уровнем — пробуем оба
|
|
48
|
+
try {
|
|
49
|
+
const here = fileURLToPath(import.meta.url);
|
|
50
|
+
for (const up of ['..', '../..']) {
|
|
51
|
+
const candidate = join(here, '..', up, 'bin', name);
|
|
52
|
+
if (ok(candidate))
|
|
53
|
+
return candidate;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// import.meta недоступен — падаем на PATH
|
|
58
|
+
}
|
|
59
|
+
return `e8-server${ext}`;
|
|
60
|
+
}
|
|
61
|
+
// Копия контракта — источник истины crates/e8-server/proto/engine.proto.
|
|
62
|
+
const ENGINE_PROTO = `
|
|
63
|
+
syntax = "proto3";
|
|
64
|
+
package e8;
|
|
65
|
+
service Engine {
|
|
66
|
+
rpc ListGames(ListGamesRequest) returns (ListGamesResponse);
|
|
67
|
+
rpc GetConfig(ConfigRequest) returns (ConfigResponse);
|
|
68
|
+
rpc StartRound(StartRoundRequest) returns (RoundResponse);
|
|
69
|
+
rpc Step(RoundStepRequest) returns (RoundResponse);
|
|
70
|
+
rpc GetRound(GetRoundRequest) returns (RoundStateResponse);
|
|
71
|
+
rpc Health(HealthRequest) returns (HealthResponse);
|
|
72
|
+
}
|
|
73
|
+
message ListGamesRequest {}
|
|
74
|
+
message GameInfo {
|
|
75
|
+
string game_id = 1;
|
|
76
|
+
string script_sha256 = 2;
|
|
77
|
+
string vars_layout_hash = 3;
|
|
78
|
+
repeated string entry_actions = 4;
|
|
79
|
+
repeated string loaded_versions = 5;
|
|
80
|
+
}
|
|
81
|
+
message ListGamesResponse { repeated GameInfo games = 1; }
|
|
82
|
+
message ConfigRequest { string game_id = 1; }
|
|
83
|
+
message ConfigResponse { string config_json = 1; string error = 2; }
|
|
84
|
+
message StartRoundRequest {
|
|
85
|
+
string game_id = 1;
|
|
86
|
+
string player_id = 2;
|
|
87
|
+
string round_id = 3;
|
|
88
|
+
string server_seed = 4;
|
|
89
|
+
string client_seed = 5;
|
|
90
|
+
int64 nonce = 6;
|
|
91
|
+
string action = 7;
|
|
92
|
+
double bet = 8;
|
|
93
|
+
string params_json = 9;
|
|
94
|
+
string request_id = 10;
|
|
95
|
+
bool recording = 11;
|
|
96
|
+
}
|
|
97
|
+
message RoundStepRequest {
|
|
98
|
+
string round_id = 1;
|
|
99
|
+
string action = 2;
|
|
100
|
+
string params_json = 3;
|
|
101
|
+
string request_id = 4;
|
|
102
|
+
}
|
|
103
|
+
message RoundResponse {
|
|
104
|
+
double win = 1;
|
|
105
|
+
double total_win = 2;
|
|
106
|
+
string data_json = 3;
|
|
107
|
+
string vars_json = 4;
|
|
108
|
+
string globals_json = 5;
|
|
109
|
+
repeated string next_actions = 6;
|
|
110
|
+
bool round_complete = 7;
|
|
111
|
+
int64 spins_remaining = 8;
|
|
112
|
+
uint32 spins_played = 9;
|
|
113
|
+
string script_sha256 = 10;
|
|
114
|
+
string error = 11;
|
|
115
|
+
double bet = 12;
|
|
116
|
+
}
|
|
117
|
+
message GetRoundRequest { string round_id = 1; }
|
|
118
|
+
message RoundStateResponse {
|
|
119
|
+
bool found = 1;
|
|
120
|
+
string game_id = 2;
|
|
121
|
+
string script_sha256 = 3;
|
|
122
|
+
double total_win = 4;
|
|
123
|
+
uint32 spins_played = 5;
|
|
124
|
+
int64 spins_remaining = 6;
|
|
125
|
+
repeated string next_actions = 7;
|
|
126
|
+
bool round_complete = 8;
|
|
127
|
+
string vars_json = 9;
|
|
128
|
+
string error = 10;
|
|
129
|
+
double bet = 11;
|
|
130
|
+
}
|
|
131
|
+
message HealthRequest {}
|
|
132
|
+
message HealthResponse { bool ok = 1; uint32 games_loaded = 2; string sessions_backend = 3; }
|
|
133
|
+
`;
|
|
134
|
+
function spinPlugin(opts = {}) {
|
|
135
|
+
const port = opts.port ?? 50151;
|
|
136
|
+
const serverSeed = opts.serverSeed ?? 'e8-dev-seed';
|
|
137
|
+
let child = null;
|
|
138
|
+
let client = null;
|
|
139
|
+
let gameId = opts.gameId ?? '';
|
|
140
|
+
let entryActions = [];
|
|
141
|
+
let roundCounter = 0;
|
|
142
|
+
let reqCounter = 0;
|
|
143
|
+
// презентационное состояние протокола (history / bet раунда)
|
|
144
|
+
const rounds = new Map();
|
|
145
|
+
let activeRoundId = null;
|
|
146
|
+
function grpc() {
|
|
147
|
+
// createRequire: vite.config грузится и как ESM, и как CJS-бандл
|
|
148
|
+
const req = createRequire(import.meta.url);
|
|
149
|
+
const grpcJs = req('@grpc/grpc-js');
|
|
150
|
+
const loader = req('@grpc/proto-loader');
|
|
151
|
+
const dir = mkdtempSync(join(tmpdir(), 'e8proto-'));
|
|
152
|
+
writeFileSync(join(dir, 'engine.proto'), ENGINE_PROTO);
|
|
153
|
+
const def = loader.loadSync(join(dir, 'engine.proto'), {
|
|
154
|
+
keepCase: true,
|
|
155
|
+
longs: Number,
|
|
156
|
+
defaults: true,
|
|
157
|
+
});
|
|
158
|
+
const pkg = grpcJs.loadPackageDefinition(def);
|
|
159
|
+
return new pkg.e8.Engine(`127.0.0.1:${port}`, grpcJs.credentials.createInsecure());
|
|
160
|
+
}
|
|
161
|
+
function call(method, req) {
|
|
162
|
+
return new Promise((resolve, reject) => {
|
|
163
|
+
client[method](req, (err, resp) => err ? reject(err) : resolve(resp));
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
function toLegacy(r, roundId) {
|
|
167
|
+
const meta = rounds.get(roundId);
|
|
168
|
+
const data = r.data_json ? JSON.parse(r.data_json) : null;
|
|
169
|
+
meta.history.push({
|
|
170
|
+
spinIndex: r.spins_played - 1,
|
|
171
|
+
win: r.win * meta.bet,
|
|
172
|
+
data,
|
|
173
|
+
});
|
|
174
|
+
const hadSession = r.spins_played > 1 || !r.round_complete;
|
|
175
|
+
if (r.round_complete) {
|
|
176
|
+
rounds.delete(roundId);
|
|
177
|
+
if (activeRoundId === roundId)
|
|
178
|
+
activeRoundId = null;
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
totalWin: r.round_complete && r.spins_played > 1 ? r.total_win : r.win,
|
|
182
|
+
data,
|
|
183
|
+
nextActions: r.next_actions,
|
|
184
|
+
session: hadSession
|
|
185
|
+
? {
|
|
186
|
+
spinsRemaining: r.spins_remaining,
|
|
187
|
+
spinsPlayed: r.spins_played,
|
|
188
|
+
totalWin: r.total_win * meta.bet,
|
|
189
|
+
betAmount: meta.bet,
|
|
190
|
+
completed: r.round_complete,
|
|
191
|
+
maxWinReached: false,
|
|
192
|
+
history: meta.history,
|
|
193
|
+
}
|
|
194
|
+
: null,
|
|
195
|
+
variables: r.vars_json ? JSON.parse(r.vars_json) : {},
|
|
196
|
+
globals: r.globals_json ? JSON.parse(r.globals_json) : {},
|
|
197
|
+
creditDeferred: !r.round_complete,
|
|
198
|
+
roundId,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
async function play(body) {
|
|
202
|
+
const action = body.action ?? 'spin';
|
|
203
|
+
const params = body.params ? JSON.stringify(body.params) : '';
|
|
204
|
+
const rid = body.roundId ?? activeRoundId;
|
|
205
|
+
reqCounter += 1;
|
|
206
|
+
// шаг открытого раунда, если действие принадлежит его активной сессии.
|
|
207
|
+
// Маршрутизируем ПО СЕРВЕРУ (GetRound), а не по локальной карте: клиент
|
|
208
|
+
// (DevBridge) - владелец roundId и может пережить перезапуск плагина.
|
|
209
|
+
if (rid) {
|
|
210
|
+
const st = await call('GetRound', { round_id: rid });
|
|
211
|
+
if (st.found && !st.round_complete && st.next_actions.includes(action)) {
|
|
212
|
+
if (!rounds.has(rid))
|
|
213
|
+
rounds.set(rid, { bet: st.bet || 1.0, history: [] });
|
|
214
|
+
const r = await call('Step', {
|
|
215
|
+
round_id: rid,
|
|
216
|
+
action,
|
|
217
|
+
params_json: params,
|
|
218
|
+
request_id: `dev-${reqCounter}`,
|
|
219
|
+
});
|
|
220
|
+
if (r.error)
|
|
221
|
+
throw new Error(r.error);
|
|
222
|
+
return toLegacy(r, rid);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// entry: новый раунд. roundId КЛИЕНТА уважается (их DevBridge генерит
|
|
226
|
+
// uuid на entry и шлёт его же в session-шаги) — id-пространства совпадают.
|
|
227
|
+
roundCounter += 1;
|
|
228
|
+
const roundId = body.roundId ?? `r${roundCounter.toString(16).padStart(8, '0')}`;
|
|
229
|
+
const bet = body.bet ?? 1.0;
|
|
230
|
+
rounds.set(roundId, { bet, history: [] });
|
|
231
|
+
const r = await call('StartRound', {
|
|
232
|
+
game_id: gameId,
|
|
233
|
+
player_id: 'dev-player',
|
|
234
|
+
round_id: roundId,
|
|
235
|
+
server_seed: serverSeed,
|
|
236
|
+
client_seed: 'dev',
|
|
237
|
+
nonce: roundCounter,
|
|
238
|
+
action,
|
|
239
|
+
bet,
|
|
240
|
+
params_json: params,
|
|
241
|
+
request_id: `dev-${reqCounter}`,
|
|
242
|
+
recording: true,
|
|
243
|
+
});
|
|
244
|
+
if (r.error)
|
|
245
|
+
throw new Error(r.error);
|
|
246
|
+
if (!r.round_complete)
|
|
247
|
+
activeRoundId = roundId;
|
|
248
|
+
return toLegacy(r, roundId);
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
name: 'e8:spin',
|
|
252
|
+
apply: 'serve',
|
|
253
|
+
// pre: наша мидлвара /__lua-play регистрируется раньше luaPlugin из
|
|
254
|
+
// defineGameConfig — .spin-игры перехватывают роут без правок конфига
|
|
255
|
+
// движка (их LuaEngine на .spin-тексте тихо не поднимется).
|
|
256
|
+
enforce: 'pre',
|
|
257
|
+
async configureServer(server) {
|
|
258
|
+
if (!opts.external) {
|
|
259
|
+
const args = ['--port', String(port), '--sessions', 'memory', '--watch'];
|
|
260
|
+
if (opts.gamesDir)
|
|
261
|
+
args.push('--games-dir', opts.gamesDir);
|
|
262
|
+
else if (opts.spinPath) {
|
|
263
|
+
const dir = opts.spinPath.replace(/\/[^/]+$/, '') || '.';
|
|
264
|
+
args.push('--games-dir', dir);
|
|
265
|
+
}
|
|
266
|
+
child = spawn(resolveServerBinary(opts.binPath), args, { stdio: 'inherit' });
|
|
267
|
+
server.httpServer?.on('close', () => child?.kill());
|
|
268
|
+
}
|
|
269
|
+
client = grpc();
|
|
270
|
+
for (let i = 0; i < 100; i++) {
|
|
271
|
+
try {
|
|
272
|
+
const games = await call('ListGames', {});
|
|
273
|
+
if (!gameId)
|
|
274
|
+
gameId = games.games[0]?.game_id ?? '';
|
|
275
|
+
const info = games.games.find((g) => g.game_id === gameId);
|
|
276
|
+
entryActions = info?.entry_actions ?? [];
|
|
277
|
+
console.log(`[e8] connected: game=${gameId} script=${info?.script_sha256?.slice(0, 12)} entry=[${entryActions}]`);
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
await new Promise((res) => setTimeout(res, 300));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
server.middlewares.use('/__lua-play', (req, res) => {
|
|
285
|
+
if (req.method !== 'POST') {
|
|
286
|
+
res.statusCode = 405;
|
|
287
|
+
res.end('Method Not Allowed');
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
let body = '';
|
|
291
|
+
req.on('data', (c) => (body += c));
|
|
292
|
+
req.on('end', async () => {
|
|
293
|
+
res.setHeader('Content-Type', 'application/json');
|
|
294
|
+
try {
|
|
295
|
+
res.statusCode = 200;
|
|
296
|
+
res.end(JSON.stringify(await play(JSON.parse(body))));
|
|
297
|
+
}
|
|
298
|
+
catch (e) {
|
|
299
|
+
res.statusCode = 500;
|
|
300
|
+
res.end(JSON.stringify({ error: e.message }));
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
server.middlewares.use('/config', async (_req, res) => {
|
|
305
|
+
res.setHeader('Content-Type', 'application/json');
|
|
306
|
+
try {
|
|
307
|
+
const c = await call('GetConfig', { game_id: gameId });
|
|
308
|
+
res.statusCode = 200;
|
|
309
|
+
res.end(c.config_json || JSON.stringify({ error: c.error }));
|
|
310
|
+
}
|
|
311
|
+
catch (e) {
|
|
312
|
+
res.statusCode = 500;
|
|
313
|
+
res.end(JSON.stringify({ error: e.message }));
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
1
320
|
// ─── DevBridge Plugin ────────────────────────────────────
|
|
2
321
|
/**
|
|
3
322
|
* Vite plugin that auto-injects the DevBridge mock-host bootstrapper
|
|
4
323
|
* into the HTML during development, so the game can communicate with
|
|
5
324
|
* a mock casino host without manual setup.
|
|
6
325
|
*
|
|
7
|
-
* Pair with `
|
|
8
|
-
*
|
|
326
|
+
* Pair with `spinPlugin` to serve the math endpoint at POST /__lua-play
|
|
327
|
+
* (the route name is the frozen frontend contract; the engine is e8).
|
|
9
328
|
*/
|
|
10
329
|
const VIRTUAL_ID = '/@dev-bridge-entry.js';
|
|
11
330
|
function devBridgePlugin(configPath) {
|
|
@@ -65,112 +384,6 @@ await import('${entrySrc}');
|
|
|
65
384
|
},
|
|
66
385
|
};
|
|
67
386
|
}
|
|
68
|
-
// ─── Lua Plugin ─────────────────────────────────────────
|
|
69
|
-
/**
|
|
70
|
-
* Vite plugin that:
|
|
71
|
-
* 1. Enables importing `.lua` files as raw strings with HMR
|
|
72
|
-
* 2. Runs a LuaEngine on the Vite dev server (Node.js) via POST /__lua-play
|
|
73
|
-
*
|
|
74
|
-
* fengari runs server-side only — no browser shims needed.
|
|
75
|
-
*/
|
|
76
|
-
function luaPlugin(configPath) {
|
|
77
|
-
let luaEngine = null;
|
|
78
|
-
let viteServer = null;
|
|
79
|
-
async function initEngine() {
|
|
80
|
-
if (!viteServer)
|
|
81
|
-
return;
|
|
82
|
-
try {
|
|
83
|
-
// Invalidate cached modules so HMR picks up changes
|
|
84
|
-
const root = viteServer.config.root;
|
|
85
|
-
const fullConfigPath = configPath.startsWith('.')
|
|
86
|
-
? root + '/' + configPath.replace(/^\.\//, '')
|
|
87
|
-
: configPath;
|
|
88
|
-
// Invalidate the config module and its dependencies
|
|
89
|
-
const configMod = viteServer.moduleGraph.getModuleById(fullConfigPath);
|
|
90
|
-
if (configMod)
|
|
91
|
-
viteServer.moduleGraph.invalidateModule(configMod);
|
|
92
|
-
// ssrLoadModule handles TS transpilation and resolves all imports
|
|
93
|
-
const mod = await viteServer.ssrLoadModule(fullConfigPath);
|
|
94
|
-
const config = mod.default ?? mod.config ?? mod;
|
|
95
|
-
if (!config.luaScript || !config.gameDefinition) {
|
|
96
|
-
console.log('[LuaPlugin] No luaScript/gameDefinition in config — Lua server disabled');
|
|
97
|
-
luaEngine = null;
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
// Load LuaEngine via SSR (fengari runs natively in Node.js)
|
|
101
|
-
const luaMod = await viteServer.ssrLoadModule('@energy8platform/platform-core/lua');
|
|
102
|
-
const { LuaEngine } = luaMod;
|
|
103
|
-
if (luaEngine)
|
|
104
|
-
luaEngine.destroy();
|
|
105
|
-
luaEngine = new LuaEngine({
|
|
106
|
-
script: config.luaScript,
|
|
107
|
-
gameDefinition: config.gameDefinition,
|
|
108
|
-
seed: config.luaSeed,
|
|
109
|
-
});
|
|
110
|
-
console.log('[LuaPlugin] LuaEngine initialized (server-side)');
|
|
111
|
-
}
|
|
112
|
-
catch (e) {
|
|
113
|
-
console.warn('[LuaPlugin] Failed to initialize LuaEngine:', e.message);
|
|
114
|
-
luaEngine = null;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
return {
|
|
118
|
-
name: 'platform-core:lua',
|
|
119
|
-
apply: 'serve',
|
|
120
|
-
async configureServer(server) {
|
|
121
|
-
viteServer = server;
|
|
122
|
-
await initEngine();
|
|
123
|
-
// POST /__lua-play — execute Lua on the server
|
|
124
|
-
server.middlewares.use('/__lua-play', (req, res) => {
|
|
125
|
-
if (req.method !== 'POST') {
|
|
126
|
-
res.statusCode = 405;
|
|
127
|
-
res.end('Method Not Allowed');
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
let body = '';
|
|
131
|
-
req.on('data', (chunk) => { body += chunk; });
|
|
132
|
-
req.on('end', () => {
|
|
133
|
-
try {
|
|
134
|
-
if (!luaEngine) {
|
|
135
|
-
res.statusCode = 503;
|
|
136
|
-
res.setHeader('Content-Type', 'application/json');
|
|
137
|
-
res.end(JSON.stringify({ error: 'LuaEngine not initialized' }));
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
const params = JSON.parse(body);
|
|
141
|
-
const result = luaEngine.execute(params);
|
|
142
|
-
res.statusCode = 200;
|
|
143
|
-
res.setHeader('Content-Type', 'application/json');
|
|
144
|
-
res.end(JSON.stringify(result));
|
|
145
|
-
}
|
|
146
|
-
catch (e) {
|
|
147
|
-
res.statusCode = 500;
|
|
148
|
-
res.setHeader('Content-Type', 'application/json');
|
|
149
|
-
res.end(JSON.stringify({ error: e.message }));
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
},
|
|
154
|
-
transform(code, id) {
|
|
155
|
-
if (id.endsWith('.lua')) {
|
|
156
|
-
return {
|
|
157
|
-
code: `export default ${JSON.stringify(code)};`,
|
|
158
|
-
map: null,
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
},
|
|
162
|
-
async handleHotUpdate({ file, server }) {
|
|
163
|
-
if (file.endsWith('.lua') || file.includes('dev.config')) {
|
|
164
|
-
console.log('[LuaPlugin] Reloading LuaEngine...');
|
|
165
|
-
// Invalidate all SSR modules so ssrLoadModule picks up fresh code
|
|
166
|
-
server.moduleGraph.invalidateAll();
|
|
167
|
-
await initEngine();
|
|
168
|
-
server.ws.send({ type: 'full-reload' });
|
|
169
|
-
return [];
|
|
170
|
-
}
|
|
171
|
-
},
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
387
|
|
|
175
|
-
export { devBridgePlugin,
|
|
388
|
+
export { devBridgePlugin, spinPlugin };
|
|
176
389
|
//# sourceMappingURL=vite.esm.js.map
|
package/dist/vite.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.esm.js","sources":["../src/vite/index.ts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"vite.esm.js","sources":["../src/vite/spinPlugin.ts","../src/vite/index.ts"],"sourcesContent":[null,null],"names":["fsConstants"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@energy8platform/platform-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"description": "Energy8 platform core: Lua engine, DevBridge, RTP simulation, and SDK session orchestration. Renderer-agnostic — pair with any game framework (Pixi, Phaser, Three.js, custom).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs.js",
|
|
@@ -65,12 +65,11 @@
|
|
|
65
65
|
"typecheck": "tsc --noEmit",
|
|
66
66
|
"test": "vitest run",
|
|
67
67
|
"test:watch": "vitest",
|
|
68
|
-
"postinstall": "node scripts/install-
|
|
68
|
+
"postinstall": "node scripts/install-e8.mjs",
|
|
69
69
|
"prepublishOnly": "npm run build"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"@energy8platform/game-sdk": "^2.9.0",
|
|
73
|
-
"fengari": "^0.1.4",
|
|
74
73
|
"vite": "^5.0.0 || ^6.0.0"
|
|
75
74
|
},
|
|
76
75
|
"peerDependenciesMeta": {
|
|
@@ -85,8 +84,6 @@
|
|
|
85
84
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
86
85
|
"@typescript-eslint/parser": "^8.0.0",
|
|
87
86
|
"eslint": "^9.0.0",
|
|
88
|
-
"fengari": "^0.1.5",
|
|
89
|
-
"fengari-web": "^0.1.4",
|
|
90
87
|
"jsdom": "^25.0.1",
|
|
91
88
|
"rollup": "^4.24.0",
|
|
92
89
|
"rollup-plugin-dts": "^6.1.0",
|
|
@@ -107,5 +104,9 @@
|
|
|
107
104
|
"type": "git",
|
|
108
105
|
"url": "https://github.com/energy8platform/game-engine.git",
|
|
109
106
|
"directory": "packages/platform-core"
|
|
107
|
+
},
|
|
108
|
+
"dependencies": {
|
|
109
|
+
"@grpc/grpc-js": "^1.12.0",
|
|
110
|
+
"@grpc/proto-loader": "^0.7.13"
|
|
110
111
|
}
|
|
111
112
|
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Postinstall script: downloads the e8 SpinML engine binaries (Rust) for the
|
|
5
|
+
* current platform — the math runtime for games with `runtime: 'spin'` in
|
|
6
|
+
* math.config.ts. Falls back silently: spin games can point E8_BINARY /
|
|
7
|
+
* E8_SERVER_BINARY at a local build (casino-platform/e8/target/release).
|
|
8
|
+
*
|
|
9
|
+
* Delivery: GitHub Releases of THIS repo (game-engine), tag `e8-v<version>`
|
|
10
|
+
* — the engine source lives in the private casino-platform repo, so the
|
|
11
|
+
* binaries are published here, same discipline as the old Go simulate CLI.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { createWriteStream, chmodSync, existsSync, mkdirSync } from 'fs';
|
|
15
|
+
import { join, dirname } from 'path';
|
|
16
|
+
import { fileURLToPath } from 'url';
|
|
17
|
+
import { get } from 'https';
|
|
18
|
+
|
|
19
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
const BIN_DIR = join(__dirname, '..', 'bin');
|
|
21
|
+
|
|
22
|
+
// ─── Config ─────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
const REPO = process.env.E8_RELEASE_REPO || 'energy8platform/game-engine';
|
|
25
|
+
// e8 binary version — bump when new Rust binaries are uploaded to Releases.
|
|
26
|
+
// The binary is game-agnostic (it compiles any .spin), so it only needs to
|
|
27
|
+
// move when the engine/CLI itself changes.
|
|
28
|
+
const BINARY_VERSION = process.env.E8_BINARY_VERSION || '0.1.0';
|
|
29
|
+
|
|
30
|
+
// Два бинаря на платформу: e8 (математика/симуляция) и e8-server
|
|
31
|
+
// (дев-раунды для Vite-плагина).
|
|
32
|
+
const PLATFORM_MAP = {
|
|
33
|
+
'darwin-arm64': ['e8-darwin-arm64', 'e8-server-darwin-arm64'],
|
|
34
|
+
'darwin-x64': ['e8-darwin-amd64', 'e8-server-darwin-amd64'],
|
|
35
|
+
'linux-x64': ['e8-linux-amd64', 'e8-server-linux-amd64'],
|
|
36
|
+
'linux-arm64': ['e8-linux-arm64', 'e8-server-linux-arm64'],
|
|
37
|
+
'win32-x64': ['e8-windows-amd64.exe', 'e8-server-windows-amd64.exe'],
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// ─── Main ───────────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
async function main() {
|
|
43
|
+
const key = `${process.platform}-${process.arch}`;
|
|
44
|
+
const binaryNames = PLATFORM_MAP[key];
|
|
45
|
+
|
|
46
|
+
if (!binaryNames) {
|
|
47
|
+
console.log(`[e8] No engine binaries available for ${key}; spin-runtime math will need E8_BINARY.`);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Префикс e8-: в этом репо теги v* заняты релизами старого Go simulate CLI.
|
|
52
|
+
const tag = `e8-v${BINARY_VERSION}`;
|
|
53
|
+
|
|
54
|
+
for (const binaryName of binaryNames) {
|
|
55
|
+
const dest = join(BIN_DIR, binaryName);
|
|
56
|
+
|
|
57
|
+
// Skip if already downloaded
|
|
58
|
+
if (existsSync(dest)) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const url =
|
|
63
|
+
process.env.E8_DOWNLOAD_BASE
|
|
64
|
+
? `${process.env.E8_DOWNLOAD_BASE}/${tag}/${binaryName}`
|
|
65
|
+
: `https://github.com/${REPO}/releases/download/${tag}/${binaryName}`;
|
|
66
|
+
|
|
67
|
+
console.log(`[e8] Downloading ${binaryName} for ${key}...`);
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
if (!existsSync(BIN_DIR)) {
|
|
71
|
+
mkdirSync(BIN_DIR, { recursive: true });
|
|
72
|
+
}
|
|
73
|
+
await download(url, dest);
|
|
74
|
+
chmodSync(dest, 0o755);
|
|
75
|
+
console.log(`[e8] Installed ${binaryName}`);
|
|
76
|
+
} catch (err) {
|
|
77
|
+
// Non-fatal — Lua games are unaffected; spin games can use
|
|
78
|
+
// E8_BINARY / E8_SERVER_BINARY or a $PATH install.
|
|
79
|
+
console.log(`[e8] Could not download ${binaryName}: ${err.message}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ─── Download with redirect following ───────────────────
|
|
85
|
+
|
|
86
|
+
function download(url, dest, redirects = 5) {
|
|
87
|
+
return new Promise((resolve, reject) => {
|
|
88
|
+
if (redirects <= 0) {
|
|
89
|
+
return reject(new Error('Too many redirects'));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
get(url, { headers: { 'User-Agent': 'game-engine-postinstall' } }, (res) => {
|
|
93
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
94
|
+
res.resume();
|
|
95
|
+
return download(res.headers.location, dest, redirects - 1).then(resolve, reject);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (res.statusCode !== 200) {
|
|
99
|
+
res.resume();
|
|
100
|
+
return reject(new Error(`HTTP ${res.statusCode} for ${url}`));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const file = createWriteStream(dest);
|
|
104
|
+
res.pipe(file);
|
|
105
|
+
file.on('finish', () => file.close(resolve));
|
|
106
|
+
file.on('error', reject);
|
|
107
|
+
}).on('error', reject);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
main().catch(() => {
|
|
112
|
+
// Never fail the install
|
|
113
|
+
});
|