@energy8platform/game-engine 0.24.0 → 0.25.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/dist/devtools.cjs.js +577 -0
- package/dist/devtools.cjs.js.map +1 -0
- package/dist/devtools.d.ts +424 -0
- package/dist/devtools.esm.js +565 -0
- package/dist/devtools.esm.js.map +1 -0
- package/dist/harness.cjs.js +33 -0
- package/dist/harness.cjs.js.map +1 -0
- package/dist/harness.d.ts +25 -0
- package/dist/harness.esm.js +30 -0
- package/dist/harness.esm.js.map +1 -0
- package/dist/reel-panel-client.cjs.js +610 -0
- package/dist/reel-panel-client.cjs.js.map +1 -0
- package/dist/reel-panel-client.d.ts +5 -0
- package/dist/reel-panel-client.esm.js +608 -0
- package/dist/reel-panel-client.esm.js.map +1 -0
- package/package.json +16 -1
- package/src/harness/index.ts +35 -0
- package/src/slot/devtools/configDiff.ts +41 -0
- package/src/slot/devtools/controlPanel.ts +151 -0
- package/src/slot/devtools/fieldSchema.ts +190 -0
- package/src/slot/devtools/index.ts +31 -0
- package/src/slot/devtools/panelClient.ts +113 -0
- package/src/slot/devtools/protocol.ts +29 -0
- package/src/slot/devtools/reelDevBridge.ts +80 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// packages/game-engine/src/slot/devtools/protocol.ts
|
|
2
|
+
//
|
|
3
|
+
// The postMessage protocol between the harness reel panel (parent window) and the
|
|
4
|
+
// reel dev bridge (game iframe). Pure constants + message types — no deps.
|
|
5
|
+
|
|
6
|
+
import type { DeepPartial, ReelSystemConfig } from '../config/ReelSystemConfig';
|
|
7
|
+
|
|
8
|
+
/** Game → panel: announces the current resolved config (on mount + on request). */
|
|
9
|
+
export interface ReelReadyMessage {
|
|
10
|
+
type: 'e8:reel:ready';
|
|
11
|
+
config: ReelSystemConfig;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Panel → game: apply a partial config live (system.update). */
|
|
15
|
+
export interface ReelApplyMessage {
|
|
16
|
+
type: 'e8:reel:apply';
|
|
17
|
+
patch: DeepPartial<ReelSystemConfig>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Panel → game: (re)request the current config, e.g. when the panel opens late. */
|
|
21
|
+
export interface ReelRequestMessage {
|
|
22
|
+
type: 'e8:reel:request';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type ReelDevMessage = ReelReadyMessage | ReelApplyMessage | ReelRequestMessage;
|
|
26
|
+
|
|
27
|
+
export const REEL_READY = 'e8:reel:ready';
|
|
28
|
+
export const REEL_APPLY = 'e8:reel:apply';
|
|
29
|
+
export const REEL_REQUEST = 'e8:reel:request';
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// packages/game-engine/src/slot/devtools/reelDevBridge.ts
|
|
2
|
+
//
|
|
3
|
+
// Game-side opt-in bridge for the harness reel panel. Call once, after creating the
|
|
4
|
+
// ReelSystem, to let the harness sidebar tune the reels LIVE:
|
|
5
|
+
//
|
|
6
|
+
// import { mountReelDevBridge } from '@energy8platform/game-engine/devtools';
|
|
7
|
+
// const bridge = mountReelDevBridge({ system });
|
|
8
|
+
//
|
|
9
|
+
// It announces the system's current config to the parent (the harness wrapper) and
|
|
10
|
+
// applies incoming patches via `system.update()`. Changes are EPHEMERAL — they live
|
|
11
|
+
// only in this running iframe and are lost on reload. To persist, use the panel's
|
|
12
|
+
// "Copy config" button and paste the snippet into your game's reel config.
|
|
13
|
+
//
|
|
14
|
+
// No-op outside an iframe (window.parent === window), so it is safe to leave in.
|
|
15
|
+
|
|
16
|
+
import type { DeepPartial, ReelSystemConfig } from '../config/ReelSystemConfig';
|
|
17
|
+
import { REEL_APPLY, REEL_READY, REEL_REQUEST, type ReelDevMessage } from './protocol';
|
|
18
|
+
|
|
19
|
+
/** Minimal ReelSystem surface the bridge needs (keeps it decoupled/testable). */
|
|
20
|
+
export interface ReelDevBridgeTarget {
|
|
21
|
+
readonly config: ReelSystemConfig;
|
|
22
|
+
update(partial: DeepPartial<ReelSystemConfig>): void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ReelDevBridgeOptions {
|
|
26
|
+
system: ReelDevBridgeTarget;
|
|
27
|
+
/** postMessage targetOrigin for the parent. Default '*' (dev harness, same-origin). */
|
|
28
|
+
targetOrigin?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Guard: only mount when true. Defaults to `import.meta.env?.DEV` when available,
|
|
31
|
+
* else true. Pass `false` to hard-disable.
|
|
32
|
+
*/
|
|
33
|
+
enabled?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface ReelDevBridge {
|
|
37
|
+
/** Re-announce the current config to the parent. */
|
|
38
|
+
announce(): void;
|
|
39
|
+
/** Detach the message listener. */
|
|
40
|
+
dispose(): void;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function defaultEnabled(): boolean {
|
|
44
|
+
try {
|
|
45
|
+
// vite injects import.meta.env.DEV; guard so non-vite builds don't throw.
|
|
46
|
+
const env = (import.meta as unknown as { env?: { DEV?: boolean } }).env;
|
|
47
|
+
return env?.DEV ?? true;
|
|
48
|
+
} catch {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function mountReelDevBridge(opts: ReelDevBridgeOptions): ReelDevBridge {
|
|
54
|
+
const enabled = opts.enabled ?? defaultEnabled();
|
|
55
|
+
const noop: ReelDevBridge = { announce: () => {}, dispose: () => {} };
|
|
56
|
+
if (!enabled || typeof window === 'undefined' || window.parent === window) return noop;
|
|
57
|
+
|
|
58
|
+
const origin = opts.targetOrigin ?? '*';
|
|
59
|
+
const { system } = opts;
|
|
60
|
+
|
|
61
|
+
const announce = (): void => {
|
|
62
|
+
window.parent.postMessage({ type: REEL_READY, config: system.config } satisfies ReelDevMessage, origin);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const onMessage = (e: MessageEvent): void => {
|
|
66
|
+
if (e.source !== window.parent) return;
|
|
67
|
+
const msg = e.data as ReelDevMessage | undefined;
|
|
68
|
+
if (!msg || typeof msg !== 'object') return;
|
|
69
|
+
if (msg.type === REEL_APPLY) system.update(msg.patch);
|
|
70
|
+
else if (msg.type === REEL_REQUEST) announce();
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
window.addEventListener('message', onMessage);
|
|
74
|
+
announce(); // cover the panel-already-open case
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
announce,
|
|
78
|
+
dispose: () => window.removeEventListener('message', onMessage),
|
|
79
|
+
};
|
|
80
|
+
}
|