feat(state): 迁移 tankBuilderState
This commit is contained in:
1 parent
6a1c8b4306
commit
0cd2a23c9e
8 files changed
+205
-21
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` 动作名。
|
||||
- 已迁移切片 **74/89**:
|
||||
- 已迁移切片 **75/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)
|
||||
@@ -375,12 +375,16 @@
|
||||
`UpdateProgress` / `GetReward` 复制单条合同再放回;`Fnt`(原名 `GetReward`,与任务切片同名)改名
|
||||
`ClaimContractReward`,`Hnt`→`RemoveCompletedContracts` 只留还有奖励的合同;
|
||||
`InitBattle` 只把 `lastBattleProgress` 归零。
|
||||
- `tankBuilderState` → `brt` / `wp.ati`(`TankBuilderStateReducer.kt`):6 字段,4 个分支。
|
||||
`SetParts` 把零件表拆成 `hulls`(hullId 列表)与 `weapons`(index → weaponIds)、并写 `paints`;
|
||||
`SetPartsInfo` 按零件 / 涂装各自的 id 建索引;零件模型跨模块,收口为
|
||||
`TankBuilderPart` / `TankBuilderPartInfo` / `TankBuilderPaintInfo`;`Trt`→`ResetTankBuilder` 整片复位。
|
||||
- `launchParams` → `(pass-through)`:原根 reducer 对 `hpx_1` 没有调用,缺省是 `ag()` 空 Map;
|
||||
`RootState.LaunchParams` 收口为 `LaunchParamsStateSlice = Map<String, String>`,不新增 reducer/动作。
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 73 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **15 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 74/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **815 项全绿**,含 89 槽位完整性、73 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 74 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **14 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 75/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **823 项全绿**,含 89 槽位完整性、74 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
以及用 `action_trace_merged.json` 真实派发的两条商店动作(`SetCoinPaymentProviderUrl` / `ToggleShopActivity`)回放。
|
||||
- 委派表里的已知形态:`shop` / `home` / `localBattleUserState` / `partner` 是内联 IIFE,
|
||||
已按字段具名为 `(inline@<field>)` 并从函数体抓到顶层动作名(69 / 1 / 2 / 11 个);
|
||||
@@ -405,7 +409,8 @@
|
||||
设置类切片的 `_C`(共用重载)+ `Bet`/`Fet`/`Uet`/`v2`/`C7`/`E7`/`Iut` 也已登记,
|
||||
其中原名都是 `UpdateSettings` 的类按切片改名为 `Apply*`,避免生成物同名冲突
|
||||
(`Bet`/`v2`/`B2`/`u2`/`K0`/`C7` 共 6 个)。
|
||||
contractState 的 `Fnt`/`Hnt` 也已登记(`Fnt` 因与任务切片同名改名为 `ClaimContractReward`)。
|
||||
contractState 的 `Fnt`/`Hnt` 也已登记(`Fnt` 因与任务切片同名改名为 `ClaimContractReward`);
|
||||
tankBuilderState 的 `Trt`(`ResetTankBuilder`)同样按效果定名。
|
||||
|
||||
### S4 引擎核心
|
||||
- 模块:32088(3D 数学)、92980(渲染)、61378(ECS)、55088(物理)、36659 + 71105(资源)、36734(音频)、3569(输入)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generatedAt": "2026-10-24T09:26:08.293Z",
|
||||
"generatedAt": "2026-10-24T09:32:15.650Z",
|
||||
"module": "module_10032.js",
|
||||
"RootState": {
|
||||
"Class": "z6",
|
||||
@@ -80,7 +80,8 @@
|
||||
"graphicsSettings",
|
||||
"controlSettings",
|
||||
"battleSettings",
|
||||
"contractState"
|
||||
"contractState",
|
||||
"tankBuilderState"
|
||||
],
|
||||
"AnonymousActions": [
|
||||
{
|
||||
@@ -1367,6 +1368,12 @@
|
||||
"Name": "RemoveCompletedContracts",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "只保留 rewards 非空的合同"
|
||||
},
|
||||
{
|
||||
"Local": "Trt",
|
||||
"Name": "ResetTankBuilder",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "new brt() 整片复位"
|
||||
}
|
||||
],
|
||||
"Markers": [
|
||||
@@ -3052,13 +3059,13 @@
|
||||
"Reducer": "wp.ati",
|
||||
"Delegate": "wp.ati(t, n.epy_1)",
|
||||
"Actions": [
|
||||
"?Trt",
|
||||
"ResetTankBuilder",
|
||||
"SetKode",
|
||||
"SetParts",
|
||||
"SetPartsInfo"
|
||||
],
|
||||
"Default": "new brt()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "contractState",
|
||||
|
||||
@@ -314,6 +314,8 @@ const AnonymousActionNames = new Map([
|
||||
// contractState 切片(Ont / Wnt.bti):Fnt 的 GetReward 与任务切片同名,Hnt 没有 toString。
|
||||
['Fnt', 'ClaimContractReward'],
|
||||
['Hnt', 'RemoveCompletedContracts'],
|
||||
// tankBuilderState 切片(brt / Irt.ati):Trt 没有 toString。
|
||||
['Trt', 'ResetTankBuilder'],
|
||||
]);
|
||||
|
||||
// 非动作的 `instanceof`:屏幕标识类,用于 GoTo 分支判断(不是 dispatch 的动作)。
|
||||
@@ -789,6 +791,7 @@ const Migrated = {
|
||||
controlSettings: { Type: 'ControlSettingsStateSlice', Reduce: 'ReduceControlSettings' },
|
||||
battleSettings: { Type: 'BattleSettingsStateSlice', Reduce: 'ReduceBattleSettings' },
|
||||
contractState: { Type: 'ContractStateSlice', Reduce: 'ReduceContractState' },
|
||||
tankBuilderState: { Type: 'TankBuilderStateSlice', Reduce: 'ReduceTankBuilder' },
|
||||
};
|
||||
|
||||
for (const R of Rows) R.Migrated = Object.prototype.hasOwnProperty.call(Migrated, R.Field);
|
||||
@@ -1194,6 +1197,7 @@ const AppSettingsAnonymousEffects = {
|
||||
K0: '战斗显示设置整体替换(原名 UpdateSettings)',
|
||||
Fnt: '复制该合同并把 rewards 清空(原名 GetReward,与任务切片同名)',
|
||||
Hnt: '只保留 rewards 非空的合同',
|
||||
Trt: 'new brt() 整片复位',
|
||||
};
|
||||
|
||||
fs.writeFileSync(
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
// TankBuilderStateReducer.kt —— 坦克构建器切片(对应 module_10032 的 brt 状态 + Irt.ati)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 brt:6 个字段,toString 名 "TankBuilderState(…)";copy 是 ktt(6 字段 + 回调)。
|
||||
// 默认:hulls=emptyList()、weapons=emptyMap()、paints=emptyList()、
|
||||
// paintInfo=emptyMap()、partInfo=emptyMap()、kode=emptyList()。
|
||||
// 根委派:`wp.ati(t, n.epy_1)`。
|
||||
// reducer(4 个实例臂):
|
||||
// yrt(SetKode) → kode
|
||||
// $rt(SetParts) → hulls = parts.map { hullId };weapons = parts 按 index 建表;paints
|
||||
// xrt(SetPartsInfo) → paintInfo / partInfo 分别按各自的 id 建索引
|
||||
// Trt(无 toString) → `new brt()` 整片复位
|
||||
//
|
||||
// 零件 / 涂装模型在另一个模块(零件字段 `vek_1`=hullId、`xek()`=weapons;info 的键分别是 `iek_1` / `cek_1`),
|
||||
// 这里收口成 `TankBuilderPart` / `TankBuilderPartInfo` / `TankBuilderPaintInfo`。
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.SetKode
|
||||
import App.State.SetParts
|
||||
import App.State.SetPartsInfo
|
||||
|
||||
/* ------------------------------------------------------------------ 模型 */
|
||||
|
||||
data class TankBuilderPart(
|
||||
val hullId: Any?,
|
||||
val weaponIds: Any?,
|
||||
)
|
||||
|
||||
data class TankBuilderPartInfo(
|
||||
val partId: Any?,
|
||||
val info: Any? = null,
|
||||
)
|
||||
|
||||
data class TankBuilderPaintInfo(
|
||||
val paintId: Any?,
|
||||
val info: Any? = null,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `Trt`:整片复位(`new brt()`)。 */
|
||||
object ResetTankBuilder
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class TankBuilderStateSlice(
|
||||
val Hulls: List<Any?> = emptyList(),
|
||||
val Weapons: Map<Any?, Any?> = emptyMap(),
|
||||
val Paints: List<Any?> = emptyList(),
|
||||
val PaintInfo: Map<Any?, Any?> = emptyMap(),
|
||||
val PartInfo: Map<Any?, Any?> = emptyMap(),
|
||||
val Kode: List<Any?> = emptyList(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
private fun PartsOf(Value: Any?): List<TankBuilderPart> =
|
||||
(Value as? Iterable<*>)
|
||||
?.mapNotNull { it as? TankBuilderPart }
|
||||
?: emptyList()
|
||||
|
||||
fun ReduceTankBuilder(
|
||||
State0: TankBuilderStateSlice,
|
||||
Action: Any,
|
||||
): TankBuilderStateSlice = when (Action) {
|
||||
is SetKode -> State0.copy(Kode = Action.kode as? List<Any?> ?: emptyList())
|
||||
is SetParts -> {
|
||||
val Parts = PartsOf(Action.parts)
|
||||
State0.copy(
|
||||
Hulls = Parts.map { it.hullId },
|
||||
Weapons = Parts.mapIndexed { Index, Part -> Index to Part.weaponIds }.toMap(),
|
||||
Paints = (Action.paints as? List<Any?>) ?: emptyList(),
|
||||
)
|
||||
}
|
||||
is SetPartsInfo -> {
|
||||
val PartInfos = (Action.partsInfo as? Iterable<*>)
|
||||
?.mapNotNull { it as? TankBuilderPartInfo } ?: emptyList()
|
||||
val PaintInfos = (Action.paintsInfo as? Iterable<*>)
|
||||
?.mapNotNull { it as? TankBuilderPaintInfo } ?: emptyList()
|
||||
State0.copy(
|
||||
PartInfo = PartInfos.associate { it.partId to it.info },
|
||||
PaintInfo = PaintInfos.associate { it.paintId to it.info },
|
||||
)
|
||||
}
|
||||
is ResetTankBuilder -> TankBuilderStateSlice()
|
||||
else -> State0
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// RootReducer.kt —— 根 reducer 骨架(对应 module_10032 的根状态 z6 / TOState 与根 reducer k6)
|
||||
//
|
||||
// 原包 k6 对 89 个切片逐个调用各自的 reducer,再 `return n.cti(...)`(copy 出新状态)。
|
||||
// 这里采用同一形状。已迁移的 74 个切片里,73 个真正调用 reducer,launchParams 只做类型收口:
|
||||
// 这里采用同一形状。已迁移的 75 个切片里,74 个真正调用 reducer,launchParams 只做类型收口:
|
||||
//
|
||||
// inviteState → ReduceInvite(aD / pD.er5)
|
||||
// loginByPassword → ReduceLoginByPassword(gD / MD.cr6)
|
||||
@@ -76,9 +76,10 @@
|
||||
// controlSettings → ReduceControlSettings(i2 / _2().ess,根委派 `_2().ess(t, n.zpw_1)`)
|
||||
// battleSettings → ReduceBattleSettings(W0 / X0().esq,根委派 `X0().esq(t, n.xpw_1)`)
|
||||
// contractState → ReduceContractState(Ont / xv.bti,根委派 `xv.bti(t, n.fpy_1)`)
|
||||
// tankBuilderState → ReduceTankBuilder(brt / wp.ati,根委派 `wp.ati(t, n.epy_1)`)
|
||||
// launchParams → 无 reducer(原根 reducer 原样透传;默认 `ag()` = emptyMap())
|
||||
//
|
||||
// 其余 15 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 其余 14 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 所以一次 copy 里串起全部已迁移 reducer,与按动作路由再归约的结果一致。
|
||||
// 迁移进度与每个字段的证据见生成物 RootWiring.kt(不要手改)。
|
||||
package App.State
|
||||
@@ -149,6 +150,7 @@ import App.State.Reducers.ReduceSupplies
|
||||
import App.State.Reducers.ReduceSuppliesTutorial
|
||||
import App.State.Reducers.ReduceSystem
|
||||
import App.State.Reducers.ReduceTankActionsLog
|
||||
import App.State.Reducers.ReduceTankBuilder
|
||||
import App.State.Reducers.ReduceTips
|
||||
import App.State.Reducers.ReduceTouchscreenHudSettings
|
||||
import App.State.Reducers.ReduceTwitch
|
||||
@@ -243,6 +245,7 @@ object RootReducer {
|
||||
ControlSettings = ReduceControlSettings(State0.ControlSettings, Action),
|
||||
BattleSettings = ReduceBattleSettings(State0.BattleSettings, Action),
|
||||
ContractState = ReduceContractState(State0.ContractState, Action),
|
||||
TankBuilderState = ReduceTankBuilder(State0.TankBuilderState, Action),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ import App.State.Reducers.SuppliesTutorialStateSlice
|
||||
import App.State.Reducers.SupportUrlStateSlice
|
||||
import App.State.Reducers.SystemStateSlice
|
||||
import App.State.Reducers.TankActionsLogStateSlice
|
||||
import App.State.Reducers.TankBuilderStateSlice
|
||||
import App.State.Reducers.TipsStateSlice
|
||||
import App.State.Reducers.TouchscreenHudSettingsStateSlice
|
||||
import App.State.Reducers.TwitchStateSlice
|
||||
@@ -250,8 +251,8 @@ data class RootState(
|
||||
val AvailabilityByRank: AvailabilityByRankStateSlice = AvailabilityByRankStateSlice(),
|
||||
/** 原 userReportsState(Zst / qot.zth)。已迁移。 */
|
||||
val UserReportsState: UserReportsStateSlice = UserReportsStateSlice(),
|
||||
/** 原 tankBuilderState(brt / wp.ati)。未迁移:原样透传。 */
|
||||
val TankBuilderState: Any? = null,
|
||||
/** 原 tankBuilderState(brt / wp.ati)。已迁移。 */
|
||||
val TankBuilderState: TankBuilderStateSlice = TankBuilderStateSlice(),
|
||||
/** 原 contractState(Ont / xv.bti)。已迁移。 */
|
||||
val ContractState: ContractStateSlice = ContractStateSlice(),
|
||||
/** 原 promoCode(cZ / Q_.ysg)。已迁移。 */
|
||||
|
||||
@@ -98,7 +98,7 @@ object RootWiring {
|
||||
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")),
|
||||
SliceWiring("userReportsState", "dpy_1", "Zst", "qot.zth", "(null == sd && new qot(), sd).zth(t, n.dpy_1)", listOf("InitUserReports", "ReportBattleChatMessage", "ReportLobbyChatMessage", "ReportProBattleName", "SetAvailableGameReports", "SetAvailableReports")),
|
||||
SliceWiring("tankBuilderState", "epy_1", "brt", "wp.ati", "wp.ati(t, n.epy_1)", listOf("?Trt", "SetKode", "SetParts", "SetPartsInfo")),
|
||||
SliceWiring("tankBuilderState", "epy_1", "brt", "wp.ati", "wp.ati(t, n.epy_1)", listOf("ResetTankBuilder", "SetKode", "SetParts", "SetPartsInfo")),
|
||||
SliceWiring("contractState", "fpy_1", "Ont", "xv.bti", "xv.bti(t, n.fpy_1)", listOf("ClaimContractReward", "InitBattle", "RemoveCompletedContracts", "SetActiveContract", "SetBattleProgress", "SetContract", "UpdateProgress")),
|
||||
SliceWiring("promoCode", "gpy_1", "cZ", "Q_.ysg", "Q_.ysg(t, n.gpy_1)", listOf("ActivatePromoCode", "SetCodeValidateStatus")),
|
||||
SliceWiring("referralEvent", "hpy_1", "pQ", "lh.osk", "lh.osk(t, n.hpy_1)", listOf("SetPromoCode", "SetReferralEventData", "SetReferrals", "SetReferrer")),
|
||||
@@ -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", "battlePauseState", "battleViewState", "tankActionsLogState", "suppliesTutorial", "clanChatState", "battleSearchState", "battleStatistics", "soundSettings", "gameSettings", "keyboardSettings", "touchscreenHudSettings", "graphicsSettings", "controlSettings", "battleSettings", "contractState")
|
||||
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", "clanChatState", "battleSearchState", "battleStatistics", "soundSettings", "gameSettings", "keyboardSettings", "touchscreenHudSettings", "graphicsSettings", "controlSettings", "battleSettings", "contractState", "tankBuilderState")
|
||||
|
||||
/** 未迁移字段:归约时原样透传,作为后续迁移清单。 */
|
||||
val Unmigrated: List<SliceWiring> get() = All.filter { it.Field !in Migrated }
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
// System / ContextTutorial / BattleTutorial / Spectator / TwoStepVerification / AntiAddiction /
|
||||
// Moderation / MigrationState / Register / UserReports /
|
||||
// Friends / Supplies / ClanUserInfo / BattleInvite / Partner / UserRename /
|
||||
// BattlePause / BattleView / TankActionsLog / SuppliesTutorial / ClanChat / BattleSearch / BattleStatistics / SoundSettings / GameSettings / KeyboardSettings / TouchscreenHudSettings / GraphicsSettings / ControlSettings / BattleSettings / ContractState;
|
||||
// BattlePause / BattleView / TankActionsLog / SuppliesTutorial / ClanChat / BattleSearch / BattleStatistics / SoundSettings / GameSettings / KeyboardSettings / TouchscreenHudSettings / GraphicsSettings / ControlSettings / BattleSettings / ContractState / TankBuilder;
|
||||
// ㉑ launchParams 是纯透传切片(无 reducer/动作),只做 Map 类型收口;⑭ 根 reducer 的 89 槽位委派
|
||||
//
|
||||
// 用法:$env:TANKIOFFLINE_STATE_TEST='1'; node …(见 TankiOffline/tools/RunStateTest.ps1)
|
||||
@@ -707,6 +707,15 @@ import App.State.Reducers.ContractEntry
|
||||
import App.State.Reducers.ContractStateSlice
|
||||
import App.State.Reducers.ReduceContractState
|
||||
import App.State.Reducers.RemoveCompletedContracts
|
||||
import App.State.SetKode
|
||||
import App.State.SetParts
|
||||
import App.State.SetPartsInfo
|
||||
import App.State.Reducers.ReduceTankBuilder
|
||||
import App.State.Reducers.ResetTankBuilder
|
||||
import App.State.Reducers.TankBuilderPaintInfo
|
||||
import App.State.Reducers.TankBuilderPart
|
||||
import App.State.Reducers.TankBuilderPartInfo
|
||||
import App.State.Reducers.TankBuilderStateSlice
|
||||
import App.State.Reducers.UserRankBounds
|
||||
import App.State.Reducers.UserStateSlice
|
||||
import App.State.Reducers.ClearHullData
|
||||
@@ -1134,7 +1143,7 @@ object StateCheck {
|
||||
Check("切片 LocalBattleUser:接 Store 派发后状态已归约", Store.State.IsReArmorTemporaryDisabled)
|
||||
}
|
||||
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 74 个已迁移切片(73 归约 + launchParams 透传)
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 75 个已迁移切片(74 归约 + launchParams 透传)
|
||||
run {
|
||||
Check("根:根状态 89 个切片槽位", RootWiring.All.size == 89)
|
||||
Check(
|
||||
@@ -1198,7 +1207,7 @@ object StateCheck {
|
||||
LocalBattleW.Reducer == "(inline@localBattleUserState)"
|
||||
)
|
||||
Check(
|
||||
"根:迁移表 = 74 个已迁移字段,其余 15 个待迁",
|
||||
"根:迁移表 = 75 个已迁移字段,其余 14 个待迁",
|
||||
RootReducer.Migrated ==
|
||||
setOf(
|
||||
"inviteState", "loginByPassword", "twitchState", "home",
|
||||
@@ -1221,8 +1230,9 @@ object StateCheck {
|
||||
"clanChatState", "battleSearchState", "battleStatistics",
|
||||
"soundSettings", "gameSettings", "keyboardSettings", "touchscreenHudSettings",
|
||||
"graphicsSettings", "controlSettings", "battleSettings", "contractState",
|
||||
"tankBuilderState",
|
||||
) &&
|
||||
RootWiring.Unmigrated.size == 15
|
||||
RootWiring.Unmigrated.size == 14
|
||||
)
|
||||
|
||||
// 一次 ReduceRoot 里多个切片各归约自己的动作,互不串片
|
||||
@@ -1278,7 +1288,7 @@ object StateCheck {
|
||||
S5.User.Uid == "user-1" && S5.Screen.Current == NamedScreen("Preloader")
|
||||
)
|
||||
Check("根:无关动作返回等值状态", ReduceRoot(S5, AddFrags(1)) == S5)
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 74/89")
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 75/89")
|
||||
|
||||
val Store = ReduxStore(RootState(), { S, A -> ReduceRoot(S, A) })
|
||||
Store.Dispatch(SetStatus("LOGGING_IN"))
|
||||
@@ -6196,6 +6206,73 @@ object StateCheck {
|
||||
)
|
||||
}
|
||||
|
||||
// 85 切片 reducer:TankBuilder(brt / wp.ati,6 字段;4 个动作)
|
||||
run {
|
||||
val S0 = TankBuilderStateSlice()
|
||||
Check(
|
||||
"切片 TankBuilder:默认值完整",
|
||||
S0.Hulls.isEmpty() && S0.Weapons.isEmpty() && S0.Paints.isEmpty() &&
|
||||
S0.PaintInfo.isEmpty() && S0.PartInfo.isEmpty() && S0.Kode.isEmpty()
|
||||
)
|
||||
val S1 = ReduceTankBuilder(S0, SetKode(listOf("k1")))
|
||||
Check("切片 TankBuilder:SetKode 写 kode", S1.Kode == listOf<Any?>("k1"))
|
||||
val S2 = ReduceTankBuilder(
|
||||
S1,
|
||||
SetParts(
|
||||
parts = listOf(
|
||||
TankBuilderPart("hull1", listOf("w1")),
|
||||
TankBuilderPart("hull2", listOf("w2", "w3")),
|
||||
),
|
||||
paints = listOf("p1"),
|
||||
),
|
||||
)
|
||||
Check(
|
||||
"切片 TankBuilder:SetParts 拆出 hulls / weapons / paints",
|
||||
S2.Hulls == listOf<Any?>("hull1", "hull2") &&
|
||||
S2.Weapons == mapOf<Any?, Any?>(
|
||||
0 to listOf("w1"),
|
||||
1 to listOf("w2", "w3"),
|
||||
) &&
|
||||
S2.Paints == listOf<Any?>("p1")
|
||||
)
|
||||
val S3 = ReduceTankBuilder(
|
||||
S2,
|
||||
SetPartsInfo(
|
||||
partsInfo = listOf(TankBuilderPartInfo("part1", "info1")),
|
||||
paintsInfo = listOf(TankBuilderPaintInfo("paint1", "info2")),
|
||||
),
|
||||
)
|
||||
Check(
|
||||
"切片 TankBuilder:SetPartsInfo 按各自 id 建索引",
|
||||
S3.PartInfo == mapOf<Any?, Any?>("part1" to "info1") &&
|
||||
S3.PaintInfo == mapOf<Any?, Any?>("paint1" to "info2")
|
||||
)
|
||||
Check(
|
||||
"切片 TankBuilder:ResetTankBuilder 整片复位",
|
||||
ReduceTankBuilder(S3, ResetTankBuilder) == TankBuilderStateSlice()
|
||||
)
|
||||
Check(
|
||||
"切片 TankBuilder:无关动作不改状态",
|
||||
ReduceTankBuilder(S3, AddFrags(1)) == S3
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, SetKode(listOf("x")))
|
||||
Check(
|
||||
"根:SetKode 只动 tankBuilderState",
|
||||
Root1.TankBuilderState.Kode == listOf<Any?>("x") &&
|
||||
Root1.ContractState == Root0.ContractState
|
||||
)
|
||||
val W = RootWiring.ByField("tankBuilderState")!!
|
||||
Check(
|
||||
"根:tankBuilderState 委派到 brt / wp.ati 且 4 个动作",
|
||||
W.SliceClass == "brt" && W.Reducer == "wp.ati" &&
|
||||
W.Actions.toSet() == setOf(
|
||||
"SetKode", "SetParts", "SetPartsInfo", "ResetTankBuilder",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
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