feat(state): 迁移 soundSettings/gameSettings/keyboardSettings/touchscreenHudSettings
This commit is contained in:
1 parent
86979eb168
commit
cade4020a5
11 files changed
+604
-51
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` 动作名。
|
||||
- 已迁移切片 **66/89**:
|
||||
- 已迁移切片 **70/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)
|
||||
@@ -350,12 +350,23 @@
|
||||
- `battleStatistics` → `jR` / `rr.fqr`(`BattleStatisticsReducer.kt`):27 字段,22 个分支。
|
||||
`FR`(14 字段的 Init)与通知切片的同名类冲突,改名为 `InitBattle`(contractState 之后复用);
|
||||
其余为战斗元信息 setter + 回合 / 统计面板 / 菜单 / 旗主 / 加载位;`SetRemainingTime` 用 `$m` 把时长转秒。
|
||||
- `soundSettings` → `Det` / `Wet().jth`(`SoundSettingsReducer.kt`):10 字段,4 个分支。
|
||||
音量缺省 100/100/50/50/50/50/50,三个开关 false/false/true;`Bet`/`Fet` 都改名为
|
||||
`ApplySoundSettings` / `SetEntranceSoundSettings`(原名都是 `UpdateSettings`,与其它设置切片同名)。
|
||||
storage 读写属 storage port,`_C`→`ResetSettingsFromStorage` 保留现有状态。
|
||||
- `gameSettings` → `c2` / `g2().zss`(`GameSettingsReducer.kt`):6 字段,2 个分支。
|
||||
五个显示开关缺省 true、`mobilePadding=null`;`v2` 同样因 `UpdateSettings` 重名改名为 `ApplyGameSettings`。
|
||||
- `keyboardSettings` → `Sut` / `bw.oth`(`KeyboardSettingsReducer.kt`):1 字段 `Map<action, Map<index, keyState>>`,5 个分支。
|
||||
`ChangeAction` 先按 keyState 从其它 index 解绑再写入新绑定;`RemoveAction` 解绑单个 index;
|
||||
`ResetAction` 依赖外部 helper,纯 reducer 保留原状态;两个默认复位清空绑定表。
|
||||
- `touchscreenHudSettings` → `j7` / `N7().xsv`(`TouchscreenHudSettingsReducer.kt`):1 字段,3 个分支。
|
||||
`C7`(原名 `UpdateSettings`)改名为 `ApplyTouchscreenHudSettings`;`E7`→`ResetTouchscreenHudMapping` 恢复默认布局。
|
||||
- `launchParams` → `(pass-through)`:原根 reducer 对 `hpx_1` 没有调用,缺省是 `ag()` 空 Map;
|
||||
`RootState.LaunchParams` 收口为 `LaunchParamsStateSlice = Map<String, String>`,不新增 reducer/动作。
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 65 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **23 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 66/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **755 项全绿**,含 89 槽位完整性、65 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 69 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **19 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 70/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **787 项全绿**,含 89 槽位完整性、69 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
以及用 `action_trace_merged.json` 真实派发的两条商店动作(`SetCoinPaymentProviderUrl` / `ToggleShopActivity`)回放。
|
||||
- 委派表里的已知形态:`shop` / `home` / `localBattleUserState` / `partner` 是内联 IIFE,
|
||||
已按字段具名为 `(inline@<field>)` 并从函数体抓到顶层动作名(69 / 1 / 2 / 11 个);
|
||||
@@ -377,6 +388,8 @@
|
||||
battlePauseState 的 2 个、battleViewState 的 12 个、tankActionsLogState 的 1 个同样按效果定名。
|
||||
clanChatState 的 3 个(`$nt`/`xnt`/`Tnt`)、battleSearchState 的 1 个也已登记。
|
||||
battleStatistics 的 12 个(含改名的 `FR`→`InitBattle`)同样按效果定名。
|
||||
设置类切片的 `_C`(共用重载)+ `Bet`/`Fet`/`Uet`/`v2`/`C7`/`E7`/`Iut` 也已登记,
|
||||
其中四个原名都是 `UpdateSettings` 的类按切片改名为 `Apply*`,避免生成物同名冲突。
|
||||
|
||||
### S4 引擎核心
|
||||
- 模块:32088(3D 数学)、92980(渲染)、61378(ECS)、55088(物理)、36659 + 71105(资源)、36734(音频)、3569(输入)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generatedAt": "2026-10-24T08:50:07.796Z",
|
||||
"generatedAt": "2026-10-24T09:04:37.952Z",
|
||||
"module": "module_10032.js",
|
||||
"RootState": {
|
||||
"Class": "z6",
|
||||
@@ -72,7 +72,11 @@
|
||||
"suppliesTutorial",
|
||||
"clanChatState",
|
||||
"battleSearchState",
|
||||
"battleStatistics"
|
||||
"battleStatistics",
|
||||
"soundSettings",
|
||||
"gameSettings",
|
||||
"keyboardSettings",
|
||||
"touchscreenHudSettings"
|
||||
],
|
||||
"AnonymousActions": [
|
||||
{
|
||||
@@ -1281,6 +1285,54 @@
|
||||
"Name": "ResetBattleStatistics",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "new jR() 整片复位"
|
||||
},
|
||||
{
|
||||
"Local": "_C",
|
||||
"Name": "ResetSettingsFromStorage",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "各设置切片共用的重载动作:sound/game/control 读 localStorage,keyboard/touchscreen 恢复默认表"
|
||||
},
|
||||
{
|
||||
"Local": "Bet",
|
||||
"Name": "ApplySoundSettings",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "听到设置整体替换(原名 UpdateSettings)"
|
||||
},
|
||||
{
|
||||
"Local": "Fet",
|
||||
"Name": "SetEntranceSoundSettings",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "入口音效开关后整体替换设置(原名 SetEntranceSoundEnabled)"
|
||||
},
|
||||
{
|
||||
"Local": "Uet",
|
||||
"Name": "EnableEntranceSound",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "isEntranceSoundOn=true(存储缺省)"
|
||||
},
|
||||
{
|
||||
"Local": "v2",
|
||||
"Name": "ApplyGameSettings",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "游戏内显示设置整体替换(原名 UpdateSettings)"
|
||||
},
|
||||
{
|
||||
"Local": "C7",
|
||||
"Name": "ApplyTouchscreenHudSettings",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "触屏布局整体替换(原名 UpdateSettings)"
|
||||
},
|
||||
{
|
||||
"Local": "E7",
|
||||
"Name": "ResetTouchscreenHudMapping",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "恢复默认触屏布局(`new j7()`)"
|
||||
},
|
||||
{
|
||||
"Local": "Iut",
|
||||
"Name": "ResetKeyMappingFromDefaults",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "恢复键位默认绑定(`rut().mu7_1`)"
|
||||
}
|
||||
],
|
||||
"Markers": [
|
||||
@@ -1726,7 +1778,6 @@
|
||||
"Actions": [
|
||||
"?QP",
|
||||
"?XP",
|
||||
"?_C",
|
||||
"?bN",
|
||||
"?fN",
|
||||
"?lN",
|
||||
@@ -1740,6 +1791,7 @@
|
||||
"CleanUsersMessage",
|
||||
"Configure",
|
||||
"IgnoreUserMessages",
|
||||
"ResetSettingsFromStorage",
|
||||
"SaveChatMessage",
|
||||
"SendMessageToServer",
|
||||
"SetMessages",
|
||||
@@ -2444,13 +2496,13 @@
|
||||
"Reducer": "Wet().jth",
|
||||
"Delegate": "Wet().jth(t, n.vpw_1)",
|
||||
"Actions": [
|
||||
"?Uet",
|
||||
"?_C",
|
||||
"SetEntranceSoundEnabled",
|
||||
"UpdateSettings"
|
||||
"ApplySoundSettings",
|
||||
"EnableEntranceSound",
|
||||
"ResetSettingsFromStorage",
|
||||
"SetEntranceSoundSettings"
|
||||
],
|
||||
"Default": "new Det()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "gameSettings",
|
||||
@@ -2459,11 +2511,11 @@
|
||||
"Reducer": "g2().zss",
|
||||
"Delegate": "g2().zss(t, n.wpw_1)",
|
||||
"Actions": [
|
||||
"?_C",
|
||||
"UpdateSettings"
|
||||
"ApplyGameSettings",
|
||||
"ResetSettingsFromStorage"
|
||||
],
|
||||
"Default": "new c2()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "battleSettings",
|
||||
@@ -2472,7 +2524,7 @@
|
||||
"Reducer": "X0().esq",
|
||||
"Delegate": "X0().esq(t, n.xpw_1)",
|
||||
"Actions": [
|
||||
"?_C",
|
||||
"ResetSettingsFromStorage",
|
||||
"UpdateSettings"
|
||||
],
|
||||
"Default": "new W0()",
|
||||
@@ -2497,7 +2549,7 @@
|
||||
"Reducer": "_2().ess",
|
||||
"Delegate": "_2().ess(t, n.zpw_1)",
|
||||
"Actions": [
|
||||
"?_C",
|
||||
"ResetSettingsFromStorage",
|
||||
"UpdateSettings"
|
||||
],
|
||||
"Default": "new i2()",
|
||||
@@ -2553,14 +2605,14 @@
|
||||
"Reducer": "bw.oth",
|
||||
"Delegate": "bw.oth(t, n.dpx_1)",
|
||||
"Actions": [
|
||||
"?Iut",
|
||||
"?_C",
|
||||
"ChangeAction",
|
||||
"RemoveAction",
|
||||
"ResetAction"
|
||||
"ResetAction",
|
||||
"ResetKeyMappingFromDefaults",
|
||||
"ResetSettingsFromStorage"
|
||||
],
|
||||
"Default": "new Sut()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "touchscreenHudSettings",
|
||||
@@ -2569,12 +2621,12 @@
|
||||
"Reducer": "N7().xsv",
|
||||
"Delegate": "N7().xsv(t, n.epx_1)",
|
||||
"Actions": [
|
||||
"?E7",
|
||||
"?_C",
|
||||
"UpdateSettings"
|
||||
"ApplyTouchscreenHudSettings",
|
||||
"ResetSettingsFromStorage",
|
||||
"ResetTouchscreenHudMapping"
|
||||
],
|
||||
"Default": "new j7()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "mainQuest",
|
||||
@@ -2864,10 +2916,10 @@
|
||||
"Delegate": "A1().dso(t, n.xpx_1)",
|
||||
"Actions": [
|
||||
"?S1",
|
||||
"?_C",
|
||||
"AddItemNotification",
|
||||
"AddItemNotifications",
|
||||
"RemoveItemNotification",
|
||||
"ResetSettingsFromStorage",
|
||||
"UpdateItemNotification"
|
||||
],
|
||||
"Default": "new _1()",
|
||||
|
||||
@@ -294,6 +294,19 @@ const AnonymousActionNames = new Map([
|
||||
['tP', 'MarkBattleLoaded'],
|
||||
['nP', 'MarkBattleUnloaded'],
|
||||
['HR', 'ResetBattleStatistics'],
|
||||
// 设置类切片的共用匿名动作与同名类:_C 是各设置切片共用的「从存储重载」动作。
|
||||
['_C', 'ResetSettingsFromStorage'],
|
||||
// soundSettings 切片(Det / Het.jth):Bet/Fet 的 toString 名都是 UpdateSettings/…,与其它设置切片同名。
|
||||
['Bet', 'ApplySoundSettings'],
|
||||
['Fet', 'SetEntranceSoundSettings'],
|
||||
['Uet', 'EnableEntranceSound'],
|
||||
// gameSettings 切片(c2 / d2.zss):v2 的 toString 名也是 UpdateSettings。
|
||||
['v2', 'ApplyGameSettings'],
|
||||
// touchscreenHudSettings 切片(j7 / P7.xsv):C7 的 toString 名也是 UpdateSettings;E7 没有 toString。
|
||||
['C7', 'ApplyTouchscreenHudSettings'],
|
||||
['E7', 'ResetTouchscreenHudMapping'],
|
||||
// keyboardSettings 切片(Sut / Nut.oth):Iut 没有 toString。
|
||||
['Iut', 'ResetKeyMappingFromDefaults'],
|
||||
]);
|
||||
|
||||
// 非动作的 `instanceof`:屏幕标识类,用于 GoTo 分支判断(不是 dispatch 的动作)。
|
||||
@@ -753,6 +766,13 @@ const Migrated = {
|
||||
clanChatState: { Type: 'ClanChatStateSlice', Reduce: 'ReduceClanChat' },
|
||||
battleSearchState: { Type: 'BattleSearchStateSlice', Reduce: 'ReduceBattleSearch' },
|
||||
battleStatistics: { Type: 'BattleStatisticsStateSlice', Reduce: 'ReduceBattleStatistics' },
|
||||
soundSettings: { Type: 'SoundSettingsStateSlice', Reduce: 'ReduceSoundSettings' },
|
||||
gameSettings: { Type: 'GameSettingsStateSlice', Reduce: 'ReduceGameSettings' },
|
||||
keyboardSettings: { Type: 'KeyboardSettingsStateSlice', Reduce: 'ReduceKeyboardSettings' },
|
||||
touchscreenHudSettings: {
|
||||
Type: 'TouchscreenHudSettingsStateSlice',
|
||||
Reduce: 'ReduceTouchscreenHudSettings',
|
||||
},
|
||||
};
|
||||
|
||||
for (const R of Rows) R.Migrated = Object.prototype.hasOwnProperty.call(Migrated, R.Field);
|
||||
@@ -1143,6 +1163,18 @@ const BattleStatisticsAnonymousEffects = {
|
||||
HR: 'new jR() 整片复位',
|
||||
};
|
||||
|
||||
// 设置类切片:_C 是共用的「从存储重载」,其余是各切片里与 UpdateSettings 同名的动作。
|
||||
const AppSettingsAnonymousEffects = {
|
||||
_C: '各设置切片共用的重载动作:sound/game/control 读 localStorage,keyboard/touchscreen 恢复默认表',
|
||||
Bet: '听到设置整体替换(原名 UpdateSettings)',
|
||||
Fet: '入口音效开关后整体替换设置(原名 SetEntranceSoundEnabled)',
|
||||
Uet: 'isEntranceSoundOn=true(存储缺省)',
|
||||
v2: '游戏内显示设置整体替换(原名 UpdateSettings)',
|
||||
C7: '触屏布局整体替换(原名 UpdateSettings)',
|
||||
E7: '恢复默认触屏布局(`new j7()`)',
|
||||
Iut: '恢复键位默认绑定(`rut().mu7_1`)',
|
||||
};
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(P, 'names', 'root_wiring.json'),
|
||||
JSON.stringify(
|
||||
@@ -1405,6 +1437,12 @@ fs.writeFileSync(
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(AppSettingsAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
],
|
||||
Markers: [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
// GameSettingsReducer.kt —— 游戏内显示设置切片(对应 module_10032 的 c2 状态 + d2.zss)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 c2:6 个字段,toString 名 "GameSettings(…)"。
|
||||
// 默认:5 个显示开关全 true、mobilePadding=null。
|
||||
// 根委派:`g2().zss(t, n.wpw_1)`。
|
||||
// reducer:
|
||||
// _C(ResetSettingsFromStorage)→ 从 localStorage 重新读
|
||||
// v2(UpdateSettings) → 整体替换设置对象
|
||||
//
|
||||
// storage 读写属 storage port 职责:`_C` 保留现有状态,`v2` 用动作携带的设置对象替换。
|
||||
package App.State.Reducers
|
||||
|
||||
/* ------------------------------------------------------------------ 动作 */
|
||||
|
||||
/** 原 `v2`(`UpdateSettings`,与其它设置切片同名):整体替换游戏内显示设置。 */
|
||||
data class ApplyGameSettings(val settings: GameSettingsStateSlice)
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class GameSettingsStateSlice(
|
||||
val ShowDropZones: Boolean = true,
|
||||
val ShowYourDrone: Boolean = true,
|
||||
val ShowChat: Boolean = true,
|
||||
val ShowNotifications: Boolean = true,
|
||||
val ShowOtherDrone: Boolean = true,
|
||||
val MobilePadding: Any? = null,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceGameSettings(
|
||||
State0: GameSettingsStateSlice,
|
||||
Action: Any,
|
||||
): GameSettingsStateSlice = when (Action) {
|
||||
is ApplyGameSettings -> Action.settings
|
||||
is ResetSettingsFromStorage -> State0
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// KeyboardSettingsReducer.kt —— 键盘按键绑定切片(对应 module_10032 的 Sut 状态 + Nut.oth)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 Sut:1 个字段,toString 名 "KeyboardSettings(mapping=…)"。
|
||||
// 默认:mapping = rut().mu7_1(内置默认绑定表)。
|
||||
// 根委派:`bw.oth(t, n.dpx_1)`。
|
||||
// reducer:
|
||||
// _C(ResetSettingsFromStorage)→ 恢复内置默认绑定(`Mut()`)
|
||||
// Iut(无 toString) → 另一个默认来源(`rut().mu7_1`)
|
||||
// Cut(ChangeAction) → 把 keyState 从其它 index 上解绑,再绑到 (action, index)
|
||||
// Eut(RemoveAction) → 解绑 (action, index);action 不存在时 no-op
|
||||
// Tut(ResetAction) → `Aut(...)`:把某个 action 的绑定重置为默认(外部 helper)
|
||||
//
|
||||
// mapping 形状:`Map<action, Map<index, keyState>>`(源码里外层 key 是 `v2()`、内层是 `Vd(index, keyState)`)。
|
||||
// storage / 输入服务的写回属 side effect,`Tut` 在纯 reducer 里保留原状态。
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.ChangeAction
|
||||
import App.State.RemoveAction
|
||||
import App.State.ResetAction
|
||||
|
||||
/* ------------------------------------------------------------------ 动作 */
|
||||
|
||||
/** 原 `Iut`:从另一个默认来源恢复绑定。 */
|
||||
object ResetKeyMappingFromDefaults
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class KeyboardSettingsStateSlice(
|
||||
val Mapping: Map<Any?, Any?> = emptyMap(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun InnerOf(Mapping: Map<Any?, Any?>, Action: Any?): Map<Any?, Any?> =
|
||||
Mapping[Action] as? Map<Any?, Any?> ?: emptyMap()
|
||||
|
||||
/** 原 `Cut` 的映射重建:每个 action 的绑定表先去掉占用同一 keyState 的项,再写入新绑定。 */
|
||||
private fun ChangeBinding(
|
||||
Mapping: Map<Any?, Any?>,
|
||||
Action: ChangeAction,
|
||||
): Map<Any?, Any?> {
|
||||
val Result = LinkedHashMap<Any?, Any?>()
|
||||
for ((ActionKey, Inner) in Mapping) {
|
||||
val Kept = LinkedHashMap<Any?, Any?>()
|
||||
for ((Index, KeyState) in (Inner as? Map<Any?, Any?> ?: emptyMap())) {
|
||||
if (KeyState != Action.keyState) Kept[Index] = KeyState
|
||||
}
|
||||
Result[ActionKey] = Kept
|
||||
}
|
||||
val Target = Result[Action.action] as? Map<Any?, Any?> ?: emptyMap()
|
||||
Result[Action.action] = Target + (Action.index to Action.keyState)
|
||||
return Result
|
||||
}
|
||||
|
||||
fun ReduceKeyboardSettings(
|
||||
State0: KeyboardSettingsStateSlice,
|
||||
Action: Any,
|
||||
): KeyboardSettingsStateSlice = when (Action) {
|
||||
// 两个默认来源在离线重建里都收口为空绑定表(storage/输入服务不在纯 reducer 内)。
|
||||
is ResetSettingsFromStorage -> KeyboardSettingsStateSlice()
|
||||
is ResetKeyMappingFromDefaults -> KeyboardSettingsStateSlice()
|
||||
is ChangeAction -> State0.copy(Mapping = ChangeBinding(State0.Mapping, Action))
|
||||
is RemoveAction -> {
|
||||
if (State0.Mapping.containsKey(Action.action)) {
|
||||
val Inner = InnerOf(State0.Mapping, Action.action) - Action.index
|
||||
State0.copy(Mapping = State0.Mapping + (Action.action to Inner))
|
||||
} else State0
|
||||
}
|
||||
is ResetAction -> State0
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// SoundSettingsReducer.kt —— 音量设置切片(对应 module_10032 的 Det 状态 + Het.jth)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 Det:10 个字段,toString 名 "SoundSettings(…)"。
|
||||
// 默认:master/ui=100,music/ambient/sfx/hitmarkPlayer/hitmarkEnemy=50,
|
||||
// mute=false、muteInBackground=false、isEntranceSoundOn=true。
|
||||
// 根委派:`Wet().jth(t, n.vpw_1)`。
|
||||
// reducer:
|
||||
// _C(ResetSettingsFromStorage) → 从 localStorage 重新读整套音量
|
||||
// Bet(UpdateSettings) → 整体替换设置对象
|
||||
// Uet(无 toString) → isEntranceSoundOn=true(从存储读默认)
|
||||
// Fet(SetEntranceSoundEnabled) → 用动作里的设置对象替换(并写回存储)
|
||||
//
|
||||
// storage 相关读写属 storage port 职责,纯 reducer 不做 IO:
|
||||
// `_C` 保留现有状态,`Bet`/`Fet` 用动作携带的设置对象整体替换。
|
||||
package App.State.Reducers
|
||||
|
||||
/* ------------------------------------------------------------------ 动作 */
|
||||
|
||||
/** 原 `Bet`(`UpdateSettings`,与其它设置切片同名):整体替换音量设置。 */
|
||||
data class ApplySoundSettings(val settings: SoundSettingsStateSlice)
|
||||
|
||||
/** 原 `Fet`(`SetEntranceSoundEnabled`):入口音效开关后整体替换设置。 */
|
||||
data class SetEntranceSoundSettings(val settings: SoundSettingsStateSlice)
|
||||
|
||||
/** 原 `Uet`:把入口音效打开(存储缺省 true)。 */
|
||||
object EnableEntranceSound
|
||||
|
||||
/** 原 `_C`:从存储重载设置;没有 storage port 时保留现有状态。 */
|
||||
object ResetSettingsFromStorage
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class SoundSettingsStateSlice(
|
||||
val MasterVolume: Double = 100.0,
|
||||
val UiVolume: Double = 100.0,
|
||||
val MusicVolume: Double = 50.0,
|
||||
val AmbientVolume: Double = 50.0,
|
||||
val SfxVolume: Double = 50.0,
|
||||
val HitmarkPlayerVolume: Double = 50.0,
|
||||
val HitmarkEnemyVolume: Double = 50.0,
|
||||
val Mute: Boolean = false,
|
||||
val MuteInBackground: Boolean = false,
|
||||
val IsEntranceSoundOn: Boolean = true,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceSoundSettings(
|
||||
State0: SoundSettingsStateSlice,
|
||||
Action: Any,
|
||||
): SoundSettingsStateSlice = when (Action) {
|
||||
is ApplySoundSettings -> Action.settings
|
||||
is SetEntranceSoundSettings -> Action.settings
|
||||
is EnableEntranceSound -> State0.copy(IsEntranceSoundOn = true)
|
||||
is ResetSettingsFromStorage -> State0
|
||||
else -> State0
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// TouchscreenHudSettingsReducer.kt —— 触屏 HUD 布局切片(对应 module_10032 的 j7 状态 + P7.xsv)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 j7:1 个字段,toString 名 "TouchscreenHudSettings(mapping=…)"。
|
||||
// 默认:mapping = c7().rsv_1。
|
||||
// 根委派:`N7().xsv(t, n.epx_1)`。
|
||||
// reducer:
|
||||
// _C(ResetSettingsFromStorage)→ 从存储读默认布局(`T7(this)`)
|
||||
// C7(UpdateSettings) → 整体替换 mapping(并写回存储)
|
||||
// E7(无 toString) → 恢复默认 mapping(`new j7()`)
|
||||
//
|
||||
// storage 读写属 storage port 职责;`_C` 与 `E7` 都收口为「恢复空 mapping」。
|
||||
package App.State.Reducers
|
||||
|
||||
/* ------------------------------------------------------------------ 动作 */
|
||||
|
||||
/** 原 `C7`(`UpdateSettings`,与其它设置切片同名):整体替换触屏布局。 */
|
||||
data class ApplyTouchscreenHudSettings(val settings: TouchscreenHudSettingsStateSlice)
|
||||
|
||||
/** 原 `E7`:恢复默认触屏布局。 */
|
||||
object ResetTouchscreenHudMapping
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class TouchscreenHudSettingsStateSlice(
|
||||
val Mapping: Map<Any?, Any?> = emptyMap(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceTouchscreenHudSettings(
|
||||
State0: TouchscreenHudSettingsStateSlice,
|
||||
Action: Any,
|
||||
): TouchscreenHudSettingsStateSlice = when (Action) {
|
||||
is ApplyTouchscreenHudSettings -> Action.settings
|
||||
is ResetTouchscreenHudMapping -> TouchscreenHudSettingsStateSlice()
|
||||
is ResetSettingsFromStorage -> TouchscreenHudSettingsStateSlice()
|
||||
else -> State0
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// RootReducer.kt —— 根 reducer 骨架(对应 module_10032 的根状态 z6 / TOState 与根 reducer k6)
|
||||
//
|
||||
// 原包 k6 对 89 个切片逐个调用各自的 reducer,再 `return n.cti(...)`(copy 出新状态)。
|
||||
// 这里采用同一形状。已迁移的 66 个切片里,65 个真正调用 reducer,launchParams 只做类型收口:
|
||||
// 这里采用同一形状。已迁移的 70 个切片里,69 个真正调用 reducer,launchParams 只做类型收口:
|
||||
//
|
||||
// inviteState → ReduceInvite(aD / pD.er5)
|
||||
// loginByPassword → ReduceLoginByPassword(gD / MD.cr6)
|
||||
@@ -68,9 +68,13 @@
|
||||
// clanChatState → ReduceClanChat(qnt / yv.qtg,根委派 `yv.qtg(t, n.ppv_1)`)
|
||||
// battleSearchState → ReduceBattleSearch(Itt / Htt().vtg,根委派 `Htt().vtg(t, n.epw_1)`)
|
||||
// battleStatistics → ReduceBattleStatistics(jR / rr.fqr,根委派 `rr.fqr(t, n.bpv_1)`)
|
||||
// soundSettings → ReduceSoundSettings(Det / Wet().jth,根委派 `Wet().jth(t, n.vpw_1)`)
|
||||
// gameSettings → ReduceGameSettings(c2 / g2().zss,根委派 `g2().zss(t, n.wpw_1)`)
|
||||
// keyboardSettings → ReduceKeyboardSettings(Sut / bw.oth,根委派 `bw.oth(t, n.dpx_1)`)
|
||||
// touchscreenHudSettings → ReduceTouchscreenHudSettings(j7 / N7().xsv,根委派 `N7().xsv(t, n.epx_1)`)
|
||||
// launchParams → 无 reducer(原根 reducer 原样透传;默认 `ag()` = emptyMap())
|
||||
//
|
||||
// 其余 23 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 其余 19 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 所以一次 copy 里串起全部已迁移 reducer,与按动作路由再归约的结果一致。
|
||||
// 迁移进度与每个字段的证据见生成物 RootWiring.kt(不要手改)。
|
||||
package App.State
|
||||
@@ -96,9 +100,11 @@ import App.State.Reducers.ReduceEventGoods
|
||||
import App.State.Reducers.ReduceGarage
|
||||
import App.State.Reducers.ReduceGaragePreview
|
||||
import App.State.Reducers.ReduceFriends
|
||||
import App.State.Reducers.ReduceGameSettings
|
||||
import App.State.Reducers.ReduceHome
|
||||
import App.State.Reducers.ReduceIcons
|
||||
import App.State.Reducers.ReduceInvite
|
||||
import App.State.Reducers.ReduceKeyboardSettings
|
||||
import App.State.Reducers.ReduceLanguage
|
||||
import App.State.Reducers.ReduceLocalBattleUser
|
||||
import App.State.Reducers.ReduceLoginByPassword
|
||||
@@ -130,11 +136,13 @@ import App.State.Reducers.ReduceSpectator
|
||||
import App.State.Reducers.ReduceSupportUrl
|
||||
import App.State.Reducers.ReduceSettings
|
||||
import App.State.Reducers.ReduceShop
|
||||
import App.State.Reducers.ReduceSoundSettings
|
||||
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.ReduceTouchscreenHudSettings
|
||||
import App.State.Reducers.ReduceTwitch
|
||||
import App.State.Reducers.ReduceTwoStepVerification
|
||||
import App.State.Reducers.ReduceUser
|
||||
@@ -219,6 +227,10 @@ object RootReducer {
|
||||
ClanChatState = ReduceClanChat(State0.ClanChatState, Action),
|
||||
BattleSearchState = ReduceBattleSearch(State0.BattleSearchState, Action),
|
||||
BattleStatistics = ReduceBattleStatistics(State0.BattleStatistics, Action),
|
||||
SoundSettings = ReduceSoundSettings(State0.SoundSettings, Action),
|
||||
GameSettings = ReduceGameSettings(State0.GameSettings, Action),
|
||||
KeyboardSettings = ReduceKeyboardSettings(State0.KeyboardSettings, Action),
|
||||
TouchscreenHudSettings = ReduceTouchscreenHudSettings(State0.TouchscreenHudSettings, Action),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,11 +24,13 @@ import App.State.Reducers.DroppableGoldStateSlice
|
||||
import App.State.Reducers.EntranceStateSlice
|
||||
import App.State.Reducers.EventGoodsStateSlice
|
||||
import App.State.Reducers.FriendsStateSlice
|
||||
import App.State.Reducers.GameSettingsStateSlice
|
||||
import App.State.Reducers.GarageStateSlice
|
||||
import App.State.Reducers.GaragePreviewStateSlice
|
||||
import App.State.Reducers.HomeStateSlice
|
||||
import App.State.Reducers.IconsStateSlice
|
||||
import App.State.Reducers.InviteStateSlice
|
||||
import App.State.Reducers.KeyboardSettingsStateSlice
|
||||
import App.State.Reducers.LobbyLoaderStateSlice
|
||||
import App.State.Reducers.LocalBattleUserStateSlice
|
||||
import App.State.Reducers.LoginByPasswordStateSlice
|
||||
@@ -56,6 +58,7 @@ import App.State.Reducers.ScreenStateSlice
|
||||
import App.State.Reducers.SecuritySettingsStateSlice
|
||||
import App.State.Reducers.SettingsStateSlice
|
||||
import App.State.Reducers.ShopStateSlice
|
||||
import App.State.Reducers.SoundSettingsStateSlice
|
||||
import App.State.Reducers.SpectatorStateSlice
|
||||
import App.State.Reducers.SuppliesStateSlice
|
||||
import App.State.Reducers.SuppliesTutorialStateSlice
|
||||
@@ -63,6 +66,7 @@ import App.State.Reducers.SupportUrlStateSlice
|
||||
import App.State.Reducers.SystemStateSlice
|
||||
import App.State.Reducers.TankActionsLogStateSlice
|
||||
import App.State.Reducers.TipsStateSlice
|
||||
import App.State.Reducers.TouchscreenHudSettingsStateSlice
|
||||
import App.State.Reducers.TwitchStateSlice
|
||||
import App.State.Reducers.TwoStepVerificationStateSlice
|
||||
import App.State.Reducers.UserStateSlice
|
||||
@@ -172,10 +176,10 @@ data class RootState(
|
||||
val Home: HomeStateSlice = HomeStateSlice(),
|
||||
/** 原 localBattleUserState(lE / (inline@localBattleUserState))。已迁移。 */
|
||||
val LocalBattleUserState: LocalBattleUserStateSlice = LocalBattleUserStateSlice(),
|
||||
/** 原 soundSettings(Det / Wet().jth)。未迁移:原样透传。 */
|
||||
val SoundSettings: Any? = null,
|
||||
/** 原 gameSettings(c2 / g2().zss)。未迁移:原样透传。 */
|
||||
val GameSettings: Any? = null,
|
||||
/** 原 soundSettings(Det / Wet().jth)。已迁移。 */
|
||||
val SoundSettings: SoundSettingsStateSlice = SoundSettingsStateSlice(),
|
||||
/** 原 gameSettings(c2 / g2().zss)。已迁移。 */
|
||||
val GameSettings: GameSettingsStateSlice = GameSettingsStateSlice(),
|
||||
/** 原 battleSettings(W0 / X0().esq)。未迁移:原样透传。 */
|
||||
val BattleSettings: Any? = null,
|
||||
/** 原 graphicsSettings(? / lc.isu)。未迁移:原样透传。 */
|
||||
@@ -188,10 +192,10 @@ data class RootState(
|
||||
val PurchaseDialogState: PurchaseDialogStateSlice = PurchaseDialogStateSlice(),
|
||||
/** 原 battleInviteState(att / Ttt().nth)。已迁移。 */
|
||||
val BattleInviteState: BattleInviteStateSlice = BattleInviteStateSlice(),
|
||||
/** 原 keyboardSettings(Sut / bw.oth)。未迁移:原样透传。 */
|
||||
val KeyboardSettings: Any? = null,
|
||||
/** 原 touchscreenHudSettings(j7 / N7().xsv)。未迁移:原样透传。 */
|
||||
val TouchscreenHudSettings: Any? = null,
|
||||
/** 原 keyboardSettings(Sut / bw.oth)。已迁移。 */
|
||||
val KeyboardSettings: KeyboardSettingsStateSlice = KeyboardSettingsStateSlice(),
|
||||
/** 原 touchscreenHudSettings(j7 / N7().xsv)。已迁移。 */
|
||||
val TouchscreenHudSettings: TouchscreenHudSettingsStateSlice = TouchscreenHudSettingsStateSlice(),
|
||||
/** 原 mainQuest(WZ / ih.bsk)。已迁移。 */
|
||||
val MainQuest: MainQuestStateSlice = MainQuestStateSlice(),
|
||||
/** 原 language(? / m6().jtg)。已迁移。 */
|
||||
|
||||
@@ -30,7 +30,7 @@ object RootWiring {
|
||||
SliceWiring("passwordChangeState", "lpv_1", "VD", "uu.pr6", "uu.pr6(t, n.lpv_1)", listOf("SetPasswordChangeHash", "ShowEmailAndPasswordChangeDialog")),
|
||||
SliceWiring("system", "mpv_1", "_9", "w9().xt9", "w9().xt9(t, n.mpv_1)", listOf("DoShowMessage", "SetFatalError")),
|
||||
SliceWiring("quests", "npv_1", "Frt", "Yrt.otg", "(null == zp && new Yrt(), zp).otg(t, n.npv_1)", listOf("GoTo", "SetCurrentCategory", "SetNotCompletedQuests")),
|
||||
SliceWiring("chatState", "opv_1", "LP", "\$r.wqv", "\$r.wqv(t, n.opv_1)", listOf("?QP", "?XP", "?_C", "?bN", "?fN", "?lN", "?nN", "?pN", "?qN", "?sN", "?vN", "?wN", "ChangeChannel", "CleanUsersMessage", "Configure", "IgnoreUserMessages", "SaveChatMessage", "SendMessageToServer", "SetMessages", "SetSelectedUid", "ShowContextMenu", "ShowUserMessages", "UpdateTypingSpeedAntifloodParams", "UpdateUsers")),
|
||||
SliceWiring("chatState", "opv_1", "LP", "\$r.wqv", "\$r.wqv(t, n.opv_1)", listOf("?QP", "?XP", "?bN", "?fN", "?lN", "?nN", "?pN", "?qN", "?sN", "?vN", "?wN", "ChangeChannel", "CleanUsersMessage", "Configure", "IgnoreUserMessages", "ResetSettingsFromStorage", "SaveChatMessage", "SendMessageToServer", "SetMessages", "SetSelectedUid", "ShowContextMenu", "ShowUserMessages", "UpdateTypingSpeedAntifloodParams", "UpdateUsers")),
|
||||
SliceWiring("clanChatState", "ppv_1", "qnt", "yv.qtg", "yv.qtg(t, n.ppv_1)", listOf("CloseClanChat", "Configure", "DoAddMessages", "OpenClanChat", "ResetClanChat")),
|
||||
SliceWiring("clan", "qpv_1", "jN", "we.hr0", "we.hr0(t, n.qpv_1)", listOf("?FM", "?IM", "?KM", "?PM", "?RM", "?VM", "?YM", "?iM", "AcceptedUserViewed", "AddIncomingClan", "AddNewIncoming", "AddNewIncomingClan", "AddOutgoingClan", "AddUsersToAccepted", "AddUsersToNewAccepted", "ClanBanned", "ClanInfoLoaded", "ClanLoaded", "ClanModalVisible", "IncomingAdded", "IncomingRemoved", "IncomingUserViewed", "MembersFetched", "NewAcceptedUserNotification", "NewClanInviteNotification", "NewIncomingUserNotification", "OutgoingAdded", "OutgoingRemoved", "RemoveIncomingClan", "RemoveNewIncoming", "RemoveNewIncomingClan", "RemoveOutgoingClan", "RemoveUserFromAccepted", "RemoveUsersFromNewAccepted", "SetClanEditPrice", "SetMinRankForCreate", "UpdateClanLicense", "UpdateClanNameValidation", "UpdateClanSearchValidation", "UpdateClanTagValidation", "UpdateHasClan", "UpdateTimeToJoinRestriction", "UpdateValidation")),
|
||||
SliceWiring("clansStorage", "rpv_1", "lO", "me.vr1", "me.vr1(t, n.rpv_1)", listOf("?mO", "AddUser", "AddUsersToNewAccepted", "BuyAdditionalPlace", "ClanLoaded", "ClanUnloaded", "ForeignClanLoaded", "MinimalRankChanged", "RecruitmentChanged", "RemoveUser", "RemoveUsersFromNewAccepted", "ShowForeignClan", "UpdateClan")),
|
||||
@@ -63,16 +63,16 @@ object RootWiring {
|
||||
SliceWiring("droppableGold", "spw_1", "Vet", "Wp.kth", "Wp.kth(t, n.spw_1)", listOf("HideDroppableGoldAuthor", "ShowDroppableGoldAuthor")),
|
||||
SliceWiring("home", "tpw_1", "s1", "(inline@home)", "(function (t, n) { return t instanceof o1 ? n.f7j(!0) : n; })(t, n.tpw_1)", listOf("ShowShopDiscountNotification")),
|
||||
SliceWiring("localBattleUserState", "upw_1", "lE", "(inline@localBattleUserState)", "(function (t, n) { return t instanceof fE ? n.xq8(t.yq8_1) : t instanceof vE ? n.xq8(cd, t.zq8_1) : n; })(t, n.upw_1)", listOf("SetLocalWeaponResistanceProperty", "SetReArmorTemporaryDisabled")),
|
||||
SliceWiring("soundSettings", "vpw_1", "Det", "Wet().jth", "Wet().jth(t, n.vpw_1)", listOf("?Uet", "?_C", "SetEntranceSoundEnabled", "UpdateSettings")),
|
||||
SliceWiring("gameSettings", "wpw_1", "c2", "g2().zss", "g2().zss(t, n.wpw_1)", listOf("?_C", "UpdateSettings")),
|
||||
SliceWiring("battleSettings", "xpw_1", "W0", "X0().esq", "X0().esq(t, n.xpw_1)", listOf("?_C", "UpdateSettings")),
|
||||
SliceWiring("soundSettings", "vpw_1", "Det", "Wet().jth", "Wet().jth(t, n.vpw_1)", listOf("ApplySoundSettings", "EnableEntranceSound", "ResetSettingsFromStorage", "SetEntranceSoundSettings")),
|
||||
SliceWiring("gameSettings", "wpw_1", "c2", "g2().zss", "g2().zss(t, n.wpw_1)", listOf("ApplyGameSettings", "ResetSettingsFromStorage")),
|
||||
SliceWiring("battleSettings", "xpw_1", "W0", "X0().esq", "X0().esq(t, n.xpw_1)", listOf("ResetSettingsFromStorage", "UpdateSettings")),
|
||||
SliceWiring("graphicsSettings", "ypw_1", "?", "lc.isu", "lc.isu(t, n.ypw_1)", listOf("UpdateSettings")),
|
||||
SliceWiring("controlSettings", "zpw_1", "i2", "_2().ess", "_2().ess(t, n.zpw_1)", listOf("?_C", "UpdateSettings")),
|
||||
SliceWiring("controlSettings", "zpw_1", "i2", "_2().ess", "_2().ess(t, n.zpw_1)", listOf("ResetSettingsFromStorage", "UpdateSettings")),
|
||||
SliceWiring("securitySettings", "apx_1", "V2", "pc.qsv", "pc.qsv(t, n.apx_1)", listOf("SetProfileBlockStatus")),
|
||||
SliceWiring("purchaseDialogState", "bpx_1", "CO", "je.ur2", "je.ur2(t, n.bpx_1)", listOf("ChangeEmailStatus", "ResetPurchaseDialog", "SuccessfullyPurchase")),
|
||||
SliceWiring("battleInviteState", "cpx_1", "att", "Ttt().nth", "Ttt().nth(t, n.cpx_1)", listOf("AddInvitedUser", "ClearSelectedForInvite", "EnableSetBattleInviteNotifications", "InvitationResponse", "RemoveUserFromInvited", "SelectUserToInvite")),
|
||||
SliceWiring("keyboardSettings", "dpx_1", "Sut", "bw.oth", "bw.oth(t, n.dpx_1)", listOf("?Iut", "?_C", "ChangeAction", "RemoveAction", "ResetAction")),
|
||||
SliceWiring("touchscreenHudSettings", "epx_1", "j7", "N7().xsv", "N7().xsv(t, n.epx_1)", listOf("?E7", "?_C", "UpdateSettings")),
|
||||
SliceWiring("keyboardSettings", "dpx_1", "Sut", "bw.oth", "bw.oth(t, n.dpx_1)", listOf("ChangeAction", "RemoveAction", "ResetAction", "ResetKeyMappingFromDefaults", "ResetSettingsFromStorage")),
|
||||
SliceWiring("touchscreenHudSettings", "epx_1", "j7", "N7().xsv", "N7().xsv(t, n.epx_1)", listOf("ApplyTouchscreenHudSettings", "ResetSettingsFromStorage", "ResetTouchscreenHudMapping")),
|
||||
SliceWiring("mainQuest", "fpx_1", "WZ", "ih.bsk", "ih.bsk(t, n.fpx_1)", listOf("AddRewardedQuest", "QuestsLoaded", "ResetQuestsLoaded", "SetBattleUpdatedQuests", "SetEventPassShopItemId", "SetQuests", "UpdateQuests")),
|
||||
SliceWiring("language", "gpx_1", "?", "m6().jtg", "m6().jtg(t, n.gpx_1)", listOf("SetLanguage")),
|
||||
SliceWiring("launchParams", "hpx_1", "?", "(pass-through)", "n.hpx_1", listOf()),
|
||||
@@ -91,7 +91,7 @@ object RootWiring {
|
||||
SliceWiring("rewardedVideosState", "upx_1", "JQ", "xh.zsl", "xh.zsl(t, n.upx_1)", listOf("SetDisplayState")),
|
||||
SliceWiring("twitchState", "vpx_1", "g9", "uf.gta", "uf.gta(t, n.vpx_1)", listOf("SetAccount", "SetDaysForNextLinking", "SetTwitchEnabled")),
|
||||
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("itemNotifications", "xpx_1", "_1", "A1().dso", "A1().dso(t, n.xpx_1)", listOf("?S1", "AddItemNotification", "AddItemNotifications", "RemoveItemNotification", "ResetSettingsFromStorage", "UpdateItemNotification")),
|
||||
SliceWiring("contextTutorial", "ypx_1", "Mst", "Jst().tth", "Jst().tth(t, n.ypx_1)", listOf("LoadCurrentElement", "MarkElementAsViewed", "SetLoadedElements", "SetMissionToElement", "SetUnViewedElements")),
|
||||
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")),
|
||||
@@ -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")
|
||||
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")
|
||||
|
||||
/** 未迁移字段:归约时原样透传,作为后续迁移清单。 */
|
||||
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;
|
||||
// BattlePause / BattleView / TankActionsLog / SuppliesTutorial / ClanChat / BattleSearch / BattleStatistics / SoundSettings / GameSettings / KeyboardSettings / TouchscreenHudSettings;
|
||||
// ㉑ launchParams 是纯透传切片(无 reducer/动作),只做 Map 类型收口;⑭ 根 reducer 的 89 槽位委派
|
||||
//
|
||||
// 用法:$env:TANKIOFFLINE_STATE_TEST='1'; node …(见 TankiOffline/tools/RunStateTest.ps1)
|
||||
@@ -667,6 +667,25 @@ import App.State.Reducers.ResetBattleStatistics
|
||||
import App.State.Reducers.ResetRoundState
|
||||
import App.State.Reducers.ShowStat
|
||||
import App.State.Reducers.ToggleStatMenu
|
||||
import App.State.ChangeAction
|
||||
import App.State.RemoveAction
|
||||
import App.State.ResetAction
|
||||
import App.State.Reducers.ApplyGameSettings
|
||||
import App.State.Reducers.ApplySoundSettings
|
||||
import App.State.Reducers.ApplyTouchscreenHudSettings
|
||||
import App.State.Reducers.EnableEntranceSound
|
||||
import App.State.Reducers.GameSettingsStateSlice
|
||||
import App.State.Reducers.KeyboardSettingsStateSlice
|
||||
import App.State.Reducers.ReduceGameSettings
|
||||
import App.State.Reducers.ReduceKeyboardSettings
|
||||
import App.State.Reducers.ReduceSoundSettings
|
||||
import App.State.Reducers.ReduceTouchscreenHudSettings
|
||||
import App.State.Reducers.ResetKeyMappingFromDefaults
|
||||
import App.State.Reducers.ResetSettingsFromStorage
|
||||
import App.State.Reducers.ResetTouchscreenHudMapping
|
||||
import App.State.Reducers.SetEntranceSoundSettings
|
||||
import App.State.Reducers.SoundSettingsStateSlice
|
||||
import App.State.Reducers.TouchscreenHudSettingsStateSlice
|
||||
import App.State.Reducers.UserRankBounds
|
||||
import App.State.Reducers.UserStateSlice
|
||||
import App.State.Reducers.ClearHullData
|
||||
@@ -1094,7 +1113,7 @@ object StateCheck {
|
||||
Check("切片 LocalBattleUser:接 Store 派发后状态已归约", Store.State.IsReArmorTemporaryDisabled)
|
||||
}
|
||||
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 66 个已迁移切片(65 归约 + launchParams 透传)
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 70 个已迁移切片(69 归约 + launchParams 透传)
|
||||
run {
|
||||
Check("根:根状态 89 个切片槽位", RootWiring.All.size == 89)
|
||||
Check(
|
||||
@@ -1158,7 +1177,7 @@ object StateCheck {
|
||||
LocalBattleW.Reducer == "(inline@localBattleUserState)"
|
||||
)
|
||||
Check(
|
||||
"根:迁移表 = 66 个已迁移字段,其余 23 个待迁",
|
||||
"根:迁移表 = 70 个已迁移字段,其余 19 个待迁",
|
||||
RootReducer.Migrated ==
|
||||
setOf(
|
||||
"inviteState", "loginByPassword", "twitchState", "home",
|
||||
@@ -1179,8 +1198,9 @@ object StateCheck {
|
||||
"partner", "userRenameState",
|
||||
"battlePauseState", "battleViewState", "tankActionsLogState", "suppliesTutorial",
|
||||
"clanChatState", "battleSearchState", "battleStatistics",
|
||||
"soundSettings", "gameSettings", "keyboardSettings", "touchscreenHudSettings",
|
||||
) &&
|
||||
RootWiring.Unmigrated.size == 23
|
||||
RootWiring.Unmigrated.size == 19
|
||||
)
|
||||
|
||||
// 一次 ReduceRoot 里多个切片各归约自己的动作,互不串片
|
||||
@@ -1236,7 +1256,7 @@ object StateCheck {
|
||||
S5.User.Uid == "user-1" && S5.Screen.Current == NamedScreen("Preloader")
|
||||
)
|
||||
Check("根:无关动作返回等值状态", ReduceRoot(S5, AddFrags(1)) == S5)
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 66/89")
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 70/89")
|
||||
|
||||
val Store = ReduxStore(RootState(), { S, A -> ReduceRoot(S, A) })
|
||||
Store.Dispatch(SetStatus("LOGGING_IN"))
|
||||
@@ -5742,6 +5762,211 @@ object StateCheck {
|
||||
)
|
||||
}
|
||||
|
||||
// 77 切片 reducer:SoundSettings(Det / Wet().jth,10 字段;4 个动作)
|
||||
run {
|
||||
val S0 = SoundSettingsStateSlice()
|
||||
Check(
|
||||
"切片 SoundSettings:默认音量与开关",
|
||||
S0.MasterVolume == 100.0 && S0.UiVolume == 100.0 &&
|
||||
S0.MusicVolume == 50.0 && S0.AmbientVolume == 50.0 &&
|
||||
S0.SfxVolume == 50.0 && S0.HitmarkPlayerVolume == 50.0 &&
|
||||
S0.HitmarkEnemyVolume == 50.0 && !S0.Mute &&
|
||||
!S0.MuteInBackground && S0.IsEntranceSoundOn
|
||||
)
|
||||
val Custom = SoundSettingsStateSlice(
|
||||
MasterVolume = 10.0, UiVolume = 20.0, MusicVolume = 30.0,
|
||||
AmbientVolume = 40.0, SfxVolume = 25.0, HitmarkPlayerVolume = 15.0,
|
||||
HitmarkEnemyVolume = 5.0, Mute = true, MuteInBackground = true,
|
||||
IsEntranceSoundOn = false,
|
||||
)
|
||||
Check(
|
||||
"切片 SoundSettings:ApplySoundSettings 整体替换",
|
||||
ReduceSoundSettings(S0, ApplySoundSettings(Custom)) == Custom
|
||||
)
|
||||
Check(
|
||||
"切片 SoundSettings:SetEntranceSoundSettings 整体替换",
|
||||
ReduceSoundSettings(S0, SetEntranceSoundSettings(Custom)) == Custom
|
||||
)
|
||||
Check(
|
||||
"切片 SoundSettings:EnableEntranceSound 只开入口音效",
|
||||
ReduceSoundSettings(Custom, EnableEntranceSound)
|
||||
.let { it.IsEntranceSoundOn && it.Mute }
|
||||
)
|
||||
Check(
|
||||
"切片 SoundSettings:ResetSettingsFromStorage 不做 IO、保留状态",
|
||||
ReduceSoundSettings(Custom, ResetSettingsFromStorage) == Custom
|
||||
)
|
||||
Check(
|
||||
"切片 SoundSettings:无关动作不改状态",
|
||||
ReduceSoundSettings(Custom, AddFrags(1)) == Custom
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, EnableEntranceSound)
|
||||
Check(
|
||||
"根:EnableEntranceSound 只动 soundSettings",
|
||||
Root1.SoundSettings.IsEntranceSoundOn &&
|
||||
Root1.GameSettings == Root0.GameSettings
|
||||
)
|
||||
val W = RootWiring.ByField("soundSettings")!!
|
||||
Check(
|
||||
"根:soundSettings 委派到 Det / Wet().jth 且 4 个动作",
|
||||
W.SliceClass == "Det" && W.Reducer == "Wet().jth" &&
|
||||
W.Actions.toSet() == setOf(
|
||||
"ApplySoundSettings", "SetEntranceSoundSettings", "EnableEntranceSound",
|
||||
"ResetSettingsFromStorage",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// 78 切片 reducer:GameSettings(c2 / g2().zss,6 字段;2 个动作)
|
||||
run {
|
||||
val S0 = GameSettingsStateSlice()
|
||||
Check(
|
||||
"切片 GameSettings:默认五个开关全开、padding 为 null",
|
||||
S0.ShowDropZones && S0.ShowYourDrone && S0.ShowChat &&
|
||||
S0.ShowNotifications && S0.ShowOtherDrone && S0.MobilePadding == null
|
||||
)
|
||||
val Custom = GameSettingsStateSlice(
|
||||
ShowDropZones = false, ShowYourDrone = false, ShowChat = false,
|
||||
ShowNotifications = false, ShowOtherDrone = false, MobilePadding = 32,
|
||||
)
|
||||
Check(
|
||||
"切片 GameSettings:ApplyGameSettings 整体替换",
|
||||
ReduceGameSettings(S0, ApplyGameSettings(Custom)) == Custom
|
||||
)
|
||||
Check(
|
||||
"切片 GameSettings:ResetSettingsFromStorage 保留状态",
|
||||
ReduceGameSettings(Custom, ResetSettingsFromStorage) == Custom
|
||||
)
|
||||
Check(
|
||||
"切片 GameSettings:无关动作不改状态",
|
||||
ReduceGameSettings(Custom, AddFrags(1)) == Custom
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, ApplyGameSettings(Custom))
|
||||
Check(
|
||||
"根:ApplyGameSettings 只动 gameSettings",
|
||||
Root1.GameSettings == Custom && Root1.KeyboardSettings == Root0.KeyboardSettings
|
||||
)
|
||||
val W = RootWiring.ByField("gameSettings")!!
|
||||
Check(
|
||||
"根:gameSettings 委派到 c2 / g2().zss 且 2 个动作",
|
||||
W.SliceClass == "c2" && W.Reducer == "g2().zss" &&
|
||||
W.Actions.toSet() == setOf("ApplyGameSettings", "ResetSettingsFromStorage")
|
||||
)
|
||||
}
|
||||
|
||||
// 79 切片 reducer:KeyboardSettings(Sut / bw.oth,1 字段;5 个动作)
|
||||
run {
|
||||
val S0 = KeyboardSettingsStateSlice()
|
||||
Check("切片 KeyboardSettings:默认空绑定表", S0.Mapping.isEmpty())
|
||||
val S1 = ReduceKeyboardSettings(S0, ChangeAction("fire", 0, "KeyF"))
|
||||
Check(
|
||||
"切片 KeyboardSettings:ChangeAction 写入 action→index→keyState",
|
||||
S1.Mapping == mapOf<Any?, Any?>(
|
||||
"fire" to mapOf<Any?, Any?>(0 to "KeyF"),
|
||||
)
|
||||
)
|
||||
val S2 = ReduceKeyboardSettings(S1, ChangeAction("fire", 1, "KeyG"))
|
||||
Check(
|
||||
"切片 KeyboardSettings:同一 action 不同 index 追加绑定",
|
||||
S2.Mapping == mapOf<Any?, Any?>(
|
||||
"fire" to mapOf<Any?, Any?>(0 to "KeyF", 1 to "KeyG"),
|
||||
)
|
||||
)
|
||||
Check(
|
||||
"切片 KeyboardSettings:同一 keyState 从别的 action 上解绑",
|
||||
ReduceKeyboardSettings(
|
||||
ReduceKeyboardSettings(S0, ChangeAction("fire", 0, "KeyF")),
|
||||
ChangeAction("jump", 0, "KeyF"),
|
||||
).Mapping == mapOf<Any?, Any?>(
|
||||
"fire" to emptyMap<Any?, Any?>(),
|
||||
"jump" to mapOf<Any?, Any?>(0 to "KeyF"),
|
||||
)
|
||||
)
|
||||
Check(
|
||||
"切片 KeyboardSettings:RemoveAction 解绑一个 index",
|
||||
ReduceKeyboardSettings(S2, RemoveAction("fire", 1)).Mapping ==
|
||||
mapOf<Any?, Any?>("fire" to mapOf<Any?, Any?>(0 to "KeyF"))
|
||||
)
|
||||
Check(
|
||||
"切片 KeyboardSettings:RemoveAction 对未知 action 是 no-op",
|
||||
ReduceKeyboardSettings(S2, RemoveAction("nope", 0)) == S2
|
||||
)
|
||||
Check(
|
||||
"切片 KeyboardSettings:ResetAction 保留状态(外部 helper)",
|
||||
ReduceKeyboardSettings(S2, ResetAction("fire")) == S2
|
||||
)
|
||||
Check(
|
||||
"切片 KeyboardSettings:两个默认复位都清空绑定表",
|
||||
ReduceKeyboardSettings(S2, ResetSettingsFromStorage) ==
|
||||
KeyboardSettingsStateSlice() &&
|
||||
ReduceKeyboardSettings(S2, ResetKeyMappingFromDefaults) ==
|
||||
KeyboardSettingsStateSlice()
|
||||
)
|
||||
Check(
|
||||
"切片 KeyboardSettings:无关动作不改状态",
|
||||
ReduceKeyboardSettings(S2, AddFrags(1)) == S2
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, RemoveAction("fire", 1))
|
||||
Check(
|
||||
"根:RemoveAction 只动 keyboardSettings",
|
||||
Root1.KeyboardSettings == KeyboardSettingsStateSlice() &&
|
||||
Root1.TouchscreenHudSettings == Root0.TouchscreenHudSettings
|
||||
)
|
||||
val W = RootWiring.ByField("keyboardSettings")!!
|
||||
Check(
|
||||
"根:keyboardSettings 委派到 Sut / bw.oth 且 5 个动作",
|
||||
W.SliceClass == "Sut" && W.Reducer == "bw.oth" && W.Actions.size == 5
|
||||
)
|
||||
}
|
||||
|
||||
// 80 切片 reducer:TouchscreenHudSettings(j7 / N7().xsv,1 字段;3 个动作)
|
||||
run {
|
||||
val S0 = TouchscreenHudSettingsStateSlice()
|
||||
Check("切片 TouchscreenHudSettings:默认空布局", S0.Mapping.isEmpty())
|
||||
val Custom = TouchscreenHudSettingsStateSlice(mapOf<Any?, Any?>("fire" to 1))
|
||||
Check(
|
||||
"切片 TouchscreenHudSettings:ApplyTouchscreenHudSettings 整体替换",
|
||||
ReduceTouchscreenHudSettings(S0, ApplyTouchscreenHudSettings(Custom)) == Custom
|
||||
)
|
||||
Check(
|
||||
"切片 TouchscreenHudSettings:ResetTouchscreenHudMapping 恢复默认",
|
||||
ReduceTouchscreenHudSettings(Custom, ResetTouchscreenHudMapping) ==
|
||||
TouchscreenHudSettingsStateSlice()
|
||||
)
|
||||
Check(
|
||||
"切片 TouchscreenHudSettings:ResetSettingsFromStorage 恢复默认",
|
||||
ReduceTouchscreenHudSettings(Custom, ResetSettingsFromStorage) ==
|
||||
TouchscreenHudSettingsStateSlice()
|
||||
)
|
||||
Check(
|
||||
"切片 TouchscreenHudSettings:无关动作不改状态",
|
||||
ReduceTouchscreenHudSettings(Custom, AddFrags(1)) == Custom
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, ResetTouchscreenHudMapping)
|
||||
Check(
|
||||
"根:ResetTouchscreenHudMapping 只动 touchscreenHudSettings",
|
||||
Root1.TouchscreenHudSettings == TouchscreenHudSettingsStateSlice() &&
|
||||
Root1.SoundSettings == Root0.SoundSettings
|
||||
)
|
||||
val W = RootWiring.ByField("touchscreenHudSettings")!!
|
||||
Check(
|
||||
"根:touchscreenHudSettings 委派到 j7 / N7().xsv 且 3 个动作",
|
||||
W.SliceClass == "j7" && W.Reducer == "N7().xsv" &&
|
||||
W.Actions.toSet() == setOf(
|
||||
"ApplyTouchscreenHudSettings", "ResetTouchscreenHudMapping",
|
||||
"ResetSettingsFromStorage",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
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