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