@mpgd/cli 0.57.0 → 0.58.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 (46) hide show
  1. package/dist/capacitor-shell-starter.d.ts +30 -0
  2. package/dist/capacitor-shell-starter.js +243 -11
  3. package/dist/index.js +170 -11
  4. package/dist/legal-site-output.d.ts +18 -0
  5. package/dist/legal-site-output.js +46 -1
  6. package/dist/native-build-info.json +2 -2
  7. package/dist/native-build-target.js +1663 -899
  8. package/dist/native-deploy-run.js +4 -0
  9. package/dist/native-shell-store-policy.d.ts +123 -0
  10. package/dist/native-shell-store-policy.js +816 -0
  11. package/dist/release-state.d.ts +2 -0
  12. package/dist/release-state.js +4 -2
  13. package/dist/testflight-submission.d.ts +9 -0
  14. package/dist/testflight-submission.js +69 -0
  15. package/package.json +17 -17
  16. package/templates/lite-overlay/agent/acceptance.md +1 -1
  17. package/templates/lite-overlay/agent/brief.md +1 -1
  18. package/templates/lite-overlay/src/lite/deleteAccountButton.ts +173 -0
  19. package/templates/lite-overlay/src/lite/restorePurchasesButton.ts +63 -0
  20. package/templates/lite-overlay/src/runtime/createGame.ts +8 -0
  21. package/templates/notifications-overlay/common/docs/NOTIFICATIONS.md +12 -6
  22. package/templates/notifications-overlay/common/notifications/deployment.json +2 -1
  23. package/templates/notifications-overlay/common/notifications/topics.json +3 -0
  24. package/templates/notifications-overlay/common/src/platform/capacitorNotifications.ts +8 -3
  25. package/templates/notifications-overlay/common/src/platform/notifications.ts +17 -3
  26. package/templates/phaser-game/README.md +72 -0
  27. package/templates/phaser-game/agent/acceptance.md +4 -1
  28. package/templates/phaser-game/agent/brief.md +14 -4
  29. package/templates/phaser-game/gitignore +11 -0
  30. package/templates/phaser-game/legal/delete-account.html +133 -0
  31. package/templates/phaser-game/legal/privacy.html +111 -12
  32. package/templates/phaser-game/legal/support.html +1 -0
  33. package/templates/phaser-game/legal/terms.html +1 -0
  34. package/templates/phaser-game/mpgd.game.json +3 -0
  35. package/templates/phaser-game/src/env.d.ts +6 -0
  36. package/templates/phaser-game/src/i18n/messages.ts +86 -1
  37. package/templates/phaser-game/src/main.ts +69 -8
  38. package/templates/phaser-game/src/platform/commerceAccountBinding.ts +39 -10
  39. package/templates/phaser-game/src/platform/deleteAccount.ts +334 -0
  40. package/templates/phaser-game/src/platform/gameServices.ts +55 -10
  41. package/templates/phaser-game/src/platform/guestIdentity.ts +301 -0
  42. package/templates/phaser-game/src/platform/restorePurchases.ts +205 -0
  43. package/templates/phaser-game/src/platform/serverSession.ts +8 -0
  44. package/templates/phaser-game/src/platform/sessionGatedServices.ts +217 -0
  45. package/templates/phaser-game/src/scenes/LobbyScene.ts +254 -1
  46. package/templates/phaser-game/src/scenes/PlayScene.ts +16 -6
@@ -507,3 +507,75 @@ credentials: Game Services reports `missing_authoritative_backend` or
507
507
  backends require both a non-production authority mode and an explicit
508
508
  `allowLocalBackend` opt-in, so they cannot manufacture successful production
509
509
  purchase, rewarded-ad, or leaderboard ledger results.
