diff --git a/3DTank/docs/ArchitectureModules.md b/3DTank/docs/ArchitectureModules.md new file mode 100644 index 0000000..fe702ac --- /dev/null +++ b/3DTank/docs/ArchitectureModules.md @@ -0,0 +1,472 @@ +# 3DTank 架构模块调研 + +> 本文件内容全部由 `3DTank/names/module-graph.json` 的数据生成(一次性内联 node 命令,仓库不保留生成脚本);计数、依赖、分层均非手工绘制。 + +## 1. 总览 + +- 模块总数:**126**(均为 webpack 代码模块;index.json 中其余条目是资源模块,不在本调研范围) +- 按 Kind:游戏本体 **40** / Kotlin生态库 **22** / 第三方库 **64** +- 依赖边总数:**533**;孤立模块(无出度且无入度):**3** 个 +- 依赖层次最深(最长依赖链):**Level 17** + +### 1.1 依赖与结构的抽取方法(覆盖率) + +- **依赖(DependsOn)**:取模块工厂第 3 个参数作为 webpack require(形如 `(t, n, i) => {` 里的 `i`),再扫描 `i()` 静态调用,且 id 必须命中已知代码模块 id 集合。**126/126 模块都执行了抽取**,其中 **97 个模块抽到 ≥1 条边(77%)**;**29 个模块 DependsOn 为空**,原因是:24 个模块工厂只有 1~2 个参数(编译产物里根本没有 require 参数),5 个模块有 require 参数但源码无静态 `i()` 调用(7793、14766、17323、55920、94965;其中 55920 用 `t.require(n)` 动态取模块,无法静态解析)。`index.json` 只含 id/type/path,**不含依赖信息**,故依赖全部来自源码扫描。 +- **Kind**:按 dir.file 职责描述判定。职责点名可识别外部包/产品(React、ReactDOM、Scheduler、Sentry、qrcode、fflate、Emotion、underscore、inline-style-prefixer、prop-types、react-is、react-list、hoist-non-react-statics、@preact/signals-react、WebViewJavascriptBridge、Google Play Billing、Yandex Metrica、Dijkstra 库等)→ 第三方库;Kotlin/JS 编译出的通用基础设施(kotlin-stdlib、kotlinx.serialization、kotlinx.coroutines、atomicfu、ByteBuffer、DOM/CSS 构建器、RBuilder、Kotlin<->React 桥、kotlin-redux 框架核心、通用工具模块)→ Kotlin生态库;其余游戏业务逻辑(客户端、协议编解码、模型注册、UI/HUD、战斗、资源、音频、埋点、游戏引擎、启动入口)→ 游戏本体。规则表已写死为显式 id 列表,126 个模块全部命中、无默认兜底。 +- **Anchors**:优先取字符串字面量(长度 3~90,滤掉 HTML/CSS 噪声词与纯符号/数字串,CSS 函数名如 `image-set(` 保留),按 `跨模块出现次数`(仅 1 个模块出现 +4、≤3 个 +2、>40 个 -4)+ `错误信息关键词`(not found / exception / invalid / failed / unknown 等 +5)+ `camelCase 标识符`(+4)打分取前 5;**字面量不足 3 个时**用该模块内出现次数少的高辨识度标识符(导出名 / 属性名,如 `getPositions`、`createRoot`)补齐,纯转发模块补转发目标 `i()`。仍有 6 个模块(17323、19074、29545、31584、58309、99295)没有任何可用锚点,其 `Anchors` 为空数组(不编造)。 +- **顶层类/函数**:统计最浅缩进层的 `function NAME(` 声明(Kotlin/JS 产物会把函数声明提升到同一层);名称首字母大写计入 TopLevelClasses(Kotlin 类名 PascalCase,压缩后仍有大写开头,如 71105 中可见 `ResourceBatchLoadException`),其余计入 TopLevelFunctions。这是启发式口径,非精确语义。 + +### 1.2 代码量分布(按字节 Top 20) + +| # | 模块 | 字节 | KB | Kind | +|---|---|---|---|---| +| 1 | `module_82347` | 5498676 | 5370 | 游戏本体 | +| 2 | `module_87072` | 3775340 | 3687 | 游戏本体 | +| 3 | `module_10032` | 1536764 | 1501 | 游戏本体 | +| 4 | `module_85183` | 1176860 | 1149 | 游戏本体 | +| 5 | `module_92980` | 822309 | 803.0 | 游戏本体 | +| 6 | `module_47243` | 534291 | 521.8 | 游戏本体 | +| 7 | `module_71105` | 372886 | 364.1 | 游戏本体 | +| 8 | `module_21300` | 355930 | 347.6 | 游戏本体 | +| 9 | `module_37036` | 347491 | 339.3 | Kotlin生态库 | +| 10 | `module_18334` | 303005 | 295.9 | 游戏本体 | +| 11 | `module_70130` | 293925 | 287.0 | 游戏本体 | +| 12 | `module_85196` | 235678 | 230.2 | 游戏本体 | +| 13 | `module_45555` | 224856 | 219.6 | 第三方库 | +| 14 | `module_36659` | 182712 | 178.4 | 游戏本体 | +| 15 | `module_63383` | 177741 | 173.6 | Kotlin生态库 | +| 16 | `module_55088` | 148469 | 145.0 | 游戏本体 | +| 17 | `module_52943` | 145059 | 141.7 | Kotlin生态库 | +| 18 | `module_3569` | 141181 | 137.9 | 游戏本体 | +| 19 | `module_9539` | 131066 | 128.0 | Kotlin生态库 | +| 20 | `module_30285` | 123696 | 120.8 | 第三方库 | + +## 2. 依赖图摘要 + +### 2.1 入度 Top 15(被最多模块依赖) + +| 模块 | 入度 | Kind | 职责 | +|---|---|---|---| +| `module_37036` | 59 | Kotlin生态库 | Kotlin/JS 标准库(kotlin-stdlib-js)的运行时核心模块 | +| `module_52943` | 39 | Kotlin生态库 | 网页游戏/应用底层工具库,认设备,管键盘,翻译,报错,调用浏览器本地存储,服务管理 | +| `module_61860` | 24 | 游戏本体 | 网络连接与游戏对象模型的核心模块,Kotlin/JS 编译产物。它把客户端和服务端连接起来,并管理游戏对象的生命周期。 | +| `module_24635` | 24 | Kotlin生态库 | Kotlin/JS 二进制序列化/反序列化(Protocol Buffer 风格)编解码框架 | +| `module_32088` | 18 | 游戏本体 | Alternativa3D,3D 数学库,用 Kotlin 编写 | +| `module_71105` | 15 | 游戏本体 | 游戏资源加载系统(Resource Loader) | +| `module_89613` | 15 | Kotlin生态库 | Kotlin Coroutines (kotlinx.coroutines) 核心基础设施的 JS 移植版 | +| `module_31908` | 12 | 游戏本体 | 游戏战斗(Battle)域的协议编解码模块 | +| `module_92980` | 11 | 游戏本体 | 使用 WebGL 技术开发的3D 游戏引擎或大型 3D 交互应用的渲染核心模块 | +| `module_7552` | 10 | 第三方库 | 转发实现 | +| `module_85196` | 8 | 游戏本体 | 游戏车库(Garage)系统的协议编解码模块,属于同一个坦克对战类游戏。它负责定义和注册与“车库/装备/商店”相关的网络协议消息的二进制编解码器。 | +| `module_3569` | 8 | 游戏本体 | 游戏客户端的输入与坦克预览模块 | +| `module_85667` | 8 | 游戏本体 | 客户端协议编解码模块 | +| `module_88693` | 8 | 游戏本体 | 网络协议与数据模型层的实现,主要负责处理客户端与服务器之间关于社交、好友、举报、通知权限等非战斗数据的序列化与反序列化,并管理相关的网络路由和回调。 | +| `module_10849` | 8 | Kotlin生态库 | Kotlin/JS 编译后的 Redux 状态管理框架核心模块 | + +### 2.2 出度 Top 15(依赖最多模块) + +| 模块 | 出度 | Kind | 职责 | +|---|---|---|---| +| `module_82347` | 46 | 游戏本体 | 负责注册大厅、车库、商店、部落、战斗结算等几乎所有核心 UI 界面的组件样式与逻辑。 | +| `module_13431` | 46 | 游戏本体 | Kotlin/JS 编译后的游戏客户端启动入口模块,负责整个游戏的初始化、渲染和启动流程。 | +| `module_18334` | 28 | 游戏本体 | 游戏客户端的总装配/依赖注入模块 | +| `module_10032` | 25 | 游戏本体 | 游戏客户端核心 Redux 状态管理模块。Redux 架构 | +| `module_87072` | 24 | 游戏本体 | 战斗系统,底盘与物理系统,战斗模式,物品池和特效系统,空投与补给系统,地图与场景渲染 | +| `module_21300` | 19 | 游戏本体 | Kotlin/JS 游戏战斗内 HUD(战斗界面)与用户交互系统 | +| `module_70130` | 19 | 游戏本体 | 游戏战斗场景(Battle)的模型注册与初始化模块 | +| `module_71105` | 16 | 游戏本体 | 游戏资源加载系统(Resource Loader) | +| `module_84441` | 13 | 第三方库 | 负责把文本数据编码成 QR 码的模块矩阵。qrcode 库 | +| `module_47243` | 11 | 游戏本体 | 游戏客户端"面板(Panel)系统"的协议编解码模块,用 Kotlin 编写。它是整个项目中最大的协议模块之一,定义了面板 UI 相关的所有枚举、数据类、编解码器。 | +| `module_52943` | 9 | Kotlin生态库 | 网页游戏/应用底层工具库,认设备,管键盘,翻译,报错,调用浏览器本地存储,服务管理 | +| `module_24923` | 9 | Kotlin生态库 | CSS-in-JS 样式引擎(类似 styled-components / Emotion / Stitches 的实现),用 Kotlin 编写并编译成 JS。它负责在运行时动态生成、管理和注入 CSS,支持 React 组件样式、主题、媒体查询、动画等。 | +| `module_57128` | 9 | 游戏本体 | UI 交互与触控/鼠标手势处理模块 | +| `module_85183` | 8 | 游戏本体 | 定义并注册游戏中各种网络协议消息的编解码器(Codec),用于在客户端与服务器之间序列化/反序列化数据。 | +| `module_3569` | 8 | 游戏本体 | 游戏客户端的输入与坦克预览模块 | + +### 2.3 叶子模块(无出度,共 29 个) + +其中属于游戏本体的(1 个):`module_26482` + +其余叶子模块:`module_905`(第三方库)、`module_7793`(第三方库)、`module_13532`(第三方库)、`module_14766`(第三方库)、`module_15330`(第三方库)、`module_17259`(第三方库)、`module_17323`(第三方库)、`module_19074`(第三方库)、`module_21973`(第三方库)、`module_27736`(第三方库)、`module_29545`(第三方库)、`module_31509`(第三方库)、`module_31584`(Kotlin生态库)、`module_37036`(Kotlin生态库)、`module_38335`(第三方库)、`module_43319`(第三方库)、`module_44794`(第三方库)、`module_55920`(第三方库)、`module_57328`(第三方库)、`module_64280`(第三方库)、`module_66610`(第三方库)、`module_76074`(第三方库)、`module_77672`(第三方库)、`module_78231`(第三方库)、`module_78931`(第三方库)、`module_79763`(第三方库)、`module_94965`(Kotlin生态库)、`module_99295`(第三方库) + +### 2.4 孤立模块(既不被依赖也不依赖别人,共 3 个) + +- `module_26482`(0.7 KB,游戏本体)Service Worker 注册模块 +- `module_76074`(1.4 KB,第三方库)Yandex Metrica(俄版 Google Analytics)的集成模块,用于加载分析脚本并暴露事件上报接口。 +- `module_78231`(5.2 KB,第三方库)WebView JavaScript Bridge 的加载与实现模块,用于原生 App(iOS/Android)与网页之间的双向通信。 + +## 3. 游戏本体模块逐条(40 个) + +### `module_82347`(5370 KB) +- 职责:负责注册大厅、车库、商店、部落、战斗结算等几乎所有核心 UI 界面的组件样式与逻辑。 +- 依赖的模块:`59411`, `7552`, `40293`, `28485`, `1901`, `14766`, `37036`, `52943`, `59131`, `90875`, `24923`, `61860`, `10032`, `57128`, `18334`, …(共 46 个) +- 顶层类 / 其它顶层函数:5256 / 5656 +- 锚点:`imageBackgroundMessageError`、`getDerivedStateFromError`、`commonBlockMessageError` + +### `module_87072`(3687 KB) +- 职责:战斗系统,底盘与物理系统,战斗模式,物品池和特效系统,空投与补给系统,地图与场景渲染 +- 依赖的模块:`37036`, `52943`, `61860`, `24635`, `85183`, `61378`, `10032`, `10849`, `32088`, `31908`, `72834`, `55088`, `3569`, `92980`, `97556`, …(共 24 个) +- 顶层类 / 其它顶层函数:3094 / 3327 +- 锚点:`Invalid weapon effect timings`、`Mesh texture not found`、`Invalid supply type ` + +### `module_10032`(1501 KB) +- 职责:游戏客户端核心 Redux 状态管理模块。Redux 架构 +- 依赖的模块:`37036`, `10849`, `9539`, `52943`, `61430`, `31908`, `89803`, `47243`, `85667`, `88693`, `54199`, `41164`, `99527`, `85196`, `31584`, …(共 25 个) +- 顶层类 / 其它顶层函数:1100 / 1196 +- 锚点:`FPS seems awful but cannot decrease the settings`、`Not found params for property `、`Unexpected response status ` + +### `module_85183`(1149 KB) +- 职责:定义并注册游戏中各种网络协议消息的编解码器(Codec),用于在客户端与服务器之间序列化/反序列化数据。 +- 依赖的模块:`37036`, `24635`, `71105`, `61860`, `31908`, `32088`, `85196`, `52943` +- 顶层类 / 其它顶层函数:1164 / 1241 +- 锚点:`pointCaptureStartNegativeSound`、`pointCaptureStartPositiveSound`、`pointCaptureStopNegativeSound` + +### `module_92980`(803.0 KB) +- 职责:使用 WebGL 技术开发的3D 游戏引擎或大型 3D 交互应用的渲染核心模块 +- 依赖的模块:`52943`, `37036`, `32088`, `97556`, `72834`, `9345` +- 顶层类 / 其它顶层函数:494 / 534 +- 锚点:`Cannot use default vertex array object`、`Cannot create empty LodGroup`、`Cannot remove last layout` + +### `module_47243`(521.8 KB) +- 职责:游戏客户端"面板(Panel)系统"的协议编解码模块,用 Kotlin 编写。它是整个项目中最大的协议模块之一,定义了面板 UI 相关的所有枚举、数据类、编解码器。 +- 依赖的模块:`37036`, `24635`, `71105`, `31908`, `52943`, `25377`, `85196`, `85667`, `61860`, `88693`, `99527` +- 顶层类 / 其它顶层函数:605 / 643 +- 锚点:`disabledNotificationTypes`、`expireActiveTimeRewards`、`expireRewardTimeRewards` + +### `module_71105`(364.1 KB) +- 职责:游戏资源加载系统(Resource Loader) +- 依赖的模块:`37036`, `9539`, `89613`, `52943`, `61860`, `24635`, `9345`, `92980`, `32088`, `72834`, `16100`, `61430`, `36734`, `97556`, `7426`, …(共 16 个) +- 顶层类 / 其它顶层函数:226 / 250 +- 锚点:`Unexpected 3D file format for `、`Invalid file extension `、`Unknown resource type ` + +### `module_21300`(347.6 KB) +- 职责:Kotlin/JS 游戏战斗内 HUD(战斗界面)与用户交互系统 +- 依赖的模块:`7552`, `36659`, `82347`, `37036`, `24923`, `3569`, `10032`, `59131`, `52943`, `63383`, `10849`, `7426`, `90875`, `41164`, `31908`, …(共 19 个) +- 顶层类 / 其它顶层函数:348 / 385 +- 锚点:`containerUserNickNameClanTag`、`commonContainerIconOptions`、`inputContainerSpectators` + +### `module_18334`(295.9 KB) +- 职责:游戏客户端的总装配/依赖注入模块 +- 依赖的模块:`37036`, `37504`, `10849`, `52943`, `10032`, `61860`, `47243`, `85667`, `88693`, `10283`, `85196`, `32088`, `3569`, `71105`, `99527`, …(共 28 个) +- 顶层类 / 其它顶层函数:237 / 266 +- 锚点:`vkInitFailed`、`initError`、`Cannot find SteamAPI for SteamPaymentModel` + +### `module_70130`(287.0 KB) +- 职责:游戏战斗场景(Battle)的模型注册与初始化模块 +- 依赖的模块:`37036`, `52943`, `61860`, `87072`, `10032`, `92980`, `61378`, `31908`, `85183`, `10849`, `3569`, `36734`, `97556`, `32088`, `71105`, …(共 19 个) +- 顶层类 / 其它顶层函数:260 / 280 +- 锚点:`onGrahpicsSettingsChange`、`onBattleSettingsChange`、`lightingEffectService` + +### `module_85196`(230.2 KB) +- 职责:游戏车库(Garage)系统的协议编解码模块,属于同一个坦克对战类游戏。它负责定义和注册与“车库/装备/商店”相关的网络协议消息的二进制编解码器。 +- 依赖的模块:`37036`, `24635`, `71105`, `85667`, `32088`, `61860`, `52943` +- 顶层类 / 其它顶层函数:312 / 342 +- 锚点:`staticCollisionBoxes`、`mainCollisionBox`、`skyboxFrontSide` + +### `module_36659`(178.4 KB) +- 职责:游戏客户端的纹理/资源注册与加载系统 +- 依赖的模块:`37036`, `89613`, `52943`, `92980`, `71105` +- 顶层类 / 其它顶层函数:292 / 319 +- 锚点:`desktopHudNuclearRechargeFlashBackground`、`deviceFasterHorizontalTrackingRailgun`、`deviceFasterHorizontalTrackingVulcan` + +### `module_55088`(145.0 KB) +- 职责:物理引擎与碰撞检测系统,同样是 Kotlin/JS 编译产物。 +- 依赖的模块:`32088`, `37036`, `52943` +- 顶层类 / 其它顶层函数:105 / 112 +- 锚点:`Bound box size is zero`、`Negative mass`、`Level ` + +### `module_3569`(137.9 KB) +- 职责:游戏客户端的输入与坦克预览模块 +- 依赖的模块:`37036`, `32088`, `52943`, `92980`, `9345`, `55088`, `97556`, `7426` +- 顶层类 / 其它顶层函数:130 / 133 +- 锚点:`onPointerLockError`、`Cannot get free screen pointer!`、`Cannot find parent` + +### `module_37504`(104.5 KB) +- 职责:游戏客户端"氏族(Clan)系统"的协议编解码模块,用 Kotlin 编写 +- 依赖的模块:`37036`, `24635`, `52943`, `61860` +- 顶层类 / 其它顶层函数:103 / 110 +- 锚点:`Enum item not found for code `、`modelRegistry`、`modelService` + +### `module_61378`(92.7 KB) +- 职责:游戏世界(World)与实体-组件系统(ECS)的核心模块 +- 依赖的模块:`37036`, `52943`, `92980`, `3569`, `32088`, `55088`, `89613`, `97556` +- 顶层类 / 其它顶层函数:66 / 73 +- 锚点:`World.addGameEffect cannot add effect during update.`、`Cannot remove all while dispatching`、`Cannot dispose while dispatching` + +### `module_10283`(91.4 KB) +- 职责:Kotlin/JS 编译后的协议模型注册模块 +- 依赖的模块:`37036`, `24635`, `71105`, `52943`, `61860`, `67222` +- 顶层类 / 其它顶层函数:77 / 82 +- 锚点:`proBattlesLimitSound`、`socialNetworkParams`、`entranceBackgrounds` + +### `module_97675`(90.0 KB) +- 职责:WebView JS‑Native 双向通信桥(Bridge) +- 依赖的模块:`37036`, `52943`, `61430`, `9539`, `89613` +- 顶层类 / 其它顶层函数:30 / 53 +- 锚点:`Invalid result structure`、`checkUnfinishedPurchases`、`finishVerifiedPurchase` + +### `module_89803`(85.1 KB) +- 职责:游戏/应用中用于处理“匹配系统”和“对战大厅”网络通信和数据序列化的核心代码库。 +- 依赖的模块:`37036`, `24635`, `31908`, `61860`, `71105`, `85667`, `52943` +- 顶层类 / 其它顶层函数:78 / 91 +- 锚点:`matchmakingModeRanks`、`optionsDefaults`、`supportedModes` + +### `module_85667`(80.6 KB) +- 职责:客户端协议编解码模块 +- 依赖的模块:`37036`, `24635`, `71105`, `52943`, `61860` +- 顶层类 / 其它顶层函数:143 / 141 +- 锚点:`browserExtensionsToDetect`、`stateWithCaptcha`、`clientKey` + +### `module_32088`(79.7 KB) +- 职责:Alternativa3D,3D 数学库,用 Kotlin 编写 +- 依赖的模块:`37036`, `9539` +- 顶层类 / 其它顶层函数:26 / 35 +- 锚点:`Failed requirement.`、` + + this.z1z_1 + + `、` + + this.a20_1 + + ` + +### `module_31908`(77.2 KB) +- 职责:游戏战斗(Battle)域的协议编解码模块 +- 依赖的模块:`37036`, `24635`, `88693`, `52943`, `61860` +- 顶层类 / 其它顶层函数:104 / 110 +- 锚点:`experiencePremiumBonusByActions`、`suspiciousByIpUserIds`、`suspiciousUserIds` + +### `module_61860`(74.9 KB) +- 职责:网络连接与游戏对象模型的核心模块,Kotlin/JS 编译产物。它把客户端和服务端连接起来,并管理游戏对象的生命周期。 +- 依赖的模块:`24635`, `37036`, `52943`, `32088`, `72834`, `89613`, `61430`, `9539` +- 顶层类 / 其它顶层函数:69 / 72 +- 锚点:`Constructor codec not found for model `、`Param config-template not found in url`、`Config load exception with status ` + +### `module_9345`(69.5 KB) +- 职责:A3D 二进制 3D 模型格式 的完整解析器 +- 依赖的模块:`37036`, `72834`, `32088`, `97556` +- 顶层类 / 其它顶层函数:52 / 68 +- 锚点:`Unknown attribute type id `、`Unknown attribute type `、` not found ` + +### `module_89679`(58.4 KB) +- 职责:集成 Google Play 计费 API +- 依赖的模块:`89613`, `10032`, `37036`, `52943`, `97675`, `10849`, `56077`, `47243` +- 顶层类 / 其它顶层函数:32 / 32 +- 锚点:`Failed to complete payment response with fail`、`API not supported in this browser context`、`Unknown BridgeBillingService shop type` + +### `module_16100`(57.0 KB) +- 职责:Kotlin/JS 编译后的战斗地图(BattleMap)协议模型注册模块 +- 依赖的模块:`37036`, `24635`, `52943` +- 顶层类 / 其它顶层函数:74 / 82 +- 锚点:`collisionGeometryOutsideGamingZone`、`collisionGeometry`、`textureParameter` + +### `module_25377`(52.7 KB) +- 职责:游戏客户端与服务器之间的"通知/事件"协议编解码层,用 Kotlin 编写。它基于模块 24635 的二进制编解码框架,定义了所有服务器→客户端的通知消息类型及其序列化格式。 +- 依赖的模块:`37036`, `24635`, `31908`, `52943`, `61860`, `85667`, `99527` +- 顶层类 / 其它顶层函数:61 / 69 +- 锚点:`Enum item not found for code `、`wsProto`、`modelRegistry` + +### `module_13431`(46.6 KB) +- 职责:Kotlin/JS 编译后的游戏客户端启动入口模块,负责整个游戏的初始化、渲染和启动流程。 +- 依赖的模块:`30285`, `81886`, `37036`, `82347`, `21300`, `10032`, `89613`, `41164`, `52943`, `7426`, `3569`, `92980`, `10849`, `97675`, `61860`, …(共 46 个) +- 顶层类 / 其它顶层函数:44 / 38 +- 锚点:`onVisibilityChanged`、`lockScreenLandscape`、`requestFullscreen` + +### `module_36734`(40.5 KB) +- 职责:游戏客户端的音频系统,用 Kotlin 编写。它基于 Web Audio API 实现了完整的音效播放引擎,包括:音频解码、声道管理、优先级调度、3D 空间音效、音量/静音控制、分组增益 +- 依赖的模块:`37036`, `32088`, `52943`, `89613`, `7426` +- 顶层类 / 其它顶层函数:35 / 26 +- 锚点:`audioContextService`、`onChannelRecycled`、`effectiveGain` + +### `module_54199`(39.8 KB) +- 职责:游戏聊天系统的网络协议编解码模块 +- 依赖的模块:`37036`, `24635`, `88693`, `52943`, `61860` +- 顶层类 / 其它顶层函数:37 / 54 +- 锚点:`linksWhiteList`、`battleIdHex`、`battleLinks` + +### `module_88693`(34.3 KB) +- 职责:网络协议与数据模型层的实现,主要负责处理客户端与服务器之间关于社交、好友、举报、通知权限等非战斗数据的序列化与反序列化,并管理相关的网络路由和回调。 +- 依赖的模块:`37036`, `24635`, `52943`, `61860` +- 顶层类 / 其它顶层函数:27 / 49 +- 锚点:`Enum item not found for code `、`No enum constant projects.tanks.multiplatform.users.model.keys.KeyTypeEnum.`、`modelRegistry` + +### `module_1510`(30.9 KB) +- 职责:库Kotlin/JS 编译的支付/交易协议处理器模块 +- 依赖的模块:`37036`, `24635`, `52943`, `61860` +- 顶层类 / 其它顶层函数:31 / 47 +- 锚点:`questToAchievementMap`、`itemIdMap`、`Enum item not found for code ` + +### `module_57128`(29.9 KB) +- 职责:UI 交互与触控/鼠标手势处理模块 +- 依赖的模块:`14766`, `32088`, `37036`, `52943`, `31908`, `92980`, `71105`, `7426`, `59131` +- 顶层类 / 其它顶层函数:26 / 13 +- 锚点:`Not found icon for `、`getBattleModeLocalizedShortName`、`intertialScroll` + +### `module_45686`(15.0 KB) +- 职责:游戏客户端的模型注册与空间(Space)加载系统,用 Kotlin 编写。它负责把服务器下发的模型数据注册到客户端的模型注册表中,并管理"空间"(游戏场景/实例)的加载与切换。 +- 依赖的模块:`37036`, `61860`, `29554`, `52943`, `71105`, `24635` +- 顶层类 / 其它顶层函数:3 / 24 +- 锚点:`onError`、`gameTypeRegistry`、`modelRegister` + +### `module_41164`(13.2 KB) +- 职责:游戏客户端的分析(Analytics)与埋点系统,用 Kotlin 编写。它负责向多个分析平台(Google Analytics、Yandex Metrica、自有分析服务)上报用户行为事件,包括登录、注册、战斗开始、购买、教程进度等。 +- 依赖的模块:`37036`, `61430`, `97675`, `52943` +- 顶层类 / 其它顶层函数:8 / 22 +- 锚点:`currencyCode`、`ecommerce`、`substage` + +### `module_99527`(10.9 KB) +- 职责:Protobuf媒体编解码器 + 时间周期配置 + 参数校验 +- 依赖的模块:`37036`, `24635`, `52943`, `61860` +- 顶层类 / 其它顶层函数:20 / 11 +- 锚点:`FORBIDDEN`、`Enum item not found for code `、`modelRegistry` + +### `module_29554`(9.7 KB) +- 职责:游戏客户端的模型/对象数据加载协议编解码模块 +- 依赖的模块:`37036`, `24635`, `61860`, `71105`, `52943` +- 顶层类 / 其它顶层函数:18 / 0 +- 锚点:`modelsData`、`modelService`、`_loadDependencies_dependenciesCodec` + +### `module_67222`(8.1 KB) +- 职责:社交网络登录与账号绑定的网络协议模块 +- 依赖的模块:`37036`, `24635`, `52943`, `61860` +- 顶层类 / 其它顶层函数:19 / 2 +- 锚点:`failedRedirectUrl`、`codec_failedRedirectUrl`、`Enum item not found for code ` + +### `module_85745`(4.0 KB) +- 职责:资源图片帧动画相关的网络序列化 / 反序列化 +- 依赖的模块:`37036`, `24635`, `52943` +- 顶层类 / 其它顶层函数:5 / 2 +- 锚点:`Enum item not found for code `、` + + this.y1we_1 + + `、` + + this.z1we_1 + + ` + +### `module_26482`(0.7 KB) +- 职责:Service Worker 注册模块 +- 依赖的模块:无(DependsOn 为空) +- 顶层类 / 其它顶层函数:0 / 0 +- 锚点:`serviceWorker`、`SW registration failed: `、`manifest` + +## 4. 依赖层次(由 DependsOn 计算,非手工绘制) + +Level 定义:无依赖 = Level 0,否则 = 1 + 依赖的最大 Level(存在少量循环依赖,回边被递归守卫截断,取近似最长链)。 + +- **Level 0**(29 个):游戏本体 1 个(`26482`);Kotlin生态库/第三方库 28 个 +- **Level 1**(24 个):游戏本体 0 个;Kotlin生态库/第三方库 24 个 +- **Level 2**(16 个):游戏本体 1 个(`32088`);Kotlin生态库/第三方库 15 个 +- **Level 3**(10 个):游戏本体 0 个;Kotlin生态库/第三方库 10 个 +- **Level 4**(5 个):游戏本体 1 个(`9345`);Kotlin生态库/第三方库 4 个 +- **Level 5**(3 个):游戏本体 0 个;Kotlin生态库/第三方库 3 个 +- **Level 6**(5 个):游戏本体 4 个(`92980`、`55088`、`97675`、`36734`);Kotlin生态库/第三方库 1 个 +- **Level 7**(5 个):游戏本体 5 个(`3569`、`61860`、`16100`、`41164`、`85745`);Kotlin生态库/第三方库 0 个 +- **Level 8**(8 个):游戏本体 7 个(`71105`、`37504`、`61378`、`88693`、`1510`、`99527`、`67222`);Kotlin生态库/第三方库 1 个 +- **Level 9**(6 个):游戏本体 6 个(`36659`、`10283`、`85667`、`31908`、`54199`、`29554`);Kotlin生态库/第三方库 0 个 +- **Level 10**(5 个):游戏本体 5 个(`85196`、`89803`、`25377`、`57128`、`45686`);Kotlin生态库/第三方库 0 个 +- **Level 11**(2 个):游戏本体 2 个(`85183`、`47243`);Kotlin生态库/第三方库 0 个 +- **Level 12**(1 个):游戏本体 1 个(`10032`);Kotlin生态库/第三方库 0 个 +- **Level 13**(2 个):游戏本体 2 个(`87072`、`89679`);Kotlin生态库/第三方库 0 个 +- **Level 14**(1 个):游戏本体 1 个(`18334`);Kotlin生态库/第三方库 0 个 +- **Level 15**(2 个):游戏本体 2 个(`82347`、`70130`);Kotlin生态库/第三方库 0 个 +- **Level 16**(1 个):游戏本体 1 个(`21300`);Kotlin生态库/第三方库 0 个 +- **Level 17**(1 个):游戏本体 1 个(`13431`);Kotlin生态库/第三方库 0 个 + +### 4.1 骨架图(Mermaid,节点 = 入度最高的 12 个游戏本体模块 + 入口 `13431`/装配 `18334`,边取自 DependsOn 且两端都在节点集内) + +```mermaid +graph LR + N61860["61860"] + N32088["32088"] + N71105["71105"] + N31908["31908"] + N92980["92980"] + N3569["3569"] + N85196["85196"] + N85667["85667"] + N88693["88693"] + N10032["10032"] + N36734["36734"] + N36659["36659"] + N13431["13431"] + N18334["18334"] + N61860 --> N32088 + N71105 --> N61860 + N71105 --> N92980 + N71105 --> N32088 + N71105 --> N36734 + N31908 --> N88693 + N31908 --> N61860 + N92980 --> N32088 + N3569 --> N32088 + N3569 --> N92980 + N85196 --> N71105 + N85196 --> N85667 + N85196 --> N32088 + N85196 --> N61860 + N85667 --> N71105 + N85667 --> N61860 + N88693 --> N61860 + N10032 --> N31908 + N10032 --> N85667 + N10032 --> N88693 + N10032 --> N85196 + N10032 --> N32088 + N10032 --> N3569 + N10032 --> N36659 + N10032 --> N92980 + N10032 --> N36734 + N10032 --> N61860 + N36734 --> N32088 + N36659 --> N92980 + N36659 --> N71105 + N13431 --> N10032 + N13431 --> N3569 + N13431 --> N92980 + N13431 --> N61860 + N13431 --> N31908 + N13431 --> N85667 + N13431 --> N88693 + N13431 --> N85196 + N13431 --> N36734 + N13431 --> N71105 + N13431 --> N18334 + N13431 --> N36659 + N18334 --> N10032 + N18334 --> N61860 + N18334 --> N85667 + N18334 --> N88693 + N18334 --> N85196 + N18334 --> N32088 + N18334 --> N3569 + N18334 --> N71105 + N18334 --> N92980 + N18334 --> N31908 + N18334 --> N36734 +``` + +### 4.2 节点对照表 + +| 节点 | 入度 | 出度 | 职责 | +|---|---|---|---| +| `61860` | 24 | 8 | 网络连接与游戏对象模型的核心模块,Kotlin/JS 编译产物。它把客户端和服务端连接起来,并管理游戏对象的生命周期。 | +| `32088` | 18 | 2 | Alternativa3D,3D 数学库,用 Kotlin 编写 | +| `71105` | 15 | 16 | 游戏资源加载系统(Resource Loader) | +| `31908` | 12 | 5 | 游戏战斗(Battle)域的协议编解码模块 | +| `92980` | 11 | 6 | 使用 WebGL 技术开发的3D 游戏引擎或大型 3D 交互应用的渲染核心模块 | +| `3569` | 8 | 8 | 游戏客户端的输入与坦克预览模块 | +| `85196` | 8 | 7 | 游戏车库(Garage)系统的协议编解码模块,属于同一个坦克对战类游戏。它负责定义和注册与“车库/装备/商店”相关的网络协议消息的二进制编解码器。 | +| `85667` | 8 | 5 | 客户端协议编解码模块 | +| `88693` | 8 | 4 | 网络协议与数据模型层的实现,主要负责处理客户端与服务器之间关于社交、好友、举报、通知权限等非战斗数据的序列化与反序列化,并管理相关的网络路由和回调。 | +| `10032` | 7 | 25 | 游戏客户端核心 Redux 状态管理模块。Redux 架构 | +| `36734` | 7 | 5 | 游戏客户端的音频系统,用 Kotlin 编写。它基于 Web Audio API 实现了完整的音效播放引擎,包括:音频解码、声道管理、优先级调度、3D 空间音效、音量/静音控制、分组增益 | +| `36659` | 6 | 5 | 游戏客户端的纹理/资源注册与加载系统 | +| `13431` | 0 | 46 | Kotlin/JS 编译后的游戏客户端启动入口模块,负责整个游戏的初始化、渲染和启动流程。 | +| `18334` | 3 | 28 | 游戏客户端的总装配/依赖注入模块 | + +## 5. 未能确认 / 需注意的点 + +1. **dir.file 中有两处职责与源码内容不符**(JSON 的 Duty 仍按 dir.file 原样抄录,未擅自改写): + - `module_96480` 标注“Underscore.js 1.13.6”,但源码是 inline-style-prefixer 的 transition 前缀插件(`Webkit`/`Moz` 分支、`-webkit-`/`-moz-` 常量)。 + - `module_94965` 标注“ReactHTML HTML 标签构建器”,但源码是两段 UMD 包裹的 underscore 实现(导出映射含 `VERSION`、`restArguments`,字面量 `1.13.6`),且没有任何 `div`/`span` 等 HTML 标签字面量。 +2. 6 个模块的 `Anchors` 为空数组(源码里没有可用的稳定字面量,且没有高辨识度标识符):17323、19074、29545、31584、58309、99295。 +3. 5 个模块有 require 参数但抽不到依赖:7793、14766、17323、55920、94965。推测是 webpack 模块连接(concatenation)把 require 调用内联消除,或依赖指向资源模块 id(本调研只统计代码模块 id)。 +4. DependsOn 只覆盖静态 `i()` 调用:动态取模块(55920 的 `t.require(n)`)不计入;对 `static/` 资源模块的引用也不计入。 +5. 顶层类/函数是按缩进 + 首字母大写的启发式统计(`TopLevelClasses` 不等于真实 Kotlin 类数量,压缩后部分类名非 PascalCase);Kind 中有若干边界判定(如 89679 Google Play 计费、52943 通用工具库、94965)按“代码来源 + 职责”人工定案,规则见 1.1。 +6. 分层为最长依赖链的近似值:图中存在循环依赖,回边在递归中被截断,Level 仅供骨架参考。 diff --git a/3DTank/docs/ArchitectureRuntime.md b/3DTank/docs/ArchitectureRuntime.md new file mode 100644 index 0000000..9fe5725 --- /dev/null +++ b/3DTank/docs/ArchitectureRuntime.md @@ -0,0 +1,200 @@ +# 3DTank 客户端关键运行链路(逆向) + +范围:只覆盖「运行链路」这一半(启动/网络/状态/UI/渲染/空间)。模块依赖图见另一份产出。 +证据约定: +- `[证据]` = 有稳定字符串、协议表(`names/`)、导出表或代码结构佐证,可复现。 +- `[推断]` = 由调用点语义推出,未被字符串/表直接证实。 +- 行号 = `3DTank/src/module_XXXX.js` 当前美化后的行号。 + +权威旁证:`names/method_table.json`(681) / `downlink_table.json`(680 命令, 4 容器) / `uplink_table.json`(360) / `codec_fields.json`(643 codec, SlotTypes 394) / `regdump.json`(ModelReg=`mr`, SpaceReg=`or`, Conn=`ur`) / `command_alias.json`(Spaces 别名) / `evidence.json`(126 模块, 139 DI 服务名)。 + +--- + +## 1. 启动与引导 + +**起点**:`module_13431`(IIFE 首参为 `t.exports`,模块体内未见 `$_$` 导出赋值 = 纯副作用入口模块,被 bundler 首次 import 即执行) +**终点**:`app-root` 上挂载 React root,转入 React/Redux 屏幕切换 + +| # | 关键函数 | 做什么 | 可信度 | +|---|---|---|---| +| 1 | `module_13431:1657-1718` | 按 `location.host` 判定运行环境并写 config 键 `resources`/`config-template`/`balancer`:`3dtank.com`→`https://res.3dtank.com`、`https://c{server}.3dtank.com/config.xml`、`https://3dtank.com/s/status.js`;另有 test-eu / tankionline.com(EU) / 其它(location 同源) 分支 | `[证据]` | +| 2 | `module_13431:1727-1731` | `wt(t)` = Sentry.init,dsn `sentry.tankionline.com/33`,`environment="china"` | `[证据]` | +| 3 | `module_13431:1734-1742` | 组装 DI 容器 `new Ln(Fu())`,`Bn(St(Mn),…)`、`Bn(St(Un),…)`,暴露 `window.skipEntranceAnyKey`/`noLogoutConfirmation` | `[证据]` | +| 4 | `module_13431:1776-1786` | `In(Tn, ui().fy(), hn, si(), cb)` 启动引导协程 `ss`(状态机 `ss.r9` 在 1400-1435) | `[证据]` | +| 5 | `module_13431:1400` | 引导 case0:`fr(Fu())` = 网络子系统初始化(→ `module_61860:2710` `$_$.z`) | `[证据]` | +| 6 | `module_13431:1404` | `dr(pr(Fu(),"resources"), WeakRef)` = 资源加载器初始化(`dr`=`module_71105.$_$.v`) | `[证据]`(映射)/`[推断]`(语义) | +| 7 | `module_13431:578-597` `Vu()` | 依次 `new X().t80()` × 17:按固定顺序注册 17 个协议域的 codec | `[证据]` | +| 8 | `module_13431:1408` | `yr(Fu())` = 创建 Redux store(`yr = module_10032.$_$.w1r`,见 `13431:242`) | `[证据]` | +| 9 | `module_13431:1424` | `Qn().x74() < 3`(GLES<3)→ `Ju()` 降级根;否则走完整分支 | `[证据]` | +| 10 | `module_13431:625-637` `Xu`/`Ju` | `Ju`:移除 `#preloader`,`pt(document.getElementById("app-root")).render(Xi(hs))` 挂 React root | `[证据]` | +| 11 | `module_13431:638-643` `Zu` | 正式根:`pt(#app-root).render(Xi(cs))`(`pt = i.createRoot`,`i`= `module_81886` ReactDOM client,见 13431:78) | `[证据]` | +| 12 | `module_13431:644-734` `Qu` | 注册 `visibilitychange`、`pointerup`→`requestFullscreen`、`fullscreenchange`→`screen.orientation.lock("landscape")`、`resize` | `[证据]` | +| 13 | `module_13431:565-567` `Wu` | 原生桥就绪回调:取 DI `"serverConnector"` 并 `l7i(new _s(bridge))`,写入 `bridge/bridge_version` | `[证据]` | +| 14 | `module_13431:1517+`(`Is.n1h7` 分支,1270-1302) | 按 store 的 `screen` 字段 instanceof 分派渲染登录/车库/战斗等屏幕 | `[推断]` | + +**首次网络连接**:由步骤 5 的 `fr(config)` 触发——`module_61860:2710` `$_$.z(config)` 注册 `Ne` 协议并对 `ae`(网络协调器/balancer) 绑定 `yi`/`an`;`ae` 通过 `module_61860:2632` `new Ie(proto,host,port,…)` 建连。WebSocket 本体在 `Ie` 构造器 `module_61860:981-993`。`[证据]`(2710/981/992) + `[推断]`(「fr 即首个连接触发点」)。 + +--- + +## 2. 网络层 + +**起点**:`ae`(网络协调器,`module_61860:$_\$.z` 创建)→ `Ie`(单条 WebSocket 连接) +**终点**:`ModelReg.l7n` 把一帧记录派发到具体 model codec 的 `q7i`,状态写回 Redux + +**codec 注册顺序**(连接建立前一次性完成) +1. `module_13431:578` `Vu()`:顺序即 17 个 `new X().t80()` 的书写顺序。`[证据]` +2. 每个协议域的 `t80()`(例:`module_85183:23527` `Ln(fq).t80`)做两类注册: + - `modelService.h7n(Xn(ModelId), Xn(MethodId))` → 写 `ModelReg.v7n_1`(methodId→modelId)。`module_85183:23529` 起共 249 条;全工程 `h7n` ≈700 条,与 `method_table.json` 681 条对应。`[证据]` + - `.j7n(, .n7f(new TypeCodecInfo(kClass(类),!1)))` → 写 `ModelReg.w7n_1`(modelId→codec 实例),例 `module_85183:24559,24596,24784`。`[证据]`(与 `codec_fields.json.ModelIdBinding` 的说明逐字一致) +3. `module_29554:75-85` ModelService 自身的 4 个 methodId 槽位(`x1wc_1`…`e1wd_1` = `$(lo,hi)`:`163351191/191355032` 等),在 `module_29554:212-215` 用 `h7n` 绑定。`[证据]` +4. `module_61860:2716` `$_$.a1()` 注册基础类型 codec(`W/Ii/Ni/xr/K`)。`[证据]` + +**收到一帧后的分派**(分发链) +| # | 关键函数 | 做什么 | 可信度 | +|---|---|---|---| +| 1 | `module_61860:981-1012` `Ie` ctor | 拼 URL `proto://host:port/`,`new WebSocket`,`binaryType="arraybuffer"`,挂 `onopen/onclose/onmessage` | `[证据]` | +| 2 | `module_61860:1012-1030` `onmessage` | 建帧读取器 `m7t_1.f7m(frame,data)`,循环 `Ee(t).r7f(reader,frame)` 逐条解码,再交 `n7t_1.u7m(cmd)` | `[证据]` | +| 3 | `module_61860:2111-2131` `Vr.u7m` | **帧解析**:先读 nullmap 1 bit;bit=1 → 1 字节短命令查 `Gr(space)[255&k]`(`Gr`=DI `"aliases"`,写入点 `e7p` `module_61860:2146`);bit=0 → 读 `[objectId i64][methodId i64]`;随后 `this.x7o(objectId)` 取对象、`Br(this).l7n(modelId, methodId, buf)`。`Vr.toString`=`"Space(id=…)"`(2148) | `[证据]` | +| 4 | `module_61860:1681-1692` `mr.l7n` | **最终分发函数**:`v7n_1.z2(methodId)`→modelId,`u7n_1.z2(modelId)`→codec,`codec.q7i(methodId, buf)`;失败抛 `"Model not found for methodId = …, modelId = …"`(1685 字符串) | `[证据]` | +| 5 | `module_29554`(ModelService 4 命令) | 容器命令 `LoadDependencies`/`LoadObjectsData`/`UnloadObjects`/`SetModelCommandAlias` 的负载布局 = `names/downlink_table.json.Containers` 的 `zt/pt/lt/alias`;非按字段顺序,须走容器布局 | `[证据]`(表)/`未确认`(`zt/pt/lt` 具体类所在模块,见第 6 节) | +| 6 | `module_61860:1672-1680` `mr.i7n` | 注册对象实例:写主表 `s7n_1`、`modelId→实例 u7n_1`、`类→实例 t7n_1` | `[证据]` | + +**上行组帧发送(统一入口)** +| # | 关键函数 | 做什么 | 可信度 | +|---|---|---|---| +| 1 | `module_61860:2597-2613` `Ie.i7q(cmd)` | **唯一发送入口**:`l7t_1.o7g(bufReader, cmd)` 写字段 → `DataView` → `this.q7t_1.send(view)`;若中间件存在再包一层 | `[证据]` | +| 2 | `uplink_table.json` | 每条上行命令 = `Module`/`OwnerClass`/`SendFn`/`BufferField`/`Fields`;360 条命令的 `SendFn` 即该命令类自己的序列化方法 | `[证据]` | +| 3 | `module_24635` | 二进制序列化框架(`n7f`/`p7g`/`ptg`/`q7g` 家族),被 61860/85183/29554 共用 | `[推断]`(未取到行号锚点,见「未能确认」) | + +--- + +## 3. 状态管理(Redux) + +**起点**:`module_13431:1408` `yr(Fu())`(`yr = module_10032.$_$.w1r`) +**终点**:`store.qao(action)` 分发;`v8` 根 reducer 产出新 `TOState`;订阅组件更新 + +| # | 关键函数 | 做什么 | 可信度 | +|---|---|---|---| +| 1 | `module_10032:52887-52988` `$_$.w1r` | **store 创建点**:构造 3 个中间件(`Px`,`Vx` thunk,`i8()`)+ 初始 `TOState` + 根 reducer,`new rC(...)`,再 `Nx.ear(o)`/`Ox(ag(rC),o)` 注册进 DI | `[证据]` | +| 2 | `module_10032:1605` `rC` | store 子类,`ld.call(this,t,n,i)` 转发到框架基类(`ld` = `module_10849:91` `vt`) | `[证据]`(映射)/`[推断]`(参数角色) | +| 3 | `module_10849:91-119` `vt` | 框架 Store 构造:`this.lao_1=n`(reducer)、`this.pao_1=t`(initialState)、`this.mao_1`(订阅者),用 middlewares 折叠出 dispatch 链 `nao_1`;内层 `invokeReducer`(99-104) = `state = reducer(action, state)` 并通知订阅者 | `[证据]` | +| 4 | `module_10849:320` `qao` | **dispatch**(调用点:`module_13431:621` `as(t).qao(new Cr(i))`;`13431:819` `store.qao(new ue(p))`) | `[证据]` | +| 5 | `module_10032:14307-1440` `v8(action,state)` | **根 reducer**:逐切片委派 `T6().bt7(t,n.app_1)`、`cY().wry(t,n.bpp_1)`… 返回合并后的新状态 | `[证据]`(结构)/`[推断]`(`v8`=根 reducer) | +| 6 | `module_10032:6455-6471+` `sF` | 单个切片 reducer:`if (action instanceof X) return state.vrb(field=…)`,`vrb` = 数据类 `copy` | `[证据]` | +| 7 | `module_10032:43519-43650` `vd(w8).toString` | **根状态 = `TOState`**,字段名即根 reducer 字段(见下) | `[证据]` | +| 8 | `module_10032:52898-52903` | `thunkMiddleware`(`Vx`);`module_10849:748` 另有 `com.alternativaplatform.redux.middlewares.ConsoleDebug.DebugType.*` | `[证据]` | +| 9 | `module_10849:146-156` `$t` / `157-178` `jt` / `598` | 组件订阅表(`baq_1/caq_1`)+ 更新循环:`window.requestAnimationFrame(jt)` 调度,遍历订阅组件调 `j3t()` | `[证据]` | +| 10 | `module_10849:414,440,453,623` | 运行时断言:`"GameObject already subscribed! modelId="`、`"Model already subscribed!"`、`"Key already subscribed!"`、`"Component not subscribed"` → 订阅模型/键/组件 | `[证据]` | + +**根 reducer 字段(`TOState`,只列名)**: +`user, screen, modalScreen, battleStatistics, battleTutorial, garage, garagePreview, challenges, loginByPassword, register, migrationState, inviteState, captchaState, passwordChangeState, , system, quests, chatState, clanChatState, clan, clansStorage, tipsState, news, settings, accountSettings, lootBoxes, notifications, friends, remoteUserDataStorage, battlesSelect, maps, matchmaking, battleCreateState, battleSearchState, lobbyLoader, battleResult, battleUsers, suppliesState, matchmakingGroup, shop, battlePauseState, battleViewState, rankUpDialogState, clanUserInfo, tankActionsLogState, battleMessage, battleChat, droppableGold, home, localBattleUserState, soundSettings, gameSettings, battleSettings, graphicsSettings, controlSettings, securitySettings, purchaseDialogState, …, keyboardSettings, touchscreenHudSettings, mainQuest` + +**action 形态**:Kotlin 数据类,`new XxxAction(args)`(例 `module_13431:621` `new Cr(i)`、`new Er(!1)`、`new Tr(!1)`;`13431:819` `new ue(p)`);分派统一走 `store.qao(action)`(`module_10849:320`)。副作用机制 = 中间件,无 saga/effect 层。 + +--- + +## 4. UI 系统 + +**起点**:`module_90875`(RBuilder 核心)+ `module_09963`(`create()` 工厂) +**终点**:React 元素树 → `module_81886 createRoot().render()` + +| # | 关键函数 | 做什么 | 可信度 | +|---|---|---|---| +| 1 | `module_90875:23-53,130` `x(fn)` | 把「builder 回调」编译成 React 元素:`fn(RBuilderImpl)` → 取 children → `React.createElement` | `[证据]` | +| 2 | `module_90875:54-58` | 类名注册:`RBuilder`/`RElementBuilder`/`RBuilderImpl`/`RElementBuilderImpl`/`RComponent`(`RComponent` 继承 `React.Component`) | `[证据]` | +| 3 | `module_90875:59-115` | RBuilder API:`ban()`取 children、`can(t)`挂子、`ean`/`fan`建元素、`ian(KClass,λ)`按组件类型挂子、`gan(tag)`按标签建元素、`han(KClass,λ)`、`jan` 取 `Children.toArray`;`RElementBuilder`:`lan(key?)`/`man(key)`/`nan(ref)` | `[证据]` | +| 4 | `module_90875:76-78,67-75` | `RComponent.render()` → `uan()` → `x(this::tan)`:Kotlin 组件只需实现 `tan(RBuilder)` | `[证据]` | +| 5 | `module_90875:117-126` | `$_$.a`/`$_$.b` = RComponent 工厂(`ran`/`san` 初始化 state) | `[证据]` | +| 6 | `module_90875:131-145` | `$_$.g` = `React.forwardRef` 包装 | `[证据]` | +| 7 | `module_09963:21-32` | `create(name, fn)` = 函数组件工厂(`displayName=name`,渲染 `Fragment` 包裹的 children) | `[证据]` | +| 8 | `module_13431:774-784` | 最小真实组件渲染体示例(见下) | `[证据]` | +| 9 | `module_82347:1308-1311` | `hq = Co.$_$.c`、`fq = Co.$_$.kd`、`jq = Co.$_$.fd`(`Co` = 被 import 的 stdlib/UI 导出包) | `[证据]`(映射) | +| 10 | `module_37036:1249,1252,1257,1328` | `Qr`(=`fd`)=defineClass、`ne`(=`kd`)=**defineObject**、`ge`(=`cd`)=defineProperty/delegate、`te`=公共实现 | `[证据]` | + +**最小真实组件示例**(`module_13431:774-784`,去掉 Kotlin 的 `ps()` 初始化后即此形): +```js +function hs(t) { // t = RBuilder + return (ps(), t.gan(Ir()), Ct); // gan(tag) 建一个标签元素 +} +function cs(t) { + var n = St(Uu); // St(...) 取组件类 + return (t.ian(n, ls), Ct); // ian(组件类, 渲染λ) 挂子节点 +} +``` +另一形态是 `kt(Uu).tan = function(t){ t.ian(...) }`(`module_13431:1238+`):组件类实现 `tan(RBuilder)`。 + +**样式注入 / 类名生成** +- `module_24923` = CSS-in-JS 引擎:`StyledDOMBuilder`(626)、`Styled`(627)、`StyledDOMBuilderImpl`(628)、`globalThis.StyledNext`(716);类名与使用追踪见 `"UsedCssInfo(className=…, usedBy=…, groupId=…)"`(893)、`"CssInfo(isFresh=…, className=…)"`(913);注入点 `document.styleSheets`(650-655)。`[证据]` +- `module_63383` = CSS 类型核心:`"StyledElement"`(5792)、`"BorderStyle"`(5825)、`"FontStyle"`(5830)、`"ListStyleType"`(5844)、`"StyleList"`(5852)、`"StyledElementImpl"`(5855)。`[证据]` +- `module_59131` = kotlinx.html DSL(标签/属性构建),`module_50824` 用 `React.createElement`(`50824:14`)。`[证据]`(仅导入事实)/`未确认`(具体标签绑定行号) + +**`82347` 里 248 个 `fq(cls, "XxxStyle", …)` 是什么、谁消费(关键)** +- 它们是 **Kotlin `object` 声明**,不是组件、也不是 CSS 类名注册:`fq = Co.$_$.kd`,而 `module_37036:1257` `ne(t,n,…)` → `te("object", …)`,`te`(`module_37036:1252-1255`) 只做 `prototype`/`$metadata$` 挂载。所以 `fq(y7,"AnnouncementComponentStyle",hq,K$)` = 「定义一个名为 AnnouncementComponentStyle 的对象」。`[证据]` +- 数量实测:`module_82347` 内 `fq(` 442 次,其中带 `"…Style"` 字面量 248 次(与挖出的 267 个 `*Style` 类名同一来源)。`[证据]` +- **消费方**:这些 `*Style` 对象是 CSS 声明集合(`module_63383` 的 StyleList/StyledElement 树),由 CSS-in-JS 运行时(`module_24923` 的 `Styled`/`StyledDOMBuilderImpl`)在组件渲染时读取并生成 className、注入 `document.styleSheets`。`[推断]`(未抓到「某组件读某 Style 对象」的具体赋值行,见「未能确认」) +- 类似地 `module_13431:1128` `du(Gs,"StartScreenComponentStyle",hn,wu)`(`du = m.$_$.kd`)也是同一 defineObject 调用,印证命名族一致。`[证据]` + +--- + +## 5. 资源与渲染 + +**起点**:`module_13431:1404` `dr(, WeakRef 实现)` +**终点**:WebGL 提交(`module_92980`)由每帧 ticker 驱动 + +| # | 关键函数 | 做什么 | 可信度 | +|---|---|---|---| +| 1 | `module_45686:73-87` `ut` | DI 取 `"resourceLoaderService"` | `[证据]` | +| 2 | `module_45686:145-159` `gt` | DI 取 `"resourceRegistry"`(同一服务也被 `module_71105:12407` 取出并 `.z83()`) | `[证据]` | +| 3 | `module_71105`(`.z2(key)` 大量调用点,如 `4009/4048/4060/5475/5488`) | 资源按 **Map key 查表**:`registry.z2(key)`(Kotlin `Map.get`);未在任何模块发现字符串字面量 key(`module_36659` 内 `"…"` key 为 0),key 是对象/KClass 而非字符串 | `[证据]`(z2 即 Map.get、无字符串 key)/`[推断]`(key 具体类型) | +| 4 | `module_92980:20348,20357,20360` | WebGL 提交面:`clear(t)`、`drawElements(t,n,i,r)`、`drawElementsInstanced(...)`,全部转发到内部 GL 上下文对象 `b74_1` | `[证据]` | +| 5 | `module_52943:2284-2323` `Tc` | **帧循环**:`animationFrameCallback` 里 `tick(); requestAnimationFrame(自)` 自续;另有 33ms `setInterval` 后台计时(`Ec.m2o_1=33`)与 `visibilitychange` 切换 | `[证据]` | +| 6 | `module_36734:1460`、`module_70130:1225` | DI `"tickerService"` + `.u2f(callback, priority)`:游戏逻辑/音频按优先级挂每帧回调 | `[证据]` | +| 7 | `module_10849:157-178,598` | UI 侧每帧循环:`requestAnimationFrame(jt)` → 遍历订阅组件调 `j3t()`(与 3D ticker 是两条独立循环) | `[证据]` | +| 8 | `module_32088` | Alternativa3D 数学库(Vector/Matrix/四元数),被动调用 | `[推断]`(未取行号) | + +**每帧做的事(合并两条循环)**:①`tickerService` 回调链(优先序)更新逻辑/物理/战斗;②`module_92980` GL 上下文 `clear`+`drawElements*` 提交;③UI 侧 `jt()` 刷新订阅组件。`[证据]`(①②③各自) + `[推断]`(顺序) + +**场景图 / 相机 / 实体组织** +| # | 关键函数 | 做什么 | 可信度 | +|---|---|---|---| +| 1 | `module_61378` | World/ECS 核心:`"World.addGameEffect cannot add effect during update."`(1806)、`"Entity is not set"`(2329)、`"Entity is already initialized"`(2414)、`"BattleEntity.createComponent duplicate component class …"`(2441) → World 持有 Entity,BattleEntity 由 Component 组成 | `[证据]` | +| 2 | `module_87072` | 战斗域:底盘/物理/模式/物品池/特效/空投/地图场景;内含 17 处 `.t80()` 注册(与 13431 的 17 个协议域同构) | `[证据]`(17×t80)/`[推断]`(其余职责描述来自目录表) | +| 3 | `module_61860:2111-2131` `Vr.u7m` | 网络对象挂在 **Space** 上(`Vr`=`Space`),Space 是场景容器,持有对象表 `Gr`(aliases)+spaceRegistry | `[证据]` | +| 4 | `61378`(ECS) ↔ `87072`(战斗) | `87072` 依赖 `61378` 的 World/Entity 组织战斗实体(`BattleEntity`);相机与空间对象随 Space 创建 | `[推断]` | + +--- + +## 6. 空间与对象模型 + +**起点**:服务端下发 SpaceCommand(`module_61860:1315-1324` `Ni.toString` 含 `objectId/methodId/protocolBuffer`) +**终点**:对象实例进入 Space 的对象表 / ModelReg + +| # | 关键函数 | 做什么 | 可信度 | +|---|---|---|---| +| 1 | `module_61860:361-363` `or` | **SpaceReg**(regdump 确认 ctor=`or`),两张表 `x7m_1`/`y7m_1`(regdump size=2,key 为 `"1"`,`"2"`) | `[证据]` | +| 2 | `module_61860:1597-1606` `or.p7g` | SpaceReg 的 codec:先解基类再解登记表 | `[证据]` | +| 3 | `module_61860:2111-2150` `Vr` | **Space 本体**:`toString` = `"Space(id=)"`;`u7m` 处理帧、`e7p` 写短命令别名表、`b7p`/`r7m`/`s7m`/`c7p` 为 Space 级事件 | `[证据]` | +| 4 | `module_61860:1326-1328` `Oi` | `"[SpaceOpenedCommand spaceId=… hash=…]"`:Space 打开命令(含 hash) | `[证据]` | +| 5 | `module_61860:547-561` `Ur` | DI 取 `"spaceRegistry"`(`module_45686:175-189` 同名访问器) | `[证据]` | +| 6 | `module_45686:111-120` `ft(conn, cmd)` | **对象/模型数据入注册表**:读 `[i64,i64]`(`a7g_1.q2u()`×2),前一个是当前 Space 已有对象则先 `z7o` 移除;`wt().o1we().f7n(r)` 按类 id 查类,失败抛 `"Class not found exception class=…, object=…"`,成功后 `e.y7o(objectId, class, "")` 在 Space 里建对象 | `[证据]` | +| 7 | `module_61860:1672-1680` `mr.i7n` | 模型实例注册(`s7n_1`/`u7n_1`/`t7n_1`);`module_70130` 内 `i7n` 202 次 = 战斗模型注册入口 | `[证据]`(结构)/`[推断]`(202 次归属战斗模型) | +| 8 | `module_45686:60-72,160-174` | DI 取 `"modelRegister"`/`"modelRegistry"` | `[证据]` | +| 9 | `command_alias.json.Spaces` | 已证空间别名:`100045260`=Entrance、`100045720`=Chat、`100072911`=Shop、`100073070`=Garage、`100119080`=Unknown1、`920007382011`=Queue、`3074457345817190050`=Battle(未证) | `[证据]`(表) | + +**服务器下发数据 → 注册表,与已逆向容器的对应** +- 4 个 ModelService 容器命令(`names/downlink_table.json.Containers`)与布局:`LoadDependencies`(methodId 3216143066888387731, layout `zt`)、`LoadObjectsData`(7640916300855664666, `pt`)、`UnloadObjects`(9038756763225879447, `lt`)、`SetModelCommandAlias`(8179162314198150518, `alias`)。`[证据]` +- `lt`/`pt`/`zt` = 这 4 条命令的**负载容器布局类**,其负载**不按字段顺序**排列,必须按容器布局解;因此 `downlink_table` 把它们单列为 `Kind=container`。`[证据]`(表) +- 绑定流程:容器命令解出 modelId/methodId → `mr.l7n` 找到 codec(`v7n_1`/`u7n_1`)→ `codec.q7i` 解出的模型实例经 `mr.i7n` 进 `s7n_1/u7n_1/t7n_1`(模块内模型注册),对象则经 `module_45686:ft` 进当前 Space。`[证据]`(各步) / `[推断]`(串联顺序) + +--- + +## 未能确认清单 + +1. **`fr(config)` 是否就是「首次建立网络连接」的唯一触发点**:`module_61860:2710` 只证实它注册协议 + 创建 `ae`;`ae`→`new Ie` 的调用点在 `module_61860:2632`(某 `ae` 方法内),未确认该方法是被 balancer 轮询还是被上层直接调用。卡点:`module_61860:2626-2632`。 +2. **`module_24635` 二进制框架**:只确认被 61860/85183/29554 共用(`n7f`/`p7g`/`q7g`/`o7g`),未定位「写字节的统一函数」行号(该模块 27KB,未逐段读)。 +3. **`zt`/`pt`/`lt` 三个容器类的宿主模块**:`downlink_table` 给出布局名,但 `function zt(` 在同名局部类里遍布 17 个模块,无法唯一定位到 ModelService 的容器实现(可能在 `module_29554`/`module_45686` 的局部类中,未被锚点锁定)。 +4. **`TOState` 字段 `npp_1` 的名字**:`module_10032:43519-43650` 的 toString 序列中该行未读到(读取窗口边缘),其余字段名齐全。 +5. **`*Style` 对象的具体消费点**:只证明「`*Style` 是 Kotlin object(defineObject),CSS 由 24923/63383 注入」,未抓到「组件读某 `*Style` 生成 className」的赋值行。卡点:`module_82347` UI 渲染体(5.5MB,只按 `fq(` 锚点取样)。 +6. **`module_59131`/`module_50824` 的标签/属性绑定行号**:`50824:14` 只见 `React.createElement` 取用,`59131` 内无 `setAttribute/appendChild/createElement`,怀疑其只做 kotlinx.html DSL 结构,未取到具体绑定点。 +7. **`module_32088`(3D 数学)**、**`module_87072`(战斗/物理)内部主流程**:均未展开(体积/预算),只确认其对外连接点(`87072` 的 17×`t80`、被 `13431:245` `qr=rt.$_$.h2` 以挂起函数方式调用)。 +8. **`response 帧的 CS 侧封装**(`module_21300` 战斗 HUD 的 rAF 循环 `21300:12112`)未追踪**:属 UI 侧次要循环。 diff --git a/3DTank/docs/StateMap.md b/3DTank/docs/StateMap.md new file mode 100644 index 0000000..53a203b --- /dev/null +++ b/3DTank/docs/StateMap.md @@ -0,0 +1,292 @@ +# TOState 字段 ↔ reducer 映射表 + +本文是 `names/tostate-map.json` 的人类可读版,用途:**重写客户端时对照根状态的每个分片该由哪个 reducer / 哪些 action 驱动**。 + +## 1. TOState 是什么 + +- **根状态类**:`TOState`,即 `module_10032.js` 里的类 `w8`;其 `toString` 以 `"TOState(user="` 开头,定义在 **`module_10032.js:43519`**(`vd(w8).toString`)。 +- **字段数**:**89 个**(每个字段在源码里是 `this.<槽位>_1`,形如 `app_1` / `bpp_1` … `kps_1`)。 +- **根 reducer**:`module_10032.js:14307-15449` 的函数 **`v8(action, state)`**(`[证据]`:`module_10849:91` 的 Store 构造把 `v8` 作为 reducer 传入,见 `ArchitectureRuntime.md` 第 3 节)。它把 89 个分片逐一委派给各自的分片 reducer,最后用 `state.ntb(...)`(`vd(w8).ntb`,定义 `module_10032.js:42968`,方法体就是一串 `return new w8(参数…)`)合成新 `TOState`。 +- **store / dispatch**:`module_10032.js:52887` 的 `$_$.w1r` 创建 store(被 `module_13431:1408` 调用);`dispatch` 即 `module_10849:320` 的 `qao`。无 saga/effect,只有 thunk + ConsoleDebug 中间件。 +- **action 形态**:Kotlin 数据类实例,`new XxxAction(...)`,经 `store.qao(action)` 分发;分片 reducer 内部用 `if (t instanceof XxxAction)` 长链分派。 + +> 一致性交叉验证:`v8` 末尾 `return state.ntb(i, r, N, s, o, e, u, _, c, $, q, h, a, …)` 的**实参顺序**与 `TOState` 的**字段顺序**逐位对齐(第 1 位 `i`=`app_1`=`user`,第 2 位 `r`=`bpp_1`=`screen`,…),且每一位实参本身调用的 reducer 恰好读取同一个槽位。两套独立证据吻合,故下表映射记为 `证据`。 + +## 2. 主表(全部 89 个字段) + +「reducer 函数」列 = `v8` 中处理该槽位的调用式(源码形态);「位置」= 该调用在根 reducer 中的行;「相关 action」见第 3 节分组表。 + +| 业务域 | 字段 | 槽位 | reducer 函数 | 位置 | 可信度 | +|---|---|---|---|---|---| +| 登录与账号 | `user` | `app_1` | `T6().bt7` | module_10032.js:14308 | 证据 | +| UI/面板 | `screen` | `bpp_1` | `cY().wry` | module_10032.js:14309 | 证据 | +| UI/面板 | `modalScreen` | `cpp_1` | `Us.wru` | module_10032.js:14342 | 证据 | +| 战斗 | `battleStatistics` | `dpp_1` | `rr.tqk` | module_10032.js:14312 | 证据 | +| 战斗 | `battleTutorial` | `epp_1` | `Q.uq2` | module_10032.js:14313 | 证据 | +| 车库与物品 | `garage` | `fpp_1` | `sF` | module_10032.js:14310 | 证据 | +| 车库与物品 | `garagePreview` | `gpp_1` | `ls.rrn` | module_10032.js:14311 | 证据 | +| 任务与内容 | `challenges` | `hpp_1` | `ta.tsc` | module_10032.js:14314 | 证据 | +| 登录与账号 | `loginByPassword` | `ipp_1` | `nu.qqz` | module_10032.js:14317 | 证据 | +| 登录与账号 | `register` | `jpp_1` | `fw.dta` | module_10032.js:14330 | 证据 | +| 登录与账号 | `migrationState` | `kpp_1` | `Gv.cta` | module_10032.js:14329 | 证据 | +| 登录与账号 | `inviteState` | `lpp_1` | `Ke.sqy` | module_10032.js:14316 | 证据 | +| 登录与账号 | `captchaState` | `mpp_1` | `hr.wqm` | module_10032.js:14315 | 证据 | +| 登录与账号 | `passwordChangeState` | `npp_1` | `uu.dr0` | module_10032.js:14341 | 证据 | +| 网络/系统 | `system` | `opp_1` | `l4().jt3` | module_10032.js:14318 | 证据 | +| 任务与内容 | `quests` | `ppp_1` | `(null == qw && new Vrt(), qw).zt9` | module_10032.js:14321 | 证据 | +| 聊天/社交 | `chatState` | `qpp_1` | `jr.kqp` | module_10032.js:14322 | 证据 | +| 聊天/社交 | `clanChatState` | `rpp_1` | `xv.bta` | module_10032.js:14323 | 证据 | +| 聊天/社交 | `clan` | `spp_1` | `pe.vqt` | module_10032.js:14325 | 证据 | +| 聊天/社交 | `clansStorage` | `tpp_1` | `me.jqv` | module_10032.js:14326 | 证据 | +| UI/面板 | `tipsState` | `upp_1` | `Vp.gtb` | module_10032.js:15348 | 证据 | +| UI/面板 | `news` | `vpp_1` | `C_.ms6` | module_10032.js:14327 | 证据 | +| 设置 | `settings` | `wpp_1` | `Sp.wt9` | module_10032.js:14319 | 证据 | +| 设置 | `accountSettings` | `xpp_1` | `Uw.xt9` | module_10032.js:14320 | 证据 | +| 车库与物品 | `lootBoxes` | `ypp_1` | `ws.jrp` | module_10032.js:14328 | 证据 | +| UI/面板 | `notifications` | `zpp_1` | `L_.us7` | module_10032.js:14331 | 证据 | +| 聊天/社交 | `friends` | `apq_1` | `AL().qr2` | module_10032.js:14332 | 证据 | +| 网络/系统 | `remoteUserDataStorage` | `bpq_1` | `fa.use` | module_10032.js:14333 | 证据 | +| 空间与场景 | `battlesSelect` | `cpq_1` | `Oi.wqe` | module_10032.js:14334 | 证据 | +| 空间与场景 | `maps` | `dpq_1` | `Mi.gqf` | module_10032.js:14335 | 证据 | +| 空间与场景 | `matchmaking` | `epq_1` | `WH().drr` | module_10032.js:14336 | 证据 | +| 空间与场景 | `battleCreateState` | `fpq_1` | `Uf.eta` | module_10032.js:14338 | 证据 | +| 空间与场景 | `battleSearchState` | `gpq_1` | `Gtt().gta` | module_10032.js:14339 | 证据 | +| UI/面板 | `lobbyLoader` | `hpq_1` | `Ls.rru` | module_10032.js:14340 | 证据 | +| 战斗 | `battleResult` | `ipq_1` | `Fi.oqi` | module_10032.js:14343 | 证据 | +| 战斗 | `battleUsers` | `jpq_1` | `sr.vql` | module_10032.js:14344 | 证据 | +| 战斗 | `suppliesState` | `kpq_1` | `jt.hq3` | module_10032.js:15249 | 证据 | +| 空间与场景 | `matchmakingGroup` | `lpq_1` | `TW().vrt` | module_10032.js:14337 | 证据 | +| 车库与物品 | `shop` | `mpq_1` | `(inline IIFE)@module_10032.js:14345` | module_10032.js:14345 | 证据 | +| 战斗 | `battlePauseState` | `npq_1` | `RT().oq6` | module_10032.js:15251 | 证据 | +| 战斗 | `battleViewState` | `opq_1` | `(null == jn && new eI(), jn).lq7` | module_10032.js:15250 | 证据 | +| 战斗 | `rankUpDialogState` | `ppq_1` | `Se.pqw` | module_10032.js:15252 | 证据 | +| 聊天/社交 | `clanUserInfo` | `qpq_1` | `de.uqu` | module_10032.js:14324 | 证据 | +| 战斗 | `tankActionsLogState` | `rpq_1` | `pi.iq8` | module_10032.js:15253 | 证据 | +| 战斗 | `battleMessage` | `spq_1` | `lT().tq5` | module_10032.js:15254 | 证据 | +| 聊天/社交 | `battleChat` | `tpq_1` | `Kf.hta` | module_10032.js:15255 | 证据 | +| 战斗 | `droppableGold` | `upq_1` | `Kw.vta` | module_10032.js:15271 | 证据 | +| UI/面板 | `home` | `vpq_1` | `(inline IIFE)@module_10032.js:15256` | module_10032.js:15256 | 证据 | +| 战斗 | `localBattleUserState` | `wpq_1` | `(inline IIFE)@module_10032.js:15265` | module_10032.js:15265 | 证据 | +| 设置 | `soundSettings` | `xpq_1` | `Get().uta` | module_10032.js:15268 | 证据 | +| 设置 | `gameSettings` | `ypq_1` | `v2().osm` | module_10032.js:15270 | 证据 | +| 设置 | `battleSettings` | `zpq_1` | `W0().tsj` | module_10032.js:15269 | 证据 | +| 设置 | `graphicsSettings` | `apr_1` | `lc.wsn` | module_10032.js:15272 | 证据 | +| 设置 | `controlSettings` | `bpr_1` | `e2().tsl` | module_10032.js:15273 | 证据 | +| 设置 | `securitySettings` | `cpr_1` | `wc.dsp` | module_10032.js:15275 | 证据 | +| 车库与物品 | `purchaseDialogState` | `dpr_1` | `ze.iqw` | module_10032.js:15276 | 证据 | +| 战斗 | `battleInviteState` | `epr_1` | `Itt().yta` | module_10032.js:15277 | 证据 | +| 设置 | `keyboardSettings` | `fpr_1` | `$p.zta` | module_10032.js:15278 | 证据 | +| 设置 | `touchscreenHudSettings` | `gpr_1` | `I7().ksp` | module_10032.js:15274 | 证据 | +| 任务与内容 | `mainQuest` | `hpr_1` | `na.nsd` | module_10032.js:15279 | 证据 | +| 设置 | `language` | `ipr_1` | `f8().ut9` | module_10032.js:15330 | 证据 | +| 登录与账号 | `partner` | `kpr_1` | `(inline IIFE)@module_10032.js:15280` | module_10032.js:15280 | 证据 | +| UI/面板 | `entrance` | `lpr_1` | `Fv.atb` | module_10032.js:15331 | 证据 | +| 登录与账号 | `antiAddiction` | `mpr_1` | `W.kq2` | module_10032.js:15332 | 证据 | +| 战斗 | `spectator` | `npr_1` | `Li.xqf` | module_10032.js:15334 | 证据 | +| 登录与账号 | `moderation` | `opr_1` | `Ei.qqb` | module_10032.js:15333 | 证据 | +| 登录与账号 | `rulesUpdated` | `ppr_1` | `Sa.psf` | module_10032.js:15335 | 证据 | +| UI/面板 | `announcement` | `qpr_1` | `AC().tpz` | module_10032.js:15336 | 证据 | +| UI/面板 | `notificationByCountry` | `rpr_1` | `A_.es7` | module_10032.js:15337 | 证据 | +| 登录与账号 | `userRenameState` | `spr_1` | `Af.at8` | module_10032.js:15338 | 证据 | +| 车库与物品 | `eventGoods` | `tpr_1` | `Wc.rsq` | module_10032.js:15339 | 证据 | +| 任务与内容 | `creatorTagState` | `upr_1` | `ke.sqv` | module_10032.js:15340 | 证据 | +| 登录与账号 | `twoStepVerificationState` | `vpr_1` | `_f.mt4` | module_10032.js:15341 | 证据 | +| 任务与内容 | `rewardedVideosState` | `wpr_1` | `ja.lsf` | module_10032.js:15342 | 证据 | +| 任务与内容 | `twitchState` | `xpr_1` | `uf.st3` | module_10032.js:15343 | 证据 | +| UI/面板 | `icons` | `ypr_1` | `fs.xrn` | module_10032.js:15344 | 证据 | +| UI/面板 | `itemNotifications` | `zpr_1` | `C1().ssh` | module_10032.js:15345 | 证据 | +| 战斗 | `contextTutorial` | `aps_1` | `Yst().etb` | module_10032.js:15346 | 证据 | +| 战斗 | `suppliesTutorial` | `bps_1` | `Gp.ftb` | module_10032.js:15347 | 证据 | +| 任务与内容 | `questCategories` | `cps_1` | `Q_.xsa` | module_10032.js:15349 | 证据 | +| 空间与场景 | `proBattle` | `dps_1` | `_v.htb` | module_10032.js:15350 | 证据 | +| 空间与场景 | `availabilityByRank` | `eps_1` | `zw.itb` | module_10032.js:15351 | 证据 | +| 登录与账号 | `userReportsState` | `fps_1` | `(null == _d && new kot(), _d).ktb` | module_10032.js:15352 | 证据 | +| 车库与物品 | `tankBuilderState` | `gps_1` | `gw.ltb` | module_10032.js:15353 | 证据 | +| 任务与内容 | `contractState` | `hps_1` | `Sv.mtb` | module_10032.js:15354 | 证据 | +| 任务与内容 | `promoCode` | `ips_1` | `Z_.ksa` | module_10032.js:15355 | 证据 | +| 任务与内容 | `referralEvent` | `jps_1` | `ca.ase` | module_10032.js:15356 | 证据 | +| 登录与账号 | `supportUrl` | `kps_1` | `Yl.ot0` | module_10032.js:15357 | 证据 | +| 网络/系统 | `launchParams` | `jpr_1` | —(透传,无 reducer) | module_10032.js:15328 | 未映射 | + +## 3. 按业务域分组 + +每组给出字段 → reducer 函数(`(inline IIFE)@…` 表示根 reducer 内联的匿名 reducer,其函数体直接写在 `v8` 里,没有独立函数名)。相关 action 见 `names/tostate-map.json` 各 entry 的 `Actions`;下表为高频代表。 + +### 3.1 登录与账号(15 字段) +- `user`→`T6().bt7`、`loginByPassword`→`nu.qqz`、`register`→`fw.dta`、`migrationState`→`Gv.cta`、`inviteState`→`Ke.sqy`、`captchaState`→`hr.wqm`、`passwordChangeState`→`uu.dr0`、`userRenameState`→`Af.at8`、`twoStepVerificationState`→`_f.mt4`、`antiAddiction`→`W.kq2`、`moderation`→`Ei.qqb`、`rulesUpdated`→`Sa.psf`、`partner`→`(inline IIFE)@15280`、`supportUrl`→`Yl.ot0`、`userReportsState`→`(null == _d && new kot(), _d).ktb` + +| 字段 | reducer | 相关 action(代表) | +|---|---|---| +| `user` | `T6().bt7` @14308 | SetClanInfo, UpdateCrystals, SpendCrystals, AddCoins, SetCoins, SpendCoins, SetHasTemporaryCash, AddRubies …(共 27 个) | +| `loginByPassword` | `nu.qqz` @14317 | SetLogin, SetPassword, SetRememberMe, SetStatus, IncorrectLogin2FA …(共 9 个) | +| `register` | `fw.dta` @14330 | SetUid, ForceSetUid, SetPassword, EnteredUidIsBusy …(共 19 个) | +| `migrationState` | `Gv.cta` @14329 | SetUid, ForceSetUid, SetPassword …(共 11 个) | +| `inviteState` | `Ke.sqy` @14316 | SetInviteNeed, SetInviteStatus, ApplyInvite | +| `captchaState` | `hr.wqm` @14315 | SetLocations, LocationsUpdated | +| `passwordChangeState` | `uu.dr0` @14341 | SetPasswordChangeHash | +| `userRenameState` | `Af.at8` @15338 | ChangeUidInputState, SetValidationStatus, SetRubiesForRename, ResponseDelivered …(共 11 个) | +| `twoStepVerificationState` | `_f.mt4` @15341 | SetUse2FA, ActivationStatus2FA, SetSecretAndQRCode, VerificationStatus, Enable2FaRequest | +| `antiAddiction` | `W.kq2` @15332 | SetRealNameAndIdNumber, SetValidateAntiAddictionUserDataStatus | +| `moderation` | `Ei.qqb` @15333 | …(共 13 个) | +| `rulesUpdated` | `Sa.psf` @15335 | UpdateRules | +| `partner` | `(inline IIFE)@15280` | SetPartnerId, SetLoginParams, SetPartnerParameters, InitPartnerInviteAction, SetLoginStatusForBinding …(共 11 个) | +| `supportUrl` | `Yl.ot0` @15357 | SetUrl | +| `userReportsState` | `(…, _d).ktb` @15352 | SetAvailableReports, SetAvailableGameReports, ReportProBattleName, ReportLobbyChatMessage, ReportBattleChatMessage | + +### 3.2 UI/面板(12 字段) +- `screen`→`cY().wry`、`modalScreen`→`Us.wru`、`home`→`(inline IIFE)@15256`、`lobbyLoader`→`Ls.rru`、`tipsState`→`Vp.gtb`、`news`→`C_.ms6`、`notifications`→`L_.us7`、`announcement`→`AC().tpz`、`notificationByCountry`→`A_.es7`、`icons`→`fs.xrn`、`itemNotifications`→`C1().ssh`、`entrance`→`Fv.atb` + +| 字段 | reducer | 相关 action(代表) | +|---|---|---| +| `screen` | `cY().wry` @14309 | GoTo, PressedAnyButton, DisplayMainEntranceScreen, DisplayReauthorizationMessage …(共 15 个) | +| `modalScreen` | `Us.wru` @14342 | AddModal, RemoveModal, RemoveCurrentByName | +| `home` | `(inline IIFE)@15256` | (3 个:`i1`/`n1`/`r1`) | +| `lobbyLoader` | `Ls.rru` @14340 | (2 个) | +| `tipsState` | `Vp.gtb` @15348 | UpdateTips | +| `news` | `C_.ms6` @14327 | SetNewsItemAction, AddNewsItemAction, RemoveNewsItemAction, SetUnreadNewsCounter | +| `notifications` | `L_.us7` @14331 | InitNotificationSound, AddNotification | +| `announcement` | `AC().tpz` @15336 | Init, SetSkipNextPromotedAnnounce | +| `notificationByCountry` | `A_.es7` @15337 | (2 个) | +| `icons` | `fs.xrn` @15344 | SetIcons | +| `itemNotifications` | `C1().ssh` @15345 | AddItemNotifications | +| `entrance` | `Fv.atb` @15331 | SetAgeWarnShow …(共 7 个) | + +### 3.3 空间与场景(8 字段) +- `battlesSelect`→`Oi.wqe`、`maps`→`Mi.gqf`、`matchmaking`→`WH().drr`、`matchmakingGroup`→`TW().vrt`、`battleCreateState`→`Uf.eta`、`battleSearchState`→`Gtt().gta`、`proBattle`→`_v.htb`、`availabilityByRank`→`zw.itb` + +| 字段 | reducer | 相关 action(代表) | +|---|---|---| +| `battlesSelect` | `Oi.wqe` @14334 | RoundStarted, SwapTeam, RoundFinish, RemoveBattle, ChangeName …(共 20 个) | +| `maps` | `Mi.gqf` @14335 | AddMap | +| `matchmaking` | `WH().drr` @14336 | SelectMatchmakingMode, WasRegistered, EnterToBattleApply …(共 9 个) | +| `matchmakingGroup` | `TW().vrt` @14337 | InitMatchmakingGroup, SetAllowedFromFriends, AddUser, UserRemoved, Invite, AcceptedInviteToGroup …(共 13 个) | +| `battleCreateState` | `Uf.eta` @14338 | Configure, SetName, SetMode, SetMaxPeopleInTeam, SetScoreLimit, SetSearch, SetRanks, SetAvailableRanks …(共 17 个) | +| `battleSearchState` | `Gtt().gta` @14339 | SetFilter, SetSearch, SetSuspiciousFilter, Fight, EnterToBattle, SelectBattle, SelectBattleFormat, RemoveBattle …(共 9 个) | +| `proBattle` | `_v.htb` @15350 | Fight, SetPassword | +| `availabilityByRank` | `zw.itb` @15351 | SetLoadedData | + +> 注意:`battleCreateState` 的 reducer `Uf.eta(t, n.fpq_1, n.dpq_1, n.app_1)` 是**三槽位联合 reducer**(同时读 `maps`、`user`),重写时不可只传自身分片。 + +### 3.4 车库与物品(7 字段) +- `garage`→`sF`、`garagePreview`→`ls.rrn`、`shop`→`(inline IIFE)@14345`、`lootBoxes`→`ws.jrp`、`eventGoods`→`Wc.rsq`、`purchaseDialogState`→`ze.iqw`、`tankBuilderState`→`gw.ltb` + +| 字段 | reducer | 相关 action(代表) | +|---|---|---| +| `garage` | `sF` @14310 | SetGarageSkinsAction …(共 60 个;`sF` 是读整个 state 的跨分片 reducer,见 `module_10032.js:6455`,内部取 `n.fpp_1`) | +| `garagePreview` | `ls.rrn` @14311 | UpdatePreviewSettings, InitGarageResources, SetExpectedItemId, AddRequestedItem …(共 22 个) | +| `shop` | `(inline IIFE)@14345` | SetCoinPaymentProviderUrl, PaymentUrlReceived, SetBraintreeToken, SetStripeIntentParams, BraintreeLoadingInterrupt …(共 69 个,是全表 action 最多的分片) | +| `lootBoxes` | `ws.jrp` @14328 | SetPossibleRewards, SetCurrentContainer, SetKeys, AddKeys, SetGoToGarage, SetRewards …(共 18 个) | +| `eventGoods` | `Wc.rsq` @15339 | InitEventGoods | +| `purchaseDialogState` | `ze.iqw` @15276 | ChangeEmailStatus …(共 3 个) | +| `tankBuilderState` | `gw.ltb` @15353 | SetKode, SetParts, SetPartsInfo | + +### 3.5 战斗(16 字段) +- `battleStatistics`→`rr.tqk`、`battleTutorial`→`Q.uq2`、`battleResult`→`Fi.oqi`、`battleUsers`→`sr.vql`、`suppliesState`→`jt.hq3`、`battlePauseState`→`RT().oq6`、`battleViewState`→`(…, jn).lq7`、`rankUpDialogState`→`Se.pqw`、`tankActionsLogState`→`pi.iq8`、`battleMessage`→`lT().tq5`、`droppableGold`→`Kw.vta`、`localBattleUserState`→`(inline IIFE)@15265`、`battleInviteState`→`Itt().yta`、`spectator`→`Li.xqf`、`contextTutorial`→`Yst().etb`、`suppliesTutorial`→`Gp.ftb` + +| 字段 | reducer | 相关 action(代表) | +|---|---|---| +| `battleStatistics` | `rr.tqk` @14312 | SetDisplayClientInfo, SetBattleMode, SetReArmor, SetRankRange, UpdateScore, UpdateFund …(共 22 个) | +| `battleTutorial` | `Q.uq2` @14313 | ShowMessage, SetFragsCount | +| `battleResult` | `Fi.oqi` @14343 | SetRewards, SetHasBattleResult | +| `battleUsers` | `sr.vql` @14344 | UpdateUserRank, UpdateUsersClanTag, UpdateUserScoreKillsAndDeaths, SetGearScore …(共 18 个) | +| `suppliesState` | `jt.hq3` @15249 | (`kE`) | +| `battlePauseState` | `RT().oq6` @15251 | OnPauseMode, SetIdleKickPeriod | +| `battleViewState` | `(…, jn).lq7` @15250 | SetVisibility, SetElementsVisibility …(共 14 个) | +| `rankUpDialogState` | `Se.pqw` @15252 | ShowAvailableItems | +| `tankActionsLogState` | `pi.iq8` @15253 | OnUserJoinTheBattle, OnUserLeaveTheBattle, UpdateLog | +| `battleMessage` | `lT().tq5` @15254 | HideMessage, RemoveMessage | +| `droppableGold` | `Kw.vta` @15271 | (2 个) | +| `localBattleUserState` | `(inline IIFE)@15265` | SetLocalWeaponResistanceProperty, SetReArmorTemporaryDisabled | +| `battleInviteState` | `Itt().yta` @15277 | SelectUserToInvite, RemoveUserFromInvited, EnableSetBattleInviteNotifications | +| `spectator` | `Li.xqf` @15334 | SetSpectator, UpdateHudLayout | +| `contextTutorial` | `Yst().etb` @15346 | LoadCurrentElement, SetUnViewedElements, MarkElementAsViewed, SetLoadedElements, SetMissionToElement | +| `suppliesTutorial` | `Gp.ftb` @15347 | ActivatedInCurrentBattle, SetLoadedElement | + +### 3.6 聊天/社交(7 字段) +- `chatState`→`jr.kqp`、`clanChatState`→`xv.bta`、`clan`→`pe.vqt`、`clansStorage`→`me.jqv`、`clanUserInfo`→`de.uqu`、`friends`→`AL().qr2`、`battleChat`→`Kf.hta` + +| 字段 | reducer | 相关 action(代表) | +|---|---|---| +| `chatState` | `jr.kqp` @14322 | Configure, ChangeChannel, SaveChatMessage, SetMessages, CleanUsersMessage, UpdateUsers …(共 24 个) | +| `clanChatState` | `xv.bta` @14323 | Configure, DoAddMessages | +| `clan` | `pe.vqt` @14325 | AddUsersToAccepted, RemoveUserFromAccepted, SetMinRankForCreate, MembersFetched, ClanInfoLoaded, IncomingAdded …(共 43 个) | +| `clansStorage` | `me.jqv` @14326 | ClanLoaded, ClanUnloaded, MinimalRankChanged, RecruitmentChanged, AddUser, RemoveUser …(共 13 个) | +| `clanUserInfo` | `de.uqu` @14324 | Loaded | +| `friends` | `AL().qr2` @14332 | ChangeFriendAddFindState, SetLimits, AddUsersToAccepted, RemoveUserFromAccepted ≥ …(共 13 个) | +| `battleChat` | `Kf.hta` @15255 | AddMessage …(共 6 个) | + +### 3.7 设置(11 字段) +- `settings`→`Sp.wt9`、`accountSettings`→`Uw.xt9`、`soundSettings`→`Get().uta`、`gameSettings`→`v2().osm`、`battleSettings`→`W0().tsj`、`graphicsSettings`→`lc.wsn`、`controlSettings`→`e2().tsl`、`securitySettings`→`wc.dsp`、`keyboardSettings`→`$p.zta`、`touchscreenHudSettings`→`I7().ksp`、`language`→`f8().ut9` + +| 字段 | reducer | 相关 action(代表) | +|---|---|---| +| `settings` | `Sp.wt9` @14319 | (2 个) | +| `accountSettings` | `Uw.xt9` @14320 | …(共 13 个) | +| `soundSettings` | `Get().uta` @15268 | UpdateSettings, SetEntranceSoundEnabled | +| `gameSettings` | `v2().osm` @15270 | UpdateSettings | +| `battleSettings` | `W0().tsj` @15269 | UpdateSettings | +| `graphicsSettings` | `lc.wsn` @15272 | UpdateSettings | +| `controlSettings` | `e2().tsl` @15273 | UpdateSettings | +| `securitySettings` | `wc.dsp` @15275 | SetProfileBlockStatus | +| `keyboardSettings` | `$p.zta` @15278 | RemoveAction, ResetAction | +| `touchscreenHudSettings` | `I7().ksp` @15274 | UpdateSettings | +| `language` | `f8().ut9` @15330 | (`c8`) | + +> 各 `*Settings` 分片共用同一个 `UpdateSettings` 类 action,靠 reducer 内部区分目标分片;重写时不要把它当成单一 store。 + +### 3.8 任务与内容(10 字段) +- `challenges`→`ta.tsc`、`quests`→`(…, qw).zt9`、`mainQuest`→`na.nsd`、`questCategories`→`Q_.xsa`、`contractState`→`Sv.mtb`、`promoCode`→`Z_.ksa`、`referralEvent`→`ca.ase`、`rewardedVideosState`→`ja.lsf`、`twitchState`→`uf.st3`、`creatorTagState`→`ke.sqv` + +| 字段 | reducer | 相关 action(代表) | +|---|---|---| +| `challenges` | `ta.tsc` @14314 | UpdateStars, SetChallenge, RemoveChallenge, SetBattlePass, SetRewardForDialog, SetBattlePassPackages, SetTakenFreeRewardIndex …(共 9 个) | +| `quests` | `(…, qw).zt9` @14321 | SetCurrentCategory, GoTo, QuestCategory | +| `mainQuest` | `na.nsd` @15279 | QuestsLoaded, SetQuests, UpdateQuests, AddRewardedQuest, SetEventPassShopItemId, SetBattleUpdatedQuests | +| `questCategories` | `Q_.xsa` @15349 | SetQuestCategories, RemoveQuestCategory, RequestQuestCategoriesStatistic, SetQuestCategoriesStatistic | +| `contractState` | `Sv.mtb` @15354 | SetActiveContract, SetContract, UpdateProgress, SetBattleProgress, GetReward | +| `promoCode` | `Z_.ksa` @15355 | ActivatePromoCode, SetCodeValidateStatus | +| `referralEvent` | `ca.ase` @15356 | SetReferralEventData, SetPromoCode, SetReferrals, SetReferrer | +| `rewardedVideosState` | `ja.lsf` @15342 | SetDisplayState | +| `twitchState` | `uf.st3` @15343 | SetTwitchEnabled, SetAccount, SetDaysForNextLinking | +| `creatorTagState` | `ke.sqv` @15340 | SetCreatorTags, SetCreatorTag, SetAttachedCreatorTag | + +### 3.9 网络/系统(2 字段 + 1 未映射) +- `system`→`l4().jt3`、`remoteUserDataStorage`→`fa.use`(`launchParams` 未映射,见第 4 节) + +| 字段 | reducer | 相关 action(代表) | +|---|---|---| +| `system` | `l4().jt3` @14318 | DoShowMessage, SetFatalError | +| `remoteUserDataStorage` | `fa.use` @14333 | UpdateUids, UpdateRanks, UpdatePremiumStatus, UpdateClanTags, UpdateOnlineStatus, UserEnterBattle, UserLeaveBattle, UserLeaveGroup | + +## 4. 未映射字段 + +| 字段 | 槽位 | 原因 | +|---|---|---| +| `launchParams` | `jpr_1` | 根 reducer `v8` 在 `module_10032.js:15328` 用 `ht = n.jpr_1` **原样透传**:没有分片 reducer,也没有任何 `instanceof` 分支写它。该字段只在初始化(`module_10032.js:52909` `new w8().vt9(...)`)时被写入,之后不可变。重写时按只读启动参数处理即可。 | + +其余 88 个字段全部定位到分片 reducer(`Stats`: 证据 88 / 推断 0 / 未映射 1)。 + +## 5. 方法说明(如何把 TOState 字段与根 reducer 分支对上) + +**关键难点**:`v8` 是 1143 行的巨型函数,且不以 `if (t instanceof …)` 长链覆盖全部字段 —— 前 38 行是「直线式委派」,其余散落在 14345–15357 的续行里,且**顺序与 `TOState` 字段顺序完全不同**(例如 `battlePauseState` 在 15341、`modalScreen` 在 14342)。因此不能靠"读顺序"对齐,必须做双向锚定。 + +实际用到的四步与锚点: + +1. **抽出字段→槽位表**。定位 `module_10032.js:43519` 的 `vd(w8).toString`,用正则 + `/([A-Za-z][A-Za-z0-9]*)="\s*\+\s*(?:this\.([A-Za-z0-9_]+)|qd\(this\.([A-Za-z0-9_]+)\))/g` + 在 `"TOState(user="` 到 `hashCode` 之间的片段上匹配,得到 89 组 `字段名 → this.<槽位>`。注意字段名在 `="` 之前(形如 `..., screen=" + this.bpp_1 ...`),直接抓 `"name="` 会失败。 + +2. **抽出 `v8` 的委派语句**。定位 `function v8(t, n)`,用花括号配对取出函数体;再以「括号深度 0 处的逗号」切分变量声明链(`var i = ..., r = ..., e = ...;`),得到 89 条 `变量 = 表达式`。每条记录其起始偏移,换算成文件行号(注意函数体第一个换行导致 **+1 修正**——行号在起草稿时曾整体偏 −1,已校准)。 + +3. **把变量接到字段上(主锚点)**。`v8` 末尾 `return n.ntb(...)` 调用 `vd(w8).ntb`(`module_10032.js:42968`),而 `ntb` 的形参顺序 = `new w8(...)` 的实参顺序 = `TOState` 字段顺序(`app_1, bpp_1, cpp_1, …`)。于是**第 k 个实参 ↔ 第 k 个字段**。同时每个实参变量(如第 1 个 `i = T6().bt7(t, n.app_1)`)自身读取的槽位又是 `app_1` —— 两个方向的独立结果逐位一致(89/89),故此映射可直接标 `证据`,无需 `推断`。 + +4. **抽 action 类名**。对每个分片 reducer 取方法名(如 `bt7`),在 `module_10032.js` 里找 `.bt7 = function` / `function bt7(` 定义点,花括号配对取出函数体,用 `/\binstanceof\s+([A-Za-z_$][A-Za-z0-9_$]*)/g` 收集分支上的类名,再用 `names/evidence.json` 的 `byModule.10032.classNames`(混淆名→真名,如 `E6→State`)翻译成可读 action 名。分片状态类同理取自定义点的 `vd().`。 + - 内联匿名 reducer(`shop`/`home`/`localBattleUserState`/`partner`)无独立函数名,直接从 `v8` 内的 IIFE 函数体取 `instanceof` 链。 + - 特殊形态 `(null == qw && new Vrt(), qw).zt9(t, n.ppp_1)`(惰性单例)需要从 `(…, <名字>).<方法>` 里剥出方法名,普通 `^X.y(t` 正则会漏掉。 + +**复现命令**(只读,无临时文件):对 `module_10032.js` 用 `node -e` 跑上述四步的正则/配对逻辑即可重建 `names/tostate-map.json`;`Stats` 与 `Entries` 应逐条一致。 + +**已知不确定点**: +- `SliceClass` 有 5 项为空(`garage` 由顶层函数 `sF` 处理而非类方法;`shop`/`home`/`localBattleUserState`/`partner` 是内联 IIFE),其分片状态类名未在本模块内定位。 +- `Actions` 中部分仍是混淆名(如 `c6`/`p6`/`S6`),因为 `evidence.json` 的 `classNames` 未覆盖这些类;它们**确实是**能改该字段的 action 类,只是真名缺失。 +- `garage` 的 reducer `sF` 读整个 state(`n.fpp_1` 等)而非仅自身分片,属跨分片 reducer;`battleCreateState` 的 `Uf.eta` 显式接收 `maps`/`user` 两个额外槽位。重写时这两个是重点。 diff --git a/3DTank/names/tostate-map.json b/3DTank/names/tostate-map.json new file mode 100644 index 0000000..f0297b8 --- /dev/null +++ b/3DTank/names/tostate-map.json @@ -0,0 +1,1820 @@ +{ + "Note": "TOState 字段 → 分片 → reducer 函数 的映射(由 module_10032.js 的 TOState 定义与根 reducer 抽取)", + "RootState": { + "Class": "TOState", + "Site": "module_10032.js:43519", + "FieldCount": 89 + }, + "RootReducer": { + "Fn": "v8", + "Site": "module_10032.js:14307", + "ArmCount": 89 + }, + "Entries": [ + { + "Field": "user", + "Slot": "app_1", + "SliceClass": "E6", + "ReducerFn": "T6().bt7", + "ReducerSite": "module_10032.js:14308", + "Actions": [ + "SetClanInfo", + "UpdateCrystals", + "SpendCrystals", + "AddCoins", + "SetCoins", + "SpendCoins", + "SetHasTemporaryCash", + "AddRubies", + "SetRubies", + "SpendRubies", + "UpdateUserRating", + "UpdateUid", + "UpdateClanTag", + "UpdateScore", + "c6", + "p6", + "SetUserPropertiesAction", + "SetPremiumExpirationTime", + "UpdatePremium", + "UpdateEventPass", + "SetProStatusRemainingTime", + "SetRankNames", + "SetUserId", + "S6", + "SetBatteryLevel", + "_6", + "a6" + ], + "HandledBy": "T6().bt7(t, n.app_1)", + "Confidence": "证据", + "Why": "module_10032.js:14308 根 reducer 委派 T6().bt7(t, n.app_1);reducer 定义于 module_10032.js:42231" + }, + { + "Field": "screen", + "Slot": "bpp_1", + "SliceClass": "hY", + "ReducerFn": "cY().wry", + "ReducerSite": "module_10032.js:14309", + "Actions": [ + "eC", + "uC", + "ZK", + "QK", + "tY", + "GoTo", + "RX", + "SX", + "nY", + "sY", + "uY", + "oY", + "PressedAnyButton", + "DisplayMainEntranceScreen", + "DisplayReauthorizationMessage" + ], + "HandledBy": "cY().wry(t, n.bpp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14309 根 reducer 委派 cY().wry(t, n.bpp_1);reducer 定义于 module_10032.js:34850" + }, + { + "Field": "modalScreen", + "Slot": "cpp_1", + "SliceClass": "KW", + "ReducerFn": "Us.wru", + "ReducerSite": "module_10032.js:14342", + "Actions": [ + "AddModal", + "RemoveModal", + "HW", + "RemoveCurrentByName" + ], + "HandledBy": "Us.wru(t, n.cpp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14342 根 reducer 委派 Us.wru(t, n.cpp_1);reducer 定义于 module_10032.js:34150" + }, + { + "Field": "battleStatistics", + "Slot": "dpp_1", + "SliceClass": "tP", + "ReducerFn": "rr.tqk", + "ReducerSite": "module_10032.js:14312", + "Actions": [ + "LR", + "SetDisplayClientInfo", + "SetBattleMode", + "SetReArmor", + "SetRankRange", + "UpdateScore", + "UpdateFund", + "IR", + "SetRoundRestartTime", + "HR", + "WR", + "VR", + "DR", + "XR", + "YR", + "SetRemainingTime", + "SetFlagOrBallOwner", + "NR", + "JR", + "ZR", + "UR", + "InitBattleModeWithLevels" + ], + "HandledBy": "rr.tqk(t, n.dpp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14312 根 reducer 委派 rr.tqk(t, n.dpp_1);reducer 定义于 module_10032.js:23871" + }, + { + "Field": "battleTutorial", + "Slot": "epp_1", + "SliceClass": "oE", + "ReducerFn": "Q.uq2", + "ReducerSite": "module_10032.js:14313", + "Actions": [ + "ShowMessage", + "SetFragsCount", + "uE", + "eE" + ], + "HandledBy": "Q.uq2(t, n.epp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14313 根 reducer 委派 Q.uq2(t, n.epp_1);reducer 定义于 module_10032.js:21068" + }, + { + "Field": "garage", + "Slot": "fpp_1", + "SliceClass": null, + "ReducerFn": "sF", + "ReducerSite": "module_10032.js:14310", + "Actions": [ + "nk", + "DB", + "tF", + "zU", + "TU", + "IU", + "AU", + "SetGarageSkinsAction", + "nF", + "GB", + "KB", + "GarageSelectItem", + "XU", + "GarageUpdateItemCount", + "jU", + "QB", + "RU", + "vU", + "fU", + "FU", + "tU", + "VB", + "KU", + "YU", + "GarageUpgradeItemConfirm", + "$U", + "GarageRemoveDevice", + "AF", + "GarageDeviceTrySetInfinityLifetime", + "GarageSelectAlteration", + "GarageSelectSkin", + "GarageSelectShotSkin", + "GarageRemoveDiscountForDevice", + "UpdateDiscount", + "GarageAddItemToDepot", + "GarageRemoveItemFromDepot", + "GarageRemoveItemFromStore", + "oF", + "_F", + "aF", + "hF", + "RemoveFromSale", + "SetRestrictionMount", + "mU", + "cF", + "lF", + "SetItemRarity", + "AddToFavoriteItem", + "RemoveFromFavoriteItem", + "GoTo", + "OX", + "kU", + "FB", + "BuyProtectionSlot", + "SwitchingRowsScroll", + "WU", + "VU", + "PU", + "LB", + "yU" + ], + "HandledBy": "sF(t, n)", + "Confidence": "证据", + "Why": "module_10032.js:14310 根 reducer 委派 sF(t, n.fpp_1);reducer 定义于 module_10032.js:6455" + }, + { + "Field": "garagePreview", + "Slot": "gpp_1", + "SliceClass": "nH", + "ReducerFn": "ls.rrn", + "ReducerSite": "module_10032.js:14311", + "Actions": [ + "TG", + "UpdatePreviewSettings", + "AG", + "InitGarageResources", + "SetExpectedItemId", + "AddRequestedItem", + "UG", + "FG", + "JG", + "VG", + "KG", + "YG", + "XG", + "GG", + "HG", + "WG", + "SetPaint", + "ResetItem3dModelActionCache", + "SetMountedItemsProperties", + "PG", + "NG", + "OG" + ], + "HandledBy": "ls.rrn(t, n.gpp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14311 根 reducer 委派 ls.rrn(t, n.gpp_1);reducer 定义于 module_10032.js:32468" + }, + { + "Field": "challenges", + "Slot": "hpp_1", + "SliceClass": "DZ", + "ReducerFn": "ta.tsc", + "ReducerSite": "module_10032.js:14314", + "Actions": [ + "UpdateStars", + "SetChallenge", + "RemoveChallenge", + "SetBattlePass", + "SetRewardForDialog", + "RZ", + "SetBattlePassPackages", + "SetTakenFreeRewardIndex", + "TZ" + ], + "HandledBy": "ta.tsc(t, n.hpp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14314 根 reducer 委派 ta.tsc(t, n.hpp_1);reducer 定义于 module_10032.js:36260" + }, + { + "Field": "loginByPassword", + "Slot": "ipp_1", + "SliceClass": "RD", + "ReducerFn": "nu.qqz", + "ReducerSite": "module_10032.js:14317", + "Actions": [ + "ID", + "TD", + "SetLogin", + "SetPassword", + "SetRememberMe", + "SetStatus", + "AD", + "IncorrectLogin2FA", + "RequestsNumber2FA" + ], + "HandledBy": "nu.qqz(t, n.ipp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14317 根 reducer 委派 nu.qqz(t, n.ipp_1);reducer 定义于 module_10032.js:27960" + }, + { + "Field": "register", + "Slot": "jpp_1", + "SliceClass": "_rt", + "ReducerFn": "fw.dta", + "ReducerSite": "module_10032.js:14330", + "Actions": [ + "Pit", + "SetUid", + "ForceSetUid", + "SetPassword", + "Oit", + "EnteredUidIsBusy", + "Mit", + "Dit", + "Lit", + "Bit", + "Uit", + "SocialNetworkAvailability", + "SocialNetworkClientIds", + "ReceiveOAuthUri", + "srt", + "Fit", + "ort", + "Rit", + "SetOpenedPassword" + ], + "HandledBy": "fw.dta(t, n.jpp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14330 根 reducer 委派 fw.dta(t, n.jpp_1);reducer 定义于 module_10032.js:46180" + }, + { + "Field": "migrationState", + "Slot": "kpp_1", + "SliceClass": "xit", + "ReducerFn": "Gv.cta", + "ReducerSite": "module_10032.js:14329", + "Actions": [ + "SetUid", + "ForceSetUid", + "SetPassword", + "Oit", + "EnteredUidIsBusy", + "Mit", + "Dit", + "Bit", + "Uit", + "Fit", + "srt" + ], + "HandledBy": "Gv.cta(t, n.kpp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14329 根 reducer 委派 Gv.cta(t, n.kpp_1);reducer 定义于 module_10032.js:45858" + }, + { + "Field": "inviteState", + "Slot": "lpp_1", + "SliceClass": "lD", + "ReducerFn": "Ke.sqy", + "ReducerSite": "module_10032.js:14316", + "Actions": [ + "SetInviteNeed", + "SetInviteStatus", + "ApplyInvite" + ], + "HandledBy": "Ke.sqy(t, n.lpp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14316 根 reducer 委派 Ke.sqy(t, n.lpp_1);reducer 定义于 module_10032.js:27794" + }, + { + "Field": "captchaState", + "Slot": "mpp_1", + "SliceClass": "RP", + "ReducerFn": "hr.wqm", + "ReducerSite": "module_10032.js:14315", + "Actions": [ + "jP", + "SetLocations", + "CP", + "EP", + "TP", + "IP", + "LocationsUpdated" + ], + "HandledBy": "hr.wqm(t, n.mpp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14315 根 reducer 委派 hr.wqm(t, n.mpp_1);reducer 定义于 module_10032.js:24504" + }, + { + "Field": "passwordChangeState", + "Slot": "npp_1", + "SliceClass": "FD", + "ReducerFn": "uu.dr0", + "ReducerSite": "module_10032.js:14341", + "Actions": [ + "SetPasswordChangeHash", + "UD" + ], + "HandledBy": "uu.dr0(t, n.npp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14341 根 reducer 委派 uu.dr0(t, n.npp_1);reducer 定义于 module_10032.js:28052" + }, + { + "Field": "system", + "Slot": "opp_1", + "SliceClass": "c4", + "ReducerFn": "l4().jt3", + "ReducerSite": "module_10032.js:14318", + "Actions": [ + "DoShowMessage", + "SetFatalError" + ], + "HandledBy": "l4().jt3(t, n.opp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14318 根 reducer 委派 l4().jt3(t, n.opp_1);reducer 定义于 module_10032.js:41254" + }, + { + "Field": "quests", + "Slot": "ppp_1", + "SliceClass": "Vrt", + "ReducerFn": "(null == qw && new Vrt(), qw).zt9", + "ReducerSite": "module_10032.js:14321", + "Actions": [ + "SetCurrentCategory", + "Frt", + "GoTo", + "QuestCategory" + ], + "HandledBy": "(null == qw && new Vrt(), qw).zt9(t, n.ppp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14321 根 reducer 委派 (null == qw && new Vrt(), qw).zt9(t, n.ppp_1);reducer 定义于 module_10032.js:48279" + }, + { + "Field": "chatState", + "Slot": "qpp_1", + "SliceClass": "kN", + "ReducerFn": "jr.kqp", + "ReducerSite": "module_10032.js:14322", + "Actions": [ + "Configure", + "VP", + "XP", + "ChangeChannel", + "SaveChatMessage", + "SetMessages", + "CleanUsersMessage", + "UpdateUsers", + "ShowContextMenu", + "ZP", + "aN", + "hN", + "cN", + "lN", + "sN", + "fN", + "mN", + "yN", + "vN", + "SetSelectedUid", + "rN", + "IgnoreUserMessages", + "ShowUserMessages", + "sC" + ], + "HandledBy": "jr.kqp(t, n.qpp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14322 根 reducer 委派 jr.kqp(t, n.qpp_1);reducer 定义于 module_10032.js:24889" + }, + { + "Field": "clanChatState", + "Slot": "rpp_1", + "SliceClass": "Ent", + "ReducerFn": "xv.bta", + "ReducerSite": "module_10032.js:14323", + "Actions": [ + "qnt", + "$nt", + "Configure", + "DoAddMessages", + "Cnt" + ], + "HandledBy": "xv.bta(t, n.rpp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14323 根 reducer 委派 xv.bta(t, n.rpp_1);reducer 定义于 module_10032.js:45500" + }, + { + "Field": "clan", + "Slot": "spp_1", + "SliceClass": "iM", + "ReducerFn": "pe.vqt", + "ReducerSite": "module_10032.js:14325", + "Actions": [ + "AddUsersToAccepted", + "RemoveUserFromAccepted", + "AddUsersToNewAccepted", + "LN", + "SetMinRankForCreate", + "MembersFetched", + "ClanInfoLoaded", + "IncomingAdded", + "IncomingRemoved", + "OutgoingAdded", + "OutgoingRemoved", + "QN", + "UpdateValidation", + "UpdateClanNameValidation", + "UpdateClanTagValidation", + "UpdateClanSearchValidation", + "UpdateClanLicense", + "UpdateHasClan", + "ClanLoaded", + "AddOutgoingClan", + "RemoveOutgoingClan", + "AddIncomingClan", + "RemoveIncomingClan", + "AddNewIncomingClan", + "RemoveNewIncomingClan", + "UpdateTimeToJoinRestriction", + "CO", + "TO", + "IO", + "ClanBanned", + "LO", + "AddNewIncoming", + "RemoveNewIncoming", + "GO", + "HO", + "WO", + "AcceptedUserViewed", + "IncomingUserViewed", + "NewIncomingUserNotification", + "NewAcceptedUserNotification", + "NewClanInviteNotification", + "ClanModalVisible", + "SetClanEditPrice" + ], + "HandledBy": "pe.vqt(t, n.spp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14325 根 reducer 委派 pe.vqt(t, n.spp_1);reducer 定义于 module_10032.js:25969" + }, + { + "Field": "clansStorage", + "Slot": "tpp_1", + "SliceClass": "gM", + "ReducerFn": "me.jqv", + "ReducerSite": "module_10032.js:14326", + "Actions": [ + "ClanLoaded", + "ClanUnloaded", + "MinimalRankChanged", + "RecruitmentChanged", + "AddUsersToNewAccepted", + "LN", + "AddUser", + "RemoveUser", + "ForeignClanLoaded", + "pM", + "ShowForeignClan", + "ZO", + "BuyAdditionalPlace" + ], + "HandledBy": "me.jqv(t, n.tpp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14326 根 reducer 委派 me.jqv(t, n.tpp_1);reducer 定义于 module_10032.js:27134" + }, + { + "Field": "tipsState", + "Slot": "upp_1", + "SliceClass": "yst", + "ReducerFn": "Vp.gtb", + "ReducerSite": "module_10032.js:15348", + "Actions": [ + "UpdateTips" + ], + "HandledBy": "Vp.gtb(t, n.upp_1)", + "Confidence": "证据", + "Why": "module_10032.js:15348 根 reducer 委派 Vp.gtb(t, n.upp_1);reducer 定义于 module_10032.js:48964" + }, + { + "Field": "news", + "Slot": "vpp_1", + "SliceClass": "hJ", + "ReducerFn": "C_.ms6", + "ReducerSite": "module_10032.js:14327", + "Actions": [ + "SetNewsItemAction", + "AddNewsItemAction", + "RemoveNewsItemAction", + "SetUnreadNewsCounter", + "rJ" + ], + "HandledBy": "C_.ms6(t, n.vpp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14327 根 reducer 委派 C_.ms6(t, n.vpp_1);reducer 定义于 module_10032.js:35347" + }, + { + "Field": "settings", + "Slot": "wpp_1", + "SliceClass": "Fut", + "ReducerFn": "Sp.wt9", + "ReducerSite": "module_10032.js:14319", + "Actions": [ + "But", + "Uut" + ], + "HandledBy": "Sp.wt9(t, n.wpp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14319 根 reducer 委派 Sp.wt9(t, n.wpp_1);reducer 定义于 module_10032.js:48856" + }, + { + "Field": "accountSettings", + "Slot": "xpp_1", + "SliceClass": "Cet", + "ReducerFn": "Uw.xt9", + "ReducerSite": "module_10032.js:14320", + "Actions": [ + "_et", + "het", + "cet", + "fet", + "vet", + "wet", + "pet", + "det", + "aet", + "get", + "ClearInputUid", + "SetAccountRemovalDays", + "$et" + ], + "HandledBy": "Uw.xt9(t, n.xpp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14320 根 reducer 委派 Uw.xt9(t, n.xpp_1);reducer 定义于 module_10032.js:48527" + }, + { + "Field": "lootBoxes", + "Slot": "ypp_1", + "SliceClass": "jH", + "ReducerFn": "ws.jrp", + "ReducerSite": "module_10032.js:14328", + "Actions": [ + "SetPossibleRewards", + "SetCurrentContainer", + "SetKeys", + "AddKeys", + "hH", + "SetGoToGarage", + "SetRewards", + "vH", + "wH", + "pH", + "fH", + "SelectCategory", + "ShownRewards", + "SetIsOpening", + "SetIsAccelerated", + "SetIsShopVisited", + "$H", + "qH" + ], + "HandledBy": "ws.jrp(t, n.ypp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14328 根 reducer 委派 ws.jrp(t, n.ypp_1);reducer 定义于 module_10032.js:33059" + }, + { + "Field": "notifications", + "Slot": "zpp_1", + "SliceClass": "EJ", + "ReducerFn": "L_.us7", + "ReducerSite": "module_10032.js:14331", + "Actions": [ + "InitNotificationSound", + "AddNotification", + "SJ", + "CJ" + ], + "HandledBy": "L_.us7(t, n.zpp_1)", + "Confidence": "证据", + "Why": "module_10032.js:14331 根 reducer 委派 L_.us7(t, n.zpp_1);reducer 定义于 module_10032.js:35522" + }, + { + "Field": "friends", + "Slot": "apq_1", + "SliceClass": "IL", + "ReducerFn": "AL().qr2", + "ReducerSite": "module_10032.js:14332", + "Actions": [ + "ChangeFriendAddFindState", + "uL", + "sL", + "SetLimits", + "AddUsersToAccepted", + "RemoveUserFromAccepted", + "AddUsersToNewAccepted", + "RemoveUserFromNewAccepted", + "AddUsersToIncoming", + "RemoveUserFromIncoming", + "AddUsersToNewIncoming", + "RemoveUsersFromNewIncoming", + "SetValidationStatus" + ], + "HandledBy": "AL().qr2(t, n.apq_1)", + "Confidence": "证据", + "Why": "module_10032.js:14332 根 reducer 委派 AL().qr2(t, n.apq_1);reducer 定义于 module_10032.js:28378" + }, + { + "Field": "remoteUserDataStorage", + "Slot": "bpq_1", + "SliceClass": "SQ", + "ReducerFn": "fa.use", + "ReducerSite": "module_10032.js:14333", + "Actions": [ + "UpdateUids", + "UpdateRanks", + "UpdatePremiumStatus", + "UpdateClanTags", + "UpdateOnlineStatus", + "UserEnterBattle", + "UserLeaveBattle", + "UserLeaveGroup" + ], + "HandledBy": "fa.use(t, n.bpq_1)", + "Confidence": "证据", + "Why": "module_10032.js:14333 根 reducer 委派 fa.use(t, n.bpq_1);reducer 定义于 module_10032.js:36820" + }, + { + "Field": "battlesSelect", + "Slot": "cpq_1", + "SliceClass": "PA", + "ReducerFn": "Oi.wqe", + "ReducerSite": "module_10032.js:14334", + "Actions": [ + "RoundStarted", + "SwapTeam", + "RoundFinish", + "pA", + "dA", + "RemoveBattle", + "ChangeName", + "yA", + "bA", + "qA", + "RemoveUser", + "jA", + "zA", + "kA", + "wA", + "EnterToBattleInfo", + "UpdateFund", + "InitProBattleRewardLimit", + "LimitReached", + "SetReEnterProtectBattleId" + ], + "HandledBy": "Oi.wqe(t, n.cpq_1)", + "Confidence": "证据", + "Why": "module_10032.js:14334 根 reducer 委派 Oi.wqe(t, n.cpq_1);reducer 定义于 module_10032.js:22781" + }, + { + "Field": "maps", + "Slot": "dpq_1", + "SliceClass": "DA", + "ReducerFn": "Mi.gqf", + "ReducerSite": "module_10032.js:14335", + "Actions": [ + "AddMap" + ], + "HandledBy": "Mi.gqf(t, n.dpq_1)", + "Confidence": "证据", + "Why": "module_10032.js:14335 根 reducer 委派 Mi.gqf(t, n.dpq_1);reducer 定义于 module_10032.js:23042" + }, + { + "Field": "matchmaking", + "Slot": "epq_1", + "SliceClass": "HH", + "ReducerFn": "WH().drr", + "ReducerSite": "module_10032.js:14336", + "Actions": [ + "IH", + "TH", + "SelectMatchmakingMode", + "WasRegistered", + "EnterToBattleApply", + "BH", + "YH", + "XH", + "SetRankIndexToMinGS" + ], + "HandledBy": "WH().drr(t, n.epq_1)", + "Confidence": "证据", + "Why": "module_10032.js:14336 根 reducer 委派 WH().drr(t, n.epq_1);reducer 定义于 module_10032.js:33437" + }, + { + "Field": "battleCreateState", + "Slot": "fpq_1", + "SliceClass": "W8", + "ReducerFn": "Uf.eta", + "ReducerSite": "module_10032.js:14338", + "Actions": [ + "Configure", + "SetName", + "SetMode", + "SetMaxPeopleInTeam", + "SetScoreLimit", + "SetSearch", + "SetRanks", + "SetAvailableRanks", + "SetFormat", + "SetTimeLimit", + "SetRestrictions", + "SetMap", + "L8", + "B8", + "SetFilter", + "M8", + "SetCurrentPage" + ], + "HandledBy": "Uf.eta(t, n.fpq_1, n.dpq_1, n.app_1)", + "Confidence": "证据", + "Why": "module_10032.js:14338 根 reducer 委派 Uf.eta(t, n.fpq_1);reducer 定义于 module_10032.js:44187" + }, + { + "Field": "battleSearchState", + "Slot": "gpq_1", + "SliceClass": "Ftt", + "ReducerFn": "Gtt().gta", + "ReducerSite": "module_10032.js:14339", + "Actions": [ + "SetFilter", + "SetSearch", + "SetSuspiciousFilter", + "Fight", + "EnterToBattle", + "SelectBattle", + "SelectBattleFormat", + "RemoveBattle", + "Ltt" + ], + "HandledBy": "Gtt().gta(t, n.gpq_1)", + "Confidence": "证据", + "Why": "module_10032.js:14339 根 reducer 委派 Gtt().gta(t, n.gpq_1);reducer 定义于 module_10032.js:45030" + }, + { + "Field": "lobbyLoader", + "Slot": "hpq_1", + "SliceClass": "UW", + "ReducerFn": "Ls.rru", + "ReducerSite": "module_10032.js:14340", + "Actions": [ + "MW", + "DW" + ], + "HandledBy": "Ls.rru(t, n.hpq_1)", + "Confidence": "证据", + "Why": "module_10032.js:14340 根 reducer 委派 Ls.rru(t, n.hpq_1);reducer 定义于 module_10032.js:34080" + }, + { + "Field": "battleResult", + "Slot": "ipq_1", + "SliceClass": "lR", + "ReducerFn": "Fi.oqi", + "ReducerSite": "module_10032.js:14343", + "Actions": [ + "SetRewards", + "SetHasBattleResult", + "_R", + "aR", + "hR", + "DoInit" + ], + "HandledBy": "Fi.oqi(t, n.ipq_1)", + "Confidence": "证据", + "Why": "module_10032.js:14343 根 reducer 委派 Fi.oqi(t, n.ipq_1);reducer 定义于 module_10032.js:23324" + }, + { + "Field": "battleUsers", + "Slot": "jpq_1", + "SliceClass": "kP", + "ReducerFn": "sr.vql", + "ReducerSite": "module_10032.js:14344", + "Actions": [ + "eP", + "uP", + "sP", + "UpdateUserRank", + "UpdateUsersClanTag", + "UpdateUserScoreKillsAndDeaths", + "UpdateUsersScoreKillsAndDeaths", + "SetGearScore", + "SetTankResistance", + "yP", + "aP", + "hP", + "cP", + "rP", + "InitUserLevels", + "UpdateUserLevel", + "SetTankInfo", + "RemoveTankInfo" + ], + "HandledBy": "sr.vql(t, n.jpq_1)", + "Confidence": "证据", + "Why": "module_10032.js:14344 根 reducer 委派 sr.vql(t, n.jpq_1);reducer 定义于 module_10032.js:24267" + }, + { + "Field": "suppliesState", + "Slot": "kpq_1", + "SliceClass": "bE", + "ReducerFn": "jt.hq3", + "ReducerSite": "module_10032.js:15249", + "Actions": [ + "kE" + ], + "HandledBy": "jt.hq3(t, n.kpq_1)", + "Confidence": "证据", + "Why": "module_10032.js:15249 根 reducer 委派 jt.hq3(t, n.kpq_1);reducer 定义于 module_10032.js:21147" + }, + { + "Field": "matchmakingGroup", + "Slot": "lpq_1", + "SliceClass": "EW", + "ReducerFn": "TW().vrt", + "ReducerSite": "module_10032.js:14337", + "Actions": [ + "InitMatchmakingGroup", + "SetAllowedFromFriends", + "AddUser", + "UserRemoved", + "pW", + "Invite", + "AcceptedInviteToGroup", + "jW", + "UpdateMountItems", + "UpdateUserReadiness", + "AddUserToSelected", + "RemoveUserToSelected", + "SetSelectedUsers" + ], + "HandledBy": "TW().vrt(t, n.lpq_1)", + "Confidence": "证据", + "Why": "module_10032.js:14337 根 reducer 委派 TW().vrt(t, n.lpq_1);reducer 定义于 module_10032.js:33738" + }, + { + "Field": "shop", + "Slot": "mpq_1", + "SliceClass": null, + "ReducerFn": "(inline IIFE)@module_10032.js:14345", + "ReducerSite": "module_10032.js:14345", + "Actions": [ + "SetCoinPaymentProviderUrl", + "Vut", + "D5", + "PaymentUrlReceived", + "SetBraintreeToken", + "SetStripeIntentParams", + "BraintreeLoadingInterrupt", + "v9", + "CurrentPayMode", + "W5", + "MobilePaymentStateChanged", + "InitPayModeAction", + "e9", + "SelectItem", + "SetInitShopItemId", + "ToggleShopActivity", + "b9", + "InitShopItem", + "V3", + "Y3", + "K3", + "ShopCardSold", + "ShopCardExpired", + "ShopCardRemoved", + "j3", + "InitPaymentProviderItems", + "InitFeatureItem", + "E3", + "z3", + "x3", + "F3", + "G3", + "P3", + "InitAmountString", + "R3", + "i5", + "T3", + "I3", + "N3", + "InitCompensation", + "r5", + "e5", + "S3", + "U3", + "B3", + "InitKitBundle", + "TryToBuyOneTimePurchase", + "DeleteOneTimePurchaseItem", + "InitGroup", + "InitCategory", + "B7", + "SetupDiscountCategoryByItem", + "SelectCategory", + "SelectCategoryId", + "l5", + "r9", + "w9", + "p9", + "Z5", + "X5", + "UB", + "RemoveItemFromOrderProcessing", + "SavePreviousScreen", + "a5", + "SaveTargetVisitedCategory", + "h5", + "SaveTargetProductId", + "c5", + "SetPurchaseCompleted" + ], + "HandledBy": "(function (t, n) { var i; if (t instanceof l9) i = n.ct0(fd, fd, fd, fd, fd, fd, fd, t.xsz...", + "Confidence": "证据", + "Why": "module_10032.js:14345 根 reducer 内联 IIFE,以第二参 n.mpq_1 为分片状态;链内 instanceof 类即能改该字段的 action" + }, + { + "Field": "battlePauseState", + "Slot": "npq_1", + "SliceClass": "AT", + "ReducerFn": "RT().oq6", + "ReducerSite": "module_10032.js:15251", + "Actions": [ + "$T", + "OnPauseMode", + "CT", + "SetIdleKickPeriod" + ], + "HandledBy": "RT().oq6(t, n.npq_1)", + "Confidence": "证据", + "Why": "module_10032.js:15251 根 reducer 委派 RT().oq6(t, n.npq_1);reducer 定义于 module_10032.js:21591" + }, + { + "Field": "battleViewState", + "Slot": "opq_1", + "SliceClass": "eI", + "ReducerFn": "(null == jn && new eI(), jn).lq7", + "ReducerSite": "module_10032.js:15250", + "Actions": [ + "GT", + "SetVisibility", + "SetElementsVisibility", + "VT", + "YT", + "XT", + "JT", + "ZT", + "QT", + "tI", + "QC", + "ZC", + "nI", + "iI" + ], + "HandledBy": "(null == jn && new eI(), jn).lq7(t, n.opq_1)", + "Confidence": "证据", + "Why": "module_10032.js:15250 根 reducer 委派 (null == jn && new eI(), jn).lq7(t, n.opq_1);reducer 定义于 module_10032.js:21690" + }, + { + "Field": "rankUpDialogState", + "Slot": "ppq_1", + "SliceClass": "BM", + "ReducerFn": "Se.pqw", + "ReducerSite": "module_10032.js:15252", + "Actions": [ + "ShowAvailableItems", + "LM" + ], + "HandledBy": "Se.pqw(t, n.ppq_1)", + "Confidence": "证据", + "Why": "module_10032.js:15252 根 reducer 委派 Se.pqw(t, n.ppq_1);reducer 定义于 module_10032.js:27425" + }, + { + "Field": "clanUserInfo", + "Slot": "qpq_1", + "SliceClass": "_M", + "ReducerFn": "de.uqu", + "ReducerSite": "module_10032.js:14324", + "Actions": [ + "Loaded" + ], + "HandledBy": "de.uqu(t, n.qpq_1)", + "Confidence": "证据", + "Why": "module_10032.js:14324 根 reducer 委派 de.uqu(t, n.qpq_1);reducer 定义于 module_10032.js:26941" + }, + { + "Field": "tankActionsLogState", + "Slot": "rpq_1", + "SliceClass": "bI", + "ReducerFn": "pi.iq8", + "ReducerSite": "module_10032.js:15253", + "Actions": [ + "wI", + "OnUserJoinTheBattle", + "OnUserLeaveTheBattle", + "UpdateLog" + ], + "HandledBy": "pi.iq8(t, n.rpq_1)", + "Confidence": "证据", + "Why": "module_10032.js:15253 根 reducer 委派 pi.iq8(t, n.rpq_1);reducer 定义于 module_10032.js:21835" + }, + { + "Field": "battleMessage", + "Slot": "spq_1", + "SliceClass": "cT", + "ReducerFn": "lT().tq5", + "ReducerSite": "module_10032.js:15254", + "Actions": [ + "_T", + "uT", + "sT", + "oT", + "HideMessage", + "RemoveMessage", + "eT" + ], + "HandledBy": "lT().tq5(t, n.spq_1)", + "Confidence": "证据", + "Why": "module_10032.js:15254 根 reducer 委派 lT().tq5(t, n.spq_1);reducer 定义于 module_10032.js:21492" + }, + { + "Field": "battleChat", + "Slot": "tpq_1", + "SliceClass": "htt", + "ReducerFn": "Kf.hta", + "ReducerSite": "module_10032.js:15255", + "Actions": [ + "rtt", + "AddMessage", + "utt", + "stt", + "ott", + "ett" + ], + "HandledBy": "Kf.hta(t, n.tpq_1)", + "Confidence": "证据", + "Why": "module_10032.js:15255 根 reducer 委派 Kf.hta(t, n.tpq_1);reducer 定义于 module_10032.js:44503" + }, + { + "Field": "droppableGold", + "Slot": "upq_1", + "SliceClass": "Ket", + "ReducerFn": "Kw.vta", + "ReducerSite": "module_10032.js:15271", + "Actions": [ + "Wet", + "Vet" + ], + "HandledBy": "Kw.vta(t, n.upq_1)", + "Confidence": "证据", + "Why": "module_10032.js:15271 根 reducer 委派 Kw.vta(t, n.upq_1);reducer 定义于 module_10032.js:48731" + }, + { + "Field": "home", + "Slot": "vpq_1", + "SliceClass": null, + "ReducerFn": "(inline IIFE)@module_10032.js:15256", + "ReducerSite": "module_10032.js:15256", + "Actions": [ + "i1", + "n1", + "r1" + ], + "HandledBy": "(function (t, n) { return t instanceof i1 ? n.tsf(fd, !0) : t instanceof n1 ? n.tsf(!0) : ...", + "Confidence": "证据", + "Why": "module_10032.js:15256 根 reducer 内联 IIFE,以第二参 n.vpq_1 为分片状态;链内 instanceof 类即能改该字段的 action" + }, + { + "Field": "localBattleUserState", + "Slot": "wpq_1", + "SliceClass": null, + "ReducerFn": "(inline IIFE)@module_10032.js:15265", + "ReducerSite": "module_10032.js:15265", + "Actions": [ + "SetLocalWeaponResistanceProperty", + "SetReArmorTemporaryDisabled" + ], + "HandledBy": "(function (t, n) { return t instanceof cE ? n.zq2(t.aq3_1) : t instanceof lE ? n.zq2(fd, t...", + "Confidence": "证据", + "Why": "module_10032.js:15265 根 reducer 内联 IIFE,以第二参 n.wpq_1 为分片状态;链内 instanceof 类即能改该字段的 action" + }, + { + "Field": "soundSettings", + "Slot": "xpq_1", + "SliceClass": "Fet", + "ReducerFn": "Get().uta", + "ReducerSite": "module_10032.js:15268", + "Actions": [ + "sC", + "UpdateSettings", + "Let", + "SetEntranceSoundEnabled" + ], + "HandledBy": "Get().uta(t, n.xpq_1)", + "Confidence": "证据", + "Why": "module_10032.js:15268 根 reducer 委派 Get().uta(t, n.xpq_1);reducer 定义于 module_10032.js:48661" + }, + { + "Field": "gameSettings", + "Slot": "ypq_1", + "SliceClass": "f2", + "ReducerFn": "v2().osm", + "ReducerSite": "module_10032.js:15270", + "Actions": [ + "sC", + "UpdateSettings" + ], + "HandledBy": "v2().osm(t, n.ypq_1)", + "Confidence": "证据", + "Why": "module_10032.js:15270 根 reducer 委派 v2().osm(t, n.ypq_1);reducer 定义于 module_10032.js:38179" + }, + { + "Field": "battleSettings", + "Slot": "zpq_1", + "SliceClass": "H0", + "ReducerFn": "W0().tsj", + "ReducerSite": "module_10032.js:15269", + "Actions": [ + "sC", + "UpdateSettings" + ], + "HandledBy": "W0().tsj(t, n.zpq_1)", + "Confidence": "证据", + "Why": "module_10032.js:15269 根 reducer 委派 W0().tsj(t, n.zpq_1);reducer 定义于 module_10032.js:37795" + }, + { + "Field": "graphicsSettings", + "Slot": "apr_1", + "SliceClass": "M2", + "ReducerFn": "lc.wsn", + "ReducerSite": "module_10032.js:15272", + "Actions": [ + "UpdateSettings" + ], + "HandledBy": "lc.wsn(t, n.apr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15272 根 reducer 委派 lc.wsn(t, n.apr_1);reducer 定义于 module_10032.js:38434" + }, + { + "Field": "controlSettings", + "Slot": "bpr_1", + "SliceClass": "r2", + "ReducerFn": "e2().tsl", + "ReducerSite": "module_10032.js:15273", + "Actions": [ + "sC", + "UpdateSettings" + ], + "HandledBy": "e2().tsl(t, n.bpr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15273 根 reducer 委派 e2().tsl(t, n.bpr_1);reducer 定义于 module_10032.js:38030" + }, + { + "Field": "securitySettings", + "Slot": "cpr_1", + "SliceClass": "W2", + "ReducerFn": "wc.dsp", + "ReducerSite": "module_10032.js:15275", + "Actions": [ + "SetProfileBlockStatus" + ], + "HandledBy": "wc.dsp(t, n.cpr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15275 根 reducer 委派 wc.dsp(t, n.cpr_1);reducer 定义于 module_10032.js:38567" + }, + { + "Field": "purchaseDialogState", + "Slot": "dpr_1", + "SliceClass": "NM", + "ReducerFn": "ze.iqw", + "ReducerSite": "module_10032.js:15276", + "Actions": [ + "AM", + "ChangeEmailStatus", + "PM" + ], + "HandledBy": "ze.iqw(t, n.dpr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15276 根 reducer 委派 ze.iqw(t, n.dpr_1);reducer 定义于 module_10032.js:27363" + }, + { + "Field": "battleInviteState", + "Slot": "epr_1", + "SliceClass": "Ttt", + "ReducerFn": "Itt().yta", + "ReducerSite": "module_10032.js:15277", + "Actions": [ + "ytt", + "jtt", + "SelectUserToInvite", + "RemoveUserFromInvited", + "gtt", + "EnableSetBattleInviteNotifications" + ], + "HandledBy": "Itt().yta(t, n.epr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15277 根 reducer 委派 Itt().yta(t, n.epr_1);reducer 定义于 module_10032.js:44893" + }, + { + "Field": "keyboardSettings", + "Slot": "fpr_1", + "SliceClass": "Rut", + "ReducerFn": "$p.zta", + "ReducerSite": "module_10032.js:15278", + "Actions": [ + "sC", + "Eut", + "zut", + "RemoveAction", + "ResetAction" + ], + "HandledBy": "$p.zta(t, n.fpr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15278 根 reducer 委派 $p.zta(t, n.fpr_1);reducer 定义于 module_10032.js:48789" + }, + { + "Field": "touchscreenHudSettings", + "Slot": "gpr_1", + "SliceClass": "T7", + "ReducerFn": "I7().ksp", + "ReducerSite": "module_10032.js:15274", + "Actions": [ + "sC", + "UpdateSettings", + "x7" + ], + "HandledBy": "I7().ksp(t, n.gpr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15274 根 reducer 委派 I7().ksp(t, n.gpr_1);reducer 定义于 module_10032.js:38591" + }, + { + "Field": "mainQuest", + "Slot": "hpr_1", + "SliceClass": "YZ", + "ReducerFn": "na.nsd", + "ReducerSite": "module_10032.js:15279", + "Actions": [ + "BZ", + "QuestsLoaded", + "SetQuests", + "UpdateQuests", + "AddRewardedQuest", + "SetEventPassShopItemId", + "SetBattleUpdatedQuests" + ], + "HandledBy": "na.nsd(t, n.hpr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15279 根 reducer 委派 na.nsd(t, n.hpr_1);reducer 定义于 module_10032.js:36440" + }, + { + "Field": "language", + "Slot": "ipr_1", + "SliceClass": "l8", + "ReducerFn": "f8().ut9", + "ReducerSite": "module_10032.js:15330", + "Actions": [ + "c8" + ], + "HandledBy": "f8().ut9(t, n.ipr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15330 根 reducer 委派 f8().ut9(t, n.ipr_1);reducer 定义于 module_10032.js:42965" + }, + { + "Field": "partner", + "Slot": "kpr_1", + "SliceClass": null, + "ReducerFn": "(inline IIFE)@module_10032.js:15280", + "ReducerSite": "module_10032.js:15280", + "Actions": [ + "SetPartnerId", + "YJ", + "SetLoginParams", + "SetPartnerParameters", + "InitPartnerInviteAction", + "iZ", + "SetLoginStatusForBinding", + "KJ", + "HJ", + "rZ", + "SetPartnerReady" + ], + "HandledBy": "(function (t, n) { var i; if (t instanceof BJ) i = n.as9(t.ds9_1, fd, fd, fd, fd, fd, fd, ...", + "Confidence": "证据", + "Why": "module_10032.js:15280 根 reducer 内联 IIFE,以第二参 n.kpr_1 为分片状态;链内 instanceof 类即能改该字段的 action" + }, + { + "Field": "entrance", + "Slot": "lpr_1", + "SliceClass": "kit", + "ReducerFn": "Fv.atb", + "ReducerSite": "module_10032.js:15331", + "Actions": [ + "iit", + "rit", + "eit", + "uit", + "SetAgeWarnShow", + "hit", + "cit" + ], + "HandledBy": "Fv.atb(t, n.lpr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15331 根 reducer 委派 Fv.atb(t, n.lpr_1);reducer 定义于 module_10032.js:45754" + }, + { + "Field": "antiAddiction", + "Slot": "mpr_1", + "SliceClass": "YC", + "ReducerFn": "W.kq2", + "ReducerSite": "module_10032.js:15332", + "Actions": [ + "BC", + "KC", + "VC", + "SetRealNameAndIdNumber", + "SetValidateAntiAddictionUserDataStatus" + ], + "HandledBy": "W.kq2(t, n.mpr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15332 根 reducer 委派 W.kq2(t, n.mpr_1);reducer 定义于 module_10032.js:20950" + }, + { + "Field": "spectator", + "Slot": "npr_1", + "SliceClass": "JA", + "ReducerFn": "Li.xqf", + "ReducerSite": "module_10032.js:15334", + "Actions": [ + "SetSpectator", + "UpdateHudLayout", + "VA", + "KA", + "YA", + "WA" + ], + "HandledBy": "Li.xqf(t, n.npr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15334 根 reducer 委派 Li.xqf(t, n.npr_1);reducer 定义于 module_10032.js:23119" + }, + { + "Field": "moderation", + "Slot": "opr_1", + "SliceClass": "sA", + "ReducerFn": "Ei.qqb", + "ReducerSite": "module_10032.js:15333", + "Actions": [ + "LI", + "BI", + "KI", + "YI", + "UI", + "GI", + "WI", + "VI", + "XI", + "JI", + "ZI", + "QI", + "rA" + ], + "HandledBy": "Ei.qqb(t, n.opr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15333 根 reducer 委派 Ei.qqb(t, n.opr_1);reducer 定义于 module_10032.js:22215" + }, + { + "Field": "rulesUpdated", + "Slot": "ppr_1", + "SliceClass": "QQ", + "ReducerFn": "Sa.psf", + "ReducerSite": "module_10032.js:15335", + "Actions": [ + "UpdateRules" + ], + "HandledBy": "Sa.psf(t, n.ppr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15335 根 reducer 委派 Sa.psf(t, n.ppr_1);reducer 定义于 module_10032.js:37075" + }, + { + "Field": "announcement", + "Slot": "qpr_1", + "SliceClass": "IC", + "ReducerFn": "AC().tpz", + "ReducerSite": "module_10032.js:15336", + "Actions": [ + "yC", + "kC", + "Init", + "SetSkipNextPromotedAnnounce" + ], + "HandledBy": "AC().tpz(t, n.qpr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15336 根 reducer 委派 AC().tpz(t, n.qpr_1);reducer 定义于 module_10032.js:20714" + }, + { + "Field": "notificationByCountry", + "Slot": "rpr_1", + "SliceClass": "mJ", + "ReducerFn": "A_.es7", + "ReducerSite": "module_10032.js:15337", + "Actions": [ + "pJ", + "dJ" + ], + "HandledBy": "A_.es7(t, n.rpr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15337 根 reducer 委派 A_.es7(t, n.rpr_1);reducer 定义于 module_10032.js:35463" + }, + { + "Field": "userRenameState", + "Slot": "spr_1", + "SliceClass": "K6", + "ReducerFn": "Af.at8", + "ReducerSite": "module_10032.js:15338", + "Actions": [ + "ChangeUidInputState", + "P6", + "O6", + "N6", + "SetValidationStatus", + "SetRubiesForRename", + "M6", + "ResponseDelivered", + "ResponseActual", + "SetChangeUidParams", + "V6" + ], + "HandledBy": "Af.at8(t, n.spr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15338 根 reducer 委派 Af.at8(t, n.spr_1);reducer 定义于 module_10032.js:42816" + }, + { + "Field": "eventGoods", + "Slot": "tpr_1", + "SliceClass": "G7", + "ReducerFn": "Wc.rsq", + "ReducerSite": "module_10032.js:15339", + "Actions": [ + "InitEventGoods" + ], + "HandledBy": "Wc.rsq(t, n.tpr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15339 根 reducer 委派 Wc.rsq(t, n.tpr_1);reducer 定义于 module_10032.js:38831" + }, + { + "Field": "creatorTagState", + "Slot": "upr_1", + "SliceClass": "jM", + "ReducerFn": "ke.sqv", + "ReducerSite": "module_10032.js:15340", + "Actions": [ + "SetCreatorTags", + "SetCreatorTag", + "$M", + "SetAttachedCreatorTag" + ], + "HandledBy": "ke.sqv(t, n.upr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15340 根 reducer 委派 ke.sqv(t, n.upr_1);reducer 定义于 module_10032.js:27245" + }, + { + "Field": "twoStepVerificationState", + "Slot": "vpr_1", + "SliceClass": "T4", + "ReducerFn": "_f.mt4", + "ReducerSite": "module_10032.js:15341", + "Actions": [ + "SetUse2FA", + "ActivationStatus2FA", + "SetSecretAndQRCode", + "VerificationStatus", + "Enable2FaRequest" + ], + "HandledBy": "_f.mt4(t, n.vpr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15341 根 reducer 委派 _f.mt4(t, n.vpr_1);reducer 定义于 module_10032.js:41472" + }, + { + "Field": "rewardedVideosState", + "Slot": "wpr_1", + "SliceClass": "YQ", + "ReducerFn": "ja.lsf", + "ReducerSite": "module_10032.js:15342", + "Actions": [ + "SetDisplayState" + ], + "HandledBy": "ja.lsf(t, n.wpr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15342 根 reducer 委派 ja.lsf(t, n.wpr_1);reducer 定义于 module_10032.js:37051" + }, + { + "Field": "twitchState", + "Slot": "xpr_1", + "SliceClass": "y4", + "ReducerFn": "uf.st3", + "ReducerSite": "module_10032.js:15343", + "Actions": [ + "SetTwitchEnabled", + "SetAccount", + "SetDaysForNextLinking" + ], + "HandledBy": "uf.st3(t, n.xpr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15343 根 reducer 委派 uf.st3(t, n.xpr_1);reducer 定义于 module_10032.js:41338" + }, + { + "Field": "icons", + "Slot": "ypr_1", + "SliceClass": "eH", + "ReducerFn": "fs.xrn", + "ReducerSite": "module_10032.js:15344", + "Actions": [ + "SetIcons" + ], + "HandledBy": "fs.xrn(t, n.ypr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15344 根 reducer 委派 fs.xrn(t, n.ypr_1);reducer 定义于 module_10032.js:32798" + }, + { + "Field": "itemNotifications", + "Slot": "zpr_1", + "SliceClass": "S1", + "ReducerFn": "C1().ssh", + "ReducerSite": "module_10032.js:15345", + "Actions": [ + "AddItemNotifications", + "y1", + "k1", + "q1", + "$1", + "sC" + ], + "HandledBy": "C1().ssh(t, n.zpr_1)", + "Confidence": "证据", + "Why": "module_10032.js:15345 根 reducer 委派 C1().ssh(t, n.zpr_1);reducer 定义于 module_10032.js:37474" + }, + { + "Field": "contextTutorial", + "Slot": "aps_1", + "SliceClass": "Kst", + "ReducerFn": "Yst().etb", + "ReducerSite": "module_10032.js:15346", + "Actions": [ + "LoadCurrentElement", + "SetUnViewedElements", + "MarkElementAsViewed", + "SetLoadedElements", + "SetMissionToElement" + ], + "HandledBy": "Yst().etb(t, n.aps_1)", + "Confidence": "证据", + "Why": "module_10032.js:15346 根 reducer 委派 Yst().etb(t, n.aps_1);reducer 定义于 module_10032.js:49277" + }, + { + "Field": "suppliesTutorial", + "Slot": "bps_1", + "SliceClass": "cst", + "ReducerFn": "Gp.ftb", + "ReducerSite": "module_10032.js:15347", + "Actions": [ + "ActivatedInCurrentBattle", + "SetLoadedElement" + ], + "HandledBy": "Gp.ftb(t, n.bps_1)", + "Confidence": "证据", + "Why": "module_10032.js:15347 根 reducer 委派 Gp.ftb(t, n.bps_1);reducer 定义于 module_10032.js:48930" + }, + { + "Field": "questCategories", + "Slot": "cps_1", + "SliceClass": "bZ", + "ReducerFn": "Q_.xsa", + "ReducerSite": "module_10032.js:15349", + "Actions": [ + "SetQuestCategories", + "RemoveQuestCategory", + "RequestQuestCategoriesStatistic", + "SetQuestCategoriesStatistic" + ], + "HandledBy": "Q_.xsa(t, n.cps_1)", + "Confidence": "证据", + "Why": "module_10032.js:15349 根 reducer 委派 Q_.xsa(t, n.cps_1);reducer 定义于 module_10032.js:35932" + }, + { + "Field": "proBattle", + "Slot": "dps_1", + "SliceClass": "Xtt", + "ReducerFn": "_v.htb", + "ReducerSite": "module_10032.js:15350", + "Actions": [ + "Fight", + "SetPassword" + ], + "HandledBy": "_v.htb(t, n.dps_1)", + "Confidence": "证据", + "Why": "module_10032.js:15350 根 reducer 委派 _v.htb(t, n.dps_1);reducer 定义于 module_10032.js:45191" + }, + { + "Field": "availabilityByRank", + "Slot": "eps_1", + "SliceClass": "eet", + "ReducerFn": "zw.itb", + "ReducerSite": "module_10032.js:15351", + "Actions": [ + "SetLoadedData" + ], + "HandledBy": "zw.itb(t, n.eps_1)", + "Confidence": "证据", + "Why": "module_10032.js:15351 根 reducer 委派 zw.itb(t, n.eps_1);reducer 定义于 module_10032.js:48398" + }, + { + "Field": "userReportsState", + "Slot": "fps_1", + "SliceClass": "kot", + "ReducerFn": "(null == _d && new kot(), _d).ktb", + "ReducerSite": "module_10032.js:15352", + "Actions": [ + "aot", + "SetAvailableReports", + "SetAvailableGameReports", + "ReportProBattleName", + "ReportLobbyChatMessage", + "ReportBattleChatMessage" + ], + "HandledBy": "(null == _d && new kot(), _d).ktb(t, n.fps_1)", + "Confidence": "证据", + "Why": "module_10032.js:15352 根 reducer 委派 (null == _d && new kot(), _d).ktb(t, n.fps_1);reducer 定义于 module_10032.js:49696" + }, + { + "Field": "tankBuilderState", + "Slot": "gps_1", + "SliceClass": "Ert", + "ReducerFn": "gw.ltb", + "ReducerSite": "module_10032.js:15353", + "Actions": [ + "SetKode", + "SetParts", + "SetPartsInfo", + "Crt" + ], + "HandledBy": "gw.ltb(t, n.gps_1)", + "Confidence": "证据", + "Why": "module_10032.js:15353 根 reducer 委派 gw.ltb(t, n.gps_1);reducer 定义于 module_10032.js:46392" + }, + { + "Field": "contractState", + "Slot": "hps_1", + "SliceClass": "Gnt", + "ReducerFn": "Sv.mtb", + "ReducerSite": "module_10032.js:15354", + "Actions": [ + "SetActiveContract", + "SetContract", + "UpdateProgress", + "SetBattleProgress", + "GetReward", + "Fnt", + "LR" + ], + "HandledBy": "Sv.mtb(t, n.hps_1)", + "Confidence": "证据", + "Why": "module_10032.js:15354 根 reducer 委派 Sv.mtb(t, n.hps_1);reducer 定义于 module_10032.js:45645" + }, + { + "Field": "promoCode", + "Slot": "ips_1", + "SliceClass": "hZ", + "ReducerFn": "Z_.ksa", + "ReducerSite": "module_10032.js:15355", + "Actions": [ + "ActivatePromoCode", + "SetCodeValidateStatus" + ], + "HandledBy": "Z_.ksa(t, n.ips_1)", + "Confidence": "证据", + "Why": "module_10032.js:15355 根 reducer 委派 Z_.ksa(t, n.ips_1);reducer 定义于 module_10032.js:35824" + }, + { + "Field": "referralEvent", + "Slot": "jps_1", + "SliceClass": "pQ", + "ReducerFn": "ca.ase", + "ReducerSite": "module_10032.js:15356", + "Actions": [ + "SetReferralEventData", + "SetPromoCode", + "SetReferrals", + "SetReferrer" + ], + "HandledBy": "ca.ase(t, n.jps_1)", + "Confidence": "证据", + "Why": "module_10032.js:15356 根 reducer 委派 ca.ase(t, n.jps_1);reducer 定义于 module_10032.js:36632" + }, + { + "Field": "supportUrl", + "Slot": "kps_1", + "SliceClass": "T9", + "ReducerFn": "Yl.ot0", + "ReducerSite": "module_10032.js:15357", + "Actions": [ + "SetUrl", + "E9" + ], + "HandledBy": "Yl.ot0(t, n.kps_1); return n.ntb( i, r, N, s, o, e, u, _, c, $, q, h, a, P, l, w, p, d, m,...", + "Confidence": "证据", + "Why": "module_10032.js:15357 根 reducer 委派 Yl.ot0(t, n.kps_1);reducer 定义于 module_10032.js:41036" + } + ], + "Unmapped": [ + { + "Field": "launchParams", + "Slot": "jpr_1", + "Why": "module_10032.js:15329 根 reducer 直接透传(n.jpr_1),无任何 reducer 处理,字段一经初始化不再变化" + } + ], + "Stats": { + "Total": 89, + "证据": 88, + "推断": 0, + "未映射": 1 + } +} \ No newline at end of file