feat(state): 迁移 battlePauseState/battleViewState/tankActionsLogState/suppliesTutorial
This commit is contained in:
1 parent
0183f191d3
commit
38ec7fa28e
11 files changed
+719
-49
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` 动作名。
|
||||
- 已迁移切片 **59/89**:
|
||||
- 已迁移切片 **63/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)
|
||||
@@ -330,12 +330,23 @@
|
||||
`SetValidationStatus` 按 ordinal 映射输入状态(EMPTY→SHORT、SHORT→NOT_VALID、RESERVED→RESERVED、
|
||||
FORBIDDEN/NOT_VALID→FORBIDDEN、FREE→FREE)并把 `isResponseDelivered` 置 true;
|
||||
`G8`→`ResetRenameDialog` 复位弹窗字段但保留 rubies / hash / email。
|
||||
- `battlePauseState` → `dT` / `NT().mqc`(`BattlePauseStateReducer.kt`):3 字段,4 个分支。
|
||||
`OnPauseMode` 置 `inAutoPauseMode=true` 并写剩余时长;`ResetBattlePause` 只保留
|
||||
`idleKickPeriodInMsec`;`timeForAutoLeave` 原值是「当前时间 + 时长」,时钟换算留给中间件层。
|
||||
- `battleViewState` → `DT` / `sI.jqd`(`BattleViewStateReducer.kt`):7 字段,14 个分支。
|
||||
`SetVisibility` / `SetElementsVisibility` 按 `visible` 增删 `invisibleElements`;
|
||||
其余 12 个无 `toString` 的动作两两成对,分别切换输入 / 统计 / 菜单 / 隐藏 / 后台位。
|
||||
- `tankActionsLogState` → `vI` / `wi.gqe`(`TankActionsLogReducer.kt`):2 字段,4 个分支。
|
||||
`UpdateLog` 在超过 10 条时先丢弃最早一条再追加(源码 `(Lf = 10)`);
|
||||
`OnUserJoinTheBattle` / `OnUserLeaveTheBattle` 增删 `noticed`;`dI`→`ResetTankActionsLog` 整片复位。
|
||||
- `suppliesTutorial` → `ust` / `Uw.uth`(`SuppliesTutorialReducer.kt`):2 字段,2 个分支。
|
||||
生成器认不出切片类(根构造默认值不是 `new ust()`),在迁移表里显式补 `SliceClass: 'ust'`。
|
||||
- `launchParams` → `(pass-through)`:原根 reducer 对 `hpx_1` 没有调用,缺省是 `ag()` 空 Map;
|
||||
`RootState.LaunchParams` 收口为 `LaunchParamsStateSlice = Map<String, String>`,不新增 reducer/动作。
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 58 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **30 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 59/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **685 项全绿**,含 89 槽位完整性、58 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 62 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **26 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 63/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **719 项全绿**,含 89 槽位完整性、62 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
以及用 `action_trace_merged.json` 真实派发的两条商店动作(`SetCoinPaymentProviderUrl` / `ToggleShopActivity`)回放。
|
||||
- 委派表里的已知形态:`shop` / `home` / `localBattleUserState` / `partner` 是内联 IIFE,
|
||||
已按字段具名为 `(inline@<field>)` 并从函数体抓到顶层动作名(69 / 1 / 2 / 11 个);
|
||||
@@ -353,7 +364,8 @@
|
||||
battleTutorial 的 2 个、spectator 的 4 个、antiAddiction 的 3 个、moderation 的 13 个、
|
||||
迁移 / 注册共用的 10 个(`Mit`…`_rt`)匿名类 / 单例同样按效果定名并登记。
|
||||
friends 的 2 个、suppliesState 的 1 个、battleInviteState 的 2 个、partner 的 4 个、
|
||||
userRenameState 的 5 个也已登记(其中 `mtt` 因同名类冲突改名为 `AddInvitedUser`)。
|
||||
userRenameState 的 5 个也已登记(其中 `mtt` 因同名类冲突改名为 `AddInvitedUser`);
|
||||
battlePauseState 的 2 个、battleViewState 的 12 个、tankActionsLogState 的 1 个同样按效果定名。
|
||||
|
||||
### S4 引擎核心
|
||||
- 模块:32088(3D 数学)、92980(渲染)、61378(ECS)、55088(物理)、36659 + 71105(资源)、36734(音频)、3569(输入)
|
||||
|
||||
+117
-23
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generatedAt": "2026-10-24T07:48:13.464Z",
|
||||
"generatedAt": "2026-10-24T08:27:50.811Z",
|
||||
"module": "module_10032.js",
|
||||
"RootState": {
|
||||
"Class": "z6",
|
||||
@@ -65,7 +65,11 @@
|
||||
"clanUserInfo",
|
||||
"battleInviteState",
|
||||
"partner",
|
||||
"userRenameState"
|
||||
"userRenameState",
|
||||
"battlePauseState",
|
||||
"battleViewState",
|
||||
"tankActionsLogState",
|
||||
"suppliesTutorial"
|
||||
],
|
||||
"AnonymousActions": [
|
||||
{
|
||||
@@ -1088,6 +1092,96 @@
|
||||
"Name": "HideLinkErrorWarning",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "showLinkErrorWarning=false(`n.cte(…, !1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "xT",
|
||||
"Name": "ResetBattlePause",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "inAutoPauseMode=false、timeForAutoLeave 复位,保留 idleKickPeriodInMsec(`new dT(cd, cd, n.uqb_1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "TT",
|
||||
"Name": "CancelAutoPause",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "inAutoPauseMode=false(`n.wqb(!1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "WT",
|
||||
"Name": "ResetBattleView",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "new DT() 整片复位"
|
||||
},
|
||||
{
|
||||
"Local": "YT",
|
||||
"Name": "ClearInvisibleElements",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "invisibleElements=emptySet()(`n.vqc(cd, cd, Yg())`)"
|
||||
},
|
||||
{
|
||||
"Local": "JT",
|
||||
"Name": "EnableBattleInput",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "inputEnabled=true(`n.vqc(cd, cd, cd, !0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "ZT",
|
||||
"Name": "DisableBattleInput",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "inputEnabled=false(`n.vqc(cd, cd, cd, !1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "QT",
|
||||
"Name": "EnableBattleStatistics",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "battleStatisticsActive=true(`n.vqc(cd, cd, cd, cd, !0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "tI",
|
||||
"Name": "DisableBattleStatistics",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "battleStatisticsActive=false(`n.vqc(cd, cd, cd, cd, !1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "nI",
|
||||
"Name": "EnableBattleMenu",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "battleMenuActive=true(`n.vqc(cd, cd, cd, cd, cd, !0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "iI",
|
||||
"Name": "DisableBattleMenu",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "battleMenuActive=false(`n.vqc(cd, cd, cd, cd, cd, !1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "nE",
|
||||
"Name": "HideBattleView",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "isHidden=true(`n.vqc(cd, !0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "tE",
|
||||
"Name": "ShowBattleView",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "isHidden=false(`n.vqc(cd, !1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "rI",
|
||||
"Name": "EnterBackground",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "inBackgroundState=true(`n.vqc(!0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "eI",
|
||||
"Name": "LeaveBackground",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "inBackgroundState=false(`n.vqc(!1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "dI",
|
||||
"Name": "ResetTankActionsLog",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "new vI() 整片复位"
|
||||
}
|
||||
],
|
||||
"Markers": [
|
||||
@@ -2098,13 +2192,13 @@
|
||||
"Reducer": "NT().mqc",
|
||||
"Delegate": "NT().mqc(t, n.lpw_1)",
|
||||
"Actions": [
|
||||
"?TT",
|
||||
"?xT",
|
||||
"CancelAutoPause",
|
||||
"OnPauseMode",
|
||||
"ResetBattlePause",
|
||||
"SetIdleKickPeriod"
|
||||
],
|
||||
"Default": "new dT()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "battleViewState",
|
||||
@@ -2113,23 +2207,23 @@
|
||||
"Reducer": "sI.jqd",
|
||||
"Delegate": "(null == $n && new sI(), $n).jqd(t, n.mpw_1)",
|
||||
"Actions": [
|
||||
"?JT",
|
||||
"?QT",
|
||||
"?WT",
|
||||
"?YT",
|
||||
"?ZT",
|
||||
"?eI",
|
||||
"?iI",
|
||||
"?nE",
|
||||
"?nI",
|
||||
"?rI",
|
||||
"?tE",
|
||||
"?tI",
|
||||
"ClearInvisibleElements",
|
||||
"DisableBattleInput",
|
||||
"DisableBattleMenu",
|
||||
"DisableBattleStatistics",
|
||||
"EnableBattleInput",
|
||||
"EnableBattleMenu",
|
||||
"EnableBattleStatistics",
|
||||
"EnterBackground",
|
||||
"HideBattleView",
|
||||
"LeaveBackground",
|
||||
"ResetBattleView",
|
||||
"SetElementsVisibility",
|
||||
"SetVisibility"
|
||||
"SetVisibility",
|
||||
"ShowBattleView"
|
||||
],
|
||||
"Default": "new DT()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "rankUpDialogState",
|
||||
@@ -2163,13 +2257,13 @@
|
||||
"Reducer": "wi.gqe",
|
||||
"Delegate": "wi.gqe(t, n.ppw_1)",
|
||||
"Actions": [
|
||||
"?dI",
|
||||
"OnUserJoinTheBattle",
|
||||
"OnUserLeaveTheBattle",
|
||||
"ResetTankActionsLog",
|
||||
"UpdateLog"
|
||||
],
|
||||
"Default": "new vI()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "battleMessage",
|
||||
@@ -2699,7 +2793,7 @@
|
||||
{
|
||||
"Field": "suppliesTutorial",
|
||||
"Slot": "zpx_1",
|
||||
"SliceClass": null,
|
||||
"SliceClass": "ust",
|
||||
"Reducer": "Uw.uth",
|
||||
"Delegate": "Uw.uth(t, n.zpx_1)",
|
||||
"Actions": [
|
||||
@@ -2707,7 +2801,7 @@
|
||||
"SetLoadedElement"
|
||||
],
|
||||
"Default": "",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "questCategories",
|
||||
|
||||
@@ -257,6 +257,24 @@ const AnonymousActionNames = new Map([
|
||||
['U8', 'MarkRenameFailed'],
|
||||
['G8', 'ResetRenameDialog'],
|
||||
['Q8', 'HideLinkErrorWarning'],
|
||||
// battlePauseState 切片(dT / PT.mqc):xT / TT 没有 toString。
|
||||
['xT', 'ResetBattlePause'],
|
||||
['TT', 'CancelAutoPause'],
|
||||
// battleViewState 切片(DT / sI.jqd):WT/YT/JT/ZT/QT/tI/nI/iI/nE/tE/rI/eI 没有 toString。
|
||||
['WT', 'ResetBattleView'],
|
||||
['YT', 'ClearInvisibleElements'],
|
||||
['JT', 'EnableBattleInput'],
|
||||
['ZT', 'DisableBattleInput'],
|
||||
['QT', 'EnableBattleStatistics'],
|
||||
['tI', 'DisableBattleStatistics'],
|
||||
['nI', 'EnableBattleMenu'],
|
||||
['iI', 'DisableBattleMenu'],
|
||||
['nE', 'HideBattleView'],
|
||||
['tE', 'ShowBattleView'],
|
||||
['rI', 'EnterBackground'],
|
||||
['eI', 'LeaveBackground'],
|
||||
// tankActionsLogState 切片(vI / yI.gqe):dI 没有 toString。
|
||||
['dI', 'ResetTankActionsLog'],
|
||||
]);
|
||||
|
||||
// 非动作的 `instanceof`:屏幕标识类,用于 GoTo 分支判断(不是 dispatch 的动作)。
|
||||
@@ -704,6 +722,15 @@ const Migrated = {
|
||||
battleInviteState: { Type: 'BattleInviteStateSlice', Reduce: 'ReduceBattleInvite' },
|
||||
partner: { Type: 'PartnerStateSlice', Reduce: 'ReducePartner' },
|
||||
userRenameState: { Type: 'UserRenameStateSlice', Reduce: 'ReduceUserRename' },
|
||||
battlePauseState: { Type: 'BattlePauseStateSlice', Reduce: 'ReduceBattlePause' },
|
||||
battleViewState: { Type: 'BattleViewStateSlice', Reduce: 'ReduceBattleView' },
|
||||
tankActionsLogState: { Type: 'TankActionsLogStateSlice', Reduce: 'ReduceTankActionsLog' },
|
||||
// 根构造里 suppliesTutorial 的默认值不是 `new <Class>()`,生成器认不出切片类,这里显式补。
|
||||
suppliesTutorial: {
|
||||
Type: 'SuppliesTutorialStateSlice',
|
||||
SliceClass: 'ust',
|
||||
Reduce: 'ReduceSuppliesTutorial',
|
||||
},
|
||||
};
|
||||
|
||||
for (const R of Rows) R.Migrated = Object.prototype.hasOwnProperty.call(Migrated, R.Field);
|
||||
@@ -1039,6 +1066,33 @@ const UserRenameAnonymousEffects = {
|
||||
Q8: 'showLinkErrorWarning=false(`n.cte(…, !1)`)',
|
||||
};
|
||||
|
||||
// battlePauseState 切片(dT / PT.mqc):xT / TT 没有 toString。
|
||||
const BattlePauseAnonymousEffects = {
|
||||
xT: 'inAutoPauseMode=false、timeForAutoLeave 复位,保留 idleKickPeriodInMsec(`new dT(cd, cd, n.uqb_1)`)',
|
||||
TT: 'inAutoPauseMode=false(`n.wqb(!1)`)',
|
||||
};
|
||||
|
||||
// battleViewState 切片(DT / sI.jqd):12 个类没有 toString。
|
||||
const BattleViewAnonymousEffects = {
|
||||
WT: 'new DT() 整片复位',
|
||||
YT: 'invisibleElements=emptySet()(`n.vqc(cd, cd, Yg())`)',
|
||||
JT: 'inputEnabled=true(`n.vqc(cd, cd, cd, !0)`)',
|
||||
ZT: 'inputEnabled=false(`n.vqc(cd, cd, cd, !1)`)',
|
||||
QT: 'battleStatisticsActive=true(`n.vqc(cd, cd, cd, cd, !0)`)',
|
||||
tI: 'battleStatisticsActive=false(`n.vqc(cd, cd, cd, cd, !1)`)',
|
||||
nI: 'battleMenuActive=true(`n.vqc(cd, cd, cd, cd, cd, !0)`)',
|
||||
iI: 'battleMenuActive=false(`n.vqc(cd, cd, cd, cd, cd, !1)`)',
|
||||
nE: 'isHidden=true(`n.vqc(cd, !0)`)',
|
||||
tE: 'isHidden=false(`n.vqc(cd, !1)`)',
|
||||
rI: 'inBackgroundState=true(`n.vqc(!0)`)',
|
||||
eI: 'inBackgroundState=false(`n.vqc(!1)`)',
|
||||
};
|
||||
|
||||
// tankActionsLogState 切片(vI / yI.gqe):dI 没有 toString。
|
||||
const TankActionsLogAnonymousEffects = {
|
||||
dI: 'new vI() 整片复位',
|
||||
};
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(P, 'names', 'root_wiring.json'),
|
||||
JSON.stringify(
|
||||
@@ -1265,6 +1319,24 @@ fs.writeFileSync(
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(BattlePauseAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(BattleViewAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(TankActionsLogAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
],
|
||||
Markers: [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
// BattlePauseStateReducer.kt —— 战斗自动暂停切片(对应 module_10032 的 dT 状态 + PT.mqc)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 dT:3 个字段,toString 名 "BattlePauseState(…)"。
|
||||
// 默认:inAutoPauseMode=false、timeForAutoLeave=new Dd(0,0)、idleKickPeriodInMsec=0。
|
||||
// 根委派:`NT().mqc(t, n.lpw_1)`。
|
||||
// reducer:
|
||||
// xT(无 toString) → `new dT(cd, cd, n.uqb_1)`:只保留 idleKickPeriodInMsec
|
||||
// jT(OnPauseMode) → inAutoPauseMode=true、timeForAutoLeave=剩余时长
|
||||
// TT(无 toString) → inAutoPauseMode=false
|
||||
// CT(SetIdleKickPeriod)→ idleKickPeriodInMsec
|
||||
//
|
||||
// `timeForAutoLeave` 原值是 `Fg(Md(), Wg(remaining))`(当前时间 + 时长),需要时钟服务;
|
||||
// 离线重建把动作给的值原样收口在 `Any?` 里,时间换算留给中间件层。
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.OnPauseMode
|
||||
import App.State.SetIdleKickPeriod
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `xT`:退出战斗时复位暂停状态,只保留挂机踢出周期。 */
|
||||
object ResetBattlePause
|
||||
|
||||
/** 原 `TT`:取消自动暂停。 */
|
||||
object CancelAutoPause
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class BattlePauseStateSlice(
|
||||
val InAutoPauseMode: Boolean = false,
|
||||
val TimeForAutoLeave: Any? = null,
|
||||
val IdleKickPeriodInMsec: Any? = 0,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceBattlePause(
|
||||
State0: BattlePauseStateSlice,
|
||||
Action: Any,
|
||||
): BattlePauseStateSlice = when (Action) {
|
||||
is ResetBattlePause -> BattlePauseStateSlice(IdleKickPeriodInMsec = State0.IdleKickPeriodInMsec)
|
||||
is OnPauseMode -> State0.copy(
|
||||
InAutoPauseMode = true,
|
||||
TimeForAutoLeave = Action.remainingTimeForAutoLeave,
|
||||
)
|
||||
is CancelAutoPause -> State0.copy(InAutoPauseMode = false)
|
||||
is SetIdleKickPeriod -> State0.copy(IdleKickPeriodInMsec = Action.idleKickPeriodMsec)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
// BattleViewStateReducer.kt —— 战斗视图切片(对应 module_10032 的 DT 状态 + sI.jqd)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 DT:7 个字段,toString 名 "BattleViewState(…)"。
|
||||
// 默认:inBackgroundState=true、isHidden=true、invisibleElements=emptySet()、inputEnabled=true、
|
||||
// battleStatisticsActive=false、battleMenuActive=false、joystickPosition=null。
|
||||
// 根委派:`(null == $n && new sI(), $n).jqd(t, n.mpw_1)`。
|
||||
// reducer(13 个实例臂):
|
||||
// WT(无 toString) → `new DT()` 整片复位
|
||||
// VT(SetVisibility) → invisibleElements:visible=true 删元素、false 加元素
|
||||
// KT(SetElementsVisibility)→ 同上,但按集合批量增删
|
||||
// YT(无 toString) → invisibleElements=emptySet()
|
||||
// JT / ZT(无 toString) → inputEnabled=true / false
|
||||
// QT / tI(无 toString) → battleStatisticsActive=true / false
|
||||
// nI / iI(无 toString) → battleMenuActive=true / false
|
||||
// nE / tE(无 toString) → isHidden=true / false
|
||||
// rI / eI(无 toString) → inBackgroundState=true / false
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.SetElementsVisibility
|
||||
import App.State.SetVisibility
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `WT`:整片复位(`new DT()`)。 */
|
||||
object ResetBattleView
|
||||
|
||||
/** 原 `YT`:清空隐藏元素集合。 */
|
||||
object ClearInvisibleElements
|
||||
|
||||
/** 原 `JT` / `ZT`:开 / 关输入。 */
|
||||
object EnableBattleInput
|
||||
object DisableBattleInput
|
||||
|
||||
/** 原 `QT` / `tI`:开 / 关战斗统计。 */
|
||||
object EnableBattleStatistics
|
||||
object DisableBattleStatistics
|
||||
|
||||
/** 原 `nI` / `iI`:开 / 关战斗菜单。 */
|
||||
object EnableBattleMenu
|
||||
object DisableBattleMenu
|
||||
|
||||
/** 原 `nE` / `tE`:隐藏 / 显示战斗界面。 */
|
||||
object HideBattleView
|
||||
object ShowBattleView
|
||||
|
||||
/** 原 `rI` / `eI`:切到后台 / 前台。 */
|
||||
object EnterBackground
|
||||
object LeaveBackground
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class BattleViewStateSlice(
|
||||
val InBackgroundState: Boolean = true,
|
||||
val IsHidden: Boolean = true,
|
||||
val InvisibleElements: Set<Any?> = emptySet(),
|
||||
val InputEnabled: Boolean = true,
|
||||
val BattleStatisticsActive: Boolean = false,
|
||||
val BattleMenuActive: Boolean = false,
|
||||
val JoystickPosition: Any? = null,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
/** 原 `Qg`:集合 -= 集合 / 单值。 */
|
||||
private fun Minus(Target: Set<Any?>, Value: Any?): Set<Any?> =
|
||||
if (Value is Iterable<*>) Target - Value.toSet() else Target - Value
|
||||
|
||||
/** 原 `Zg`:集合 += 集合 / 单值。 */
|
||||
private fun Plus(Target: Set<Any?>, Value: Any?): Set<Any?> =
|
||||
if (Value is Iterable<*>) Target + Value.toSet() else Target + Value
|
||||
|
||||
fun ReduceBattleView(
|
||||
State0: BattleViewStateSlice,
|
||||
Action: Any,
|
||||
): BattleViewStateSlice = when (Action) {
|
||||
is ResetBattleView -> BattleViewStateSlice()
|
||||
is SetVisibility -> State0.copy(
|
||||
InvisibleElements =
|
||||
if (Action.visible) State0.InvisibleElements - Action.element
|
||||
else State0.InvisibleElements + Action.element,
|
||||
)
|
||||
is SetElementsVisibility -> State0.copy(
|
||||
InvisibleElements =
|
||||
if (Action.visible) Minus(State0.InvisibleElements, Action.elements)
|
||||
else Plus(State0.InvisibleElements, Action.elements),
|
||||
)
|
||||
is ClearInvisibleElements -> State0.copy(InvisibleElements = emptySet())
|
||||
is EnableBattleInput -> State0.copy(InputEnabled = true)
|
||||
is DisableBattleInput -> State0.copy(InputEnabled = false)
|
||||
is EnableBattleStatistics -> State0.copy(BattleStatisticsActive = true)
|
||||
is DisableBattleStatistics -> State0.copy(BattleStatisticsActive = false)
|
||||
is EnableBattleMenu -> State0.copy(BattleMenuActive = true)
|
||||
is DisableBattleMenu -> State0.copy(BattleMenuActive = false)
|
||||
is HideBattleView -> State0.copy(IsHidden = true)
|
||||
is ShowBattleView -> State0.copy(IsHidden = false)
|
||||
is EnterBackground -> State0.copy(InBackgroundState = true)
|
||||
is LeaveBackground -> State0.copy(InBackgroundState = false)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// SuppliesTutorialReducer.kt —— 补给上手指引切片(对应 module_10032 的 ust 状态 + fst.uth)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 ust:2 个字段,toString 名 "SuppliesTutorialState(loadedElement=…, activatedInCurrentBattle=…)"。
|
||||
// 默认:loadedElement=null、activatedInCurrentBattle=false。
|
||||
// 根委派:`Uw.uth(t, n.zpx_1)`。
|
||||
// reducer:
|
||||
// hst(ActivatedInCurrentBattle)→ activatedInCurrentBattle
|
||||
// ast(SetLoadedElement) → loadedElement
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.ActivatedInCurrentBattle
|
||||
import App.State.SetLoadedElement
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class SuppliesTutorialStateSlice(
|
||||
val LoadedElement: Any? = null,
|
||||
val ActivatedInCurrentBattle: Boolean = false,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceSuppliesTutorial(
|
||||
State0: SuppliesTutorialStateSlice,
|
||||
Action: Any,
|
||||
): SuppliesTutorialStateSlice = when (Action) {
|
||||
is ActivatedInCurrentBattle ->
|
||||
State0.copy(ActivatedInCurrentBattle = Action.effectActivated)
|
||||
is SetLoadedElement -> State0.copy(LoadedElement = Action.loadedElement)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// TankActionsLogReducer.kt —— 战斗日志切片(对应 module_10032 的 vI 状态 + yI.gqe)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 vI:2 个字段,toString 名 "TankActionsLogState(…)"。
|
||||
// 默认:logs=emptyList()、noticed=emptySet()。
|
||||
// 根委派:`wi.gqe(t, n.ppw_1)`。
|
||||
// reducer:
|
||||
// dI(无 toString) → `new vI()` 整片复位
|
||||
// zI(OnUserJoinTheBattle)→ noticed += userId
|
||||
// bI(OnUserLeaveTheBattle)→ noticed -= userId
|
||||
// qI(UpdateLog) → logs 先按上限截断,再追加一条
|
||||
//
|
||||
// 上限 `Lf = 10`(module_10032 初始化:`(Lf = 10)`);原逻辑是
|
||||
// 「size >= 10 时从第 2 条开始拷贝,再 append 新日志」。
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.OnUserJoinTheBattle
|
||||
import App.State.OnUserLeaveTheBattle
|
||||
import App.State.UpdateLog
|
||||
|
||||
/* ------------------------------------------------------------------ 常量 */
|
||||
|
||||
private const val MaxLogs = 10
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `dI`:整片复位(`new vI()`)。 */
|
||||
object ResetTankActionsLog
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class TankActionsLogStateSlice(
|
||||
val Logs: List<Any?> = emptyList(),
|
||||
val Noticed: Set<Any?> = emptySet(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceTankActionsLog(
|
||||
State0: TankActionsLogStateSlice,
|
||||
Action: Any,
|
||||
): TankActionsLogStateSlice = when (Action) {
|
||||
is ResetTankActionsLog -> TankActionsLogStateSlice()
|
||||
is OnUserJoinTheBattle -> State0.copy(Noticed = State0.Noticed + Action.userId)
|
||||
is OnUserLeaveTheBattle -> State0.copy(Noticed = State0.Noticed - Action.userId)
|
||||
is UpdateLog -> {
|
||||
val Kept = if (State0.Logs.size >= MaxLogs) State0.Logs.drop(1) else State0.Logs
|
||||
State0.copy(Logs = Kept + Action.tankActionLog)
|
||||
}
|
||||
else -> State0
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// RootReducer.kt —— 根 reducer 骨架(对应 module_10032 的根状态 z6 / TOState 与根 reducer k6)
|
||||
//
|
||||
// 原包 k6 对 89 个切片逐个调用各自的 reducer,再 `return n.cti(...)`(copy 出新状态)。
|
||||
// 这里采用同一形状。已迁移的 59 个切片里,58 个真正调用 reducer,launchParams 只做类型收口:
|
||||
// 这里采用同一形状。已迁移的 63 个切片里,62 个真正调用 reducer,launchParams 只做类型收口:
|
||||
//
|
||||
// inviteState → ReduceInvite(aD / pD.er5)
|
||||
// loginByPassword → ReduceLoginByPassword(gD / MD.cr6)
|
||||
@@ -61,9 +61,13 @@
|
||||
// battleInviteState → ReduceBattleInvite(att / Ttt().nth,根委派 `Ttt().nth(t, n.cpx_1)`)
|
||||
// partner → ReducePartner(UJ / `(inline@partner)`,根委派内联 IIFE)
|
||||
// userRenameState → ReduceUserRename(O8 / Rf.pte,根委派 `Rf.pte(t, n.qpx_1)`)
|
||||
// battlePauseState → ReduceBattlePause(dT / NT().mqc,根委派 `NT().mqc(t, n.lpw_1)`)
|
||||
// battleViewState → ReduceBattleView(DT / sI.jqd,根委派 `(null == $n && new sI(), $n).jqd(t, n.mpw_1)`)
|
||||
// tankActionsLogState → ReduceTankActionsLog(vI / wi.gqe,根委派 `wi.gqe(t, n.ppw_1)`)
|
||||
// suppliesTutorial → ReduceSuppliesTutorial(ust / Uw.uth,根委派 `Uw.uth(t, n.zpx_1)`)
|
||||
// launchParams → 无 reducer(原根 reducer 原样透传;默认 `ag()` = emptyMap())
|
||||
//
|
||||
// 其余 30 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 其余 26 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 所以一次 copy 里串起全部已迁移 reducer,与按动作路由再归约的结果一致。
|
||||
// 迁移进度与每个字段的证据见生成物 RootWiring.kt(不要手改)。
|
||||
package App.State
|
||||
@@ -72,7 +76,9 @@ import App.State.Reducers.ReduceAccountSettings
|
||||
import App.State.Reducers.ReduceAnnouncement
|
||||
import App.State.Reducers.ReduceAntiAddiction
|
||||
import App.State.Reducers.ReduceBattleResult
|
||||
import App.State.Reducers.ReduceBattlePause
|
||||
import App.State.Reducers.ReduceBattleTutorial
|
||||
import App.State.Reducers.ReduceBattleView
|
||||
import App.State.Reducers.ReduceBattleInvite
|
||||
import App.State.Reducers.ReduceCaptcha
|
||||
import App.State.Reducers.ReduceClanUserInfo
|
||||
@@ -119,7 +125,9 @@ import App.State.Reducers.ReduceSupportUrl
|
||||
import App.State.Reducers.ReduceSettings
|
||||
import App.State.Reducers.ReduceShop
|
||||
import App.State.Reducers.ReduceSupplies
|
||||
import App.State.Reducers.ReduceSuppliesTutorial
|
||||
import App.State.Reducers.ReduceSystem
|
||||
import App.State.Reducers.ReduceTankActionsLog
|
||||
import App.State.Reducers.ReduceTips
|
||||
import App.State.Reducers.ReduceTwitch
|
||||
import App.State.Reducers.ReduceTwoStepVerification
|
||||
@@ -198,6 +206,10 @@ object RootReducer {
|
||||
BattleInviteState = ReduceBattleInvite(State0.BattleInviteState, Action),
|
||||
Partner = ReducePartner(State0.Partner, Action),
|
||||
UserRenameState = ReduceUserRename(State0.UserRenameState, Action),
|
||||
BattlePauseState = ReduceBattlePause(State0.BattlePauseState, Action),
|
||||
BattleViewState = ReduceBattleView(State0.BattleViewState, Action),
|
||||
TankActionsLogState = ReduceTankActionsLog(State0.TankActionsLogState, Action),
|
||||
SuppliesTutorial = ReduceSuppliesTutorial(State0.SuppliesTutorial, Action),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,10 @@ import App.State.Reducers.AnnouncementStateSlice
|
||||
import App.State.Reducers.AntiAddictionStateSlice
|
||||
import App.State.Reducers.AvailabilityByRankStateSlice
|
||||
import App.State.Reducers.BattleInviteStateSlice
|
||||
import App.State.Reducers.BattlePauseStateSlice
|
||||
import App.State.Reducers.BattleResultStateSlice
|
||||
import App.State.Reducers.BattleTutorialStateSlice
|
||||
import App.State.Reducers.BattleViewStateSlice
|
||||
import App.State.Reducers.CaptchaStateSlice
|
||||
import App.State.Reducers.ClanUserInfoStateSlice
|
||||
import App.State.Reducers.ContextTutorialStateSlice
|
||||
@@ -53,8 +55,10 @@ import App.State.Reducers.SettingsStateSlice
|
||||
import App.State.Reducers.ShopStateSlice
|
||||
import App.State.Reducers.SpectatorStateSlice
|
||||
import App.State.Reducers.SuppliesStateSlice
|
||||
import App.State.Reducers.SuppliesTutorialStateSlice
|
||||
import App.State.Reducers.SupportUrlStateSlice
|
||||
import App.State.Reducers.SystemStateSlice
|
||||
import App.State.Reducers.TankActionsLogStateSlice
|
||||
import App.State.Reducers.TipsStateSlice
|
||||
import App.State.Reducers.TwitchStateSlice
|
||||
import App.State.Reducers.TwoStepVerificationStateSlice
|
||||
@@ -145,16 +149,16 @@ data class RootState(
|
||||
val MatchmakingGroup: Any? = null,
|
||||
/** 原 shop(j4 / (inline@shop))。已迁移。 */
|
||||
val Shop: ShopStateSlice = ShopStateSlice(),
|
||||
/** 原 battlePauseState(dT / NT().mqc)。未迁移:原样透传。 */
|
||||
val BattlePauseState: Any? = null,
|
||||
/** 原 battleViewState(DT / sI.jqd)。未迁移:原样透传。 */
|
||||
val BattleViewState: Any? = null,
|
||||
/** 原 battlePauseState(dT / NT().mqc)。已迁移。 */
|
||||
val BattlePauseState: BattlePauseStateSlice = BattlePauseStateSlice(),
|
||||
/** 原 battleViewState(DT / sI.jqd)。已迁移。 */
|
||||
val BattleViewState: BattleViewStateSlice = BattleViewStateSlice(),
|
||||
/** 原 rankUpDialogState(LO / Se.br3)。已迁移。 */
|
||||
val RankUpDialogState: RankUpDialogStateSlice = RankUpDialogStateSlice(),
|
||||
/** 原 clanUserInfo(hO / de.gr1)。已迁移。 */
|
||||
val ClanUserInfo: ClanUserInfoStateSlice = ClanUserInfoStateSlice(),
|
||||
/** 原 tankActionsLogState(vI / wi.gqe)。未迁移:原样透传。 */
|
||||
val TankActionsLogState: Any? = null,
|
||||
/** 原 tankActionsLogState(vI / wi.gqe)。已迁移。 */
|
||||
val TankActionsLogState: TankActionsLogStateSlice = TankActionsLogStateSlice(),
|
||||
/** 原 battleMessage(FE / vT().rqb)。未迁移:原样透传。 */
|
||||
val BattleMessage: Any? = null,
|
||||
/** 原 battleChat(Q6 / Hf.wtg)。未迁移:原样透传。 */
|
||||
@@ -225,8 +229,8 @@ data class RootState(
|
||||
val ItemNotifications: Any? = null,
|
||||
/** 原 contextTutorial(Mst / Jst().tth)。已迁移。 */
|
||||
val ContextTutorial: ContextTutorialStateSlice = ContextTutorialStateSlice(),
|
||||
/** 原 suppliesTutorial(? / Uw.uth)。未迁移:原样透传。 */
|
||||
val SuppliesTutorial: Any? = null,
|
||||
/** 原 suppliesTutorial(ust / Uw.uth)。已迁移。 */
|
||||
val SuppliesTutorial: SuppliesTutorialStateSlice = SuppliesTutorialStateSlice(),
|
||||
/** 原 questCategories(zZ / th.lsh)。已迁移。 */
|
||||
val QuestCategories: QuestCategoriesStateSlice = QuestCategoriesStateSlice(),
|
||||
/** 原 proBattle(Wtt / uv.wth)。已迁移。 */
|
||||
|
||||
@@ -53,11 +53,11 @@ object RootWiring {
|
||||
SliceWiring("suppliesState", "ipw_1", "wE", "\$t.fq9", "\$t.fq9(t, n.ipw_1)", listOf("SetSupplyCount")),
|
||||
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("battlePauseState", "lpw_1", "dT", "NT().mqc", "NT().mqc(t, n.lpw_1)", listOf("CancelAutoPause", "OnPauseMode", "ResetBattlePause", "SetIdleKickPeriod")),
|
||||
SliceWiring("battleViewState", "mpw_1", "DT", "sI.jqd", "(null == \$n && new sI(), \$n).jqd(t, n.mpw_1)", listOf("ClearInvisibleElements", "DisableBattleInput", "DisableBattleMenu", "DisableBattleStatistics", "EnableBattleInput", "EnableBattleMenu", "EnableBattleStatistics", "EnterBackground", "HideBattleView", "LeaveBackground", "ResetBattleView", "SetElementsVisibility", "SetVisibility", "ShowBattleView")),
|
||||
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("tankActionsLogState", "ppw_1", "vI", "wi.gqe", "wi.gqe(t, n.ppw_1)", listOf("OnUserJoinTheBattle", "OnUserLeaveTheBattle", "ResetTankActionsLog", "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("HideDroppableGoldAuthor", "ShowDroppableGoldAuthor")),
|
||||
@@ -93,7 +93,7 @@ object RootWiring {
|
||||
SliceWiring("icons", "wpx_1", "oH", "vs.kru", "vs.kru(t, n.wpx_1)", listOf("SetIcons")),
|
||||
SliceWiring("itemNotifications", "xpx_1", "_1", "A1().dso", "A1().dso(t, n.xpx_1)", listOf("?S1", "?_C", "AddItemNotification", "AddItemNotifications", "RemoveItemNotification", "UpdateItemNotification")),
|
||||
SliceWiring("contextTutorial", "ypx_1", "Mst", "Jst().tth", "Jst().tth(t, n.ypx_1)", listOf("LoadCurrentElement", "MarkElementAsViewed", "SetLoadedElements", "SetMissionToElement", "SetUnViewedElements")),
|
||||
SliceWiring("suppliesTutorial", "zpx_1", "?", "Uw.uth", "Uw.uth(t, n.zpx_1)", listOf("ActivatedInCurrentBattle", "SetLoadedElement")),
|
||||
SliceWiring("suppliesTutorial", "zpx_1", "ust", "Uw.uth", "Uw.uth(t, n.zpx_1)", listOf("ActivatedInCurrentBattle", "SetLoadedElement")),
|
||||
SliceWiring("questCategories", "apy_1", "zZ", "th.lsh", "th.lsh(t, n.apy_1)", listOf("RemoveQuestCategory", "RequestQuestCategoriesStatistic", "SetQuestCategories", "SetQuestCategoriesStatistic")),
|
||||
SliceWiring("proBattle", "bpy_1", "Wtt", "uv.wth", "uv.wth(t, n.bpy_1)", listOf("Fight", "SetPassword")),
|
||||
SliceWiring("availabilityByRank", "cpy_1", "tet", "\$p.xth", "\$p.xth(t, n.cpy_1)", listOf("SetLoadedData")),
|
||||
@@ -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", "tipsState", "rankUpDialogState", "battleResult", "captchaState", "modalScreen", "droppableGold", "eventGoods", "creatorTagState", "rewardedVideosState", "passwordChangeState", "system", "contextTutorial", "battleTutorial", "spectator", "twoStepVerificationState", "antiAddiction", "moderation", "migrationState", "register", "userReportsState", "friends", "suppliesState", "clanUserInfo", "battleInviteState", "partner", "userRenameState")
|
||||
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", "system", "contextTutorial", "battleTutorial", "spectator", "twoStepVerificationState", "antiAddiction", "moderation", "migrationState", "register", "userReportsState", "friends", "suppliesState", "clanUserInfo", "battleInviteState", "partner", "userRenameState", "battlePauseState", "battleViewState", "tankActionsLogState", "suppliesTutorial")
|
||||
|
||||
/** 未迁移字段:归约时原样透传,作为后续迁移清单。 */
|
||||
val Unmigrated: List<SliceWiring> get() = All.filter { it.Field !in Migrated }
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
// CreatorTagState / RewardedVideosState / PasswordChangeState /
|
||||
// System / ContextTutorial / BattleTutorial / Spectator / TwoStepVerification / AntiAddiction /
|
||||
// Moderation / MigrationState / Register / UserReports /
|
||||
// Friends / Supplies / ClanUserInfo / BattleInvite / Partner / UserRename;
|
||||
// Friends / Supplies / ClanUserInfo / BattleInvite / Partner / UserRename /
|
||||
// BattlePause / BattleView / TankActionsLog / SuppliesTutorial;
|
||||
// ㉑ launchParams 是纯透传切片(无 reducer/动作),只做 Map 类型收口;⑭ 根 reducer 的 89 槽位委派
|
||||
//
|
||||
// 用法:$env:TANKIOFFLINE_STATE_TEST='1'; node …(见 TankiOffline/tools/RunStateTest.ps1)
|
||||
@@ -592,6 +593,38 @@ import App.State.Reducers.ReduceUserRename
|
||||
import App.State.Reducers.ResetRenameDialog
|
||||
import App.State.Reducers.RenameUidState
|
||||
import App.State.Reducers.UserRenameStateSlice
|
||||
import App.State.OnPauseMode
|
||||
import App.State.SetIdleKickPeriod
|
||||
import App.State.Reducers.BattlePauseStateSlice
|
||||
import App.State.Reducers.CancelAutoPause
|
||||
import App.State.Reducers.ReduceBattlePause
|
||||
import App.State.Reducers.ResetBattlePause
|
||||
import App.State.SetElementsVisibility
|
||||
import App.State.SetVisibility
|
||||
import App.State.Reducers.BattleViewStateSlice
|
||||
import App.State.Reducers.ClearInvisibleElements
|
||||
import App.State.Reducers.DisableBattleInput
|
||||
import App.State.Reducers.DisableBattleMenu
|
||||
import App.State.Reducers.DisableBattleStatistics
|
||||
import App.State.Reducers.EnableBattleInput
|
||||
import App.State.Reducers.EnableBattleMenu
|
||||
import App.State.Reducers.EnableBattleStatistics
|
||||
import App.State.Reducers.EnterBackground
|
||||
import App.State.Reducers.HideBattleView
|
||||
import App.State.Reducers.LeaveBackground
|
||||
import App.State.Reducers.ReduceBattleView
|
||||
import App.State.Reducers.ResetBattleView
|
||||
import App.State.Reducers.ShowBattleView
|
||||
import App.State.OnUserJoinTheBattle
|
||||
import App.State.OnUserLeaveTheBattle
|
||||
import App.State.UpdateLog
|
||||
import App.State.Reducers.ReduceTankActionsLog
|
||||
import App.State.Reducers.ResetTankActionsLog
|
||||
import App.State.Reducers.TankActionsLogStateSlice
|
||||
import App.State.ActivatedInCurrentBattle
|
||||
import App.State.SetLoadedElement
|
||||
import App.State.Reducers.ReduceSuppliesTutorial
|
||||
import App.State.Reducers.SuppliesTutorialStateSlice
|
||||
import App.State.Reducers.UserRankBounds
|
||||
import App.State.Reducers.UserStateSlice
|
||||
import App.State.Reducers.ClearHullData
|
||||
@@ -1019,7 +1052,7 @@ object StateCheck {
|
||||
Check("切片 LocalBattleUser:接 Store 派发后状态已归约", Store.State.IsReArmorTemporaryDisabled)
|
||||
}
|
||||
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 59 个已迁移切片(58 归约 + launchParams 透传)
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 63 个已迁移切片(62 归约 + launchParams 透传)
|
||||
run {
|
||||
Check("根:根状态 89 个切片槽位", RootWiring.All.size == 89)
|
||||
Check(
|
||||
@@ -1083,7 +1116,7 @@ object StateCheck {
|
||||
LocalBattleW.Reducer == "(inline@localBattleUserState)"
|
||||
)
|
||||
Check(
|
||||
"根:迁移表 = 59 个已迁移字段,其余 30 个待迁",
|
||||
"根:迁移表 = 63 个已迁移字段,其余 26 个待迁",
|
||||
RootReducer.Migrated ==
|
||||
setOf(
|
||||
"inviteState", "loginByPassword", "twitchState", "home",
|
||||
@@ -1102,8 +1135,9 @@ object StateCheck {
|
||||
"migrationState", "register", "userReportsState",
|
||||
"friends", "suppliesState", "clanUserInfo", "battleInviteState",
|
||||
"partner", "userRenameState",
|
||||
"battlePauseState", "battleViewState", "tankActionsLogState", "suppliesTutorial",
|
||||
) &&
|
||||
RootWiring.Unmigrated.size == 30
|
||||
RootWiring.Unmigrated.size == 26
|
||||
)
|
||||
|
||||
// 一次 ReduceRoot 里多个切片各归约自己的动作,互不串片
|
||||
@@ -1159,7 +1193,7 @@ object StateCheck {
|
||||
S5.User.Uid == "user-1" && S5.Screen.Current == NamedScreen("Preloader")
|
||||
)
|
||||
Check("根:无关动作返回等值状态", ReduceRoot(S5, AddFrags(1)) == S5)
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 59/89")
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 63/89")
|
||||
|
||||
val Store = ReduxStore(RootState(), { S, A -> ReduceRoot(S, A) })
|
||||
Store.Dispatch(SetStatus("LOGGING_IN"))
|
||||
@@ -5233,6 +5267,215 @@ object StateCheck {
|
||||
)
|
||||
}
|
||||
|
||||
// 70 切片 reducer:BattlePause(dT / NT().mqc,3 字段;4 个动作)
|
||||
run {
|
||||
val S0 = BattlePauseStateSlice()
|
||||
Check(
|
||||
"切片 BattlePause:默认不暂停、无剩余时间",
|
||||
!S0.InAutoPauseMode && S0.TimeForAutoLeave == null && S0.IdleKickPeriodInMsec == 0
|
||||
)
|
||||
val S1 = ReduceBattlePause(S0, OnPauseMode("30s"))
|
||||
Check(
|
||||
"切片 BattlePause:OnPauseMode 置暂停并写剩余时间",
|
||||
S1.InAutoPauseMode && S1.TimeForAutoLeave == "30s"
|
||||
)
|
||||
Check(
|
||||
"切片 BattlePause:CancelAutoPause 只清暂停位",
|
||||
ReduceBattlePause(S1, CancelAutoPause).let {
|
||||
!it.InAutoPauseMode && it.TimeForAutoLeave == "30s"
|
||||
}
|
||||
)
|
||||
Check(
|
||||
"切片 BattlePause:SetIdleKickPeriod 写周期",
|
||||
ReduceBattlePause(S1, SetIdleKickPeriod(120)).IdleKickPeriodInMsec == 120
|
||||
)
|
||||
Check(
|
||||
"切片 BattlePause:ResetBattlePause 保留挂机周期",
|
||||
ReduceBattlePause(
|
||||
ReduceBattlePause(S1, SetIdleKickPeriod(120)),
|
||||
ResetBattlePause,
|
||||
).let { !it.InAutoPauseMode && it.IdleKickPeriodInMsec == 120 }
|
||||
)
|
||||
Check(
|
||||
"切片 BattlePause:无关动作不改状态",
|
||||
ReduceBattlePause(S1, AddFrags(1)) == S1
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, CancelAutoPause)
|
||||
Check(
|
||||
"根:CancelAutoPause 只动 battlePauseState",
|
||||
!Root1.BattlePauseState.InAutoPauseMode &&
|
||||
Root1.BattleViewState == Root0.BattleViewState
|
||||
)
|
||||
val W = RootWiring.ByField("battlePauseState")!!
|
||||
Check(
|
||||
"根:battlePauseState 委派到 dT / NT().mqc 且 4 个动作",
|
||||
W.SliceClass == "dT" && W.Reducer == "NT().mqc" &&
|
||||
W.Actions.toSet() == setOf(
|
||||
"ResetBattlePause", "OnPauseMode", "CancelAutoPause", "SetIdleKickPeriod",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// 71 切片 reducer:BattleView(DT / sI.jqd,7 字段;14 个动作)
|
||||
run {
|
||||
val S0 = BattleViewStateSlice()
|
||||
Check(
|
||||
"切片 BattleView:默认在后台、隐藏、输入开",
|
||||
S0.InBackgroundState && S0.IsHidden && S0.InvisibleElements.isEmpty() &&
|
||||
S0.InputEnabled && !S0.BattleStatisticsActive && !S0.BattleMenuActive &&
|
||||
S0.JoystickPosition == null
|
||||
)
|
||||
val S1 = ReduceBattleView(S0, SetVisibility(true, "e1"))
|
||||
Check(
|
||||
"切片 BattleView:SetVisibility(true) 从隐藏集合删元素",
|
||||
S1.InvisibleElements.isEmpty()
|
||||
)
|
||||
val S2 = ReduceBattleView(S1, SetVisibility(false, "e1"))
|
||||
Check(
|
||||
"切片 BattleView:SetVisibility(false) 加入隐藏集合",
|
||||
S2.InvisibleElements == setOf<Any?>("e1")
|
||||
)
|
||||
val S3 = ReduceBattleView(
|
||||
S2,
|
||||
SetElementsVisibility(true, listOf("e1", "e2")),
|
||||
)
|
||||
Check(
|
||||
"切片 BattleView:SetElementsVisibility 按集合增删",
|
||||
S3.InvisibleElements.isEmpty() &&
|
||||
ReduceBattleView(S3, SetElementsVisibility(false, listOf("x", "y")))
|
||||
.InvisibleElements == setOf<Any?>("x", "y")
|
||||
)
|
||||
Check(
|
||||
"切片 BattleView:ClearInvisibleElements 清空",
|
||||
ReduceBattleView(S2, ClearInvisibleElements).InvisibleElements.isEmpty()
|
||||
)
|
||||
Check(
|
||||
"切片 BattleView:输入开关两态",
|
||||
ReduceBattleView(S2, DisableBattleInput).let { !it.InputEnabled } &&
|
||||
ReduceBattleView(S2, EnableBattleInput).InputEnabled
|
||||
)
|
||||
Check(
|
||||
"切片 BattleView:统计与菜单开关两态",
|
||||
ReduceBattleView(S2, EnableBattleStatistics).BattleStatisticsActive &&
|
||||
!ReduceBattleView(S2, DisableBattleStatistics).BattleStatisticsActive &&
|
||||
ReduceBattleView(S2, EnableBattleMenu).BattleMenuActive &&
|
||||
!ReduceBattleView(S2, DisableBattleMenu).BattleMenuActive
|
||||
)
|
||||
Check(
|
||||
"切片 BattleView:显示 / 后台开关两态",
|
||||
!ReduceBattleView(S2, ShowBattleView).IsHidden &&
|
||||
ReduceBattleView(S2, HideBattleView).IsHidden &&
|
||||
!ReduceBattleView(S2, LeaveBackground).InBackgroundState &&
|
||||
ReduceBattleView(S2, EnterBackground).InBackgroundState
|
||||
)
|
||||
Check(
|
||||
"切片 BattleView:ResetBattleView 整片复位",
|
||||
ReduceBattleView(S2, ResetBattleView) == BattleViewStateSlice()
|
||||
)
|
||||
Check(
|
||||
"切片 BattleView:无关动作不改状态",
|
||||
ReduceBattleView(S2, AddFrags(1)) == S2
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, DisableBattleInput)
|
||||
Check(
|
||||
"根:DisableBattleInput 只动 battleViewState",
|
||||
!Root1.BattleViewState.InputEnabled &&
|
||||
Root1.BattlePauseState == Root0.BattlePauseState
|
||||
)
|
||||
val W = RootWiring.ByField("battleViewState")!!
|
||||
Check(
|
||||
"根:battleViewState 委派到 DT / sI.jqd 且 14 个动作",
|
||||
W.SliceClass == "DT" && W.Reducer == "sI.jqd" && W.Actions.size == 14
|
||||
)
|
||||
}
|
||||
|
||||
// 72 切片 reducer:TankActionsLog(vI / wi.gqe,2 字段;4 个动作)
|
||||
run {
|
||||
val S0 = TankActionsLogStateSlice()
|
||||
Check(
|
||||
"切片 TankActionsLog:默认两个集合为空",
|
||||
S0.Logs.isEmpty() && S0.Noticed.isEmpty()
|
||||
)
|
||||
val S1 = ReduceTankActionsLog(S0, OnUserJoinTheBattle(1L))
|
||||
Check(
|
||||
"切片 TankActionsLog:OnUserJoinTheBattle 记入 noticed",
|
||||
S1.Noticed == setOf<Any?>(1L)
|
||||
)
|
||||
Check(
|
||||
"切片 TankActionsLog:OnUserLeaveTheBattle 移除 noticed",
|
||||
ReduceTankActionsLog(S1, OnUserLeaveTheBattle(1L)).Noticed.isEmpty()
|
||||
)
|
||||
var S2 = S1
|
||||
for (I in 1..12) S2 = ReduceTankActionsLog(S2, UpdateLog("log$I"))
|
||||
Check(
|
||||
"切片 TankActionsLog:超过 10 条从头截断",
|
||||
S2.Logs.size == 10 && S2.Logs.first() == "log3" && S2.Logs.last() == "log12"
|
||||
)
|
||||
Check(
|
||||
"切片 TankActionsLog:ResetTankActionsLog 整片复位",
|
||||
ReduceTankActionsLog(S2, ResetTankActionsLog) == TankActionsLogStateSlice()
|
||||
)
|
||||
Check(
|
||||
"切片 TankActionsLog:无关动作不改状态",
|
||||
ReduceTankActionsLog(S2, AddFrags(1)) == S2
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, UpdateLog("x"))
|
||||
Check(
|
||||
"根:UpdateLog 只动 tankActionsLogState",
|
||||
Root1.TankActionsLogState.Logs == listOf<Any?>("x") &&
|
||||
Root1.SuppliesTutorial == Root0.SuppliesTutorial
|
||||
)
|
||||
val W = RootWiring.ByField("tankActionsLogState")!!
|
||||
Check(
|
||||
"根:tankActionsLogState 委派到 vI / wi.gqe 且 4 个动作",
|
||||
W.SliceClass == "vI" && W.Reducer == "wi.gqe" &&
|
||||
W.Actions.toSet() == setOf(
|
||||
"ResetTankActionsLog", "OnUserJoinTheBattle", "OnUserLeaveTheBattle",
|
||||
"UpdateLog",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// 73 切片 reducer:SuppliesTutorial(ust / Uw.uth,2 字段;2 个动作)
|
||||
run {
|
||||
val S0 = SuppliesTutorialStateSlice()
|
||||
Check(
|
||||
"切片 SuppliesTutorial:默认未加载、未激活",
|
||||
S0.LoadedElement == null && !S0.ActivatedInCurrentBattle
|
||||
)
|
||||
val S1 = ReduceSuppliesTutorial(S0, SetLoadedElement("hull"))
|
||||
Check("切片 SuppliesTutorial:SetLoadedElement 写元素", S1.LoadedElement == "hull")
|
||||
Check(
|
||||
"切片 SuppliesTutorial:ActivatedInCurrentBattle 写激活位",
|
||||
ReduceSuppliesTutorial(S1, ActivatedInCurrentBattle(true))
|
||||
.ActivatedInCurrentBattle
|
||||
)
|
||||
Check(
|
||||
"切片 SuppliesTutorial:无关动作不改状态",
|
||||
ReduceSuppliesTutorial(S1, AddFrags(1)) == S1
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, SetLoadedElement("x"))
|
||||
Check(
|
||||
"根:SetLoadedElement 只动 suppliesTutorial",
|
||||
Root1.SuppliesTutorial.LoadedElement == "x" &&
|
||||
Root1.TankActionsLogState == Root0.TankActionsLogState
|
||||
)
|
||||
val W = RootWiring.ByField("suppliesTutorial")!!
|
||||
Check(
|
||||
"根:suppliesTutorial 委派到 ust / Uw.uth",
|
||||
W.SliceClass == "ust" && W.Reducer == "Uw.uth" &&
|
||||
W.Actions.toSet() == setOf("ActivatedInCurrentBattle", "SetLoadedElement")
|
||||
)
|
||||
}
|
||||
|
||||
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