@mpgd/cli 0.3.2 → 0.4.1
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/index.js +349 -22
- package/package.json +14 -2
- package/templates/phaser-game/README.md +130 -6
- package/templates/phaser-game/agent/acceptance.md +7 -2
- package/templates/phaser-game/agent/brief.md +1 -1
- package/templates/phaser-game/agent/game-manifest.json +5 -1
- package/templates/phaser-game/apps/target-cloudflare-pages/package.json +28 -0
- package/templates/phaser-game/apps/target-cloudflare-pages/src/worker.ts +12 -0
- package/templates/phaser-game/apps/target-cloudflare-pages/tsconfig.json +8 -0
- package/templates/phaser-game/apps/target-cloudflare-pages/vite.config.ts +28 -0
- package/templates/phaser-game/apps/target-cloudflare-pages/wrangler.jsonc +28 -0
- package/templates/phaser-game/apps/target-devvit/README.md +1 -1
- package/templates/phaser-game/apps/target-devvit/package.json +1 -1
- package/templates/phaser-game/apps/target-devvit/src/server/index.ts +4 -4
- package/templates/phaser-game/index.html +2 -0
- package/templates/phaser-game/legal/privacy.html +78 -0
- package/templates/phaser-game/legal/support.html +66 -0
- package/templates/phaser-game/legal/terms.html +70 -0
- package/templates/phaser-game/mpgd.targets.json +6 -0
- package/templates/phaser-game/package.json +42 -12
- package/templates/phaser-game/pnpm-workspace.yaml +7 -0
- package/templates/phaser-game/public/icon.svg +12 -0
- package/templates/phaser-game/public/manifest.webmanifest +20 -0
- package/templates/phaser-game/src/assets/manifest.ts +15 -0
- package/templates/phaser-game/src/assets/marker.svg +12 -0
- package/templates/phaser-game/src/env.d.ts +1 -0
- package/templates/phaser-game/src/i18n/messages.ts +3 -0
- package/templates/phaser-game/src/main.ts +49 -0
- package/templates/phaser-game/src/platform/installPlatform.ts +1 -1
- package/templates/phaser-game/src/platform/runtimeDetector.ts +9 -1
- package/templates/phaser-game/src/runtime/gameContext.ts +6 -1
- package/templates/phaser-game/src/scenes/BootScene.ts +8 -0
- package/templates/phaser-game/src/scenes/LobbyScene.ts +18 -2
- package/templates/phaser-game/src/scenes/PlayScene.ts +3 -2
- package/templates/phaser-game/src/styles.css +25 -2
- package/templates/phaser-game/vite.config.ts +2 -0
|
@@ -5,7 +5,7 @@ Standalone Phaser 4 game starter generated by `@mpgd/create-game`.
|
|
|
5
5
|
## Local Loop
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
pnpm install
|
|
8
|
+
pnpm install -w
|
|
9
9
|
pnpm dev
|
|
10
10
|
pnpm check
|
|
11
11
|
pnpm build
|
|
@@ -15,6 +15,7 @@ The starter keeps game code behind `PlatformGateway` and demonstrates:
|
|
|
15
15
|
|
|
16
16
|
- target-aware adapter selection through `APP_TARGET`
|
|
17
17
|
- target-config/effective-config runtime snapshots
|
|
18
|
+
- target-portable Phaser asset manifest loading
|
|
18
19
|
- local translation keys
|
|
19
20
|
- optional `@mpgd/game-services` client wiring
|
|
20
21
|
- best-effort analytics events
|
|
@@ -30,12 +31,16 @@ platform-specific artifacts. Keep an `mpgd-kit` checkout nearby and pass it with
|
|
|
30
31
|
pnpm exec mpgd target build-all \
|
|
31
32
|
--targets-file ./mpgd.targets.json \
|
|
32
33
|
--kit-path ../mpgd-kit \
|
|
33
|
-
--targets web,ait,reddit \
|
|
34
|
+
--targets web,microsoft-store,ait,reddit \
|
|
34
35
|
--ait-variant wrapper
|
|
35
36
|
pnpm exec mpgd target smoke-all \
|
|
36
37
|
--targets-file ./mpgd.targets.json \
|
|
37
38
|
--kit-path ../mpgd-kit \
|
|
38
|
-
--targets web,ait,reddit
|
|
39
|
+
--targets web,microsoft-store,ait,reddit
|
|
40
|
+
pnpm exec mpgd target doctor \
|
|
41
|
+
--targets-file ./mpgd.targets.json \
|
|
42
|
+
--kit-path ../mpgd-kit \
|
|
43
|
+
--targets web,microsoft-store,ait,reddit
|
|
39
44
|
```
|
|
40
45
|
|
|
41
46
|
When developing the kit itself, the same commands work through the repository
|
|
@@ -45,7 +50,7 @@ script:
|
|
|
45
50
|
pnpm --dir ../mpgd-kit mpgd target build-all \
|
|
46
51
|
--targets-file "$PWD/mpgd.targets.json" \
|
|
47
52
|
--kit-path ../mpgd-kit \
|
|
48
|
-
--targets web,ait,reddit \
|
|
53
|
+
--targets web,microsoft-store,ait,reddit \
|
|
49
54
|
--ait-variant wrapper
|
|
50
55
|
```
|
|
51
56
|
|
|
@@ -53,6 +58,52 @@ pnpm --dir ../mpgd-kit mpgd target build-all \
|
|
|
53
58
|
into `.mpgd.targets.generated.json` before calling the kit's existing target
|
|
54
59
|
build and smoke scripts.
|
|
55
60
|
|
|
61
|
+
`mpgd target doctor` verifies that release manifest artifact paths stay under
|
|
62
|
+
this game directory, even when a build used the kit reference Apps in Toss or
|
|
63
|
+
Capacitor wrappers.
|
|
64
|
+
|
|
65
|
+
## Assets
|
|
66
|
+
|
|
67
|
+
Static assets live under `src/assets` and are declared in
|
|
68
|
+
`src/assets/manifest.ts`. Use stable manifest keys in scenes and pass Vite-
|
|
69
|
+
emitted URLs into the manifest with `?url` imports, or keep static
|
|
70
|
+
`new URL('./file', import.meta.url)` calls directly in the manifest module. The
|
|
71
|
+
starter keeps Vite `base: './'` so generated asset URLs stay portable across web
|
|
72
|
+
preview, Apps in Toss, Devvit, Android, and iOS bundles.
|
|
73
|
+
|
|
74
|
+
## Viewport And Controls
|
|
75
|
+
|
|
76
|
+
The starter computes an initial viewport plan with `@mpgd/target-config`.
|
|
77
|
+
Measure the game container first, then fall back to `visualViewport` or
|
|
78
|
+
`window.innerWidth`:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
const measured = measureGameViewport();
|
|
82
|
+
const viewport = resolveTargetViewportPlan({
|
|
83
|
+
width: measured.width,
|
|
84
|
+
height: measured.height,
|
|
85
|
+
source: measured.source,
|
|
86
|
+
runtime: runtime.config.runtime,
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Use this as a starting point for game-specific layout. The returned
|
|
91
|
+
recommendation is not a hard target rule; override it when your playfield or
|
|
92
|
+
input model needs a different UI arrangement.
|
|
93
|
+
|
|
94
|
+
- `compact` is `<= 599px`: phone and narrow Devvit/card layouts. Prefer bottom
|
|
95
|
+
controls and drawers.
|
|
96
|
+
- `medium` is `600px` through `899px`: larger phones, small tablets, and
|
|
97
|
+
moderate embeds. Keep the play surface centered and only add side controls
|
|
98
|
+
when touch targets remain comfortable.
|
|
99
|
+
- `expanded` is `>= 900px`: desktop-like layouts. Side controls and panels are
|
|
100
|
+
acceptable.
|
|
101
|
+
|
|
102
|
+
Orientation is measured from the container: height greater than width is
|
|
103
|
+
`portrait`; width greater than or equal to height is `landscape`. Devvit should
|
|
104
|
+
be treated as an embedded webview, so do not assume desktop Reddit always means
|
|
105
|
+
an expanded game surface.
|
|
106
|
+
|
|
56
107
|
## Reddit Devvit
|
|
57
108
|
|
|
58
109
|
This starter owns its Devvit app root in `apps/target-devvit`. That directory
|
|
@@ -66,7 +117,7 @@ name.
|
|
|
66
117
|
First-time Devvit setup:
|
|
67
118
|
|
|
68
119
|
```sh
|
|
69
|
-
pnpm install
|
|
120
|
+
pnpm install -w
|
|
70
121
|
pnpm devvit:login
|
|
71
122
|
pnpm devvit:whoami
|
|
72
123
|
pnpm devvit:init
|
|
@@ -81,9 +132,81 @@ authorization is not available in the current terminal session. After init, use
|
|
|
81
132
|
`pnpm devvit:playtest`, `pnpm devvit:upload`, and `pnpm devvit:publish` from
|
|
82
133
|
this game root.
|
|
83
134
|
|
|
135
|
+
## Apps in Toss
|
|
136
|
+
|
|
137
|
+
Use the target-aware local loop while developing game code for Apps in Toss:
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
pnpm dev:ait
|
|
141
|
+
pnpm build:ait
|
|
142
|
+
pnpm smoke:ait
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The kit reference wrapper includes the Apps in Toss community devtools package
|
|
146
|
+
for SDK mock and device debugging while the wrapper is still kit-owned:
|
|
147
|
+
|
|
148
|
+
```sh
|
|
149
|
+
pnpm ait:wrapper:dev
|
|
150
|
+
pnpm ait:wrapper:dev:plain
|
|
151
|
+
pnpm ait:wrapper:dev:phone
|
|
152
|
+
pnpm ait:devtools:mcp
|
|
153
|
+
pnpm ait:devtools:mcp:mobile
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
`ait:wrapper:dev` runs the kit wrapper with the community Vite plugin enabled.
|
|
157
|
+
It loads the last game bundle copied by `pnpm build:ait` from the wrapper's
|
|
158
|
+
`public/game` directory, so run `pnpm build:ait` again after game changes before
|
|
159
|
+
opening a wrapper devtools session. Use `ait:wrapper:dev:plain` to disable the
|
|
160
|
+
devtools plugin. `ait:wrapper:dev:phone` uses the devtools tunnel and CDP relay
|
|
161
|
+
for phone sandbox checks, and `ait:devtools:mcp:mobile` starts the community MCP
|
|
162
|
+
bridge in the phone tunnel mode after the wrapper prints the tunnel URLs. Use
|
|
163
|
+
`ait:devtools:mcp` for the default local or relay debugging mode. The kit
|
|
164
|
+
intentionally leaves
|
|
165
|
+
`cloudflared` postinstall disabled; the first phone tunnel session downloads the
|
|
166
|
+
binary lazily through the community devtools package instead of during ordinary
|
|
167
|
+
workspace install.
|
|
168
|
+
|
|
169
|
+
The starter includes `@ait-co/console-cli`, the Apps in Toss community console
|
|
170
|
+
CLI, as a dev dependency for project-local console automation:
|
|
171
|
+
|
|
172
|
+
```sh
|
|
173
|
+
pnpm ait:console:login
|
|
174
|
+
pnpm ait:console:whoami
|
|
175
|
+
pnpm ait:console:init
|
|
176
|
+
# add the real logo, thumbnail, and screenshot files referenced by aitcc.yaml
|
|
177
|
+
pnpm ait:console:register
|
|
178
|
+
pnpm ait:console:status
|
|
179
|
+
pnpm build:ait:package
|
|
180
|
+
pnpm ait:console:deploy -- release-output/ait/YOUR_APP.ait
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
`ait:console:init` creates the game-owned `aitcc.yaml` context, and
|
|
184
|
+
`ait:console:register` creates the mini-app and writes its `miniAppId` back to
|
|
185
|
+
that file. Before registration, add the real logo, thumbnail, and screenshot
|
|
186
|
+
files referenced by `aitcc.yaml` under `./assets/`. Use `pnpm build:ait` for the
|
|
187
|
+
kit wrapper smoke loop, and run `pnpm build:ait:package` before console deploys
|
|
188
|
+
so `release-output/ait/` contains the `.ait` bundle you pass after `--`.
|
|
189
|
+
|
|
190
|
+
The starter also installs `@apps-in-toss/web-framework` and awaits
|
|
191
|
+
`install()` from `@ait-co/polyfill` only when `__APP_TARGET__` is `ait`. In the
|
|
192
|
+
Apps in Toss WebView runtime, standard Web APIs such as `navigator.clipboard`,
|
|
193
|
+
`navigator.geolocation`, `navigator.share`, `navigator.vibrate`, network status,
|
|
194
|
+
and `_blank` `window.open` calls route through the Apps in Toss SDK. Plain
|
|
195
|
+
browser, Microsoft Store, Reddit, Android, and iOS builds do not import the AIT
|
|
196
|
+
SDK chunk and keep their native browser behavior. `pnpm dev:ait` is useful for
|
|
197
|
+
checking the AIT-gated bundle path, but SDK-backed API behavior should be
|
|
198
|
+
verified in the Apps in Toss sandbox or a game-owned devtools setup. If your
|
|
199
|
+
game uses permission-gated APIs such as clipboard or geolocation, declare the
|
|
200
|
+
matching permissions in the game-owned Apps in Toss `granite.config.ts` before
|
|
201
|
+
submission.
|
|
202
|
+
|
|
84
203
|
## Target Ownership Notes
|
|
85
204
|
|
|
86
205
|
- Browser preview is fully game-owned and writes to `artifacts/web-preview`.
|
|
206
|
+
- Microsoft Store is a game-owned PWA target that reuses the browser adapter and
|
|
207
|
+
writes to `artifacts/microsoft-store` with `manifest.webmanifest` for
|
|
208
|
+
PWABuilder packaging. Replace the starter icon and manifest metadata before
|
|
209
|
+
Store submission.
|
|
87
210
|
- Reddit Devvit is game-owned in `apps/target-devvit`.
|
|
88
211
|
- Apps in Toss currently uses the kit reference wrapper at
|
|
89
212
|
`${MPGD_KIT_PATH}/apps/target-ait` for smoke packaging. Before a real Toss
|
|
@@ -91,7 +214,8 @@ this game root.
|
|
|
91
214
|
review metadata are not shared with the kit demo.
|
|
92
215
|
- Android and iOS currently use the kit reference Capacitor shell at
|
|
93
216
|
`${MPGD_KIT_PATH}/apps/mobile-capacitor`. That is useful for local artifact
|
|
94
|
-
checks,
|
|
217
|
+
checks, and final artifacts are copied back to this game's `release-output/`
|
|
218
|
+
directory. Production apps should own their bundle ID/package ID, signing,
|
|
95
219
|
icons, and store metadata in a game-specific shell.
|
|
96
220
|
|
|
97
221
|
## Game Services
|
|
@@ -5,8 +5,9 @@ Run these checks before handing off a generated game starter:
|
|
|
5
5
|
```sh
|
|
6
6
|
pnpm check
|
|
7
7
|
pnpm build
|
|
8
|
-
pnpm --dir ../mpgd-kit mpgd target build-all --targets-file "$PWD/mpgd.targets.json" --targets web,ait,reddit --ait-variant wrapper
|
|
9
|
-
pnpm --dir ../mpgd-kit mpgd target smoke-all --targets-file "$PWD/mpgd.targets.json" --targets web,ait,reddit
|
|
8
|
+
pnpm --dir ../mpgd-kit mpgd target build-all --targets-file "$PWD/mpgd.targets.json" --targets web,microsoft-store,ait,reddit --ait-variant wrapper
|
|
9
|
+
pnpm --dir ../mpgd-kit mpgd target smoke-all --targets-file "$PWD/mpgd.targets.json" --targets web,microsoft-store,ait,reddit
|
|
10
|
+
pnpm --dir ../mpgd-kit mpgd target doctor --targets-file "$PWD/mpgd.targets.json" --targets web,microsoft-store,ait,reddit
|
|
10
11
|
```
|
|
11
12
|
|
|
12
13
|
For Apps in Toss changes, use the apps-in-toss MCP before implementation and
|
|
@@ -16,3 +17,7 @@ For Reddit Devvit changes, keep Devvit SDK calls inside the target wrapper and
|
|
|
16
17
|
continue to expose game-facing behavior through `PlatformGateway`. The Devvit
|
|
17
18
|
app root is game-owned in `apps/target-devvit`; run `pnpm devvit:init` once
|
|
18
19
|
after login before upload or playtest.
|
|
20
|
+
|
|
21
|
+
For Microsoft Store changes, keep the first pass as a PWA/web target that uses
|
|
22
|
+
the browser adapter. Add a dedicated Store commerce adapter only when wiring
|
|
23
|
+
Digital Goods API and Payment Request through backend ledger verification.
|
|
@@ -16,7 +16,7 @@ Useful commands:
|
|
|
16
16
|
pnpm dev
|
|
17
17
|
pnpm check
|
|
18
18
|
pnpm build
|
|
19
|
-
pnpm exec mpgd target build-all --targets-file ./mpgd.targets.json --kit-path ../mpgd-kit --targets web,ait,reddit --ait-variant wrapper
|
|
19
|
+
pnpm exec mpgd target build-all --targets-file ./mpgd.targets.json --kit-path ../mpgd-kit --targets web,microsoft-store,ait,reddit --ait-variant wrapper
|
|
20
20
|
pnpm devvit:login
|
|
21
21
|
pnpm devvit:init
|
|
22
22
|
pnpm devvit:playtest
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "__GAME_TITLE__",
|
|
6
6
|
"engine": "phaser-4"
|
|
7
7
|
},
|
|
8
|
-
"targets": ["web-preview", "android", "ios", "ait", "reddit"],
|
|
8
|
+
"targets": ["web-preview", "microsoft-store", "android", "ios", "ait", "reddit"],
|
|
9
9
|
"futureTargets": ["telegram", "tauri"],
|
|
10
10
|
"platformBoundary": "PlatformGateway",
|
|
11
11
|
"mcpRequirements": {
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
"id": "simulation.loop.phase",
|
|
18
18
|
"owner": "src/game/state.ts"
|
|
19
19
|
},
|
|
20
|
+
{
|
|
21
|
+
"id": "assets.manifest.phaser-loader",
|
|
22
|
+
"owner": "src/assets/manifest.ts"
|
|
23
|
+
},
|
|
20
24
|
{
|
|
21
25
|
"id": "runtime.platform.gateway",
|
|
22
26
|
"owner": "src/platform/installPlatform.ts"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__PACKAGE_NAME__-target-cloudflare-pages",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"check": "ttsc --noEmit -p tsconfig.json",
|
|
8
|
+
"lint": "ttsc --noEmit -p tsconfig.json",
|
|
9
|
+
"format": "ttsc format",
|
|
10
|
+
"fix": "ttsc fix",
|
|
11
|
+
"build": "vite build",
|
|
12
|
+
"dev": "pnpm build && wrangler pages dev dist --port 8788",
|
|
13
|
+
"preview": "pnpm build && wrangler pages dev dist --port 8788",
|
|
14
|
+
"deploy": "pnpm build && wrangler pages deploy dist --project-name __GAME_NAME__",
|
|
15
|
+
"types": "wrangler types --path ./src/worker-configuration.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@mpgd/bridge": "__MPGD_DEPENDENCY_VERSION_BRIDGE__"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@cloudflare/workers-types": "^5.20260707.1",
|
|
22
|
+
"@ttsc/unplugin": "0.16.9",
|
|
23
|
+
"ttsc": "0.16.9",
|
|
24
|
+
"typescript": "7.0.1-rc",
|
|
25
|
+
"vite": "^8.1.3",
|
|
26
|
+
"wrangler": "^4.107.0"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createMpgdCloudflarePagesHostFetchHandler,
|
|
3
|
+
type MpgdCloudflarePagesHostEnv,
|
|
4
|
+
} from '@mpgd/bridge/cloudflare-pages';
|
|
5
|
+
|
|
6
|
+
const fetchHandler = createMpgdCloudflarePagesHostFetchHandler();
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
fetch(request, env, ctx) {
|
|
10
|
+
return fetchHandler(request, env, ctx);
|
|
11
|
+
},
|
|
12
|
+
} satisfies ExportedHandler<MpgdCloudflarePagesHostEnv>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import ttsc from '@ttsc/unplugin/vite';
|
|
2
|
+
import { defineConfig } from 'vite';
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
publicDir: '../../artifacts/legal-site',
|
|
6
|
+
plugins: [
|
|
7
|
+
ttsc({
|
|
8
|
+
project: 'tsconfig.json',
|
|
9
|
+
plugins: false,
|
|
10
|
+
}),
|
|
11
|
+
],
|
|
12
|
+
build: {
|
|
13
|
+
outDir: 'dist',
|
|
14
|
+
emptyOutDir: true,
|
|
15
|
+
target: 'es2022',
|
|
16
|
+
sourcemap: false,
|
|
17
|
+
lib: {
|
|
18
|
+
entry: 'src/worker.ts',
|
|
19
|
+
formats: ['es'],
|
|
20
|
+
fileName: () => '_worker.js',
|
|
21
|
+
},
|
|
22
|
+
rollupOptions: {
|
|
23
|
+
output: {
|
|
24
|
+
entryFileNames: '_worker.js',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../../node_modules/wrangler/config-schema.json",
|
|
3
|
+
"name": "__GAME_NAME__",
|
|
4
|
+
"compatibility_date": "2026-07-07",
|
|
5
|
+
"compatibility_flags": ["nodejs_compat"],
|
|
6
|
+
"pages_build_output_dir": "./dist",
|
|
7
|
+
"observability": {
|
|
8
|
+
"enabled": true,
|
|
9
|
+
"logs": {
|
|
10
|
+
"enabled": true,
|
|
11
|
+
"head_sampling_rate": 1
|
|
12
|
+
},
|
|
13
|
+
"traces": {
|
|
14
|
+
"enabled": true,
|
|
15
|
+
"head_sampling_rate": 0.01
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
// Bind an authoritative game-services Worker when this Pages host should
|
|
20
|
+
// expose /api/game-services/* locally or in production:
|
|
21
|
+
//
|
|
22
|
+
// "services": [
|
|
23
|
+
// {
|
|
24
|
+
// "binding": "GAME_SERVICES",
|
|
25
|
+
// "service": "mpgd-game-services"
|
|
26
|
+
// }
|
|
27
|
+
// ]
|
|
28
|
+
}
|
|
@@ -480,7 +480,7 @@ async function acquireLeaderboardLock(lockKey: string, lockToken: string): Promi
|
|
|
480
480
|
|
|
481
481
|
function leaderboardLockExpirationDate(): Date {
|
|
482
482
|
// Devvit Redis SetOptions expects a Date and converts it to Redis EX seconds internally.
|
|
483
|
-
return new Date(Date.now() +
|
|
483
|
+
return new Date(Date.now() + leaderboardLockTtlMs);
|
|
484
484
|
}
|
|
485
485
|
|
|
486
486
|
async function writeLeaderboardScoreIfLockHeld(
|
|
@@ -613,11 +613,11 @@ function expressRequestToFetchRequest(request: ExpressRequest): Request {
|
|
|
613
613
|
};
|
|
614
614
|
|
|
615
615
|
if (request.method !== 'GET' && request.method !== 'HEAD') {
|
|
616
|
-
|
|
616
|
+
init.body = requestBodyToBodyInit(request.body);
|
|
617
|
+
|
|
618
|
+
if (!headers.has('content-type') && !(request.body instanceof Uint8Array)) {
|
|
617
619
|
headers.set('content-type', 'application/json');
|
|
618
620
|
}
|
|
619
|
-
|
|
620
|
-
init.body = requestBodyToBodyInit(request.body);
|
|
621
621
|
}
|
|
622
622
|
|
|
623
623
|
return new Request(expressRequestUrl(request), init);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>__GAME_TITLE__ Privacy Policy</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
color-scheme: light dark;
|
|
10
|
+
font-family:
|
|
11
|
+
Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
12
|
+
line-height: 1.6;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
body {
|
|
16
|
+
margin: 0;
|
|
17
|
+
background: Canvas;
|
|
18
|
+
color: CanvasText;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
main {
|
|
22
|
+
box-sizing: border-box;
|
|
23
|
+
margin: 0 auto;
|
|
24
|
+
max-width: 760px;
|
|
25
|
+
padding: 48px 24px;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
h1,
|
|
29
|
+
h2 {
|
|
30
|
+
line-height: 1.2;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
a {
|
|
34
|
+
color: LinkText;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
nav {
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-wrap: wrap;
|
|
40
|
+
gap: 16px;
|
|
41
|
+
margin: 0 0 32px;
|
|
42
|
+
}
|
|
43
|
+
</style>
|
|
44
|
+
</head>
|
|
45
|
+
<body>
|
|
46
|
+
<main>
|
|
47
|
+
<nav aria-label="Legal pages">
|
|
48
|
+
<a href="/privacy/" aria-current="page">Privacy</a>
|
|
49
|
+
<a href="/support/">Support</a>
|
|
50
|
+
<a href="/terms/">Terms</a>
|
|
51
|
+
</nav>
|
|
52
|
+
<h1>__GAME_TITLE__ Privacy Policy</h1>
|
|
53
|
+
<p>Last updated: __LEGAL_LAST_UPDATED__</p>
|
|
54
|
+
<p>
|
|
55
|
+
__GAME_TITLE__ collects only the information needed to run the game,
|
|
56
|
+
keep player progress, operate platform features, and respond to support
|
|
57
|
+
requests.
|
|
58
|
+
</p>
|
|
59
|
+
<h2>Information We Process</h2>
|
|
60
|
+
<p>
|
|
61
|
+
The game may process platform player identifiers, gameplay progress,
|
|
62
|
+
leaderboard scores, purchase or reward validation records, coarse
|
|
63
|
+
device/runtime information, and support messages you choose to send.
|
|
64
|
+
</p>
|
|
65
|
+
<h2>How We Use Information</h2>
|
|
66
|
+
<p>
|
|
67
|
+
We use this information to provide gameplay features, prevent duplicate
|
|
68
|
+
grants, maintain leaderboards, troubleshoot issues, and satisfy platform
|
|
69
|
+
review or safety requirements.
|
|
70
|
+
</p>
|
|
71
|
+
<h2>Contact</h2>
|
|
72
|
+
<p>
|
|
73
|
+
Replace this template before release with the game owner's support
|
|
74
|
+
contact and jurisdiction-specific privacy disclosures.
|
|
75
|
+
</p>
|
|
76
|
+
</main>
|
|
77
|
+
</body>
|
|
78
|
+
</html>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>__GAME_TITLE__ Support</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
color-scheme: light dark;
|
|
10
|
+
font-family:
|
|
11
|
+
Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
12
|
+
line-height: 1.6;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
body {
|
|
16
|
+
margin: 0;
|
|
17
|
+
background: Canvas;
|
|
18
|
+
color: CanvasText;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
main {
|
|
22
|
+
box-sizing: border-box;
|
|
23
|
+
margin: 0 auto;
|
|
24
|
+
max-width: 760px;
|
|
25
|
+
padding: 48px 24px;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
h1,
|
|
29
|
+
h2 {
|
|
30
|
+
line-height: 1.2;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
a {
|
|
34
|
+
color: LinkText;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
nav {
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-wrap: wrap;
|
|
40
|
+
gap: 16px;
|
|
41
|
+
margin: 0 0 32px;
|
|
42
|
+
}
|
|
43
|
+
</style>
|
|
44
|
+
</head>
|
|
45
|
+
<body>
|
|
46
|
+
<main>
|
|
47
|
+
<nav aria-label="Legal pages">
|
|
48
|
+
<a href="/privacy/">Privacy</a>
|
|
49
|
+
<a href="/support/" aria-current="page">Support</a>
|
|
50
|
+
<a href="/terms/">Terms</a>
|
|
51
|
+
</nav>
|
|
52
|
+
<h1>__GAME_TITLE__ Support</h1>
|
|
53
|
+
<p>
|
|
54
|
+
Replace this template before release with a monitored support email or
|
|
55
|
+
help desk URL. When contacting support, include your platform, app
|
|
56
|
+
version, build ID, and a short description of the issue.
|
|
57
|
+
</p>
|
|
58
|
+
<h2>Common Requests</h2>
|
|
59
|
+
<p>
|
|
60
|
+
Include relevant purchase receipts, reward/ad context, leaderboard run
|
|
61
|
+
IDs, or save-slot details when reporting account, purchase, reward, or
|
|
62
|
+
progress problems.
|
|
63
|
+
</p>
|
|
64
|
+
</main>
|
|
65
|
+
</body>
|
|
66
|
+
</html>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>__GAME_TITLE__ Terms</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
color-scheme: light dark;
|
|
10
|
+
font-family:
|
|
11
|
+
Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
12
|
+
line-height: 1.6;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
body {
|
|
16
|
+
margin: 0;
|
|
17
|
+
background: Canvas;
|
|
18
|
+
color: CanvasText;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
main {
|
|
22
|
+
box-sizing: border-box;
|
|
23
|
+
margin: 0 auto;
|
|
24
|
+
max-width: 760px;
|
|
25
|
+
padding: 48px 24px;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
h1,
|
|
29
|
+
h2 {
|
|
30
|
+
line-height: 1.2;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
a {
|
|
34
|
+
color: LinkText;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
nav {
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-wrap: wrap;
|
|
40
|
+
gap: 16px;
|
|
41
|
+
margin: 0 0 32px;
|
|
42
|
+
}
|
|
43
|
+
</style>
|
|
44
|
+
</head>
|
|
45
|
+
<body>
|
|
46
|
+
<main>
|
|
47
|
+
<nav aria-label="Legal pages">
|
|
48
|
+
<a href="/privacy/">Privacy</a>
|
|
49
|
+
<a href="/support/">Support</a>
|
|
50
|
+
<a href="/terms/" aria-current="page">Terms</a>
|
|
51
|
+
</nav>
|
|
52
|
+
<h1>__GAME_TITLE__ Terms</h1>
|
|
53
|
+
<p>Last updated: __LEGAL_LAST_UPDATED__</p>
|
|
54
|
+
<p>
|
|
55
|
+
These starter terms are placeholders for the game owner's production
|
|
56
|
+
terms of service.
|
|
57
|
+
</p>
|
|
58
|
+
<h2>Gameplay</h2>
|
|
59
|
+
<p>
|
|
60
|
+
Players are expected to follow platform rules, avoid abusive behavior,
|
|
61
|
+
and use the game only through supported clients and stores.
|
|
62
|
+
</p>
|
|
63
|
+
<h2>Platform Features</h2>
|
|
64
|
+
<p>
|
|
65
|
+
Purchases, rewarded ads, saves, and leaderboards may depend on platform
|
|
66
|
+
availability and authoritative backend validation.
|
|
67
|
+
</p>
|
|
68
|
+
</main>
|
|
69
|
+
</body>
|
|
70
|
+
</html>
|
|
@@ -6,6 +6,12 @@
|
|
|
6
6
|
"adapter": "browser",
|
|
7
7
|
"output": "artifacts/web-preview"
|
|
8
8
|
},
|
|
9
|
+
"microsoft-store": {
|
|
10
|
+
"kind": "web",
|
|
11
|
+
"gameApp": ".",
|
|
12
|
+
"adapter": "browser",
|
|
13
|
+
"output": "artifacts/microsoft-store"
|
|
14
|
+
},
|
|
9
15
|
"android": {
|
|
10
16
|
"kind": "capacitor-android",
|
|
11
17
|
"gameApp": ".",
|