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`。
|
`names/root_wiring.json` + `TankiOffline/.../App/State/RootState.kt`、`RootWiring.kt`。
|
||||||
- 根状态 `z6`(`TOState`)的 **89 个槽位**全部入表;字段顺序取 `toString`,槽位取构造函数 `<名>_1`。
|
- 根状态 `z6`(`TOState`)的 **89 个槽位**全部入表;字段顺序取 `toString`,槽位取构造函数 `<名>_1`。
|
||||||
- 根 reducer `k6` 的逐切片委派记全:reducer 引用、委派表达式、顶层 `instanceof` 动作名。
|
- 根 reducer `k6` 的逐切片委派记全:reducer 引用、委派表达式、顶层 `instanceof` 动作名。
|
||||||
- 已迁移切片 **75/89**:
|
- 已迁移切片 **76/89**:
|
||||||
- `inviteState` → `aD` / `pD.er5`(`InviteReducer.kt`)
|
- `inviteState` → `aD` / `pD.er5`(`InviteReducer.kt`)
|
||||||
- `loginByPassword` → `gD` / `MD.cr6`(`LoginReducer.kt`,含 `SetLogin`/`SetPassword` 把 status 打回 `NONE` 的原语义)
|
- `loginByPassword` → `gD` / `MD.cr6`(`LoginReducer.kt`,含 `SetLogin`/`SetPassword` 把 status 打回 `NONE` 的原语义)
|
||||||
- `twitchState` → `g9` / `y9.gta`(`TwitchReducer.kt`;`SetAccount` 是 Twitch 账号,不是 UID)
|
- `twitchState` → `g9` / `y9.gta`(`TwitchReducer.kt`;`SetAccount` 是 Twitch 账号,不是 UID)
|
||||||
@@ -379,12 +379,17 @@
|
|||||||
`SetParts` 把零件表拆成 `hulls`(hullId 列表)与 `weapons`(index → weaponIds)、并写 `paints`;
|
`SetParts` 把零件表拆成 `hulls`(hullId 列表)与 `weapons`(index → weaponIds)、并写 `paints`;
|
||||||
`SetPartsInfo` 按零件 / 涂装各自的 id 建索引;零件模型跨模块,收口为
|
`SetPartsInfo` 按零件 / 涂装各自的 id 建索引;零件模型跨模块,收口为
|
||||||
`TankBuilderPart` / `TankBuilderPartInfo` / `TankBuilderPaintInfo`;`Trt`→`ResetTankBuilder` 整片复位。
|
`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;
|
- `launchParams` → `(pass-through)`:原根 reducer 对 `hpx_1` 没有调用,缺省是 `ag()` 空 Map;
|
||||||
`RootState.LaunchParams` 收口为 `LaunchParamsStateSlice = Map<String, String>`,不新增 reducer/动作。
|
`RootState.LaunchParams` 收口为 `LaunchParamsStateSlice = Map<String, String>`,不新增 reducer/动作。
|
||||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 74 个有 reducer 的切片,
|
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 75 个有 reducer 的切片,
|
||||||
`launchParams` 与其余 **14 个字段原样透传**;
|
`launchParams` 与其余 **13 个字段原样透传**;
|
||||||
迁移进度用 `RootReducer.Coverage`(`已迁移 75/89`)与 `RootWiring.Unmigrated` 暴露。
|
迁移进度用 `RootReducer.Coverage`(`已迁移 76/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **823 项全绿**,含 89 槽位完整性、74 个归约切片一次归约互不串片、未迁移字段透传,
|
- 自检:`TankiOffline/tools/RunStateTest.ps1` **832 项全绿**,含 89 槽位完整性、75 个归约切片一次归约互不串片、未迁移字段透传,
|
||||||
以及用 `action_trace_merged.json` 真实派发的两条商店动作(`SetCoinPaymentProviderUrl` / `ToggleShopActivity`)回放。
|
以及用 `action_trace_merged.json` 真实派发的两条商店动作(`SetCoinPaymentProviderUrl` / `ToggleShopActivity`)回放。
|
||||||
- 委派表里的已知形态:`shop` / `home` / `localBattleUserState` / `partner` 是内联 IIFE,
|
- 委派表里的已知形态:`shop` / `home` / `localBattleUserState` / `partner` 是内联 IIFE,
|
||||||
已按字段具名为 `(inline@<field>)` 并从函数体抓到顶层动作名(69 / 1 / 2 / 11 个);
|
已按字段具名为 `(inline@<field>)` 并从函数体抓到顶层动作名(69 / 1 / 2 / 11 个);
|
||||||
@@ -411,6 +416,7 @@
|
|||||||
(`Bet`/`v2`/`B2`/`u2`/`K0`/`C7` 共 6 个)。
|
(`Bet`/`v2`/`B2`/`u2`/`K0`/`C7` 共 6 个)。
|
||||||
contractState 的 `Fnt`/`Hnt` 也已登记(`Fnt` 因与任务切片同名改名为 `ClaimContractReward`);
|
contractState 的 `Fnt`/`Hnt` 也已登记(`Fnt` 因与任务切片同名改名为 `ClaimContractReward`);
|
||||||
tankBuilderState 的 `Trt`(`ResetTankBuilder`)同样按效果定名。
|
tankBuilderState 的 `Trt`(`ResetTankBuilder`)同样按效果定名。
|
||||||
|
battleMessage 的 `sT`(`ResetBattleMessages`)也已登记。
|
||||||
|
|
||||||
### S4 引擎核心
|
### S4 引擎核心
|
||||||
- 模块:32088(3D 数学)、92980(渲染)、61378(ECS)、55088(物理)、36659 + 71105(资源)、36734(音频)、3569(输入)
|
- 模块: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",
|
"module": "module_10032.js",
|
||||||
"RootState": {
|
"RootState": {
|
||||||
"Class": "z6",
|
"Class": "z6",
|
||||||
@@ -81,7 +81,8 @@
|
|||||||
"controlSettings",
|
"controlSettings",
|
||||||
"battleSettings",
|
"battleSettings",
|
||||||
"contractState",
|
"contractState",
|
||||||
"tankBuilderState"
|
"tankBuilderState",
|
||||||
|
"battleMessage"
|
||||||
],
|
],
|
||||||
"AnonymousActions": [
|
"AnonymousActions": [
|
||||||
{
|
{
|
||||||
@@ -1374,6 +1375,12 @@
|
|||||||
"Name": "ResetTankBuilder",
|
"Name": "ResetTankBuilder",
|
||||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||||
"Effect": "new brt() 整片复位"
|
"Effect": "new brt() 整片复位"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Local": "sT",
|
||||||
|
"Name": "ResetBattleMessages",
|
||||||
|
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||||
|
"Effect": "new FE() 整片复位"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Markers": [
|
"Markers": [
|
||||||
@@ -2464,16 +2471,16 @@
|
|||||||
"Reducer": "vT().rqb",
|
"Reducer": "vT().rqb",
|
||||||
"Delegate": "vT().rqb(t, n.qpw_1)",
|
"Delegate": "vT().rqb(t, n.qpw_1)",
|
||||||
"Actions": [
|
"Actions": [
|
||||||
"?sT",
|
|
||||||
"DoAddLocalizedMessage",
|
"DoAddLocalizedMessage",
|
||||||
"DoAddLocalizedTeamMessage",
|
"DoAddLocalizedTeamMessage",
|
||||||
"DoAddLocalizedUserMessage",
|
"DoAddLocalizedUserMessage",
|
||||||
"DoAddTextMessage",
|
"DoAddTextMessage",
|
||||||
"HideMessage",
|
"HideMessage",
|
||||||
"RemoveMessage"
|
"RemoveMessage",
|
||||||
|
"ResetBattleMessages"
|
||||||
],
|
],
|
||||||
"Default": "new FE()",
|
"Default": "new FE()",
|
||||||
"Migrated": false
|
"Migrated": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Field": "battleChat",
|
"Field": "battleChat",
|
||||||
|
|||||||
@@ -316,6 +316,8 @@ const AnonymousActionNames = new Map([
|
|||||||
['Hnt', 'RemoveCompletedContracts'],
|
['Hnt', 'RemoveCompletedContracts'],
|
||||||
// tankBuilderState 切片(brt / Irt.ati):Trt 没有 toString。
|
// tankBuilderState 切片(brt / Irt.ati):Trt 没有 toString。
|
||||||
['Trt', 'ResetTankBuilder'],
|
['Trt', 'ResetTankBuilder'],
|
||||||
|
// battleMessage 切片(FE / fT.rqb):sT 没有 toString。
|
||||||
|
['sT', 'ResetBattleMessages'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 非动作的 `instanceof`:屏幕标识类,用于 GoTo 分支判断(不是 dispatch 的动作)。
|
// 非动作的 `instanceof`:屏幕标识类,用于 GoTo 分支判断(不是 dispatch 的动作)。
|
||||||
@@ -792,6 +794,7 @@ const Migrated = {
|
|||||||
battleSettings: { Type: 'BattleSettingsStateSlice', Reduce: 'ReduceBattleSettings' },
|
battleSettings: { Type: 'BattleSettingsStateSlice', Reduce: 'ReduceBattleSettings' },
|
||||||
contractState: { Type: 'ContractStateSlice', Reduce: 'ReduceContractState' },
|
contractState: { Type: 'ContractStateSlice', Reduce: 'ReduceContractState' },
|
||||||
tankBuilderState: { Type: 'TankBuilderStateSlice', Reduce: 'ReduceTankBuilder' },
|
tankBuilderState: { Type: 'TankBuilderStateSlice', Reduce: 'ReduceTankBuilder' },
|
||||||
|
battleMessage: { Type: 'BattleMessageStateSlice', Reduce: 'ReduceBattleMessage' },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const R of Rows) R.Migrated = Object.prototype.hasOwnProperty.call(Migrated, R.Field);
|
for (const R of Rows) R.Migrated = Object.prototype.hasOwnProperty.call(Migrated, R.Field);
|
||||||
@@ -1198,6 +1201,7 @@ const AppSettingsAnonymousEffects = {
|
|||||||
Fnt: '复制该合同并把 rewards 清空(原名 GetReward,与任务切片同名)',
|
Fnt: '复制该合同并把 rewards 清空(原名 GetReward,与任务切片同名)',
|
||||||
Hnt: '只保留 rewards 非空的合同',
|
Hnt: '只保留 rewards 非空的合同',
|
||||||
Trt: 'new brt() 整片复位',
|
Trt: 'new brt() 整片复位',
|
||||||
|
sT: 'new FE() 整片复位',
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.writeFileSync(
|
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)
|
// RootReducer.kt —— 根 reducer 骨架(对应 module_10032 的根状态 z6 / TOState 与根 reducer k6)
|
||||||
//
|
//
|
||||||
// 原包 k6 对 89 个切片逐个调用各自的 reducer,再 `return n.cti(...)`(copy 出新状态)。
|
// 原包 k6 对 89 个切片逐个调用各自的 reducer,再 `return n.cti(...)`(copy 出新状态)。
|
||||||
// 这里采用同一形状。已迁移的 75 个切片里,74 个真正调用 reducer,launchParams 只做类型收口:
|
// 这里采用同一形状。已迁移的 76 个切片里,75 个真正调用 reducer,launchParams 只做类型收口:
|
||||||
//
|
//
|
||||||
// inviteState → ReduceInvite(aD / pD.er5)
|
// inviteState → ReduceInvite(aD / pD.er5)
|
||||||
// loginByPassword → ReduceLoginByPassword(gD / MD.cr6)
|
// loginByPassword → ReduceLoginByPassword(gD / MD.cr6)
|
||||||
@@ -77,9 +77,10 @@
|
|||||||
// battleSettings → ReduceBattleSettings(W0 / X0().esq,根委派 `X0().esq(t, n.xpw_1)`)
|
// battleSettings → ReduceBattleSettings(W0 / X0().esq,根委派 `X0().esq(t, n.xpw_1)`)
|
||||||
// contractState → ReduceContractState(Ont / xv.bti,根委派 `xv.bti(t, n.fpy_1)`)
|
// contractState → ReduceContractState(Ont / xv.bti,根委派 `xv.bti(t, n.fpy_1)`)
|
||||||
// tankBuilderState → ReduceTankBuilder(brt / wp.ati,根委派 `wp.ati(t, n.epy_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())
|
// launchParams → 无 reducer(原根 reducer 原样透传;默认 `ag()` = emptyMap())
|
||||||
//
|
//
|
||||||
// 其余 14 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
// 其余 13 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||||
// 所以一次 copy 里串起全部已迁移 reducer,与按动作路由再归约的结果一致。
|
// 所以一次 copy 里串起全部已迁移 reducer,与按动作路由再归约的结果一致。
|
||||||
// 迁移进度与每个字段的证据见生成物 RootWiring.kt(不要手改)。
|
// 迁移进度与每个字段的证据见生成物 RootWiring.kt(不要手改)。
|
||||||
package App.State
|
package App.State
|
||||||
@@ -88,6 +89,7 @@ import App.State.Reducers.ReduceAccountSettings
|
|||||||
import App.State.Reducers.ReduceAnnouncement
|
import App.State.Reducers.ReduceAnnouncement
|
||||||
import App.State.Reducers.ReduceAntiAddiction
|
import App.State.Reducers.ReduceAntiAddiction
|
||||||
import App.State.Reducers.ReduceBattleResult
|
import App.State.Reducers.ReduceBattleResult
|
||||||
|
import App.State.Reducers.ReduceBattleMessage
|
||||||
import App.State.Reducers.ReduceBattlePause
|
import App.State.Reducers.ReduceBattlePause
|
||||||
import App.State.Reducers.ReduceBattleSearch
|
import App.State.Reducers.ReduceBattleSearch
|
||||||
import App.State.Reducers.ReduceBattleSettings
|
import App.State.Reducers.ReduceBattleSettings
|
||||||
@@ -246,6 +248,7 @@ object RootReducer {
|
|||||||
BattleSettings = ReduceBattleSettings(State0.BattleSettings, Action),
|
BattleSettings = ReduceBattleSettings(State0.BattleSettings, Action),
|
||||||
ContractState = ReduceContractState(State0.ContractState, Action),
|
ContractState = ReduceContractState(State0.ContractState, Action),
|
||||||
TankBuilderState = ReduceTankBuilder(State0.TankBuilderState, 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.AntiAddictionStateSlice
|
||||||
import App.State.Reducers.AvailabilityByRankStateSlice
|
import App.State.Reducers.AvailabilityByRankStateSlice
|
||||||
import App.State.Reducers.BattleInviteStateSlice
|
import App.State.Reducers.BattleInviteStateSlice
|
||||||
|
import App.State.Reducers.BattleMessageStateSlice
|
||||||
import App.State.Reducers.BattlePauseStateSlice
|
import App.State.Reducers.BattlePauseStateSlice
|
||||||
import App.State.Reducers.BattleResultStateSlice
|
import App.State.Reducers.BattleResultStateSlice
|
||||||
import App.State.Reducers.BattleSearchStateSlice
|
import App.State.Reducers.BattleSearchStateSlice
|
||||||
@@ -171,8 +172,8 @@ data class RootState(
|
|||||||
val ClanUserInfo: ClanUserInfoStateSlice = ClanUserInfoStateSlice(),
|
val ClanUserInfo: ClanUserInfoStateSlice = ClanUserInfoStateSlice(),
|
||||||
/** 原 tankActionsLogState(vI / wi.gqe)。已迁移。 */
|
/** 原 tankActionsLogState(vI / wi.gqe)。已迁移。 */
|
||||||
val TankActionsLogState: TankActionsLogStateSlice = TankActionsLogStateSlice(),
|
val TankActionsLogState: TankActionsLogStateSlice = TankActionsLogStateSlice(),
|
||||||
/** 原 battleMessage(FE / vT().rqb)。未迁移:原样透传。 */
|
/** 原 battleMessage(FE / vT().rqb)。已迁移。 */
|
||||||
val BattleMessage: Any? = null,
|
val BattleMessage: BattleMessageStateSlice = BattleMessageStateSlice(),
|
||||||
/** 原 battleChat(Q6 / Hf.wtg)。未迁移:原样透传。 */
|
/** 原 battleChat(Q6 / Hf.wtg)。未迁移:原样透传。 */
|
||||||
val BattleChat: Any? = null,
|
val BattleChat: Any? = null,
|
||||||
/** 原 droppableGold(Vet / Wp.kth)。已迁移。 */
|
/** 原 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("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("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("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("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("droppableGold", "spw_1", "Vet", "Wp.kth", "Wp.kth(t, n.spw_1)", listOf("HideDroppableGoldAuthor", "ShowDroppableGoldAuthor")),
|
||||||
SliceWiring("home", "tpw_1", "s1", "(inline@home)", "(function (t, n) { return t instanceof o1 ? n.f7j(!0) : n; })(t, n.tpw_1)", listOf("ShowShopDiscountNotification")),
|
SliceWiring("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)的字段。 */
|
/** 已迁移(强类型;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 }
|
val Unmigrated: List<SliceWiring> get() = All.filter { it.Field !in Migrated }
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
// System / ContextTutorial / BattleTutorial / Spectator / TwoStepVerification / AntiAddiction /
|
// System / ContextTutorial / BattleTutorial / Spectator / TwoStepVerification / AntiAddiction /
|
||||||
// Moderation / MigrationState / Register / UserReports /
|
// Moderation / MigrationState / Register / UserReports /
|
||||||
// Friends / Supplies / ClanUserInfo / BattleInvite / Partner / UserRename /
|
// 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 槽位委派
|
// ㉑ launchParams 是纯透传切片(无 reducer/动作),只做 Map 类型收口;⑭ 根 reducer 的 89 槽位委派
|
||||||
//
|
//
|
||||||
// 用法:$env:TANKIOFFLINE_STATE_TEST='1'; node …(见 TankiOffline/tools/RunStateTest.ps1)
|
// 用法:$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.TankBuilderPart
|
||||||
import App.State.Reducers.TankBuilderPartInfo
|
import App.State.Reducers.TankBuilderPartInfo
|
||||||
import App.State.Reducers.TankBuilderStateSlice
|
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.UserRankBounds
|
||||||
import App.State.Reducers.UserStateSlice
|
import App.State.Reducers.UserStateSlice
|
||||||
import App.State.Reducers.ClearHullData
|
import App.State.Reducers.ClearHullData
|
||||||
@@ -1143,7 +1157,7 @@ object StateCheck {
|
|||||||
Check("切片 LocalBattleUser:接 Store 派发后状态已归约", Store.State.IsReArmorTemporaryDisabled)
|
Check("切片 LocalBattleUser:接 Store 派发后状态已归约", Store.State.IsReArmorTemporaryDisabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ⑭ 根 reducer:89 个槽位的委派表 + 75 个已迁移切片(74 归约 + launchParams 透传)
|
// ⑭ 根 reducer:89 个槽位的委派表 + 76 个已迁移切片(75 归约 + launchParams 透传)
|
||||||
run {
|
run {
|
||||||
Check("根:根状态 89 个切片槽位", RootWiring.All.size == 89)
|
Check("根:根状态 89 个切片槽位", RootWiring.All.size == 89)
|
||||||
Check(
|
Check(
|
||||||
@@ -1207,7 +1221,7 @@ object StateCheck {
|
|||||||
LocalBattleW.Reducer == "(inline@localBattleUserState)"
|
LocalBattleW.Reducer == "(inline@localBattleUserState)"
|
||||||
)
|
)
|
||||||
Check(
|
Check(
|
||||||
"根:迁移表 = 75 个已迁移字段,其余 14 个待迁",
|
"根:迁移表 = 76 个已迁移字段,其余 13 个待迁",
|
||||||
RootReducer.Migrated ==
|
RootReducer.Migrated ==
|
||||||
setOf(
|
setOf(
|
||||||
"inviteState", "loginByPassword", "twitchState", "home",
|
"inviteState", "loginByPassword", "twitchState", "home",
|
||||||
@@ -1230,9 +1244,9 @@ object StateCheck {
|
|||||||
"clanChatState", "battleSearchState", "battleStatistics",
|
"clanChatState", "battleSearchState", "battleStatistics",
|
||||||
"soundSettings", "gameSettings", "keyboardSettings", "touchscreenHudSettings",
|
"soundSettings", "gameSettings", "keyboardSettings", "touchscreenHudSettings",
|
||||||
"graphicsSettings", "controlSettings", "battleSettings", "contractState",
|
"graphicsSettings", "controlSettings", "battleSettings", "contractState",
|
||||||
"tankBuilderState",
|
"tankBuilderState", "battleMessage",
|
||||||
) &&
|
) &&
|
||||||
RootWiring.Unmigrated.size == 14
|
RootWiring.Unmigrated.size == 13
|
||||||
)
|
)
|
||||||
|
|
||||||
// 一次 ReduceRoot 里多个切片各归约自己的动作,互不串片
|
// 一次 ReduceRoot 里多个切片各归约自己的动作,互不串片
|
||||||
@@ -1288,7 +1302,7 @@ object StateCheck {
|
|||||||
S5.User.Uid == "user-1" && S5.Screen.Current == NamedScreen("Preloader")
|
S5.User.Uid == "user-1" && S5.Screen.Current == NamedScreen("Preloader")
|
||||||
)
|
)
|
||||||
Check("根:无关动作返回等值状态", ReduceRoot(S5, AddFrags(1)) == S5)
|
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) })
|
val Store = ReduxStore(RootState(), { S, A -> ReduceRoot(S, A) })
|
||||||
Store.Dispatch(SetStatus("LOGGING_IN"))
|
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 }
|
val Failed = Results.filter { !it.second }
|
||||||
println("TankiOffline 状态层自检:${Results.size} 项")
|
println("TankiOffline 状态层自检:${Results.size} 项")
|
||||||
for ((Name, Ok) in Results) println((if (Ok) " ✓ " else " ✗ ") + Name)
|
for ((Name, Ok) in Results) println((if (Ok) " ✓ " else " ✗ ") + Name)
|
||||||
|
|||||||
Reference in new issue
Block a user