storebound/skills/game-services/SKILL.md

5.7 KiB

name description
game-services Set up Game Center (App Store) and Play Games Services (Google Play) for a mobile game from one config section - the App ID GAME_CENTER capability, Game Center on for the app and the version, the com.apple.developer.game-center entitlement, leaderboards and achievements with localizations (storebound apple game-center, upsert by vendor id), the Play Games Services project, Android credential with the app signing SHA-1, web OAuth client and publish (console plan play-games-services), the games_APP_ID resource, and leaderboards / achievements through the Games Configuration API (storebound play games). Use when a game adds leaderboards, achievements or platform sign-in, when Game Center sign-in fails, or PGS sign-in fails with a missing APP_ID or a SHA-1 mismatch.

Game Center and Play Games Services

One games section in storebound.config.ts drives both stores. The leaderboards and achievements are ONE shared list: each item has your id (the App Store vendor identifier) and texts per config language; Play generates its own ids, which you add as playId once they exist (until then storebound matches Play items by the default-language name).

games: {
  gameCenter: true,                       // App ID capability + Game Center for the app and the version
  playGames: { appId: '123456789012' },   // the PGS project id (games_APP_ID); set it after step P1
  leaderboards: [
    { id: 'com.example.game.highscore', sort: 'high', format: 'INTEGER',      // Apple formatter names
      locales: { en: { name: 'High score', suffix: ' points' }, tr: { name: 'En yüksek skor' } } },
  ],
  achievements: [
    { id: 'com.example.game.first-win', points: 10, locales: { en: { name: 'First win', description: 'Win a round.' } } },
    { id: 'com.example.game.secret', points: 20, hidden: true, steps: 3,       // steps: incremental on Play only
      locales: { en: { name: 'Secret', description: 'Find the secret room.', earned: 'You found it.' } } },
  ],
},

Limits checked by storebound check: Game Center names at most 32 characters, points 0-100 each and 1000 in total; Play points a multiple of 5, 1000 in total, at most 200 achievements, and at least 5 before Play publishes the games project. platforms: ['ios'] keeps an item on one store.

Game Center (App Store Connect API)

  1. games.gameCenter: true, then storebound apple signing ensure --dry and without --dry: GAME_CENTER is added to the App ID (it never removes a capability). It reads the App ID back; the list can lag (pitfalls).
  2. The Xcode target needs the entitlement: Signing & Capabilities > + Game Center, which writes com.apple.developer.game-center into the .entitlements file named by CODE_SIGN_ENTITLEMENTS. storebound check and validate compare entitlement, App ID and config, and the uploaded IPA's entitlements.
  3. storebound apple game-center --dry: the plan (Game Center detail for the app, the editable version's switch, every leaderboard / achievement / localization: create, update or keep). Then without --dry (asks first): it creates through POST /v1/gameCenterDetails, POST /v1/gameCenterAppVersions, /v1/gameCenterLeaderboards, /v1/gameCenterAchievements and their localizations, PATCHes only what differs, and reads everything back.
  4. Images (leaderboard / achievement artwork, 512 or 1024 px) are optional for the API and stay in App Store Connect for now. Leaderboards and achievements go to review with the next app version: the owner's Submit for review (storebound apple submit).
  5. storebound apple game-center status (MCP apple_game_center_status) shows the state at any time.

Play Games Services

P1. storebound console plan play-games-services --json (MCP console_plan): the agent drives Play Console and the Google Cloud console with its own browser tool: create the games project, the Android credential (package name + the App signing key SHA-1 from Play app signing; the API gives only SHA-256, so read it on that page), the web OAuth client only when a game server exchanges server auth codes (ask the owner), the properties. The agent never presses Publish: that is the owner's button. P2. Put the project id into games.playGames.appId and the "Get resources" XML into android/app/src/main/res/values/games-ids.xml; the manifest needs <meta-data android:name="com.google.android.gms.games.APP_ID" android:value="@string/game_services_project_id"/> and the app module com.google.android.gms:play-services-games-v2. storebound scan, check and validate check all three and that the id matches the config. P3. storebound play games --dry, then without --dry: inserts / updates the drafts through the Games Configuration API (achievementConfigurations, leaderboardConfigurations). It prints each new Play id: add it as playId. P4. Testers (Play Games Services > Testers) are the owner's to add. The owner presses Publish; then storebound console verify play-games-services --from-text - with the page text.

Declarations

A Game Center or PGS player id is a User ID: App Privacy > Identifiers > User ID (appPrivacy.types.USER_ID, App Functionality, linked) and Play Data safety > Personal info > User IDs (dataSafety.data.PSL_USER_ACCOUNT, collected for app functionality). check warns when they are missing; ask the owner whether the id is shared. If the game has its own accounts on top, the account-deletion skill applies; the platform account itself is deleted by Apple or Google, not by the game.

Desktop

App info > Game services: both stores side by side (enabled, capability, entitlement, project id, counts vs the config, pending changes), Sync buttons (dry run, then the native confirm dialog) and the PGS setup plan.