@umicat/phaser-sdk 1.0.6 → 1.0.7
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/editor/EditorBridge.js +86 -3
- package/dist/editor/EditorState.d.ts +10 -0
- package/dist/editor/EditorState.js +7 -0
- package/dist/index.d.ts +1 -1
- package/dist/protocol.d.ts +31 -1
- package/dist/scene/types.d.ts +21 -0
- package/package.json +1 -1
|
@@ -11,7 +11,7 @@ import { resolveRenderScript } from '../scene/renderScripts.js';
|
|
|
11
11
|
import { getManifest } from '../scene/SceneLoader.js';
|
|
12
12
|
import { getRules, patchRule } from '../scene/Rules.js';
|
|
13
13
|
import { EditorOverlayScene, EDITOR_OVERLAY_KEY } from './EditorOverlayScene.js';
|
|
14
|
-
import { getEditorState, setEditorActive, setSelection, getSelection, getEditorMode, setEditorMode, setDebugOverlayState, setTilemapToolState, } from './EditorState.js';
|
|
14
|
+
import { getEditorState, setEditorActive, setSelection, getSelection, getEditorMode, setEditorMode, getActiveSceneId, setActiveSceneId, setDebugOverlayState, setTilemapToolState, } from './EditorState.js';
|
|
15
15
|
import { applyHudPatch, createHudEntityInScene, deleteHudEntityFromScene, findHudRegistry, findHudSceneFile, UMICAT_HUD_SCENE_KEY, } from '../scene/HudRuntime.js';
|
|
16
16
|
/**
|
|
17
17
|
* EditorBridge wires the host (home-ui) to the iframe's Phaser game during
|
|
@@ -126,7 +126,67 @@ function handleMessage(game, msg) {
|
|
|
126
126
|
// load when manifestAsset present); fire-and-forget the promise.
|
|
127
127
|
void handleEditTilemap(game, msg.entityId, msg.ops, msg.manifestAsset);
|
|
128
128
|
break;
|
|
129
|
+
case 'umicat:editor:loadScene':
|
|
130
|
+
// Scene browser (design 01 §6.1) — switch to a different world scene.
|
|
131
|
+
handleLoadScene(game, msg.sceneId, msg.sceneFile, msg.manifest);
|
|
132
|
+
break;
|
|
133
|
+
case 'umicat:editor:updateManifest':
|
|
134
|
+
// Scene browser — non-switch structural op (create / rename / reorder
|
|
135
|
+
// / folders / set-initial) refreshed the manifest on disk; mirror it
|
|
136
|
+
// into the iframe's cache so it never goes stale.
|
|
137
|
+
handleUpdateManifest(game, msg.manifest);
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// --- Scene browser (design 01 §6.1) ----------------------------------------
|
|
142
|
+
/**
|
|
143
|
+
* Replace the game-global JSON cache entry under `key` with `value`. The
|
|
144
|
+
* remove + add pair changes object identity, which is what makes
|
|
145
|
+
* SceneLoader's `getOrInitState` rebuild its assetsById index on the next
|
|
146
|
+
* `getManifest` call.
|
|
147
|
+
*/
|
|
148
|
+
function replaceJsonCacheEntry(game, key, value) {
|
|
149
|
+
if (game.cache.json.exists(key))
|
|
150
|
+
game.cache.json.remove(key);
|
|
151
|
+
game.cache.json.add(key, value);
|
|
152
|
+
}
|
|
153
|
+
function handleLoadScene(game, sceneId, sceneFile, manifest) {
|
|
154
|
+
if (manifest)
|
|
155
|
+
replaceJsonCacheEntry(game, 'umicat:manifest', manifest);
|
|
156
|
+
if (sceneFile)
|
|
157
|
+
replaceJsonCacheEntry(game, `umicat:scene:${sceneId}`, sceneFile);
|
|
158
|
+
setActiveSceneId(game, sceneId);
|
|
159
|
+
setSelection(game, null);
|
|
160
|
+
// Allow the post-restart enterEdit to post a fresh snapshot — that
|
|
161
|
+
// snapshot (a new `sceneLoaded`) is the host's switch ACK.
|
|
162
|
+
delete game[SNAPSHOT_POSTED_FLAG];
|
|
163
|
+
const scene = findWorldScene(game);
|
|
164
|
+
if (!scene) {
|
|
165
|
+
// Boot race — no world scene yet. The activeSceneId is set; when the
|
|
166
|
+
// scene boots it loads whatever the template's init data says, and the
|
|
167
|
+
// PRE_STEP hook completes editor install. Rare enough to warn.
|
|
168
|
+
// eslint-disable-next-line no-console
|
|
169
|
+
console.warn('[umicat/editor] loadScene: no world scene to restart yet');
|
|
170
|
+
return;
|
|
129
171
|
}
|
|
172
|
+
// Tear down editor chrome BEFORE the restart. The restart destroys the
|
|
173
|
+
// scene's cameras, but the game-bag EDITOR_CAM_KEY ref would go stale
|
|
174
|
+
// (still truthy) — the PRE_STEP late-boot hook checks `!getEditorCamera`
|
|
175
|
+
// and would never re-run enterEdit. Uninstalling clears the key so the
|
|
176
|
+
// hook fires once the scene rebuilds, exactly like the boot-flag path.
|
|
177
|
+
uninstallVoidFill(game);
|
|
178
|
+
uninstallEditorCameras(game);
|
|
179
|
+
// Restart with the new sceneId. The template's GameScene.init({ sceneId })
|
|
180
|
+
// accepts this; loadWorldScene then reads the scene JSON we just cached.
|
|
181
|
+
// The PRE_STEP late-boot hook (1.0.6) re-runs the idempotent enterEdit
|
|
182
|
+
// once the scene rebuilds, re-installing editor chrome and posting the
|
|
183
|
+
// fresh sceneLoaded.
|
|
184
|
+
scene.scene.restart({ sceneId });
|
|
185
|
+
}
|
|
186
|
+
function handleUpdateManifest(game, manifest) {
|
|
187
|
+
if (!manifest)
|
|
188
|
+
return;
|
|
189
|
+
replaceJsonCacheEntry(game, 'umicat:manifest', manifest);
|
|
130
190
|
}
|
|
131
191
|
// --- Enter / exit ---------------------------------------------------------
|
|
132
192
|
function enterEdit(game) {
|
|
@@ -423,6 +483,10 @@ function postSceneSnapshot(game) {
|
|
|
423
483
|
manifest,
|
|
424
484
|
});
|
|
425
485
|
game[SNAPSHOT_POSTED_FLAG] = sceneFile.id;
|
|
486
|
+
// Scene browser — pin the active-scene tracker on the boot snapshot so
|
|
487
|
+
// readActiveSceneFile stays deterministic after later scene switches.
|
|
488
|
+
if (!getActiveSceneId(game))
|
|
489
|
+
setActiveSceneId(game, sceneFile.id);
|
|
426
490
|
}
|
|
427
491
|
// Also post the HUD scene if attached + loaded. The host stashes both
|
|
428
492
|
// snapshots so the World/HUD toggle is purely a UI switch — no fresh
|
|
@@ -631,9 +695,19 @@ function hasPostedSnapshot(game) {
|
|
|
631
695
|
return !!game[SNAPSHOT_POSTED_FLAG];
|
|
632
696
|
}
|
|
633
697
|
function readActiveSceneFile(game) {
|
|
698
|
+
// Scene browser — once two scenes have been visited, the JSON cache holds
|
|
699
|
+
// multiple `umicat:scene:*` entries and the scan below becomes ambiguous.
|
|
700
|
+
// Prefer the exact entry for the tracked active scene when set.
|
|
701
|
+
const activeId = getActiveSceneId(game);
|
|
702
|
+
if (activeId) {
|
|
703
|
+
const exact = game.cache.json.get(`umicat:scene:${activeId}`);
|
|
704
|
+
if (isWorldScene(exact))
|
|
705
|
+
return exact;
|
|
706
|
+
}
|
|
634
707
|
// The active world scene cached its scene file in Phaser's JSON cache via
|
|
635
708
|
// SceneLoader. Pull it from there. We pick the first non-Boot scene we
|
|
636
|
-
// find with a JSON entry matching `umicat:scene:<id>`.
|
|
709
|
+
// find with a JSON entry matching `umicat:scene:<id>`. (Boot path / old
|
|
710
|
+
// hosts — activeSceneId not yet set.)
|
|
637
711
|
for (const scene of game.scene.getScenes(false)) {
|
|
638
712
|
const key = scene.scene.key;
|
|
639
713
|
if (BOOT_SCENE_KEYS.has(key))
|
|
@@ -1972,7 +2046,16 @@ function restoreHudCamera(game) {
|
|
|
1972
2046
|
* `postCameraState`, and the overlay scene's mirror in `create`.
|
|
1973
2047
|
*/
|
|
1974
2048
|
export function getEditorCamera(game) {
|
|
1975
|
-
|
|
2049
|
+
const cam = game[EDITOR_CAM_KEY] ?? null;
|
|
2050
|
+
// Scene browser — a scene restart (loadScene switch) destroys the scene's
|
|
2051
|
+
// cameras but leaves this game-bag ref dangling. Phaser's BaseCamera
|
|
2052
|
+
// .destroy() nulls `cam.scene`; treat such a camera as absent and clear
|
|
2053
|
+
// the stale key so the PRE_STEP late-boot hook can re-run enterEdit.
|
|
2054
|
+
if (cam && !cam.scene) {
|
|
2055
|
+
delete game[EDITOR_CAM_KEY];
|
|
2056
|
+
return null;
|
|
2057
|
+
}
|
|
2058
|
+
return cam;
|
|
1976
2059
|
}
|
|
1977
2060
|
/**
|
|
1978
2061
|
* Toggle HUD scene rendering. HUD widgets are canvas-relative (anchor-
|
|
@@ -62,6 +62,14 @@ interface EditorStateShape {
|
|
|
62
62
|
active: boolean;
|
|
63
63
|
selectedId: string | null;
|
|
64
64
|
mode: EditorMode;
|
|
65
|
+
/**
|
|
66
|
+
* Scene browser (design 01 §6.1) — which world scene the editor is
|
|
67
|
+
* currently editing. Set by `umicat:editor:loadScene` and by the first
|
|
68
|
+
* scene snapshot. Once two scenes have been visited, the JSON cache holds
|
|
69
|
+
* multiple `umicat:scene:*` entries — this disambiguates which one
|
|
70
|
+
* `readActiveSceneFile` should return.
|
|
71
|
+
*/
|
|
72
|
+
activeSceneId: string | null;
|
|
65
73
|
/**
|
|
66
74
|
* Drag-in-progress info. While set, the overlay scene mutates the entity's
|
|
67
75
|
* x/y directly per pointermove without going through the host. On
|
|
@@ -219,6 +227,8 @@ export declare function getEditorState(game: AnyObject): EditorStateShape;
|
|
|
219
227
|
export declare function setEditorActive(game: AnyObject, active: boolean): void;
|
|
220
228
|
export declare function getEditorMode(game: AnyObject): EditorMode;
|
|
221
229
|
export declare function setEditorMode(game: AnyObject, mode: EditorMode): void;
|
|
230
|
+
export declare function getActiveSceneId(game: AnyObject): string | null;
|
|
231
|
+
export declare function setActiveSceneId(game: AnyObject, id: string | null): void;
|
|
222
232
|
export declare function setSelection(game: AnyObject, id: string | null): void;
|
|
223
233
|
export declare function getSelection(game: AnyObject): string | null;
|
|
224
234
|
export declare function startDrag(game: AnyObject, entityId: string, startWorld: {
|
|
@@ -19,6 +19,7 @@ export function getEditorState(game) {
|
|
|
19
19
|
active: false,
|
|
20
20
|
selectedId: null,
|
|
21
21
|
mode: 'world',
|
|
22
|
+
activeSceneId: null,
|
|
22
23
|
drag: null,
|
|
23
24
|
debugOverlay: { showHitboxes: false },
|
|
24
25
|
tilemap: {
|
|
@@ -45,6 +46,12 @@ export function getEditorMode(game) {
|
|
|
45
46
|
export function setEditorMode(game, mode) {
|
|
46
47
|
getEditorState(game).mode = mode;
|
|
47
48
|
}
|
|
49
|
+
export function getActiveSceneId(game) {
|
|
50
|
+
return getEditorState(game).activeSceneId;
|
|
51
|
+
}
|
|
52
|
+
export function setActiveSceneId(game, id) {
|
|
53
|
+
getEditorState(game).activeSceneId = id;
|
|
54
|
+
}
|
|
48
55
|
export function setSelection(game, id) {
|
|
49
56
|
getEditorState(game).selectedId = id;
|
|
50
57
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -39,5 +39,5 @@ export { setupEditorBridge } from './editor/EditorBridge.js';
|
|
|
39
39
|
export { EditorOverlayScene, EDITOR_OVERLAY_KEY } from './editor/EditorOverlayScene.js';
|
|
40
40
|
export type { EditorEntityPatch, EditorEnterMessage, EditorExitMessage, EditorGetSceneMessage, EditorApplyEditMessage, EditorSetSelectionMessage, EditorPanZoomMessage, EditorHostToSdkMessage, EditorSceneLoadedMessage, EditorSelectionPickedMessage, EditorDragEndMessage, EditorShortcutMessage, EditorCreateEntityMessage, EditorDeleteEntityMessage, EditorSetEditModeMessage, EditorSelectionRectMessage, EditorSdkToHostMessage, } from './protocol.js';
|
|
41
41
|
export { SCHEMA_VERSION, isPerFrameNinePatch, isPerFrameHitbox, } from './scene/types.js';
|
|
42
|
-
export type { Manifest, SceneRef, HudRef, AssetRecord, AssetKind, SceneType, SceneFile, WorldScene, HudScene, WorldSceneConfig, CameraConfig, WorldEntity, WorldEntityKind, NonGroupWorldEntity, RenderableEntity, SpriteEntity, RectEntity, CircleEntity, CodeRenderedEntity, GroupEntity, TilemapEntity, TilemapLayer, TilesetMetadata, TileMetadata, TilesetAutotile, TilesetAnimation, WangTerrain, TriggerEntity, TriggerShape, HudEntity, HudEntityKind, HudEntityBase, HudTextEntity, HudImageEntity, HudIconButtonEntity, HudProgressBarEntity, HudPanelEntity, HudTextSource, HudNumberSource, HudLayer, Transform, Anchor, AnchorSide, NinePatchConfig, NinePatchPerFrame, HitboxRect, HitboxPerFrame, DepthAnchor, } from './scene/types.js';
|
|
42
|
+
export type { Manifest, ManifestGroup, SceneRef, HudRef, AssetRecord, AssetKind, SceneType, SceneFile, WorldScene, HudScene, WorldSceneConfig, CameraConfig, WorldEntity, WorldEntityKind, NonGroupWorldEntity, RenderableEntity, SpriteEntity, RectEntity, CircleEntity, CodeRenderedEntity, GroupEntity, TilemapEntity, TilemapLayer, TilesetMetadata, TileMetadata, TilesetAutotile, TilesetAnimation, WangTerrain, TriggerEntity, TriggerShape, HudEntity, HudEntityKind, HudEntityBase, HudTextEntity, HudImageEntity, HudIconButtonEntity, HudProgressBarEntity, HudPanelEntity, HudTextSource, HudNumberSource, HudLayer, Transform, Anchor, AnchorSide, NinePatchConfig, NinePatchPerFrame, HitboxRect, HitboxPerFrame, DepthAnchor, } from './scene/types.js';
|
|
43
43
|
export { PROTOCOL_VERSION, type HelloMessage, type InitMessage, type RpcRequestMessage, type RpcResultOk, type RpcResultError, type HostToSdkMessage, type SdkToHostMessage, type RpcErrorPayload, type RpcMethod, type SavesGetParams, type SavesGetResult, type SavesSetParams, type SavesSetResult, type SavesDeleteParams, type SavesDeleteResult, type SavesListResult, type GameDataGetParams, type GameDataGetResult, type GameDataSetParams, type GameDataSetResult, type GameDataDeleteParams, type GameDataDeleteResult, type GameDataListResult, type RealtimeGetTokenParams, type RealtimeGetTokenResult, } from './protocol.js';
|
package/dist/protocol.d.ts
CHANGED
|
@@ -580,7 +580,37 @@ export type TilemapEditOp = {
|
|
|
580
580
|
y: number;
|
|
581
581
|
};
|
|
582
582
|
};
|
|
583
|
-
|
|
583
|
+
/**
|
|
584
|
+
* Switch the editor to a different world scene (scene browser — design 01
|
|
585
|
+
* §6.1). The iframe loads scene JSON from the deployed dist, NOT the
|
|
586
|
+
* workspace, so the host pushes the current on-disk truth here (fetched via
|
|
587
|
+
* the session-server's `request_workspace_file`) instead of letting the
|
|
588
|
+
* iframe fetch a stale copy.
|
|
589
|
+
*
|
|
590
|
+
* The bridge overwrites the Phaser JSON cache entries, then restarts the
|
|
591
|
+
* world scene with `{ sceneId }` init data. The restart destroys the editor
|
|
592
|
+
* camera; the PRE_STEP late-boot-completion hook (1.0.6) detects that and
|
|
593
|
+
* re-runs the idempotent `enterEdit`, which re-installs editor chrome and
|
|
594
|
+
* posts a fresh `sceneLoaded` — that snapshot is the host's switch ACK.
|
|
595
|
+
*/
|
|
596
|
+
export interface EditorLoadSceneMessage {
|
|
597
|
+
type: 'umicat:editor:loadScene';
|
|
598
|
+
sceneId: string;
|
|
599
|
+
/** Scene file content (workspace truth). When present, replaces the cached copy. */
|
|
600
|
+
sceneFile?: unknown;
|
|
601
|
+
/** Updated manifest (new scenes / groups / initialScene). Replaces cache entry. */
|
|
602
|
+
manifest?: unknown;
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Replace the iframe's cached manifest without a scene switch — used after
|
|
606
|
+
* structural scene ops (create / rename / reorder / folders / set-initial)
|
|
607
|
+
* so the cached copy never goes stale relative to the workspace.
|
|
608
|
+
*/
|
|
609
|
+
export interface EditorUpdateManifestMessage {
|
|
610
|
+
type: 'umicat:editor:updateManifest';
|
|
611
|
+
manifest: unknown;
|
|
612
|
+
}
|
|
613
|
+
export type EditorHostToSdkMessage = EditorEnterMessage | EditorExitMessage | EditorGetSceneMessage | EditorApplyEditMessage | EditorSetSelectionMessage | EditorPanZoomMessage | EditorCreateEntityMessage | EditorDeleteEntityMessage | EditorSetEditModeMessage | EditorAssetUpdateMessage | EditorSetDebugOverlayMessage | EditorEditPrefabMessage | EditorPatchRuleMessage | EditorSetTilemapToolMessage | EditorEditTilemapMessage | EditorLoadSceneMessage | EditorUpdateManifestMessage;
|
|
584
614
|
export interface EditorSceneLoadedMessage {
|
|
585
615
|
type: 'umicat:editor:sceneLoaded';
|
|
586
616
|
sceneId: string;
|
package/dist/scene/types.d.ts
CHANGED
|
@@ -11,12 +11,28 @@ export declare const SCHEMA_VERSION = 1;
|
|
|
11
11
|
export type SceneType = 'world' | 'hud';
|
|
12
12
|
export interface SceneRef {
|
|
13
13
|
id: string;
|
|
14
|
+
/**
|
|
15
|
+
* Display name shown in the editor's scene browser (design 01 §6.1).
|
|
16
|
+
* Denormalized copy of the scene file's `name`; kept in sync by the
|
|
17
|
+
* editor's rename op. Optional — display falls back to `id`.
|
|
18
|
+
*/
|
|
19
|
+
name?: string;
|
|
14
20
|
type: SceneType;
|
|
15
21
|
/** Path under `public/scenes/`, e.g. `"world/level-1-1.json"`. */
|
|
16
22
|
file: string;
|
|
17
23
|
/** Optional HUD scene id to overlay (world scenes only). Null = no HUD. */
|
|
18
24
|
hud?: string | null;
|
|
19
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Editor-only scene folder (scene browser — design 03 §3.1's "loose
|
|
28
|
+
* enhancement"). Groups scenes for display; the runtime ignores it.
|
|
29
|
+
* Scenes not in any group render below a separator in `scenes[]` order.
|
|
30
|
+
*/
|
|
31
|
+
export interface ManifestGroup {
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
sceneIds: string[];
|
|
35
|
+
}
|
|
20
36
|
export interface HudRef {
|
|
21
37
|
id: string;
|
|
22
38
|
/** Path under `public/scenes/`, e.g. `"hud/game-hud.json"`. */
|
|
@@ -526,6 +542,11 @@ export interface Manifest {
|
|
|
526
542
|
* spawning) can omit this field.
|
|
527
543
|
*/
|
|
528
544
|
prefabs?: PrefabRecord[];
|
|
545
|
+
/**
|
|
546
|
+
* Editor-only scene folders (scene browser). Optional + purely additive —
|
|
547
|
+
* runtime never reads it. See {@link ManifestGroup}.
|
|
548
|
+
*/
|
|
549
|
+
groups?: ManifestGroup[];
|
|
529
550
|
globals?: {
|
|
530
551
|
physics?: {
|
|
531
552
|
gravity?: {
|