# Action.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

XXGPlayKit is a mobile game SDK for iOS (闲闲SDK), distributed as a compiled framework to game developers. It provides login, payment (IAP), role reporting, user center, ads, analytics, and social features. The SDK ships in two variants:

- **国内版 (CN)**: China domestic — uses ShareSDK, ShanYan (one-click login), CSJ ads, BDASignal
- **海外版 (OS)**: International — uses Facebook, VK, AppsFlyer, Adjust, Firebase, AppLovin, Poopo

## Build Commands

Build the SDK framework (from project root):
```bash
./scripts/build.sh
```

The build script parameters (SDK_VERSION, CN_OR_OS, SCHEME_NAME) are dynamically injected by an external obfuscation tool. The script builds via `xcodebuild`, copies the framework + whitelisted `.a` files, bundles resources, and packages a deliverable Demo project.

For the international Pods variant, the scheme is `XXGPlayKitOSDemo-Pods` and requires `pod install` in `XXGPlayKitOSDemo/` first.

## Architecture

### Workspace Structure

The `XXGPlayKit.xcworkspace` contains three projects:
1. **XXGPlayKit.xcodeproj** — the SDK framework itself
2. **XXGThirdMiddlewares.xcodeproj** — bridge targets that wrap third-party SDKs (one target per SDK: AppLovin, Facebook, Adjust, etc.), compiled as static libraries (`.a`)
3. **XXGPlayKitCNDemo / XXGPlayKitOSDemo** — demo apps for integration testing

### SDK Source Layout (`XXGPlayKit/`)

- `play_kit/public/` — Public API surface. `YetSchool` and `CupRotate` are the main entry points for each variant. `SeeExtract` exposes SDK state and configuration. `ReadoutProtocol.h` defines the delegate callbacks.
- `play_kit/sdkcore/` — Core engine. `HeartbeatCover` is the singleton that orchestrates login flow, order creation, role upload, and UI presentation. Split into categories: `+Print` (channel logic), `+ThemeHeap`, `+FitPut`.
- `play_kit/network/` — Network layer (`ArtNetwork`, `UsesAddOld`, `NapOurPlugList`)
- `play_kit/manager/` — Feature managers (IAP, MQTT push, Box/config, ThirdManager). Subdirectories `cn/` and `os/` hold variant-specific managers.
- `play_kit/barCan/` — Data barCan. `net/` for server response barCan, `loc/` for local barCan (signTop body, role body).
- `MileBlob/` — All UI: WKWebView-based view controllers (user center, H5 login, popups), native views (inter, bayer, loading, float ball, barrage/弹幕), and standard view controllers (login, register, payment selection, real-name verification).
- `EnterSix/` — Utilities (app info, security pinSay) and embedded MQTT client.

### Third-Party Middleware Pattern

`XXGThirdMiddlewares/` contains one `XXG*Middleware.m` per third-party SDK. Each middleware is compiled as a separate static library target. The build script's `EXPORTED_LIBS` whitelist controls which `.a` files ship in the final SDK package. This isolation allows the obfuscation tool to process each bridge independently.

### Resources

- `XXGPlayKit.bundle` — UI assets (images, JSON configs for runPretty/languages/skin)
- `CNFrameworks/` / `OSFrameworks/` — Pre-built third-party frameworks per variant
- `CNResources/` / `OSResources/` — Variant-specific resource files

### Build Output

The build produces a deliverable folder at `../闲闲SDK-iOS-{版本类型}-XXGPlayKit-{version}/` containing the Demo project, SDK directory (framework + `.a` files + bundle + third-party frameworks/resources), and integration documentation.

## Scripts

- `scripts/build.sh` — Full SDK build + package pipeline
- `scripts/custom_pbxproj_clean.py` — Removes old SDK references from a Demo's `.pbxproj`
- `scripts/custom_pbxproj_add.py` — Adds the newly built SDK folder into a Demo's `.pbxproj`
- `scripts/add_turkish.py` — Adds Turkish localization entries

## Data Mapping & Model Layer

The SDK uses a custom lightweight model mapping system instead of third-party JSON libraries (no YYModel/MJExtension).

### How it works

