feat(state): 迁移 tipsState/rankUpDialogState/battleResult/captchaState/modalScreen/droppableGold/eventGoods/creatorTagState/rewardedVideosState/passwordChangeState
This commit is contained in:
1 parent
6d2487d9ea
commit
8633fc91c1
17 files changed
+1206
-68
No files matched your search
@@ -143,7 +143,7 @@
|
||||
`names/root_wiring.json` + `TankiOffline/.../App/State/RootState.kt`、`RootWiring.kt`。
|
||||
- 根状态 `z6`(`TOState`)的 **89 个槽位**全部入表;字段顺序取 `toString`,槽位取构造函数 `<名>_1`。
|
||||
- 根 reducer `k6` 的逐切片委派记全:reducer 引用、委派表达式、顶层 `instanceof` 动作名。
|
||||
- 已迁移切片 **33/89**:
|
||||
- 已迁移切片 **43/89**:
|
||||
- `inviteState` → `aD` / `pD.er5`(`InviteReducer.kt`)
|
||||
- `loginByPassword` → `gD` / `MD.cr6`(`LoginReducer.kt`,含 `SetLogin`/`SetPassword` 把 status 打回 `NONE` 的原语义)
|
||||
- `twitchState` → `g9` / `y9.gta`(`TwitchReducer.kt`;`SetAccount` 是 Twitch 账号,不是 UID)
|
||||
@@ -256,12 +256,35 @@
|
||||
- `referralEvent` → `pQ` / `lh.osk`(`ReferralEventReducer.kt`):14 字段,4 个实例臂。
|
||||
`SetReferrer` 写前 2 字段、`SetReferrals` 写人数与明细、`SetPromoCode` 写邀请码;
|
||||
`SetReferralEventData` 一次写后 9 个字段(面板标题 / 弹窗图与背景 / 两个分类 id / 任务数 / 两个隐藏标志 / 公告时间)。
|
||||
- `tipsState` → `dst` / `Hw.vth`(`TipsStateReducer.kt`):1 字段,`UpdateTips` 整体替换提示列表,缺省空表。
|
||||
- `rankUpDialogState` → `LO` / `Se.br3`(`RankUpDialogReducer.kt`):1 字段,2 个分支。
|
||||
`ShowAvailableItems` 是**追加**(`Im`:元素或整表),`FO`→`ResetRankUpDialog` 直接 `new LO()` 清空。
|
||||
- `battleResult` → `sR` / `Fi.aqp`(`BattleResultReducer.kt`):5 字段,6 个实例臂。
|
||||
`SetRewards` / `SetHasBattleResult` 写前两字段;`cR`/`lR`→`SetIncreasedReward`/`SetSimpleReward` 写两个奖励数值;
|
||||
`fR`→`ResetBattleRewards` 只把两数值归零;`DoInit` 重建状态只带 `initialCurrentUserXP`。
|
||||
- `captchaState` → `jP` / `ar.iqt`(`CaptchaStateReducer.kt`):4 字段,7 个实例臂。
|
||||
三个位置集合缺省 `emptySet()`;`SetLocations` 用 `toSet()` 收口;
|
||||
`SP`→`ShowFakeCaptcha` 只置 `useFake`,其余是启用 / 已验证 / 待重置集合的增删元素。
|
||||
- `modalScreen` → `nV` / `Fs.js1`(`ModalScreenReducer.kt`):2 字段,4 个分支。
|
||||
`AddModal` 按 `toString()` 判重后 `current=screenId` 并入队;`RemoveModal` 出队后 `current = queue.firstOrNull()`;
|
||||
`XW`→`CloseCurrentModal` 关当前窗口;`RemoveCurrentByName` 名称不匹配时 no-op。
|
||||
- `droppableGold` → `Vet` / `Wp.kth`(`DroppableGoldReducer.kt`):1 字段,缺省 `showDroppableGoldAuthor=true`;
|
||||
`Ket`/`Yet` 两个单例 → `ShowDroppableGoldAuthor` / `HideDroppableGoldAuthor`。
|
||||
- `eventGoods` → `W7` / `Wc.esx`(`EventGoodsReducer.kt`):1 字段 `Map<Any?, Any?>`,缺省空 Map;
|
||||
`InitEventGoods(itemId, goods)` 在 `goods == null` 时删键,否则写键值。
|
||||
- `creatorTagState` → `qO` / `ze.er2`(`CreatorTagReducer.kt`):2 字段,4 个分支。
|
||||
`creatorTags` 缺省 null;`SetCreatorTags` / `SetCreatorTag` / `SetAttachedCreatorTag` 写对应字段,
|
||||
`jO`→`ClearCreatorTag` 只清 `creatorTag`。
|
||||
- `rewardedVideosState` → `JQ` / `xh.zsl`(`RewardedVideosReducer.kt`):1 字段,
|
||||
新增枚举 `RewardVideoDisplayState { NONE, LOADING, DISPLAY }`,缺省 `NONE`;`SetDisplayState` 整体替换。
|
||||
- `passwordChangeState` → `VD` / `uu.pr6`(`PasswordChangeReducer.kt`):3 个字符串字段(hash / uid / email),
|
||||
缺省全为空串;`SetPasswordChangeHash` 只写 hash,`ShowEmailAndPasswordChangeDialog` 写 uid/email 并保留 hash。
|
||||
- `launchParams` → `(pass-through)`:原根 reducer 对 `hpx_1` 没有调用,缺省是 `ag()` 空 Map;
|
||||
`RootState.LaunchParams` 收口为 `LaunchParamsStateSlice = Map<String, String>`,不新增 reducer/动作。
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 32 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **56 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 33/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **457 项全绿**,含 89 槽位完整性、32 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 42 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **46 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 43/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **529 项全绿**,含 89 槽位完整性、42 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
以及用 `action_trace_merged.json` 真实派发的两条商店动作(`SetCoinPaymentProviderUrl` / `ToggleShopActivity`)回放。
|
||||
- 委派表里的已知形态:`shop` / `home` / `localBattleUserState` / `partner` 是内联 IIFE,
|
||||
已按字段具名为 `(inline@<field>)` 并从函数体抓到顶层动作名(69 / 1 / 2 / 11 个);
|
||||
@@ -274,7 +297,8 @@
|
||||
entrance 的 6 个、user 的 3 个、settings 的 2 个、accountSettings 的 11 个、
|
||||
language 的 1 个、announcement 的 3 个、news 的 3 个(含两个单例)、notifications 的 2 个、
|
||||
quests 的 1 个、lobbyLoader 的 2 个、purchaseDialogState 的 1 个、supportUrl 的 1 个、
|
||||
notificationByCountry 的 1 个、mainQuest 的 1 个匿名类 / 单例同样按效果定名并登记。
|
||||
notificationByCountry 的 1 个、mainQuest 的 1 个、rankUpDialogState 的 1 个、battleResult 的 3 个、
|
||||
captchaState 的 5 个、modalScreen 的 1 个、droppableGold 的 2 个、creatorTagState 的 1 个匿名类 / 单例同样按效果定名并登记。
|
||||
|
||||
### S4 引擎核心
|
||||
- 模块:32088(3D 数学)、92980(渲染)、61378(ECS)、55088(物理)、36659 + 71105(资源)、36734(音频)、3569(输入)
|
||||
|
||||
+115
-27
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generatedAt": "2026-10-24T06:01:37.203Z",
|
||||
"generatedAt": "2026-10-24T06:30:01.615Z",
|
||||
"module": "module_10032.js",
|
||||
"RootState": {
|
||||
"Class": "z6",
|
||||
@@ -39,7 +39,17 @@
|
||||
"questCategories",
|
||||
"mainQuest",
|
||||
"securitySettings",
|
||||
"referralEvent"
|
||||
"referralEvent",
|
||||
"tipsState",
|
||||
"rankUpDialogState",
|
||||
"battleResult",
|
||||
"captchaState",
|
||||
"modalScreen",
|
||||
"droppableGold",
|
||||
"eventGoods",
|
||||
"creatorTagState",
|
||||
"rewardedVideosState",
|
||||
"passwordChangeState"
|
||||
],
|
||||
"AnonymousActions": [
|
||||
{
|
||||
@@ -708,6 +718,84 @@
|
||||
"Name": "ResetQuestsLoaded",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "isLoaded=false(`n.qsj(!1)`;动作类 rsj_1 在 reducer 里未被读取)"
|
||||
},
|
||||
{
|
||||
"Local": "FO",
|
||||
"Name": "ResetRankUpDialog",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "availableItems=emptyList()(`new LO()`)"
|
||||
},
|
||||
{
|
||||
"Local": "cR",
|
||||
"Name": "SetIncreasedReward",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "increasedReward=动作数值(`n.qqn(cd, cd, cd, t.cqp_1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "lR",
|
||||
"Name": "SetSimpleReward",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "simpleReward=动作数值(`n.qqn(cd, cd, cd, cd, t.bqp_1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "fR",
|
||||
"Name": "ResetBattleRewards",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "increasedReward=0、simpleReward=0(`n.qqn(cd, cd, cd, 0, 0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "SP",
|
||||
"Name": "ShowFakeCaptcha",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "useFake=true(`n.wqs(!0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "IP",
|
||||
"Name": "AddVerifiedCaptchaLocation",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "verifiedLocations + location(`Xg`)"
|
||||
},
|
||||
{
|
||||
"Local": "AP",
|
||||
"Name": "RemoveVerifiedCaptchaLocation",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "verifiedLocations - location(`Jg`)"
|
||||
},
|
||||
{
|
||||
"Local": "RP",
|
||||
"Name": "AddCaptchaLocationToReset",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "locationsToReset + location(`Xg`)"
|
||||
},
|
||||
{
|
||||
"Local": "PP",
|
||||
"Name": "RemoveCaptchaLocationToReset",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "locationsToReset - location(`Jg`)"
|
||||
},
|
||||
{
|
||||
"Local": "XW",
|
||||
"Name": "CloseCurrentModal",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "current 非空时 queue -= current、current=queue.firstOrNull()"
|
||||
},
|
||||
{
|
||||
"Local": "Ket",
|
||||
"Name": "ShowDroppableGoldAuthor",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "showDroppableGoldAuthor=true(`n.f7j(!0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "Yet",
|
||||
"Name": "HideDroppableGoldAuthor",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "showDroppableGoldAuthor=false(`n.f7j(!1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "jO",
|
||||
"Name": "ClearCreatorTag",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "creatorTag=null(`n.ar2(null)`)"
|
||||
}
|
||||
],
|
||||
"Markers": [
|
||||
@@ -822,13 +910,13 @@
|
||||
"Reducer": "Fs.js1",
|
||||
"Delegate": "Fs.js1(t, n.apv_1)",
|
||||
"Actions": [
|
||||
"?XW",
|
||||
"AddModal",
|
||||
"CloseCurrentModal",
|
||||
"RemoveCurrentByName",
|
||||
"RemoveModal"
|
||||
],
|
||||
"Default": "new nV()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "battleStatistics",
|
||||
@@ -1093,16 +1181,16 @@
|
||||
"Reducer": "ar.iqt",
|
||||
"Delegate": "ar.iqt(t, n.kpv_1)",
|
||||
"Actions": [
|
||||
"?AP",
|
||||
"?IP",
|
||||
"?PP",
|
||||
"?RP",
|
||||
"?SP",
|
||||
"AddCaptchaLocationToReset",
|
||||
"AddVerifiedCaptchaLocation",
|
||||
"LocationsUpdated",
|
||||
"SetLocations"
|
||||
"RemoveCaptchaLocationToReset",
|
||||
"RemoveVerifiedCaptchaLocation",
|
||||
"SetLocations",
|
||||
"ShowFakeCaptcha"
|
||||
],
|
||||
"Default": "new jP()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "passwordChangeState",
|
||||
@@ -1115,7 +1203,7 @@
|
||||
"ShowEmailAndPasswordChangeDialog"
|
||||
],
|
||||
"Default": "new VD()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "system",
|
||||
@@ -1283,7 +1371,7 @@
|
||||
"UpdateTips"
|
||||
],
|
||||
"Default": "new dst()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "news",
|
||||
@@ -1556,15 +1644,15 @@
|
||||
"Reducer": "Fi.aqp",
|
||||
"Delegate": "Fi.aqp(t, n.gpw_1)",
|
||||
"Actions": [
|
||||
"?cR",
|
||||
"?fR",
|
||||
"?lR",
|
||||
"DoInit",
|
||||
"ResetBattleRewards",
|
||||
"SetHasBattleResult",
|
||||
"SetRewards"
|
||||
"SetIncreasedReward",
|
||||
"SetRewards",
|
||||
"SetSimpleReward"
|
||||
],
|
||||
"Default": "new sR()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "battleUsers",
|
||||
@@ -1758,11 +1846,11 @@
|
||||
"Reducer": "Se.br3",
|
||||
"Delegate": "Se.br3(t, n.npw_1)",
|
||||
"Actions": [
|
||||
"?FO",
|
||||
"ResetRankUpDialog",
|
||||
"ShowAvailableItems"
|
||||
],
|
||||
"Default": "new LO()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "clanUserInfo",
|
||||
@@ -1833,11 +1921,11 @@
|
||||
"Reducer": "Wp.kth",
|
||||
"Delegate": "Wp.kth(t, n.spw_1)",
|
||||
"Actions": [
|
||||
"?Ket",
|
||||
"?Yet"
|
||||
"HideDroppableGoldAuthor",
|
||||
"ShowDroppableGoldAuthor"
|
||||
],
|
||||
"Default": "new Vet()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "home",
|
||||
@@ -2212,7 +2300,7 @@
|
||||
"InitEventGoods"
|
||||
],
|
||||
"Default": "new W7()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "creatorTagState",
|
||||
@@ -2221,13 +2309,13 @@
|
||||
"Reducer": "ze.er2",
|
||||
"Delegate": "ze.er2(t, n.spx_1)",
|
||||
"Actions": [
|
||||
"?jO",
|
||||
"ClearCreatorTag",
|
||||
"SetAttachedCreatorTag",
|
||||
"SetCreatorTag",
|
||||
"SetCreatorTags"
|
||||
],
|
||||
"Default": "new qO()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "twoStepVerificationState",
|
||||
@@ -2255,7 +2343,7 @@
|
||||
"SetDisplayState"
|
||||
],
|
||||
"Default": "new JQ()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "twitchState",
|
||||
|
||||
@@ -181,6 +181,25 @@ const AnonymousActionNames = new Map([
|
||||
['qJ', 'MarkHomeScreenDialogShown'],
|
||||
// mainQuest 切片(WZ / ih.bsk):VZ 没有 toString,按 reducer 效果定名。
|
||||
['VZ', 'ResetQuestsLoaded'],
|
||||
// rankUpDialogState 切片(LO / GO.br3):FO 没有 toString。
|
||||
['FO', 'ResetRankUpDialog'],
|
||||
// battleResult 切片(sR / pR.aqp):cR/lR/fR 没有 toString。
|
||||
['cR', 'SetIncreasedReward'],
|
||||
['lR', 'SetSimpleReward'],
|
||||
['fR', 'ResetBattleRewards'],
|
||||
// captchaState 切片(jP / MP.iqt):SP/IP/AP/RP/PP 没有 toString。
|
||||
['SP', 'ShowFakeCaptcha'],
|
||||
['IP', 'AddVerifiedCaptchaLocation'],
|
||||
['AP', 'RemoveVerifiedCaptchaLocation'],
|
||||
['RP', 'AddCaptchaLocationToReset'],
|
||||
['PP', 'RemoveCaptchaLocationToReset'],
|
||||
// modalScreen 切片(nV / QW.js1):XW 没有 toString。
|
||||
['XW', 'CloseCurrentModal'],
|
||||
// droppableGold 切片(Vet / Xet.kth):Ket/Yet 两个单例。
|
||||
['Ket', 'ShowDroppableGoldAuthor'],
|
||||
['Yet', 'HideDroppableGoldAuthor'],
|
||||
// creatorTagState 切片(qO / SO.er2):jO 没有 toString。
|
||||
['jO', 'ClearCreatorTag'],
|
||||
]);
|
||||
|
||||
// 非动作的 `instanceof`:屏幕标识类,用于 GoTo 分支判断(不是 dispatch 的动作)。
|
||||
@@ -599,6 +618,16 @@ const Migrated = {
|
||||
mainQuest: { Type: 'MainQuestStateSlice', Reduce: 'ReduceMainQuest' },
|
||||
securitySettings: { Type: 'SecuritySettingsStateSlice', Reduce: 'ReduceSecuritySettings' },
|
||||
referralEvent: { Type: 'ReferralEventStateSlice', Reduce: 'ReduceReferralEvent' },
|
||||
tipsState: { Type: 'TipsStateSlice', Reduce: 'ReduceTips' },
|
||||
rankUpDialogState: { Type: 'RankUpDialogStateSlice', Reduce: 'ReduceRankUpDialog' },
|
||||
battleResult: { Type: 'BattleResultStateSlice', Reduce: 'ReduceBattleResult' },
|
||||
captchaState: { Type: 'CaptchaStateSlice', Reduce: 'ReduceCaptcha' },
|
||||
modalScreen: { Type: 'ModalScreenStateSlice', Reduce: 'ReduceModalScreen' },
|
||||
droppableGold: { Type: 'DroppableGoldStateSlice', Reduce: 'ReduceDroppableGold' },
|
||||
eventGoods: { Type: 'EventGoodsStateSlice', Reduce: 'ReduceEventGoods' },
|
||||
creatorTagState: { Type: 'CreatorTagStateSlice', Reduce: 'ReduceCreatorTag' },
|
||||
rewardedVideosState: { Type: 'RewardedVideosStateSlice', Reduce: 'ReduceRewardedVideos' },
|
||||
passwordChangeState: { Type: 'PasswordChangeStateSlice', Reduce: 'ReducePasswordChange' },
|
||||
};
|
||||
|
||||
for (const R of Rows) R.Migrated = Object.prototype.hasOwnProperty.call(Migrated, R.Field);
|
||||
@@ -811,6 +840,43 @@ const MainQuestAnonymousEffects = {
|
||||
VZ: 'isLoaded=false(`n.qsj(!1)`;动作类 rsj_1 在 reducer 里未被读取)',
|
||||
};
|
||||
|
||||
// rankUpDialogState 切片(LO / GO.br3):FO 没有 toString。
|
||||
const RankUpDialogAnonymousEffects = {
|
||||
FO: 'availableItems=emptyList()(`new LO()`)',
|
||||
};
|
||||
|
||||
// battleResult 切片(sR / pR.aqp):cR/lR/fR 没有 toString。
|
||||
const BattleResultAnonymousEffects = {
|
||||
cR: 'increasedReward=动作数值(`n.qqn(cd, cd, cd, t.cqp_1)`)',
|
||||
lR: 'simpleReward=动作数值(`n.qqn(cd, cd, cd, cd, t.bqp_1)`)',
|
||||
fR: 'increasedReward=0、simpleReward=0(`n.qqn(cd, cd, cd, 0, 0)`)',
|
||||
};
|
||||
|
||||
// captchaState 切片(jP / MP.iqt):SP/IP/AP/RP/PP 没有 toString。
|
||||
const CaptchaAnonymousEffects = {
|
||||
SP: 'useFake=true(`n.wqs(!0)`)',
|
||||
IP: 'verifiedLocations + location(`Xg`)',
|
||||
AP: 'verifiedLocations - location(`Jg`)',
|
||||
RP: 'locationsToReset + location(`Xg`)',
|
||||
PP: 'locationsToReset - location(`Jg`)',
|
||||
};
|
||||
|
||||
// modalScreen 切片(nV / QW.js1):XW 没有 toString。
|
||||
const ModalScreenAnonymousEffects = {
|
||||
XW: 'current 非空时 queue -= current、current=queue.firstOrNull()',
|
||||
};
|
||||
|
||||
// droppableGold 切片(Vet / Xet.kth):Ket/Yet 是单例。
|
||||
const DroppableGoldAnonymousEffects = {
|
||||
Ket: 'showDroppableGoldAuthor=true(`n.f7j(!0)`)',
|
||||
Yet: 'showDroppableGoldAuthor=false(`n.f7j(!1)`)',
|
||||
};
|
||||
|
||||
// creatorTagState 切片(qO / SO.er2):jO 没有 toString。
|
||||
const CreatorTagAnonymousEffects = {
|
||||
jO: 'creatorTag=null(`n.ar2(null)`)',
|
||||
};
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(P, 'names', 'root_wiring.json'),
|
||||
JSON.stringify(
|
||||
@@ -941,6 +1007,42 @@ fs.writeFileSync(
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(RankUpDialogAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(BattleResultAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(CaptchaAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(ModalScreenAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(DroppableGoldAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(CreatorTagAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
],
|
||||
Markers: [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
// BattleResultReducer.kt —— 战斗结算切片(对应 module_10032 的 sR 状态 + pR.aqp)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 sR:5 个字段,字段名取自 toString;copy 是 qqn(5 字段 + 回调)。
|
||||
// 默认:hasBattleResult=false、rewards=emptyList()、initialCurrentUserXP=0、increasedReward=0、simpleReward=0。
|
||||
// 根委派:`Fi.aqp(t, n.gpw_1)`。
|
||||
// reducer:
|
||||
// aR(SetRewards) → rewards
|
||||
// hR(SetHasBattleResult)→ hasBattleResult
|
||||
// cR(无 toString) → increasedReward
|
||||
// lR(无 toString) → simpleReward
|
||||
// fR(无 toString) → increasedReward=0、simpleReward=0
|
||||
// vR(DoInit) → 全新状态,只带 initialCurrentUserXP(`new sR(cd, cd, t.zqo_1)`)
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.ContainerGivenItem
|
||||
import App.State.DoInit
|
||||
import App.State.SetHasBattleResult
|
||||
import App.State.SetRewards
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `cR`:写「加成后奖励」数值。 */
|
||||
data class SetIncreasedReward(val value: Int)
|
||||
|
||||
/** 原 `lR`:写「原始奖励」数值。 */
|
||||
data class SetSimpleReward(val value: Int)
|
||||
|
||||
/** 原 `fR`:把两个奖励数值归零。 */
|
||||
object ResetBattleRewards
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class BattleResultStateSlice(
|
||||
val HasBattleResult: Boolean = false,
|
||||
val Rewards: List<ContainerGivenItem> = emptyList(),
|
||||
val InitialCurrentUserXP: Any? = null,
|
||||
val IncreasedReward: Int = 0,
|
||||
val SimpleReward: Int = 0,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceBattleResult(
|
||||
State0: BattleResultStateSlice,
|
||||
Action: Any,
|
||||
): BattleResultStateSlice = when (Action) {
|
||||
is SetRewards -> State0.copy(Rewards = Action.rewards)
|
||||
is SetHasBattleResult -> State0.copy(HasBattleResult = Action.hasBattleResult)
|
||||
is SetIncreasedReward -> State0.copy(IncreasedReward = Action.value)
|
||||
is SetSimpleReward -> State0.copy(SimpleReward = Action.value)
|
||||
is ResetBattleRewards -> State0.copy(IncreasedReward = 0, SimpleReward = 0)
|
||||
is DoInit -> BattleResultStateSlice(InitialCurrentUserXP = Action.initialCurrentUserXP)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// CaptchaStateReducer.kt —— 验证码切片(对应 module_10032 的 jP 状态 + MP.iqt)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 jP:4 个字段,copy 是 wqs(4 字段 + 回调)。
|
||||
// 默认:useFake=false,三个位置集合都是 `Yg()` = emptySet()。
|
||||
// 根委派:`ar.iqt(t, n.kpv_1)`。
|
||||
// reducer:
|
||||
// SP(无 toString) → useFake=true
|
||||
// CP(SetLocations) → enabledLocations = Sm(captchaLocations)(`Sm` = toSet)
|
||||
// IP(无 toString) → verifiedLocations + location(`Xg` = 集合加元素)
|
||||
// AP(无 toString) → verifiedLocations - location(`Jg` = 集合删元素)
|
||||
// RP(无 toString) → locationsToReset + location
|
||||
// PP(无 toString) → locationsToReset - location
|
||||
// NP(LocationsUpdated)→ enabledLocations + location
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.LocationsUpdated
|
||||
import App.State.SetLocations
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `SP`:开启假验证码(`n.wqs(!0)`)。 */
|
||||
object ShowFakeCaptcha
|
||||
|
||||
/** 原 `IP`:把地点加入已验证集合。 */
|
||||
data class AddVerifiedCaptchaLocation(val location: Any?)
|
||||
|
||||
/** 原 `AP`:把地点移出已验证集合。 */
|
||||
data class RemoveVerifiedCaptchaLocation(val location: Any?)
|
||||
|
||||
/** 原 `RP`:把地点加入待重置集合。 */
|
||||
data class AddCaptchaLocationToReset(val location: Any?)
|
||||
|
||||
/** 原 `PP`:把地点移出待重置集合。 */
|
||||
data class RemoveCaptchaLocationToReset(val location: Any?)
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class CaptchaStateSlice(
|
||||
val UseFake: Boolean = false,
|
||||
val EnabledLocations: Set<Any?> = emptySet(),
|
||||
val VerifiedLocations: Set<Any?> = emptySet(),
|
||||
val LocationsToReset: Set<Any?> = emptySet(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceCaptcha(
|
||||
State0: CaptchaStateSlice,
|
||||
Action: Any,
|
||||
): CaptchaStateSlice = when (Action) {
|
||||
is ShowFakeCaptcha -> State0.copy(UseFake = true)
|
||||
is SetLocations -> State0.copy(
|
||||
EnabledLocations = (Action.captchaLocations as List<Any?>).toSet(),
|
||||
)
|
||||
is AddVerifiedCaptchaLocation ->
|
||||
State0.copy(VerifiedLocations = State0.VerifiedLocations + Action.location)
|
||||
is RemoveVerifiedCaptchaLocation ->
|
||||
State0.copy(VerifiedLocations = State0.VerifiedLocations - Action.location)
|
||||
is AddCaptchaLocationToReset ->
|
||||
State0.copy(LocationsToReset = State0.LocationsToReset + Action.location)
|
||||
is RemoveCaptchaLocationToReset ->
|
||||
State0.copy(LocationsToReset = State0.LocationsToReset - Action.location)
|
||||
is LocationsUpdated ->
|
||||
State0.copy(EnabledLocations = State0.EnabledLocations + Action.location)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// CreatorTagReducer.kt —— 创作者标签切片(对应 module_10032 的 qO 状态 + SO.er2)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 qO:2 个字段,toString 名 "CreatorTagState(creatorTag=…, creatorTags=…)";copy 是 ar2(2 字段)。
|
||||
// 默认:creatorTag=null、creatorTags=null。
|
||||
// 根委派:`ze.er2(t, n.spx_1)`。
|
||||
// reducer:
|
||||
// yO(SetCreatorTags) → creatorTags
|
||||
// $O(SetCreatorTag) → creatorTag
|
||||
// jO(无 toString) → creatorTag=null(`n.ar2(null)`)
|
||||
// xO(SetAttachedCreatorTag) → creatorTag
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.SetAttachedCreatorTag
|
||||
import App.State.SetCreatorTag
|
||||
import App.State.SetCreatorTags
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `jO`:清空已挂载的创作者标签。 */
|
||||
object ClearCreatorTag
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class CreatorTagStateSlice(
|
||||
val CreatorTag: Any? = null,
|
||||
val CreatorTags: List<Any?>? = null,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceCreatorTag(
|
||||
State0: CreatorTagStateSlice,
|
||||
Action: Any,
|
||||
): CreatorTagStateSlice = when (Action) {
|
||||
is SetCreatorTags ->
|
||||
State0.copy(CreatorTags = Action.creatorTags as List<Any?>?)
|
||||
is SetCreatorTag -> State0.copy(CreatorTag = Action.creatorTag)
|
||||
is SetAttachedCreatorTag -> State0.copy(CreatorTag = Action.creatorTag)
|
||||
is ClearCreatorTag -> State0.copy(CreatorTag = null)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// DroppableGoldReducer.kt —— 掉落金币署名开关切片(对应 module_10032 的 Vet 状态 + Xet.kth)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 Vet:1 个字段,copy 是 f7j(1 字段)。
|
||||
// 默认:`showDroppableGoldAuthor=true`。
|
||||
// 根委派:`Wp.kth(t, n.spw_1)`。
|
||||
// reducer:`Ket ? n.f7j(!0) : Yet ? n.f7j(!1) : n`。
|
||||
package App.State.Reducers
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `Ket` 单例:显示掉落金币的作者署名。 */
|
||||
object ShowDroppableGoldAuthor
|
||||
|
||||
/** 原 `Yet` 单例:隐藏掉落金币的作者署名。 */
|
||||
object HideDroppableGoldAuthor
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class DroppableGoldStateSlice(
|
||||
val ShowDroppableGoldAuthor: Boolean = true,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceDroppableGold(
|
||||
State0: DroppableGoldStateSlice,
|
||||
Action: Any,
|
||||
): DroppableGoldStateSlice = when (Action) {
|
||||
is ShowDroppableGoldAuthor -> State0.copy(ShowDroppableGoldAuthor = true)
|
||||
is HideDroppableGoldAuthor -> State0.copy(ShowDroppableGoldAuthor = false)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// EventGoodsReducer.kt —— 活动商品表切片(对应 module_10032 的 W7 状态 + K7.esx)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 W7:1 个字段,toString 名 "EventGoodsState(eventGoods=…)";copy 是 bsx(1 字段)。
|
||||
// 默认:eventGoods = ag() = emptyMap()。
|
||||
// 根委派:`Wc.esx(t, n.rpx_1)`。
|
||||
// reducer:`t instanceof V7 ? (goods 为空 ? map 删键 : map 写键值) : n`
|
||||
// V7 = InitEventGoods(itemId, goods);`am` = map 删键、`cg` = map 写键值。
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.InitEventGoods
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class EventGoodsStateSlice(
|
||||
val EventGoods: Map<Any?, Any?> = emptyMap(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceEventGoods(
|
||||
State0: EventGoodsStateSlice,
|
||||
Action: Any,
|
||||
): EventGoodsStateSlice = when (Action) {
|
||||
is InitEventGoods -> State0.copy(
|
||||
EventGoods =
|
||||
if (Action.goods == null) State0.EventGoods - Action.itemId
|
||||
else State0.EventGoods + (Action.itemId to Action.goods),
|
||||
)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// ModalScreenReducer.kt —— 模态窗口队列切片(对应 module_10032 的 nV 状态 + QW.js1)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 nV:2 个字段,toString 名 "ModalScreen(current=…, modalQueue=…)";copy 是 ks1(2 字段)。
|
||||
// 默认:current=null、modalQueue=emptyList()。
|
||||
// 根委派:`Fs.js1(t, n.apv_1)`。
|
||||
// reducer:
|
||||
// YW(AddModal) → 队列里已有同名窗口时 no-op;否则 current=screenId、queue += screenId。
|
||||
// 原判重是 `Xd(e, iV) && n.ls1(e)`:`ls1` 用 `toString()` 比较队列元素。
|
||||
// `iV` 是模态屏幕标识的标记接口,Kotlin 侧按「所有 AddModal 都参与判重」处理。
|
||||
// JW(RemoveModal)→ queue -= screenId、current = queue.firstOrNull()(`mk` = firstOrNull)
|
||||
// XW(无 toString) → current 为空时 no-op;否则 queue -= current、current = queue.firstOrNull()
|
||||
// ZW(RemoveCurrentByName)→ current 为空或 toString 不等于 name 时 no-op,否则同上
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.AddModal
|
||||
import App.State.RemoveCurrentByName
|
||||
import App.State.RemoveModal
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `XW` 单例:关掉当前窗口,并把 current 交给队首。 */
|
||||
object CloseCurrentModal
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class ModalScreenStateSlice(
|
||||
val Current: Any? = null,
|
||||
val ModalQueue: List<Any?> = emptyList(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
private fun FirstOrNull(Items: List<Any?>): Any? = Items.firstOrNull()
|
||||
|
||||
fun ReduceModalScreen(
|
||||
State0: ModalScreenStateSlice,
|
||||
Action: Any,
|
||||
): ModalScreenStateSlice = when (Action) {
|
||||
is AddModal -> {
|
||||
val ScreenId: Any? = Action.screenId
|
||||
val Name = ScreenId.toString()
|
||||
if (State0.ModalQueue.any { it.toString() == Name }) State0
|
||||
else State0.copy(Current = ScreenId, ModalQueue = State0.ModalQueue + ScreenId)
|
||||
}
|
||||
is RemoveModal -> {
|
||||
val Queue = State0.ModalQueue - Action.screenId
|
||||
State0.copy(Current = FirstOrNull(Queue), ModalQueue = Queue)
|
||||
}
|
||||
is CloseCurrentModal -> {
|
||||
val CurrentModal = State0.Current
|
||||
if (CurrentModal == null) State0
|
||||
else {
|
||||
val Queue = State0.ModalQueue - CurrentModal
|
||||
State0.copy(Current = FirstOrNull(Queue), ModalQueue = Queue)
|
||||
}
|
||||
}
|
||||
is RemoveCurrentByName -> {
|
||||
val CurrentModal = State0.Current
|
||||
if (CurrentModal == null || CurrentModal.toString() != Action.name.toString()) State0
|
||||
else {
|
||||
val Queue = State0.ModalQueue - CurrentModal
|
||||
State0.copy(Current = FirstOrNull(Queue), ModalQueue = Queue)
|
||||
}
|
||||
}
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// PasswordChangeReducer.kt —— 改密流程切片(对应 module_10032 的 VD 状态 + WD.pr6)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 VD:3 个字段,toString 名 "PasswordChangeState(hash=…, uid=…, email=…)";copy 是 tr6(3 字段)。
|
||||
// 默认:hash=""、uid=""、email=""。
|
||||
// 根委派:`uu.pr6(t, n.lpv_1)`。
|
||||
// reducer:
|
||||
// UD(SetPasswordChangeHash) → hash(`n.tr6(t.fr6_1)`)
|
||||
// HD(ShowEmailAndPasswordChangeDialog)→ `n.tr6(cd, e, r)`,其中 r=email、e=uid,即保持 hash
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.SetPasswordChangeHash
|
||||
import App.State.ShowEmailAndPasswordChangeDialog
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class PasswordChangeStateSlice(
|
||||
val Hash: String = "",
|
||||
val Uid: String = "",
|
||||
val Email: String = "",
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReducePasswordChange(
|
||||
State0: PasswordChangeStateSlice,
|
||||
Action: Any,
|
||||
): PasswordChangeStateSlice = when (Action) {
|
||||
is SetPasswordChangeHash -> State0.copy(Hash = Action.hash.toString())
|
||||
is ShowEmailAndPasswordChangeDialog -> State0.copy(
|
||||
Uid = Action.uid.toString(),
|
||||
Email = Action.email.toString(),
|
||||
)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// RankUpDialogReducer.kt —— 升级奖励弹窗切片(对应 module_10032 的 LO 状态 + GO.br3)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 LO:1 个字段,toString 名 "RankUpDialogState(availableItems=…)";copy 是 wr2(1 字段)。
|
||||
// 默认:availableItems = md() = emptyList()。
|
||||
// 根委派:`Se.br3(t, n.npw_1)`。
|
||||
// reducer:
|
||||
// UO(ShowAvailableItems)→ `n.wr2(Im(n.vr2_1, t.ar3_1))`,即在现有列表后追加(元素或整表)
|
||||
// FO(无 toString) → `new LO()`,复位为空表
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.ShowAvailableItems
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `FO`:清空升级奖励弹窗列表(`new LO()`)。 */
|
||||
object ResetRankUpDialog
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class RankUpDialogStateSlice(
|
||||
val AvailableItems: List<Any?> = emptyList(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
/** 原 `Im`:列表追加;`Items` 本身是集合时做拼接,否则当作单个元素。 */
|
||||
private fun PlusItems(Base: List<Any?>, Items: Any?): List<Any?> =
|
||||
if (Items is List<*>) Base + Items else Base + listOf(Items)
|
||||
|
||||
fun ReduceRankUpDialog(
|
||||
State0: RankUpDialogStateSlice,
|
||||
Action: Any,
|
||||
): RankUpDialogStateSlice = when (Action) {
|
||||
is ShowAvailableItems ->
|
||||
State0.copy(AvailableItems = PlusItems(State0.AvailableItems, Action.items))
|
||||
is ResetRankUpDialog -> RankUpDialogStateSlice()
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// RewardedVideosReducer.kt —— 激励视频切片(对应 module_10032 的 JQ 状态 + n1.zsl)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 JQ:1 个字段,toString 名 "RewardedVideosState(displayState=…)";copy 是 vsl(1 字段)。
|
||||
// 默认:`XQ()` → `FQ()` 里的 `dh`,即枚举 NONE。
|
||||
// reducer:`t instanceof t1 ? n.vsl(t.ysl_1) : n`,`t1` 是 SetDisplayState(displayState)。
|
||||
// 枚举 `VQ`:NONE / LOADING / DISPLAY。
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.SetDisplayState
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
enum class RewardVideoDisplayState {
|
||||
NONE,
|
||||
LOADING,
|
||||
DISPLAY,
|
||||
}
|
||||
|
||||
data class RewardedVideosStateSlice(
|
||||
val DisplayState: RewardVideoDisplayState = RewardVideoDisplayState.NONE,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceRewardedVideos(
|
||||
State0: RewardedVideosStateSlice,
|
||||
Action: Any,
|
||||
): RewardedVideosStateSlice = when (Action) {
|
||||
is SetDisplayState ->
|
||||
State0.copy(DisplayState = Action.displayState as RewardVideoDisplayState)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// TipsStateReducer.kt —— 大厅提示条切片(对应 module_10032 的 dst 状态 + bst.vth)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 dst:1 个字段,toString 名 "TipsState(tips=…)";copy 是 su8(1 字段)。
|
||||
// 默认:tips = md() = emptyList()。
|
||||
// 根委派:`Hw.vth(t, n.spv_1)`。
|
||||
// reducer:`t instanceof mst ? n.su8(t.yu8_1) : n`,`mst` 是 UpdateTips(tips),整体替换。
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.UpdateTips
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class TipsStateSlice(
|
||||
val Tips: List<Any?> = emptyList(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceTips(
|
||||
State0: TipsStateSlice,
|
||||
Action: Any,
|
||||
): TipsStateSlice = when (Action) {
|
||||
is UpdateTips -> State0.copy(Tips = Action.tips as List<Any?>)
|
||||
else -> State0
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// RootReducer.kt —— 根 reducer 骨架(对应 module_10032 的根状态 z6 / TOState 与根 reducer k6)
|
||||
//
|
||||
// 原包 k6 对 89 个切片逐个调用各自的 reducer,再 `return n.cti(...)`(copy 出新状态)。
|
||||
// 这里采用同一形状。已迁移的 33 个切片里,32 个真正调用 reducer,launchParams 只做类型收口:
|
||||
// 这里采用同一形状。已迁移的 43 个切片里,42 个真正调用 reducer,launchParams 只做类型收口:
|
||||
//
|
||||
// inviteState → ReduceInvite(aD / pD.er5)
|
||||
// loginByPassword → ReduceLoginByPassword(gD / MD.cr6)
|
||||
@@ -35,16 +35,31 @@
|
||||
// mainQuest → ReduceMainQuest(WZ / ih.bsk,根委派 `(null == ih && new nQ(), ih).bsk(t, n.fpx_1)`)
|
||||
// securitySettings → ReduceSecuritySettings(V2 / pc.qsv,根委派 `pc.qsv(t, n.apx_1)`)
|
||||
// referralEvent → ReduceReferralEvent(pQ / lh.osk,根委派 `lh.osk(t, n.hpy_1)`)
|
||||
// tipsState → ReduceTips(dst / Hw.vth,根委派 `Hw.vth(t, n.spv_1)`)
|
||||
// rankUpDialogState → ReduceRankUpDialog(LO / Se.br3,根委派 `Se.br3(t, n.npw_1)`)
|
||||
// battleResult → ReduceBattleResult(sR / Fi.aqp,根委派 `Fi.aqp(t, n.gpw_1)`)
|
||||
// captchaState → ReduceCaptcha(jP / ar.iqt,根委派 `ar.iqt(t, n.kpv_1)`)
|
||||
// modalScreen → ReduceModalScreen(nV / Fs.js1,根委派 `Fs.js1(t, n.apv_1)`)
|
||||
// droppableGold → ReduceDroppableGold(Vet / Wp.kth,根委派 `Wp.kth(t, n.spw_1)`)
|
||||
// eventGoods → ReduceEventGoods(W7 / Wc.esx,根委派 `Wc.esx(t, n.rpx_1)`)
|
||||
// creatorTagState → ReduceCreatorTag(qO / ze.er2,根委派 `ze.er2(t, n.spx_1)`)
|
||||
// rewardedVideosState → ReduceRewardedVideos(JQ / xh.zsl,根委派 `xh.zsl(t, n.upx_1)`)
|
||||
// passwordChangeState → ReducePasswordChange(VD / uu.pr6,根委派 `uu.pr6(t, n.lpv_1)`)
|
||||
// launchParams → 无 reducer(原根 reducer 原样透传;默认 `ag()` = emptyMap())
|
||||
//
|
||||
// 其余 56 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 其余 46 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 所以一次 copy 里串起全部已迁移 reducer,与按动作路由再归约的结果一致。
|
||||
// 迁移进度与每个字段的证据见生成物 RootWiring.kt(不要手改)。
|
||||
package App.State
|
||||
|
||||
import App.State.Reducers.ReduceAccountSettings
|
||||
import App.State.Reducers.ReduceAnnouncement
|
||||
import App.State.Reducers.ReduceBattleResult
|
||||
import App.State.Reducers.ReduceCaptcha
|
||||
import App.State.Reducers.ReduceCreatorTag
|
||||
import App.State.Reducers.ReduceDroppableGold
|
||||
import App.State.Reducers.ReduceEntrance
|
||||
import App.State.Reducers.ReduceEventGoods
|
||||
import App.State.Reducers.ReduceGarage
|
||||
import App.State.Reducers.ReduceGaragePreview
|
||||
import App.State.Reducers.ReduceHome
|
||||
@@ -57,21 +72,26 @@ import App.State.Reducers.ReduceLootBoxes
|
||||
import App.State.Reducers.ReduceMainQuest
|
||||
import App.State.Reducers.ReduceAvailabilityByRank
|
||||
import App.State.Reducers.ReduceLobbyLoader
|
||||
import App.State.Reducers.ReduceModalScreen
|
||||
import App.State.Reducers.ReduceNews
|
||||
import App.State.Reducers.ReduceNotificationByCountry
|
||||
import App.State.Reducers.ReduceNotifications
|
||||
import App.State.Reducers.ReducePasswordChange
|
||||
import App.State.Reducers.ReduceProBattle
|
||||
import App.State.Reducers.ReducePromoCode
|
||||
import App.State.Reducers.ReducePurchaseDialog
|
||||
import App.State.Reducers.ReduceQuestCategories
|
||||
import App.State.Reducers.ReduceQuests
|
||||
import App.State.Reducers.ReduceRankUpDialog
|
||||
import App.State.Reducers.ReduceReferralEvent
|
||||
import App.State.Reducers.ReduceRewardedVideos
|
||||
import App.State.Reducers.ReduceRulesUpdated
|
||||
import App.State.Reducers.ReduceScreen
|
||||
import App.State.Reducers.ReduceSecuritySettings
|
||||
import App.State.Reducers.ReduceSupportUrl
|
||||
import App.State.Reducers.ReduceSettings
|
||||
import App.State.Reducers.ReduceShop
|
||||
import App.State.Reducers.ReduceTips
|
||||
import App.State.Reducers.ReduceTwitch
|
||||
import App.State.Reducers.ReduceUser
|
||||
|
||||
@@ -120,6 +140,16 @@ object RootReducer {
|
||||
MainQuest = ReduceMainQuest(State0.MainQuest, Action),
|
||||
SecuritySettings = ReduceSecuritySettings(State0.SecuritySettings, Action),
|
||||
ReferralEvent = ReduceReferralEvent(State0.ReferralEvent, Action),
|
||||
TipsState = ReduceTips(State0.TipsState, Action),
|
||||
RankUpDialogState = ReduceRankUpDialog(State0.RankUpDialogState, Action),
|
||||
BattleResult = ReduceBattleResult(State0.BattleResult, Action),
|
||||
CaptchaState = ReduceCaptcha(State0.CaptchaState, Action),
|
||||
ModalScreen = ReduceModalScreen(State0.ModalScreen, Action),
|
||||
DroppableGold = ReduceDroppableGold(State0.DroppableGold, Action),
|
||||
EventGoods = ReduceEventGoods(State0.EventGoods, Action),
|
||||
CreatorTagState = ReduceCreatorTag(State0.CreatorTagState, Action),
|
||||
RewardedVideosState = ReduceRewardedVideos(State0.RewardedVideosState, Action),
|
||||
PasswordChangeState = ReducePasswordChange(State0.PasswordChangeState, Action),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,12 @@ package App.State
|
||||
import App.State.Reducers.AccountSettingsStateSlice
|
||||
import App.State.Reducers.AnnouncementStateSlice
|
||||
import App.State.Reducers.AvailabilityByRankStateSlice
|
||||
import App.State.Reducers.BattleResultStateSlice
|
||||
import App.State.Reducers.CaptchaStateSlice
|
||||
import App.State.Reducers.CreatorTagStateSlice
|
||||
import App.State.Reducers.DroppableGoldStateSlice
|
||||
import App.State.Reducers.EntranceStateSlice
|
||||
import App.State.Reducers.EventGoodsStateSlice
|
||||
import App.State.Reducers.GarageStateSlice
|
||||
import App.State.Reducers.GaragePreviewStateSlice
|
||||
import App.State.Reducers.HomeStateSlice
|
||||
@@ -18,21 +23,26 @@ import App.State.Reducers.LocalBattleUserStateSlice
|
||||
import App.State.Reducers.LoginByPasswordStateSlice
|
||||
import App.State.Reducers.LootBoxesStateSlice
|
||||
import App.State.Reducers.MainQuestStateSlice
|
||||
import App.State.Reducers.ModalScreenStateSlice
|
||||
import App.State.Reducers.NewsStateSlice
|
||||
import App.State.Reducers.NotificationByCountryStateSlice
|
||||
import App.State.Reducers.NotificationsStateSlice
|
||||
import App.State.Reducers.PasswordChangeStateSlice
|
||||
import App.State.Reducers.ProBattleStateSlice
|
||||
import App.State.Reducers.PromoCodeStateSlice
|
||||
import App.State.Reducers.PurchaseDialogStateSlice
|
||||
import App.State.Reducers.QuestCategoriesStateSlice
|
||||
import App.State.Reducers.QuestsStateSlice
|
||||
import App.State.Reducers.RankUpDialogStateSlice
|
||||
import App.State.Reducers.ReferralEventStateSlice
|
||||
import App.State.Reducers.RewardedVideosStateSlice
|
||||
import App.State.Reducers.RulesUpdatedStateSlice
|
||||
import App.State.Reducers.ScreenStateSlice
|
||||
import App.State.Reducers.SecuritySettingsStateSlice
|
||||
import App.State.Reducers.SettingsStateSlice
|
||||
import App.State.Reducers.ShopStateSlice
|
||||
import App.State.Reducers.SupportUrlStateSlice
|
||||
import App.State.Reducers.TipsStateSlice
|
||||
import App.State.Reducers.TwitchStateSlice
|
||||
import App.State.Reducers.UserStateSlice
|
||||
|
||||
@@ -45,8 +55,8 @@ data class RootState(
|
||||
val User: UserStateSlice = UserStateSlice(),
|
||||
/** 原 screen(WK / dY().ks5)。已迁移。 */
|
||||
val Screen: ScreenStateSlice = ScreenStateSlice(),
|
||||
/** 原 modalScreen(nV / Fs.js1)。未迁移:原样透传。 */
|
||||
val ModalScreen: Any? = null,
|
||||
/** 原 modalScreen(nV / Fs.js1)。已迁移。 */
|
||||
val ModalScreen: ModalScreenStateSlice = ModalScreenStateSlice(),
|
||||
/** 原 battleStatistics(jR / rr.fqr)。未迁移:原样透传。 */
|
||||
val BattleStatistics: Any? = null,
|
||||
/** 原 battleTutorial(rE / Q.sq8)。未迁移:原样透传。 */
|
||||
@@ -65,10 +75,10 @@ data class RootState(
|
||||
val MigrationState: Any? = null,
|
||||
/** 原 inviteState(aD / Ke.er5)。已迁移。 */
|
||||
val InviteState: InviteStateSlice = InviteStateSlice(),
|
||||
/** 原 captchaState(jP / ar.iqt)。未迁移:原样透传。 */
|
||||
val CaptchaState: Any? = null,
|
||||
/** 原 passwordChangeState(VD / uu.pr6)。未迁移:原样透传。 */
|
||||
val PasswordChangeState: Any? = null,
|
||||
/** 原 captchaState(jP / ar.iqt)。已迁移。 */
|
||||
val CaptchaState: CaptchaStateSlice = CaptchaStateSlice(),
|
||||
/** 原 passwordChangeState(VD / uu.pr6)。已迁移。 */
|
||||
val PasswordChangeState: PasswordChangeStateSlice = PasswordChangeStateSlice(),
|
||||
/** 原 system(_9 / w9().xt9)。未迁移:原样透传。 */
|
||||
val System: Any? = null,
|
||||
/** 原 quests(Frt / Yrt.otg)。已迁移。 */
|
||||
@@ -81,8 +91,8 @@ data class RootState(
|
||||
val Clan: Any? = null,
|
||||
/** 原 clansStorage(lO / me.vr1)。未迁移:原样透传。 */
|
||||
val ClansStorage: Any? = null,
|
||||
/** 原 tipsState(dst / Hw.vth)。未迁移:原样透传。 */
|
||||
val TipsState: Any? = null,
|
||||
/** 原 tipsState(dst / Hw.vth)。已迁移。 */
|
||||
val TipsState: TipsStateSlice = TipsStateSlice(),
|
||||
/** 原 news(ZX / E_.asd)。已迁移。 */
|
||||
val News: NewsStateSlice = NewsStateSlice(),
|
||||
/** 原 settings(Uut / xw.ltg)。已迁移。 */
|
||||
@@ -109,8 +119,8 @@ data class RootState(
|
||||
val BattleSearchState: Any? = null,
|
||||
/** 原 lobbyLoader(KW / Bs.es1)。已迁移。 */
|
||||
val LobbyLoader: LobbyLoaderStateSlice = LobbyLoaderStateSlice(),
|
||||
/** 原 battleResult(sR / Fi.aqp)。未迁移:原样透传。 */
|
||||
val BattleResult: Any? = null,
|
||||
/** 原 battleResult(sR / Fi.aqp)。已迁移。 */
|
||||
val BattleResult: BattleResultStateSlice = BattleResultStateSlice(),
|
||||
/** 原 battleUsers(uP / sr.hqs)。未迁移:原样透传。 */
|
||||
val BattleUsers: Any? = null,
|
||||
/** 原 suppliesState(wE / $t.fq9)。未迁移:原样透传。 */
|
||||
@@ -123,8 +133,8 @@ data class RootState(
|
||||
val BattlePauseState: Any? = null,
|
||||
/** 原 battleViewState(DT / sI.jqd)。未迁移:原样透传。 */
|
||||
val BattleViewState: Any? = null,
|
||||
/** 原 rankUpDialogState(LO / Se.br3)。未迁移:原样透传。 */
|
||||
val RankUpDialogState: Any? = null,
|
||||
/** 原 rankUpDialogState(LO / Se.br3)。已迁移。 */
|
||||
val RankUpDialogState: RankUpDialogStateSlice = RankUpDialogStateSlice(),
|
||||
/** 原 clanUserInfo(hO / de.gr1)。未迁移:原样透传。 */
|
||||
val ClanUserInfo: Any? = null,
|
||||
/** 原 tankActionsLogState(vI / wi.gqe)。未迁移:原样透传。 */
|
||||
@@ -133,8 +143,8 @@ data class RootState(
|
||||
val BattleMessage: Any? = null,
|
||||
/** 原 battleChat(Q6 / Hf.wtg)。未迁移:原样透传。 */
|
||||
val BattleChat: Any? = null,
|
||||
/** 原 droppableGold(Vet / Wp.kth)。未迁移:原样透传。 */
|
||||
val DroppableGold: Any? = null,
|
||||
/** 原 droppableGold(Vet / Wp.kth)。已迁移。 */
|
||||
val DroppableGold: DroppableGoldStateSlice = DroppableGoldStateSlice(),
|
||||
/** 原 home(s1 / (inline@home))。已迁移。 */
|
||||
val Home: HomeStateSlice = HomeStateSlice(),
|
||||
/** 原 localBattleUserState(lE / (inline@localBattleUserState))。已迁移。 */
|
||||
@@ -183,14 +193,14 @@ data class RootState(
|
||||
val NotificationByCountry: NotificationByCountryStateSlice = NotificationByCountryStateSlice(),
|
||||
/** 原 userRenameState(O8 / Rf.pte)。未迁移:原样透传。 */
|
||||
val UserRenameState: Any? = null,
|
||||
/** 原 eventGoods(W7 / Wc.esx)。未迁移:原样透传。 */
|
||||
val EventGoods: Any? = null,
|
||||
/** 原 creatorTagState(qO / ze.er2)。未迁移:原样透传。 */
|
||||
val CreatorTagState: Any? = null,
|
||||
/** 原 eventGoods(W7 / Wc.esx)。已迁移。 */
|
||||
val EventGoods: EventGoodsStateSlice = EventGoodsStateSlice(),
|
||||
/** 原 creatorTagState(qO / ze.er2)。已迁移。 */
|
||||
val CreatorTagState: CreatorTagStateSlice = CreatorTagStateSlice(),
|
||||
/** 原 twoStepVerificationState(x9 / _f.atb)。未迁移:原样透传。 */
|
||||
val TwoStepVerificationState: Any? = null,
|
||||
/** 原 rewardedVideosState(JQ / xh.zsl)。未迁移:原样透传。 */
|
||||
val RewardedVideosState: Any? = null,
|
||||
/** 原 rewardedVideosState(JQ / xh.zsl)。已迁移。 */
|
||||
val RewardedVideosState: RewardedVideosStateSlice = RewardedVideosStateSlice(),
|
||||
/** 原 twitchState(g9 / uf.gta)。已迁移。 */
|
||||
val TwitchState: TwitchStateSlice = TwitchStateSlice(),
|
||||
/** 原 icons(oH / vs.kru)。已迁移。 */
|
||||
|
||||
@@ -16,7 +16,7 @@ object RootWiring {
|
||||
val All: List<SliceWiring> = listOf(
|
||||
SliceWiring("user", "ypu_1", "t8", "M8().qtd", "M8().qtd(t, n.ypu_1)", listOf("AddCoins", "AddRubies", "ClearInDebt", "DisableLobbyTutorial", "SetBatteryLevel", "SetClanInfo", "SetCoins", "SetDisabledWithoutPremiumLocations", "SetHasTemporaryCash", "SetInDebt", "SetPremiumExpirationTime", "SetRankNames", "SetRubies", "SetUserId", "SetUserPropertiesAction", "SpendCoins", "SpendCrystals", "SpendRubies", "UpdateClanTag", "UpdateCrystals", "UpdateEventPass", "UpdateGearScore", "UpdatePremium", "UpdateRank", "UpdateScore", "UpdateUid", "UpdateUserRating")),
|
||||
SliceWiring("screen", "zpu_1", "WK", "dY().ks5", "dY().ks5(t, n.zpu_1)", listOf("ClearScreenStack", "DelayNextGoTo", "DisableBack", "DisableForeground", "DisplayMainEntranceScreen", "DisplayReauthorizationMessage", "EnableBack", "EnableForeground", "FilterScreenStack", "GoTo", "PopScreen", "PressedAnyButton", "ResetScreenStackOnNextGoTo")),
|
||||
SliceWiring("modalScreen", "apv_1", "nV", "Fs.js1", "Fs.js1(t, n.apv_1)", listOf("?XW", "AddModal", "RemoveCurrentByName", "RemoveModal")),
|
||||
SliceWiring("modalScreen", "apv_1", "nV", "Fs.js1", "Fs.js1(t, n.apv_1)", listOf("AddModal", "CloseCurrentModal", "RemoveCurrentByName", "RemoveModal")),
|
||||
SliceWiring("battleStatistics", "bpv_1", "jR", "rr.fqr", "rr.fqr(t, n.bpv_1)", listOf("?DR", "?HR", "?KR", "?PR", "?QR", "?UR", "?XR", "?YR", "?ZR", "?nP", "?tP", "Init", "InitBattleModeWithLevels", "SetBattleMode", "SetDisplayClientInfo", "SetFlagOrBallOwner", "SetRankRange", "SetReArmor", "SetRemainingTime", "SetRoundRestartTime", "UpdateFund", "UpdateScore")),
|
||||
SliceWiring("battleTutorial", "cpv_1", "rE", "Q.sq8", "Q.sq8(t, n.cpv_1)", listOf("?oE", "?sE", "SetFragsCount", "ShowMessage")),
|
||||
SliceWiring("garage", "dpv_1", "UB", "hF", "hF(t, n)", listOf("AddGarageItemCount", "AddNewItem", "AddOverdriveDescription", "AddRelatedBazooka", "AddRelatedResistanceModule", "AddToFavoriteItem", "BuyProtectionSlot", "ClearWaitServerItemMount", "GarageAddItemToDepot", "GarageApplyResistanceMount", "GarageBuyDevice", "GarageDeviceTrySetInfinityLifetime", "GarageDevicesLoadedAction", "GarageLoaded", "GarageMountItem", "GarageMountItems", "GarageRemoveDevice", "GarageRemoveDiscountForDevice", "GarageRemoveItemFromDepot", "GarageRemoveItemFromStore", "GarageResistanceUnMount", "GarageSelectAlteration", "GarageSelectItem", "GarageSelectShotSkin", "GarageSelectSkin", "GarageUnmountItem", "GarageUpdateItemCount", "GarageUpgradeItemAction", "GarageUpgradeItemConfirm", "GarageUpgradeItemCoolDownFinished", "GarageUpgradeItemCoolDownStarted", "GoTo", "HideVideoInDescription", "InitState", "RemoveFromFavoriteItem", "RemoveFromSale", "RemoveNewItem", "RemoveWaitServerItemMount", "ResetGarage", "ResetMountDelay", "SelectGarageCategory", "SetCooldownReduceEndTime", "SetGarageNotLoaded", "SetGarageObject", "SetGarageSkinsAction", "SetItemRarity", "SetItemsOnDepot", "SetItemsOnMarket", "SetMountedItems", "SetMountedShotSkinForItems", "SetMountedSkinForItems", "SetNewItems", "SetResistanceReadyToMount", "SetRestrictionMount", "ShowGarageDiscountNotification", "StartCooldownReduce", "SwitchingRowsScroll", "UpdateDiscount")),
|
||||
@@ -26,7 +26,7 @@ object RootWiring {
|
||||
SliceWiring("register", "hpv_1", "Cit", "cp.stg", "cp.stg(t, n.hpv_1)", listOf("?Bit", "?Dit", "?Fit", "?Git", "?Hit", "?Lit", "?Mit", "?Uit", "?_rt", "?hrt", "EnteredUidIsBusy", "ForceSetUid", "ReceiveOAuthUri", "SetOpenedPassword", "SetPassword", "SetPasswordRestrictions", "SetUid", "SocialNetworkAvailability", "SocialNetworkClientIds")),
|
||||
SliceWiring("migrationState", "ipv_1", "\$it", "Uv.rtg", "Uv.rtg(t, n.ipv_1)", listOf("?Bit", "?Dit", "?Fit", "?Git", "?Hit", "?Lit", "?_rt", "EnteredUidIsBusy", "ForceSetUid", "SetPassword", "SetUid")),
|
||||
SliceWiring("inviteState", "jpv_1", "aD", "Ke.er5", "Ke.er5(t, n.jpv_1)", listOf("ApplyInvite", "SetInviteNeed", "SetInviteStatus")),
|
||||
SliceWiring("captchaState", "kpv_1", "jP", "ar.iqt", "ar.iqt(t, n.kpv_1)", listOf("?AP", "?IP", "?PP", "?RP", "?SP", "LocationsUpdated", "SetLocations")),
|
||||
SliceWiring("captchaState", "kpv_1", "jP", "ar.iqt", "ar.iqt(t, n.kpv_1)", listOf("AddCaptchaLocationToReset", "AddVerifiedCaptchaLocation", "LocationsUpdated", "RemoveCaptchaLocationToReset", "RemoveVerifiedCaptchaLocation", "SetLocations", "ShowFakeCaptcha")),
|
||||
SliceWiring("passwordChangeState", "lpv_1", "VD", "uu.pr6", "uu.pr6(t, n.lpv_1)", listOf("SetPasswordChangeHash", "ShowEmailAndPasswordChangeDialog")),
|
||||
SliceWiring("system", "mpv_1", "_9", "w9().xt9", "w9().xt9(t, n.mpv_1)", listOf("DoShowMessage", "SetFatalError")),
|
||||
SliceWiring("quests", "npv_1", "Frt", "Yrt.otg", "(null == zp && new Yrt(), zp).otg(t, n.npv_1)", listOf("GoTo", "SetCurrentCategory", "SetNotCompletedQuests")),
|
||||
@@ -48,19 +48,19 @@ object RootWiring {
|
||||
SliceWiring("battleCreateState", "dpw_1", "\$6", "Df.ttg", "Df.ttg(t, n.dpw_1, n.bpw_1, n.ypu_1)", listOf("?A6", "?B6", "?C6", "?D6", "?E6", "?F6", "?I6", "?L6", "?M6", "?N6", "?P6", "?R6", "?T6", "?U6", "Configure", "CreateBattle", "SetRestrictions")),
|
||||
SliceWiring("battleSearchState", "epw_1", "Itt", "Htt().vtg", "Htt().vtg(t, n.epw_1)", listOf("?Dtt", "EnterToBattle", "Fight", "RemoveBattle", "SelectBattle", "SelectBattleFormat", "SetFilter", "SetSearch", "SetSuspiciousFilter")),
|
||||
SliceWiring("lobbyLoader", "fpw_1", "KW", "Bs.es1", "Bs.es1(t, n.fpw_1)", listOf("HideLoader", "ShowLoader")),
|
||||
SliceWiring("battleResult", "gpw_1", "sR", "Fi.aqp", "Fi.aqp(t, n.gpw_1)", listOf("?cR", "?fR", "?lR", "DoInit", "SetHasBattleResult", "SetRewards")),
|
||||
SliceWiring("battleResult", "gpw_1", "sR", "Fi.aqp", "Fi.aqp(t, n.gpw_1)", listOf("DoInit", "ResetBattleRewards", "SetHasBattleResult", "SetIncreasedReward", "SetRewards", "SetSimpleReward")),
|
||||
SliceWiring("battleUsers", "hpw_1", "uP", "sr.hqs", "sr.hqs(t, n.hpw_1)", listOf("?_P", "?hP", "?lP", "?oP", "?qP", "?sP", "InitSuspiciousState", "InitUserLevels", "RemoveTankInfo", "SetGearScore", "SetTankInfo", "SetTankResistance", "UpdateUserLevel", "UpdateUserRank", "UpdateUserScoreKillsAndDeaths", "UpdateUserSuspiciousState", "UpdateUsersClanTag", "UpdateUsersScoreKillsAndDeaths")),
|
||||
SliceWiring("suppliesState", "ipw_1", "wE", "\$t.fq9", "\$t.fq9(t, n.ipw_1)", listOf("?qE")),
|
||||
SliceWiring("matchmakingGroup", "jpw_1", "rW", "NW().is0", "NW().is0(t, n.jpw_1)", listOf("?zW", "AcceptedInviteToGroup", "AddUser", "AddUserToSelected", "InitMatchmakingGroup", "Invite", "RejectedInviteToGroup", "RemoveUserToSelected", "SetAllowedFromFriends", "SetSelectedUsers", "UpdateMountItems", "UpdateUserReadiness", "UserRemoved")),
|
||||
SliceWiring("shop", "kpw_1", "j4", "(inline@shop)", "(function (t, n) { var i; if (t instanceof w4) i = n.qt6(cd, cd, cd, cd, cd, cd, cd, t.lt6_1); else if (t instanceof Yut) i = n.qt6(cd, cd, cd, cd, !0); else if (t instanceof F5) i = new j4(cd, cd, cd, cd, cd, cd, cd, n.qq3_1); else if (t instanceof h4) i = n.qt6(cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, t.st5_1); else if (t instanceof c4) i = n.qt6(cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, cd, t.ut5_1); else if (t instanceof u4) i = n.qt6( cd, cd, cd, cd, cd, cd, …", listOf("?x4", "AddCategoriesWithBonus", "AddItemToOrderProcessing", "BlockBackButton", "BraintreeLoadingInterrupt", "ClearPreviousScreen", "ClearTargetCategory", "ClearTargetProductId", "CurrentPayMode", "DeleteOneTimePurchaseItem", "InitAdditionalDescription", "InitAmountString", "InitCategory", "InitCoinPackage", "InitCompensation", "InitCrystalKitPackage", "InitFeatureItem", "InitGroup", "InitItemViewType", "InitKeysPackage", "InitKitBundle", "InitKitPackage", "InitLootBoxAndPaint", "InitOneTimePurchaseItem", "InitPayModeAction", "InitPaymentModeAsShopItem", "InitPaymentProviderItems", "InitPaymentViewType", "InitRestrictionByPayMode", "InitRewardedVideosBlocks", "InitShopCard", "InitShopCardDiscount", "InitShopCardView", "InitShopItem", "InitShopItemName", "InitSingleItemKit", "InitSpecialKitPackage", "MobilePaymentStateChanged", "PaymentProviderFinishFail", "PaymentProviderFinishSuccess", "PaymentProviderInProgress", "PaymentUrlReceiveFailed", "PaymentUrlReceived", "RemoveDiscountItemForItem", "RemoveItemFromOrderProcessing", "ResetPaymentState", "ResetShop", "SavePreviousScreen", "SaveTargetProductId", "SaveTargetVisitedCategory", "SelectCategory", "SelectCategoryId", "SelectItem", "SetBraintreeToken", "SetCoinPaymentProviderUrl", "SetGoToHomeAfterBuy", "SetInitShopItemId", "SetPurchaseCompleted", "SetStripeIntentParams", "SetupDiscountCategoryByItem", "SetupDiscountItem", "SetupDiscountItemForItem", "ShopCardExpired", "ShopCardRemoved", "ShopCardSold", "ShopLoaded", "ToggleShopActivity", "TryToBuyOneTimePurchase", "UnblockBackButton")),
|
||||
SliceWiring("battlePauseState", "lpw_1", "dT", "NT().mqc", "NT().mqc(t, n.lpw_1)", listOf("?TT", "?xT", "OnPauseMode", "SetIdleKickPeriod")),
|
||||
SliceWiring("battleViewState", "mpw_1", "DT", "sI.jqd", "(null == \$n && new sI(), \$n).jqd(t, n.mpw_1)", listOf("?JT", "?QT", "?WT", "?YT", "?ZT", "?eI", "?iI", "?nE", "?nI", "?rI", "?tE", "?tI", "SetElementsVisibility", "SetVisibility")),
|
||||
SliceWiring("rankUpDialogState", "npw_1", "LO", "Se.br3", "Se.br3(t, n.npw_1)", listOf("?FO", "ShowAvailableItems")),
|
||||
SliceWiring("rankUpDialogState", "npw_1", "LO", "Se.br3", "Se.br3(t, n.npw_1)", listOf("ResetRankUpDialog", "ShowAvailableItems")),
|
||||
SliceWiring("clanUserInfo", "opw_1", "hO", "de.gr1", "de.gr1(t, n.opw_1)", listOf("Loaded")),
|
||||
SliceWiring("tankActionsLogState", "ppw_1", "vI", "wi.gqe", "wi.gqe(t, n.ppw_1)", listOf("?dI", "OnUserJoinTheBattle", "OnUserLeaveTheBattle", "UpdateLog")),
|
||||
SliceWiring("battleMessage", "qpw_1", "FE", "vT().rqb", "vT().rqb(t, n.qpw_1)", listOf("?sT", "DoAddLocalizedMessage", "DoAddLocalizedTeamMessage", "DoAddLocalizedUserMessage", "DoAddTextMessage", "HideMessage", "RemoveMessage")),
|
||||
SliceWiring("battleChat", "rpw_1", "Q6", "Hf.wtg", "Hf.wtg(t, n.rpw_1)", listOf("?ett", "?rtt", "?stt", "?utt", "AddMessage", "ChatLoaded")),
|
||||
SliceWiring("droppableGold", "spw_1", "Vet", "Wp.kth", "Wp.kth(t, n.spw_1)", listOf("?Ket", "?Yet")),
|
||||
SliceWiring("droppableGold", "spw_1", "Vet", "Wp.kth", "Wp.kth(t, n.spw_1)", listOf("HideDroppableGoldAuthor", "ShowDroppableGoldAuthor")),
|
||||
SliceWiring("home", "tpw_1", "s1", "(inline@home)", "(function (t, n) { return t instanceof o1 ? n.f7j(!0) : n; })(t, n.tpw_1)", listOf("ShowShopDiscountNotification")),
|
||||
SliceWiring("localBattleUserState", "upw_1", "lE", "(inline@localBattleUserState)", "(function (t, n) { return t instanceof fE ? n.xq8(t.yq8_1) : t instanceof vE ? n.xq8(cd, t.zq8_1) : n; })(t, n.upw_1)", listOf("SetLocalWeaponResistanceProperty", "SetReArmorTemporaryDisabled")),
|
||||
SliceWiring("soundSettings", "vpw_1", "Det", "Wet().jth", "Wet().jth(t, n.vpw_1)", listOf("?Uet", "?_C", "SetEntranceSoundEnabled", "UpdateSettings")),
|
||||
@@ -86,7 +86,7 @@ object RootWiring {
|
||||
SliceWiring("notificationByCountry", "ppx_1", "gJ", "R_.ssd", "R_.ssd(t, n.ppx_1)", listOf("Init", "MarkHomeScreenDialogShown")),
|
||||
SliceWiring("userRenameState", "qpx_1", "O8", "Rf.pte", "Rf.pte(t, n.qpx_1)", listOf("?B8", "?F8", "?G8", "?Q8", "?U8", "ChangeUidInputState", "ResponseActual", "ResponseDelivered", "SetChangeUidParams", "SetRubiesForRename", "SetValidationStatus")),
|
||||
SliceWiring("eventGoods", "rpx_1", "W7", "Wc.esx", "Wc.esx(t, n.rpx_1)", listOf("InitEventGoods")),
|
||||
SliceWiring("creatorTagState", "spx_1", "qO", "ze.er2", "ze.er2(t, n.spx_1)", listOf("?jO", "SetAttachedCreatorTag", "SetCreatorTag", "SetCreatorTags")),
|
||||
SliceWiring("creatorTagState", "spx_1", "qO", "ze.er2", "ze.er2(t, n.spx_1)", listOf("ClearCreatorTag", "SetAttachedCreatorTag", "SetCreatorTag", "SetCreatorTags")),
|
||||
SliceWiring("twoStepVerificationState", "tpx_1", "x9", "_f.atb", "_f.atb(t, n.tpx_1)", listOf("ActivationStatus2FA", "Enable2FaRequest", "SetSecretAndQRCode", "SetUse2FA", "VerificationStatus")),
|
||||
SliceWiring("rewardedVideosState", "upx_1", "JQ", "xh.zsl", "xh.zsl(t, n.upx_1)", listOf("SetDisplayState")),
|
||||
SliceWiring("twitchState", "vpx_1", "g9", "uf.gta", "uf.gta(t, n.vpx_1)", listOf("SetAccount", "SetDaysForNextLinking", "SetTwitchEnabled")),
|
||||
@@ -106,7 +106,7 @@ object RootWiring {
|
||||
)
|
||||
|
||||
/** 已迁移(强类型;launchParams 为透传,不调用 reducer)的字段。 */
|
||||
val Migrated: Set<String> = setOf("inviteState", "loginByPassword", "twitchState", "home", "localBattleUserState", "shop", "screen", "lootBoxes", "garage", "garagePreview", "entrance", "user", "settings", "accountSettings", "proBattle", "language", "announcement", "launchParams", "news", "notifications", "quests", "lobbyLoader", "purchaseDialogState", "promoCode", "supportUrl", "rulesUpdated", "notificationByCountry", "availabilityByRank", "icons", "questCategories", "mainQuest", "securitySettings", "referralEvent")
|
||||
val Migrated: Set<String> = setOf("inviteState", "loginByPassword", "twitchState", "home", "localBattleUserState", "shop", "screen", "lootBoxes", "garage", "garagePreview", "entrance", "user", "settings", "accountSettings", "proBattle", "language", "announcement", "launchParams", "news", "notifications", "quests", "lobbyLoader", "purchaseDialogState", "promoCode", "supportUrl", "rulesUpdated", "notificationByCountry", "availabilityByRank", "icons", "questCategories", "mainQuest", "securitySettings", "referralEvent", "tipsState", "rankUpDialogState", "battleResult", "captchaState", "modalScreen", "droppableGold", "eventGoods", "creatorTagState", "rewardedVideosState", "passwordChangeState")
|
||||
|
||||
/** 未迁移字段:归约时原样透传,作为后续迁移清单。 */
|
||||
val Unmigrated: List<SliceWiring> get() = All.filter { it.Field !in Migrated }
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
// ⑥ 动作目录:816 个类与 138 个真实派发名对齐
|
||||
// ⑦ 回放:真实 toString 样例的类/字段/类型校验
|
||||
// ⑧ 全目录动作类都能按 KClass 路由
|
||||
// ⑨~㊸ 切片 reducer:InviteState / LoginByPasswordState / TwitchState / HomeScreen / LocalBattleUserState /
|
||||
// ⑨~㊿/51-53 切片 reducer:InviteState / LoginByPasswordState / TwitchState / HomeScreen / LocalBattleUserState /
|
||||
// Shop(含 U7 类别表与 w3 物品表两个子 reducer)/ Screen / LootBoxes / Garage / GaragePreview / Entrance / User / Settings /
|
||||
// AccountSettings / ProBattle / Language / Announcement / News / Notifications / Quests /
|
||||
// LobbyLoader / PurchaseDialogState / PromoCode / SupportUrl / RulesUpdated / NotificationByCountry / AvailabilityByRank /
|
||||
// Icons / QuestCategories / MainQuest / SecuritySettings / ReferralEvent;
|
||||
// Icons / QuestCategories / MainQuest / SecuritySettings / ReferralEvent /
|
||||
// TipsState / RankUpDialogState / BattleResult / CaptchaState / ModalScreen / DroppableGold / EventGoods /
|
||||
// CreatorTagState / RewardedVideosState / PasswordChangeState;
|
||||
// ㉑ launchParams 是纯透传切片(无 reducer/动作),只做 Map 类型收口;⑭ 根 reducer 的 89 槽位委派
|
||||
//
|
||||
// 用法:$env:TANKIOFFLINE_STATE_TEST='1'; node …(见 TankiOffline/tools/RunStateTest.ps1)
|
||||
@@ -388,6 +390,56 @@ import App.State.SetReferrals
|
||||
import App.State.SetReferrer
|
||||
import App.State.Reducers.ReduceReferralEvent
|
||||
import App.State.Reducers.ReferralEventStateSlice
|
||||
import App.State.UpdateTips
|
||||
import App.State.Reducers.ReduceTips
|
||||
import App.State.Reducers.TipsStateSlice
|
||||
import App.State.ShowAvailableItems
|
||||
import App.State.Reducers.RankUpDialogStateSlice
|
||||
import App.State.Reducers.ReduceRankUpDialog
|
||||
import App.State.Reducers.ResetRankUpDialog
|
||||
import App.State.DoInit
|
||||
import App.State.SetHasBattleResult
|
||||
import App.State.Reducers.BattleResultStateSlice
|
||||
import App.State.Reducers.ReduceBattleResult
|
||||
import App.State.Reducers.ResetBattleRewards
|
||||
import App.State.Reducers.SetIncreasedReward
|
||||
import App.State.Reducers.SetSimpleReward
|
||||
import App.State.LocationsUpdated
|
||||
import App.State.SetLocations
|
||||
import App.State.Reducers.AddCaptchaLocationToReset
|
||||
import App.State.Reducers.AddVerifiedCaptchaLocation
|
||||
import App.State.Reducers.CaptchaStateSlice
|
||||
import App.State.Reducers.ReduceCaptcha
|
||||
import App.State.Reducers.RemoveCaptchaLocationToReset
|
||||
import App.State.Reducers.RemoveVerifiedCaptchaLocation
|
||||
import App.State.Reducers.ShowFakeCaptcha
|
||||
import App.State.AddModal
|
||||
import App.State.RemoveCurrentByName
|
||||
import App.State.RemoveModal
|
||||
import App.State.Reducers.CloseCurrentModal
|
||||
import App.State.Reducers.ModalScreenStateSlice
|
||||
import App.State.Reducers.ReduceModalScreen
|
||||
import App.State.Reducers.DroppableGoldStateSlice
|
||||
import App.State.Reducers.HideDroppableGoldAuthor
|
||||
import App.State.Reducers.ReduceDroppableGold
|
||||
import App.State.Reducers.ShowDroppableGoldAuthor
|
||||
import App.State.InitEventGoods
|
||||
import App.State.Reducers.EventGoodsStateSlice
|
||||
import App.State.Reducers.ReduceEventGoods
|
||||
import App.State.SetAttachedCreatorTag
|
||||
import App.State.SetCreatorTag
|
||||
import App.State.SetCreatorTags
|
||||
import App.State.Reducers.ClearCreatorTag
|
||||
import App.State.Reducers.CreatorTagStateSlice
|
||||
import App.State.Reducers.ReduceCreatorTag
|
||||
import App.State.SetDisplayState
|
||||
import App.State.Reducers.ReduceRewardedVideos
|
||||
import App.State.Reducers.RewardVideoDisplayState
|
||||
import App.State.Reducers.RewardedVideosStateSlice
|
||||
import App.State.SetPasswordChangeHash
|
||||
import App.State.ShowEmailAndPasswordChangeDialog
|
||||
import App.State.Reducers.PasswordChangeStateSlice
|
||||
import App.State.Reducers.ReducePasswordChange
|
||||
import App.State.Reducers.UserRankBounds
|
||||
import App.State.Reducers.UserStateSlice
|
||||
import App.State.Reducers.ClearHullData
|
||||
@@ -815,7 +867,7 @@ object StateCheck {
|
||||
Check("切片 LocalBattleUser:接 Store 派发后状态已归约", Store.State.IsReArmorTemporaryDisabled)
|
||||
}
|
||||
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 33 个已迁移切片(32 归约 + launchParams 透传)
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 43 个已迁移切片(42 归约 + launchParams 透传)
|
||||
run {
|
||||
Check("根:根状态 89 个切片槽位", RootWiring.All.size == 89)
|
||||
Check(
|
||||
@@ -879,7 +931,7 @@ object StateCheck {
|
||||
LocalBattleW.Reducer == "(inline@localBattleUserState)"
|
||||
)
|
||||
Check(
|
||||
"根:迁移表 = 33 个已迁移字段,其余 56 个待迁",
|
||||
"根:迁移表 = 43 个已迁移字段,其余 46 个待迁",
|
||||
RootReducer.Migrated ==
|
||||
setOf(
|
||||
"inviteState", "loginByPassword", "twitchState", "home",
|
||||
@@ -890,8 +942,11 @@ object StateCheck {
|
||||
"lobbyLoader", "purchaseDialogState", "promoCode", "supportUrl",
|
||||
"rulesUpdated", "notificationByCountry", "availabilityByRank",
|
||||
"icons", "questCategories", "mainQuest", "securitySettings", "referralEvent",
|
||||
"tipsState", "rankUpDialogState", "battleResult", "captchaState",
|
||||
"modalScreen", "droppableGold", "eventGoods", "creatorTagState",
|
||||
"rewardedVideosState", "passwordChangeState",
|
||||
) &&
|
||||
RootWiring.Unmigrated.size == 56
|
||||
RootWiring.Unmigrated.size == 46
|
||||
)
|
||||
|
||||
// 一次 ReduceRoot 里多个切片各归约自己的动作,互不串片
|
||||
@@ -947,7 +1002,7 @@ object StateCheck {
|
||||
S5.User.Uid == "user-1" && S5.Screen.Current == NamedScreen("Preloader")
|
||||
)
|
||||
Check("根:无关动作返回等值状态", ReduceRoot(S5, AddFrags(1)) == S5)
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 33/89")
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 43/89")
|
||||
|
||||
val Store = ReduxStore(RootState(), { S, A -> ReduceRoot(S, A) })
|
||||
Store.Dispatch(SetStatus("LOGGING_IN"))
|
||||
@@ -3664,6 +3719,407 @@ object StateCheck {
|
||||
)
|
||||
}
|
||||
|
||||
// ㊹ 切片 reducer:TipsState(dst / Hw.vth,1 字段;mst → UpdateTips)
|
||||
run {
|
||||
val S0 = TipsStateSlice()
|
||||
Check("切片 TipsState:默认空列表", S0.Tips.isEmpty())
|
||||
val S1 = ReduceTips(S0, UpdateTips(listOf("a", "b")))
|
||||
Check("切片 TipsState:UpdateTips 整体替换", S1.Tips == listOf<Any?>("a", "b"))
|
||||
Check("切片 TipsState:无关动作不改状态", ReduceTips(S1, AddFrags(1)) == S1)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, UpdateTips(listOf("x")))
|
||||
Check(
|
||||
"根:UpdateTips 只动 tipsState",
|
||||
Root1.TipsState.Tips == listOf<Any?>("x") && Root1.BattleResult == Root0.BattleResult
|
||||
)
|
||||
val W = RootWiring.ByField("tipsState")!!
|
||||
Check(
|
||||
"根:tipsState 委派到 dst / Hw.vth",
|
||||
W.SliceClass == "dst" && W.Reducer == "Hw.vth" && W.Actions == listOf("UpdateTips")
|
||||
)
|
||||
}
|
||||
|
||||
// ㊺ 切片 reducer:RankUpDialog(LO / Se.br3,1 字段;UO + FO)
|
||||
run {
|
||||
val S0 = RankUpDialogStateSlice()
|
||||
Check("切片 RankUpDialog:默认空表", S0.AvailableItems.isEmpty())
|
||||
val S1 = ReduceRankUpDialog(S0, ShowAvailableItems(listOf("a")))
|
||||
Check(
|
||||
"切片 RankUpDialog:ShowAvailableItems 追加整表",
|
||||
S1.AvailableItems == listOf<Any?>("a")
|
||||
)
|
||||
val S2 = ReduceRankUpDialog(S1, ShowAvailableItems(listOf("b", "c")))
|
||||
Check(
|
||||
"切片 RankUpDialog:再次追加是拼接",
|
||||
S2.AvailableItems == listOf<Any?>("a", "b", "c")
|
||||
)
|
||||
Check(
|
||||
"切片 RankUpDialog:ResetRankUpDialog 清空列表",
|
||||
ReduceRankUpDialog(S2, ResetRankUpDialog).AvailableItems.isEmpty()
|
||||
)
|
||||
Check(
|
||||
"切片 RankUpDialog:无关动作不改状态",
|
||||
ReduceRankUpDialog(S2, AddFrags(1)) == S2
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, ShowAvailableItems(listOf("x")))
|
||||
Check(
|
||||
"根:ShowAvailableItems 只动 rankUpDialogState",
|
||||
Root1.RankUpDialogState.AvailableItems == listOf<Any?>("x") &&
|
||||
Root1.TipsState == Root0.TipsState
|
||||
)
|
||||
val W = RootWiring.ByField("rankUpDialogState")!!
|
||||
Check(
|
||||
"根:rankUpDialogState 委派到 LO / Se.br3 且 2 个动作",
|
||||
W.SliceClass == "LO" && W.Reducer == "Se.br3" &&
|
||||
W.Actions.toSet() == setOf("ShowAvailableItems", "ResetRankUpDialog")
|
||||
)
|
||||
}
|
||||
|
||||
// ㊻ 切片 reducer:BattleResult(sR / Fi.aqp,5 字段;6 个动作)
|
||||
run {
|
||||
val Item = ContainerGivenItem(
|
||||
category = "cat", count = 1, garageItemCategory = "hull", garageItemId = 2,
|
||||
image = null, name = "n", rewardType = "t",
|
||||
)
|
||||
val S0 = BattleResultStateSlice()
|
||||
Check(
|
||||
"切片 BattleResult:默认值完整",
|
||||
!S0.HasBattleResult && S0.Rewards.isEmpty() &&
|
||||
S0.InitialCurrentUserXP == null && S0.IncreasedReward == 0 &&
|
||||
S0.SimpleReward == 0
|
||||
)
|
||||
val S1 = ReduceBattleResult(S0, SetRewards(listOf(Item)))
|
||||
Check("切片 BattleResult:SetRewards 写奖励表", S1.Rewards == listOf(Item))
|
||||
val S2 = ReduceBattleResult(S1, SetHasBattleResult(true))
|
||||
Check("切片 BattleResult:SetHasBattleResult 写布尔", S2.HasBattleResult)
|
||||
val S3 = ReduceBattleResult(
|
||||
ReduceBattleResult(S2, SetIncreasedReward(15)),
|
||||
SetSimpleReward(10),
|
||||
)
|
||||
Check(
|
||||
"切片 BattleResult:cR / lR 分别写两个奖励数值",
|
||||
S3.IncreasedReward == 15 && S3.SimpleReward == 10
|
||||
)
|
||||
Check(
|
||||
"切片 BattleResult:ResetBattleRewards 只把两个数值归零",
|
||||
ReduceBattleResult(S3, ResetBattleRewards) ==
|
||||
S3.copy(IncreasedReward = 0, SimpleReward = 0)
|
||||
)
|
||||
val S4 = ReduceBattleResult(S3, DoInit(500))
|
||||
Check(
|
||||
"切片 BattleResult:DoInit 重建状态只带初始 XP",
|
||||
!S4.HasBattleResult && S4.Rewards.isEmpty() &&
|
||||
S4.InitialCurrentUserXP == 500 && S4.IncreasedReward == 0 &&
|
||||
S4.SimpleReward == 0
|
||||
)
|
||||
Check(
|
||||
"切片 BattleResult:无关动作不改状态",
|
||||
ReduceBattleResult(S4, AddFrags(1)) == S4
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, SetHasBattleResult(true))
|
||||
Check(
|
||||
"根:SetHasBattleResult 只动 battleResult",
|
||||
Root1.BattleResult.HasBattleResult && Root1.CaptchaState == Root0.CaptchaState
|
||||
)
|
||||
val W = RootWiring.ByField("battleResult")!!
|
||||
Check(
|
||||
"根:battleResult 委派到 sR / Fi.aqp 且 6 个动作",
|
||||
W.SliceClass == "sR" && W.Reducer == "Fi.aqp" &&
|
||||
W.Actions.toSet() == setOf(
|
||||
"SetRewards", "SetHasBattleResult", "SetIncreasedReward",
|
||||
"SetSimpleReward", "ResetBattleRewards", "DoInit",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// ㊼ 切片 reducer:Captcha(jP / ar.iqt,4 字段;7 个动作)
|
||||
run {
|
||||
val S0 = CaptchaStateSlice()
|
||||
Check(
|
||||
"切片 Captcha:默认不造假、三个集合为空",
|
||||
!S0.UseFake && S0.EnabledLocations.isEmpty() &&
|
||||
S0.VerifiedLocations.isEmpty() && S0.LocationsToReset.isEmpty()
|
||||
)
|
||||
val S1 = ReduceCaptcha(S0, ShowFakeCaptcha)
|
||||
Check("切片 Captcha:ShowFakeCaptcha 置 useFake", S1.UseFake)
|
||||
val S2 = ReduceCaptcha(S1, SetLocations(listOf("a", "b")))
|
||||
Check(
|
||||
"切片 Captcha:SetLocations 收成集合",
|
||||
S2.EnabledLocations == setOf<Any?>("a", "b")
|
||||
)
|
||||
val S3 = ReduceCaptcha(
|
||||
ReduceCaptcha(S2, AddVerifiedCaptchaLocation("a")),
|
||||
AddVerifiedCaptchaLocation("b"),
|
||||
)
|
||||
Check(
|
||||
"切片 Captcha:已验证集合加元素",
|
||||
S3.VerifiedLocations == setOf<Any?>("a", "b")
|
||||
)
|
||||
Check(
|
||||
"切片 Captcha:已验证集合删元素",
|
||||
ReduceCaptcha(S3, RemoveVerifiedCaptchaLocation("a"))
|
||||
.VerifiedLocations == setOf<Any?>("b")
|
||||
)
|
||||
val S4 = ReduceCaptcha(
|
||||
ReduceCaptcha(S3, AddCaptchaLocationToReset("c")),
|
||||
RemoveCaptchaLocationToReset("c"),
|
||||
)
|
||||
Check("切片 Captcha:待重置集合加减后为空", S4.LocationsToReset.isEmpty())
|
||||
Check(
|
||||
"切片 Captcha:LocationsUpdated 追加到启用集合",
|
||||
ReduceCaptcha(S4, LocationsUpdated("d"))
|
||||
.EnabledLocations == setOf<Any?>("a", "b", "d")
|
||||
)
|
||||
Check("切片 Captcha:无关动作不改状态", ReduceCaptcha(S4, AddFrags(1)) == S4)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, ShowFakeCaptcha)
|
||||
Check(
|
||||
"根:ShowFakeCaptcha 只动 captchaState",
|
||||
Root1.CaptchaState.UseFake && Root1.ModalScreen == Root0.ModalScreen
|
||||
)
|
||||
val W = RootWiring.ByField("captchaState")!!
|
||||
Check(
|
||||
"根:captchaState 委派到 jP / ar.iqt 且 7 个动作",
|
||||
W.SliceClass == "jP" && W.Reducer == "ar.iqt" &&
|
||||
W.Actions.toSet() == setOf(
|
||||
"ShowFakeCaptcha", "SetLocations", "AddVerifiedCaptchaLocation",
|
||||
"RemoveVerifiedCaptchaLocation", "AddCaptchaLocationToReset",
|
||||
"RemoveCaptchaLocationToReset", "LocationsUpdated",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// ㊽ 切片 reducer:ModalScreen(nV / Fs.js1,2 字段;4 个动作)
|
||||
run {
|
||||
val S0 = ModalScreenStateSlice()
|
||||
Check(
|
||||
"切片 ModalScreen:默认无当前窗口、队列为空",
|
||||
S0.Current == null && S0.ModalQueue.isEmpty()
|
||||
)
|
||||
val S1 = ReduceModalScreen(S0, AddModal(true))
|
||||
Check(
|
||||
"切片 ModalScreen:AddModal 写 current 并入队",
|
||||
S1.Current == true && S1.ModalQueue == listOf<Any?>(true)
|
||||
)
|
||||
Check(
|
||||
"切片 ModalScreen:同名窗口不重复入队",
|
||||
ReduceModalScreen(S1, AddModal(true)) == S1
|
||||
)
|
||||
val S2 = ReduceModalScreen(S1, AddModal(false))
|
||||
Check(
|
||||
"切片 ModalScreen:第二个窗口排到队尾",
|
||||
S2.Current == false && S2.ModalQueue == listOf<Any?>(true, false)
|
||||
)
|
||||
val S3 = ReduceModalScreen(S2, RemoveModal(true))
|
||||
Check(
|
||||
"切片 ModalScreen:RemoveModal 出队并把 current 交给队首",
|
||||
S3.Current == false && S3.ModalQueue == listOf<Any?>(false)
|
||||
)
|
||||
Check(
|
||||
"切片 ModalScreen:CloseCurrentModal 清掉当前窗口",
|
||||
ReduceModalScreen(S3, CloseCurrentModal) == ModalScreenStateSlice()
|
||||
)
|
||||
Check(
|
||||
"切片 ModalScreen:RemoveCurrentByName 名称不符时不动",
|
||||
ReduceModalScreen(S3, RemoveCurrentByName("other")) == S3
|
||||
)
|
||||
Check(
|
||||
"切片 ModalScreen:RemoveCurrentByName 名称匹配时关闭",
|
||||
ReduceModalScreen(S3, RemoveCurrentByName("false")) == ModalScreenStateSlice()
|
||||
)
|
||||
Check(
|
||||
"切片 ModalScreen:无关动作不改状态",
|
||||
ReduceModalScreen(S3, AddFrags(1)) == S3
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, AddModal(true))
|
||||
Check(
|
||||
"根:AddModal 只动 modalScreen",
|
||||
Root1.ModalScreen.Current == true &&
|
||||
Root1.EventGoods == Root0.EventGoods
|
||||
)
|
||||
val W = RootWiring.ByField("modalScreen")!!
|
||||
Check(
|
||||
"根:modalScreen 委派到 nV / Fs.js1 且 4 个动作",
|
||||
W.SliceClass == "nV" && W.Reducer == "Fs.js1" &&
|
||||
W.Actions.toSet() == setOf(
|
||||
"AddModal", "RemoveModal", "CloseCurrentModal", "RemoveCurrentByName",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// ㊾ 切片 reducer:DroppableGold(Vet / Wp.kth,1 字段;Ket/Yet 两个单例)
|
||||
run {
|
||||
val S0 = DroppableGoldStateSlice()
|
||||
Check("切片 DroppableGold:默认显示作者署名", S0.ShowDroppableGoldAuthor)
|
||||
Check(
|
||||
"切片 DroppableGold:Hide 置 false、Show 置 true",
|
||||
!ReduceDroppableGold(S0, HideDroppableGoldAuthor).ShowDroppableGoldAuthor &&
|
||||
ReduceDroppableGold(S0, ShowDroppableGoldAuthor).ShowDroppableGoldAuthor
|
||||
)
|
||||
Check(
|
||||
"切片 DroppableGold:无关动作不改状态",
|
||||
ReduceDroppableGold(S0, AddFrags(1)) == S0
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, HideDroppableGoldAuthor)
|
||||
Check(
|
||||
"根:HideDroppableGoldAuthor 只动 droppableGold",
|
||||
!Root1.DroppableGold.ShowDroppableGoldAuthor &&
|
||||
Root1.CreatorTagState == Root0.CreatorTagState
|
||||
)
|
||||
val W = RootWiring.ByField("droppableGold")!!
|
||||
Check(
|
||||
"根:droppableGold 委派到 Vet / Wp.kth 且 2 个动作",
|
||||
W.SliceClass == "Vet" && W.Reducer == "Wp.kth" &&
|
||||
W.Actions.toSet() == setOf("ShowDroppableGoldAuthor", "HideDroppableGoldAuthor")
|
||||
)
|
||||
}
|
||||
|
||||
// ㊿ 切片 reducer:EventGoods(W7 / Wc.esx,1 字段;V7 → InitEventGoods)
|
||||
run {
|
||||
val S0 = EventGoodsStateSlice()
|
||||
Check("切片 EventGoods:默认空表", S0.EventGoods.isEmpty())
|
||||
val S1 = ReduceEventGoods(S0, InitEventGoods("spectatorMode", true))
|
||||
Check(
|
||||
"切片 EventGoods:InitEventGoods 写键值",
|
||||
S1.EventGoods == mapOf<Any?, Any?>("spectatorMode" to true)
|
||||
)
|
||||
val S2 = ReduceEventGoods(S1, InitEventGoods("spectatorMode", null))
|
||||
Check("切片 EventGoods:goods 为空时删键", S2.EventGoods.isEmpty())
|
||||
Check(
|
||||
"切片 EventGoods:无关动作不改状态",
|
||||
ReduceEventGoods(S1, AddFrags(1)) == S1
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, InitEventGoods("k", 1))
|
||||
Check(
|
||||
"根:InitEventGoods 只动 eventGoods",
|
||||
Root1.EventGoods.EventGoods == mapOf<Any?, Any?>("k" to 1) &&
|
||||
Root1.RewardedVideosState == Root0.RewardedVideosState
|
||||
)
|
||||
val W = RootWiring.ByField("eventGoods")!!
|
||||
Check(
|
||||
"根:eventGoods 委派到 W7 / Wc.esx",
|
||||
W.SliceClass == "W7" && W.Reducer == "Wc.esx" &&
|
||||
W.Actions == listOf("InitEventGoods")
|
||||
)
|
||||
}
|
||||
|
||||
// 51 切片 reducer:CreatorTag(qO / ze.er2,2 字段;4 个动作)
|
||||
run {
|
||||
val S0 = CreatorTagStateSlice()
|
||||
Check("切片 CreatorTag:默认两个字段都为 null", S0.CreatorTag == null && S0.CreatorTags == null)
|
||||
val S1 = ReduceCreatorTag(S0, SetCreatorTags(listOf("a")))
|
||||
Check("切片 CreatorTag:SetCreatorTags 写列表", S1.CreatorTags == listOf<Any?>("a"))
|
||||
Check(
|
||||
"切片 CreatorTag:SetCreatorTag 写当前标签",
|
||||
ReduceCreatorTag(S1, SetCreatorTag("t1")).CreatorTag == "t1"
|
||||
)
|
||||
val S2 = ReduceCreatorTag(S1, SetAttachedCreatorTag("t2"))
|
||||
Check(
|
||||
"切片 CreatorTag:SetAttachedCreatorTag 覆盖当前标签",
|
||||
S2.CreatorTag == "t2" && S2.CreatorTags == listOf<Any?>("a")
|
||||
)
|
||||
val S3 = ReduceCreatorTag(S2, ClearCreatorTag)
|
||||
Check(
|
||||
"切片 CreatorTag:ClearCreatorTag 只清当前标签",
|
||||
S3.CreatorTag == null && S3.CreatorTags == listOf<Any?>("a")
|
||||
)
|
||||
Check("切片 CreatorTag:无关动作不改状态", ReduceCreatorTag(S3, AddFrags(1)) == S3)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, SetCreatorTag("x"))
|
||||
Check(
|
||||
"根:SetCreatorTag 只动 creatorTagState",
|
||||
Root1.CreatorTagState.CreatorTag == "x" && Root1.EventGoods == Root0.EventGoods
|
||||
)
|
||||
val W = RootWiring.ByField("creatorTagState")!!
|
||||
Check(
|
||||
"根:creatorTagState 委派到 qO / ze.er2 且 4 个动作",
|
||||
W.SliceClass == "qO" && W.Reducer == "ze.er2" &&
|
||||
W.Actions.toSet() == setOf(
|
||||
"SetCreatorTags", "SetCreatorTag", "SetAttachedCreatorTag", "ClearCreatorTag",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// 52 切片 reducer:RewardedVideos(JQ / xh.zsl,1 字段;t1 → SetDisplayState)
|
||||
run {
|
||||
val S0 = RewardedVideosStateSlice()
|
||||
Check("切片 RewardedVideos:默认 NONE", S0.DisplayState == RewardVideoDisplayState.NONE)
|
||||
Check(
|
||||
"切片 RewardedVideos:SetDisplayState 写枚举",
|
||||
ReduceRewardedVideos(S0, SetDisplayState(RewardVideoDisplayState.DISPLAY))
|
||||
.DisplayState == RewardVideoDisplayState.DISPLAY
|
||||
)
|
||||
Check(
|
||||
"切片 RewardedVideos:无关动作不改状态",
|
||||
ReduceRewardedVideos(S0, AddFrags(1)) == S0
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, SetDisplayState(RewardVideoDisplayState.LOADING))
|
||||
Check(
|
||||
"根:SetDisplayState 只动 rewardedVideosState",
|
||||
Root1.RewardedVideosState.DisplayState == RewardVideoDisplayState.LOADING &&
|
||||
Root1.PasswordChangeState == Root0.PasswordChangeState
|
||||
)
|
||||
val W = RootWiring.ByField("rewardedVideosState")!!
|
||||
Check(
|
||||
"根:rewardedVideosState 委派到 JQ / xh.zsl",
|
||||
W.SliceClass == "JQ" && W.Reducer == "xh.zsl" &&
|
||||
W.Actions == listOf("SetDisplayState")
|
||||
)
|
||||
}
|
||||
|
||||
// 53 切片 reducer:PasswordChange(VD / uu.pr6,3 字段;UD + HD)
|
||||
run {
|
||||
val S0 = PasswordChangeStateSlice()
|
||||
Check(
|
||||
"切片 PasswordChange:默认三个空串",
|
||||
S0.Hash == "" && S0.Uid == "" && S0.Email == ""
|
||||
)
|
||||
val S1 = ReducePasswordChange(S0, SetPasswordChangeHash("h"))
|
||||
Check(
|
||||
"切片 PasswordChange:SetPasswordChangeHash 只写 hash",
|
||||
S1.Hash == "h" && S1.Uid == "" && S1.Email == ""
|
||||
)
|
||||
val S2 = ReducePasswordChange(S1, ShowEmailAndPasswordChangeDialog("e", "u", "r"))
|
||||
Check(
|
||||
"切片 PasswordChange:ShowEmailAndPasswordChangeDialog 写 uid/email 但保留 hash",
|
||||
S2.Hash == "h" && S2.Uid == "u" && S2.Email == "e"
|
||||
)
|
||||
Check(
|
||||
"切片 PasswordChange:无关动作不改状态",
|
||||
ReducePasswordChange(S2, AddFrags(1)) == S2
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, SetPasswordChangeHash("x"))
|
||||
Check(
|
||||
"根:SetPasswordChangeHash 只动 passwordChangeState",
|
||||
Root1.PasswordChangeState.Hash == "x" && Root1.TipsState == Root0.TipsState
|
||||
)
|
||||
val W = RootWiring.ByField("passwordChangeState")!!
|
||||
Check(
|
||||
"根:passwordChangeState 委派到 VD / uu.pr6 且 2 个动作",
|
||||
W.SliceClass == "VD" && W.Reducer == "uu.pr6" &&
|
||||
W.Actions.toSet() == setOf(
|
||||
"SetPasswordChangeHash", "ShowEmailAndPasswordChangeDialog",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val Failed = Results.filter { !it.second }
|
||||
println("TankiOffline 状态层自检:${Results.size} 项")
|
||||
for ((Name, Ok) in Results) println((if (Ok) " ✓ " else " ✗ ") + Name)
|
||||
|
||||
Reference in new issue
Block a user