create-smore-game 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/package.json +1 -1
- package/templates.js +116 -59
package/package.json
CHANGED
package/templates.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// pnpm-workspace.yaml is no longer generated.
|
|
4
4
|
// npm workspaces are configured in root package.json instead.
|
|
5
5
|
|
|
6
|
-
const SDK_VERSION = '^2.
|
|
6
|
+
const SDK_VERSION = '^2.2.0';
|
|
7
7
|
|
|
8
8
|
export function rootPackageJson(name) {
|
|
9
9
|
return JSON.stringify(
|
|
@@ -119,7 +119,7 @@ function screenIndexHtml(title, isReact) {
|
|
|
119
119
|
|
|
120
120
|
// Screen: React + Phaser
|
|
121
121
|
// Test utilities: createMockScreen(), createMockController() can be imported in test files
|
|
122
|
-
// Example: import { createMockScreen } from '@smoregg/sdk';
|
|
122
|
+
// Example: import { createMockScreen } from '@smoregg/sdk/testing';
|
|
123
123
|
export function screenReactPhaser(gameId) {
|
|
124
124
|
return {
|
|
125
125
|
"package.json": JSON.stringify(
|
|
@@ -162,12 +162,14 @@ import { useEffect, useRef, useState } from 'react';
|
|
|
162
162
|
import Phaser from 'phaser';
|
|
163
163
|
import { GameScene } from './scenes/GameScene';
|
|
164
164
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
165
|
+
interface GameEvents {
|
|
166
|
+
'score-update': { score: number };
|
|
167
|
+
'personal-message': { text: string };
|
|
168
|
+
'tap': { timestamp: number };
|
|
169
|
+
}
|
|
168
170
|
|
|
169
171
|
// Testing: Use mock utilities for unit tests
|
|
170
|
-
// import { createMockScreen, createMockController } from '@smoregg/sdk';
|
|
172
|
+
// import { createMockScreen, createMockController } from '@smoregg/sdk/testing';
|
|
171
173
|
// const mockScreen = createMockScreen();
|
|
172
174
|
// mockScreen.simulateControllerJoin({ playerIndex: 0, name: 'Test' });
|
|
173
175
|
|
|
@@ -175,10 +177,8 @@ import { GameScene } from './scenes/GameScene';
|
|
|
175
177
|
// screen/controller onError callback handles initialization and runtime errors.
|
|
176
178
|
// Wrap critical game logic in try/catch for graceful error recovery.
|
|
177
179
|
|
|
178
|
-
//
|
|
179
|
-
// import type { GameMetadata } from '@smoregg/sdk';
|
|
180
|
+
// Game metadata is defined in game.json (see S'MORE platform docs)
|
|
180
181
|
// game.json fields: { id, title, description, minPlayers, maxPlayers, version }
|
|
181
|
-
// See docs for full GameMetadata schema.
|
|
182
182
|
|
|
183
183
|
export function App() {
|
|
184
184
|
const screenRef = useRef<Screen | null>(null);
|
|
@@ -189,7 +189,7 @@ export function App() {
|
|
|
189
189
|
useEffect(() => {
|
|
190
190
|
let mounted = true;
|
|
191
191
|
|
|
192
|
-
const screen = createScreen({ debug: true });
|
|
192
|
+
const screen = createScreen<GameEvents>({ debug: true });
|
|
193
193
|
|
|
194
194
|
screen.onControllerJoin((playerIndex, info) => {
|
|
195
195
|
console.log('Player joined:', playerIndex);
|
|
@@ -212,9 +212,9 @@ export function App() {
|
|
|
212
212
|
});
|
|
213
213
|
// screen.onControllerReconnect((playerIndex, info) => { console.log('Player reconnected:', playerIndex); });
|
|
214
214
|
// screen.onCharacterUpdated((playerIndex, appearance) => { console.log('Character updated:', playerIndex); });
|
|
215
|
-
//
|
|
215
|
+
// Rate limiting is delivered through onError() with code 'RATE_LIMITED'
|
|
216
216
|
// screen.onAllReady(() => { console.log('All participants ready'); });
|
|
217
|
-
// To control autoReady
|
|
217
|
+
// To control autoReady: createScreen({ autoReady: false }) or createController({ autoReady: false })
|
|
218
218
|
|
|
219
219
|
screen.onError((error) => {
|
|
220
220
|
console.error('SDK Error:', error.message);
|
|
@@ -310,7 +310,7 @@ export class GameScene extends Phaser.Scene {
|
|
|
310
310
|
|
|
311
311
|
// Screen: React only
|
|
312
312
|
// Test utilities: createMockScreen(), createMockController() can be imported in test files
|
|
313
|
-
// Example: import { createMockScreen } from '@smoregg/sdk';
|
|
313
|
+
// Example: import { createMockScreen } from '@smoregg/sdk/testing';
|
|
314
314
|
export function screenReact(gameId) {
|
|
315
315
|
return {
|
|
316
316
|
"package.json": JSON.stringify(
|
|
@@ -350,12 +350,14 @@ createRoot(document.getElementById('root')!).render(<App />);
|
|
|
350
350
|
import type { Screen, ControllerInfo, GameResults } from '@smoregg/sdk';
|
|
351
351
|
import { useEffect, useRef, useState } from 'react';
|
|
352
352
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
353
|
+
interface GameEvents {
|
|
354
|
+
'score-update': { score: number };
|
|
355
|
+
'personal-message': { text: string };
|
|
356
|
+
'tap': { timestamp: number };
|
|
357
|
+
}
|
|
356
358
|
|
|
357
359
|
// Testing: Use mock utilities for unit tests
|
|
358
|
-
// import { createMockScreen, createMockController } from '@smoregg/sdk';
|
|
360
|
+
// import { createMockScreen, createMockController } from '@smoregg/sdk/testing';
|
|
359
361
|
// const mockScreen = createMockScreen();
|
|
360
362
|
// mockScreen.simulateControllerJoin({ playerIndex: 0, name: 'Test' });
|
|
361
363
|
|
|
@@ -363,25 +365,20 @@ import { useEffect, useRef, useState } from 'react';
|
|
|
363
365
|
// screen/controller onError callback handles initialization and runtime errors.
|
|
364
366
|
// Wrap critical game logic in try/catch for graceful error recovery.
|
|
365
367
|
|
|
366
|
-
//
|
|
367
|
-
// import type { GameMetadata } from '@smoregg/sdk';
|
|
368
|
+
// Game metadata is defined in game.json (see S'MORE platform docs)
|
|
368
369
|
// game.json fields: { id, title, description, minPlayers, maxPlayers, version }
|
|
369
|
-
// See docs for full GameMetadata schema.
|
|
370
|
-
|
|
371
|
-
// Advanced: Validate custom event names before sending
|
|
372
|
-
// import { validateEventName } from '@smoregg/sdk';
|
|
373
|
-
// validateEventName('my-event'); // throws if contains ':'
|
|
374
370
|
|
|
375
371
|
export function App() {
|
|
376
372
|
const screenRef = useRef<Screen | null>(null);
|
|
377
373
|
const [roomCode, setRoomCode] = useState('');
|
|
378
374
|
const [controllers, setControllers] = useState<ControllerInfo[]>([]);
|
|
379
375
|
const [taps, setTaps] = useState<{ playerIndex: number; time: number }[]>([]);
|
|
376
|
+
const [customStates, setCustomStates] = useState<Record<number, Record<string, unknown>>>({});
|
|
380
377
|
|
|
381
378
|
useEffect(() => {
|
|
382
379
|
let mounted = true;
|
|
383
380
|
|
|
384
|
-
const screen = createScreen({ debug: true });
|
|
381
|
+
const screen = createScreen<GameEvents>({ debug: true });
|
|
385
382
|
|
|
386
383
|
screen.onControllerJoin((playerIndex, info) => {
|
|
387
384
|
console.log('Player joined:', playerIndex);
|
|
@@ -401,9 +398,9 @@ export function App() {
|
|
|
401
398
|
});
|
|
402
399
|
// screen.onControllerReconnect((playerIndex, info) => { console.log('Player reconnected:', playerIndex); });
|
|
403
400
|
// screen.onCharacterUpdated((playerIndex, appearance) => { console.log('Character updated:', playerIndex); });
|
|
404
|
-
//
|
|
401
|
+
// Rate limiting is delivered through onError() with code 'RATE_LIMITED'
|
|
405
402
|
// screen.onAllReady(() => { console.log('All participants ready'); });
|
|
406
|
-
// To control autoReady
|
|
403
|
+
// To control autoReady: createScreen({ autoReady: false }) or createController({ autoReady: false })
|
|
407
404
|
|
|
408
405
|
screen.onError((error) => {
|
|
409
406
|
console.error('SDK Error:', error.message);
|
|
@@ -416,11 +413,16 @@ export function App() {
|
|
|
416
413
|
setControllers([...screen.controllers]);
|
|
417
414
|
});
|
|
418
415
|
|
|
416
|
+
screen.onCustomStateChange((playerIndex, state) => {
|
|
417
|
+
if (!mounted) return;
|
|
418
|
+
setCustomStates((prev) => ({ ...prev, [playerIndex]: state }));
|
|
419
|
+
});
|
|
420
|
+
|
|
419
421
|
screenRef.current = screen;
|
|
420
422
|
|
|
421
423
|
// Use screen.on(event, handler) / screen.off(event, handler) for dynamic event listeners.
|
|
422
424
|
// destroy() automatically removes all listeners, so explicit off() cleanup is not needed.
|
|
423
|
-
screen.on('tap', (playerIndex) => {
|
|
425
|
+
screen.on('tap', (playerIndex, data) => {
|
|
424
426
|
if (!mounted) return;
|
|
425
427
|
setTaps((prev) => [...prev.slice(-9), { playerIndex, time: Date.now() }]);
|
|
426
428
|
});
|
|
@@ -448,11 +450,11 @@ export function App() {
|
|
|
448
450
|
controllers.forEach((_, idx) => {
|
|
449
451
|
scores[idx] = Math.floor(Math.random() * 100);
|
|
450
452
|
});
|
|
451
|
-
// GameResults fields: scores (
|
|
453
|
+
// GameResults fields: scores (optional), winner (optional), rankings (optional), custom (optional)
|
|
452
454
|
const results: GameResults = {
|
|
453
455
|
scores,
|
|
454
456
|
// winner: 0, // optional — playerIndex of winner
|
|
455
|
-
// reason: 'time-up', // optional
|
|
457
|
+
// custom: { reason: 'time-up' }, // optional -- custom game-specific data
|
|
456
458
|
};
|
|
457
459
|
screenRef.current?.gameOver(results);
|
|
458
460
|
};
|
|
@@ -479,7 +481,7 @@ export function App() {
|
|
|
479
481
|
|
|
480
482
|
// Screen: Vanilla JS
|
|
481
483
|
// Test utilities: createMockScreen(), createMockController() can be imported in test files
|
|
482
|
-
// Example: import { createMockScreen } from '@smoregg/sdk';
|
|
484
|
+
// Example: import { createMockScreen } from '@smoregg/sdk/testing';
|
|
483
485
|
export function screenVanilla(gameId) {
|
|
484
486
|
return {
|
|
485
487
|
"package.json": JSON.stringify(
|
|
@@ -530,14 +532,16 @@ export function screenVanilla(gameId) {
|
|
|
530
532
|
</html>
|
|
531
533
|
`,
|
|
532
534
|
"src/main.ts": `import { createScreen } from '@smoregg/sdk';
|
|
533
|
-
import type {
|
|
535
|
+
import type { GameResults } from '@smoregg/sdk';
|
|
534
536
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
537
|
+
interface GameEvents {
|
|
538
|
+
'score-update': { score: number };
|
|
539
|
+
'personal-message': { text: string };
|
|
540
|
+
'tap': { timestamp: number };
|
|
541
|
+
}
|
|
538
542
|
|
|
539
543
|
// Testing: Use mock utilities for unit tests
|
|
540
|
-
// import { createMockScreen, createMockController } from '@smoregg/sdk';
|
|
544
|
+
// import { createMockScreen, createMockController } from '@smoregg/sdk/testing';
|
|
541
545
|
// const mockScreen = createMockScreen();
|
|
542
546
|
// mockScreen.simulateControllerJoin({ playerIndex: 0, name: 'Test' });
|
|
543
547
|
|
|
@@ -545,16 +549,14 @@ import type { Screen, ControllerInfo, GameResults } from '@smoregg/sdk';
|
|
|
545
549
|
// screen/controller onError callback handles initialization and runtime errors.
|
|
546
550
|
// Wrap critical game logic in try/catch for graceful error recovery.
|
|
547
551
|
|
|
548
|
-
//
|
|
549
|
-
// import type { GameMetadata } from '@smoregg/sdk';
|
|
552
|
+
// Game metadata is defined in game.json (see S'MORE platform docs)
|
|
550
553
|
// game.json fields: { id, title, description, minPlayers, maxPlayers, version }
|
|
551
|
-
// See docs for full GameMetadata schema.
|
|
552
554
|
|
|
553
555
|
const statusEl = document.getElementById('status')!;
|
|
554
556
|
const roomCodeEl = document.getElementById('room-code')!;
|
|
555
557
|
const logEl = document.getElementById('log')!;
|
|
556
558
|
|
|
557
|
-
const screen = createScreen({ debug: true });
|
|
559
|
+
const screen = createScreen<GameEvents>({ debug: true });
|
|
558
560
|
|
|
559
561
|
screen.onControllerJoin((playerIndex) => {
|
|
560
562
|
console.log('Player joined:', playerIndex);
|
|
@@ -572,9 +574,9 @@ screen.onControllerDisconnect((playerIndex) => {
|
|
|
572
574
|
});
|
|
573
575
|
// screen.onControllerReconnect((playerIndex, info) => { console.log('Player reconnected:', playerIndex); });
|
|
574
576
|
// screen.onCharacterUpdated((playerIndex, appearance) => { console.log('Character updated:', playerIndex); });
|
|
575
|
-
//
|
|
577
|
+
// Rate limiting is delivered through onError() with code 'RATE_LIMITED'
|
|
576
578
|
// screen.onAllReady(() => { console.log('All participants ready'); });
|
|
577
|
-
// To control autoReady
|
|
579
|
+
// To control autoReady: createScreen({ autoReady: false }) or createController({ autoReady: false })
|
|
578
580
|
|
|
579
581
|
screen.onError((error) => {
|
|
580
582
|
console.error('SDK Error:', error.message);
|
|
@@ -588,7 +590,7 @@ screen.onAllReady(() => {
|
|
|
588
590
|
|
|
589
591
|
// Use screen.on(event, handler) / screen.off(event, handler) for dynamic event listeners.
|
|
590
592
|
// destroy() automatically removes all listeners, so explicit off() cleanup is not needed.
|
|
591
|
-
screen.on('tap', (playerIndex
|
|
593
|
+
screen.on('tap', (playerIndex, data) => {
|
|
592
594
|
const line = document.createElement('div');
|
|
593
595
|
line.textContent = \`Player \${playerIndex} tapped\`;
|
|
594
596
|
logEl.appendChild(line);
|
|
@@ -609,7 +611,7 @@ function updateStatus() {
|
|
|
609
611
|
// const results: GameResults = {
|
|
610
612
|
// scores: { 0: 50, 1: 75 },
|
|
611
613
|
// // winner: 0,
|
|
612
|
-
// // reason: 'time-up',
|
|
614
|
+
// // custom: { reason: 'time-up' },
|
|
613
615
|
// };
|
|
614
616
|
// screen.gameOver(results);
|
|
615
617
|
`,
|
|
@@ -722,38 +724,46 @@ createRoot(document.getElementById('root')!).render(<App />);
|
|
|
722
724
|
import type { Controller, ControllerInfo } from '@smoregg/sdk';
|
|
723
725
|
import { useEffect, useRef, useState } from 'react';
|
|
724
726
|
|
|
727
|
+
interface GameEvents {
|
|
728
|
+
'score-update': { score: number };
|
|
729
|
+
'personal-message': { text: string };
|
|
730
|
+
'tap': { timestamp: number };
|
|
731
|
+
}
|
|
732
|
+
|
|
725
733
|
export function App() {
|
|
726
734
|
const controllerRef = useRef<Controller | null>(null);
|
|
727
735
|
const [myIndex, setMyIndex] = useState(-1);
|
|
736
|
+
const [me, setMe] = useState<ControllerInfo | null>(null);
|
|
728
737
|
const [count, setCount] = useState(0);
|
|
729
738
|
const [isReady, setIsReady] = useState(false);
|
|
730
739
|
|
|
731
740
|
useEffect(() => {
|
|
732
741
|
let mounted = true;
|
|
733
742
|
|
|
734
|
-
const controller = createController({ debug: true });
|
|
743
|
+
const controller = createController<GameEvents>({ debug: true });
|
|
735
744
|
|
|
736
745
|
// Lifecycle callbacks (uncomment to use):
|
|
737
746
|
// controller.onControllerJoin((playerIndex, info) => { console.log('Player joined:', playerIndex); });
|
|
738
747
|
// controller.onControllerLeave((playerIndex) => { console.log('Player left:', playerIndex); });
|
|
739
748
|
// controller.onError((error) => { console.error('SDK Error:', error.message); });
|
|
740
749
|
// controller.onAllReady(() => { console.log('All participants ready'); });
|
|
741
|
-
// To control autoReady
|
|
750
|
+
// To control autoReady: createScreen({ autoReady: false }) or createController({ autoReady: false })
|
|
742
751
|
|
|
743
752
|
controller.onAllReady(() => {
|
|
744
753
|
if (!mounted) return;
|
|
745
|
-
setMyIndex(controller.
|
|
754
|
+
setMyIndex(controller.myPlayerIndex);
|
|
755
|
+
setMe(controller.me);
|
|
746
756
|
setIsReady(true);
|
|
747
757
|
});
|
|
748
758
|
|
|
749
759
|
controllerRef.current = controller;
|
|
750
760
|
|
|
751
|
-
controller.on('score-update', (data
|
|
761
|
+
controller.on('score-update', (data) => {
|
|
752
762
|
if (!mounted) return;
|
|
753
763
|
setCount(data.score);
|
|
754
764
|
});
|
|
755
765
|
|
|
756
|
-
controller.on('personal-message', (data
|
|
766
|
+
controller.on('personal-message', (data) => {
|
|
757
767
|
console.log('Received message:', data.text);
|
|
758
768
|
});
|
|
759
769
|
|
|
@@ -777,7 +787,7 @@ export function App() {
|
|
|
777
787
|
touchAction: 'manipulation', userSelect: 'none',
|
|
778
788
|
}}>
|
|
779
789
|
{isReady && (
|
|
780
|
-
<div style={{ fontSize: '16px', opacity: 0.6 }}>Player {myIndex}</div>
|
|
790
|
+
<div style={{ fontSize: '16px', opacity: 0.6 }}>{me?.name ?? \`Player \${myIndex}\`}</div>
|
|
781
791
|
)}
|
|
782
792
|
<div style={{ fontSize: '48px', fontWeight: 'bold' }}>{count}</div>
|
|
783
793
|
<button
|
|
@@ -872,7 +882,12 @@ export default defineConfig({
|
|
|
872
882
|
</html>
|
|
873
883
|
`,
|
|
874
884
|
"src/main.ts": `import { createController } from '@smoregg/sdk';
|
|
875
|
-
|
|
885
|
+
|
|
886
|
+
interface GameEvents {
|
|
887
|
+
'score-update': { score: number };
|
|
888
|
+
'personal-message': { text: string };
|
|
889
|
+
'tap': { timestamp: number };
|
|
890
|
+
}
|
|
876
891
|
|
|
877
892
|
let count = 0;
|
|
878
893
|
|
|
@@ -880,25 +895,25 @@ const playerInfoEl = document.getElementById('player-info')!;
|
|
|
880
895
|
const countEl = document.getElementById('count')!;
|
|
881
896
|
const tapBtn = document.getElementById('tap-btn')!;
|
|
882
897
|
|
|
883
|
-
const controller = createController({ debug: true });
|
|
898
|
+
const controller = createController<GameEvents>({ debug: true });
|
|
884
899
|
|
|
885
900
|
// Lifecycle callbacks (uncomment to use):
|
|
886
901
|
// controller.onControllerJoin((playerIndex, info) => { console.log('Player joined:', playerIndex); });
|
|
887
902
|
// controller.onControllerLeave((playerIndex) => { console.log('Player left:', playerIndex); });
|
|
888
903
|
// controller.onError((error) => { console.error('SDK Error:', error.message); });
|
|
889
904
|
// controller.onAllReady(() => { console.log('All participants ready'); });
|
|
890
|
-
// To control autoReady
|
|
905
|
+
// To control autoReady: createScreen({ autoReady: false }) or createController({ autoReady: false })
|
|
891
906
|
|
|
892
907
|
controller.onAllReady(() => {
|
|
893
|
-
playerInfoEl.textContent = \`Player \${controller.
|
|
908
|
+
playerInfoEl.textContent = controller.me?.name ?? \`Player \${controller.myPlayerIndex}\`;
|
|
894
909
|
});
|
|
895
910
|
|
|
896
|
-
controller.on('score-update', (data
|
|
911
|
+
controller.on('score-update', (data) => {
|
|
897
912
|
count = data.score;
|
|
898
913
|
countEl.textContent = String(count);
|
|
899
914
|
});
|
|
900
915
|
|
|
901
|
-
controller.on('personal-message', (data
|
|
916
|
+
controller.on('personal-message', (data) => {
|
|
902
917
|
console.log('Received message:', data.text);
|
|
903
918
|
});
|
|
904
919
|
|
|
@@ -989,6 +1004,7 @@ const room = {
|
|
|
989
1004
|
gameId: '',
|
|
990
1005
|
status: 'waiting',
|
|
991
1006
|
readyIds: new Set(),
|
|
1007
|
+
customStates: new Map(), // playerIndex -> state object
|
|
992
1008
|
};
|
|
993
1009
|
|
|
994
1010
|
function toPlayerDTO(p) {
|
|
@@ -1135,6 +1151,20 @@ async function main() {
|
|
|
1135
1151
|
io.to(room.code).emit('smore:game-over', data);
|
|
1136
1152
|
});
|
|
1137
1153
|
|
|
1154
|
+
socket.on('smore:set-custom-state', (data) => {
|
|
1155
|
+
if (socket.role !== 'player') return;
|
|
1156
|
+
const prev = room.customStates.get(socket.playerIndex) || {};
|
|
1157
|
+
const next = Object.assign({}, prev, data && typeof data === 'object' ? data : {});
|
|
1158
|
+
room.customStates.set(socket.playerIndex, next);
|
|
1159
|
+
io.to(room.code).emit('smore:custom-state-changed', { playerIndex: socket.playerIndex, state: next });
|
|
1160
|
+
});
|
|
1161
|
+
|
|
1162
|
+
socket.on('smore:get-custom-states', () => {
|
|
1163
|
+
const states = {};
|
|
1164
|
+
room.customStates.forEach((state, playerIndex) => { states[playerIndex] = state; });
|
|
1165
|
+
socket.emit('smore:custom-states', { states });
|
|
1166
|
+
});
|
|
1167
|
+
|
|
1138
1168
|
socket.on('smore:return-to-selection', () => {
|
|
1139
1169
|
room.status = 'waiting';
|
|
1140
1170
|
room.gameId = '';
|
|
@@ -1156,6 +1186,7 @@ async function main() {
|
|
|
1156
1186
|
room.gameId = '';
|
|
1157
1187
|
room.status = 'waiting';
|
|
1158
1188
|
room.readyIds = new Set();
|
|
1189
|
+
room.customStates = new Map();
|
|
1159
1190
|
console.log(' [reset] Room reset by host');
|
|
1160
1191
|
if (typeof callback === 'function') callback({ success: true });
|
|
1161
1192
|
});
|
|
@@ -1529,7 +1560,8 @@ export function devHarness(gameId) {
|
|
|
1529
1560
|
// Forward specific smore: system events to screen iframe
|
|
1530
1561
|
var screenSysEvents = [
|
|
1531
1562
|
'smore:player-joined', 'smore:player-left', 'smore:player-disconnected', 'smore:player-reconnected',
|
|
1532
|
-
'smore:player-character-updated', 'smore:rate-limited', 'smore:game-over', 'smore:all-ready'
|
|
1563
|
+
'smore:player-character-updated', 'smore:rate-limited', 'smore:game-over', 'smore:all-ready',
|
|
1564
|
+
'smore:self-disconnected', 'smore:self-reconnected', 'smore:custom-state-changed', 'smore:custom-states'
|
|
1533
1565
|
];
|
|
1534
1566
|
screenSysEvents.forEach(function(sysEvent) {
|
|
1535
1567
|
screenSocket.on(sysEvent, function(data) {
|
|
@@ -1610,7 +1642,8 @@ export function devHarness(gameId) {
|
|
|
1610
1642
|
var ctrlSysEvents = [
|
|
1611
1643
|
'smore:game-over',
|
|
1612
1644
|
'smore:player-joined', 'smore:player-left', 'smore:player-disconnected', 'smore:player-reconnected',
|
|
1613
|
-
'smore:player-character-updated', 'smore:rate-limited', 'smore:all-ready'
|
|
1645
|
+
'smore:player-character-updated', 'smore:rate-limited', 'smore:all-ready',
|
|
1646
|
+
'smore:self-disconnected', 'smore:self-reconnected', 'smore:custom-state-changed', 'smore:custom-states'
|
|
1614
1647
|
];
|
|
1615
1648
|
ctrlSysEvents.forEach(function(sysEvent) {
|
|
1616
1649
|
controllerSocket.on(sysEvent, function(data) {
|
|
@@ -1647,6 +1680,7 @@ export function devHarness(gameId) {
|
|
|
1647
1680
|
side: 'host',
|
|
1648
1681
|
roomCode: roomCode,
|
|
1649
1682
|
players: getPlayerList(),
|
|
1683
|
+
protocolVersion: 1,
|
|
1650
1684
|
},
|
|
1651
1685
|
}, '*');
|
|
1652
1686
|
return;
|
|
@@ -1700,6 +1734,7 @@ export function devHarness(gameId) {
|
|
|
1700
1734
|
roomCode: roomCode,
|
|
1701
1735
|
players: getPlayerList(),
|
|
1702
1736
|
myIndex: player.playerIndex,
|
|
1737
|
+
protocolVersion: 1,
|
|
1703
1738
|
},
|
|
1704
1739
|
}, '*');
|
|
1705
1740
|
return;
|
|
@@ -1724,6 +1759,16 @@ export function devHarness(gameId) {
|
|
|
1724
1759
|
return;
|
|
1725
1760
|
}
|
|
1726
1761
|
|
|
1762
|
+
// Relay custom state events to server
|
|
1763
|
+
if (event === 'smore:set-custom-state') {
|
|
1764
|
+
player.socket.emit('smore:set-custom-state', data || {});
|
|
1765
|
+
return;
|
|
1766
|
+
}
|
|
1767
|
+
if (event === 'smore:get-custom-states') {
|
|
1768
|
+
player.socket.emit('smore:get-custom-states');
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1727
1772
|
// Block smore:* events
|
|
1728
1773
|
if (event.startsWith('smore:')) return;
|
|
1729
1774
|
|
|
@@ -1936,7 +1981,8 @@ export function devControllerPage(gameId) {
|
|
|
1936
1981
|
var sysEvents = [
|
|
1937
1982
|
'smore:game-over',
|
|
1938
1983
|
'smore:player-joined', 'smore:player-left', 'smore:player-disconnected', 'smore:player-reconnected',
|
|
1939
|
-
'smore:player-character-updated', 'smore:rate-limited', 'smore:all-ready'
|
|
1984
|
+
'smore:player-character-updated', 'smore:rate-limited', 'smore:all-ready',
|
|
1985
|
+
'smore:self-disconnected', 'smore:self-reconnected', 'smore:custom-state-changed', 'smore:custom-states'
|
|
1940
1986
|
];
|
|
1941
1987
|
sysEvents.forEach(function(sysEvent) {
|
|
1942
1988
|
socket.on(sysEvent, function(data) {
|
|
@@ -1982,6 +2028,7 @@ export function devControllerPage(gameId) {
|
|
|
1982
2028
|
roomCode: roomCode,
|
|
1983
2029
|
players: players,
|
|
1984
2030
|
myIndex: playerIndex,
|
|
2031
|
+
protocolVersion: 1,
|
|
1985
2032
|
},
|
|
1986
2033
|
}, '*');
|
|
1987
2034
|
}
|
|
@@ -1997,6 +2044,16 @@ export function devControllerPage(gameId) {
|
|
|
1997
2044
|
return;
|
|
1998
2045
|
}
|
|
1999
2046
|
|
|
2047
|
+
// Relay custom state events to server
|
|
2048
|
+
if (event === 'smore:set-custom-state') {
|
|
2049
|
+
socket.emit('smore:set-custom-state', data || {});
|
|
2050
|
+
return;
|
|
2051
|
+
}
|
|
2052
|
+
if (event === 'smore:get-custom-states') {
|
|
2053
|
+
socket.emit('smore:get-custom-states');
|
|
2054
|
+
return;
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2000
2057
|
// Block smore:* events
|
|
2001
2058
|
if (event.startsWith('smore:')) return;
|
|
2002
2059
|
|