@umicat/phaser-sdk 1.0.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.
Files changed (62) hide show
  1. package/SDK-GUIDE.md +1726 -0
  2. package/dist/core/Transport.d.ts +28 -0
  3. package/dist/core/Transport.js +7 -0
  4. package/dist/core/Umicat.d.ts +45 -0
  5. package/dist/core/Umicat.js +60 -0
  6. package/dist/core/UmicatGame.d.ts +43 -0
  7. package/dist/core/UmicatGame.js +64 -0
  8. package/dist/core/UmicatScene.d.ts +19 -0
  9. package/dist/core/UmicatScene.js +38 -0
  10. package/dist/core/transports/LocalStorageTransport.d.ts +22 -0
  11. package/dist/core/transports/LocalStorageTransport.js +78 -0
  12. package/dist/core/transports/PostMessageTransport.d.ts +28 -0
  13. package/dist/core/transports/PostMessageTransport.js +105 -0
  14. package/dist/editor/EditorBridge.d.ts +114 -0
  15. package/dist/editor/EditorBridge.js +2608 -0
  16. package/dist/editor/EditorOverlayScene.d.ts +333 -0
  17. package/dist/editor/EditorOverlayScene.js +1896 -0
  18. package/dist/editor/EditorState.d.ts +251 -0
  19. package/dist/editor/EditorState.js +197 -0
  20. package/dist/gamedata/GameDataModule.d.ts +45 -0
  21. package/dist/gamedata/GameDataModule.js +59 -0
  22. package/dist/index.d.ts +43 -0
  23. package/dist/index.js +43 -0
  24. package/dist/orientation.d.ts +5 -0
  25. package/dist/orientation.js +4 -0
  26. package/dist/protocol.d.ts +807 -0
  27. package/dist/protocol.js +3 -0
  28. package/dist/realtime/RealtimeModule.d.ts +93 -0
  29. package/dist/realtime/RealtimeModule.js +115 -0
  30. package/dist/realtime/UmicatRoom.d.ts +197 -0
  31. package/dist/realtime/UmicatRoom.js +353 -0
  32. package/dist/recording/RecordingManager.d.ts +11 -0
  33. package/dist/recording/RecordingManager.js +59 -0
  34. package/dist/saves/SavesModule.d.ts +23 -0
  35. package/dist/saves/SavesModule.js +37 -0
  36. package/dist/scene/EditorMode.d.ts +17 -0
  37. package/dist/scene/EditorMode.js +22 -0
  38. package/dist/scene/EntityRegistry.d.ts +39 -0
  39. package/dist/scene/EntityRegistry.js +103 -0
  40. package/dist/scene/GameConfig.d.ts +60 -0
  41. package/dist/scene/GameConfig.js +50 -0
  42. package/dist/scene/HudRuntime.d.ts +131 -0
  43. package/dist/scene/HudRuntime.js +1224 -0
  44. package/dist/scene/Prefabs.d.ts +92 -0
  45. package/dist/scene/Prefabs.js +175 -0
  46. package/dist/scene/Rules.d.ts +73 -0
  47. package/dist/scene/Rules.js +164 -0
  48. package/dist/scene/SceneLoader.d.ts +118 -0
  49. package/dist/scene/SceneLoader.js +615 -0
  50. package/dist/scene/Waves.d.ts +85 -0
  51. package/dist/scene/Waves.js +365 -0
  52. package/dist/scene/autotile.d.ts +103 -0
  53. package/dist/scene/autotile.js +321 -0
  54. package/dist/scene/renderScripts.d.ts +53 -0
  55. package/dist/scene/renderScripts.js +67 -0
  56. package/dist/scene/spawnEntity.d.ts +201 -0
  57. package/dist/scene/spawnEntity.js +1326 -0
  58. package/dist/scene/types.d.ts +1166 -0
  59. package/dist/scene/types.js +34 -0
  60. package/dist/screenshot/ScreenshotManager.d.ts +14 -0
  61. package/dist/screenshot/ScreenshotManager.js +33 -0
  62. package/package.json +35 -0
