@littlepartytime/sdk 2.2.3 → 2.3.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/GAME_DEV_GUIDE.md CHANGED
@@ -86,6 +86,8 @@ const config: GameConfig = {
86
86
  tags: ["strategy", "card"],
87
87
  version: "1.0.0",
88
88
  sdkVersion: "2.0.0",
89
+ // Optional: include a demo site in the game package
90
+ // demo: { title: "My Game — Demo" },
89
91
  };
90
92
 
91
93
  export default config;
@@ -430,9 +432,33 @@ Features:
430
432
  - **Action log**: See all actions sent by players in real-time
431
433
  - **Game over detection**: Automatically detects when `isGameOver()` returns true and displays results
432
434
  - **Reset**: Re-initialize the game at any time
435
+ - **Screenshot**: Capture the game content area (without the phone frame) as a PNG file
433
436
 
434
437
  This enables a rapid development cycle: **edit code -> refresh browser -> test immediately**.
435
438
 
439
+ ### Screenshot
440
+
441
+ A **Screenshot** button floats at the bottom of the phone frame on the Preview page. Clicking it captures the game's safe area (390×751 px, 2× retina resolution) as a PNG and downloads it immediately. The phone bezel, Dynamic Island, and Home Indicator are excluded.
442
+
443
+ The same capture function is also exposed as a JavaScript API on the page, so LLMs and Playwright scripts can call it programmatically:
444
+
445
+ ```javascript
446
+ // Via Playwright evaluate (e.g. in a test or from an AI agent):
447
+ const dataUrl = await page.evaluate(() => window.__devkit__.captureScreen());
448
+ // dataUrl is a "data:image/png;base64,..." string — pass it to a vision model or save it.
449
+
450
+ // Save to file in Node.js:
451
+ const base64 = dataUrl.replace(/^data:image\/png;base64,/, '');
452
+ fs.writeFileSync('screenshot.png', Buffer.from(base64, 'base64'));
453
+ ```
454
+
455
+ Alternatively, Playwright's built-in element screenshot can target the game area directly using the stable test ID:
456
+
457
+ ```javascript
458
+ const el = page.getByTestId('game-screen');
459
+ await el.screenshot({ path: 'screenshot.png' });
460
+ ```
461
+
436
462
  ### Multiplayer Page
437
463
 
438
464
  The Play page runs your game with real Socket.IO multiplayer:
@@ -535,6 +561,16 @@ await preview.startGame(); // Host clicks "Start Game"
535
561
  await preview.stop(); // Clean up browser + server
536
562
  ```
537
563
 
564
+ To capture a screenshot of the game area during a test, use either approach:
565
+
566
+ ```typescript
567
+ // Option A: via window.__devkit__ (returns base64 data URL)
568
+ const dataUrl = await page.evaluate(() => window.__devkit__.captureScreen());
569
+
570
+ // Option B: via Playwright element screenshot (saves directly to file)
571
+ await page.getByTestId('game-screen').screenshot({ path: 'screenshot.png' });
572
+ ```
573
+
538
574
  ### Excluding E2E Tests from Unit Test Runs
539
575
 
540
576
  E2E tests are slower and require playwright. Exclude them from the default `vitest run`:
@@ -572,8 +608,9 @@ This command:
572
608
  3. Reads `GameConfig` from the built engine to extract metadata
573
609
  4. Validates the required image assets (format, dimensions, aspect ratio)
574
610
  5. Validates `rules.md` exists and is non-empty
575
- 6. Generates `manifest.json` from your config
576
- 7. Creates a `.zip` file in the `dist/` directory containing code, manifest, rules, and images
611
+ 6. If `GameConfig.demo` is set, validates that `demo/dist/index.html` exists
612
+ 7. Generates `manifest.json` from your config
613
+ 8. Creates a `.zip` file in the `dist/` directory containing code, manifest, rules, images, and optional demo site
577
614
 
578
615
  ### Build Output
579
616
 
@@ -598,11 +635,13 @@ The `.zip` upload package contains:
598
635
  ├── banner.png|.webp # 16:9 banner
599
636
  ├── cover.png|.webp # 21:9 cover
600
637
  ├── splash.png|.webp # 9:21 splash screen
601
- └── assets/ # Custom game assets (if any)
602
- ├── cards/
603
- │ └── king.png
604
- └── sounds/
605
- └── flip.mp3
638
+ ├── assets/ # Custom game assets (if any)
639
+ ├── cards/
640
+ └── king.png
641
+ └── sounds/
642
+ └── flip.mp3
643
+ └── demo/ # Demo site (optional, only if GameConfig.demo is set)
644
+ └── index.html
606
645
  ```
607
646
 
608
647
  ### Configuration
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export type { Player, GameAction, GameResult, Platform, HapticImpactStyle, HapticNotificationType, DeviceTilt, DeviceCapabilities, } from './types';
2
- export type { PlayerState, GameState, GameAssets, GameConfig, GameEngine, GameRendererProps } from './interfaces';
2
+ export type { PlayerState, GameState, GameAssets, GameDemo, GameConfig, GameEngine, GameRendererProps } from './interfaces';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,MAAM,EACN,UAAU,EACV,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,EACV,kBAAkB,GACnB,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,MAAM,EACN,UAAU,EACV,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,EACV,kBAAkB,GACnB,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
@@ -18,6 +18,10 @@ export interface GameAssets {
18
18
  /** 9:21 loading/splash screen (1080x2520+ recommended, .png or .webp) */
19
19
  splash: string;
20
20
  }
21
+ export interface GameDemo {
22
+ /** Title shown on the demo page (e.g. "奶酪大盗 — 游戏演示") */
23
+ title: string;
24
+ }
21
25
  export interface GameConfig {
22
26
  name: string;
23
27
  description: string;
@@ -28,6 +32,8 @@ export interface GameConfig {
28
32
  version: string;
29
33
  sdkVersion: string;
30
34
  price?: number;
35
+ /** Optional demo site metadata. When present, `lpt-dev-kit pack` will look for `demo/dist/` and include it in the ZIP. */
36
+ demo?: GameDemo;
31
37
  }
32
38
  export interface GameEngine {
33
39
  init(players: Player[], options?: Record<string, unknown>): GameState;
@@ -1 +1 @@
1
- {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExE,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,UAAU;IACzB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACtE,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,SAAS,CAAC;IAChF;;;;;;;;;OASG;IACH,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC;IACtC,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,UAAU,CAAC;IACxC,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACvE;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;CAC3B"}
1
+ {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExE,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,UAAU;IACzB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0HAA0H;IAC1H,IAAI,CAAC,EAAE,QAAQ,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACtE,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,SAAS,CAAC;IAChF;;;;;;;;;OASG;IACH,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC;IACtC,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,UAAU,CAAC;IACxC,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACvE;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;CAC3B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@littlepartytime/sdk",
3
- "version": "2.2.3",
3
+ "version": "2.3.0",
4
4
  "description": "Game SDK for Little Party Time platform - type definitions and testing utilities",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",