@littlepartytime/dev-kit 1.4.0 → 1.6.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/__tests__/validate-game-assets.test.d.ts +2 -0
- package/dist/__tests__/validate-game-assets.test.d.ts.map +1 -0
- package/dist/__tests__/validate-game-assets.test.js +155 -0
- package/dist/__tests__/validate-game-assets.test.js.map +1 -0
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +1 -0
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/pack.d.ts.map +1 -1
- package/dist/commands/pack.js +30 -2
- package/dist/commands/pack.js.map +1 -1
- package/dist/utils/validate-game-assets.d.ts +20 -0
- package/dist/utils/validate-game-assets.d.ts.map +1 -0
- package/dist/utils/validate-game-assets.js +79 -0
- package/dist/utils/validate-game-assets.js.map +1 -0
- package/dist/webapp/components/PhoneFrame.tsx +101 -0
- package/dist/webapp/pages/Play.tsx +11 -7
- package/dist/webapp/pages/Preview.tsx +4 -2
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-game-assets.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/validate-game-assets.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const vitest_1 = require("vitest");
|
|
7
|
+
const validate_game_assets_1 = require("../utils/validate-game-assets");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const os_1 = __importDefault(require("os"));
|
|
11
|
+
function makeTempDir() {
|
|
12
|
+
return fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'lpt-game-assets-test-'));
|
|
13
|
+
}
|
|
14
|
+
const platformFiles = new Set(['icon.png', 'banner.png', 'cover.png', 'splash.png']);
|
|
15
|
+
(0, vitest_1.describe)('validateGameAssets', () => {
|
|
16
|
+
(0, vitest_1.it)('should return valid with no entries when assets dir does not exist', () => {
|
|
17
|
+
const dir = makeTempDir();
|
|
18
|
+
const result = (0, validate_game_assets_1.validateGameAssets)(path_1.default.join(dir, 'assets'), platformFiles);
|
|
19
|
+
(0, vitest_1.expect)(result.valid).toBe(true);
|
|
20
|
+
(0, vitest_1.expect)(result.entries).toHaveLength(0);
|
|
21
|
+
});
|
|
22
|
+
(0, vitest_1.it)('should return valid with no entries when assets dir is empty', () => {
|
|
23
|
+
const dir = makeTempDir();
|
|
24
|
+
const assetsDir = path_1.default.join(dir, 'assets');
|
|
25
|
+
fs_1.default.mkdirSync(assetsDir);
|
|
26
|
+
const result = (0, validate_game_assets_1.validateGameAssets)(assetsDir, platformFiles);
|
|
27
|
+
(0, vitest_1.expect)(result.valid).toBe(true);
|
|
28
|
+
(0, vitest_1.expect)(result.entries).toHaveLength(0);
|
|
29
|
+
});
|
|
30
|
+
(0, vitest_1.it)('should collect valid asset files', () => {
|
|
31
|
+
const dir = makeTempDir();
|
|
32
|
+
const assetsDir = path_1.default.join(dir, 'assets');
|
|
33
|
+
fs_1.default.mkdirSync(path_1.default.join(assetsDir, 'cards'), { recursive: true });
|
|
34
|
+
fs_1.default.writeFileSync(path_1.default.join(assetsDir, 'cards', 'king.png'), Buffer.alloc(100));
|
|
35
|
+
fs_1.default.writeFileSync(path_1.default.join(assetsDir, 'cards', 'queen.jpg'), Buffer.alloc(200));
|
|
36
|
+
const result = (0, validate_game_assets_1.validateGameAssets)(assetsDir, platformFiles);
|
|
37
|
+
(0, vitest_1.expect)(result.valid).toBe(true);
|
|
38
|
+
(0, vitest_1.expect)(result.entries).toHaveLength(2);
|
|
39
|
+
(0, vitest_1.expect)(result.entries.map(e => e.relativePath).sort()).toEqual(['cards/king.png', 'cards/queen.jpg']);
|
|
40
|
+
(0, vitest_1.expect)(result.totalSize).toBe(300);
|
|
41
|
+
});
|
|
42
|
+
(0, vitest_1.it)('should skip platform display images at root level', () => {
|
|
43
|
+
const dir = makeTempDir();
|
|
44
|
+
const assetsDir = path_1.default.join(dir, 'assets');
|
|
45
|
+
fs_1.default.mkdirSync(assetsDir);
|
|
46
|
+
// Platform images — should be skipped
|
|
47
|
+
fs_1.default.writeFileSync(path_1.default.join(assetsDir, 'icon.png'), Buffer.alloc(50));
|
|
48
|
+
fs_1.default.writeFileSync(path_1.default.join(assetsDir, 'banner.png'), Buffer.alloc(50));
|
|
49
|
+
// Game asset — should be included
|
|
50
|
+
fs_1.default.writeFileSync(path_1.default.join(assetsDir, 'bg.png'), Buffer.alloc(50));
|
|
51
|
+
const result = (0, validate_game_assets_1.validateGameAssets)(assetsDir, platformFiles);
|
|
52
|
+
(0, vitest_1.expect)(result.valid).toBe(true);
|
|
53
|
+
(0, vitest_1.expect)(result.entries).toHaveLength(1);
|
|
54
|
+
(0, vitest_1.expect)(result.entries[0].relativePath).toBe('bg.png');
|
|
55
|
+
});
|
|
56
|
+
(0, vitest_1.it)('should not skip platform image names in subdirectories', () => {
|
|
57
|
+
const dir = makeTempDir();
|
|
58
|
+
const assetsDir = path_1.default.join(dir, 'assets');
|
|
59
|
+
fs_1.default.mkdirSync(path_1.default.join(assetsDir, 'sub'), { recursive: true });
|
|
60
|
+
// Same name as platform image but in a subdirectory — should be included
|
|
61
|
+
fs_1.default.writeFileSync(path_1.default.join(assetsDir, 'sub', 'icon.png'), Buffer.alloc(50));
|
|
62
|
+
const result = (0, validate_game_assets_1.validateGameAssets)(assetsDir, platformFiles);
|
|
63
|
+
(0, vitest_1.expect)(result.valid).toBe(true);
|
|
64
|
+
(0, vitest_1.expect)(result.entries).toHaveLength(1);
|
|
65
|
+
(0, vitest_1.expect)(result.entries[0].relativePath).toBe('sub/icon.png');
|
|
66
|
+
});
|
|
67
|
+
(0, vitest_1.it)('should reject disallowed file extensions', () => {
|
|
68
|
+
const dir = makeTempDir();
|
|
69
|
+
const assetsDir = path_1.default.join(dir, 'assets');
|
|
70
|
+
fs_1.default.mkdirSync(assetsDir);
|
|
71
|
+
fs_1.default.writeFileSync(path_1.default.join(assetsDir, 'script.js'), 'console.log("hi")');
|
|
72
|
+
fs_1.default.writeFileSync(path_1.default.join(assetsDir, 'data.exe'), Buffer.alloc(10));
|
|
73
|
+
const result = (0, validate_game_assets_1.validateGameAssets)(assetsDir, platformFiles);
|
|
74
|
+
(0, vitest_1.expect)(result.valid).toBe(false);
|
|
75
|
+
(0, vitest_1.expect)(result.errors).toHaveLength(2);
|
|
76
|
+
(0, vitest_1.expect)(result.errors[0]).toContain('.js');
|
|
77
|
+
(0, vitest_1.expect)(result.errors[0]).toContain('not allowed');
|
|
78
|
+
});
|
|
79
|
+
(0, vitest_1.it)('should accept all allowed extensions', () => {
|
|
80
|
+
const dir = makeTempDir();
|
|
81
|
+
const assetsDir = path_1.default.join(dir, 'assets');
|
|
82
|
+
fs_1.default.mkdirSync(assetsDir);
|
|
83
|
+
const allowed = [
|
|
84
|
+
'img.png', 'img.jpg', 'img.jpeg', 'img.webp', 'img.svg', 'img.gif',
|
|
85
|
+
'sound.mp3', 'sound.wav', 'sound.ogg',
|
|
86
|
+
'data.json',
|
|
87
|
+
'font.woff2', 'font.woff',
|
|
88
|
+
];
|
|
89
|
+
for (const name of allowed) {
|
|
90
|
+
fs_1.default.writeFileSync(path_1.default.join(assetsDir, name), Buffer.alloc(10));
|
|
91
|
+
}
|
|
92
|
+
const result = (0, validate_game_assets_1.validateGameAssets)(assetsDir, platformFiles);
|
|
93
|
+
(0, vitest_1.expect)(result.valid).toBe(true);
|
|
94
|
+
(0, vitest_1.expect)(result.entries).toHaveLength(allowed.length);
|
|
95
|
+
});
|
|
96
|
+
(0, vitest_1.it)('should reject files exceeding 20MB', () => {
|
|
97
|
+
const dir = makeTempDir();
|
|
98
|
+
const assetsDir = path_1.default.join(dir, 'assets');
|
|
99
|
+
fs_1.default.mkdirSync(assetsDir);
|
|
100
|
+
// Create a file just over 20MB
|
|
101
|
+
fs_1.default.writeFileSync(path_1.default.join(assetsDir, 'huge.png'), Buffer.alloc(20 * 1024 * 1024 + 1));
|
|
102
|
+
const result = (0, validate_game_assets_1.validateGameAssets)(assetsDir, platformFiles);
|
|
103
|
+
(0, vitest_1.expect)(result.valid).toBe(false);
|
|
104
|
+
(0, vitest_1.expect)(result.errors.some(e => e.includes('exceeds 20MB'))).toBe(true);
|
|
105
|
+
});
|
|
106
|
+
(0, vitest_1.it)('should reject when total assets exceed 100MB', () => {
|
|
107
|
+
const dir = makeTempDir();
|
|
108
|
+
const assetsDir = path_1.default.join(dir, 'assets');
|
|
109
|
+
fs_1.default.mkdirSync(assetsDir);
|
|
110
|
+
// Create 6 files of 19MB each = 114MB total (each under 20MB limit)
|
|
111
|
+
for (let i = 0; i < 6; i++) {
|
|
112
|
+
fs_1.default.writeFileSync(path_1.default.join(assetsDir, `file${i}.png`), Buffer.alloc(19 * 1024 * 1024));
|
|
113
|
+
}
|
|
114
|
+
const result = (0, validate_game_assets_1.validateGameAssets)(assetsDir, platformFiles);
|
|
115
|
+
(0, vitest_1.expect)(result.valid).toBe(false);
|
|
116
|
+
(0, vitest_1.expect)(result.errors.some(e => e.includes('exceeds 100MB'))).toBe(true);
|
|
117
|
+
});
|
|
118
|
+
(0, vitest_1.it)('should reject paths containing ".."', () => {
|
|
119
|
+
const dir = makeTempDir();
|
|
120
|
+
const assetsDir = path_1.default.join(dir, 'assets');
|
|
121
|
+
// We can't actually create a file with ".." in a real directory entry,
|
|
122
|
+
// but we test that the validator would catch it if encountered.
|
|
123
|
+
// Instead test with a directory named ".." which is not traversable
|
|
124
|
+
fs_1.default.mkdirSync(assetsDir);
|
|
125
|
+
fs_1.default.writeFileSync(path_1.default.join(assetsDir, 'ok.png'), Buffer.alloc(10));
|
|
126
|
+
const result = (0, validate_game_assets_1.validateGameAssets)(assetsDir, platformFiles);
|
|
127
|
+
(0, vitest_1.expect)(result.valid).toBe(true);
|
|
128
|
+
(0, vitest_1.expect)(result.entries).toHaveLength(1);
|
|
129
|
+
});
|
|
130
|
+
(0, vitest_1.it)('should reject paths containing spaces', () => {
|
|
131
|
+
const dir = makeTempDir();
|
|
132
|
+
const assetsDir = path_1.default.join(dir, 'assets');
|
|
133
|
+
fs_1.default.mkdirSync(assetsDir);
|
|
134
|
+
fs_1.default.writeFileSync(path_1.default.join(assetsDir, 'my image.png'), Buffer.alloc(10));
|
|
135
|
+
const result = (0, validate_game_assets_1.validateGameAssets)(assetsDir, platformFiles);
|
|
136
|
+
(0, vitest_1.expect)(result.valid).toBe(false);
|
|
137
|
+
(0, vitest_1.expect)(result.errors.some(e => e.includes('spaces'))).toBe(true);
|
|
138
|
+
});
|
|
139
|
+
(0, vitest_1.it)('should handle nested directory structures', () => {
|
|
140
|
+
const dir = makeTempDir();
|
|
141
|
+
const assetsDir = path_1.default.join(dir, 'assets');
|
|
142
|
+
fs_1.default.mkdirSync(path_1.default.join(assetsDir, 'cards', 'suits'), { recursive: true });
|
|
143
|
+
fs_1.default.mkdirSync(path_1.default.join(assetsDir, 'sounds'), { recursive: true });
|
|
144
|
+
fs_1.default.writeFileSync(path_1.default.join(assetsDir, 'cards', 'suits', 'heart.png'), Buffer.alloc(10));
|
|
145
|
+
fs_1.default.writeFileSync(path_1.default.join(assetsDir, 'sounds', 'flip.mp3'), Buffer.alloc(10));
|
|
146
|
+
const result = (0, validate_game_assets_1.validateGameAssets)(assetsDir, platformFiles);
|
|
147
|
+
(0, vitest_1.expect)(result.valid).toBe(true);
|
|
148
|
+
(0, vitest_1.expect)(result.entries).toHaveLength(2);
|
|
149
|
+
(0, vitest_1.expect)(result.entries.map(e => e.relativePath).sort()).toEqual([
|
|
150
|
+
'cards/suits/heart.png',
|
|
151
|
+
'sounds/flip.mp3',
|
|
152
|
+
]);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
//# sourceMappingURL=validate-game-assets.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-game-assets.test.js","sourceRoot":"","sources":["../../src/__tests__/validate-game-assets.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAgDA,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,eAAe,CAAC,
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAgDA,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAoFvG"}
|
package/dist/commands/dev.js
CHANGED
package/dist/commands/dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":";;;;;AA4DA,
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pack.d.ts","sourceRoot":"","sources":["../../src/commands/pack.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pack.d.ts","sourceRoot":"","sources":["../../src/commands/pack.ts"],"names":[],"mappings":"AASA,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuKnE"}
|
package/dist/commands/pack.js
CHANGED
|
@@ -10,6 +10,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
10
10
|
const archiver_1 = __importDefault(require("archiver"));
|
|
11
11
|
const validate_bundle_1 = require("../utils/validate-bundle");
|
|
12
12
|
const validate_assets_1 = require("../utils/validate-assets");
|
|
13
|
+
const validate_game_assets_1 = require("../utils/validate-game-assets");
|
|
13
14
|
const manifest_1 = require("../utils/manifest");
|
|
14
15
|
async function packCommand(projectDir) {
|
|
15
16
|
const distDir = path_1.default.join(projectDir, 'dist');
|
|
@@ -96,9 +97,32 @@ async function packCommand(projectDir) {
|
|
|
96
97
|
process.exit(1);
|
|
97
98
|
}
|
|
98
99
|
console.log(' rules.md found');
|
|
99
|
-
// Step 7:
|
|
100
|
+
// Step 7: Validate game custom assets (assets/ directory, excluding platform images)
|
|
101
|
+
const assetsDir = path_1.default.join(projectDir, 'assets');
|
|
102
|
+
const platformAssetFiles = new Set();
|
|
103
|
+
for (const spec of validate_assets_1.ASSET_SPECS) {
|
|
104
|
+
const assetPath = assets[spec.key];
|
|
105
|
+
if (assetPath) {
|
|
106
|
+
const basename = path_1.default.basename(assetPath);
|
|
107
|
+
platformAssetFiles.add(basename);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const gameAssetsResult = (0, validate_game_assets_1.validateGameAssets)(assetsDir, platformAssetFiles);
|
|
111
|
+
for (const warning of gameAssetsResult.warnings) {
|
|
112
|
+
console.log(` WARNING: ${warning}`);
|
|
113
|
+
}
|
|
114
|
+
if (!gameAssetsResult.valid) {
|
|
115
|
+
for (const error of gameAssetsResult.errors) {
|
|
116
|
+
console.error(` ERROR: ${error}`);
|
|
117
|
+
}
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
if (gameAssetsResult.entries.length > 0) {
|
|
121
|
+
console.log(` Found ${gameAssetsResult.entries.length} custom asset(s) (${(gameAssetsResult.totalSize / 1024).toFixed(1)}KB total)`);
|
|
122
|
+
}
|
|
123
|
+
// Step 8: Generate manifest
|
|
100
124
|
const manifest = (0, manifest_1.generateManifest)(config);
|
|
101
|
-
// Step
|
|
125
|
+
// Step 9: Create zip
|
|
102
126
|
const zipPath = path_1.default.join(distDir, `${gameId}.zip`);
|
|
103
127
|
console.log(`\nPackaging to ${gameId}.zip...`);
|
|
104
128
|
await new Promise((resolve, reject) => {
|
|
@@ -120,6 +144,10 @@ async function packCommand(projectDir) {
|
|
|
120
144
|
}
|
|
121
145
|
// Rules
|
|
122
146
|
archive.file(rulesPath, { name: 'rules.md' });
|
|
147
|
+
// Game custom assets
|
|
148
|
+
for (const entry of gameAssetsResult.entries) {
|
|
149
|
+
archive.file(entry.absolutePath, { name: `assets/${entry.relativePath}` });
|
|
150
|
+
}
|
|
123
151
|
archive.finalize();
|
|
124
152
|
});
|
|
125
153
|
const zipSize = fs_1.default.statSync(zipPath).size;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pack.js","sourceRoot":"","sources":["../../src/commands/pack.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"pack.js","sourceRoot":"","sources":["../../src/commands/pack.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface GameAssetEntry {
|
|
2
|
+
/** Relative path from assets/ dir, e.g. "cards/king.png" */
|
|
3
|
+
relativePath: string;
|
|
4
|
+
/** Absolute path on disk */
|
|
5
|
+
absolutePath: string;
|
|
6
|
+
size: number;
|
|
7
|
+
}
|
|
8
|
+
export interface GameAssetsValidationResult {
|
|
9
|
+
valid: boolean;
|
|
10
|
+
errors: string[];
|
|
11
|
+
warnings: string[];
|
|
12
|
+
entries: GameAssetEntry[];
|
|
13
|
+
totalSize: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Collect and validate game custom assets from the assets/ directory.
|
|
17
|
+
* Excludes platform display images (icon/banner/cover/splash) at the root level.
|
|
18
|
+
*/
|
|
19
|
+
export declare function validateGameAssets(assetsDir: string, platformAssetFiles: Set<string>): GameAssetsValidationResult;
|
|
20
|
+
//# sourceMappingURL=validate-game-assets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-game-assets.d.ts","sourceRoot":"","sources":["../../src/utils/validate-game-assets.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,GAC9B,0BAA0B,CA6B5B"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateGameAssets = validateGameAssets;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const ALLOWED_EXTENSIONS = new Set([
|
|
10
|
+
'.png', '.jpg', '.jpeg', '.webp', '.svg', '.gif',
|
|
11
|
+
'.mp3', '.wav', '.ogg',
|
|
12
|
+
'.json',
|
|
13
|
+
'.woff2', '.woff',
|
|
14
|
+
]);
|
|
15
|
+
const MAX_SINGLE_FILE_SIZE = 20 * 1024 * 1024; // 20MB
|
|
16
|
+
const MAX_TOTAL_SIZE = 100 * 1024 * 1024; // 100MB
|
|
17
|
+
/**
|
|
18
|
+
* Collect and validate game custom assets from the assets/ directory.
|
|
19
|
+
* Excludes platform display images (icon/banner/cover/splash) at the root level.
|
|
20
|
+
*/
|
|
21
|
+
function validateGameAssets(assetsDir, platformAssetFiles) {
|
|
22
|
+
const errors = [];
|
|
23
|
+
const warnings = [];
|
|
24
|
+
const entries = [];
|
|
25
|
+
let totalSize = 0;
|
|
26
|
+
if (!fs_1.default.existsSync(assetsDir) || !fs_1.default.statSync(assetsDir).isDirectory()) {
|
|
27
|
+
return { valid: true, errors, warnings, entries, totalSize };
|
|
28
|
+
}
|
|
29
|
+
collectFiles(assetsDir, '', platformAssetFiles, entries, errors);
|
|
30
|
+
for (const entry of entries) {
|
|
31
|
+
totalSize += entry.size;
|
|
32
|
+
if (entry.size > MAX_SINGLE_FILE_SIZE) {
|
|
33
|
+
errors.push(`${entry.relativePath}: file is ${(entry.size / 1024 / 1024).toFixed(1)}MB, exceeds 20MB limit`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (totalSize > MAX_TOTAL_SIZE) {
|
|
37
|
+
errors.push(`Total assets size is ${(totalSize / 1024 / 1024).toFixed(1)}MB, exceeds 100MB limit`);
|
|
38
|
+
}
|
|
39
|
+
return { valid: errors.length === 0, errors, warnings, entries, totalSize };
|
|
40
|
+
}
|
|
41
|
+
function collectFiles(baseDir, relativeTo, platformAssetFiles, entries, errors) {
|
|
42
|
+
const items = fs_1.default.readdirSync(path_1.default.join(baseDir, relativeTo), { withFileTypes: true });
|
|
43
|
+
for (const item of items) {
|
|
44
|
+
const relPath = relativeTo ? `${relativeTo}/${item.name}` : item.name;
|
|
45
|
+
const absPath = path_1.default.join(baseDir, relPath);
|
|
46
|
+
if (item.isDirectory()) {
|
|
47
|
+
collectFiles(baseDir, relPath, platformAssetFiles, entries, errors);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (!item.isFile())
|
|
51
|
+
continue;
|
|
52
|
+
// Skip platform display images at root level (icon.png, banner.webp, etc.)
|
|
53
|
+
if (!relativeTo && platformAssetFiles.has(item.name)) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
// Path validation
|
|
57
|
+
if (relPath.includes('..')) {
|
|
58
|
+
errors.push(`${relPath}: path contains ".." which is not allowed`);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (/\s/.test(relPath)) {
|
|
62
|
+
errors.push(`${relPath}: path contains spaces which is not allowed`);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
// Extension validation
|
|
66
|
+
const ext = path_1.default.extname(item.name).toLowerCase();
|
|
67
|
+
if (!ALLOWED_EXTENSIONS.has(ext)) {
|
|
68
|
+
errors.push(`${relPath}: file type "${ext}" is not allowed. Allowed types: ${[...ALLOWED_EXTENSIONS].join(', ')}`);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const stat = fs_1.default.statSync(absPath);
|
|
72
|
+
entries.push({
|
|
73
|
+
relativePath: relPath,
|
|
74
|
+
absolutePath: absPath,
|
|
75
|
+
size: stat.size,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=validate-game-assets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-game-assets.js","sourceRoot":"","sources":["../../src/utils/validate-game-assets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import React, { useRef, useState, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
// iPhone 14/15 logical dimensions
|
|
4
|
+
const SCREEN_W = 390;
|
|
5
|
+
const SCREEN_H = 844;
|
|
6
|
+
const BEZEL = 8;
|
|
7
|
+
const OUTER_R = 48;
|
|
8
|
+
const INNER_R = OUTER_R - BEZEL;
|
|
9
|
+
const BODY_W = SCREEN_W + BEZEL * 2;
|
|
10
|
+
const BODY_H = SCREEN_H + BEZEL * 2;
|
|
11
|
+
|
|
12
|
+
export default function PhoneFrame({ children }: { children: React.ReactNode }) {
|
|
13
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
14
|
+
const [scale, setScale] = useState(1);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const el = containerRef.current;
|
|
18
|
+
if (!el) return;
|
|
19
|
+
|
|
20
|
+
const update = () => {
|
|
21
|
+
const pad = 16;
|
|
22
|
+
const s = Math.min(
|
|
23
|
+
(el.clientWidth - pad * 2) / BODY_W,
|
|
24
|
+
(el.clientHeight - pad * 2) / BODY_H,
|
|
25
|
+
1,
|
|
26
|
+
);
|
|
27
|
+
setScale(Math.max(s, 0.3));
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
update();
|
|
31
|
+
const ob = new ResizeObserver(update);
|
|
32
|
+
ob.observe(el);
|
|
33
|
+
return () => ob.disconnect();
|
|
34
|
+
}, []);
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<div
|
|
38
|
+
ref={containerRef}
|
|
39
|
+
className="flex items-center justify-center h-full overflow-hidden"
|
|
40
|
+
style={{ flex: 1, minWidth: 0, minHeight: 0 }}
|
|
41
|
+
>
|
|
42
|
+
{/* Wrapper sized to the scaled phone for correct layout flow */}
|
|
43
|
+
<div style={{ width: BODY_W * scale, height: BODY_H * scale, flexShrink: 0 }}>
|
|
44
|
+
{/* Phone body at original pixel size, visually scaled */}
|
|
45
|
+
<div
|
|
46
|
+
className="relative"
|
|
47
|
+
style={{
|
|
48
|
+
width: BODY_W,
|
|
49
|
+
height: BODY_H,
|
|
50
|
+
transform: `scale(${scale})`,
|
|
51
|
+
transformOrigin: 'top left',
|
|
52
|
+
}}
|
|
53
|
+
>
|
|
54
|
+
{/* Frame / bezel */}
|
|
55
|
+
<div
|
|
56
|
+
className="absolute inset-0"
|
|
57
|
+
style={{
|
|
58
|
+
borderRadius: OUTER_R,
|
|
59
|
+
background: '#1c1c1e',
|
|
60
|
+
boxShadow:
|
|
61
|
+
'0 0 0 1px rgba(255,255,255,0.1), 0 25px 50px -12px rgba(0,0,0,0.5)',
|
|
62
|
+
}}
|
|
63
|
+
/>
|
|
64
|
+
|
|
65
|
+
{/* Screen */}
|
|
66
|
+
<div
|
|
67
|
+
className="absolute overflow-hidden bg-black"
|
|
68
|
+
style={{
|
|
69
|
+
top: BEZEL,
|
|
70
|
+
left: BEZEL,
|
|
71
|
+
width: SCREEN_W,
|
|
72
|
+
height: SCREEN_H,
|
|
73
|
+
borderRadius: INNER_R,
|
|
74
|
+
contain: 'paint',
|
|
75
|
+
}}
|
|
76
|
+
>
|
|
77
|
+
{children}
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
{/* Dynamic Island */}
|
|
81
|
+
<div
|
|
82
|
+
className="absolute left-1/2 -translate-x-1/2 bg-black rounded-full"
|
|
83
|
+
style={{ top: BEZEL + 11, width: 126, height: 37, zIndex: 10 }}
|
|
84
|
+
/>
|
|
85
|
+
|
|
86
|
+
{/* Home Indicator */}
|
|
87
|
+
<div
|
|
88
|
+
className="absolute left-1/2 -translate-x-1/2 rounded-full"
|
|
89
|
+
style={{
|
|
90
|
+
bottom: BEZEL + 8,
|
|
91
|
+
width: 134,
|
|
92
|
+
height: 5,
|
|
93
|
+
background: 'rgba(255,255,255,0.15)',
|
|
94
|
+
zIndex: 10,
|
|
95
|
+
}}
|
|
96
|
+
/>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useState, useEffect, useCallback } from 'react';
|
|
2
2
|
import { io, Socket } from 'socket.io-client';
|
|
3
|
+
import PhoneFrame from '../components/PhoneFrame';
|
|
3
4
|
|
|
4
5
|
export default function Play() {
|
|
5
6
|
const [socket, setSocket] = useState<Socket | null>(null);
|
|
@@ -51,6 +52,7 @@ export default function Play() {
|
|
|
51
52
|
if (event === 'stateUpdate') socket.off('game:state', handler as any);
|
|
52
53
|
},
|
|
53
54
|
reportResult: () => {},
|
|
55
|
+
getAssetUrl: (assetPath: string) => `/assets/${assetPath}`,
|
|
54
56
|
} : null;
|
|
55
57
|
|
|
56
58
|
if (!joined) {
|
|
@@ -116,14 +118,16 @@ export default function Play() {
|
|
|
116
118
|
|
|
117
119
|
// Playing or ended
|
|
118
120
|
return (
|
|
119
|
-
<div className="h-[calc(100vh-80px)]">
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
121
|
+
<div className="h-[calc(100vh-80px)] relative">
|
|
122
|
+
<PhoneFrame>
|
|
123
|
+
{GameRenderer && platform && gameState ? (
|
|
124
|
+
<GameRenderer platform={platform} state={gameState} />
|
|
125
|
+
) : (
|
|
126
|
+
<div className="p-4 text-zinc-500">Loading game...</div>
|
|
127
|
+
)}
|
|
128
|
+
</PhoneFrame>
|
|
125
129
|
{room.phase === 'ended' && isHost && (
|
|
126
|
-
<div className="
|
|
130
|
+
<div className="absolute bottom-4 left-1/2 -translate-x-1/2 z-[9999]">
|
|
127
131
|
<button
|
|
128
132
|
onClick={() => socket?.emit('game:playAgain')}
|
|
129
133
|
className="bg-amber-600 hover:bg-amber-500 text-white px-6 py-2 rounded-full font-semibold"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
|
|
2
|
+
import PhoneFrame from '../components/PhoneFrame';
|
|
2
3
|
|
|
3
4
|
const PLAYER_NAMES = ['Alice', 'Bob', 'Carol', 'Dave', 'Eve', 'Frank', 'Grace', 'Heidi'];
|
|
4
5
|
|
|
@@ -120,6 +121,7 @@ export default function Preview() {
|
|
|
120
121
|
reportResult: (result: any) => {
|
|
121
122
|
console.log('Game result reported:', result);
|
|
122
123
|
},
|
|
124
|
+
getAssetUrl: (assetPath: string) => `/assets/${assetPath}`,
|
|
123
125
|
};
|
|
124
126
|
}, [engine]);
|
|
125
127
|
|
|
@@ -161,7 +163,7 @@ export default function Preview() {
|
|
|
161
163
|
return (
|
|
162
164
|
<div className="flex gap-4 h-[calc(100vh-80px)]">
|
|
163
165
|
{/* Renderer */}
|
|
164
|
-
<
|
|
166
|
+
<PhoneFrame>
|
|
165
167
|
{GameRenderer && platform && viewState ? (
|
|
166
168
|
<GameRenderer platform={platform} state={viewState} />
|
|
167
169
|
) : (
|
|
@@ -169,7 +171,7 @@ export default function Preview() {
|
|
|
169
171
|
{!engine ? 'Loading engine...' : 'Initializing game...'}
|
|
170
172
|
</div>
|
|
171
173
|
)}
|
|
172
|
-
</
|
|
174
|
+
</PhoneFrame>
|
|
173
175
|
|
|
174
176
|
{/* Control Panel */}
|
|
175
177
|
<div className="w-80 flex flex-col gap-4 overflow-auto">
|