@@ -0,0 +1,333 @@
1
+ import Phaser from 'phaser';
2
+ /**
3
+ * Editor overlay — slice 2.
4
+ *
5
+ * Runs ABOVE the world/HUD scenes. Its job:
6
+ *
7
+ * 1. Render selection rectangle around the currently selected entity
8
+ * 2. Render world bounds rectangle (visual cue for "edge of the game world")
9
+ * 3. Capture pointer events:
10
+ * - pointerdown on an entity → posts pickEntity to host
11
+ * - drag → mutates the entity's x/y in real time (visual only)
12
+ * - pointerup → posts dragEnd with before/after to host
13
+ *
14
+ * The overlay scene is launched by EditorBridge when entering Edit mode,
15
+ * stopped on exit. It holds no persistent state of its own — selection +
16
+ * drag info live in the shared EditorState attached to the Phaser game.
17
+ */
18
+ export declare const EDITOR_OVERLAY_KEY = "__UmicatEditorOverlay";
19
+ interface EditorOverlayInitData {
20
+ /** World bounds rect to draw (slice 2 draws but doesn't allow editing). */
21
+ worldBounds?: {
22
+ x: number;
23
+ y: number;
24
+ width: number;
25
+ height: number;
26
+ };
27
+ /**
28
+ * Callback to resolve the entity at a given world point. Provided by the
29
+ * EditorBridge so the overlay doesn't have to know about the EntityRegistry.
30
+ * Returns the topmost (highest depth) entity at that point or null.
31
+ */
32
+ hitTest: (worldX: number, worldY: number) => Phaser.GameObjects.GameObject | null;
33
+ /**
34
+ * FB.9a — return ALL entities at (worldX, worldY), sorted by depth desc.
35
+ * Used by Alt+click cycle (selecting underlying entities when 2+ overlap).
36
+ */
37
+ hitTestAll: (worldX: number, worldY: number) => Phaser.GameObjects.GameObject[];
38
+ /**
39
+ * postMessage helpers (so the scene can send pickEntity / dragEnd).
40
+ *
41
+ * `prefabId` is set when the picked GameObject was spawned via `spawnPrefab`
42
+ * (tagged with `entityPrefabId` by the SDK at spawn time). The host uses
43
+ * it to open the Prefab Inspector instead of the Entity Inspector — see
44
+ * `EditorSelectionPickedMessage` in protocol.ts.
45
+ */
46
+ postPick: (entityId: string | null, modifiers: {
47
+ shift: boolean;
48
+ cmdOrCtrl: boolean;
49
+ alt: boolean;
50
+ }, prefabId?: string) => void;
51
+ postDragEnd: (entityId: string, before: {
52
+ x: number;
53
+ y: number;
54
+ }, after: {
55
+ x: number;
56
+ y: number;
57
+ }) => void;
58
+ /**
59
+ * Forward an editor keyboard shortcut to the host. Set when the iframe has
60
+ * focus (which is always after the user clicks the canvas to select);
61
+ * native Cmd+Z / Backspace otherwise can't reach the host.
62
+ */
63
+ postShortcut: (action: 'undo' | 'redo' | 'save' | 'delete') => void;
64
+ /**
65
+ * P1 infinite canvas — apply pan/zoom to the world camera. Called from
66
+ * the overlay scene's wheel + middle-button + space-drag handlers.
67
+ * Routed through EditorBridge (not called directly here) to keep the
68
+ * pan/zoom mutation in one place + avoid a circular import between
69
+ * overlay scene and bridge.
70
+ */
71
+ applyPanZoom: (msg: {
72
+ scrollX?: number;
73
+ scrollY?: number;
74
+ zoom?: number;
75
+ relative?: boolean;
76
+ }) => void;
77
+ }
78
+ export declare class EditorOverlayScene extends Phaser.Scene {
79
+ private graphics;
80
+ private worldBounds?;
81
+ private hitTest;
82
+ private hitTestAll;
83
+ private postPick;
84
+ private postDragEnd;
85
+ private postShortcut;
86
+ private applyPanZoom;
87
+ private panActive;
88
+ private spaceHeld;
89
+ private panStartScreen;
90
+ private panStartScroll;
91
+ private wheelHandler?;
92
+ constructor();
93
+ init(data: EditorOverlayInitData): void;
94
+ create(): void;
95
+ private handleShortcut;
96
+ /**
97
+ * Pointer coords mode-aware. World mode uses world coords (camera-relative);
98
+ * HUD mode transforms pointer through the HUD scene's camera to land in
99
+ * HUD-intrinsic coords (the coord space widget positions live in).
100
+ *
101
+ * Pre-0.2.90 this returned `pointer.x/y` (canvas pixels) for HUD mode
102
+ * — fine when HUD cam was an identity camera (viewport == canvas,
103
+ * zoom == 1). But 0.2.89 changed HUD cam to render INSIDE the camera-
104
+ * viewport rect on the editor canvas with editor-cam zoom, so canvas
105
+ * pixels no longer equal HUD-intrinsic coords. Hit-test against
106
+ * widgets (positioned in HUD-intrinsic) would only match a tiny
107
+ * patch near the canvas top-left, hence the user's "have to click
108
+ * many times" complaint. Using `hudCam.getWorldPoint(...)` applies
109
+ * the cam's inverse transform (subtract viewport offset, divide by
110
+ * zoom) and lands in widget coord space.
111
+ */
112
+ private pointerCoords;
113
+ private handlePointerDown;
114
+ private handlePointerMove;
115
+ private handlePointerUp;
116
+ /**
117
+ * Pointer-down inside paint mode. Returns true when the pointer hit the
118
+ * active layer (stroke began); false when the pointer fell outside the
119
+ * tilemap's bounds (caller falls through to normal selection).
120
+ *
121
+ * Begins a stroke + applies the first cell. brush/eraser tools paint
122
+ * incrementally per pointermove; rect/fill/picker (Phase B.4) handle
123
+ * pointerdown specially — for now only brush + eraser are wired.
124
+ */
125
+ private handleTilemapPaintDown;
126
+ private handleTilemapPaintMove;
127
+ /**
128
+ * Compose stroke into one TilemapEditOp + post to host. Host records the
129
+ * undo command + persists on next flush. Stroke state is cleared.
130
+ *
131
+ * Brush stroke → `paint` op with all cells. Eraser stroke → `erase` op.
132
+ * (Phase B.4 adds rect / fill emit paths.)
133
+ */
134
+ private handleTilemapPaintUp;
135
+ /**
136
+ * Compose a `fillRect` op from the completed rect drag + apply it live +
137
+ * post tilemapEdited. `previousCells` captures every cell the rect
138
+ * overwrites so undo replays them onto the layer.
139
+ */
140
+ private commitTilemapRect;
141
+ /**
142
+ * Bucket fill (4-connected flood). Captures every cell the flood
143
+ * touches into previousCells before applying, then posts one tilemapEdited
144
+ * so undo restores the whole flooded area.
145
+ *
146
+ * Reads the layer in one pass to compute the visited set + previous
147
+ * indices, then commits via Phaser's putTileAt. Single-pass because
148
+ * applyTilemapOp would re-walk + duplicate work.
149
+ */
150
+ private applyBucketFill;
151
+ /**
152
+ * Slice 6 Phase D — autotile bucket fill. 4-connected flood over cells
153
+ * with matching tile index (or all empties), then runs the wang cascade
154
+ * for each flooded cell. The resulting `autotilePaint` op carries every
155
+ * flooded cell as a clicked cell; `previousCells` covers the flood +
156
+ * its 1-cell border for cascade-correct undo.
157
+ */
158
+ private applyAutotileBucketFill;
159
+ /**
160
+ * Look up the active TilemapLayer in the world scene's entity registry,
161
+ * then walk the container's children for the layer with matching
162
+ * `tilemapLayerId` data tag.
163
+ */
164
+ private findActiveTilemapLayer;
165
+ /**
166
+ * Same as findActiveTilemapLayer but returns the container too. Callers
167
+ * that need to convert world coords to tile coords need the container's
168
+ * position to shift the input — `TilemapLayer.worldToTileXY` doesn't
169
+ * apply the container transform on its own (the layer's `x`/`y` are
170
+ * local to the container, not world coords).
171
+ */
172
+ private findActiveTilemapLayerWithContainer;
173
+ /**
174
+ * Apply one stroke cell: read prev index (for undo), apply the new
175
+ * value via Phaser's tilemap API, push the cell into the stroke
176
+ * accumulator. Dedup happens in `appendTilemapStrokeCell` so dragging
177
+ * over the same cell multiple times only records once.
178
+ */
179
+ private applyStrokeCell;
180
+ /**
181
+ * Slice 6 Phase D — resolve `{ asset, terrain }` for the layer's
182
+ * tileset + a requested terrain id. Returns null when:
183
+ * - the layer has no `tilemapTilesetId` stamp (legacy / unattached layer)
184
+ * - the manifest has no asset for that id
185
+ * - the asset's tileset metadata lacks `autotile.terrains` with that id
186
+ * Callers fall back to stamp-mode behavior on null.
187
+ */
188
+ private resolveAutotileTerrainContext;
189
+ /**
190
+ * Slice 6 Phase D — autotile-mode stroke cell. Runs the Wang cascade
191
+ * via `applyAutotile`, threads every affected cell (clicked + cascade
192
+ * neighbors) into the stroke accumulator so the pointerup commit can
193
+ * emit one `autotilePaint` op + a previousCells array that captures
194
+ * the entire region the click changed.
195
+ *
196
+ * Per-frame metadata + sub-tile body sync is handled by the host-
197
+ * driven `handleEditTilemap` path when undo replays inverse ops; the
198
+ * live stroke only touches `layer.data` (cell indices) — fine because
199
+ * cell-rect collision is re-armed at the next handleEditTilemap call.
200
+ */
201
+ private applyAutotileStrokeCell;
202
+ /**
203
+ * Sync every tilemap entity's TilemapLayers to its container's
204
+ * current world position. Runs every frame in edit mode (see update()).
205
+ * Matches the play-mode hook in SceneLoader#installTilemapLayerSync —
206
+ * same logic, different trigger source (overlay vs world scene event).
207
+ * Cheap: handful of number assignments per tilemap.
208
+ */
209
+ private syncTilemapLayersFromContainers;
210
+ /**
211
+ * Read the selected tilemap entity's bounds + return the 8 handle
212
+ * positions in world coords. Returns null when the selected entity
213
+ * is not a tilemap (no handles to draw / hit-test).
214
+ */
215
+ private tilemapHandlePositions;
216
+ /**
217
+ * Hit-test the resize handles. Corners (NW/NE/SW/SE) use a dedicated
218
+ * ~14px square click target. Edges (N/S/E/W) are grabbable along the
219
+ * ENTIRE edge line (Figma / Sketch convention) — clicking anywhere on
220
+ * the blue bounds line resizes that edge. Corner zones take priority
221
+ * over edges so dragging right at a corner gives diagonal resize, not
222
+ * single-axis.
223
+ *
224
+ * All click targets are zoom-invariant via `1/zoom` scaling so they
225
+ * stay constant size on screen regardless of how zoomed in/out.
226
+ */
227
+ private hitTestTilemapResizeHandle;
228
+ /**
229
+ * Set canvas cursor to a resize-arrow when hovering a handle, or restore
230
+ * default. Direction matches the handle's axis (Figma / Sketch / browser
231
+ * native convention):
232
+ * NW/SE corners → `nwse-resize` (↖↘)
233
+ * NE/SW corners → `nesw-resize` (↗↙)
234
+ * N/S edges → `ns-resize` (↕)
235
+ * E/W edges → `ew-resize` (↔)
236
+ *
237
+ * Active drag (getTilemapResize non-null) pins the cursor to the dragged
238
+ * handle so it doesn't flicker back to default when the cursor briefly
239
+ * leaves the handle's 14px target box during fast drag.
240
+ */
241
+ private updateResizeCursor;
242
+ /**
243
+ * Begin a resize-handle drag. Snapshots the starting size + center so
244
+ * pointermove can compute deltas relative to drag-start.
245
+ */
246
+ private beginTilemapResizeDrag;
247
+ /**
248
+ * Update preview dims based on cursor position. Snaps to integer cells.
249
+ * The handle dictates which edges move — opposite edges stay fixed.
250
+ *
251
+ * Algorithm: from the cursor position + handle, compute the new L/R/T/B
252
+ * edges; opposite edges are pinned to start values. New size = R-L, B-T
253
+ * in pixels → divide by tileSize for cell counts. New center = midpoint
254
+ * of new L/R/T/B.
255
+ */
256
+ private updateTilemapResizeDrag;
257
+ /**
258
+ * Commit the resize drag — post a `resize` op via `editTilemap` channel,
259
+ * carrying the new dims + transformDelta to keep the opposite edge
260
+ * anchored. Posted directly to host (skipping the local SDK apply path)
261
+ * because the host's draft + iframe runtime BOTH need the op — host
262
+ * records the command for undo + applies the same op back via the
263
+ * normal editTilemap dispatch (which mutates the live runtime).
264
+ */
265
+ private commitTilemapResize;
266
+ update(): void;
267
+ /**
268
+ * Render the 8 resize handles (when paint mode is active) and the
269
+ * orange ghost-rect preview (when a resize drag is in progress).
270
+ * Handles are zoom-invariant ~12px squares; preview rect snaps to
271
+ * cell boundaries via the resize-drag's running preview state.
272
+ */
273
+ private drawTilemapResizeOverlay;
274
+ /**
275
+ * Walks the world entity registry and draws each sprite's `hitbox` rect +
276
+ * `depthAnchor` crosshair (when present on the entity's Asset). Sprites
277
+ * without metadata get nothing drawn — chat-only Workflow A respect.
278
+ *
279
+ * Per-frame mode: reads the sprite's CURRENT frame index and looks up the
280
+ * override (falls back to default) so the rendered rect tracks what the
281
+ * SDK is actually applying to the body at runtime.
282
+ */
283
+ private drawHitboxDebug;
284
+ /**
285
+ * For per-frame hitboxes, pick the shape the SDK would currently be
286
+ * applying — the override for the playing frame, falling back to default.
287
+ * For single-shape hitboxes, just return the rect.
288
+ */
289
+ private resolveCurrentHitboxShape;
290
+ private findWorldSceneInstance;
291
+ /**
292
+ * Find the world scene's main camera so the overlay can mirror it.
293
+ * In edit mode, the world scene is paused but its camera state is what
294
+ * the overlay's pointer math should use.
295
+ */
296
+ private findWorldSceneCamera;
297
+ /**
298
+ * P1 infinite canvas — read the editor camera installed by
299
+ * `installEditorCameras` in EditorBridge. Returns null on the boot race
300
+ * when the overlay scene's `create` runs before the bridge attaches it
301
+ * (resolved by the next `applyEditorPanZoom` mirror).
302
+ */
303
+ private findEditorCamera;
304
+ /**
305
+ * The camera the editor is currently viewing through. Prefers the
306
+ * editor cam; falls back to the game's cameras.main if the editor cam
307
+ * hasn't been installed yet (boot race). All pan/zoom math + selection
308
+ * rects should use this, NOT cameras.main directly.
309
+ */
310
+ private findActiveEditorCamera;
311
+ /**
312
+ * P1 infinite canvas — install native DOM listeners for wheel + space
313
+ * tracking. Phaser's pointer events don't surface `wheel`, and we want
314
+ * Space to be a global modifier (held while moving cursor), not tied to
315
+ * a specific GameObject. Listeners are torn down on scene shutdown.
316
+ *
317
+ * World mode only: HUD has identity camera + anchor-positioned widgets,
318
+ * panning/zooming it would rip widgets off their anchors.
319
+ */
320
+ private installPanZoomInput;
321
+ /**
322
+ * Be polite to text input — don't intercept Space when the user is
323
+ * typing into a form control inside the iframe (shouldn't normally
324
+ * happen, but be defensive).
325
+ */
326
+ private isTypingTarget;
327
+ /**
328
+ * Mode-aware registry lookup. World mode skips the HUD scene; HUD mode
329
+ * picks the HUD scene specifically.
330
+ */
331
+ private findEntityRegistry;
332
+ }
333
+ export {};