510
+
511
+ ### Guest identity
512
+
513
+ Store purchases on Android and iOS are bound to the player of a server
514
+ session: Google Play's `obfuscatedAccountId` and StoreKit's `appAccountToken`
515
+ are derived from that player's id (`src/platform/commerceAccountBinding.ts`),
516
+ and the backend checks them before it grants. The native shell's local player
517
+ (`android-local-player` / `ios-local-player`) is the same on every install, so
518
+ it binds nothing: Play refuses with `ACCOUNT_BINDING_REQUIRED` and StoreKit
519
+ throws an error naming the missing session.
520
+
521
+ Point the game at the kit's reference guest identity Worker
522
+ (`apps/game-identity-worker` in mpgd-kit, deployed per
523
+ `docs/CLOUDFLARE_WORKER_DEPLOY.md`):
524
+
525
+ ```sh
526
+ VITE_MPGD_IDENTITY_URL=https://identity.example.com
527
+ ```
528
+
529
+ `src/platform/guestIdentity.ts` then signs the player in during bootstrap: a
530
+ server-issued guest on the first launch, kept with a rotating refresh token in
531
+ the device's Keychain or Keystore, and the same guest on later launches. The
532
+ server player becomes the game services' `playerId` and the purchases'
533
+ binding, and `setStarterServerSession` sends its access token to the
534
+ game-services Worker, which resolves it through the identity Worker's
535
+ bindings. A session the identity service ended (logout, a replayed refresh
536
+ token, or 180 days without play by default) is replaced by a new guest; without a linked
537
+ account that player's purchases stay with the old one.
538
+
539
+ Offline at launch, the game starts anyway and keeps trying in the background
540
+ (after 5 s, 15 s, 1 min, then every 5 min, and at once when the device reports
541
+ it is online). A purchase or a Restore Purchases tap signs in first; if that
542
+ still fails, the purchase is refused before any store sheet opens (it
543
+ answers `failed` with the retryable diagnostic `STARTER_SESSION_REQUIRED`,
544
+ which the game action coordinator treats as a plain failure; retry with a
545
+ new idempotency key, as for any failed purchase) and the restore control says it could not
546
+ reach the game server and stays tappable as a retry. The purchase, restore,
547
+ and notification services (`src/platform/sessionGatedServices.ts`) come up
548
+ for the server player as soon as a sign-in succeeds, and run the startup
549
+ purchase recovery then; they are never bound to the platform's local
550
+ placeholder, so no purchase or journal record changes owner. Rewarded ads
551
+ stay off for such a run: an ad watched before the session exists could not
552
+ be claimed. The scenes' `player` and `identitySession` are the boot values
553
+ for the whole run (the platform's player when the boot sign-in failed) and
554
+ the server player from the next launch on: key game-owned save data by
555
+ something that does not change, such as the platform storage itself, not by
556
+ `player.playerId`. A native shell only reaches `https:` origins, so test on a
557
+ device or emulator through an https tunnel to a local Worker. Account linking (Sign in with Apple or Google) is not
558
+ part of the reference Worker yet.
559
+
560
+ ### Restore Purchases
561
+
562
+ The lobby (Phaser) or a corner button (lite) shows **Restore purchases** on
563
+ targets that sell through a store and have a Game Services client. It calls
564
+ `monetizationRecovery.restorePurchases()` (`src/platform/restorePurchases.ts`):
565
+ the store resynchronizes (StoreKit `AppStore.sync()`; Google Play re-reads owned
566
+ items) and every purchase is verified through the backend ledger before anything
567
+ is granted. App Review expects this control while the catalog sells a
568
+ non-consumable such as `REMOVE_ADS`. On the App Store and Google Play a purchase
569
+ is bound to the server player, so without a server session (see Guest identity)
570
+ the button says to connect to the game server instead of restoring; keep it reachable from the game's own
571
+ store or settings screen when you replace the lobby.
572
+
573
+ A reinstall on Android, a new device, a second device, a logout, or (by
574
+ default) 180 days away make a new guest, and the store then returns the
575
+ purchase's non-consumables bound to the guest that bought them. The kit's
576
+ reference Worker grants a verified restore of such a non-consumable to the new
577
+ guest as well (restore sharing; earlier devices keep it, up to five guests per
578
+ purchase by default), and the control then says **Restored to this device**;
579
+ past the limit it says the purchase is already in use on the maximum number of
580
+ devices. Consumables are never shared. See "Reinstalls and new devices" in the
581
+ kit's `docs/CLOUDFLARE_WORKER_DEPLOY.md` before selling non-consumables.
@@ -67,7 +67,10 @@ the snapshot bounds for persistent controls.
67
67
  ## Server session
68
68
 
69
69
  Verify the game sets its real server-backed session with `setStarterServerSession`
70
- before `bootstrap()` (a guest backend through `createGuestServerSession`) and does
70
+ before the game services are created (the starter's `guestIdentity.ts` does it
71
+ with `VITE_MPGD_IDENTITY_URL`, a guest backend through `createGuestServerSession`),
72
+ that a store purchase on Android and iOS carries the server player's binding
73
+ (not `android-local-player` / `ios-local-player`), and that the game does
71
74
  not rely on the development fallback, which only a game created with
72
75
  `--providers notifications` reads. `VITE_MPGD_DEV_NOTIFICATION_SESSION` is local-only evidence:
73
76
  a `pnpm build` never signs in with it (its `mpgd-dev` header needs the Vite dev
@@ -51,10 +51,20 @@ and reconcile existing operations on startup and resume without opening SDK UI.
51
51
 
52
52
  ## Server session
53
53
 
54
- Set the game's server-backed session with `setStarterServerSession`
55
- (`src/platform/serverSession.ts`) before `bootstrap()`; with a guest backend use
56
- `createGuestServerSession(coordinator)`, whose `sessionId` is the stable
57
- session-family id. For local notifications work only (a game created with
54
+ With `VITE_MPGD_IDENTITY_URL` set (the kit's reference guest identity Worker,
55
+ `apps/game-identity-worker`), `src/platform/guestIdentity.ts` signs the player
56
+ in as a server-issued guest during bootstrap, before the game services read
57
+ the session: it keeps the refresh token in the device's Keychain or Keystore,
58
+ calls `setStarterServerSession` with `createGuestServerSession(coordinator)`
59
+ (whose `sessionId` is the stable session-family id), and binds StoreKit and
60
+ Google Play purchases to the server player. A failed boot sign-in is retried
61
+ in the background and before each purchase or restore; the purchase,
62
+ restore, and notification services come up when it succeeds
63
+ (`src/platform/sessionGatedServices.ts`). Without it the native shell's
64
+ local player binds no purchase, and StoreKit and Play refuse with the reason.
65
+ A game with its own identity service sets its session with
66
+ `setStarterServerSession` (`src/platform/serverSession.ts`) before the game
67
+ services are created instead. For local notifications work only (a game created with
58
68
  `--providers notifications`), `VITE_MPGD_DEV_NOTIFICATION_SESSION` on the Vite
59
69
  dev server in the `development` mode signs in with an unauthenticated
60
70
  development session (`src/platform/developmentServerSession.ts`)
@@ -18,3 +18,14 @@ apps/*/.env
18
18
  .DS_Store
19
19
  *.log
20
20
  *.ait
21
+ # Signing and store credentials stay out of Git (use mise or CI secrets).
22
+ # google-services.json and GoogleService-Info.plist are committed on
23
+ # purpose: Firebase documents them as non-secret, and release builds run from
24
+ # a pinned Git checkout that needs them.
25
+ *.p12
26
+ *.p8
27
+ *.mobileprovision
28
+ *.provisionprofile
29
+ *.keystore
30
+ *.jks
31
+ *.pepk
@@ -0,0 +1,133 @@
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>Delete Your __GAME_TITLE__ Account</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/">Terms</a>
51
+ <a href="/delete-account/" aria-current="page">Delete account</a>
52
+ </nav>
53
+ <!--
54
+ Google Play: enter this page's URL (https://<your legal site>/delete-account/)
55
+ in Play Console > App content > Data safety > "Delete account URL".
56
+ The page must name the app as the store listing does, let players
57
+ request deletion without reinstalling the game, and say what is
58
+ deleted and what is kept and for how long. Starting point, not legal
59
+ advice: replace every REPLACE marker in square brackets (mpgd legal
60
+ build and check warn while any remain).
61
+ -->
62
+ <h1>Delete Your __GAME_TITLE__ Account</h1>
63
+ <p>
64
+ This page explains how to delete your __GAME_TITLE__ account and the
65
+ data linked to it. __GAME_TITLE__ is published by [REPLACE: developer
66
+ name exactly as shown on the store listing].
67
+ </p>
68
+ <h2>In the Game</h2>
69
+ <ol>
70
+ <li>Open __GAME_TITLE__ and go to [REPLACE: menu path, for example the lobby's Delete account button].</li>
71
+ <li>Tap <strong>Delete account</strong>, read what is deleted, and tap <strong>Delete permanently</strong>.</li>
72
+ <li>
73
+ The game deletes your account and signs you out. Anything our server
74
+ cannot finish at once is completed automatically within
75
+ [REPLACE: period, for example 24 hours].
76
+ </li>
77
+ </ol>
78
+ <h2>Without the Game</h2>
79
+ <p>
80
+ If you no longer have the game installed, you do not need to reinstall
81
+ it. Send a deletion request to
82
+ [REPLACE: support email address or request form URL] with the subject
83
+ "Delete my account" and [REPLACE: what lets you find the account,
84
+ for example the player ID shown in the game's settings, or the store
85
+ order number of a purchase made with it]. We delete the account within
86
+ [REPLACE: period, for example 30 days] and confirm by reply.
87
+ [REPLACE: what happens to a guest account that has neither, for
88
+ example "If you cannot give either, we cannot find your account; its
89
+ data is deleted after N months without play."]
90
+ </p>
91
+ <h2>What Is Deleted</h2>
92
+ <ul>
93
+ <li>Your player account and every sign-in session on every device.</li>
94
+ <li>Scores and leaderboard entries.</li>
95
+ <li>[REPLACE: game progress, if our server stores it; otherwise delete this item.]</li>
96
+ <li>Rewarded-ad records.</li>
97
+ <li>Notification tokens, notification settings, and your consent records for advertising messages.</li>
98
+ </ul>
99
+ <h2>What We Keep, and for How Long</h2>
100
+ <ul>
101
+ <li>
102
+ <strong>Purchase records</strong> (the product, the store's order or
103
+ transaction number, and the date) for 5 years from the purchase or its
104
+ last refund, whichever is later, for payment and supply record
105
+ obligations [REPLACE: confirm with counsel which apply to you, for
106
+ example Korea's Act on Consumer Protection in Electronic Commerce].
107
+ They are kept separately and no longer contain your player ID (the
108
+ store's own order number still identifies the purchase), and they
109
+ also stop the same store purchase from being used twice. They are
110
+ deleted after that period.
111
+ </li>
112
+ <li>[REPLACE: anything else the game keeps, such as support messages, with the period.]</li>
113
+ </ul>
114
+ <h2>Purchases</h2>
115
+ <p>
116
+ Deleting your account does not refund purchases. Items you buy once
117
+ (such as removing ads) stay owned by your Google Play or Apple
118
+ account: if you play again, Restore purchases gives them to your new
119
+ game account as a new record, and the deleted account is never
120
+ restored. Consumable items (such as coins) are not restored. To ask
121
+ for a refund, contact Google Play or Apple. A purchase still pending when
122
+ the account is deleted (waiting for a payment or a parent's approval)
123
+ is never delivered: Google Play refunds it automatically, but an App
124
+ Store purchase is not refunded automatically; ask Apple for the
125
+ refund. [REPLACE: subscriptions, if the
126
+ game sells any: cancel them in the store first, because billing
127
+ continues through the store.]
128
+ </p>
129
+ <h2>Contact</h2>
130
+ <p>[REPLACE: support email or form, and the data protection contact if required.]</p>
131
+ </main>
132
+ </body>
133
+ </html>
@@ -48,30 +48,129 @@
48
48
  <a href="/privacy/" aria-current="page">Privacy</a>
49
49
  <a href="/support/">Support</a>
50
50
  <a href="/terms/">Terms</a>
51
+ <a href="/delete-account/">Delete account</a>
51
52
  </nav>
52
53
  <h1>__GAME_TITLE__ Privacy Policy</h1>
53
54
  <p>Last updated: __LEGAL_LAST_UPDATED__</p>
54
55
  <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.
56
+ This policy explains what __GAME_TITLE__ (the "game") and its operator,
57
+ [REPLACE: legal name of the developer or company] ("we"), collect, why,
58
+ how long we keep it, and how to have it deleted.
58
59
  </p>
60
+ <!--
61
+ Starting point, not legal advice. Before publishing, replace every
62
+ REPLACE marker in square brackets (mpgd legal build warns while any remain) and
63
+ delete what the game does not do or use.
64
+ -->
59
65
  <h2>Information We Process</h2>
66
+ <ul>
67
+ <li>
68
+ <strong>Player identifiers.</strong> A random guest player ID issued by
69
+ our game server, a random ID for this installation of the game, and,
70
+ when you sign in, the account ID of the sign-in provider. Store purchases are bound to a one-way hash of your signed-in player ID.
71
+ </li>
72
+ <li>
73
+ <strong>Game progress.</strong> Saves, settings, scores, and the
74
+ leaderboard entries you submit.
75
+ </li>
76
+ <li>
77
+ <strong>Purchases.</strong> The products you buy and the store's
78
+ transaction records (Google Play order IDs and a one-way hash of the
79
+ purchase token, which our server sends to Google to verify the
80
+ purchase; App Store transaction and original transaction IDs), kept in
81
+ our purchase ledger so a purchase is granted once and can be
82
+ restored. We never receive your payment card details.
83
+ </li>
84
+ <li>
85
+ <strong>Rewarded ads.</strong> Records of ads you chose to watch for a
86
+ reward, so the reward is granted once.
87
+ </li>
88
+ <li>
89
+ <strong>Notifications.</strong> If you allow notifications, a push
90
+ token for your device and your notification choices, including any
91
+ consent to advertising messages and when you gave it.
92
+ </li>
93
+ <li>
94
+ <strong>Technical data.</strong> App version, platform, coarse device
95
+ type, and error details needed to operate and fix the game.
96
+ </li>
97
+ <li><strong>Support.</strong> Messages you send us.</li>
98
+ </ul>
99
+ <h2>How We Use Information</h2>
60
100
  <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.
101
+ To run the game and its online features, keep your progress and
102
+ purchases, grant purchases and rewards exactly once, prevent fraud and
103
+ cheating, send the notifications you asked for, answer support requests,
104
+ and meet store and legal requirements. We do not sell your personal
105
+ information. [REPLACE: keep "We do not track you across other
106
+ companies' apps or websites." only if the game shows no personalized
107
+ ads and uses no other tracking; otherwise describe the tracking and how
108
+ to refuse it.]
64
109
  </p>
65
- <h2>How We Use Information</h2>
110
+ <h2>Third-Party Services</h2>
111
+ <!-- Keep only the services the game uses. -->
112
+ <p>
113
+ These third-party services are involved in running the game; some act on
114
+ our behalf and some under their own privacy policies.
115
+ </p>
116
+ <ul>
117
+ <li>
118
+ Google Play Billing and the Google Play Developer API (Google) or Apple
119
+ StoreKit and the App Store Server API (Apple): purchases and their
120
+ verification.
121
+ </li>
122
+ <li>
123
+ Firebase Cloud Messaging (Google): delivering push notifications.
124
+ </li>
125
+ <li>
126
+ Google AdMob and the User Messaging Platform (Google): showing ads and
127
+ asking for consent where required. AdMob may use the device
128
+ advertising identifier where the platform and your choices allow it.
129
+ </li>
130
+ <li>
131
+ Cloudflare: hosting our game server, database, and these pages.
132
+ </li>
133
+ <li>[REPLACE: any other analytics, crash-reporting, or sign-in service.]</li>
134
+ </ul>
135
+ <h2>Retention</h2>
136
+ <p>
137
+ We keep account, progress, and notification data while your account is
138
+ active and delete it when you delete your account [REPLACE: and/or
139
+ after N months of inactivity]. We keep purchase records (product,
140
+ store order or transaction number, and date) for 5 years from the
141
+ purchase or its last refund, whichever is later, for payment and supply
142
+ record obligations
143
+ [REPLACE: the laws that apply to you, for example Korea's Act on
144
+ Consumer Protection in Electronic Commerce], also after the rest of
145
+ your data is deleted, stored separately and without your player ID. Server logs are kept for
146
+ [REPLACE: period].
147
+ </p>
148
+ <h2 id="delete-account">Deleting Your Account and Data</h2>
149
+ <p>
150
+ You can delete your account and the data linked to it in the game
151
+ ([REPLACE: menu path, for example the lobby's Delete account button])
152
+ or, without reinstalling the game, by following the steps on our
153
+ <a href="/delete-account/">account deletion page</a>. The deletion
154
+ page lists what is deleted and what we must keep (see Retention).
155
+ </p>
156
+ <h2>Your Choices</h2>
157
+ <p>
158
+ You can turn notifications off in the device settings [REPLACE: and in
159
+ the game's settings, if it has a notification settings screen], change
160
+ your ad privacy choices [REPLACE: from the game's privacy options, if it
161
+ shows ads with a consent form], and ask us for a copy or correction of
162
+ your data. [REPLACE: rights and contact points required where you
163
+ operate, for example GDPR, UK GDPR, CCPA, or Korea's PIPA.]
164
+ </p>
165
+ <h2>Children</h2>
66
166
  <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.
167
+ [REPLACE: who the game is for. If it is directed at children, describe
168
+ the stricter handling the store programs require.]
70
169
  </p>
71
170
  <h2>Contact</h2>
72
171
  <p>
73
- Replace this template before release with the game owner's support
74
- contact and jurisdiction-specific privacy disclosures.
172
+ [REPLACE: support email or form, postal address, and data protection
173
+ contact if required.]
75
174
  </p>
76
175
  </main>
77
176
  </body>
@@ -48,6 +48,7 @@
48
48
  <a href="/privacy/">Privacy</a>
49
49
  <a href="/support/" aria-current="page">Support</a>
50
50
  <a href="/terms/">Terms</a>
51
+ <a href="/delete-account/">Delete account</a>
51
52
  </nav>
52
53
  <h1>__GAME_TITLE__ Support</h1>
53
54
  <p>
@@ -48,6 +48,7 @@
48
48
  <a href="/privacy/">Privacy</a>
49
49
  <a href="/support/">Support</a>
50
50
  <a href="/terms/" aria-current="page">Terms</a>
51
+ <a href="/delete-account/">Delete account</a>
51
52
  </nav>
52
53
  <h1>__GAME_TITLE__ Terms</h1>
53
54
  <p>Last updated: __LEGAL_LAST_UPDATED__</p>
@@ -8,6 +8,9 @@
8
8
  "ui": {
9
9
  "textSelection": "disabled"
10
10
  },
11
+ "native": {
12
+ "orientation": "landscape"
13
+ },
11
14
  "acceptance": {
12
15
  "gameplay": {
13
16
  "schemaVersion": 1,
@@ -19,6 +19,12 @@ interface ImportMetaEnv {
19
19
  readonly VITE_MPGD_GAME_SERVICES_URL?: string;
20
20
  readonly VITE_MPGD_GAME_SERVICES_TARGET?: string;
21
21
  readonly VITE_MPGD_GAME_SERVICES_TRANSPORT?: string;
22
+ /**
23
+ * The guest identity service (the kit's reference Worker,
24
+ * `apps/game-identity-worker`): an https URL, or http on a local
25
+ * development host. See `src/platform/guestIdentity.ts`.
26
+ */
27
+ readonly VITE_MPGD_IDENTITY_URL?: string;
22
28
  /**
23
29
  * Local development only: `<playerId>` or `<playerId>.<installationId>`
24
30
  * for an unauthenticated notifications session (see `serverSession.ts`).
@@ -16,7 +16,32 @@ export type GameMessageKey =
16
16
  | 'rewardPending'
17
17
  | 'rewardUnavailable'
18
18
  | 'analytics'
19
- | 'bootError';
19
+ | 'bootError'
20
+ | 'restorePurchases'
21
+ | 'restoreWorking'
22
+ | 'restoreDone'
23
+ | 'restoreToDevice'
24
+ | 'restoreHolderLimit'
25
+ | 'restoreNothing'
26
+ | 'restoreIncomplete'
27
+ | 'restorePartial'
28
+ | 'restoreNeedsSession'
29
+ | 'restoreNeedsConnection'
30
+ | 'restoreFailed'
31
+ | 'deleteAccount'
32
+ | 'deleteAccountConfirm'
33
+ | 'deleteAccountPendingPurchase'
34
+ | 'deleteAccountConfirmButton'
35
+ | 'deleteAccountCancel'
36
+ | 'deleteAccountClose'
37
+ | 'deleteAccountWorking'
38
+ | 'deleteAccountDone'
39
+ | 'deleteAccountDoneLocalFailed'
40
+ | 'deleteAccountSessionEnded'
41
+ | 'deleteAccountNeedsSession'
42
+ | 'deleteAccountUnavailable'
43
+ | 'deleteAccountFailed'
44
+ | 'deleteAccountRejected';
20
45
 
21
46
  const messages = {
22
47
  en: {
@@ -36,6 +61,36 @@ const messages = {
36
61
  rewardUnavailable: 'Rewarded ads unavailable on this target',
37
62
  analytics: 'Analytics events: {count}',
38
63
  bootError: 'Failed to start game',
64
+ restorePurchases: 'Restore purchases',
65
+ restoreWorking: 'Restoring purchases...',
66
+ restoreDone: 'Purchases restored ({count} confirmed)',
67
+ restoreToDevice: 'Restored to this device ({count} confirmed)',
68
+ restoreHolderLimit: 'This purchase is already in use on the maximum number of devices',
69
+ restoreNothing: 'No new purchases to restore',
70
+ restoreIncomplete: 'Some purchases are not confirmed yet. Try again later.',
71
+ restorePartial: 'Purchases restored ({count}); others are not confirmed yet. Try again later.',
72
+ restoreNeedsSession: 'Restoring purchases needs a game server session',
73
+ restoreNeedsConnection: 'Could not reach the game server. Tap to try again.',
74
+ restoreFailed: 'Could not restore purchases. Try again later.',
75
+ deleteAccount: 'Delete account',
76
+ deleteAccountConfirm:
77
+ 'Delete your account? Your progress, scores, and notification settings are erased and you are signed out. '
78
+ + 'Purchases are not refunded; ask the store you bought from for a refund. Items you bought once (such as Remove ads) can be restored to a new account with Restore purchases while the store account still owns them. '
79
+ + 'Purchase records are kept for 5 years from the purchase or its last refund, for payment and supply record obligations, without your player ID.',
80
+ deleteAccountPendingPurchase:
81
+ 'A purchase is still being processed. Deleting now loses it: Google Play refunds it, but for an App Store purchase ask Apple for the refund.',
82
+ deleteAccountConfirmButton: 'Delete permanently',
83
+ deleteAccountCancel: 'Cancel',
84
+ deleteAccountClose: 'Close',
85
+ deleteAccountWorking: 'Deleting your account...',
86
+ deleteAccountDone: 'Your account was deleted and you are signed out.',
87
+ deleteAccountDoneLocalFailed:
88
+ 'Your account was deleted, but this device could not forget its sign-in. Clear the app data or reinstall the app.',
89
+ deleteAccountSessionEnded: 'Your session has ended: your account deletion most likely completed.',
90
+ deleteAccountNeedsSession: 'Sign in to delete your account.',
91
+ deleteAccountUnavailable: 'Account deletion is not available here. Use the deletion page linked from the privacy policy.',
92
+ deleteAccountFailed: 'Could not delete your account. Try again.',
93
+ deleteAccountRejected: 'Could not delete your account. Contact support.',
39
94
  },
40
95
  ko: {
41
96
  title: '__GAME_TITLE__',
@@ -54,6 +109,36 @@ const messages = {
54
109
  rewardUnavailable: '이 타깃에서는 리워드 광고를 사용할 수 없음',
55
110
  analytics: '애널리틱스 이벤트: {count}',
56
111
  bootError: '게임 시작 실패',
112
+ restorePurchases: '구매 복원',
113
+ restoreWorking: '구매 복원 중...',
114
+ restoreDone: '구매 복원 완료 ({count}건 확인)',
115
+ restoreToDevice: '이 기기로 구매를 복원했습니다 ({count}건 확인)',
116
+ restoreHolderLimit: '이 구매는 이미 허용된 최대 기기 수에서 사용 중입니다',
117
+ restoreNothing: '새로 복원할 구매가 없습니다',
118
+ restoreIncomplete: '아직 확인되지 않은 구매가 있습니다. 나중에 다시 시도하세요.',
119
+ restorePartial: '{count}건 복원, 아직 확인되지 않은 구매가 있습니다. 나중에 다시 시도하세요.',
120
+ restoreNeedsSession: '구매를 복원하려면 게임 서버 세션이 필요합니다',
121
+ restoreNeedsConnection: '게임 서버에 연결하지 못했습니다. 다시 시도하려면 누르세요.',
122
+ restoreFailed: '구매를 복원하지 못했습니다. 나중에 다시 시도하세요.',
123
+ deleteAccount: '계정 삭제',
124
+ deleteAccountConfirm:
125
+ '계정을 삭제할까요? 진행 상황, 점수, 알림 설정이 지워지고 로그아웃됩니다. '
126
+ + '구매는 환불되지 않습니다. 환불은 구매한 스토어에 요청하세요. 한 번 구매한 항목(광고 제거 등)은 스토어 계정이 계속 보유하고 있으면 구매 복원으로 새 계정에서 다시 받을 수 있습니다. '
127
+ + '구매 기록은 거래기록 보존 의무에 따라 구매 또는 마지막 환불 시점부터 5년 동안 플레이어 ID 없이 보관됩니다.',
128
+ deleteAccountPendingPurchase:
129
+ '아직 처리 중인 구매가 있습니다. 지금 삭제하면 이 구매는 지급되지 않습니다. Google Play는 자동으로 환불하지만, App Store 구매는 Apple에 환불을 요청해야 합니다.',
130
+ deleteAccountConfirmButton: '영구 삭제',
131
+ deleteAccountCancel: '취소',
132
+ deleteAccountClose: '닫기',
133
+ deleteAccountWorking: '계정을 삭제하는 중...',
134
+ deleteAccountDone: '계정이 삭제되었고 로그아웃되었습니다.',
135
+ deleteAccountDoneLocalFailed:
136
+ '계정은 삭제되었지만 이 기기의 로그인 정보를 지우지 못했습니다. 앱 데이터를 지우거나 앱을 다시 설치하세요.',
137
+ deleteAccountSessionEnded: '세션이 종료되었습니다. 계정 삭제가 완료되었을 가능성이 높습니다.',
138
+ deleteAccountNeedsSession: '계정을 삭제하려면 로그인하세요.',
139
+ deleteAccountUnavailable: '여기서는 계정을 삭제할 수 없습니다. 개인정보처리방침에 연결된 삭제 페이지를 이용하세요.',
140
+ deleteAccountFailed: '계정을 삭제하지 못했습니다. 다시 시도하세요.',
141
+ deleteAccountRejected: '계정을 삭제하지 못했습니다. 고객 지원에 문의하세요.',
57
142
  },
58
143
  } satisfies Record<Locale, Record<GameMessageKey, string>>;
59
144