@mpgd/cli 0.57.0 → 0.59.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/capacitor-shell-starter.d.ts +30 -0
- package/dist/capacitor-shell-starter.js +243 -11
- package/dist/index.js +170 -11
- package/dist/legal-site-output.d.ts +18 -0
- package/dist/legal-site-output.js +46 -1
- package/dist/native-build-info.json +2 -2
- package/dist/native-build-target.js +1663 -899
- package/dist/native-deploy-run.js +4 -0
- package/dist/native-shell-store-policy.d.ts +123 -0
- package/dist/native-shell-store-policy.js +816 -0
- package/dist/release-state.d.ts +2 -0
- package/dist/release-state.js +4 -2
- package/dist/testflight-submission.d.ts +9 -0
- package/dist/testflight-submission.js +69 -0
- package/package.json +17 -17
- package/templates/lite-overlay/agent/acceptance.md +1 -1
- package/templates/lite-overlay/agent/brief.md +1 -1
- package/templates/lite-overlay/src/lite/deleteAccountButton.ts +173 -0
- package/templates/lite-overlay/src/lite/restorePurchasesButton.ts +63 -0
- package/templates/lite-overlay/src/runtime/createGame.ts +8 -0
- package/templates/notifications-overlay/common/docs/NOTIFICATIONS.md +12 -6
- package/templates/notifications-overlay/common/notifications/deployment.json +2 -1
- package/templates/notifications-overlay/common/notifications/topics.json +3 -0
- package/templates/notifications-overlay/common/src/platform/capacitorNotifications.ts +8 -3
- package/templates/notifications-overlay/common/src/platform/notifications.ts +17 -3
- package/templates/phaser-game/README.md +72 -0
- package/templates/phaser-game/agent/acceptance.md +4 -1
- package/templates/phaser-game/agent/brief.md +14 -4
- package/templates/phaser-game/gitignore +11 -0
- package/templates/phaser-game/legal/delete-account.html +133 -0
- package/templates/phaser-game/legal/privacy.html +111 -12
- package/templates/phaser-game/legal/support.html +1 -0
- package/templates/phaser-game/legal/terms.html +1 -0
- package/templates/phaser-game/mpgd.game.json +3 -0
- package/templates/phaser-game/src/env.d.ts +6 -0
- package/templates/phaser-game/src/i18n/messages.ts +86 -1
- package/templates/phaser-game/src/main.ts +69 -8
- package/templates/phaser-game/src/platform/commerceAccountBinding.ts +39 -10
- package/templates/phaser-game/src/platform/deleteAccount.ts +334 -0
- package/templates/phaser-game/src/platform/gameServices.ts +55 -10
- package/templates/phaser-game/src/platform/guestIdentity.ts +301 -0
- package/templates/phaser-game/src/platform/restorePurchases.ts +205 -0
- package/templates/phaser-game/src/platform/serverSession.ts +8 -0
- package/templates/phaser-game/src/platform/sessionGatedServices.ts +217 -0
- package/templates/phaser-game/src/scenes/LobbyScene.ts +254 -1
- 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
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
session
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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>
|
|
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
|
-
|
|
68
|
-
|
|
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
|
-
|
|
74
|
-
contact
|
|
172
|
+
[REPLACE: support email or form, postal address, and data protection
|
|
173
|
+
contact if required.]
|
|
75
174
|
</p>
|
|
76
175
|
</main>
|
|
77
176
|
</body>
|
|
@@ -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
|
|