feat(state): 迁移 battleMessage 并补战斗消息协议模型
This commit is contained in:
1 parent
0cd2a23c9e
commit
9cf760b354
8 files changed
+261
-22
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` 动作名。
|
||||
- 已迁移切片 **75/89**:
|
||||
- 已迁移切片 **76/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)
|
||||
@@ -379,12 +379,17 @@
|
||||
`SetParts` 把零件表拆成 `hulls`(hullId 列表)与 `weapons`(index → weaponIds)、并写 `paints`;
|
||||
`SetPartsInfo` 按零件 / 涂装各自的 id 建索引;零件模型跨模块,收口为
|
||||
`TankBuilderPart` / `TankBuilderPartInfo` / `TankBuilderPaintInfo`;`Trt`→`ResetTankBuilder` 整片复位。
|
||||
- `battleMessage` → `FE` / `vT().rqb`(`BattleMessageReducer.kt`):1 字段,7 个分支。
|
||||
四种消息模型按源码 `toString` 原样收口:`TextMessage(type, hideTimeMs, text, isHidden)`、
|
||||
`LocalizedMessage(…, content, arguments, isHidden)`、`LocalizedUserMessage(…, content, userTeamRelation, userUid)`、
|
||||
`LocalizedTeamMessage(…, content, teamRelation)`;`HideMessage` 只把 `hideTimeMs` 匹配的消息标隐藏,
|
||||
`RemoveMessage` 删掉匹配项,`sT`→`ResetBattleMessages` 整片复位。
|
||||
- `launchParams` → `(pass-through)`:原根 reducer 对 `hpx_1` 没有调用,缺省是 `ag()` 空 Map;
|
||||
`RootState.LaunchParams` 收口为 `LaunchParamsStateSlice = Map<String, String>`,不新增 reducer/动作。
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 74 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **14 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 75/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **823 项全绿**,含 89 槽位完整性、74 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 75 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **13 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 76/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **832 项全绿**,含 89 槽位完整性、75 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
以及用 `action_trace_merged.json` 真实派发的两条商店动作(`SetCoinPaymentProviderUrl` / `ToggleShopActivity`)回放。
|
||||
- 委派表里的已知形态:`shop` / `home` / `localBattleUserState` / `partner` 是内联 IIFE,
|
||||
已按字段具名为 `(inline@<field>)` 并从函数体抓到顶层动作名(69 / 1 / 2 / 11 个);
|
||||
@@ -411,6 +416,7 @@
|
||||
(`Bet`/`v2`/`B2`/`u2`/`K0`/`C7` 共 6 个)。
|
||||
contractState 的 `Fnt`/`Hnt` 也已登记(`Fnt` 因与任务切片同名改名为 `ClaimContractReward`);
|
||||
tankBuilderState 的 `Trt`(`ResetTankBuilder`)同样按效果定名。
|
||||
battleMessage 的 `sT`(`ResetBattleMessages`)也已登记。
|
||||
|
||||
### S4 引擎核心
|
||||
- 模块:32088(3D 数学)、92980(渲染)、61378(ECS)、55088(物理)、36659 + 71105(资源)、36734(音频)、3569(输入)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generatedAt": "2026-10-24T09:32:15.650Z",
|
||||
"generatedAt": "2026-10-24T11:41:22.721Z",
|
||||
"module": "module_10032.js",
|
||||
"RootState": {
|
||||
"Class": "z6",
|
||||
@@ -81,7 +81,8 @@
|
||||
"controlSettings",
|
||||
"battleSettings",
|
||||
"contractState",
|
||||
"tankBuilderState"
|
||||
"tankBuilderState",
|
||||
"battleMessage"
|
||||
],
|
||||
"AnonymousActions": [
|
||||
{
|
||||
@@ -1374,6 +1375,12 @@
|
||||
"Name": "ResetTankBuilder",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "new brt() 整片复位"
|
||||
},
|
||||
{
|
||||
"Local": "sT",
|
||||
"Name": "ResetBattleMessages",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "new FE() 整片复位"
|
||||
}
|
||||
],
|
||||
"Markers": [
|
||||
@@ -2464,16 +2471,16 @@
|
||||
"Reducer": "vT().rqb",
|
||||
"Delegate": "vT().rqb(t, n.qpw_1)",
|
||||
"Actions": [
|
||||
"?sT",
|
||||
"DoAddLocalizedMessage",
|
||||
"DoAddLocalizedTeamMessage",
|
||||
"DoAddLocalizedUserMessage",
|
||||
"DoAddTextMessage",
|
||||
"HideMessage",
|
||||
"RemoveMessage"
|
||||
"RemoveMessage",
|
||||
"ResetBattleMessages"
|
||||
],
|
||||
"Default": "new FE()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "battleChat",
|
||||
|
||||
@@ -316,6 +316,8 @@ const AnonymousActionNames = new Map([
|
||||
['Hnt', 'RemoveCompletedContracts'],
|
||||
// tankBuilderState 切片(brt / Irt.ati):Trt 没有 toString。
|
||||
['Trt', 'ResetTankBuilder'],
|
||||
// battleMessage 切片(FE / fT.rqb):sT 没有 toString。
|
||||
['sT', 'ResetBattleMessages'],
|
||||
]);
|
||||
|
||||
// 非动作的 `instanceof`:屏幕标识类,用于 GoTo 分支判断(不是 dispatch 的动作)。
|
||||
@@ -792,6 +794,7 @@ const Migrated = {
|
||||
battleSettings: { Type: 'BattleSettingsStateSlice', Reduce: 'ReduceBattleSettings' },
|
||||
contractState: { Type: 'ContractStateSlice', Reduce: 'ReduceContractState' },
|
||||
tankBuilderState: { Type: 'TankBuilderStateSlice', Reduce: 'ReduceTankBuilder' },
|
||||
battleMessage: { Type: 'BattleMessageStateSlice', Reduce: 'ReduceBattleMessage' },
|
||||
};
|
||||
|
||||
for (const R of Rows) R.Migrated = Object.prototype.hasOwnProperty.call(Migrated, R.Field);
|
||||
@@ -1198,6 +1201,7 @@ const AppSettingsAnonymousEffects = {
|
||||
Fnt: '复制该合同并把 rewards 清空(原名 GetReward,与任务切片同名)',
|
||||
Hnt: '只保留 rewards 非空的合同',
|
||||
Trt: 'new brt() 整片复位',
|
||||
sT: 'new FE() 整片复位',
|
||||
};
|
||||
|
||||
fs.writeFileSync(
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
// BattleMessageReducer.kt —— 战斗消息切片(对应 module_10032 的 FE 状态 + fT.rqb)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 FE:1 个字段,toString 名 "BattleMessageState(messages=…)"。
|
||||
// 默认:messages = emptyList()。
|
||||
// 根委派:`vT().rqb(t, n.qpw_1)`。
|
||||
// 消息模型(四种,toString 给出完整字段名):
|
||||
// HE TextMessage(type, hideTimeMs, text, isHidden)
|
||||
// GE LocalizedMessage(type, hideTimeMs, content, arguments, isHidden)
|
||||
// WE LocalizedUserMessage(type, hideTimeMs, isHidden, content, userTeamRelation, userUid)
|
||||
// VE LocalizedTeamMessage(type, hideTimeMs, isHidden, content, teamRelation)
|
||||
// reducer(6 个实例臂):
|
||||
// aT(DoAddTextMessage) → 追加 TextMessage
|
||||
// oT(DoAddLocalizedMessage) → 追加 LocalizedMessage
|
||||
// _T(DoAddLocalizedUserMessage) → 追加 LocalizedUserMessage
|
||||
// hT(DoAddLocalizedTeamMessage) → 追加 LocalizedTeamMessage
|
||||
// eT(HideMessage) → 把 hideTimeMs 匹配的消息标成 isHidden=true
|
||||
// uT(RemoveMessage) → 删掉 hideTimeMs 匹配的消息
|
||||
// sT(无 toString) → `new FE()` 整片复位
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.DoAddLocalizedMessage
|
||||
import App.State.DoAddLocalizedTeamMessage
|
||||
import App.State.DoAddLocalizedUserMessage
|
||||
import App.State.DoAddTextMessage
|
||||
import App.State.HideMessage
|
||||
import App.State.RemoveMessage
|
||||
|
||||
/* ------------------------------------------------------------------ 消息模型 */
|
||||
|
||||
sealed interface BattleMessageEntry {
|
||||
val Type: Any?
|
||||
val HideTimeMs: Any?
|
||||
val IsHidden: Boolean
|
||||
|
||||
fun WithHidden(Value: Boolean): BattleMessageEntry
|
||||
}
|
||||
|
||||
data class TextMessage(
|
||||
override val Type: Any?,
|
||||
override val HideTimeMs: Any?,
|
||||
val Text: String,
|
||||
override val IsHidden: Boolean = false,
|
||||
) : BattleMessageEntry {
|
||||
override fun WithHidden(Value: Boolean) = copy(IsHidden = Value)
|
||||
}
|
||||
|
||||
data class LocalizedMessage(
|
||||
override val Type: Any?,
|
||||
override val HideTimeMs: Any?,
|
||||
val Content: Any?,
|
||||
val Arguments: List<Any?> = emptyList(),
|
||||
override val IsHidden: Boolean = false,
|
||||
) : BattleMessageEntry {
|
||||
override fun WithHidden(Value: Boolean) = copy(IsHidden = Value)
|
||||
}
|
||||
|
||||
data class LocalizedUserMessage(
|
||||
override val Type: Any?,
|
||||
override val HideTimeMs: Any?,
|
||||
override val IsHidden: Boolean = false,
|
||||
val Content: Any?,
|
||||
val UserTeamRelation: Any?,
|
||||
val UserUid: Any?,
|
||||
) : BattleMessageEntry {
|
||||
override fun WithHidden(Value: Boolean) = copy(IsHidden = Value)
|
||||
}
|
||||
|
||||
data class LocalizedTeamMessage(
|
||||
override val Type: Any?,
|
||||
override val HideTimeMs: Any?,
|
||||
override val IsHidden: Boolean = false,
|
||||
val Content: Any?,
|
||||
val TeamRelation: Any?,
|
||||
) : BattleMessageEntry {
|
||||
override fun WithHidden(Value: Boolean) = copy(IsHidden = Value)
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `sT`:整片复位(`new FE()`)。 */
|
||||
object ResetBattleMessages
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class BattleMessageStateSlice(
|
||||
val Messages: List<Any?> = emptyList(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
private fun HideByTime(Messages: List<Any?>, HideTimeMs: Any?): List<Any?> =
|
||||
Messages.map {
|
||||
val Entry = it as? BattleMessageEntry
|
||||
if (Entry != null && Entry.HideTimeMs == HideTimeMs) Entry.WithHidden(true) else it
|
||||
}
|
||||
|
||||
fun ReduceBattleMessage(
|
||||
State0: BattleMessageStateSlice,
|
||||
Action: Any,
|
||||
): BattleMessageStateSlice = when (Action) {
|
||||
is DoAddTextMessage -> State0.copy(
|
||||
Messages = State0.Messages + TextMessage(
|
||||
Type = Action.type,
|
||||
HideTimeMs = Action.hideTimeMs,
|
||||
Text = Action.text?.toString() ?: "",
|
||||
),
|
||||
)
|
||||
is DoAddLocalizedMessage -> State0.copy(
|
||||
Messages = State0.Messages + LocalizedMessage(
|
||||
Type = Action.type,
|
||||
HideTimeMs = Action.hideTimeMs,
|
||||
Content = Action.message,
|
||||
Arguments = (Action.args as? List<Any?>) ?: emptyList(),
|
||||
),
|
||||
)
|
||||
is DoAddLocalizedUserMessage -> State0.copy(
|
||||
Messages = State0.Messages + LocalizedUserMessage(
|
||||
Type = Action.type,
|
||||
HideTimeMs = Action.hideTimeMs,
|
||||
Content = Action.message,
|
||||
UserTeamRelation = Action.userTeamRelation,
|
||||
UserUid = Action.userUid,
|
||||
),
|
||||
)
|
||||
is DoAddLocalizedTeamMessage -> State0.copy(
|
||||
Messages = State0.Messages + LocalizedTeamMessage(
|
||||
Type = Action.type,
|
||||
HideTimeMs = Action.hideTimeMs,
|
||||
Content = Action.message,
|
||||
TeamRelation = Action.teamRelation,
|
||||
),
|
||||
)
|
||||
is HideMessage -> State0.copy(Messages = HideByTime(State0.Messages, Action.hideTimeMs))
|
||||
is RemoveMessage -> State0.copy(
|
||||
Messages = State0.Messages.filterNot {
|
||||
(it as? BattleMessageEntry)?.HideTimeMs == Action.hideTimeMs
|
||||
},
|
||||
)
|
||||
is ResetBattleMessages -> BattleMessageStateSlice()
|
||||
else -> State0
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// RootReducer.kt —— 根 reducer 骨架(对应 module_10032 的根状态 z6 / TOState 与根 reducer k6)
|
||||
//
|
||||
// 原包 k6 对 89 个切片逐个调用各自的 reducer,再 `return n.cti(...)`(copy 出新状态)。
|
||||
// 这里采用同一形状。已迁移的 75 个切片里,74 个真正调用 reducer,launchParams 只做类型收口:
|
||||
// 这里采用同一形状。已迁移的 76 个切片里,75 个真正调用 reducer,launchParams 只做类型收口:
|
||||
//
|
||||
// inviteState → ReduceInvite(aD / pD.er5)
|
||||
// loginByPassword → ReduceLoginByPassword(gD / MD.cr6)
|
||||
@@ -77,9 +77,10 @@
|
||||
// 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)`)
|
||||
// battleMessage → ReduceBattleMessage(FE / vT().rqb,根委派 `vT().rqb(t, n.qpw_1)`)
|
||||
// launchParams → 无 reducer(原根 reducer 原样透传;默认 `ag()` = emptyMap())
|
||||
//
|
||||
// 其余 14 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 其余 13 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 所以一次 copy 里串起全部已迁移 reducer,与按动作路由再归约的结果一致。
|
||||
// 迁移进度与每个字段的证据见生成物 RootWiring.kt(不要手改)。
|
||||
package App.State
|
||||
@@ -88,6 +89,7 @@ import App.State.Reducers.ReduceAccountSettings
|
||||
import App.State.Reducers.ReduceAnnouncement
|
||||
import App.State.Reducers.ReduceAntiAddiction
|
||||
import App.State.Reducers.ReduceBattleResult
|
||||
import App.State.Reducers.ReduceBattleMessage
|
||||
import App.State.Reducers.ReduceBattlePause
|
||||
import App.State.Reducers.ReduceBattleSearch
|
||||
import App.State.Reducers.ReduceBattleSettings
|
||||
@@ -246,6 +248,7 @@ object RootReducer {
|
||||
BattleSettings = ReduceBattleSettings(State0.BattleSettings, Action),
|
||||
ContractState = ReduceContractState(State0.ContractState, Action),
|
||||
TankBuilderState = ReduceTankBuilder(State0.TankBuilderState, Action),
|
||||
BattleMessage = ReduceBattleMessage(State0.BattleMessage, Action),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import App.State.Reducers.AnnouncementStateSlice
|
||||
import App.State.Reducers.AntiAddictionStateSlice
|
||||
import App.State.Reducers.AvailabilityByRankStateSlice
|
||||
import App.State.Reducers.BattleInviteStateSlice
|
||||
import App.State.Reducers.BattleMessageStateSlice
|
||||
import App.State.Reducers.BattlePauseStateSlice
|
||||
import App.State.Reducers.BattleResultStateSlice
|
||||
import App.State.Reducers.BattleSearchStateSlice
|
||||
@@ -171,8 +172,8 @@ data class RootState(
|
||||
val ClanUserInfo: ClanUserInfoStateSlice = ClanUserInfoStateSlice(),
|
||||
/** 原 tankActionsLogState(vI / wi.gqe)。已迁移。 */
|
||||
val TankActionsLogState: TankActionsLogStateSlice = TankActionsLogStateSlice(),
|
||||
/** 原 battleMessage(FE / vT().rqb)。未迁移:原样透传。 */
|
||||
val BattleMessage: Any? = null,
|
||||
/** 原 battleMessage(FE / vT().rqb)。已迁移。 */
|
||||
val BattleMessage: BattleMessageStateSlice = BattleMessageStateSlice(),
|
||||
/** 原 battleChat(Q6 / Hf.wtg)。未迁移:原样透传。 */
|
||||
val BattleChat: Any? = null,
|
||||
/** 原 droppableGold(Vet / Wp.kth)。已迁移。 */
|
||||
|
||||
@@ -58,7 +58,7 @@ object RootWiring {
|
||||
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("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("battleMessage", "qpw_1", "FE", "vT().rqb", "vT().rqb(t, n.qpw_1)", listOf("DoAddLocalizedMessage", "DoAddLocalizedTeamMessage", "DoAddLocalizedUserMessage", "DoAddTextMessage", "HideMessage", "RemoveMessage", "ResetBattleMessages")),
|
||||
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")),
|
||||
SliceWiring("home", "tpw_1", "s1", "(inline@home)", "(function (t, n) { return t instanceof o1 ? n.f7j(!0) : n; })(t, n.tpw_1)", listOf("ShowShopDiscountNotification")),
|
||||
@@ -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", "tankBuilderState")
|
||||
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", "battleMessage")
|
||||
|
||||
/** 未迁移字段:归约时原样透传,作为后续迁移清单。 */
|
||||
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 / TankBuilder;
|
||||
// BattlePause / BattleView / TankActionsLog / SuppliesTutorial / ClanChat / BattleSearch / BattleStatistics / SoundSettings / GameSettings / KeyboardSettings / TouchscreenHudSettings / GraphicsSettings / ControlSettings / BattleSettings / ContractState / TankBuilder / BattleMessage;
|
||||
// ㉑ launchParams 是纯透传切片(无 reducer/动作),只做 Map 类型收口;⑭ 根 reducer 的 89 槽位委派
|
||||
//
|
||||
// 用法:$env:TANKIOFFLINE_STATE_TEST='1'; node …(见 TankiOffline/tools/RunStateTest.ps1)
|
||||
@@ -716,6 +716,20 @@ import App.State.Reducers.TankBuilderPaintInfo
|
||||
import App.State.Reducers.TankBuilderPart
|
||||
import App.State.Reducers.TankBuilderPartInfo
|
||||
import App.State.Reducers.TankBuilderStateSlice
|
||||
import App.State.DoAddLocalizedMessage
|
||||
import App.State.DoAddLocalizedTeamMessage
|
||||
import App.State.DoAddLocalizedUserMessage
|
||||
import App.State.DoAddTextMessage
|
||||
import App.State.HideMessage
|
||||
import App.State.RemoveMessage
|
||||
import App.State.Reducers.BattleMessageEntry
|
||||
import App.State.Reducers.BattleMessageStateSlice
|
||||
import App.State.Reducers.LocalizedMessage
|
||||
import App.State.Reducers.LocalizedTeamMessage
|
||||
import App.State.Reducers.LocalizedUserMessage
|
||||
import App.State.Reducers.ReduceBattleMessage
|
||||
import App.State.Reducers.ResetBattleMessages
|
||||
import App.State.Reducers.TextMessage
|
||||
import App.State.Reducers.UserRankBounds
|
||||
import App.State.Reducers.UserStateSlice
|
||||
import App.State.Reducers.ClearHullData
|
||||
@@ -1143,7 +1157,7 @@ object StateCheck {
|
||||
Check("切片 LocalBattleUser:接 Store 派发后状态已归约", Store.State.IsReArmorTemporaryDisabled)
|
||||
}
|
||||
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 75 个已迁移切片(74 归约 + launchParams 透传)
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 76 个已迁移切片(75 归约 + launchParams 透传)
|
||||
run {
|
||||
Check("根:根状态 89 个切片槽位", RootWiring.All.size == 89)
|
||||
Check(
|
||||
@@ -1207,7 +1221,7 @@ object StateCheck {
|
||||
LocalBattleW.Reducer == "(inline@localBattleUserState)"
|
||||
)
|
||||
Check(
|
||||
"根:迁移表 = 75 个已迁移字段,其余 14 个待迁",
|
||||
"根:迁移表 = 76 个已迁移字段,其余 13 个待迁",
|
||||
RootReducer.Migrated ==
|
||||
setOf(
|
||||
"inviteState", "loginByPassword", "twitchState", "home",
|
||||
@@ -1230,9 +1244,9 @@ object StateCheck {
|
||||
"clanChatState", "battleSearchState", "battleStatistics",
|
||||
"soundSettings", "gameSettings", "keyboardSettings", "touchscreenHudSettings",
|
||||
"graphicsSettings", "controlSettings", "battleSettings", "contractState",
|
||||
"tankBuilderState",
|
||||
"tankBuilderState", "battleMessage",
|
||||
) &&
|
||||
RootWiring.Unmigrated.size == 14
|
||||
RootWiring.Unmigrated.size == 13
|
||||
)
|
||||
|
||||
// 一次 ReduceRoot 里多个切片各归约自己的动作,互不串片
|
||||
@@ -1288,7 +1302,7 @@ object StateCheck {
|
||||
S5.User.Uid == "user-1" && S5.Screen.Current == NamedScreen("Preloader")
|
||||
)
|
||||
Check("根:无关动作返回等值状态", ReduceRoot(S5, AddFrags(1)) == S5)
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 75/89")
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 76/89")
|
||||
|
||||
val Store = ReduxStore(RootState(), { S, A -> ReduceRoot(S, A) })
|
||||
Store.Dispatch(SetStatus("LOGGING_IN"))
|
||||
@@ -6273,6 +6287,68 @@ object StateCheck {
|
||||
)
|
||||
}
|
||||
|
||||
// 86 切片 reducer:BattleMessage(FE / vT().rqb,1 字段;7 个动作)
|
||||
run {
|
||||
val S0 = BattleMessageStateSlice()
|
||||
Check("切片 BattleMessage:默认空消息表", S0.Messages.isEmpty())
|
||||
val S1 = ReduceBattleMessage(S0, DoAddTextMessage("info", 100L, "hello"))
|
||||
Check(
|
||||
"切片 BattleMessage:DoAddTextMessage 追加 TextMessage",
|
||||
S1.Messages.size == 1 &&
|
||||
(S1.Messages[0] as TextMessage).Text == "hello" &&
|
||||
(S1.Messages[0] as TextMessage).HideTimeMs == 100L
|
||||
)
|
||||
val S2 = ReduceBattleMessage(
|
||||
ReduceBattleMessage(
|
||||
ReduceBattleMessage(S1, DoAddLocalizedMessage("sys", 200L, "KILL", listOf("a"))),
|
||||
DoAddLocalizedUserMessage("enemy", "user", 300L, "MSG", "uid1"),
|
||||
),
|
||||
DoAddLocalizedTeamMessage("team", 400L, "TEAM", "red"),
|
||||
)
|
||||
Check(
|
||||
"切片 BattleMessage:四种消息按各自字段入表",
|
||||
S2.Messages.size == 4 &&
|
||||
(S2.Messages[1] as LocalizedMessage).Content == "KILL" &&
|
||||
(S2.Messages[1] as LocalizedMessage).Arguments == listOf<Any?>("a") &&
|
||||
(S2.Messages[2] as LocalizedUserMessage).UserTeamRelation == "enemy" &&
|
||||
(S2.Messages[2] as LocalizedUserMessage).UserUid == "uid1" &&
|
||||
(S2.Messages[3] as LocalizedTeamMessage).TeamRelation == "red"
|
||||
)
|
||||
val S3 = ReduceBattleMessage(S2, HideMessage(100L))
|
||||
Check(
|
||||
"切片 BattleMessage:HideMessage 只把匹配 hideTimeMs 的标隐藏",
|
||||
(S3.Messages[0] as TextMessage).IsHidden &&
|
||||
!(S3.Messages[1] as LocalizedMessage).IsHidden
|
||||
)
|
||||
val S4 = ReduceBattleMessage(S3, RemoveMessage(200L))
|
||||
Check(
|
||||
"切片 BattleMessage:RemoveMessage 删掉匹配的那条",
|
||||
S4.Messages.size == 3 &&
|
||||
S4.Messages.none { (it as BattleMessageEntry).HideTimeMs == 200L }
|
||||
)
|
||||
Check(
|
||||
"切片 BattleMessage:ResetBattleMessages 整片复位",
|
||||
ReduceBattleMessage(S4, ResetBattleMessages) == BattleMessageStateSlice()
|
||||
)
|
||||
Check(
|
||||
"切片 BattleMessage:无关动作不改状态",
|
||||
ReduceBattleMessage(S4, AddFrags(1)) == S4
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, DoAddTextMessage("info", 1L, "x"))
|
||||
Check(
|
||||
"根:DoAddTextMessage 只动 battleMessage",
|
||||
Root1.BattleMessage.Messages.size == 1 &&
|
||||
Root1.TankBuilderState == Root0.TankBuilderState
|
||||
)
|
||||
val W = RootWiring.ByField("battleMessage")!!
|
||||
Check(
|
||||
"根:battleMessage 委派到 FE / vT().rqb 且 7 个动作",
|
||||
W.SliceClass == "FE" && W.Reducer == "vT().rqb" && W.Actions.size == 7
|
||||
)
|
||||
}
|
||||
|
||||
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