create-smore-game 1.3.0 → 2.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 (2) hide show
  1. package/package.json +1 -1
  2. package/templates.js +162 -193
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-smore-game",
3
- "version": "1.3.0",
3
+ "version": "2.0.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "create-smore-game": "./index.js"
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 = '^1.3.0';
6
+ const SDK_VERSION = '^2.0.0';
7
7
 
8
8
  export function rootPackageJson(name) {
9
9
  return JSON.stringify(
@@ -164,7 +164,7 @@ import { GameScene } from './scenes/GameScene';
164
164
 
165
165
  // Type-safe events example:
166
166
  // type MyEvents = { 'player-move': { x: number; y: number } };
167
- // const screen = await createScreen<MyEvents>({ ... });
167
+ // const screen = createScreen<MyEvents>({ debug: true });
168
168
 
169
169
  // Testing: Use mock utilities for unit tests
170
170
  // import { createMockScreen, createMockController } from '@smoregg/sdk';
@@ -189,66 +189,56 @@ export function App() {
189
189
  useEffect(() => {
190
190
  let mounted = true;
191
191
 
192
- const init = async () => {
193
- // Alternative: register listeners in config (instead of screen.on())
194
- // const screen = await createScreen({
195
- // listeners: {
196
- // 'tap': (playerIndex, data) => console.log('Player', playerIndex, 'tapped:', data),
197
- // },
198
- // });
199
- // Note: listeners in config are set during initialization and cannot be removed.
200
- // Use screen.on(event, handler) / screen.off(event, handler) for dynamic listeners.
201
-
202
- const screen = await createScreen({
203
- debug: true,
204
- onControllerJoin: (playerIndex, info) => {
205
- console.log('Player joined:', playerIndex);
206
- // Access player character data:
207
- // const { nickname, appearance } = info;
208
- // console.log(nickname, appearance?.style, appearance?.seed);
209
- setControllers([...screen.controllers]);
210
- },
211
- onControllerLeave: (playerIndex) => {
212
- console.log('Player left:', playerIndex);
213
- setControllers([...screen.controllers]);
214
- },
215
- // Advanced callbacks (uncomment to use):
216
- onControllerDisconnect: (playerIndex) => {
217
- console.log(\`Player \${playerIndex} disconnected\`);
218
- },
219
- // onControllerReconnect: (playerIndex: number, info: ControllerInfo) => void — called when a disconnected player reconnects
220
- // onCharacterUpdated: (playerIndex: number, appearance: CharacterAppearance | null) => void — called when a player updates their character appearance
221
- // onRateLimited: (event: string) => void — called when client is rate-limited by server
222
- // onReady: () => void — called when all participants are ready. Use for countdown/game start.
223
- // To control autoReady, use: import { configure } from '@smoregg/sdk'; configure({ autoReady: false });
224
- onError: (error) => {
225
- console.error('SDK Error:', error.message);
226
- // Show user-friendly error UI
227
- },
228
- });
229
- if (!mounted) {
230
- screen.destroy();
231
- return;
232
- }
192
+ const screen = createScreen({ debug: true });
233
193
 
234
- screenRef.current = screen;
235
- setRoomCode(screen.roomCode);
194
+ screen.onControllerJoin((playerIndex, info) => {
195
+ console.log('Player joined:', playerIndex);
196
+ // Access player character data:
197
+ // const { nickname, appearance } = info;
198
+ // console.log(nickname, appearance?.style, appearance?.seed);
199
+ if (!mounted) return;
236
200
  setControllers([...screen.controllers]);
201
+ });
237
202
 
238
- // Note: listeners in config are set during initialization (onControllerJoin, etc. above).
239
- // Use screen.on(event, handler) / screen.off(event, handler) for dynamic event listeners.
240
- // Cleanup example (useful in React useEffect):
241
- // const handler = (playerIndex, data) => { ... };
242
- // screen.on('my-event', handler);
243
- // Later: screen.off('my-event', handler);
244
- screen.on('tap', (playerIndex, data) => {
245
- console.log('Player', playerIndex, 'tapped:', data);
246
- // Forward input to Phaser scene
247
- gameRef.current?.events.emit('player-tap', { playerIndex, ...data });
248
- });
249
- };
203
+ screen.onControllerLeave((playerIndex) => {
204
+ console.log('Player left:', playerIndex);
205
+ if (!mounted) return;
206
+ setControllers([...screen.controllers]);
207
+ });
208
+
209
+ // Advanced callbacks (uncomment to use):
210
+ screen.onControllerDisconnect((playerIndex) => {
211
+ console.log(\`Player \${playerIndex} disconnected\`);
212
+ });
213
+ // screen.onControllerReconnect((playerIndex, info) => { console.log('Player reconnected:', playerIndex); });
214
+ // screen.onCharacterUpdated((playerIndex, appearance) => { console.log('Character updated:', playerIndex); });
215
+ // screen.onRateLimited((event) => { console.warn('Rate limited:', event); });
216
+ // screen.onAllReady(() => { console.log('All participants ready'); });
217
+ // To control autoReady, use: import { configure } from '@smoregg/sdk'; configure({ autoReady: false });
218
+
219
+ screen.onError((error) => {
220
+ console.error('SDK Error:', error.message);
221
+ // Show user-friendly error UI
222
+ });
250
223
 
251
- init();
224
+ screen.onAllReady(() => {
225
+ if (!mounted) return;
226
+ setRoomCode(screen.roomCode);
227
+ setControllers([...screen.controllers]);
228
+ });
229
+
230
+ screenRef.current = screen;
231
+
232
+ // Use screen.on(event, handler) / screen.off(event, handler) for dynamic event listeners.
233
+ // Cleanup example (useful in React useEffect):
234
+ // const handler = (playerIndex, data) => { ... };
235
+ // screen.on('my-event', handler);
236
+ // Later: screen.off('my-event', handler);
237
+ screen.on('tap', (playerIndex, data) => {
238
+ console.log('Player', playerIndex, 'tapped:', data);
239
+ // Forward input to Phaser scene
240
+ gameRef.current?.events.emit('player-tap', { playerIndex, ...data });
241
+ });
252
242
 
253
243
  return () => {
254
244
  mounted = false;
@@ -362,7 +352,7 @@ import { useEffect, useRef, useState } from 'react';
362
352
 
363
353
  // Type-safe events example:
364
354
  // type MyEvents = { 'player-move': { x: number; y: number } };
365
- // const screen = await createScreen<MyEvents>({ ... });
355
+ // const screen = createScreen<MyEvents>({ debug: true });
366
356
 
367
357
  // Testing: Use mock utilities for unit tests
368
358
  // import { createMockScreen, createMockController } from '@smoregg/sdk';
@@ -391,49 +381,49 @@ export function App() {
391
381
  useEffect(() => {
392
382
  let mounted = true;
393
383
 
394
- const init = async () => {
395
- const screen = await createScreen({
396
- debug: true,
397
- onControllerJoin: (playerIndex, info) => {
398
- console.log('Player joined:', playerIndex);
399
- setControllers([...screen.controllers]);
400
- },
401
- onControllerLeave: (playerIndex) => {
402
- console.log('Player left:', playerIndex);
403
- setControllers([...screen.controllers]);
404
- },
405
- // Advanced callbacks (uncomment to use):
406
- onControllerDisconnect: (playerIndex) => {
407
- console.log(\`Player \${playerIndex} disconnected\`);
408
- },
409
- // onControllerReconnect: (playerIndex: number, info: ControllerInfo) => void — called when a disconnected player reconnects
410
- // onCharacterUpdated: (playerIndex: number, appearance: CharacterAppearance | null) => void — called when a player updates their character appearance
411
- // onRateLimited: (event: string) => void — called when client is rate-limited by server
412
- // onReady: () => void — called when all participants are ready. Use for countdown/game start.
413
- // To control autoReady, use: import { configure } from '@smoregg/sdk'; configure({ autoReady: false });
414
- onError: (error) => {
415
- console.error('SDK Error:', error.message);
416
- // Show user-friendly error UI
417
- },
418
- });
419
- if (!mounted) {
420
- screen.destroy();
421
- return;
422
- }
384
+ const screen = createScreen({ debug: true });
423
385
 
424
- screenRef.current = screen;
386
+ screen.onControllerJoin((playerIndex, info) => {
387
+ console.log('Player joined:', playerIndex);
388
+ if (!mounted) return;
389
+ setControllers([...screen.controllers]);
390
+ });
391
+
392
+ screen.onControllerLeave((playerIndex) => {
393
+ console.log('Player left:', playerIndex);
394
+ if (!mounted) return;
395
+ setControllers([...screen.controllers]);
396
+ });
397
+
398
+ // Advanced callbacks (uncomment to use):
399
+ screen.onControllerDisconnect((playerIndex) => {
400
+ console.log(\`Player \${playerIndex} disconnected\`);
401
+ });
402
+ // screen.onControllerReconnect((playerIndex, info) => { console.log('Player reconnected:', playerIndex); });
403
+ // screen.onCharacterUpdated((playerIndex, appearance) => { console.log('Character updated:', playerIndex); });
404
+ // screen.onRateLimited((event) => { console.warn('Rate limited:', event); });
405
+ // screen.onAllReady(() => { console.log('All participants ready'); });
406
+ // To control autoReady, use: import { configure } from '@smoregg/sdk'; configure({ autoReady: false });
407
+
408
+ screen.onError((error) => {
409
+ console.error('SDK Error:', error.message);
410
+ // Show user-friendly error UI
411
+ });
412
+
413
+ screen.onAllReady(() => {
414
+ if (!mounted) return;
425
415
  setRoomCode(screen.roomCode);
426
416
  setControllers([...screen.controllers]);
417
+ });
427
418
 
428
- // Note: listeners in config are set during initialization (onControllerJoin, etc. above).
429
- // Use screen.on(event, handler) / screen.off(event, handler) for dynamic event listeners.
430
- // destroy() automatically removes all listeners, so explicit off() cleanup is not needed.
431
- screen.on('tap', (playerIndex) => {
432
- setTaps((prev) => [...prev.slice(-9), { playerIndex, time: Date.now() }]);
433
- });
434
- };
419
+ screenRef.current = screen;
435
420
 
436
- init();
421
+ // Use screen.on(event, handler) / screen.off(event, handler) for dynamic event listeners.
422
+ // destroy() automatically removes all listeners, so explicit off() cleanup is not needed.
423
+ screen.on('tap', (playerIndex) => {
424
+ if (!mounted) return;
425
+ setTaps((prev) => [...prev.slice(-9), { playerIndex, time: Date.now() }]);
426
+ });
437
427
 
438
428
  return () => {
439
429
  mounted = false;
@@ -544,7 +534,7 @@ import type { Screen, ControllerInfo, GameResults } from '@smoregg/sdk';
544
534
 
545
535
  // Type-safe events example:
546
536
  // type MyEvents = { 'player-move': { x: number; y: number } };
547
- // const screen = await createScreen<MyEvents>({ ... });
537
+ // const screen = createScreen<MyEvents>({ debug: true });
548
538
 
549
539
  // Testing: Use mock utilities for unit tests
550
540
  // import { createMockScreen, createMockController } from '@smoregg/sdk';
@@ -564,58 +554,55 @@ const statusEl = document.getElementById('status')!;
564
554
  const roomCodeEl = document.getElementById('room-code')!;
565
555
  const logEl = document.getElementById('log')!;
566
556
 
567
- let screen: Screen;
557
+ const screen = createScreen({ debug: true });
568
558
 
569
- async function init() {
570
- screen = await createScreen({
571
- debug: true,
572
- onControllerJoin: (playerIndex) => {
573
- console.log('Player joined:', playerIndex);
574
- updateStatus();
575
- },
576
- onControllerLeave: (playerIndex) => {
577
- console.log('Player left:', playerIndex);
578
- updateStatus();
579
- },
580
- // Advanced callbacks (uncomment to use):
581
- onControllerDisconnect: (playerIndex) => {
582
- console.log(\`Player \${playerIndex} disconnected\`);
583
- },
584
- // onControllerReconnect: (playerIndex, info) => { console.log('Player reconnected:', playerIndex); },
585
- // onCharacterUpdated: (playerIndex, appearance) => { console.log('Character updated:', playerIndex); },
586
- // onRateLimited: (event: string) => { console.warn('Rate limited:', event); },
587
- // onReady: () => void called when all participants are ready. Use for countdown/game start.
588
- // To control autoReady, use: import { configure } from '@smoregg/sdk'; configure({ autoReady: false });
589
- onError: (error) => {
590
- console.error('SDK Error:', error.message);
591
- // Show user-friendly error UI
592
- },
593
- });
559
+ screen.onControllerJoin((playerIndex) => {
560
+ console.log('Player joined:', playerIndex);
561
+ updateStatus();
562
+ });
563
+
564
+ screen.onControllerLeave((playerIndex) => {
565
+ console.log('Player left:', playerIndex);
566
+ updateStatus();
567
+ });
568
+
569
+ // Advanced callbacks (uncomment to use):
570
+ screen.onControllerDisconnect((playerIndex) => {
571
+ console.log(\`Player \${playerIndex} disconnected\`);
572
+ });
573
+ // screen.onControllerReconnect((playerIndex, info) => { console.log('Player reconnected:', playerIndex); });
574
+ // screen.onCharacterUpdated((playerIndex, appearance) => { console.log('Character updated:', playerIndex); });
575
+ // screen.onRateLimited((event) => { console.warn('Rate limited:', event); });
576
+ // screen.onAllReady(() => { console.log('All participants ready'); });
577
+ // To control autoReady, use: import { configure } from '@smoregg/sdk'; configure({ autoReady: false });
578
+
579
+ screen.onError((error) => {
580
+ console.error('SDK Error:', error.message);
581
+ // Show user-friendly error UI
582
+ });
594
583
 
584
+ screen.onAllReady(() => {
595
585
  roomCodeEl.textContent = \`Room Code: \${screen.roomCode}\`;
596
586
  updateStatus();
587
+ });
597
588
 
598
- // Note: listeners in config are set during initialization (onControllerJoin, etc. above).
599
- // Use screen.on(event, handler) / screen.off(event, handler) for dynamic event listeners.
600
- // destroy() automatically removes all listeners, so explicit off() cleanup is not needed.
601
- screen.on('tap', (playerIndex: number, data: unknown) => {
602
- const line = document.createElement('div');
603
- line.textContent = \`Player \${playerIndex} tapped\`;
604
- logEl.appendChild(line);
605
- // Keep last 10 entries
606
- while (logEl.children.length > 10) {
607
- logEl.removeChild(logEl.firstChild!);
608
- }
609
- });
610
- }
589
+ // Use screen.on(event, handler) / screen.off(event, handler) for dynamic event listeners.
590
+ // destroy() automatically removes all listeners, so explicit off() cleanup is not needed.
591
+ screen.on('tap', (playerIndex: number, data: unknown) => {
592
+ const line = document.createElement('div');
593
+ line.textContent = \`Player \${playerIndex} tapped\`;
594
+ logEl.appendChild(line);
595
+ // Keep last 10 entries
596
+ while (logEl.children.length > 10) {
597
+ logEl.removeChild(logEl.firstChild!);
598
+ }
599
+ });
611
600
 
612
601
  function updateStatus() {
613
602
  const count = screen.controllers.length;
614
603
  statusEl.textContent = count > 0 ? \`\${count} player(s) connected\` : 'Waiting for players...';
615
604
  }
616
605
 
617
- init();
618
-
619
606
  // Example functions (can be called from console for testing):
620
607
  // screen.broadcast('score-update', { score: 100 });
621
608
  // screen.sendToController(0, 'message', { text: 'Hello!' });
@@ -735,11 +722,6 @@ createRoot(document.getElementById('root')!).render(<App />);
735
722
  import type { Controller, ControllerInfo } from '@smoregg/sdk';
736
723
  import { useEffect, useRef, useState } from 'react';
737
724
 
738
- // You can also register listeners in config:
739
- // const controller = await createController({
740
- // listeners: { 'game-state': (data) => { /* handle state */ } },
741
- // });
742
-
743
725
  export function App() {
744
726
  const controllerRef = useRef<Controller | null>(null);
745
727
  const [myIndex, setMyIndex] = useState(-1);
@@ -749,35 +731,31 @@ export function App() {
749
731
  useEffect(() => {
750
732
  let mounted = true;
751
733
 
752
- const init = async () => {
753
- const controller = await createController({
754
- debug: true,
755
- // Lifecycle callbacks (uncomment to use):
756
- // onControllerJoin: (playerIndex: number, info: ControllerInfo) => void called when any player joins
757
- // onControllerLeave: (playerIndex: number) => void called when any player leaves
758
- // onError: (error: SmoreError) => void called on SDK errors
759
- // onReady: () => void called when all participants are ready
760
- // To control autoReady, use: import { configure } from '@smoregg/sdk'; configure({ autoReady: false });
761
- });
762
- if (!mounted) {
763
- controller.destroy();
764
- return;
765
- }
734
+ const controller = createController({ debug: true });
735
+
736
+ // Lifecycle callbacks (uncomment to use):
737
+ // controller.onControllerJoin((playerIndex, info) => { console.log('Player joined:', playerIndex); });
738
+ // controller.onControllerLeave((playerIndex) => { console.log('Player left:', playerIndex); });
739
+ // controller.onError((error) => { console.error('SDK Error:', error.message); });
740
+ // controller.onAllReady(() => { console.log('All participants ready'); });
741
+ // To control autoReady, use: import { configure } from '@smoregg/sdk'; configure({ autoReady: false });
766
742
 
767
- controllerRef.current = controller;
743
+ controller.onAllReady(() => {
744
+ if (!mounted) return;
768
745
  setMyIndex(controller.myIndex);
769
746
  setIsReady(true);
747
+ });
770
748
 
771
- controller.on('score-update', (data: { score: number }) => {
772
- setCount(data.score);
773
- });
749
+ controllerRef.current = controller;
774
750
 
775
- controller.on('personal-message', (data: { text: string }) => {
776
- console.log('Received message:', data.text);
777
- });
778
- };
751
+ controller.on('score-update', (data: { score: number }) => {
752
+ if (!mounted) return;
753
+ setCount(data.score);
754
+ });
779
755
 
780
- init();
756
+ controller.on('personal-message', (data: { text: string }) => {
757
+ console.log('Received message:', data.text);
758
+ });
781
759
 
782
760
  return () => {
783
761
  mounted = false;
@@ -896,42 +874,33 @@ export default defineConfig({
896
874
  "src/main.ts": `import { createController } from '@smoregg/sdk';
897
875
  import type { Controller, ControllerInfo } from '@smoregg/sdk';
898
876
 
899
- // You can also register listeners in config:
900
- // const controller = await createController({
901
- // listeners: { 'game-state': (data) => { /* handle state */ } },
902
- // });
903
-
904
877
  let count = 0;
905
- let controller: Controller;
906
878
 
907
879
  const playerInfoEl = document.getElementById('player-info')!;
908
880
  const countEl = document.getElementById('count')!;
909
881
  const tapBtn = document.getElementById('tap-btn')!;
910
882
 
911
- async function init() {
912
- controller = await createController({
913
- debug: true,
914
- // Lifecycle callbacks (uncomment to use):
915
- // onControllerJoin: (playerIndex, info) => { console.log('Player joined:', playerIndex); },
916
- // onControllerLeave: (playerIndex) => { console.log('Player left:', playerIndex); },
917
- // onError: (error) => { console.error('SDK Error:', error.message); },
918
- // onReady: () => void — called when all participants are ready
919
- // To control autoReady, use: import { configure } from '@smoregg/sdk'; configure({ autoReady: false });
920
- });
883
+ const controller = createController({ debug: true });
921
884
 
922
- playerInfoEl.textContent = \`Player \${controller.myIndex}\`;
885
+ // Lifecycle callbacks (uncomment to use):
886
+ // controller.onControllerJoin((playerIndex, info) => { console.log('Player joined:', playerIndex); });
887
+ // controller.onControllerLeave((playerIndex) => { console.log('Player left:', playerIndex); });
888
+ // controller.onError((error) => { console.error('SDK Error:', error.message); });
889
+ // controller.onAllReady(() => { console.log('All participants ready'); });
890
+ // To control autoReady, use: import { configure } from '@smoregg/sdk'; configure({ autoReady: false });
923
891
 
924
- controller.on('score-update', (data: { score: number }) => {
925
- count = data.score;
926
- countEl.textContent = String(count);
927
- });
892
+ controller.onAllReady(() => {
893
+ playerInfoEl.textContent = \`Player \${controller.myIndex}\`;
894
+ });
928
895
 
929
- controller.on('personal-message', (data: { text: string }) => {
930
- console.log('Received message:', data.text);
931
- });
932
- }
896
+ controller.on('score-update', (data: { score: number }) => {
897
+ count = data.score;
898
+ countEl.textContent = String(count);
899
+ });
933
900
 
934
- init();
901
+ controller.on('personal-message', (data: { text: string }) => {
902
+ console.log('Received message:', data.text);
903
+ });
935
904
 
936
905
  tapBtn.addEventListener('pointerdown', () => {
937
906
  controller.send('tap', { timestamp: Date.now() });