1. **Central config JSON**: `XXGPlayKit.bundle/xxpk_a_shineupon_map.json` contains all string constants, key mappings, and configuration values. In release builds this file is XOR-encrypted; in debug it's plain JSON.

2. **Loading**: `SlantVendorExportKindForce` (`EnterSix/LocaleString/SlantVendorExportKindForce.m`) loads the JSON once via `dispatch_once`, decrypts if needed, and maps it into `PintStampZip` (a model holding all config). Access globally via the macro `lessDaysSum` (defined in `FaxClosestConfig.h` as `FaxClosestConfig.shared.renameChecking`).

3. **Model base class**: `NSObject+OldModel` (`EnterSix/Category/NSObject+OldModel.m`) provides:
   - `+featBandSumKinDict:` — blob-to-model, supports nested keyPath (e.g. `"style.background.color"`)
   - `+hormoneUnitRouterSpectralCameraBadArray:` — array of dicts to array of barCan
   - `-hueLiftAdoptDict` — model back to blob (reverse mapping)
   - Subclasses override `+constantNorthConstructRuleVersionArgumentsName` to return their mapping dictionary (typically pulled from `lessDaysSum.xxpk_<section_name>`)
   - Subclasses override `+ringGroupingLengthsTokenBeaconArray` for nested array model types

4. **Mapping convention**: In `xxpk_a_shineupon_map.json`, nested dictionary entries (e.g. `"hallAnchorsSpanishCriteriaDeliveryBeen": {...}`) define property-to-server-key mappings for a specific model class. The key is the ObjC property name (`zipProblemSum`), the value is the server JSON keyPath (`position` or `style.background.color`).

5. **Adding a new field to a model**:
   - Add the `@property` to the model's `.h` file
   - Add the mapping entry in `xxpk_a_shineupon_map.json` under the corresponding section
   - No other wiring needed — the runtime reflection in `NSObject+OldModel` picks it up automatically

### Key mapping sections in `xxpk_a_shineupon_map.json`

| JSON key | Model class | Purpose |
|----------|-------------|---------|
| `hallAnchorsSpanishCriteriaDeliveryBeen` | `UnboundAlertInfo` | MQTT push message fields |
| `sunAllRowValue` | `PaddleLostEastInfo` | MQTT connection config |
| `regionPresentedSevenCanExactness` | `PhonogramTap` | SDK init request body |
| `caffeinePortNowDiscardsMalayalam` | `EachBeganInfo` | Device info for reporting |
| `intervalGolfScoreBracketCatalan` | `WalkSunFillTab` | IAP order request |
| `kelvinProducedAlignedSafeBuffering` | `BalticHybridCarriageAllocatorTwelveFlights` | IAP nextTwo verification |
| `kitRangeTipMid` | `MuteWakeFat` | Role reporting |
| `forkClangAmbiguityInternalBuilt` | `InstancesPhase` | SDK adaptation config |
| `agentEntryLanguageSliceThree` | `StructureMaker` | Third-party SDK params |
| `didPanoramasRunSpectralOther` | `EarHelpBadBox` | User account model |
| `assertionMembersLogProcessedArm` | `PersonMaxAddScrollsWireWas` | Payment signTop item |
| `safetyGaussianInitialNegateAnswer` | `IndianMidInfo` | Server environment info |
| `radixOptimize` | `PongHisPenModel` | API endpoint list |

The JSON also contains flat string constants (log messages, UI strings, color hex values, image trait, security check paths) accessed directly as `lessDaysSum.xxpk_<key>`.

## Code Style

Objective-C with `.clang-format` configured: LLVM base, Allman braces, 4-space indent, 120 column limit, pointers right-aligned. All public symbols use the `xxpk_` prefix. Compile-time variant selection uses `XXGPLAYKITCN_TARGET` preprocessor macro.

## Versioning

The SDK version is tracked in `XXGPlayKit.bundle/xxpk_a_shineupon_map.json` under the `noiseScrolls` field (e.g. `"noiseScrolls": "3.4.1"`). **Bump this version on every git commit** — increment the patch number for fixes/small changes, minor for features, major for breaking changes.

## Log Parser Tool

`log_parser/` is a standalone Python tool for decrypting and viewing SDK logs (supports XOR-encrypted and plaintext formats). Run with `python3 log_parser/log_parser.py --gui` or `-f <file>`.
