@smoregg/sdk 2.0.0 → 2.2.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/cjs/controller.cjs +260 -113
- package/dist/cjs/controller.cjs.map +1 -1
- package/dist/cjs/errors.cjs +1 -0
- package/dist/cjs/errors.cjs.map +1 -1
- package/dist/cjs/events.cjs +26 -3
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/index.cjs +2 -7
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/screen.cjs +244 -128
- package/dist/cjs/screen.cjs.map +1 -1
- package/dist/cjs/shared.cjs +34 -0
- package/dist/cjs/shared.cjs.map +1 -0
- package/dist/cjs/testing.cjs +181 -73
- package/dist/cjs/testing.cjs.map +1 -1
- package/dist/cjs/transport/PostMessageTransport.cjs +12 -0
- package/dist/cjs/transport/PostMessageTransport.cjs.map +1 -1
- package/dist/cjs/transport/protocol.cjs +2 -0
- package/dist/cjs/transport/protocol.cjs.map +1 -1
- package/dist/cjs/types.cjs +16 -0
- package/dist/cjs/types.cjs.map +1 -0
- package/dist/esm/controller.js +262 -115
- package/dist/esm/controller.js.map +1 -1
- package/dist/esm/errors.js +1 -0
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/events.js +25 -4
- package/dist/esm/events.js.map +1 -1
- package/dist/esm/index.js +1 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/screen.js +246 -130
- package/dist/esm/screen.js.map +1 -1
- package/dist/esm/shared.js +30 -0
- package/dist/esm/shared.js.map +1 -0
- package/dist/esm/testing.js +181 -73
- package/dist/esm/testing.js.map +1 -1
- package/dist/esm/transport/PostMessageTransport.js +12 -0
- package/dist/esm/transport/PostMessageTransport.js.map +1 -1
- package/dist/esm/transport/protocol.js +2 -1
- package/dist/esm/transport/protocol.js.map +1 -1
- package/dist/esm/types.js +14 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/types/controller.d.ts +1 -1
- package/dist/types/controller.d.ts.map +1 -1
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/events.d.ts +14 -1
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -8
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/screen.d.ts +3 -3
- package/dist/types/screen.d.ts.map +1 -1
- package/dist/types/shared.d.ts +21 -0
- package/dist/types/shared.d.ts.map +1 -0
- package/dist/types/testing.d.ts +65 -4
- package/dist/types/testing.d.ts.map +1 -1
- package/dist/types/transport/PostMessageTransport.d.ts +1 -0
- package/dist/types/transport/PostMessageTransport.d.ts.map +1 -1
- package/dist/types/transport/protocol.d.ts +5 -0
- package/dist/types/transport/protocol.d.ts.map +1 -1
- package/dist/types/types.d.ts +254 -345
- package/dist/types/types.d.ts.map +1 -1
- package/dist/umd/smore-sdk.umd.js +575 -784
- package/dist/umd/smore-sdk.umd.js.map +1 -1
- package/dist/umd/smore-sdk.umd.min.js +1 -1
- package/dist/umd/smore-sdk.umd.min.js.map +1 -1
- package/package.json +7 -1
- package/dist/cjs/config.cjs +0 -13
- package/dist/cjs/config.cjs.map +0 -1
- package/dist/esm/config.js +0 -10
- package/dist/esm/config.js.map +0 -1
- package/dist/types/config.d.ts +0 -35
- package/dist/types/config.d.ts.map +0 -1
package/dist/esm/testing.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { validateEventName } from './events.js';
|
|
2
|
+
import { SmoreSDKError } from './errors.js';
|
|
2
3
|
|
|
3
4
|
function createMockScreen(options = {}) {
|
|
4
5
|
const {
|
|
@@ -8,6 +9,7 @@ function createMockScreen(options = {}) {
|
|
|
8
9
|
} = options;
|
|
9
10
|
let _controllers = [...initialControllers];
|
|
10
11
|
let _isReady = false;
|
|
12
|
+
let _isConnected = false;
|
|
11
13
|
let _isDestroyed = false;
|
|
12
14
|
const listeners = /* @__PURE__ */ new Map();
|
|
13
15
|
const _onAllReadyCallbacks = /* @__PURE__ */ new Set();
|
|
@@ -16,13 +18,15 @@ function createMockScreen(options = {}) {
|
|
|
16
18
|
const _onControllerDisconnectCallbacks = /* @__PURE__ */ new Set();
|
|
17
19
|
const _onControllerReconnectCallbacks = /* @__PURE__ */ new Set();
|
|
18
20
|
const _onCharacterUpdatedCallbacks = /* @__PURE__ */ new Set();
|
|
19
|
-
const _onRateLimitedCallbacks = /* @__PURE__ */ new Set();
|
|
20
21
|
const _onErrorCallbacks = /* @__PURE__ */ new Set();
|
|
22
|
+
const _onConnectionChangeCallbacks = /* @__PURE__ */ new Set();
|
|
21
23
|
let _allReadyFired = false;
|
|
22
24
|
let _readyResolve;
|
|
23
25
|
const _readyPromise = new Promise((resolve) => {
|
|
24
26
|
_readyResolve = resolve;
|
|
25
27
|
});
|
|
28
|
+
const _customStates = /* @__PURE__ */ new Map();
|
|
29
|
+
const _stateChangeListeners = /* @__PURE__ */ new Set();
|
|
26
30
|
const broadcasts = [];
|
|
27
31
|
const sends = [];
|
|
28
32
|
const screen = {
|
|
@@ -39,6 +43,12 @@ function createMockScreen(options = {}) {
|
|
|
39
43
|
get isDestroyed() {
|
|
40
44
|
return _isDestroyed;
|
|
41
45
|
},
|
|
46
|
+
get isConnected() {
|
|
47
|
+
return _isConnected;
|
|
48
|
+
},
|
|
49
|
+
get protocolVersion() {
|
|
50
|
+
return 1;
|
|
51
|
+
},
|
|
42
52
|
get ready() {
|
|
43
53
|
return _readyPromise;
|
|
44
54
|
},
|
|
@@ -82,87 +92,107 @@ function createMockScreen(options = {}) {
|
|
|
82
92
|
_onCharacterUpdatedCallbacks.delete(callback);
|
|
83
93
|
};
|
|
84
94
|
},
|
|
85
|
-
onRateLimited(callback) {
|
|
86
|
-
_onRateLimitedCallbacks.add(callback);
|
|
87
|
-
return () => {
|
|
88
|
-
_onRateLimitedCallbacks.delete(callback);
|
|
89
|
-
};
|
|
90
|
-
},
|
|
91
95
|
onError(callback) {
|
|
92
96
|
_onErrorCallbacks.add(callback);
|
|
93
97
|
return () => {
|
|
94
98
|
_onErrorCallbacks.delete(callback);
|
|
95
99
|
};
|
|
96
100
|
},
|
|
101
|
+
onConnectionChange(callback) {
|
|
102
|
+
_onConnectionChangeCallbacks.add(callback);
|
|
103
|
+
return () => {
|
|
104
|
+
_onConnectionChangeCallbacks.delete(callback);
|
|
105
|
+
};
|
|
106
|
+
},
|
|
97
107
|
// === Communication Methods ===
|
|
98
108
|
broadcast(event, data) {
|
|
99
109
|
if (_isDestroyed) {
|
|
100
|
-
throw new
|
|
101
|
-
}
|
|
102
|
-
if (!_isReady) {
|
|
103
|
-
throw new Error("Cannot broadcast: screen is not ready");
|
|
104
|
-
}
|
|
105
|
-
validateEventName(event);
|
|
106
|
-
broadcasts.push({ event, data });
|
|
107
|
-
},
|
|
108
|
-
broadcastRaw(event, data) {
|
|
109
|
-
if (_isDestroyed) {
|
|
110
|
-
throw new Error("Cannot broadcast: screen is destroyed");
|
|
110
|
+
throw new SmoreSDKError("DESTROYED", "Cannot call broadcast() after destroy()");
|
|
111
111
|
}
|
|
112
112
|
if (!_isReady) {
|
|
113
|
-
throw new
|
|
113
|
+
throw new SmoreSDKError("NOT_READY", "Cannot call broadcast() before screen is ready");
|
|
114
114
|
}
|
|
115
115
|
validateEventName(event);
|
|
116
116
|
broadcasts.push({ event, data });
|
|
117
117
|
},
|
|
118
118
|
sendToController(playerIndex, event, data) {
|
|
119
119
|
if (_isDestroyed) {
|
|
120
|
-
throw new
|
|
120
|
+
throw new SmoreSDKError("DESTROYED", "Cannot call sendToController() after destroy()");
|
|
121
121
|
}
|
|
122
122
|
if (!_isReady) {
|
|
123
|
-
throw new
|
|
123
|
+
throw new SmoreSDKError("NOT_READY", "Cannot call sendToController() before screen is ready");
|
|
124
124
|
}
|
|
125
125
|
validateEventName(event);
|
|
126
126
|
if (!_controllers.some((c) => c.playerIndex === playerIndex)) {
|
|
127
|
-
throw new
|
|
127
|
+
throw new SmoreSDKError("INVALID_PLAYER", `No controller found with player index ${playerIndex}`);
|
|
128
128
|
}
|
|
129
129
|
sends.push({ playerIndex, event, data });
|
|
130
130
|
},
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
131
|
+
// === Custom State Methods ===
|
|
132
|
+
getControllerState(playerIndex) {
|
|
133
|
+
return _customStates.get(playerIndex);
|
|
134
|
+
},
|
|
135
|
+
getAllControllerStates() {
|
|
136
|
+
const result = {};
|
|
137
|
+
_customStates.forEach((state, playerIndex) => {
|
|
138
|
+
result[playerIndex] = state;
|
|
139
|
+
});
|
|
140
|
+
return result;
|
|
141
|
+
},
|
|
142
|
+
onCustomStateChange(listener) {
|
|
143
|
+
_stateChangeListeners.add(listener);
|
|
144
|
+
return () => {
|
|
145
|
+
_stateChangeListeners.delete(listener);
|
|
146
|
+
};
|
|
147
|
+
},
|
|
148
|
+
simulateStateChange(playerIndex, state) {
|
|
149
|
+
const existing = _customStates.get(playerIndex) ?? {};
|
|
150
|
+
const next = { ...existing, ...state };
|
|
151
|
+
_customStates.set(playerIndex, next);
|
|
152
|
+
_stateChangeListeners.forEach((cb) => cb(playerIndex, next));
|
|
143
153
|
},
|
|
144
154
|
// === Game Lifecycle ===
|
|
145
155
|
gameOver(results) {
|
|
146
156
|
if (_isDestroyed) {
|
|
147
|
-
throw new
|
|
157
|
+
throw new SmoreSDKError("DESTROYED", "Cannot call gameOver() after destroy()");
|
|
148
158
|
}
|
|
149
159
|
if (!_isReady) {
|
|
150
|
-
throw new
|
|
160
|
+
throw new SmoreSDKError("NOT_READY", "Cannot call gameOver() before screen is ready");
|
|
151
161
|
}
|
|
152
162
|
broadcasts.push({ event: "smore:game-over", data: { results } });
|
|
153
163
|
},
|
|
154
164
|
signalReady() {
|
|
155
165
|
if (_isDestroyed) {
|
|
156
|
-
throw new
|
|
166
|
+
throw new SmoreSDKError("DESTROYED", "Cannot call signalReady() after destroy()");
|
|
157
167
|
}
|
|
158
168
|
if (!_isReady) {
|
|
159
|
-
throw new
|
|
169
|
+
throw new SmoreSDKError("NOT_READY", "Cannot call signalReady() before screen is ready");
|
|
160
170
|
}
|
|
161
171
|
},
|
|
162
172
|
// === Event Subscription ===
|
|
163
173
|
on(event, handler) {
|
|
164
|
-
validateEventName(event);
|
|
165
174
|
const eventStr = event;
|
|
175
|
+
if (eventStr.startsWith("$")) {
|
|
176
|
+
switch (eventStr) {
|
|
177
|
+
case "$controller-join":
|
|
178
|
+
return screen.onControllerJoin(handler);
|
|
179
|
+
case "$controller-leave":
|
|
180
|
+
return screen.onControllerLeave(handler);
|
|
181
|
+
case "$controller-disconnect":
|
|
182
|
+
return screen.onControllerDisconnect(handler);
|
|
183
|
+
case "$controller-reconnect":
|
|
184
|
+
return screen.onControllerReconnect(handler);
|
|
185
|
+
case "$character-updated":
|
|
186
|
+
return screen.onCharacterUpdated(handler);
|
|
187
|
+
case "$all-ready":
|
|
188
|
+
return screen.onAllReady(handler);
|
|
189
|
+
case "$error":
|
|
190
|
+
return screen.onError(handler);
|
|
191
|
+
case "$connection-change":
|
|
192
|
+
return screen.onConnectionChange(handler);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
validateEventName(event);
|
|
166
196
|
if (!listeners.has(eventStr)) {
|
|
167
197
|
listeners.set(eventStr, /* @__PURE__ */ new Set());
|
|
168
198
|
}
|
|
@@ -188,6 +218,13 @@ function createMockScreen(options = {}) {
|
|
|
188
218
|
listeners.get(eventStr)?.delete(handler);
|
|
189
219
|
}
|
|
190
220
|
},
|
|
221
|
+
removeAllListeners(event) {
|
|
222
|
+
if (event) {
|
|
223
|
+
listeners.delete(event);
|
|
224
|
+
} else {
|
|
225
|
+
listeners.clear();
|
|
226
|
+
}
|
|
227
|
+
},
|
|
191
228
|
// === Utilities ===
|
|
192
229
|
getController(playerIndex) {
|
|
193
230
|
return _controllers.find((c) => c.playerIndex === playerIndex);
|
|
@@ -195,9 +232,6 @@ function createMockScreen(options = {}) {
|
|
|
195
232
|
getControllerCount() {
|
|
196
233
|
return _controllers.filter((c) => c.connected).length;
|
|
197
234
|
},
|
|
198
|
-
hasAnyConnectedControllers() {
|
|
199
|
-
return _controllers.some((c) => c.connected);
|
|
200
|
-
},
|
|
201
235
|
// === Cleanup ===
|
|
202
236
|
/**
|
|
203
237
|
* Note: destroy() clears recorded broadcast/event arrays. Call getBroadcasts() before destroy() if assertions are needed.
|
|
@@ -233,7 +267,7 @@ function createMockScreen(options = {}) {
|
|
|
233
267
|
simulateControllerDisconnect(playerIndex) {
|
|
234
268
|
const controller = _controllers.find((c) => c.playerIndex === playerIndex);
|
|
235
269
|
if (!controller) {
|
|
236
|
-
throw new
|
|
270
|
+
throw new SmoreSDKError("INVALID_PLAYER", `Controller ${playerIndex} not found`);
|
|
237
271
|
}
|
|
238
272
|
_controllers = _controllers.map(
|
|
239
273
|
(c) => c.playerIndex === playerIndex ? { ...c, connected: false } : c
|
|
@@ -246,7 +280,7 @@ function createMockScreen(options = {}) {
|
|
|
246
280
|
simulateControllerReconnect(playerIndex) {
|
|
247
281
|
const controller = _controllers.find((c) => c.playerIndex === playerIndex);
|
|
248
282
|
if (!controller) {
|
|
249
|
-
throw new
|
|
283
|
+
throw new SmoreSDKError("INVALID_PLAYER", `Controller ${playerIndex} not found`);
|
|
250
284
|
}
|
|
251
285
|
const reconnectedController = { ...controller, connected: true };
|
|
252
286
|
_controllers = _controllers.map(
|
|
@@ -257,16 +291,13 @@ function createMockScreen(options = {}) {
|
|
|
257
291
|
simulateCharacterUpdate(playerIndex, appearance) {
|
|
258
292
|
const controller = _controllers.find((c) => c.playerIndex === playerIndex);
|
|
259
293
|
if (!controller) {
|
|
260
|
-
throw new
|
|
294
|
+
throw new SmoreSDKError("INVALID_PLAYER", `Controller ${playerIndex} not found`);
|
|
261
295
|
}
|
|
262
296
|
_controllers = _controllers.map(
|
|
263
297
|
(c) => c.playerIndex === playerIndex ? { ...c, appearance } : c
|
|
264
298
|
);
|
|
265
299
|
_onCharacterUpdatedCallbacks.forEach((cb) => cb(playerIndex, appearance));
|
|
266
300
|
},
|
|
267
|
-
simulateRateLimited(event) {
|
|
268
|
-
_onRateLimitedCallbacks.forEach((cb) => cb(event));
|
|
269
|
-
},
|
|
270
301
|
simulateAllReady() {
|
|
271
302
|
_allReadyFired = true;
|
|
272
303
|
_onAllReadyCallbacks.forEach((cb) => cb());
|
|
@@ -274,6 +305,10 @@ function createMockScreen(options = {}) {
|
|
|
274
305
|
simulateError(error) {
|
|
275
306
|
_onErrorCallbacks.forEach((cb) => cb(error));
|
|
276
307
|
},
|
|
308
|
+
simulateConnectionChange(connected) {
|
|
309
|
+
_isConnected = connected;
|
|
310
|
+
_onConnectionChangeCallbacks.forEach((cb) => cb(connected));
|
|
311
|
+
},
|
|
277
312
|
getBroadcasts() {
|
|
278
313
|
return [...broadcasts];
|
|
279
314
|
},
|
|
@@ -286,6 +321,7 @@ function createMockScreen(options = {}) {
|
|
|
286
321
|
},
|
|
287
322
|
triggerReady() {
|
|
288
323
|
_isReady = true;
|
|
324
|
+
_isConnected = true;
|
|
289
325
|
_readyResolve();
|
|
290
326
|
}
|
|
291
327
|
};
|
|
@@ -297,10 +333,11 @@ function createMockScreen(options = {}) {
|
|
|
297
333
|
function createMockController(options = {}) {
|
|
298
334
|
const {
|
|
299
335
|
roomCode = "TEST",
|
|
300
|
-
|
|
336
|
+
myPlayerIndex = 0,
|
|
301
337
|
autoReady = true
|
|
302
338
|
} = options;
|
|
303
339
|
let _isReady = false;
|
|
340
|
+
let _isConnected = false;
|
|
304
341
|
let _isDestroyed = false;
|
|
305
342
|
let _controllers = options.controllers ?? [];
|
|
306
343
|
const listeners = /* @__PURE__ */ new Map();
|
|
@@ -310,18 +347,21 @@ function createMockController(options = {}) {
|
|
|
310
347
|
const _onControllerDisconnectCallbacks = /* @__PURE__ */ new Set();
|
|
311
348
|
const _onControllerReconnectCallbacks = /* @__PURE__ */ new Set();
|
|
312
349
|
const _onCharacterUpdatedCallbacks = /* @__PURE__ */ new Set();
|
|
313
|
-
const _onRateLimitedCallbacks = /* @__PURE__ */ new Set();
|
|
314
350
|
const _onErrorCallbacks = /* @__PURE__ */ new Set();
|
|
351
|
+
const _onGameOverCallbacks = /* @__PURE__ */ new Set();
|
|
352
|
+
const _onConnectionChangeCallbacks = /* @__PURE__ */ new Set();
|
|
315
353
|
let _allReadyFired = false;
|
|
316
354
|
let _readyResolve;
|
|
317
355
|
const _readyPromise = new Promise((resolve) => {
|
|
318
356
|
_readyResolve = resolve;
|
|
319
357
|
});
|
|
358
|
+
const _customStates = /* @__PURE__ */ new Map();
|
|
359
|
+
const _stateChangeListeners = /* @__PURE__ */ new Set();
|
|
320
360
|
const sentEvents = [];
|
|
321
361
|
const controller = {
|
|
322
362
|
// === Properties ===
|
|
323
|
-
get
|
|
324
|
-
return
|
|
363
|
+
get myPlayerIndex() {
|
|
364
|
+
return myPlayerIndex;
|
|
325
365
|
},
|
|
326
366
|
get roomCode() {
|
|
327
367
|
return roomCode;
|
|
@@ -332,6 +372,12 @@ function createMockController(options = {}) {
|
|
|
332
372
|
get isDestroyed() {
|
|
333
373
|
return _isDestroyed;
|
|
334
374
|
},
|
|
375
|
+
get isConnected() {
|
|
376
|
+
return _isConnected;
|
|
377
|
+
},
|
|
378
|
+
get protocolVersion() {
|
|
379
|
+
return 1;
|
|
380
|
+
},
|
|
335
381
|
get controllers() {
|
|
336
382
|
return [..._controllers];
|
|
337
383
|
},
|
|
@@ -378,48 +424,92 @@ function createMockController(options = {}) {
|
|
|
378
424
|
_onCharacterUpdatedCallbacks.delete(callback);
|
|
379
425
|
};
|
|
380
426
|
},
|
|
381
|
-
onRateLimited(callback) {
|
|
382
|
-
_onRateLimitedCallbacks.add(callback);
|
|
383
|
-
return () => {
|
|
384
|
-
_onRateLimitedCallbacks.delete(callback);
|
|
385
|
-
};
|
|
386
|
-
},
|
|
387
427
|
onError(callback) {
|
|
388
428
|
_onErrorCallbacks.add(callback);
|
|
389
429
|
return () => {
|
|
390
430
|
_onErrorCallbacks.delete(callback);
|
|
391
431
|
};
|
|
392
432
|
},
|
|
433
|
+
onConnectionChange(callback) {
|
|
434
|
+
_onConnectionChangeCallbacks.add(callback);
|
|
435
|
+
return () => {
|
|
436
|
+
_onConnectionChangeCallbacks.delete(callback);
|
|
437
|
+
};
|
|
438
|
+
},
|
|
439
|
+
onGameOver(callback) {
|
|
440
|
+
_onGameOverCallbacks.add(callback);
|
|
441
|
+
return () => {
|
|
442
|
+
_onGameOverCallbacks.delete(callback);
|
|
443
|
+
};
|
|
444
|
+
},
|
|
393
445
|
getControllerCount() {
|
|
394
446
|
return _controllers.filter((c) => c.connected).length;
|
|
395
447
|
},
|
|
448
|
+
getController(playerIndex) {
|
|
449
|
+
return _controllers.find((c) => c.playerIndex === playerIndex);
|
|
450
|
+
},
|
|
451
|
+
get me() {
|
|
452
|
+
return _controllers.find((c) => c.playerIndex === myPlayerIndex);
|
|
453
|
+
},
|
|
454
|
+
setState(state) {
|
|
455
|
+
const existing = _customStates.get(myPlayerIndex) ?? {};
|
|
456
|
+
const next = { ...existing, ...state };
|
|
457
|
+
_customStates.set(myPlayerIndex, next);
|
|
458
|
+
_stateChangeListeners.forEach((cb) => cb(myPlayerIndex, next));
|
|
459
|
+
},
|
|
460
|
+
getMyState() {
|
|
461
|
+
return _customStates.get(myPlayerIndex);
|
|
462
|
+
},
|
|
463
|
+
onCustomStateChange(listener) {
|
|
464
|
+
_stateChangeListeners.add(listener);
|
|
465
|
+
return () => {
|
|
466
|
+
_stateChangeListeners.delete(listener);
|
|
467
|
+
};
|
|
468
|
+
},
|
|
396
469
|
// === Communication Methods ===
|
|
397
470
|
send(event, data) {
|
|
398
471
|
if (_isDestroyed) {
|
|
399
|
-
throw new
|
|
400
|
-
}
|
|
401
|
-
validateEventName(event);
|
|
402
|
-
sentEvents.push({ event, data });
|
|
403
|
-
},
|
|
404
|
-
sendRaw(event, data) {
|
|
405
|
-
if (_isDestroyed) {
|
|
406
|
-
throw new Error("Cannot send: controller is destroyed");
|
|
472
|
+
throw new SmoreSDKError("DESTROYED", "Cannot call send() after destroy()");
|
|
407
473
|
}
|
|
408
474
|
validateEventName(event);
|
|
409
475
|
sentEvents.push({ event, data });
|
|
410
476
|
},
|
|
411
477
|
signalReady() {
|
|
412
478
|
if (_isDestroyed) {
|
|
413
|
-
throw new
|
|
479
|
+
throw new SmoreSDKError("DESTROYED", "Cannot call signalReady() after destroy()");
|
|
414
480
|
}
|
|
415
481
|
if (!_isReady) {
|
|
416
|
-
throw new
|
|
482
|
+
throw new SmoreSDKError("NOT_READY", "Cannot call signalReady() before controller is ready");
|
|
417
483
|
}
|
|
418
484
|
},
|
|
419
485
|
// === Event Subscription ===
|
|
420
486
|
on(event, handler) {
|
|
421
|
-
validateEventName(event);
|
|
422
487
|
const eventStr = event;
|
|
488
|
+
if (eventStr.startsWith("$")) {
|
|
489
|
+
switch (eventStr) {
|
|
490
|
+
case "$controller-join":
|
|
491
|
+
return controller.onControllerJoin(handler);
|
|
492
|
+
case "$controller-leave":
|
|
493
|
+
return controller.onControllerLeave(handler);
|
|
494
|
+
case "$controller-disconnect":
|
|
495
|
+
return controller.onControllerDisconnect(handler);
|
|
496
|
+
case "$controller-reconnect":
|
|
497
|
+
return controller.onControllerReconnect(handler);
|
|
498
|
+
case "$character-updated":
|
|
499
|
+
return controller.onCharacterUpdated(handler);
|
|
500
|
+
case "$all-ready":
|
|
501
|
+
return controller.onAllReady(handler);
|
|
502
|
+
case "$error":
|
|
503
|
+
return controller.onError(handler);
|
|
504
|
+
case "$game-over":
|
|
505
|
+
return controller.onGameOver(handler);
|
|
506
|
+
case "$state-recovery":
|
|
507
|
+
return controller.onCustomStateChange(handler);
|
|
508
|
+
case "$connection-change":
|
|
509
|
+
return controller.onConnectionChange(handler);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
validateEventName(event);
|
|
423
513
|
if (!listeners.has(eventStr)) {
|
|
424
514
|
listeners.set(eventStr, /* @__PURE__ */ new Set());
|
|
425
515
|
}
|
|
@@ -445,6 +535,13 @@ function createMockController(options = {}) {
|
|
|
445
535
|
listeners.get(eventStr)?.delete(handler);
|
|
446
536
|
}
|
|
447
537
|
},
|
|
538
|
+
removeAllListeners(event) {
|
|
539
|
+
if (event) {
|
|
540
|
+
listeners.delete(event);
|
|
541
|
+
} else {
|
|
542
|
+
listeners.clear();
|
|
543
|
+
}
|
|
544
|
+
},
|
|
448
545
|
// === Cleanup ===
|
|
449
546
|
destroy() {
|
|
450
547
|
_isDestroyed = true;
|
|
@@ -470,6 +567,7 @@ function createMockController(options = {}) {
|
|
|
470
567
|
},
|
|
471
568
|
triggerReady() {
|
|
472
569
|
_isReady = true;
|
|
570
|
+
_isConnected = true;
|
|
473
571
|
_readyResolve();
|
|
474
572
|
},
|
|
475
573
|
/**
|
|
@@ -510,22 +608,32 @@ function createMockController(options = {}) {
|
|
|
510
608
|
simulateCharacterUpdate(playerIndex, appearance) {
|
|
511
609
|
const ctrl = _controllers.find((c) => c.playerIndex === playerIndex);
|
|
512
610
|
if (!ctrl) {
|
|
513
|
-
throw new
|
|
611
|
+
throw new SmoreSDKError("INVALID_PLAYER", `Controller ${playerIndex} not found`);
|
|
514
612
|
}
|
|
515
613
|
_controllers = _controllers.map(
|
|
516
614
|
(c) => c.playerIndex === playerIndex ? { ...c, appearance } : c
|
|
517
615
|
);
|
|
518
616
|
_onCharacterUpdatedCallbacks.forEach((cb) => cb(playerIndex, appearance));
|
|
519
617
|
},
|
|
520
|
-
simulateRateLimited(event) {
|
|
521
|
-
_onRateLimitedCallbacks.forEach((cb) => cb(event));
|
|
522
|
-
},
|
|
523
618
|
simulateAllReady() {
|
|
524
619
|
_allReadyFired = true;
|
|
525
620
|
_onAllReadyCallbacks.forEach((cb) => cb());
|
|
526
621
|
},
|
|
527
622
|
simulateError(error) {
|
|
528
623
|
_onErrorCallbacks.forEach((cb) => cb(error));
|
|
624
|
+
},
|
|
625
|
+
simulateGameOver(results) {
|
|
626
|
+
_onGameOverCallbacks.forEach((cb) => cb(results));
|
|
627
|
+
},
|
|
628
|
+
simulateConnectionChange(connected) {
|
|
629
|
+
_isConnected = connected;
|
|
630
|
+
_onConnectionChangeCallbacks.forEach((cb) => cb(connected));
|
|
631
|
+
},
|
|
632
|
+
simulateStateChange(playerIndex, state) {
|
|
633
|
+
const existing = _customStates.get(playerIndex) ?? {};
|
|
634
|
+
const next = { ...existing, ...state };
|
|
635
|
+
_customStates.set(playerIndex, next);
|
|
636
|
+
_stateChangeListeners.forEach((cb) => cb(playerIndex, next));
|
|
529
637
|
}
|
|
530
638
|
};
|
|
531
639
|
if (autoReady) {
|