@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,251 @@
1
+ /**
2
+ * Per-game editor state, shared between EditorBridge (postMessage handler)
3
+ * and EditorOverlayScene (canvas renderer + pointer source).
4
+ *
5
+ * Design 03 §13.5: in Edit mode the editor overlay captures clicks before
6
+ * they reach game systems; this state carries the selection + drag-in-progress
7
+ * info both sides read.
8
+ */
9
+ /**
10
+ * Editor mode — slice 5. World mode edits the active world scene; HUD mode
11
+ * edits the HUD scene attached to that world (manifest's `scenes[].hud`).
12
+ * Toggled by host via `umicat:editor:setEditMode`.
13
+ */
14
+ export type EditorMode = 'world' | 'hud';
15
+ /**
16
+ * Editor debug-overlay flags (slice 8). Toggled by the host via
17
+ * `umicat:editor:setDebugOverlay`; read each frame by EditorOverlayScene.
18
+ */
19
+ export interface EditorDebugOverlayState {
20
+ /** Draw hitbox rects + depth-anchor crosshairs on sprites with metadata. */
21
+ showHitboxes: boolean;
22
+ }
23
+ /**
24
+ * Tilemap painter active state (slice 6 Phase B).
25
+ *
26
+ * When the user selects a tilemap entity, the host pushes the current tool
27
+ * + active tile + active layer via `umicat:editor:setTilemapTool`. The SDK
28
+ * caches this; on canvas pointer events over the tilemap, the overlay
29
+ * scene reads it to drive paint behavior locally (no per-cell host
30
+ * round-trip — same split-state pattern as drag-to-move).
31
+ *
32
+ * After each completed stroke (pointerup), the SDK posts
33
+ * `umicat:sdk:tilemapEdited { entityId, op }` so the host can record an
34
+ * undo command + persist on save.
35
+ *
36
+ * `tilemapEditingId` doubles as the "are we in paint mode?" flag — when
37
+ * non-null AND the selected entity is a tilemap, paint mode is active.
38
+ */
39
+ export type TilemapTool = 'brush' | 'eraser' | 'rect' | 'fill' | 'picker';
40
+ export interface TilemapToolState {
41
+ /** Tilemap entity currently being painted. Null = not in paint mode. */
42
+ tilemapEditingId: string | null;
43
+ /** Which layer (within the tilemap) the brush affects. */
44
+ activeLayerId: string | null;
45
+ /** Active tool — defaults to 'brush' when entering paint mode. */
46
+ tool: TilemapTool;
47
+ /**
48
+ * Tile index in the layer's tileset image (0-based, row-major).
49
+ * Null when no tile is picked yet — brush/rect/fill no-op in that case.
50
+ * Eraser ignores this field.
51
+ */
52
+ activeTile: number | null;
53
+ /**
54
+ * Slice 6 Phase D — Wang terrain id when in autotile mode. Non-null
55
+ * flips brush + eraser to autotile semantics: the click cascades
56
+ * across the 3×3 cell neighborhood, vertices toggle, ruleMap[bitmask]
57
+ * picks the tile per cell. Null = stamp-mode (Phase B behavior).
58
+ */
59
+ activeTerrainId: string | null;
60
+ }
61
+ interface EditorStateShape {
62
+ active: boolean;
63
+ selectedId: string | null;
64
+ mode: EditorMode;
65
+ /**
66
+ * Drag-in-progress info. While set, the overlay scene mutates the entity's
67
+ * x/y directly per pointermove without going through the host. On
68
+ * pointerup it posts dragEnd with before/after, and the host pushes a
69
+ * single command. This is the "SDK holds short-lived visual state" path
70
+ * from the slice-2 design discussion.
71
+ */
72
+ drag: {
73
+ entityId: string;
74
+ startWorld: {
75
+ x: number;
76
+ y: number;
77
+ };
78
+ startEntity: {
79
+ x: number;
80
+ y: number;
81
+ };
82
+ } | null;
83
+ debugOverlay: EditorDebugOverlayState;
84
+ /** Slice 6 Phase B — tilemap painter active state. See TilemapToolState docs. */
85
+ tilemap: TilemapToolState;
86
+ /**
87
+ * Slice 6 Phase B — paint-stroke accumulator. Brush/eraser collect cells
88
+ * during a pointer drag; on pointerup the SDK emits ONE `tilemapEdited`
89
+ * op carrying the whole stroke so undo reverts the entire stroke
90
+ * atomically. Null when no stroke is in flight.
91
+ */
92
+ tilemapStroke: {
93
+ entityId: string;
94
+ layerId: string;
95
+ /** Cells touched by the stroke. `index = null` for eraser cells. */
96
+ cells: Array<{
97
+ x: number;
98
+ y: number;
99
+ index: number | null;
100
+ prevIndex: number | null;
101
+ }>;
102
+ /**
103
+ * Slice 6 Phase D — autotile-mode stroke metadata. Present only when
104
+ * the stroke is painting with a terrain (not stamping a tile index).
105
+ *
106
+ * The `cells` array above tracks EVERY affected cell (clicked +
107
+ * cascade neighbors) for undo; `autotile.clickedCells` records only
108
+ * the user's actual click cells — that's what gets emitted in the
109
+ * `autotilePaint` op's `cells` field so undo can replay the inverse
110
+ * stroke and reproduce the cascade exactly.
111
+ */
112
+ autotile?: {
113
+ terrainId: string;
114
+ erase: boolean;
115
+ clickedCells: Array<{
116
+ x: number;
117
+ y: number;
118
+ }>;
119
+ };
120
+ } | null;
121
+ /**
122
+ * Slice 6 Phase B.4 — rect-drag in-flight state. EditorOverlayScene.update
123
+ * draws a preview rectangle while non-null. On pointerup the SDK composes
124
+ * a `fillRect` op covering startCell → endCell. Null when no rect drag.
125
+ */
126
+ tilemapRect: {
127
+ entityId: string;
128
+ layerId: string;
129
+ /** Cell coords (tile grid units), inclusive on both ends. */
130
+ startX: number;
131
+ startY: number;
132
+ endX: number;
133
+ endY: number;
134
+ /**
135
+ * Slice 6 Phase D — autotile-mode rect. When set, the rect commits
136
+ * as one `autotilePaint` op (each in-rect cell counts as a clicked
137
+ * cell) instead of `fillRect`.
138
+ */
139
+ autotile?: {
140
+ terrainId: string;
141
+ erase: boolean;
142
+ };
143
+ } | null;
144
+ /**
145
+ * Slice 6 Phase B.6.1 — tilemap resize-handle drag in flight. Set on
146
+ * pointerdown over a corner/edge handle, cleared on pointerup. Drives:
147
+ * (a) live ghost-rect preview in update(), (b) computing the final
148
+ * resize op + transformDelta on commit.
149
+ *
150
+ * Anchor flags (left/right/top/bottom = true) mark which edges the
151
+ * drag moves. The opposite edges stay fixed → transformDelta keeps
152
+ * them anchored after the resize op rebuilds layers around the new
153
+ * center.
154
+ */
155
+ tilemapResize: {
156
+ entityId: string;
157
+ handle: TilemapResizeHandle;
158
+ /** Original size + center at drag-start, in cells + world px. */
159
+ startSize: {
160
+ width: number;
161
+ height: number;
162
+ };
163
+ startCenter: {
164
+ x: number;
165
+ y: number;
166
+ };
167
+ tileSize: {
168
+ width: number;
169
+ height: number;
170
+ };
171
+ /** Current preview dims (snapped to integer cells). Updated per pointermove. */
172
+ previewWidth: number;
173
+ previewHeight: number;
174
+ /** Current preview center (shifts as edges move). */
175
+ previewCenter: {
176
+ x: number;
177
+ y: number;
178
+ };
179
+ } | null;
180
+ }
181
+ /**
182
+ * Tilemap resize handle identity. 4 corners + 4 edge midpoints. Each
183
+ * handle defines which edges move during the drag — opposite edges stay
184
+ * fixed (transformDelta computed to keep them anchored).
185
+ */
186
+ export type TilemapResizeHandle = 'nw' | 'ne' | 'sw' | 'se' | 'n' | 's' | 'w' | 'e';
187
+ /**
188
+ * Accept any object — we only use a single internal symbol-style key, so
189
+ * there's no risk of collision with Phaser's own props.
190
+ */
191
+ type AnyObject = object;
192
+ export declare function getEditorState(game: AnyObject): EditorStateShape;
193
+ export declare function setEditorActive(game: AnyObject, active: boolean): void;
194
+ export declare function getEditorMode(game: AnyObject): EditorMode;
195
+ export declare function setEditorMode(game: AnyObject, mode: EditorMode): void;
196
+ export declare function setSelection(game: AnyObject, id: string | null): void;
197
+ export declare function getSelection(game: AnyObject): string | null;
198
+ export declare function startDrag(game: AnyObject, entityId: string, startWorld: {
199
+ x: number;
200
+ y: number;
201
+ }, startEntity: {
202
+ x: number;
203
+ y: number;
204
+ }): void;
205
+ export declare function clearDrag(game: AnyObject): void;
206
+ export declare function getDrag(game: AnyObject): EditorStateShape['drag'];
207
+ export declare function getDebugOverlayState(game: AnyObject): EditorDebugOverlayState;
208
+ export declare function setDebugOverlayState(game: AnyObject, patch: Partial<EditorDebugOverlayState>): void;
209
+ export declare function getTilemapToolState(game: AnyObject): TilemapToolState;
210
+ export declare function setTilemapToolState(game: AnyObject, patch: Partial<TilemapToolState>): void;
211
+ export declare function isTilemapPaintMode(game: AnyObject): boolean;
212
+ export declare function getTilemapStroke(game: AnyObject): EditorStateShape['tilemapStroke'];
213
+ export declare function beginTilemapStroke(game: AnyObject, entityId: string, layerId: string): void;
214
+ /**
215
+ * Slice 6 Phase D — start an autotile-mode stroke. Same shape as
216
+ * `beginTilemapStroke` but carries the autotile discriminator so the
217
+ * pointerup commit emits an `autotilePaint` op (not `paint` / `erase`).
218
+ */
219
+ export declare function beginAutotileStroke(game: AnyObject, entityId: string, layerId: string, terrainId: string, erase: boolean): void;
220
+ export declare function appendTilemapStrokeCell(game: AnyObject, cell: {
221
+ x: number;
222
+ y: number;
223
+ index: number | null;
224
+ prevIndex: number | null;
225
+ }): void;
226
+ /**
227
+ * Slice 6 Phase D — record a user-clicked cell + its cascade-affected
228
+ * cells into the stroke. Click cell goes into `autotile.clickedCells`
229
+ * (dedup'd, last-wins by x/y); every affected cell (including the click
230
+ * itself and cascade neighbors) goes into `cells` (dedup'd, FIRST-wins
231
+ * by x/y so `prevIndex` reflects the state at the start of the stroke).
232
+ */
233
+ export declare function appendAutotileStrokeClick(game: AnyObject, clickX: number, clickY: number, affected: Array<{
234
+ x: number;
235
+ y: number;
236
+ index: number;
237
+ prevIndex: number;
238
+ }>): void;
239
+ export declare function endTilemapStroke(game: AnyObject): EditorStateShape['tilemapStroke'];
240
+ export declare function getTilemapRect(game: AnyObject): EditorStateShape['tilemapRect'];
241
+ export declare function beginTilemapRect(game: AnyObject, entityId: string, layerId: string, x: number, y: number, autotile?: {
242
+ terrainId: string;
243
+ erase: boolean;
244
+ }): void;
245
+ export declare function updateTilemapRect(game: AnyObject, x: number, y: number): void;
246
+ export declare function endTilemapRect(game: AnyObject): EditorStateShape['tilemapRect'];
247
+ export declare function getTilemapResize(game: AnyObject): EditorStateShape['tilemapResize'];
248
+ export declare function beginTilemapResize(game: AnyObject, resize: NonNullable<EditorStateShape['tilemapResize']>): void;
249
+ export declare function updateTilemapResize(game: AnyObject, patch: Partial<Pick<NonNullable<EditorStateShape['tilemapResize']>, 'previewWidth' | 'previewHeight' | 'previewCenter'>>): void;
250
+ export declare function endTilemapResize(game: AnyObject): EditorStateShape['tilemapResize'];
251
+ export {};
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Per-game editor state, shared between EditorBridge (postMessage handler)
3
+ * and EditorOverlayScene (canvas renderer + pointer source).
4
+ *
5
+ * Design 03 §13.5: in Edit mode the editor overlay captures clicks before
6
+ * they reach game systems; this state carries the selection + drag-in-progress
7
+ * info both sides read.
8
+ */
9
+ const KEY = '__unboxyEditorState';
10
+ function bag(game) {
11
+ return game;
12
+ }
13
+ export function getEditorState(game) {
14
+ const b = bag(game);
15
+ const existing = b[KEY];
16
+ if (existing)
17
+ return existing;
18
+ const fresh = {
19
+ active: false,
20
+ selectedId: null,
21
+ mode: 'world',
22
+ drag: null,
23
+ debugOverlay: { showHitboxes: false },
24
+ tilemap: {
25
+ tilemapEditingId: null,
26
+ activeLayerId: null,
27
+ tool: 'brush',
28
+ activeTile: null,
29
+ activeTerrainId: null,
30
+ },
31
+ tilemapStroke: null,
32
+ tilemapRect: null,
33
+ tilemapResize: null,
34
+ };
35
+ b[KEY] = fresh;
36
+ return fresh;
37
+ }
38
+ export function setEditorActive(game, active) {
39
+ getEditorState(game).active = active;
40
+ }
41
+ export function getEditorMode(game) {
42
+ return getEditorState(game).mode;
43
+ }
44
+ export function setEditorMode(game, mode) {
45
+ getEditorState(game).mode = mode;
46
+ }
47
+ export function setSelection(game, id) {
48
+ getEditorState(game).selectedId = id;
49
+ }
50
+ export function getSelection(game) {
51
+ return getEditorState(game).selectedId;
52
+ }
53
+ export function startDrag(game, entityId, startWorld, startEntity) {
54
+ getEditorState(game).drag = { entityId, startWorld, startEntity };
55
+ }
56
+ export function clearDrag(game) {
57
+ getEditorState(game).drag = null;
58
+ }
59
+ export function getDrag(game) {
60
+ return getEditorState(game).drag;
61
+ }
62
+ export function getDebugOverlayState(game) {
63
+ return getEditorState(game).debugOverlay;
64
+ }
65
+ export function setDebugOverlayState(game, patch) {
66
+ const state = getEditorState(game).debugOverlay;
67
+ Object.assign(state, patch);
68
+ }
69
+ // --- Slice 6 Phase B — tilemap painter state -----------------------------
70
+ export function getTilemapToolState(game) {
71
+ return getEditorState(game).tilemap;
72
+ }
73
+ export function setTilemapToolState(game, patch) {
74
+ const state = getEditorState(game).tilemap;
75
+ Object.assign(state, patch);
76
+ }
77
+ export function isTilemapPaintMode(game) {
78
+ const s = getEditorState(game);
79
+ return !!s.tilemap.tilemapEditingId && s.tilemap.tilemapEditingId === s.selectedId;
80
+ }
81
+ export function getTilemapStroke(game) {
82
+ return getEditorState(game).tilemapStroke;
83
+ }
84
+ export function beginTilemapStroke(game, entityId, layerId) {
85
+ getEditorState(game).tilemapStroke = { entityId, layerId, cells: [] };
86
+ }
87
+ /**
88
+ * Slice 6 Phase D — start an autotile-mode stroke. Same shape as
89
+ * `beginTilemapStroke` but carries the autotile discriminator so the
90
+ * pointerup commit emits an `autotilePaint` op (not `paint` / `erase`).
91
+ */
92
+ export function beginAutotileStroke(game, entityId, layerId, terrainId, erase) {
93
+ getEditorState(game).tilemapStroke = {
94
+ entityId,
95
+ layerId,
96
+ cells: [],
97
+ autotile: { terrainId, erase, clickedCells: [] },
98
+ };
99
+ }
100
+ export function appendTilemapStrokeCell(game, cell) {
101
+ const stroke = getEditorState(game).tilemapStroke;
102
+ if (!stroke)
103
+ return;
104
+ // Dedupe — pointermove fires many times per cell on slow drags.
105
+ const last = stroke.cells[stroke.cells.length - 1];
106
+ if (last && last.x === cell.x && last.y === cell.y)
107
+ return;
108
+ stroke.cells.push(cell);
109
+ }
110
+ /**
111
+ * Slice 6 Phase D — record a user-clicked cell + its cascade-affected
112
+ * cells into the stroke. Click cell goes into `autotile.clickedCells`
113
+ * (dedup'd, last-wins by x/y); every affected cell (including the click
114
+ * itself and cascade neighbors) goes into `cells` (dedup'd, FIRST-wins
115
+ * by x/y so `prevIndex` reflects the state at the start of the stroke).
116
+ */
117
+ export function appendAutotileStrokeClick(game, clickX, clickY, affected) {
118
+ const stroke = getEditorState(game).tilemapStroke;
119
+ if (!stroke || !stroke.autotile)
120
+ return;
121
+ const clicked = stroke.autotile.clickedCells;
122
+ const clickedLast = clicked[clicked.length - 1];
123
+ if (!clickedLast || clickedLast.x !== clickX || clickedLast.y !== clickY) {
124
+ clicked.push({ x: clickX, y: clickY });
125
+ }
126
+ // Build a fast (x,y) → index lookup into stroke.cells so we don't
127
+ // overwrite the first-seen prevIndex of cells already in the stroke.
128
+ // (Cascade neighbors get re-touched on every adjacent click; preserving
129
+ // their original prevIndex is what makes undo restore the pre-stroke
130
+ // state.) O(stroke.cells) per click is fine — strokes max out at a
131
+ // few hundred cells.
132
+ for (const a of affected) {
133
+ const existing = stroke.cells.findIndex((c) => c.x === a.x && c.y === a.y);
134
+ if (existing >= 0) {
135
+ // Update the latest tile index (so the resulting visual matches
136
+ // the on-canvas state), keep prevIndex from the first touch.
137
+ stroke.cells[existing].index = a.index < 0 ? null : a.index;
138
+ }
139
+ else {
140
+ stroke.cells.push({
141
+ x: a.x,
142
+ y: a.y,
143
+ index: a.index < 0 ? null : a.index,
144
+ prevIndex: a.prevIndex < 0 ? null : a.prevIndex,
145
+ });
146
+ }
147
+ }
148
+ }
149
+ export function endTilemapStroke(game) {
150
+ const stroke = getEditorState(game).tilemapStroke;
151
+ getEditorState(game).tilemapStroke = null;
152
+ return stroke;
153
+ }
154
+ export function getTilemapRect(game) {
155
+ return getEditorState(game).tilemapRect;
156
+ }
157
+ export function beginTilemapRect(game, entityId, layerId, x, y, autotile) {
158
+ getEditorState(game).tilemapRect = {
159
+ entityId,
160
+ layerId,
161
+ startX: x,
162
+ startY: y,
163
+ endX: x,
164
+ endY: y,
165
+ autotile,
166
+ };
167
+ }
168
+ export function updateTilemapRect(game, x, y) {
169
+ const rect = getEditorState(game).tilemapRect;
170
+ if (!rect)
171
+ return;
172
+ rect.endX = x;
173
+ rect.endY = y;
174
+ }
175
+ export function endTilemapRect(game) {
176
+ const rect = getEditorState(game).tilemapRect;
177
+ getEditorState(game).tilemapRect = null;
178
+ return rect;
179
+ }
180
+ // --- Slice 6 Phase B.6.1 — resize-handle drag ----------------------------
181
+ export function getTilemapResize(game) {
182
+ return getEditorState(game).tilemapResize;
183
+ }
184
+ export function beginTilemapResize(game, resize) {
185
+ getEditorState(game).tilemapResize = resize;
186
+ }
187
+ export function updateTilemapResize(game, patch) {
188
+ const r = getEditorState(game).tilemapResize;
189
+ if (!r)
190
+ return;
191
+ Object.assign(r, patch);
192
+ }
193
+ export function endTilemapResize(game) {
194
+ const r = getEditorState(game).tilemapResize;
195
+ getEditorState(game).tilemapResize = null;
196
+ return r;
197
+ }
@@ -0,0 +1,45 @@
1
+ import type { Transport } from '../core/Transport.js';
2
+ /**
3
+ * Game-scope key-value store shared by all players of a game.
4
+ *
5
+ * Unlike `umicat.saves` (per-user), `gameData` lives at the game level — one
6
+ * value per key, visible to everyone. Reads are public (anonymous players
7
+ * see the same data). Writes require an authenticated user; calling
8
+ * `set()` or `delete()` when `umicat.user === null` throws an `RpcError`
9
+ * with code `UNAUTHENTICATED`.
10
+ *
11
+ * Typical uses: scoreboards, shared inventories, tournament state, level
12
+ * of the day. Values are opaque JSON — primitive, object, or collection.
13
+ *
14
+ * Trust model (see SDK-GUIDE.md for details):
15
+ * - The backend does not enforce invariants INSIDE a value. If you store
16
+ * a list and append your entry, you own the read-modify-write loop —
17
+ * including not mutating other players' entries, truncating to cap
18
+ * the list size, and retrying on 409 conflicts.
19
+ * - Use `ifVersion` to avoid lost updates when concurrent writes race.
20
+ *
21
+ * Quotas (enforced at the backend):
22
+ * - 100 KB per value
23
+ * - 1 MB total per game
24
+ * - 64 keys per game
25
+ */
26
+ export declare class GameDataModule {
27
+ private transport;
28
+ constructor(transport: Transport);
29
+ /** Read the value under `key`. Returns `null` if unset. Public — works for anonymous viewers. */
30
+ get<T = unknown>(key: string): Promise<T | null>;
31
+ /**
32
+ * Write `value` under `key`. Requires an authenticated user.
33
+ * @param options.ifVersion — only succeed if the stored version matches; otherwise throws
34
+ * an RpcError with code `VERSION_MISMATCH`. Use this to implement safe read-modify-write
35
+ * loops for list values (scoreboards, shared lists).
36
+ * @returns the new version number.
37
+ */
38
+ set(key: string, value: unknown, options?: {
39
+ ifVersion?: number;
40
+ }): Promise<number>;
41
+ /** Delete the value at `key`. Requires an authenticated user. */
42
+ delete(key: string): Promise<boolean>;
43
+ /** List all keys that have a value set for this game. Public. */
44
+ list(): Promise<string[]>;
45
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Game-scope key-value store shared by all players of a game.
3
+ *
4
+ * Unlike `umicat.saves` (per-user), `gameData` lives at the game level — one
5
+ * value per key, visible to everyone. Reads are public (anonymous players
6
+ * see the same data). Writes require an authenticated user; calling
7
+ * `set()` or `delete()` when `umicat.user === null` throws an `RpcError`
8
+ * with code `UNAUTHENTICATED`.
9
+ *
10
+ * Typical uses: scoreboards, shared inventories, tournament state, level
11
+ * of the day. Values are opaque JSON — primitive, object, or collection.
12
+ *
13
+ * Trust model (see SDK-GUIDE.md for details):
14
+ * - The backend does not enforce invariants INSIDE a value. If you store
15
+ * a list and append your entry, you own the read-modify-write loop —
16
+ * including not mutating other players' entries, truncating to cap
17
+ * the list size, and retrying on 409 conflicts.
18
+ * - Use `ifVersion` to avoid lost updates when concurrent writes race.
19
+ *
20
+ * Quotas (enforced at the backend):
21
+ * - 100 KB per value
22
+ * - 1 MB total per game
23
+ * - 64 keys per game
24
+ */
25
+ export class GameDataModule {
26
+ constructor(transport) {
27
+ this.transport = transport;
28
+ }
29
+ /** Read the value under `key`. Returns `null` if unset. Public — works for anonymous viewers. */
30
+ async get(key) {
31
+ const res = await this.transport.call('gameData.get', { key });
32
+ return (res?.value ?? null);
33
+ }
34
+ /**
35
+ * Write `value` under `key`. Requires an authenticated user.
36
+ * @param options.ifVersion — only succeed if the stored version matches; otherwise throws
37
+ * an RpcError with code `VERSION_MISMATCH`. Use this to implement safe read-modify-write
38
+ * loops for list values (scoreboards, shared lists).
39
+ * @returns the new version number.
40
+ */
41
+ async set(key, value, options) {
42
+ const res = await this.transport.call('gameData.set', {
43
+ key,
44
+ value,
45
+ ifVersion: options?.ifVersion,
46
+ });
47
+ return res.version;
48
+ }
49
+ /** Delete the value at `key`. Requires an authenticated user. */
50
+ async delete(key) {
51
+ const res = await this.transport.call('gameData.delete', { key });
52
+ return res.deleted;
53
+ }
54
+ /** List all keys that have a value set for this game. Public. */
55
+ async list() {
56
+ const res = await this.transport.call('gameData.list');
57
+ return res.keys;
58
+ }
59
+ }
@@ -0,0 +1,43 @@
1
+ export { createUmicatGame } from './core/UmicatGame.js';
2
+ export type { UmicatGameOptions } from './core/UmicatGame.js';
3
+ export { UmicatScene } from './core/UmicatScene.js';
4
+ export { ORIENTATION_DIMENSIONS } from './orientation.js';
5
+ export type { Orientation } from './orientation.js';
6
+ export { setupScreenshotListener, takeScreenshot } from './screenshot/ScreenshotManager.js';
7
+ export { setupRecordingListener } from './recording/RecordingManager.js';
8
+ export { Umicat } from './core/Umicat.js';
9
+ export type { UmicatInitOptions } from './core/Umicat.js';
10
+ export { SavesModule } from './saves/SavesModule.js';
11
+ export { GameDataModule } from './gamedata/GameDataModule.js';
12
+ export { RealtimeModule } from './realtime/RealtimeModule.js';
13
+ export type { JoinOptions, RoomListEntry, RoomListOptions } from './realtime/RealtimeModule.js';
14
+ export { UmicatRoom, PlayerDataFacade, RoomDataFacade, ChatFacade, MAX_CHAT_TEXT_LEN, } from './realtime/UmicatRoom.js';
15
+ export type { ChatMessage, ChatMessageKind } from './realtime/UmicatRoom.js';
16
+ export { RpcError } from './core/Transport.js';
17
+ export type { Transport, TransportKind } from './core/Transport.js';
18
+ export type { UmicatUser } from './protocol.js';
19
+ export { loadWorldScene, preloadManifest, preloadSceneAssets, applyPixelArtFilters, getManifest, SCENES_BASE, MANIFEST_PATH, suspendSceneUpdates, } from './scene/SceneLoader.js';
20
+ export type { LoadWorldSceneOptions } from './scene/SceneLoader.js';
21
+ export { spawnEntity, parseColor, applyAssetHitbox, applyTilesetTileMetadata, getTilemapAt, addTilemapCollider, } from './scene/spawnEntity.js';
22
+ export type { SpawnContext, AssetResolver, RenderScriptResolver, TilemapHit, } from './scene/spawnEntity.js';
23
+ export { applyAutotile, findTerrain, getAutotileKind, invalidateAutotileCells, invalidateAutotileVertices, } from './scene/autotile.js';
24
+ export type { AutotileAffectedCell } from './scene/autotile.js';
25
+ export { EntityRegistry, attachEntityRegistry, getEntityRegistry, } from './scene/EntityRegistry.js';
26
+ export { spawnPrefab, getPrefab, listPrefabs } from './scene/Prefabs.js';
27
+ export type { SpawnPrefabOverrides, SpawnPrefabOptions } from './scene/Prefabs.js';
28
+ export type { PrefabRecord, PrefabKind, PrefabPhysics, PrefabBase, SpritePrefab, RectPrefab, CirclePrefab, CodeRenderedPrefab, } from './scene/types.js';
29
+ export { preloadRules, getRule, getRules, onRuleChange, patchRule } from './scene/Rules.js';
30
+ export { loadWaveSchedule, runWaveSchedule } from './scene/Waves.js';
31
+ export type { WaveCallbacks, WaveController, SpawnInstance } from './scene/Waves.js';
32
+ export { loadGameConfig } from './scene/GameConfig.js';
33
+ export type { GameConfig } from './scene/GameConfig.js';
34
+ export type { WaveScheduleRecord, WaveRecord, SpawnInstruction, SpawnPointInstruction, SpawnFormationInstruction, FormationRecord, FormationShape, WaveEndCondition, } from './scene/types.js';
35
+ export { setupEditorModeListener, isEditMode } from './scene/EditorMode.js';
36
+ export { setRenderScriptRegistry, getRenderScriptRegistry, resolveRenderScript, } from './scene/renderScripts.js';
37
+ export type { RenderScriptModule } from './scene/renderScripts.js';
38
+ export { setupEditorBridge } from './editor/EditorBridge.js';
39
+ export { EditorOverlayScene, EDITOR_OVERLAY_KEY } from './editor/EditorOverlayScene.js';
40
+ export type { EditorEntityPatch, EditorEnterMessage, EditorExitMessage, EditorGetSceneMessage, EditorApplyEditMessage, EditorSetSelectionMessage, EditorPanZoomMessage, EditorHostToSdkMessage, EditorSceneLoadedMessage, EditorSelectionPickedMessage, EditorDragEndMessage, EditorShortcutMessage, EditorCreateEntityMessage, EditorDeleteEntityMessage, EditorSetEditModeMessage, EditorSelectionRectMessage, EditorSdkToHostMessage, } from './protocol.js';
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';
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/index.js ADDED
@@ -0,0 +1,43 @@
1
+ // Core
2
+ export { createUmicatGame } from './core/UmicatGame.js';
3
+ export { UmicatScene } from './core/UmicatScene.js';
4
+ export { ORIENTATION_DIMENSIONS } from './orientation.js';
5
+ // Screenshot
6
+ export { setupScreenshotListener, takeScreenshot } from './screenshot/ScreenshotManager.js';
7
+ // Recording
8
+ export { setupRecordingListener } from './recording/RecordingManager.js';
9
+ // Platform services (v0.2.1+)
10
+ export { Umicat } from './core/Umicat.js';
11
+ export { SavesModule } from './saves/SavesModule.js';
12
+ export { GameDataModule } from './gamedata/GameDataModule.js';
13
+ export { RealtimeModule } from './realtime/RealtimeModule.js';
14
+ export { UmicatRoom, PlayerDataFacade, RoomDataFacade, ChatFacade, MAX_CHAT_TEXT_LEN, } from './realtime/UmicatRoom.js';
15
+ export { RpcError } from './core/Transport.js';
16
+ // Scene-as-data (visual editor foundation, slice 1)
17
+ export { loadWorldScene, preloadManifest, preloadSceneAssets, applyPixelArtFilters, getManifest, SCENES_BASE, MANIFEST_PATH, suspendSceneUpdates, } from './scene/SceneLoader.js';
18
+ export { spawnEntity, parseColor, applyAssetHitbox, applyTilesetTileMetadata, getTilemapAt, addTilemapCollider, } from './scene/spawnEntity.js';
19
+ // Slice 6 Phase D — Wang autotile runtime.
20
+ export { applyAutotile, findTerrain, getAutotileKind, invalidateAutotileCells, invalidateAutotileVertices, // deprecated alias kept for 0.2.122–0.2.124 callers
21
+ } from './scene/autotile.js';
22
+ export { EntityRegistry, attachEntityRegistry, getEntityRegistry, } from './scene/EntityRegistry.js';
23
+ // Prefabs — slice 11 Phase B.1 (2026-05-12). Runtime spawning of entity TYPES
24
+ // from manifest.prefabs[]. Replaces inline `this.physics.add.sprite(...)`.
25
+ export { spawnPrefab, getPrefab, listPrefabs } from './scene/Prefabs.js';
26
+ // Rules — slice 11 Phase B.2 (2026-05-12). Tunable game parameters in
27
+ // `public/rules.json`, read by behavior code via dot-notation paths.
28
+ // Replaces `const X = ...` TS declarations for any user-tunable value.
29
+ export { preloadRules, getRule, getRules, onRuleChange, patchRule } from './scene/Rules.js';
30
+ // Waves — slice 11 Phase B.4 (2026-05-12). Spawn schedules as data in
31
+ // `public/waves/<id>.json`. Replaces hand-rolled wave loops in
32
+ // `GameScene.ts` for shooters / runners / survivors.
33
+ export { loadWaveSchedule, runWaveSchedule } from './scene/Waves.js';
34
+ // Game config — slice 11 Phase B.3 (2026-05-12). Top-level game settings
35
+ // in `public/game.json` (orientation, dimensions, physics, controls).
36
+ // Replaces hardcoded src/config.ts constants.
37
+ export { loadGameConfig } from './scene/GameConfig.js';
38
+ export { setupEditorModeListener, isEditMode } from './scene/EditorMode.js';
39
+ export { setRenderScriptRegistry, getRenderScriptRegistry, resolveRenderScript, } from './scene/renderScripts.js';
40
+ export { setupEditorBridge } from './editor/EditorBridge.js';
41
+ export { EditorOverlayScene, EDITOR_OVERLAY_KEY } from './editor/EditorOverlayScene.js';
42
+ export { SCHEMA_VERSION, isPerFrameNinePatch, isPerFrameHitbox, } from './scene/types.js';
43
+ export { PROTOCOL_VERSION, } from './protocol.js';
@@ -0,0 +1,5 @@
1
+ export type Orientation = 'portrait' | 'landscape';
2
+ export declare const ORIENTATION_DIMENSIONS: Record<Orientation, {
3
+ width: number;
4
+ height: number;
5
+ }>;
@@ -0,0 +1,4 @@
1
+ export const ORIENTATION_DIMENSIONS = {
2
+ landscape: { width: 1280, height: 720 },
3
+ portrait: { width: 720, height: 1280 },
4
+ };