feat(state): 迁移 system/contextTutorial/battleTutorial/spectator/twoStepVerificationState/antiAddiction/moderation/migrationState/register/userReportsState
This commit is contained in:
1 parent
8633fc91c1
commit
af005ab019
18 files changed
+2030
-95
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` 动作名。
|
||||
- 已迁移切片 **43/89**:
|
||||
- 已迁移切片 **53/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)
|
||||
@@ -279,12 +279,42 @@
|
||||
新增枚举 `RewardVideoDisplayState { NONE, LOADING, DISPLAY }`,缺省 `NONE`;`SetDisplayState` 整体替换。
|
||||
- `passwordChangeState` → `VD` / `uu.pr6`(`PasswordChangeReducer.kt`):3 个字符串字段(hash / uid / email),
|
||||
缺省全为空串;`SetPasswordChangeHash` 只写 hash,`ShowEmailAndPasswordChangeDialog` 写 uid/email 并保留 hash。
|
||||
- `system` → `_9` / `w9().xt9`(`SystemReducer.kt`):3 字段,2 个分支。
|
||||
`DoShowMessage(message, restart)` 写前两字段,`SetFatalError` 只写 `fatalError`。
|
||||
- `contextTutorial` → `Mst` / `Jst().tth`(`ContextTutorialReducer.kt`):4 字段,5 个分支。
|
||||
`MarkElementAsViewed` 从 `unViewedElements` 删一个元素(`Ym`),其余为整表 / 整 Map 替换。
|
||||
- `battleTutorial` → `rE` / `Q.sq8`(`BattleTutorialReducer.kt`):3 字段,4 个分支。
|
||||
`oE`→`MarkMovementStarted` 置 `movementHasStarted`,`sE`→`ResetBattleTutorial` 整片复位。
|
||||
- `spectator` → `HA` / `Li.jqm`(`SpectatorReducer.kt`):4 字段,6 个分支。
|
||||
`JA`→`AddSpectator` 追加 `SpectatorInfo`(复用生成物里的同名模型),`ZA`→`RemoveSpectator` 按 userId 过滤,
|
||||
`XA`→`SetSpectators` 整表替换,`YA`→`SetSpectatorsListVisible`。
|
||||
`spectatorHudLayout` 的原模型是 15 字段的 HUD 布局对象(战斗层),按 `Any?` 收口,缺省 null。
|
||||
- `twoStepVerificationState` → `x9` / `_f.atb`(`TwoStepVerificationReducer.kt`):6 字段,5 个分支。
|
||||
`VerificationStatus` 三态:null 清空、false 写失败、true 直接把 `isActivated2FA` 置 true(原 `rta(cd, !0)`)。
|
||||
- `antiAddiction` → `UC` / `W.iq8`(`AntiAddictionReducer.kt`):8 字段,5 个分支。
|
||||
`FC`→`EnableRealNameCheck`、`XC`→`RequireUserIdVerification`(同时置 `unknownUserId`)、
|
||||
`YC`→`UpdatePlayingTime`;`SetRealNameAndIdNumber` 的参数为 null 时保留原值。
|
||||
- `moderation` → `NI` / `Ei.oqh`(`ModerationReducer.kt`):11 字段,13 个分支。
|
||||
选中用户列表用 `ModerationUserRecord` 收口:`GI`/`WI` 先按 userId 去重再追加,`KI` 删除,`YI`/`uA` 清空;
|
||||
`XI`/`JI` 与 `ZI`/`QI` 分别是战斗信息面板、系统消息的显示/收起,`tA`/`nA` 是封禁菜单。
|
||||
`battleInfo` 的原模型 `MI` 有 13 字段(战斗层),按 `Any?` 收口。
|
||||
- `migrationState` → `$it` / `Uv.rtg`(`MigrationStateReducer.kt`):7 字段,11 个分支。
|
||||
新增 `MigrationLoginStatus { UNKNOWN, FREE, INCORRECT, BUSY, SHORT_NAME }` 与
|
||||
`MigrationRegisterStatus { UNKNOWN, PASSWORD_CORRECT, PASSWORD_INCORRECT, FAILED }`(对应源码 `Eit()` / `Iit()`)。
|
||||
`SetUid` / `ForceSetUid` / `SetPassword` 与注册、登录切片共用同一批动作类,因此几片 reducer 同时响应、各自动自己的字段。
|
||||
- `register` → `Cit` / `cp.stg`(`RegisterReducer.kt`):16 字段,19 个分支。
|
||||
新增 `UidStatus`、`RegistrationStatus` 两个枚举;`SetUid` / `ForceSetUid` 会复位 uid 校验状态,
|
||||
且只有原状态不是 `INCORRECT` 时才把 `registerStatus` 一起打回 `UNKNOWN`(原 `2 === n.wtr_1.k3_1` 分支)。
|
||||
- `userReportsState` → `Zst` / `qot.zth`(`UserReportsReducer.kt`):5 字段,6 个分支。
|
||||
新增 `ReportKind { BATTLE_NAME, LOBBY_CHAT_MESSAGE, BATTLE_CHAT_MESSAGE }` 与 `ReportEntry(kind, targetId, expireTime)`;
|
||||
三类举报都追加一条记录、有效期 +1 天。原 reducer 还把列表写回 localStorage 的 `SENT_REPORTS`,
|
||||
属 storage port 职责,纯 reducer 不做 IO(Init 保留现有列表)。
|
||||
- `launchParams` → `(pass-through)`:原根 reducer 对 `hpx_1` 没有调用,缺省是 `ag()` 空 Map;
|
||||
`RootState.LaunchParams` 收口为 `LaunchParamsStateSlice = Map<String, String>`,不新增 reducer/动作。
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 42 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **46 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 43/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **529 项全绿**,含 89 槽位完整性、42 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 52 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **36 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 53/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **627 项全绿**,含 89 槽位完整性、52 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
以及用 `action_trace_merged.json` 真实派发的两条商店动作(`SetCoinPaymentProviderUrl` / `ToggleShopActivity`)回放。
|
||||
- 委派表里的已知形态:`shop` / `home` / `localBattleUserState` / `partner` 是内联 IIFE,
|
||||
已按字段具名为 `(inline@<field>)` 并从函数体抓到顶层动作名(69 / 1 / 2 / 11 个);
|
||||
@@ -298,7 +328,9 @@
|
||||
language 的 1 个、announcement 的 3 个、news 的 3 个(含两个单例)、notifications 的 2 个、
|
||||
quests 的 1 个、lobbyLoader 的 2 个、purchaseDialogState 的 1 个、supportUrl 的 1 个、
|
||||
notificationByCountry 的 1 个、mainQuest 的 1 个、rankUpDialogState 的 1 个、battleResult 的 3 个、
|
||||
captchaState 的 5 个、modalScreen 的 1 个、droppableGold 的 2 个、creatorTagState 的 1 个匿名类 / 单例同样按效果定名并登记。
|
||||
captchaState 的 5 个、modalScreen 的 1 个、droppableGold 的 2 个、creatorTagState 的 1 个、
|
||||
battleTutorial 的 2 个、spectator 的 4 个、antiAddiction 的 3 个、moderation 的 13 个、
|
||||
迁移 / 注册共用的 10 个(`Mit`…`_rt`)匿名类 / 单例同样按效果定名并登记。
|
||||
|
||||
### S4 引擎核心
|
||||
- 模块:32088(3D 数学)、92980(渲染)、61378(ECS)、55088(物理)、36659 + 71105(资源)、36734(音频)、3569(输入)
|
||||
|
||||
+256
-54
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generatedAt": "2026-10-24T06:30:01.615Z",
|
||||
"generatedAt": "2026-10-24T07:23:39.141Z",
|
||||
"module": "module_10032.js",
|
||||
"RootState": {
|
||||
"Class": "z6",
|
||||
@@ -49,7 +49,17 @@
|
||||
"eventGoods",
|
||||
"creatorTagState",
|
||||
"rewardedVideosState",
|
||||
"passwordChangeState"
|
||||
"passwordChangeState",
|
||||
"system",
|
||||
"contextTutorial",
|
||||
"battleTutorial",
|
||||
"spectator",
|
||||
"twoStepVerificationState",
|
||||
"antiAddiction",
|
||||
"moderation",
|
||||
"migrationState",
|
||||
"register",
|
||||
"userReportsState"
|
||||
],
|
||||
"AnonymousActions": [
|
||||
{
|
||||
@@ -796,6 +806,198 @@
|
||||
"Name": "ClearCreatorTag",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "creatorTag=null(`n.ar2(null)`)"
|
||||
},
|
||||
{
|
||||
"Local": "oE",
|
||||
"Name": "MarkMovementStarted",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "movementHasStarted=true(`n.pq8(cd, cd, !0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "sE",
|
||||
"Name": "ResetBattleTutorial",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "new rE() 整片复位(`new rE()`)"
|
||||
},
|
||||
{
|
||||
"Local": "XA",
|
||||
"Name": "SetSpectators",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "spectators=整表(`n.yql(cd, cd, t.dqm_1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "JA",
|
||||
"Name": "AddSpectator",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "spectators += `new iR(userId, uid, inSupportGroup, inPunishersGroup)`(`Hg`)"
|
||||
},
|
||||
{
|
||||
"Local": "ZA",
|
||||
"Name": "RemoveSpectator",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "spectators 按 userId 过滤掉一条(`Qd(s.kqm_1, t.iqm_1) || e.y(s)`)"
|
||||
},
|
||||
{
|
||||
"Local": "YA",
|
||||
"Name": "SetSpectatorsListVisible",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "spectatorsListVisible=布尔(`n.yql(cd, cd, cd, t.cqm_1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "FC",
|
||||
"Name": "EnableRealNameCheck",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "isEnableRealNameCheck=true(`n.lq7(!0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "XC",
|
||||
"Name": "RequireUserIdVerification",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "unknownUserId=true、urlForEnterUserId=参数(`n.lq7(cd, !0, t.hq8_1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "YC",
|
||||
"Name": "UpdatePlayingTime",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "playingTimeInMinutes、alertMessage(`n.lq7(cd, cd, cd, t.fq8_1, t.gq8_1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "UI",
|
||||
"Name": "SetModeratorModes",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "moderatorMode / battleModeratorMode / eventOrganizerMode(`n.aqf(a, b, c)`)"
|
||||
},
|
||||
{
|
||||
"Local": "FI",
|
||||
"Name": "SetModerationUrlTemplates",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "两个 URL 模板(`n.aqf(cd, cd, cd, t.vqg_1, t.wqg_1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "XI",
|
||||
"Name": "ShowBattleInfo",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "battleInfo + forceShowBattleInfo=true(`n.aqf(…, t.fqh_1, !0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "JI",
|
||||
"Name": "HideBattleInfo",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "forceShowBattleInfo=false(`n.aqf(…, !1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "GI",
|
||||
"Name": "AddSelectedUser",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "selectedUsers 去重后追加 `new OI(...)`(`Hg(e, new OI(...))`)"
|
||||
},
|
||||
{
|
||||
"Local": "WI",
|
||||
"Name": "AddSelectedUserFromChat",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "同 GI,另一个派发点(`Hg(_, new OI(...))`)"
|
||||
},
|
||||
{
|
||||
"Local": "KI",
|
||||
"Name": "RemoveSelectedUser",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "selectedUsers 按 userId 过滤(`Qd(v.oqf_1, t.eqh_1) || l.y(v)`)"
|
||||
},
|
||||
{
|
||||
"Local": "YI",
|
||||
"Name": "ClearSelectedUsers",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "selectedUsers 清空(`var p = md()`)"
|
||||
},
|
||||
{
|
||||
"Local": "uA",
|
||||
"Name": "ResetSelectedUsers",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "selectedUsers 清空(`var w = md()`,另一个派发点)"
|
||||
},
|
||||
{
|
||||
"Local": "ZI",
|
||||
"Name": "ShowModerationSystemMessage",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "systemMessage + forceShowSystemMessage=true(`n.aqf(…, t.gqh_1, !0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "QI",
|
||||
"Name": "HideModerationSystemMessage",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "forceShowSystemMessage=false(`n.aqf(…, !1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "tA",
|
||||
"Name": "ShowBlockUserMenu",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "forceShowBlockUserMenu=true(`n.aqf(…, !0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "nA",
|
||||
"Name": "HideBlockUserMenu",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "forceShowBlockUserMenu=false(`n.aqf(…, !1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "Mit",
|
||||
"Name": "DisableRegister",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "isDisabled=true(`n.its(!0)`,只有注册切片读)"
|
||||
},
|
||||
{
|
||||
"Local": "Dit",
|
||||
"Name": "UidIsFree",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "loginStatus / uidValidationStatus = FREE(`lrt()`)"
|
||||
},
|
||||
{
|
||||
"Local": "Lit",
|
||||
"Name": "UidIsIncorrect",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "loginStatus / uidValidationStatus = INCORRECT(`frt()`)"
|
||||
},
|
||||
{
|
||||
"Local": "Bit",
|
||||
"Name": "ResetUidStatus",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "loginStatus / uidValidationStatus = UNKNOWN(`crt()`)"
|
||||
},
|
||||
{
|
||||
"Local": "Hit",
|
||||
"Name": "UidTooShort",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "loginStatus / uidValidationStatus = SHORT_NAME(`prt()`)"
|
||||
},
|
||||
{
|
||||
"Local": "Uit",
|
||||
"Name": "RegisterPasswordCorrect",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "registerStatus=PASSWORD_CORRECT(`(Iit(), Xv)`,只有注册切片读)"
|
||||
},
|
||||
{
|
||||
"Local": "Fit",
|
||||
"Name": "RegisterPasswordIncorrect",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "registerStatus=PASSWORD_INCORRECT(`drt()`)"
|
||||
},
|
||||
{
|
||||
"Local": "Git",
|
||||
"Name": "RegisterFailed",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "registerStatus=FAILED(`grt()`)"
|
||||
},
|
||||
{
|
||||
"Local": "hrt",
|
||||
"Name": "ResetRegisterStatus",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "registerStatus=UNKNOWN(`n.its(cd, cd, cd, cd, cd, wrt())`,只有注册切片读)"
|
||||
},
|
||||
{
|
||||
"Local": "_rt",
|
||||
"Name": "ResetAuthenticationForm",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "login=\"\"、两个状态复位(两个切片都读)"
|
||||
}
|
||||
],
|
||||
"Markers": [
|
||||
@@ -958,13 +1160,13 @@
|
||||
"Reducer": "Q.sq8",
|
||||
"Delegate": "Q.sq8(t, n.cpv_1)",
|
||||
"Actions": [
|
||||
"?oE",
|
||||
"?sE",
|
||||
"MarkMovementStarted",
|
||||
"ResetBattleTutorial",
|
||||
"SetFragsCount",
|
||||
"ShowMessage"
|
||||
],
|
||||
"Default": "new rE()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "garage",
|
||||
@@ -1115,28 +1317,28 @@
|
||||
"Reducer": "cp.stg",
|
||||
"Delegate": "cp.stg(t, n.hpv_1)",
|
||||
"Actions": [
|
||||
"?Bit",
|
||||
"?Dit",
|
||||
"?Fit",
|
||||
"?Git",
|
||||
"?Hit",
|
||||
"?Lit",
|
||||
"?Mit",
|
||||
"?Uit",
|
||||
"?_rt",
|
||||
"?hrt",
|
||||
"DisableRegister",
|
||||
"EnteredUidIsBusy",
|
||||
"ForceSetUid",
|
||||
"ReceiveOAuthUri",
|
||||
"RegisterFailed",
|
||||
"RegisterPasswordCorrect",
|
||||
"RegisterPasswordIncorrect",
|
||||
"ResetAuthenticationForm",
|
||||
"ResetRegisterStatus",
|
||||
"ResetUidStatus",
|
||||
"SetOpenedPassword",
|
||||
"SetPassword",
|
||||
"SetPasswordRestrictions",
|
||||
"SetUid",
|
||||
"SocialNetworkAvailability",
|
||||
"SocialNetworkClientIds"
|
||||
"SocialNetworkClientIds",
|
||||
"UidIsFree",
|
||||
"UidIsIncorrect",
|
||||
"UidTooShort"
|
||||
],
|
||||
"Default": "new Cit()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "migrationState",
|
||||
@@ -1145,20 +1347,20 @@
|
||||
"Reducer": "Uv.rtg",
|
||||
"Delegate": "Uv.rtg(t, n.ipv_1)",
|
||||
"Actions": [
|
||||
"?Bit",
|
||||
"?Dit",
|
||||
"?Fit",
|
||||
"?Git",
|
||||
"?Hit",
|
||||
"?Lit",
|
||||
"?_rt",
|
||||
"EnteredUidIsBusy",
|
||||
"ForceSetUid",
|
||||
"RegisterFailed",
|
||||
"RegisterPasswordIncorrect",
|
||||
"ResetAuthenticationForm",
|
||||
"ResetUidStatus",
|
||||
"SetPassword",
|
||||
"SetUid"
|
||||
"SetUid",
|
||||
"UidIsFree",
|
||||
"UidIsIncorrect",
|
||||
"UidTooShort"
|
||||
],
|
||||
"Default": "new $it()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "inviteState",
|
||||
@@ -1216,7 +1418,7 @@
|
||||
"SetFatalError"
|
||||
],
|
||||
"Default": "new _9()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "quests",
|
||||
@@ -2178,14 +2380,14 @@
|
||||
"Reducer": "W.iq8",
|
||||
"Delegate": "W.iq8(t, n.kpx_1)",
|
||||
"Actions": [
|
||||
"?FC",
|
||||
"?XC",
|
||||
"?YC",
|
||||
"EnableRealNameCheck",
|
||||
"RequireUserIdVerification",
|
||||
"SetRealNameAndIdNumber",
|
||||
"SetValidateAntiAddictionUserDataStatus"
|
||||
"SetValidateAntiAddictionUserDataStatus",
|
||||
"UpdatePlayingTime"
|
||||
],
|
||||
"Default": "new UC()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "spectator",
|
||||
@@ -2194,15 +2396,15 @@
|
||||
"Reducer": "Li.jqm",
|
||||
"Delegate": "Li.jqm(t, n.lpx_1)",
|
||||
"Actions": [
|
||||
"?JA",
|
||||
"?XA",
|
||||
"?YA",
|
||||
"?ZA",
|
||||
"AddSpectator",
|
||||
"RemoveSpectator",
|
||||
"SetSpectator",
|
||||
"SetSpectators",
|
||||
"SetSpectatorsListVisible",
|
||||
"UpdateHudLayout"
|
||||
],
|
||||
"Default": "new HA()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "moderation",
|
||||
@@ -2211,22 +2413,22 @@
|
||||
"Reducer": "Ei.oqh",
|
||||
"Delegate": "Ei.oqh(t, n.mpx_1)",
|
||||
"Actions": [
|
||||
"?FI",
|
||||
"?GI",
|
||||
"?JI",
|
||||
"?KI",
|
||||
"?QI",
|
||||
"?UI",
|
||||
"?WI",
|
||||
"?XI",
|
||||
"?YI",
|
||||
"?ZI",
|
||||
"?nA",
|
||||
"?tA",
|
||||
"?uA"
|
||||
"AddSelectedUser",
|
||||
"AddSelectedUserFromChat",
|
||||
"ClearSelectedUsers",
|
||||
"HideBattleInfo",
|
||||
"HideBlockUserMenu",
|
||||
"HideModerationSystemMessage",
|
||||
"RemoveSelectedUser",
|
||||
"ResetSelectedUsers",
|
||||
"SetModerationUrlTemplates",
|
||||
"SetModeratorModes",
|
||||
"ShowBattleInfo",
|
||||
"ShowBlockUserMenu",
|
||||
"ShowModerationSystemMessage"
|
||||
],
|
||||
"Default": "new NI()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "rulesUpdated",
|
||||
@@ -2331,7 +2533,7 @@
|
||||
"VerificationStatus"
|
||||
],
|
||||
"Default": "new x9()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "rewardedVideosState",
|
||||
@@ -2402,7 +2604,7 @@
|
||||
"SetUnViewedElements"
|
||||
],
|
||||
"Default": "new Mst()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "suppliesTutorial",
|
||||
@@ -2472,7 +2674,7 @@
|
||||
"SetAvailableReports"
|
||||
],
|
||||
"Default": "new Zst()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "tankBuilderState",
|
||||
|
||||
@@ -200,6 +200,43 @@ const AnonymousActionNames = new Map([
|
||||
['Yet', 'HideDroppableGoldAuthor'],
|
||||
// creatorTagState 切片(qO / SO.er2):jO 没有 toString。
|
||||
['jO', 'ClearCreatorTag'],
|
||||
// battleTutorial 切片(rE / hE.sq8):oE/sE 没有 toString。
|
||||
['oE', 'MarkMovementStarted'],
|
||||
['sE', 'ResetBattleTutorial'],
|
||||
// spectator 切片(HA / tR.jqm):XA/JA/ZA/YA 没有 toString。
|
||||
['XA', 'SetSpectators'],
|
||||
['JA', 'AddSpectator'],
|
||||
['ZA', 'RemoveSpectator'],
|
||||
['YA', 'SetSpectatorsListVisible'],
|
||||
// antiAddiction 切片(UC / JC.iq8):FC/XC/YC 没有 toString。
|
||||
['FC', 'EnableRealNameCheck'],
|
||||
['XC', 'RequireUserIdVerification'],
|
||||
['YC', 'UpdatePlayingTime'],
|
||||
// moderation 切片(NI / _A.oqh):13 个类全都没有 toString。
|
||||
['UI', 'SetModeratorModes'],
|
||||
['FI', 'SetModerationUrlTemplates'],
|
||||
['XI', 'ShowBattleInfo'],
|
||||
['JI', 'HideBattleInfo'],
|
||||
['GI', 'AddSelectedUser'],
|
||||
['WI', 'AddSelectedUserFromChat'],
|
||||
['KI', 'RemoveSelectedUser'],
|
||||
['YI', 'ClearSelectedUsers'],
|
||||
['uA', 'ResetSelectedUsers'],
|
||||
['ZI', 'ShowModerationSystemMessage'],
|
||||
['QI', 'HideModerationSystemMessage'],
|
||||
['tA', 'ShowBlockUserMenu'],
|
||||
['nA', 'HideBlockUserMenu'],
|
||||
// 迁移 / 注册共用(module_10032 里各只定义一次):Mit/Dit/Lit/Bit/Uit/Fit/Git/Hit/hrt/_rt。
|
||||
['Mit', 'DisableRegister'],
|
||||
['Dit', 'UidIsFree'],
|
||||
['Lit', 'UidIsIncorrect'],
|
||||
['Bit', 'ResetUidStatus'],
|
||||
['Hit', 'UidTooShort'],
|
||||
['Uit', 'RegisterPasswordCorrect'],
|
||||
['Fit', 'RegisterPasswordIncorrect'],
|
||||
['Git', 'RegisterFailed'],
|
||||
['hrt', 'ResetRegisterStatus'],
|
||||
['_rt', 'ResetAuthenticationForm'],
|
||||
]);
|
||||
|
||||
// 非动作的 `instanceof`:屏幕标识类,用于 GoTo 分支判断(不是 dispatch 的动作)。
|
||||
@@ -628,6 +665,19 @@ const Migrated = {
|
||||
creatorTagState: { Type: 'CreatorTagStateSlice', Reduce: 'ReduceCreatorTag' },
|
||||
rewardedVideosState: { Type: 'RewardedVideosStateSlice', Reduce: 'ReduceRewardedVideos' },
|
||||
passwordChangeState: { Type: 'PasswordChangeStateSlice', Reduce: 'ReducePasswordChange' },
|
||||
system: { Type: 'SystemStateSlice', Reduce: 'ReduceSystem' },
|
||||
contextTutorial: { Type: 'ContextTutorialStateSlice', Reduce: 'ReduceContextTutorial' },
|
||||
battleTutorial: { Type: 'BattleTutorialStateSlice', Reduce: 'ReduceBattleTutorial' },
|
||||
spectator: { Type: 'SpectatorStateSlice', Reduce: 'ReduceSpectator' },
|
||||
twoStepVerificationState: {
|
||||
Type: 'TwoStepVerificationStateSlice',
|
||||
Reduce: 'ReduceTwoStepVerification',
|
||||
},
|
||||
antiAddiction: { Type: 'AntiAddictionStateSlice', Reduce: 'ReduceAntiAddiction' },
|
||||
moderation: { Type: 'ModerationStateSlice', Reduce: 'ReduceModeration' },
|
||||
migrationState: { Type: 'MigrationStateSlice', Reduce: 'ReduceMigrationState' },
|
||||
register: { Type: 'RegisterStateSlice', Reduce: 'ReduceRegister' },
|
||||
userReportsState: { Type: 'UserReportsStateSlice', Reduce: 'ReduceUserReports' },
|
||||
};
|
||||
|
||||
for (const R of Rows) R.Migrated = Object.prototype.hasOwnProperty.call(Migrated, R.Field);
|
||||
@@ -877,6 +927,58 @@ const CreatorTagAnonymousEffects = {
|
||||
jO: 'creatorTag=null(`n.ar2(null)`)',
|
||||
};
|
||||
|
||||
// battleTutorial 切片(rE / hE.sq8):oE/sE 没有 toString。
|
||||
const BattleTutorialAnonymousEffects = {
|
||||
oE: 'movementHasStarted=true(`n.pq8(cd, cd, !0)`)',
|
||||
sE: 'new rE() 整片复位(`new rE()`)',
|
||||
};
|
||||
|
||||
// spectator 切片(HA / tR.jqm):XA/JA/ZA/YA 没有 toString。
|
||||
const SpectatorAnonymousEffects = {
|
||||
XA: 'spectators=整表(`n.yql(cd, cd, t.dqm_1)`)',
|
||||
JA: 'spectators += `new iR(userId, uid, inSupportGroup, inPunishersGroup)`(`Hg`)',
|
||||
ZA: 'spectators 按 userId 过滤掉一条(`Qd(s.kqm_1, t.iqm_1) || e.y(s)`)',
|
||||
YA: 'spectatorsListVisible=布尔(`n.yql(cd, cd, cd, t.cqm_1)`)',
|
||||
};
|
||||
|
||||
// antiAddiction 切片(UC / JC.iq8):FC/XC/YC 没有 toString。
|
||||
const AntiAddictionAnonymousEffects = {
|
||||
FC: 'isEnableRealNameCheck=true(`n.lq7(!0)`)',
|
||||
XC: 'unknownUserId=true、urlForEnterUserId=参数(`n.lq7(cd, !0, t.hq8_1)`)',
|
||||
YC: 'playingTimeInMinutes、alertMessage(`n.lq7(cd, cd, cd, t.fq8_1, t.gq8_1)`)',
|
||||
};
|
||||
|
||||
// moderation 切片(NI / _A.oqh):13 个类全都没有 toString。
|
||||
const ModerationAnonymousEffects = {
|
||||
UI: 'moderatorMode / battleModeratorMode / eventOrganizerMode(`n.aqf(a, b, c)`)',
|
||||
FI: '两个 URL 模板(`n.aqf(cd, cd, cd, t.vqg_1, t.wqg_1)`)',
|
||||
XI: 'battleInfo + forceShowBattleInfo=true(`n.aqf(…, t.fqh_1, !0)`)',
|
||||
JI: 'forceShowBattleInfo=false(`n.aqf(…, !1)`)',
|
||||
GI: 'selectedUsers 去重后追加 `new OI(...)`(`Hg(e, new OI(...))`)',
|
||||
WI: '同 GI,另一个派发点(`Hg(_, new OI(...))`)',
|
||||
KI: 'selectedUsers 按 userId 过滤(`Qd(v.oqf_1, t.eqh_1) || l.y(v)`)',
|
||||
YI: 'selectedUsers 清空(`var p = md()`)',
|
||||
uA: 'selectedUsers 清空(`var w = md()`,另一个派发点)',
|
||||
ZI: 'systemMessage + forceShowSystemMessage=true(`n.aqf(…, t.gqh_1, !0)`)',
|
||||
QI: 'forceShowSystemMessage=false(`n.aqf(…, !1)`)',
|
||||
tA: 'forceShowBlockUserMenu=true(`n.aqf(…, !0)`)',
|
||||
nA: 'forceShowBlockUserMenu=false(`n.aqf(…, !1)`)',
|
||||
};
|
||||
|
||||
// 迁移 / 注册共用(Sit.rtg 与 art.stg 都 instanceof 同一批类)。
|
||||
const AuthAnonymousEffects = {
|
||||
Mit: 'isDisabled=true(`n.its(!0)`,只有注册切片读)',
|
||||
Dit: 'loginStatus / uidValidationStatus = FREE(`lrt()`)',
|
||||
Lit: 'loginStatus / uidValidationStatus = INCORRECT(`frt()`)',
|
||||
Bit: 'loginStatus / uidValidationStatus = UNKNOWN(`crt()`)',
|
||||
Hit: 'loginStatus / uidValidationStatus = SHORT_NAME(`prt()`)',
|
||||
Uit: 'registerStatus=PASSWORD_CORRECT(`(Iit(), Xv)`,只有注册切片读)',
|
||||
Fit: 'registerStatus=PASSWORD_INCORRECT(`drt()`)',
|
||||
Git: 'registerStatus=FAILED(`grt()`)',
|
||||
hrt: 'registerStatus=UNKNOWN(`n.its(cd, cd, cd, cd, cd, wrt())`,只有注册切片读)',
|
||||
_rt: 'login=""、两个状态复位(两个切片都读)',
|
||||
};
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(P, 'names', 'root_wiring.json'),
|
||||
JSON.stringify(
|
||||
@@ -1043,6 +1145,36 @@ fs.writeFileSync(
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(BattleTutorialAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(SpectatorAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(AntiAddictionAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(ModerationAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(AuthAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
],
|
||||
Markers: [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// AntiAddictionReducer.kt —— 防沉迷切片(对应 module_10032 的 UC 状态 + JC.iq8)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 UC:8 个字段,toString 名 "AntiAddictionState(…)"。
|
||||
// 默认:isEnableRealNameCheck=false、unknownUserId=false、urlForEnterUserId=null、
|
||||
// playingTimeInMinutes=0、alertMessage=""、idNumber=""、realName=""、validateStatus=null。
|
||||
// 根委派:`W.iq8(t, n.kpx_1)`。
|
||||
// reducer:
|
||||
// FC(无 toString) → isEnableRealNameCheck=true
|
||||
// XC(无 toString) → unknownUserId=true、urlForEnterUserId=参数
|
||||
// YC(无 toString) → playingTimeInMinutes、alertMessage
|
||||
// HC(SetRealNameAndIdNumber) → idNumber/realName;参数为 null 时保留原值
|
||||
// VC(SetValidateAntiAddictionUserDataStatus)→ validateStatus
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.SetRealNameAndIdNumber
|
||||
import App.State.SetValidateAntiAddictionUserDataStatus
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `FC`:开启实名认证检查(`n.lq7(!0)`)。 */
|
||||
object EnableRealNameCheck
|
||||
|
||||
/** 原 `XC`:要求补录用户 id,并给出入口地址(`n.lq7(cd, !0, url)`)。 */
|
||||
data class RequireUserIdVerification(val urlForEnterUserId: Any?)
|
||||
|
||||
/** 原 `YC`:更新累计在线时长与提示语。 */
|
||||
data class UpdatePlayingTime(
|
||||
val playingTimeInMinutes: Any?,
|
||||
val alertMessage: String,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class AntiAddictionStateSlice(
|
||||
val IsEnableRealNameCheck: Boolean = false,
|
||||
val UnknownUserId: Boolean = false,
|
||||
val UrlForEnterUserId: Any? = null,
|
||||
val PlayingTimeInMinutes: Any? = 0,
|
||||
val AlertMessage: String = "",
|
||||
val IdNumber: Any? = "",
|
||||
val RealName: Any? = "",
|
||||
val ValidateStatus: Any? = null,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceAntiAddiction(
|
||||
State0: AntiAddictionStateSlice,
|
||||
Action: Any,
|
||||
): AntiAddictionStateSlice = when (Action) {
|
||||
is EnableRealNameCheck -> State0.copy(IsEnableRealNameCheck = true)
|
||||
is RequireUserIdVerification -> State0.copy(
|
||||
UnknownUserId = true,
|
||||
UrlForEnterUserId = Action.urlForEnterUserId,
|
||||
)
|
||||
is UpdatePlayingTime -> State0.copy(
|
||||
PlayingTimeInMinutes = Action.playingTimeInMinutes,
|
||||
AlertMessage = Action.alertMessage,
|
||||
)
|
||||
is SetRealNameAndIdNumber -> State0.copy(
|
||||
IdNumber = Action.idNumber ?: State0.IdNumber,
|
||||
RealName = Action.realName ?: State0.RealName,
|
||||
)
|
||||
is SetValidateAntiAddictionUserDataStatus ->
|
||||
State0.copy(ValidateStatus = Action.validateStatus)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// AuthActions.kt —— 登录 / 迁移 / 注册共用的匿名动作
|
||||
//
|
||||
// 证据链:module_10032 里这些动作类只定义一次(16907–16965),
|
||||
// 迁移切片(Sit.rtg)和注册切片(art.stg)都直接 `instanceof` 它们,
|
||||
// 因此 Kotlin 侧也只能有一份,两个 reducer 共同响应、各自动自己读的字段。
|
||||
package App.State.Reducers
|
||||
|
||||
/** 原 `Mit`:注册按钮置灰(只有注册切片读)。 */
|
||||
object DisableRegister
|
||||
|
||||
/** 原 `Dit`:uid 可用(迁移的 loginStatus / 注册的 uidValidationStatus)。 */
|
||||
object UidIsFree
|
||||
|
||||
/** 原 `Lit`:uid 不合法。 */
|
||||
object UidIsIncorrect
|
||||
|
||||
/** 原 `Bit`:uid 校验状态复位为 UNKNOWN。 */
|
||||
object ResetUidStatus
|
||||
|
||||
/** 原 `Hit`:uid 过短。 */
|
||||
object UidTooShort
|
||||
|
||||
/** 原 `Uit`:注册密码校验通过(只有注册切片读)。 */
|
||||
object RegisterPasswordCorrect
|
||||
|
||||
/** 原 `Fit`:注册密码错误。 */
|
||||
object RegisterPasswordIncorrect
|
||||
|
||||
/** 原 `Git`:注册失败。 */
|
||||
object RegisterFailed
|
||||
|
||||
/** 原 `hrt`:注册状态复位为 UNKNOWN(只有注册切片读)。 */
|
||||
object ResetRegisterStatus
|
||||
|
||||
/** 原 `_rt`:清空 login 并把两个状态复位(迁移与注册都读)。 */
|
||||
object ResetAuthenticationForm
|
||||
@@ -0,0 +1,44 @@
|
||||
// BattleTutorialReducer.kt —— 战斗内上手指引切片(对应 module_10032 的 rE 状态 + hE.sq8)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 rE:3 个字段,toString 名 "BattleTutorialState(…)"。
|
||||
// 默认:message=null、fragsCount=0、movementHasStarted=false。
|
||||
// 根委派:`Q.sq8(t, n.cpv_1)`。
|
||||
// reducer:
|
||||
// eE(ShowMessage) → message
|
||||
// _E(SetFragsCount) → fragsCount
|
||||
// oE(无 toString) → movementHasStarted=true
|
||||
// sE(无 toString) → `new rE()` 整片复位
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.SetFragsCount
|
||||
import App.State.ShowMessage
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `oE`:玩家开始移动,指引进入下一步。 */
|
||||
object MarkMovementStarted
|
||||
|
||||
/** 原 `sE`:复位整片指引状态(`new rE()`)。 */
|
||||
object ResetBattleTutorial
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class BattleTutorialStateSlice(
|
||||
val Message: Any? = null,
|
||||
val FragsCount: Any? = 0,
|
||||
val MovementHasStarted: Boolean = false,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceBattleTutorial(
|
||||
State0: BattleTutorialStateSlice,
|
||||
Action: Any,
|
||||
): BattleTutorialStateSlice = when (Action) {
|
||||
is ShowMessage -> State0.copy(Message = Action.message)
|
||||
is SetFragsCount -> State0.copy(FragsCount = Action.fragsCount)
|
||||
is MarkMovementStarted -> State0.copy(MovementHasStarted = true)
|
||||
is ResetBattleTutorial -> BattleTutorialStateSlice()
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// ContextTutorialReducer.kt —— 上手指引切片(对应 module_10032 的 Mst 状态 + Xst.tth)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 Mst:4 个字段,toString 名 "ContextTutorialState(…)"。
|
||||
// 默认:currentElement=null、loadedElements=emptyMap()、unViewedElements=emptyList()、missionToElement=emptyMap()。
|
||||
// 根委派:`Jst().tth(t, n.ypx_1)`。
|
||||
// reducer:
|
||||
// Lst(LoadCurrentElement) → currentElement
|
||||
// Bst(SetUnViewedElements) → unViewedElements
|
||||
// Fst(MarkElementAsViewed) → unViewedElements 去掉 element(`Ym` = List.minus)
|
||||
// Ust(SetLoadedElements) → loadedElements
|
||||
// Gst(SetMissionToElement) → missionToElement
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.LoadCurrentElement
|
||||
import App.State.MarkElementAsViewed
|
||||
import App.State.SetLoadedElements
|
||||
import App.State.SetMissionToElement
|
||||
import App.State.SetUnViewedElements
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class ContextTutorialStateSlice(
|
||||
val CurrentElement: Any? = null,
|
||||
val LoadedElements: Map<Any?, Any?> = emptyMap(),
|
||||
val UnViewedElements: List<Any?> = emptyList(),
|
||||
val MissionToElement: Map<String, String> = emptyMap(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun AsMap(Value: Any?): Map<Any?, Any?> =
|
||||
Value as? Map<Any?, Any?> ?: emptyMap()
|
||||
|
||||
fun ReduceContextTutorial(
|
||||
State0: ContextTutorialStateSlice,
|
||||
Action: Any,
|
||||
): ContextTutorialStateSlice = when (Action) {
|
||||
is LoadCurrentElement -> State0.copy(CurrentElement = Action.element)
|
||||
is SetUnViewedElements -> State0.copy(UnViewedElements = Action.unViewedElements)
|
||||
is MarkElementAsViewed ->
|
||||
State0.copy(UnViewedElements = State0.UnViewedElements - Action.element)
|
||||
is SetLoadedElements -> State0.copy(LoadedElements = AsMap(Action.loadedElements))
|
||||
is SetMissionToElement -> State0.copy(MissionToElement = Action.missionToElement)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
// MigrationStateReducer.kt —— 老账号迁移切片(对应 module_10032 的 $it 状态 + Sit.rtg)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 $it:7 个字段,toString 名 "MigrationState(…)";copy 是 jtr(7 字段 + 回调)。
|
||||
// 默认:requestLogin=false、login=""、forceLogin=null、password=""、
|
||||
// loginStatus=UNKNOWN、registerStatus=UNKNOWN、advisedUids=emptyList()。
|
||||
// 根委派:`Uv.rtg(t, n.ipv_1)`。
|
||||
// reducer(11 个实例臂):
|
||||
// Kit(SetUid) → login + 两个状态复位
|
||||
// Jit(ForceSetUid) → forceLogin + 两个状态复位
|
||||
// Yit(SetPassword) → password + registerStatus 复位
|
||||
// Dit(UidIsFree) → loginStatus=FREE
|
||||
// Oit(EnteredUidIsBusy)→ loginStatus=BUSY + advisedUids
|
||||
// Lit(UidIsIncorrect) → loginStatus=INCORRECT
|
||||
// Bit(ResetUidStatus) → loginStatus=UNKNOWN
|
||||
// Fit(RegisterPasswordIncorrect)→ registerStatus=PASSWORD_INCORRECT
|
||||
// Git(RegisterFailed) → registerStatus=FAILED
|
||||
// Hit(UidTooShort) → loginStatus=SHORT_NAME
|
||||
// _rt(ResetAuthenticationForm)→ login="" + 两个状态复位
|
||||
//
|
||||
// 状态枚举直接对应源码 `Eit()` / `Iit()`:
|
||||
// LoginStatus = UNKNOWN / FREE / INCORRECT / BUSY / SHORT_NAME
|
||||
// RegisterStatus = UNKNOWN / PASSWORD_CORRECT / PASSWORD_INCORRECT / FAILED
|
||||
//
|
||||
// 注意:`SetUid` / `ForceSetUid` / `SetPassword` 与注册、登录切片共用同一批动作类
|
||||
// (原包也是同一批类),因此几片 reducer 会同时响应它们,各自动自己读的字段。
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.EnteredUidIsBusy
|
||||
import App.State.ForceSetUid
|
||||
import App.State.SetPassword
|
||||
import App.State.SetUid
|
||||
|
||||
/* ------------------------------------------------------------------ 枚举 */
|
||||
|
||||
enum class MigrationLoginStatus {
|
||||
UNKNOWN,
|
||||
FREE,
|
||||
INCORRECT,
|
||||
BUSY,
|
||||
SHORT_NAME,
|
||||
}
|
||||
|
||||
enum class MigrationRegisterStatus {
|
||||
UNKNOWN,
|
||||
PASSWORD_CORRECT,
|
||||
PASSWORD_INCORRECT,
|
||||
FAILED,
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class MigrationStateSlice(
|
||||
val RequestLogin: Boolean = false,
|
||||
val Login: String = "",
|
||||
val ForceLogin: Any? = null,
|
||||
val Password: String = "",
|
||||
val LoginStatus: MigrationLoginStatus = MigrationLoginStatus.UNKNOWN,
|
||||
val RegisterStatus: MigrationRegisterStatus = MigrationRegisterStatus.UNKNOWN,
|
||||
val AdvisedUids: List<Any?> = emptyList(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceMigrationState(
|
||||
State0: MigrationStateSlice,
|
||||
Action: Any,
|
||||
): MigrationStateSlice = when (Action) {
|
||||
// Kit / Jit / Yit 都会把两个状态打回 UNKNOWN(原 `crt()` / `wrt()`)。
|
||||
is SetUid -> State0.copy(
|
||||
Login = Action.uid?.toString() ?: "",
|
||||
LoginStatus = MigrationLoginStatus.UNKNOWN,
|
||||
RegisterStatus = MigrationRegisterStatus.UNKNOWN,
|
||||
)
|
||||
is ForceSetUid -> State0.copy(
|
||||
ForceLogin = Action.uid,
|
||||
LoginStatus = MigrationLoginStatus.UNKNOWN,
|
||||
RegisterStatus = MigrationRegisterStatus.UNKNOWN,
|
||||
)
|
||||
is SetPassword -> State0.copy(
|
||||
Password = Action.password?.toString() ?: "",
|
||||
RegisterStatus = MigrationRegisterStatus.UNKNOWN,
|
||||
)
|
||||
is UidIsFree -> State0.copy(LoginStatus = MigrationLoginStatus.FREE)
|
||||
is EnteredUidIsBusy -> State0.copy(
|
||||
LoginStatus = MigrationLoginStatus.BUSY,
|
||||
AdvisedUids = Action.advisedUids as? List<Any?> ?: emptyList(),
|
||||
)
|
||||
is UidIsIncorrect -> State0.copy(LoginStatus = MigrationLoginStatus.INCORRECT)
|
||||
is ResetUidStatus -> State0.copy(LoginStatus = MigrationLoginStatus.UNKNOWN)
|
||||
is UidTooShort -> State0.copy(LoginStatus = MigrationLoginStatus.SHORT_NAME)
|
||||
is RegisterPasswordIncorrect ->
|
||||
State0.copy(RegisterStatus = MigrationRegisterStatus.PASSWORD_INCORRECT)
|
||||
is RegisterFailed ->
|
||||
State0.copy(RegisterStatus = MigrationRegisterStatus.FAILED)
|
||||
is ResetAuthenticationForm -> State0.copy(
|
||||
Login = "",
|
||||
LoginStatus = MigrationLoginStatus.UNKNOWN,
|
||||
RegisterStatus = MigrationRegisterStatus.UNKNOWN,
|
||||
)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
// ModerationReducer.kt —— 管理员工具切片(对应 module_10032 的 NI 状态 + _A.oqh)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 NI:11 个字段,toString 名 "Moderation(…)"。
|
||||
// 默认:三个模式 false、两个 URL 模板 ""、battleInfo=new MI()、三个 forceShow false、
|
||||
// systemMessage=""、selectedUsers=emptyList()。
|
||||
// 根委派:`Ei.oqh(t, n.mpx_1)`。
|
||||
// reducer(13 个实例臂):
|
||||
// UI(无 toString) → 三个模式开关
|
||||
// FI(无 toString) → 两个 URL 模板
|
||||
// XI(无 toString) → battleInfo + forceShowBattleInfo=true
|
||||
// JI(无 toString) → forceShowBattleInfo=false
|
||||
// GI(无 toString) → selectedUsers 先按 userId 去重、再追加 `new OI(...)`
|
||||
// WI(无 toString) → 同 GI(另一个派发点,效果一致)
|
||||
// KI(无 toString) → selectedUsers 按 userId 移除
|
||||
// YI(无 toString) → selectedUsers 清空
|
||||
// uA(无 toString) → selectedUsers 清空(同 YI,另一个派发点)
|
||||
// ZI(无 toString) → systemMessage + forceShowSystemMessage=true
|
||||
// QI(无 toString) → forceShowSystemMessage=false
|
||||
// tA(无 toString) → forceShowBlockUserMenu=true
|
||||
// nA(无 toString) → forceShowBlockUserMenu=false
|
||||
//
|
||||
// 说明:`battleInfo` 的原模型 `MI` 有 13 个字段(战斗信息面板),属战斗层,这里按
|
||||
// `Any?` 收口(缺省 null),只在 ShowBattleInfo 时整体替换。
|
||||
package App.State.Reducers
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `UI`:一次写三个管理员模式开关。 */
|
||||
data class SetModeratorModes(
|
||||
val moderatorMode: Boolean,
|
||||
val battleModeratorMode: Boolean,
|
||||
val eventOrganizerMode: Boolean,
|
||||
)
|
||||
|
||||
/** 原 `FI`:写管理员工具的战斗 / 用户链接模板。 */
|
||||
data class SetModerationUrlTemplates(
|
||||
val battleUrlTemplate: String,
|
||||
val userUrlTemplate: String,
|
||||
)
|
||||
|
||||
/** 原 `XI`:显示战斗信息面板。 */
|
||||
data class ShowBattleInfo(val battleInfo: Any?)
|
||||
|
||||
/** 原 `JI`:收起战斗信息面板。 */
|
||||
object HideBattleInfo
|
||||
|
||||
/** 原 `GI`:把用户加入选中列表(先按 userId 去重)。 */
|
||||
data class AddSelectedUser(
|
||||
val userId: Any?,
|
||||
val userRank: Any?,
|
||||
val userName: Any?,
|
||||
)
|
||||
|
||||
/** 原 `WI`:另一个派发点上把用户加入选中列表,效果与 `GI` 相同。 */
|
||||
data class AddSelectedUserFromChat(
|
||||
val userId: Any?,
|
||||
val userRank: Any?,
|
||||
val userName: Any?,
|
||||
)
|
||||
|
||||
/** 原 `KI`:从选中列表移除用户。 */
|
||||
data class RemoveSelectedUser(val userId: Any?)
|
||||
|
||||
/** 原 `YI`:清空选中列表。 */
|
||||
object ClearSelectedUsers
|
||||
|
||||
/** 原 `uA`:另一个派发点上清空选中列表,效果与 `YI` 相同。 */
|
||||
object ResetSelectedUsers
|
||||
|
||||
/** 原 `ZI`:显示管理员系统消息。 */
|
||||
data class ShowModerationSystemMessage(val message: String)
|
||||
|
||||
/** 原 `QI`:收起管理员系统消息。 */
|
||||
object HideModerationSystemMessage
|
||||
|
||||
/** 原 `tA`:强制弹出封禁用户菜单。 */
|
||||
object ShowBlockUserMenu
|
||||
|
||||
/** 原 `nA`:收起封禁用户菜单。 */
|
||||
object HideBlockUserMenu
|
||||
|
||||
/* ------------------------------------------------------------------ 模型 */
|
||||
|
||||
data class ModerationUserRecord(
|
||||
val userId: Any?,
|
||||
val userRank: Any?,
|
||||
val userName: Any?,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class ModerationStateSlice(
|
||||
val ModeratorMode: Boolean = false,
|
||||
val BattleModeratorMode: Boolean = false,
|
||||
val EventOrganizerMode: Boolean = false,
|
||||
val ModerationToolBattleUrlTemplate: String = "",
|
||||
val ModerationToolUserUrlTemplate: String = "",
|
||||
val BattleInfo: Any? = null,
|
||||
val ForceShowBattleInfo: Boolean = false,
|
||||
val SystemMessage: String = "",
|
||||
val ForceShowSystemMessage: Boolean = false,
|
||||
val ForceShowBlockUserMenu: Boolean = false,
|
||||
val SelectedUsers: List<Any?> = emptyList(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
/** `Hg(n.yqe_1, new OI(...))` 的等价:先去掉同 userId 的旧记录,再追加。 */
|
||||
private fun UpsertUser(Users: List<Any?>, Record: ModerationUserRecord): List<Any?> =
|
||||
Users.filterNot { (it as? ModerationUserRecord)?.userId == Record.userId } + Record
|
||||
|
||||
fun ReduceModeration(
|
||||
State0: ModerationStateSlice,
|
||||
Action: Any,
|
||||
): ModerationStateSlice = when (Action) {
|
||||
is SetModeratorModes -> State0.copy(
|
||||
ModeratorMode = Action.moderatorMode,
|
||||
BattleModeratorMode = Action.battleModeratorMode,
|
||||
EventOrganizerMode = Action.eventOrganizerMode,
|
||||
)
|
||||
is SetModerationUrlTemplates -> State0.copy(
|
||||
ModerationToolBattleUrlTemplate = Action.battleUrlTemplate,
|
||||
ModerationToolUserUrlTemplate = Action.userUrlTemplate,
|
||||
)
|
||||
is ShowBattleInfo -> State0.copy(
|
||||
BattleInfo = Action.battleInfo,
|
||||
ForceShowBattleInfo = true,
|
||||
)
|
||||
is HideBattleInfo -> State0.copy(ForceShowBattleInfo = false)
|
||||
is AddSelectedUser -> State0.copy(
|
||||
SelectedUsers = UpsertUser(
|
||||
State0.SelectedUsers,
|
||||
ModerationUserRecord(Action.userId, Action.userRank, Action.userName),
|
||||
),
|
||||
)
|
||||
is AddSelectedUserFromChat -> State0.copy(
|
||||
SelectedUsers = UpsertUser(
|
||||
State0.SelectedUsers,
|
||||
ModerationUserRecord(Action.userId, Action.userRank, Action.userName),
|
||||
),
|
||||
)
|
||||
is RemoveSelectedUser -> State0.copy(
|
||||
SelectedUsers = State0.SelectedUsers.filterNot {
|
||||
(it as? ModerationUserRecord)?.userId == Action.userId
|
||||
},
|
||||
)
|
||||
is ClearSelectedUsers -> State0.copy(SelectedUsers = emptyList())
|
||||
is ResetSelectedUsers -> State0.copy(SelectedUsers = emptyList())
|
||||
is ShowModerationSystemMessage -> State0.copy(
|
||||
SystemMessage = Action.message,
|
||||
ForceShowSystemMessage = true,
|
||||
)
|
||||
is HideModerationSystemMessage -> State0.copy(ForceShowSystemMessage = false)
|
||||
is ShowBlockUserMenu -> State0.copy(ForceShowBlockUserMenu = true)
|
||||
is HideBlockUserMenu -> State0.copy(ForceShowBlockUserMenu = false)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
// RegisterReducer.kt —— 注册切片(对应 module_10032 的 Cit 状态 + art.stg)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 Cit:16 个字段,toString 名 "RegisterState(…)";copy 是 its(16 字段 + 回调)。
|
||||
// 默认:isDisabled=false、login=""、forceLogin=null、password=""、
|
||||
// uidValidationStatus=UNKNOWN、registerStatus=UNKNOWN、advisedUids=emptyList()、
|
||||
// socialNetworkAvailability=emptyMap()、socialNetworkClientIds=emptyMap()、
|
||||
// socialNetworkOAuthData=null、minPasswordLength=6、maxPasswordLength=20、
|
||||
// 三个 passwordNeed* 为 false、openedPassword=true。
|
||||
// 根委派:`cp.stg(t, n.hpv_1)`。
|
||||
// reducer(19 个实例臂):
|
||||
// Mit(DisableRegister)→ isDisabled=true
|
||||
// Kit(SetUid) → login;uidValidationStatus=UNKNOWN;若原状态不是 INCORRECT,
|
||||
// registerStatus 也复位(原 `2 === n.wtr_1.k3_1` 分支)
|
||||
// Jit(ForceSetUid)→ forceLogin;状态复位规则同上
|
||||
// Yit(SetPassword)→ password + registerStatus=UNKNOWN
|
||||
// Dit / Oit / Lit / Bit / Hit → uidValidationStatus = FREE / BUSY(+advisedUids) / INCORRECT / UNKNOWN / SHORT_NAME
|
||||
// Uit / Fit / Git → registerStatus = PASSWORD_CORRECT / PASSWORD_INCORRECT / FAILED
|
||||
// trt(SocialNetworkAvailability)/ nrt(SocialNetworkClientIds)/ ert(ReceiveOAuthUri)
|
||||
// _rt(ResetAuthenticationForm)→ login="" + 两个状态复位
|
||||
// hrt(ResetRegisterStatus)→ registerStatus=UNKNOWN
|
||||
// Nit(SetPasswordRestrictions)→ 5 个密码规则字段
|
||||
// ort(SetOpenedPassword)→ openedPassword
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.EnteredUidIsBusy
|
||||
import App.State.ForceSetUid
|
||||
import App.State.ReceiveOAuthUri
|
||||
import App.State.SetOpenedPassword
|
||||
import App.State.SetPassword
|
||||
import App.State.SetPasswordRestrictions
|
||||
import App.State.SetUid
|
||||
import App.State.SocialNetworkAvailability
|
||||
import App.State.SocialNetworkClientIds
|
||||
|
||||
/* ------------------------------------------------------------------ 枚举 */
|
||||
|
||||
enum class UidStatus {
|
||||
UNKNOWN,
|
||||
FREE,
|
||||
INCORRECT,
|
||||
BUSY,
|
||||
SHORT_NAME,
|
||||
}
|
||||
|
||||
enum class RegistrationStatus {
|
||||
UNKNOWN,
|
||||
PASSWORD_CORRECT,
|
||||
PASSWORD_INCORRECT,
|
||||
FAILED,
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class RegisterStateSlice(
|
||||
val IsDisabled: Boolean = false,
|
||||
val Login: String = "",
|
||||
val ForceLogin: Any? = null,
|
||||
val Password: String = "",
|
||||
val UidValidationStatus: UidStatus = UidStatus.UNKNOWN,
|
||||
val RegisterStatus: RegistrationStatus = RegistrationStatus.UNKNOWN,
|
||||
val AdvisedUids: List<Any?> = emptyList(),
|
||||
val SocialNetworkAvailability: Map<String, Boolean> = emptyMap(),
|
||||
val SocialNetworkClientIds: Any? = emptyMap<String, Any?>(),
|
||||
val SocialNetworkOAuthData: Any? = null,
|
||||
val MinPasswordLength: Int = 6,
|
||||
val MaxPasswordLength: Int = 20,
|
||||
val PasswordNeedLower: Boolean = false,
|
||||
val PasswordNeedUpper: Boolean = false,
|
||||
val PasswordNeedDigit: Boolean = false,
|
||||
val OpenedPassword: Boolean = true,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
/** `Kit` / `Jit` 共用:uid 变化时复位校验状态;原本不是 INCORRECT 才连注册状态一起复位。 */
|
||||
private fun ResetUidRelated(State0: RegisterStateSlice): RegisterStateSlice = State0.copy(
|
||||
UidValidationStatus = UidStatus.UNKNOWN,
|
||||
RegisterStatus =
|
||||
if (State0.UidValidationStatus == UidStatus.INCORRECT) State0.RegisterStatus
|
||||
else RegistrationStatus.UNKNOWN,
|
||||
)
|
||||
|
||||
fun ReduceRegister(
|
||||
State0: RegisterStateSlice,
|
||||
Action: Any,
|
||||
): RegisterStateSlice = when (Action) {
|
||||
is DisableRegister -> State0.copy(IsDisabled = true)
|
||||
is SetUid -> ResetUidRelated(State0.copy(Login = Action.uid?.toString() ?: ""))
|
||||
is ForceSetUid -> ResetUidRelated(State0.copy(ForceLogin = Action.uid))
|
||||
is SetPassword -> State0.copy(
|
||||
Password = Action.password?.toString() ?: "",
|
||||
RegisterStatus = RegistrationStatus.UNKNOWN,
|
||||
)
|
||||
is UidIsFree -> State0.copy(UidValidationStatus = UidStatus.FREE)
|
||||
is EnteredUidIsBusy -> State0.copy(
|
||||
UidValidationStatus = UidStatus.BUSY,
|
||||
AdvisedUids = Action.advisedUids as? List<Any?> ?: emptyList(),
|
||||
)
|
||||
is UidIsIncorrect -> State0.copy(UidValidationStatus = UidStatus.INCORRECT)
|
||||
is ResetUidStatus -> State0.copy(UidValidationStatus = UidStatus.UNKNOWN)
|
||||
is UidTooShort -> State0.copy(UidValidationStatus = UidStatus.SHORT_NAME)
|
||||
is RegisterPasswordCorrect ->
|
||||
State0.copy(RegisterStatus = RegistrationStatus.PASSWORD_CORRECT)
|
||||
is RegisterPasswordIncorrect ->
|
||||
State0.copy(RegisterStatus = RegistrationStatus.PASSWORD_INCORRECT)
|
||||
is RegisterFailed -> State0.copy(RegisterStatus = RegistrationStatus.FAILED)
|
||||
is ResetRegisterStatus -> State0.copy(RegisterStatus = RegistrationStatus.UNKNOWN)
|
||||
is SocialNetworkAvailability ->
|
||||
State0.copy(SocialNetworkAvailability = Action.socialNetworkAvailability)
|
||||
is SocialNetworkClientIds ->
|
||||
State0.copy(SocialNetworkClientIds = Action.socialNetworkClientIds)
|
||||
is ReceiveOAuthUri -> State0.copy(SocialNetworkOAuthData = Action.startOAuthData)
|
||||
is ResetAuthenticationForm -> State0.copy(
|
||||
Login = "",
|
||||
UidValidationStatus = UidStatus.UNKNOWN,
|
||||
RegisterStatus = RegistrationStatus.UNKNOWN,
|
||||
)
|
||||
is SetPasswordRestrictions -> State0.copy(
|
||||
MinPasswordLength = Action.minPasswordLength,
|
||||
MaxPasswordLength = Action.maxPasswordLength,
|
||||
PasswordNeedLower = Action.passwordNeedLower,
|
||||
PasswordNeedUpper = Action.passwordNeedUpper,
|
||||
PasswordNeedDigit = Action.passwordNeedDigit,
|
||||
)
|
||||
is SetOpenedPassword -> State0.copy(OpenedPassword = Action.openedPassword)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// SpectatorReducer.kt —— 观战切片(对应 module_10032 的 HA 状态 + tR.jqm)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 HA:4 个字段,toString 名 "Spectator(…)"。
|
||||
// 默认:isSpectator=false、spectatorHudLayout=new nR()、spectators=emptyList()、spectatorsListVisible=true。
|
||||
// 根委派:`Li.jqm(t, n.lpx_1)`。
|
||||
// reducer:
|
||||
// WA(SetSpectator) → isSpectator
|
||||
// VA(UpdateHudLayout) → spectatorHudLayout
|
||||
// XA(无 toString) → spectators 整表替换
|
||||
// JA(无 toString) → spectators 追加 `new iR(...)`(SpectatorInfo 四字段)
|
||||
// ZA(无 toString) → spectators 按 userId 过滤掉一个
|
||||
// YA(无 toString) → spectatorsListVisible
|
||||
//
|
||||
// 说明:`spectatorHudLayout` 的默认值是 `new nR()`(15 字段的 HUD 布局对象),
|
||||
// 该模型属于战斗层,这里按 `Any?` 收口(缺省 null),只在收到 UpdateHudLayout 时替换。
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.SetSpectator
|
||||
import App.State.SpectatorInfo
|
||||
import App.State.UpdateHudLayout
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `XA`:整体替换观战者列表。 */
|
||||
data class SetSpectators(val spectators: List<Any?>)
|
||||
|
||||
/** 原 `JA`:追加一个观战者(`new iR(userId, uid, inSupportGroup, inPunishersGroup)`)。 */
|
||||
data class AddSpectator(
|
||||
val userId: Long,
|
||||
val uid: Any?,
|
||||
val inSupportGroup: Boolean,
|
||||
val inPunishersGroup: Boolean,
|
||||
)
|
||||
|
||||
/** 原 `ZA`:按 userId 移除观战者。 */
|
||||
data class RemoveSpectator(val userId: Long)
|
||||
|
||||
/** 原 `YA`:切换观战者列表可见性。 */
|
||||
data class SetSpectatorsListVisible(val visible: Boolean)
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class SpectatorStateSlice(
|
||||
val IsSpectator: Boolean = false,
|
||||
val SpectatorHudLayout: Any? = null,
|
||||
val Spectators: List<Any?> = emptyList(),
|
||||
val SpectatorsListVisible: Boolean = true,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceSpectator(
|
||||
State0: SpectatorStateSlice,
|
||||
Action: Any,
|
||||
): SpectatorStateSlice = when (Action) {
|
||||
is SetSpectator -> State0.copy(IsSpectator = Action.spectatorMode)
|
||||
is UpdateHudLayout -> State0.copy(SpectatorHudLayout = Action.hudLayout)
|
||||
is SetSpectators -> State0.copy(Spectators = Action.spectators)
|
||||
is AddSpectator -> State0.copy(
|
||||
Spectators = State0.Spectators + SpectatorInfo(
|
||||
userId = Action.userId,
|
||||
uid = Action.uid,
|
||||
inSupportGroup = Action.inSupportGroup,
|
||||
inPunishersGroup = Action.inPunishersGroup,
|
||||
),
|
||||
)
|
||||
is RemoveSpectator -> State0.copy(
|
||||
Spectators = State0.Spectators.filterNot {
|
||||
(it as? SpectatorInfo)?.userId == Action.userId
|
||||
},
|
||||
)
|
||||
is SetSpectatorsListVisible -> State0.copy(SpectatorsListVisible = Action.visible)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// SystemReducer.kt —— 全屏系统消息切片(对应 module_10032 的 _9 状态 + p9.xt9)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 _9:3 个字段,toString 名 "SystemScreenState(message=…, restart=…, fatalError=…)"。
|
||||
// 默认:message=null、restart=false、fatalError=null。
|
||||
// 根委派:`w9().xt9(t, n.mpv_1)`。
|
||||
// reducer:
|
||||
// v9(DoShowMessage) → message、restart
|
||||
// SetFatalError → fatalError
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.DoShowMessage
|
||||
import App.State.SetFatalError
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class SystemStateSlice(
|
||||
val Message: Any? = null,
|
||||
val Restart: Boolean = false,
|
||||
val FatalError: Any? = null,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceSystem(
|
||||
State0: SystemStateSlice,
|
||||
Action: Any,
|
||||
): SystemStateSlice = when (Action) {
|
||||
is DoShowMessage -> State0.copy(Message = Action.message, Restart = Action.restart)
|
||||
is SetFatalError -> State0.copy(FatalError = Action.fatalError)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// TwoStepVerificationReducer.kt —— 两步验证切片(对应 module_10032 的 x9 状态 + P9.atb)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 x9:6 个字段,toString 名 "TwoStepVerificationState(…)"。
|
||||
// 默认:isUse2FA=false、isActivated2FA=false、qrCodeDataURI=null、sharedSecret=null、
|
||||
// verificationStatus=null、enable2FaRequest=false。
|
||||
// 根委派:`_f.atb(t, n.tpx_1)`。
|
||||
// reducer:
|
||||
// j9(SetUse2FA) → isUse2FA
|
||||
// S9(ActivationStatus2FA) → isActivated2FA
|
||||
// C9(SetSecretAndQRCode) → qrCodeDataURI、sharedSecret
|
||||
// I9(VerificationStatus) → null → verificationStatus=null
|
||||
// false → verificationStatus=false
|
||||
// true → isActivated2FA=true(成功即视为已启用)
|
||||
// A9(Enable2FaRequest) → enable2FaRequest
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.ActivationStatus2FA
|
||||
import App.State.Enable2FaRequest
|
||||
import App.State.SetSecretAndQRCode
|
||||
import App.State.SetUse2FA
|
||||
import App.State.VerificationStatus
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class TwoStepVerificationStateSlice(
|
||||
val IsUse2FA: Boolean = false,
|
||||
val IsActivated2FA: Boolean = false,
|
||||
val QrCodeDataURI: Any? = null,
|
||||
val SharedSecret: Any? = null,
|
||||
val VerificationStatus: Any? = null,
|
||||
val Enable2FaRequest: Boolean = false,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceTwoStepVerification(
|
||||
State0: TwoStepVerificationStateSlice,
|
||||
Action: Any,
|
||||
): TwoStepVerificationStateSlice = when (Action) {
|
||||
is SetUse2FA -> State0.copy(IsUse2FA = Action.isUse2FA)
|
||||
is ActivationStatus2FA -> State0.copy(IsActivated2FA = Action.isActivated)
|
||||
is SetSecretAndQRCode -> State0.copy(
|
||||
QrCodeDataURI = Action.qrCodeDataURI,
|
||||
SharedSecret = Action.sharedSecret,
|
||||
)
|
||||
is VerificationStatus -> when (val Success = Action.isValidationSuccess) {
|
||||
null -> State0.copy(VerificationStatus = null)
|
||||
false -> State0.copy(VerificationStatus = false)
|
||||
true -> State0.copy(IsActivated2FA = true)
|
||||
else -> State0
|
||||
}
|
||||
is Enable2FaRequest -> State0.copy(Enable2FaRequest = Action.enable)
|
||||
else -> State0
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
// UserReportsReducer.kt —— 举报切片(对应 module_10032 的 Zst 状态 + qot.zth)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 Zst:5 个字段,toString 名 "UserReportsState(…)"。
|
||||
// 默认:isEnabled=false、helpdeskTicketsEnabled=false、availableReports=0、
|
||||
// availableGameReports=0、reports=(原 `dsv()` 从 localStorage 的 SENT_REPORTS 读回)。
|
||||
// 根委派:`(null == sd && new qot(), sd).zth(t, n.dpy_1)`。
|
||||
// reducer(6 个实例臂):
|
||||
// cot(InitUserReports) → 4 个开关/额度字段
|
||||
// lot(SetAvailableReports) → availableReports
|
||||
// fot(SetAvailableGameReports)→ availableGameReports
|
||||
// vot(ReportProBattleName) → reports 追加 BATTLE_NAME 记录(有效期 +1 天)
|
||||
// pot(ReportLobbyChatMessage) → reports 追加 LOBBY_CHAT_MESSAGE 记录
|
||||
// wot(ReportBattleChatMessage)→ reports 追加 BATTLE_CHAT_MESSAGE 记录
|
||||
//
|
||||
// 原 reducer 在 reports 变化后会把列表序列化写回 localStorage 的 SENT_REPORTS
|
||||
// (以及 Init 时从里面过滤过期项读回)。这属于 storage port 的职责,纯 reducer 不做 IO:
|
||||
// Init 保留当前列表,写回留给中间件层。
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.InitUserReports
|
||||
import App.State.ReportBattleChatMessage
|
||||
import App.State.ReportLobbyChatMessage
|
||||
import App.State.ReportProBattleName
|
||||
import App.State.SetAvailableGameReports
|
||||
import App.State.SetAvailableReports
|
||||
|
||||
/* ------------------------------------------------------------------ 模型 */
|
||||
|
||||
/** 原 `dot` 枚举:BATTLE_NAME / LOBBY_CHAT_MESSAGE / BATTLE_CHAT_MESSAGE。 */
|
||||
enum class ReportKind {
|
||||
BATTLE_NAME,
|
||||
LOBBY_CHAT_MESSAGE,
|
||||
BATTLE_CHAT_MESSAGE,
|
||||
}
|
||||
|
||||
/** 原 `mot(type, targetId, expireTime)`:一条已发送的举报。 */
|
||||
data class ReportEntry(
|
||||
val kind: ReportKind,
|
||||
val targetId: Any?,
|
||||
val expireTime: Double,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ 时间 */
|
||||
|
||||
/** 原 `Fg(Md(), new Dd(864e5, 0))`:当前时间 + 1 天。 */
|
||||
private fun ExpireAtNextDay(): Double = (js("Date.now() + 86400000") as Number).toDouble()
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class UserReportsStateSlice(
|
||||
val IsEnabled: Boolean = false,
|
||||
val HelpdeskTicketsEnabled: Boolean = false,
|
||||
val AvailableReports: Any? = 0,
|
||||
val AvailableGameReports: Any? = 0,
|
||||
val Reports: List<Any?> = emptyList(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
private fun AppendReport(State0: UserReportsStateSlice, Entry: ReportEntry): UserReportsStateSlice =
|
||||
State0.copy(Reports = State0.Reports + Entry)
|
||||
|
||||
fun ReduceUserReports(
|
||||
State0: UserReportsStateSlice,
|
||||
Action: Any,
|
||||
): UserReportsStateSlice = when (Action) {
|
||||
is InitUserReports -> State0.copy(
|
||||
IsEnabled = Action.isEnabled,
|
||||
HelpdeskTicketsEnabled = Action.helpdeskTicketsEnabled,
|
||||
AvailableReports = Action.availableReports,
|
||||
AvailableGameReports = Action.availableGameReports,
|
||||
)
|
||||
is SetAvailableReports -> State0.copy(AvailableReports = Action.availableReports)
|
||||
is SetAvailableGameReports -> State0.copy(AvailableGameReports = Action.availableGameReports)
|
||||
is ReportProBattleName -> AppendReport(
|
||||
State0,
|
||||
ReportEntry(ReportKind.BATTLE_NAME, Action.battleId, ExpireAtNextDay()),
|
||||
)
|
||||
is ReportLobbyChatMessage -> AppendReport(
|
||||
State0,
|
||||
ReportEntry(ReportKind.LOBBY_CHAT_MESSAGE, Action.messageId, ExpireAtNextDay()),
|
||||
)
|
||||
is ReportBattleChatMessage -> AppendReport(
|
||||
State0,
|
||||
ReportEntry(ReportKind.BATTLE_CHAT_MESSAGE, Action.messageId, ExpireAtNextDay()),
|
||||
)
|
||||
else -> State0
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// RootReducer.kt —— 根 reducer 骨架(对应 module_10032 的根状态 z6 / TOState 与根 reducer k6)
|
||||
//
|
||||
// 原包 k6 对 89 个切片逐个调用各自的 reducer,再 `return n.cti(...)`(copy 出新状态)。
|
||||
// 这里采用同一形状。已迁移的 43 个切片里,42 个真正调用 reducer,launchParams 只做类型收口:
|
||||
// 这里采用同一形状。已迁移的 53 个切片里,52 个真正调用 reducer,launchParams 只做类型收口:
|
||||
//
|
||||
// inviteState → ReduceInvite(aD / pD.er5)
|
||||
// loginByPassword → ReduceLoginByPassword(gD / MD.cr6)
|
||||
@@ -45,17 +45,30 @@
|
||||
// creatorTagState → ReduceCreatorTag(qO / ze.er2,根委派 `ze.er2(t, n.spx_1)`)
|
||||
// rewardedVideosState → ReduceRewardedVideos(JQ / xh.zsl,根委派 `xh.zsl(t, n.upx_1)`)
|
||||
// passwordChangeState → ReducePasswordChange(VD / uu.pr6,根委派 `uu.pr6(t, n.lpv_1)`)
|
||||
// system → ReduceSystem(_9 / w9().xt9,根委派 `w9().xt9(t, n.mpv_1)`)
|
||||
// contextTutorial → ReduceContextTutorial(Mst / Jst().tth,根委派 `Jst().tth(t, n.ypx_1)`)
|
||||
// battleTutorial → ReduceBattleTutorial(rE / Q.sq8,根委派 `Q.sq8(t, n.cpv_1)`)
|
||||
// spectator → ReduceSpectator(HA / Li.jqm,根委派 `Li.jqm(t, n.lpx_1)`)
|
||||
// twoStepVerificationState → ReduceTwoStepVerification(x9 / _f.atb,根委派 `_f.atb(t, n.tpx_1)`)
|
||||
// antiAddiction → ReduceAntiAddiction(UC / W.iq8,根委派 `W.iq8(t, n.kpx_1)`)
|
||||
// moderation → ReduceModeration(NI / Ei.oqh,根委派 `Ei.oqh(t, n.mpx_1)`)
|
||||
// migrationState → ReduceMigrationState($it / Uv.rtg,根委派 `Uv.rtg(t, n.ipv_1)`)
|
||||
// register → ReduceRegister(Cit / cp.stg,根委派 `cp.stg(t, n.hpv_1)`)
|
||||
// userReportsState → ReduceUserReports(Zst / qot.zth,根委派 `(null == sd && new qot(), sd).zth(t, n.dpy_1)`)
|
||||
// launchParams → 无 reducer(原根 reducer 原样透传;默认 `ag()` = emptyMap())
|
||||
//
|
||||
// 其余 46 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 其余 36 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 所以一次 copy 里串起全部已迁移 reducer,与按动作路由再归约的结果一致。
|
||||
// 迁移进度与每个字段的证据见生成物 RootWiring.kt(不要手改)。
|
||||
package App.State
|
||||
|
||||
import App.State.Reducers.ReduceAccountSettings
|
||||
import App.State.Reducers.ReduceAnnouncement
|
||||
import App.State.Reducers.ReduceAntiAddiction
|
||||
import App.State.Reducers.ReduceBattleResult
|
||||
import App.State.Reducers.ReduceBattleTutorial
|
||||
import App.State.Reducers.ReduceCaptcha
|
||||
import App.State.Reducers.ReduceContextTutorial
|
||||
import App.State.Reducers.ReduceCreatorTag
|
||||
import App.State.Reducers.ReduceDroppableGold
|
||||
import App.State.Reducers.ReduceEntrance
|
||||
@@ -72,7 +85,9 @@ import App.State.Reducers.ReduceLootBoxes
|
||||
import App.State.Reducers.ReduceMainQuest
|
||||
import App.State.Reducers.ReduceAvailabilityByRank
|
||||
import App.State.Reducers.ReduceLobbyLoader
|
||||
import App.State.Reducers.ReduceMigrationState
|
||||
import App.State.Reducers.ReduceModalScreen
|
||||
import App.State.Reducers.ReduceModeration
|
||||
import App.State.Reducers.ReduceNews
|
||||
import App.State.Reducers.ReduceNotificationByCountry
|
||||
import App.State.Reducers.ReduceNotifications
|
||||
@@ -84,16 +99,21 @@ import App.State.Reducers.ReduceQuestCategories
|
||||
import App.State.Reducers.ReduceQuests
|
||||
import App.State.Reducers.ReduceRankUpDialog
|
||||
import App.State.Reducers.ReduceReferralEvent
|
||||
import App.State.Reducers.ReduceRegister
|
||||
import App.State.Reducers.ReduceRewardedVideos
|
||||
import App.State.Reducers.ReduceRulesUpdated
|
||||
import App.State.Reducers.ReduceScreen
|
||||
import App.State.Reducers.ReduceSecuritySettings
|
||||
import App.State.Reducers.ReduceSpectator
|
||||
import App.State.Reducers.ReduceSupportUrl
|
||||
import App.State.Reducers.ReduceSettings
|
||||
import App.State.Reducers.ReduceShop
|
||||
import App.State.Reducers.ReduceSystem
|
||||
import App.State.Reducers.ReduceTips
|
||||
import App.State.Reducers.ReduceTwitch
|
||||
import App.State.Reducers.ReduceTwoStepVerification
|
||||
import App.State.Reducers.ReduceUser
|
||||
import App.State.Reducers.ReduceUserReports
|
||||
|
||||
/** 根 reducer:`k6`。 */
|
||||
object RootReducer {
|
||||
@@ -150,6 +170,16 @@ object RootReducer {
|
||||
CreatorTagState = ReduceCreatorTag(State0.CreatorTagState, Action),
|
||||
RewardedVideosState = ReduceRewardedVideos(State0.RewardedVideosState, Action),
|
||||
PasswordChangeState = ReducePasswordChange(State0.PasswordChangeState, Action),
|
||||
System = ReduceSystem(State0.System, Action),
|
||||
ContextTutorial = ReduceContextTutorial(State0.ContextTutorial, Action),
|
||||
BattleTutorial = ReduceBattleTutorial(State0.BattleTutorial, Action),
|
||||
Spectator = ReduceSpectator(State0.Spectator, Action),
|
||||
TwoStepVerificationState = ReduceTwoStepVerification(State0.TwoStepVerificationState, Action),
|
||||
AntiAddiction = ReduceAntiAddiction(State0.AntiAddiction, Action),
|
||||
Moderation = ReduceModeration(State0.Moderation, Action),
|
||||
MigrationState = ReduceMigrationState(State0.MigrationState, Action),
|
||||
Register = ReduceRegister(State0.Register, Action),
|
||||
UserReportsState = ReduceUserReports(State0.UserReportsState, Action),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,12 @@ package App.State
|
||||
|
||||
import App.State.Reducers.AccountSettingsStateSlice
|
||||
import App.State.Reducers.AnnouncementStateSlice
|
||||
import App.State.Reducers.AntiAddictionStateSlice
|
||||
import App.State.Reducers.AvailabilityByRankStateSlice
|
||||
import App.State.Reducers.BattleResultStateSlice
|
||||
import App.State.Reducers.BattleTutorialStateSlice
|
||||
import App.State.Reducers.CaptchaStateSlice
|
||||
import App.State.Reducers.ContextTutorialStateSlice
|
||||
import App.State.Reducers.CreatorTagStateSlice
|
||||
import App.State.Reducers.DroppableGoldStateSlice
|
||||
import App.State.Reducers.EntranceStateSlice
|
||||
@@ -23,7 +26,9 @@ import App.State.Reducers.LocalBattleUserStateSlice
|
||||
import App.State.Reducers.LoginByPasswordStateSlice
|
||||
import App.State.Reducers.LootBoxesStateSlice
|
||||
import App.State.Reducers.MainQuestStateSlice
|
||||
import App.State.Reducers.MigrationStateSlice
|
||||
import App.State.Reducers.ModalScreenStateSlice
|
||||
import App.State.Reducers.ModerationStateSlice
|
||||
import App.State.Reducers.NewsStateSlice
|
||||
import App.State.Reducers.NotificationByCountryStateSlice
|
||||
import App.State.Reducers.NotificationsStateSlice
|
||||
@@ -35,16 +40,21 @@ import App.State.Reducers.QuestCategoriesStateSlice
|
||||
import App.State.Reducers.QuestsStateSlice
|
||||
import App.State.Reducers.RankUpDialogStateSlice
|
||||
import App.State.Reducers.ReferralEventStateSlice
|
||||
import App.State.Reducers.RegisterStateSlice
|
||||
import App.State.Reducers.RewardedVideosStateSlice
|
||||
import App.State.Reducers.RulesUpdatedStateSlice
|
||||
import App.State.Reducers.ScreenStateSlice
|
||||
import App.State.Reducers.SecuritySettingsStateSlice
|
||||
import App.State.Reducers.SettingsStateSlice
|
||||
import App.State.Reducers.ShopStateSlice
|
||||
import App.State.Reducers.SpectatorStateSlice
|
||||
import App.State.Reducers.SupportUrlStateSlice
|
||||
import App.State.Reducers.SystemStateSlice
|
||||
import App.State.Reducers.TipsStateSlice
|
||||
import App.State.Reducers.TwitchStateSlice
|
||||
import App.State.Reducers.TwoStepVerificationStateSlice
|
||||
import App.State.Reducers.UserStateSlice
|
||||
import App.State.Reducers.UserReportsStateSlice
|
||||
|
||||
/**
|
||||
* 原 `z6` / `TOState`:89 个切片字段,顺序与 toString 一致。
|
||||
@@ -59,8 +69,8 @@ data class RootState(
|
||||
val ModalScreen: ModalScreenStateSlice = ModalScreenStateSlice(),
|
||||
/** 原 battleStatistics(jR / rr.fqr)。未迁移:原样透传。 */
|
||||
val BattleStatistics: Any? = null,
|
||||
/** 原 battleTutorial(rE / Q.sq8)。未迁移:原样透传。 */
|
||||
val BattleTutorial: Any? = null,
|
||||
/** 原 battleTutorial(rE / Q.sq8)。已迁移。 */
|
||||
val BattleTutorial: BattleTutorialStateSlice = BattleTutorialStateSlice(),
|
||||
/** 原 garage(UB / hF)。已迁移。 */
|
||||
val Garage: GarageStateSlice = GarageStateSlice(),
|
||||
/** 原 garagePreview(IG / fs.eru)。已迁移。 */
|
||||
@@ -69,18 +79,18 @@ data class RootState(
|
||||
val Challenges: Any? = null,
|
||||
/** 原 loginByPassword(gD / nu.cr6)。已迁移。 */
|
||||
val LoginByPassword: LoginByPasswordStateSlice = LoginByPasswordStateSlice(),
|
||||
/** 原 register(Cit / cp.stg)。未迁移:原样透传。 */
|
||||
val Register: Any? = null,
|
||||
/** 原 migrationState($it / Uv.rtg)。未迁移:原样透传。 */
|
||||
val MigrationState: Any? = null,
|
||||
/** 原 register(Cit / cp.stg)。已迁移。 */
|
||||
val Register: RegisterStateSlice = RegisterStateSlice(),
|
||||
/** 原 migrationState($it / Uv.rtg)。已迁移。 */
|
||||
val MigrationState: MigrationStateSlice = MigrationStateSlice(),
|
||||
/** 原 inviteState(aD / Ke.er5)。已迁移。 */
|
||||
val InviteState: InviteStateSlice = InviteStateSlice(),
|
||||
/** 原 captchaState(jP / ar.iqt)。已迁移。 */
|
||||
val CaptchaState: CaptchaStateSlice = CaptchaStateSlice(),
|
||||
/** 原 passwordChangeState(VD / uu.pr6)。已迁移。 */
|
||||
val PasswordChangeState: PasswordChangeStateSlice = PasswordChangeStateSlice(),
|
||||
/** 原 system(_9 / w9().xt9)。未迁移:原样透传。 */
|
||||
val System: Any? = null,
|
||||
/** 原 system(_9 / w9().xt9)。已迁移。 */
|
||||
val System: SystemStateSlice = SystemStateSlice(),
|
||||
/** 原 quests(Frt / Yrt.otg)。已迁移。 */
|
||||
val Quests: QuestsStateSlice = QuestsStateSlice(),
|
||||
/** 原 chatState(LP / $r.wqv)。未迁移:原样透传。 */
|
||||
@@ -179,12 +189,12 @@ data class RootState(
|
||||
val Partner: Any? = null,
|
||||
/** 原 entrance(hD / Bv.pth)。已迁移。 */
|
||||
val Entrance: EntranceStateSlice = EntranceStateSlice(),
|
||||
/** 原 antiAddiction(UC / W.iq8)。未迁移:原样透传。 */
|
||||
val AntiAddiction: Any? = null,
|
||||
/** 原 spectator(HA / Li.jqm)。未迁移:原样透传。 */
|
||||
val Spectator: Any? = null,
|
||||
/** 原 moderation(NI / Ei.oqh)。未迁移:原样透传。 */
|
||||
val Moderation: Any? = null,
|
||||
/** 原 antiAddiction(UC / W.iq8)。已迁移。 */
|
||||
val AntiAddiction: AntiAddictionStateSlice = AntiAddictionStateSlice(),
|
||||
/** 原 spectator(HA / Li.jqm)。已迁移。 */
|
||||
val Spectator: SpectatorStateSlice = SpectatorStateSlice(),
|
||||
/** 原 moderation(NI / Ei.oqh)。已迁移。 */
|
||||
val Moderation: ModerationStateSlice = ModerationStateSlice(),
|
||||
/** 原 rulesUpdated(i1 / Ch.dsm)。已迁移。 */
|
||||
val RulesUpdated: RulesUpdatedStateSlice = RulesUpdatedStateSlice(),
|
||||
/** 原 announcement(lC / PC().rq5)。已迁移。 */
|
||||
@@ -197,8 +207,8 @@ data class RootState(
|
||||
val EventGoods: EventGoodsStateSlice = EventGoodsStateSlice(),
|
||||
/** 原 creatorTagState(qO / ze.er2)。已迁移。 */
|
||||
val CreatorTagState: CreatorTagStateSlice = CreatorTagStateSlice(),
|
||||
/** 原 twoStepVerificationState(x9 / _f.atb)。未迁移:原样透传。 */
|
||||
val TwoStepVerificationState: Any? = null,
|
||||
/** 原 twoStepVerificationState(x9 / _f.atb)。已迁移。 */
|
||||
val TwoStepVerificationState: TwoStepVerificationStateSlice = TwoStepVerificationStateSlice(),
|
||||
/** 原 rewardedVideosState(JQ / xh.zsl)。已迁移。 */
|
||||
val RewardedVideosState: RewardedVideosStateSlice = RewardedVideosStateSlice(),
|
||||
/** 原 twitchState(g9 / uf.gta)。已迁移。 */
|
||||
@@ -207,8 +217,8 @@ data class RootState(
|
||||
val Icons: IconsStateSlice = IconsStateSlice(),
|
||||
/** 原 itemNotifications(_1 / A1().dso)。未迁移:原样透传。 */
|
||||
val ItemNotifications: Any? = null,
|
||||
/** 原 contextTutorial(Mst / Jst().tth)。未迁移:原样透传。 */
|
||||
val ContextTutorial: Any? = null,
|
||||
/** 原 contextTutorial(Mst / Jst().tth)。已迁移。 */
|
||||
val ContextTutorial: ContextTutorialStateSlice = ContextTutorialStateSlice(),
|
||||
/** 原 suppliesTutorial(? / Uw.uth)。未迁移:原样透传。 */
|
||||
val SuppliesTutorial: Any? = null,
|
||||
/** 原 questCategories(zZ / th.lsh)。已迁移。 */
|
||||
@@ -217,8 +227,8 @@ data class RootState(
|
||||
val ProBattle: ProBattleStateSlice = ProBattleStateSlice(),
|
||||
/** 原 availabilityByRank(tet / $p.xth)。已迁移。 */
|
||||
val AvailabilityByRank: AvailabilityByRankStateSlice = AvailabilityByRankStateSlice(),
|
||||
/** 原 userReportsState(Zst / qot.zth)。未迁移:原样透传。 */
|
||||
val UserReportsState: Any? = null,
|
||||
/** 原 userReportsState(Zst / qot.zth)。已迁移。 */
|
||||
val UserReportsState: UserReportsStateSlice = UserReportsStateSlice(),
|
||||
/** 原 tankBuilderState(brt / wp.ati)。未迁移:原样透传。 */
|
||||
val TankBuilderState: Any? = null,
|
||||
/** 原 contractState(Ont / xv.bti)。未迁移:原样透传。 */
|
||||
|
||||
@@ -18,13 +18,13 @@ object RootWiring {
|
||||
SliceWiring("screen", "zpu_1", "WK", "dY().ks5", "dY().ks5(t, n.zpu_1)", listOf("ClearScreenStack", "DelayNextGoTo", "DisableBack", "DisableForeground", "DisplayMainEntranceScreen", "DisplayReauthorizationMessage", "EnableBack", "EnableForeground", "FilterScreenStack", "GoTo", "PopScreen", "PressedAnyButton", "ResetScreenStackOnNextGoTo")),
|
||||
SliceWiring("modalScreen", "apv_1", "nV", "Fs.js1", "Fs.js1(t, n.apv_1)", listOf("AddModal", "CloseCurrentModal", "RemoveCurrentByName", "RemoveModal")),
|
||||
SliceWiring("battleStatistics", "bpv_1", "jR", "rr.fqr", "rr.fqr(t, n.bpv_1)", listOf("?DR", "?HR", "?KR", "?PR", "?QR", "?UR", "?XR", "?YR", "?ZR", "?nP", "?tP", "Init", "InitBattleModeWithLevels", "SetBattleMode", "SetDisplayClientInfo", "SetFlagOrBallOwner", "SetRankRange", "SetReArmor", "SetRemainingTime", "SetRoundRestartTime", "UpdateFund", "UpdateScore")),
|
||||
SliceWiring("battleTutorial", "cpv_1", "rE", "Q.sq8", "Q.sq8(t, n.cpv_1)", listOf("?oE", "?sE", "SetFragsCount", "ShowMessage")),
|
||||
SliceWiring("battleTutorial", "cpv_1", "rE", "Q.sq8", "Q.sq8(t, n.cpv_1)", listOf("MarkMovementStarted", "ResetBattleTutorial", "SetFragsCount", "ShowMessage")),
|
||||
SliceWiring("garage", "dpv_1", "UB", "hF", "hF(t, n)", listOf("AddGarageItemCount", "AddNewItem", "AddOverdriveDescription", "AddRelatedBazooka", "AddRelatedResistanceModule", "AddToFavoriteItem", "BuyProtectionSlot", "ClearWaitServerItemMount", "GarageAddItemToDepot", "GarageApplyResistanceMount", "GarageBuyDevice", "GarageDeviceTrySetInfinityLifetime", "GarageDevicesLoadedAction", "GarageLoaded", "GarageMountItem", "GarageMountItems", "GarageRemoveDevice", "GarageRemoveDiscountForDevice", "GarageRemoveItemFromDepot", "GarageRemoveItemFromStore", "GarageResistanceUnMount", "GarageSelectAlteration", "GarageSelectItem", "GarageSelectShotSkin", "GarageSelectSkin", "GarageUnmountItem", "GarageUpdateItemCount", "GarageUpgradeItemAction", "GarageUpgradeItemConfirm", "GarageUpgradeItemCoolDownFinished", "GarageUpgradeItemCoolDownStarted", "GoTo", "HideVideoInDescription", "InitState", "RemoveFromFavoriteItem", "RemoveFromSale", "RemoveNewItem", "RemoveWaitServerItemMount", "ResetGarage", "ResetMountDelay", "SelectGarageCategory", "SetCooldownReduceEndTime", "SetGarageNotLoaded", "SetGarageObject", "SetGarageSkinsAction", "SetItemRarity", "SetItemsOnDepot", "SetItemsOnMarket", "SetMountedItems", "SetMountedShotSkinForItems", "SetMountedSkinForItems", "SetNewItems", "SetResistanceReadyToMount", "SetRestrictionMount", "ShowGarageDiscountNotification", "StartCooldownReduce", "SwitchingRowsScroll", "UpdateDiscount")),
|
||||
SliceWiring("garagePreview", "epv_1", "IG", "fs.eru", "fs.eru(t, n.epv_1)", listOf("AddRequestedItem", "CaptureScreenshot", "CaptureVideo", "ClearDroneData", "ClearGrenadeData", "ClearHasGrenades", "ClearHullData", "ClearWeaponData", "InitGarageResources", "ResetItem3dModelActionCache", "SetCaptureActions", "SetDrone", "SetExpectedItemId", "SetGrenadeData", "SetHasGrenades", "SetHullData", "SetMountedItemsProperties", "SetPaint", "SetWeaponData", "ShowRequest", "UpdatePreviewSettings", "UpdateViewStyle")),
|
||||
SliceWiring("challenges", "fpv_1", "CZ", "nh.hsj", "nh.hsj(t, n.fpv_1)", listOf("?LZ", "RemoveChallenge", "SetBattlePass", "SetBattlePassPackages", "SetChallenge", "SetRewardForDialog", "SetTakenBattlePassRewardIndex", "SetTakenFreeRewardIndex", "UpdateStars")),
|
||||
SliceWiring("loginByPassword", "gpv_1", "gD", "nu.cr6", "nu.cr6(t, n.gpv_1)", listOf("?ND", "?PD", "?RD", "IncorrectLogin2FA", "RequestsNumber2FA", "SetLogin", "SetPassword", "SetRememberMe", "SetStatus")),
|
||||
SliceWiring("register", "hpv_1", "Cit", "cp.stg", "cp.stg(t, n.hpv_1)", listOf("?Bit", "?Dit", "?Fit", "?Git", "?Hit", "?Lit", "?Mit", "?Uit", "?_rt", "?hrt", "EnteredUidIsBusy", "ForceSetUid", "ReceiveOAuthUri", "SetOpenedPassword", "SetPassword", "SetPasswordRestrictions", "SetUid", "SocialNetworkAvailability", "SocialNetworkClientIds")),
|
||||
SliceWiring("migrationState", "ipv_1", "\$it", "Uv.rtg", "Uv.rtg(t, n.ipv_1)", listOf("?Bit", "?Dit", "?Fit", "?Git", "?Hit", "?Lit", "?_rt", "EnteredUidIsBusy", "ForceSetUid", "SetPassword", "SetUid")),
|
||||
SliceWiring("register", "hpv_1", "Cit", "cp.stg", "cp.stg(t, n.hpv_1)", listOf("DisableRegister", "EnteredUidIsBusy", "ForceSetUid", "ReceiveOAuthUri", "RegisterFailed", "RegisterPasswordCorrect", "RegisterPasswordIncorrect", "ResetAuthenticationForm", "ResetRegisterStatus", "ResetUidStatus", "SetOpenedPassword", "SetPassword", "SetPasswordRestrictions", "SetUid", "SocialNetworkAvailability", "SocialNetworkClientIds", "UidIsFree", "UidIsIncorrect", "UidTooShort")),
|
||||
SliceWiring("migrationState", "ipv_1", "\$it", "Uv.rtg", "Uv.rtg(t, n.ipv_1)", listOf("EnteredUidIsBusy", "ForceSetUid", "RegisterFailed", "RegisterPasswordIncorrect", "ResetAuthenticationForm", "ResetUidStatus", "SetPassword", "SetUid", "UidIsFree", "UidIsIncorrect", "UidTooShort")),
|
||||
SliceWiring("inviteState", "jpv_1", "aD", "Ke.er5", "Ke.er5(t, n.jpv_1)", listOf("ApplyInvite", "SetInviteNeed", "SetInviteStatus")),
|
||||
SliceWiring("captchaState", "kpv_1", "jP", "ar.iqt", "ar.iqt(t, n.kpv_1)", listOf("AddCaptchaLocationToReset", "AddVerifiedCaptchaLocation", "LocationsUpdated", "RemoveCaptchaLocationToReset", "RemoveVerifiedCaptchaLocation", "SetLocations", "ShowFakeCaptcha")),
|
||||
SliceWiring("passwordChangeState", "lpv_1", "VD", "uu.pr6", "uu.pr6(t, n.lpv_1)", listOf("SetPasswordChangeHash", "ShowEmailAndPasswordChangeDialog")),
|
||||
@@ -78,9 +78,9 @@ object RootWiring {
|
||||
SliceWiring("launchParams", "hpx_1", "?", "(pass-through)", "n.hpx_1", listOf()),
|
||||
SliceWiring("partner", "ipx_1", "UJ", "(inline@partner)", "(function (t, n) { var i; if (t instanceof VJ) i = n.osf(t.rsf_1, cd, cd, cd, cd, cd, cd, cd, cd, cd, t.ssf_1); else if (t instanceof nZ) { var r = t.bsg_1, e = t.csg_1, u = t.dsg_1, s = t.esg_1, o = t.fsg_1, _ = t.gsg_1; i = n.osf(cd, cd, cd, r, e, u, cd, cd, o, _, s); } else i = t instanceof iZ ? n.osf(cd, t.hsg_1) : t instanceof uZ ? n.osf(cd, cd, t.ksg_1) : t instanceof eZ ? n.osf(cd, cd, cd, cd, cd, cd, cd, t.jsg_1) : t instanceof _Z ? n.osf(cd, cd, cd, cd, cd, cd, t.osg_1) : t instanceof X …", listOf("?JJ", "?_Z", "?hZ", "?tZ", "InitPartnerInviteAction", "InitSocialNetworkParameters", "SetLoginParams", "SetLoginStatusForBinding", "SetPartnerId", "SetPartnerParameters", "SetPartnerReady")),
|
||||
SliceWiring("entrance", "jpx_1", "hD", "Bv.pth", "Bv.pth(t, n.jpx_1)", listOf("HideSocialNetworks", "SetAgeWarnShow", "SetAuthorizedByChinaSdkToken", "SetClassic", "SetControlsForChina", "SetRunningInChinaDataCenter", "SetRunningInChinaPartners")),
|
||||
SliceWiring("antiAddiction", "kpx_1", "UC", "W.iq8", "W.iq8(t, n.kpx_1)", listOf("?FC", "?XC", "?YC", "SetRealNameAndIdNumber", "SetValidateAntiAddictionUserDataStatus")),
|
||||
SliceWiring("spectator", "lpx_1", "HA", "Li.jqm", "Li.jqm(t, n.lpx_1)", listOf("?JA", "?XA", "?YA", "?ZA", "SetSpectator", "UpdateHudLayout")),
|
||||
SliceWiring("moderation", "mpx_1", "NI", "Ei.oqh", "Ei.oqh(t, n.mpx_1)", listOf("?FI", "?GI", "?JI", "?KI", "?QI", "?UI", "?WI", "?XI", "?YI", "?ZI", "?nA", "?tA", "?uA")),
|
||||
SliceWiring("antiAddiction", "kpx_1", "UC", "W.iq8", "W.iq8(t, n.kpx_1)", listOf("EnableRealNameCheck", "RequireUserIdVerification", "SetRealNameAndIdNumber", "SetValidateAntiAddictionUserDataStatus", "UpdatePlayingTime")),
|
||||
SliceWiring("spectator", "lpx_1", "HA", "Li.jqm", "Li.jqm(t, n.lpx_1)", listOf("AddSpectator", "RemoveSpectator", "SetSpectator", "SetSpectators", "SetSpectatorsListVisible", "UpdateHudLayout")),
|
||||
SliceWiring("moderation", "mpx_1", "NI", "Ei.oqh", "Ei.oqh(t, n.mpx_1)", listOf("AddSelectedUser", "AddSelectedUserFromChat", "ClearSelectedUsers", "HideBattleInfo", "HideBlockUserMenu", "HideModerationSystemMessage", "RemoveSelectedUser", "ResetSelectedUsers", "SetModerationUrlTemplates", "SetModeratorModes", "ShowBattleInfo", "ShowBlockUserMenu", "ShowModerationSystemMessage")),
|
||||
SliceWiring("rulesUpdated", "npx_1", "i1", "Ch.dsm", "Ch.dsm(t, n.npx_1)", listOf("UpdateRules")),
|
||||
SliceWiring("announcement", "opx_1", "lC", "PC().rq5", "PC().rq5(t, n.opx_1)", listOf("DisableAnnouncement", "SetAnnouncementItems", "SetAnnouncementModelLoaded", "SetSkipNextPromotedAnnounce")),
|
||||
SliceWiring("notificationByCountry", "ppx_1", "gJ", "R_.ssd", "R_.ssd(t, n.ppx_1)", listOf("Init", "MarkHomeScreenDialogShown")),
|
||||
@@ -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")
|
||||
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")
|
||||
|
||||
/** 未迁移字段:归约时原样透传,作为后续迁移清单。 */
|
||||
val Unmigrated: List<SliceWiring> get() = All.filter { it.Field !in Migrated }
|
||||
|
||||
@@ -9,13 +9,15 @@
|
||||
// ⑥ 动作目录:816 个类与 138 个真实派发名对齐
|
||||
// ⑦ 回放:真实 toString 样例的类/字段/类型校验
|
||||
// ⑧ 全目录动作类都能按 KClass 路由
|
||||
// ⑨~㊿/51-53 切片 reducer:InviteState / LoginByPasswordState / TwitchState / HomeScreen / LocalBattleUserState /
|
||||
// ⑨~㊿/51-63 切片 reducer:InviteState / LoginByPasswordState / TwitchState / HomeScreen / LocalBattleUserState /
|
||||
// Shop(含 U7 类别表与 w3 物品表两个子 reducer)/ Screen / LootBoxes / Garage / GaragePreview / Entrance / User / Settings /
|
||||
// AccountSettings / ProBattle / Language / Announcement / 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;
|
||||
// CreatorTagState / RewardedVideosState / PasswordChangeState /
|
||||
// System / ContextTutorial / BattleTutorial / Spectator / TwoStepVerification / AntiAddiction /
|
||||
// Moderation / MigrationState / Register / UserReports;
|
||||
// ㉑ launchParams 是纯透传切片(无 reducer/动作),只做 Map 类型收口;⑭ 根 reducer 的 89 槽位委派
|
||||
//
|
||||
// 用法:$env:TANKIOFFLINE_STATE_TEST='1'; node …(见 TankiOffline/tools/RunStateTest.ps1)
|
||||
@@ -440,6 +442,98 @@ import App.State.SetPasswordChangeHash
|
||||
import App.State.ShowEmailAndPasswordChangeDialog
|
||||
import App.State.Reducers.PasswordChangeStateSlice
|
||||
import App.State.Reducers.ReducePasswordChange
|
||||
import App.State.DoShowMessage
|
||||
import App.State.SetFatalError
|
||||
import App.State.Reducers.SystemStateSlice
|
||||
import App.State.Reducers.ReduceSystem
|
||||
import App.State.LoadCurrentElement
|
||||
import App.State.MarkElementAsViewed
|
||||
import App.State.SetLoadedElements
|
||||
import App.State.SetMissionToElement
|
||||
import App.State.SetUnViewedElements
|
||||
import App.State.Reducers.ContextTutorialStateSlice
|
||||
import App.State.Reducers.ReduceContextTutorial
|
||||
import App.State.SetFragsCount
|
||||
import App.State.ShowMessage
|
||||
import App.State.Reducers.BattleTutorialStateSlice
|
||||
import App.State.Reducers.MarkMovementStarted
|
||||
import App.State.Reducers.ReduceBattleTutorial
|
||||
import App.State.Reducers.ResetBattleTutorial
|
||||
import App.State.SetSpectator
|
||||
import App.State.UpdateHudLayout
|
||||
import App.State.SpectatorInfo
|
||||
import App.State.Reducers.AddSpectator
|
||||
import App.State.Reducers.ReduceSpectator
|
||||
import App.State.Reducers.RemoveSpectator
|
||||
import App.State.Reducers.SetSpectators
|
||||
import App.State.Reducers.SetSpectatorsListVisible
|
||||
import App.State.Reducers.SpectatorStateSlice
|
||||
import App.State.ActivationStatus2FA
|
||||
import App.State.Enable2FaRequest
|
||||
import App.State.SetSecretAndQRCode
|
||||
import App.State.SetUse2FA
|
||||
import App.State.VerificationStatus
|
||||
import App.State.Reducers.ReduceTwoStepVerification
|
||||
import App.State.Reducers.TwoStepVerificationStateSlice
|
||||
import App.State.SetRealNameAndIdNumber
|
||||
import App.State.SetValidateAntiAddictionUserDataStatus
|
||||
import App.State.Reducers.AntiAddictionStateSlice
|
||||
import App.State.Reducers.EnableRealNameCheck
|
||||
import App.State.Reducers.ReduceAntiAddiction
|
||||
import App.State.Reducers.RequireUserIdVerification
|
||||
import App.State.Reducers.UpdatePlayingTime
|
||||
import App.State.Reducers.AddSelectedUser
|
||||
import App.State.Reducers.AddSelectedUserFromChat
|
||||
import App.State.Reducers.ClearSelectedUsers
|
||||
import App.State.Reducers.HideBattleInfo
|
||||
import App.State.Reducers.HideBlockUserMenu
|
||||
import App.State.Reducers.HideModerationSystemMessage
|
||||
import App.State.Reducers.ModerationStateSlice
|
||||
import App.State.Reducers.ModerationUserRecord
|
||||
import App.State.Reducers.ReduceModeration
|
||||
import App.State.Reducers.RemoveSelectedUser
|
||||
import App.State.Reducers.ResetSelectedUsers
|
||||
import App.State.Reducers.SetModerationUrlTemplates
|
||||
import App.State.Reducers.SetModeratorModes
|
||||
import App.State.Reducers.ShowBattleInfo
|
||||
import App.State.Reducers.ShowBlockUserMenu
|
||||
import App.State.Reducers.ShowModerationSystemMessage
|
||||
import App.State.EnteredUidIsBusy
|
||||
import App.State.ForceSetUid
|
||||
import App.State.SetUid
|
||||
import App.State.ReceiveOAuthUri
|
||||
import App.State.SetOpenedPassword
|
||||
import App.State.SetPasswordRestrictions
|
||||
import App.State.SocialNetworkAvailability
|
||||
import App.State.SocialNetworkClientIds
|
||||
import App.State.Reducers.DisableRegister
|
||||
import App.State.Reducers.MigrationLoginStatus
|
||||
import App.State.Reducers.MigrationRegisterStatus
|
||||
import App.State.Reducers.MigrationStateSlice
|
||||
import App.State.Reducers.ReduceMigrationState
|
||||
import App.State.Reducers.ReduceRegister
|
||||
import App.State.Reducers.RegisterFailed
|
||||
import App.State.Reducers.RegisterPasswordCorrect
|
||||
import App.State.Reducers.RegisterPasswordIncorrect
|
||||
import App.State.Reducers.RegisterStateSlice
|
||||
import App.State.Reducers.RegistrationStatus
|
||||
import App.State.Reducers.ResetAuthenticationForm
|
||||
import App.State.Reducers.ResetRegisterStatus
|
||||
import App.State.Reducers.ResetUidStatus
|
||||
import App.State.Reducers.UidIsFree
|
||||
import App.State.Reducers.UidIsIncorrect
|
||||
import App.State.Reducers.UidStatus
|
||||
import App.State.Reducers.UidTooShort
|
||||
import App.State.InitUserReports
|
||||
import App.State.ReportBattleChatMessage
|
||||
import App.State.ReportLobbyChatMessage
|
||||
import App.State.ReportProBattleName
|
||||
import App.State.SetAvailableGameReports
|
||||
import App.State.SetAvailableReports
|
||||
import App.State.Reducers.ReduceUserReports
|
||||
import App.State.Reducers.ReportEntry
|
||||
import App.State.Reducers.ReportKind
|
||||
import App.State.Reducers.UserReportsStateSlice
|
||||
import App.State.Reducers.UserRankBounds
|
||||
import App.State.Reducers.UserStateSlice
|
||||
import App.State.Reducers.ClearHullData
|
||||
@@ -867,7 +961,7 @@ object StateCheck {
|
||||
Check("切片 LocalBattleUser:接 Store 派发后状态已归约", Store.State.IsReArmorTemporaryDisabled)
|
||||
}
|
||||
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 43 个已迁移切片(42 归约 + launchParams 透传)
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 53 个已迁移切片(52 归约 + launchParams 透传)
|
||||
run {
|
||||
Check("根:根状态 89 个切片槽位", RootWiring.All.size == 89)
|
||||
Check(
|
||||
@@ -931,7 +1025,7 @@ object StateCheck {
|
||||
LocalBattleW.Reducer == "(inline@localBattleUserState)"
|
||||
)
|
||||
Check(
|
||||
"根:迁移表 = 43 个已迁移字段,其余 46 个待迁",
|
||||
"根:迁移表 = 53 个已迁移字段,其余 36 个待迁",
|
||||
RootReducer.Migrated ==
|
||||
setOf(
|
||||
"inviteState", "loginByPassword", "twitchState", "home",
|
||||
@@ -945,8 +1039,11 @@ object StateCheck {
|
||||
"tipsState", "rankUpDialogState", "battleResult", "captchaState",
|
||||
"modalScreen", "droppableGold", "eventGoods", "creatorTagState",
|
||||
"rewardedVideosState", "passwordChangeState",
|
||||
"system", "contextTutorial", "battleTutorial", "spectator",
|
||||
"twoStepVerificationState", "antiAddiction", "moderation",
|
||||
"migrationState", "register", "userReportsState",
|
||||
) &&
|
||||
RootWiring.Unmigrated.size == 46
|
||||
RootWiring.Unmigrated.size == 36
|
||||
)
|
||||
|
||||
// 一次 ReduceRoot 里多个切片各归约自己的动作,互不串片
|
||||
@@ -1002,7 +1099,7 @@ object StateCheck {
|
||||
S5.User.Uid == "user-1" && S5.Screen.Current == NamedScreen("Preloader")
|
||||
)
|
||||
Check("根:无关动作返回等值状态", ReduceRoot(S5, AddFrags(1)) == S5)
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 43/89")
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 53/89")
|
||||
|
||||
val Store = ReduxStore(RootState(), { S, A -> ReduceRoot(S, A) })
|
||||
Store.Dispatch(SetStatus("LOGGING_IN"))
|
||||
@@ -4120,6 +4217,604 @@ object StateCheck {
|
||||
)
|
||||
}
|
||||
|
||||
// 54 切片 reducer:System(_9 / w9().xt9,3 字段;2 个动作)
|
||||
run {
|
||||
val S0 = SystemStateSlice()
|
||||
Check(
|
||||
"切片 System:默认值完整",
|
||||
S0.Message == null && !S0.Restart && S0.FatalError == null
|
||||
)
|
||||
val S1 = ReduceSystem(S0, DoShowMessage("m", true))
|
||||
Check(
|
||||
"切片 System:DoShowMessage 写 message/restart",
|
||||
S1.Message == "m" && S1.Restart && S1.FatalError == null
|
||||
)
|
||||
val S2 = ReduceSystem(S1, SetFatalError("boom"))
|
||||
Check(
|
||||
"切片 System:SetFatalError 写 fatalError",
|
||||
S2.FatalError == "boom" && S2.Message == "m"
|
||||
)
|
||||
Check("切片 System:无关动作不改状态", ReduceSystem(S2, AddFrags(1)) == S2)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, SetFatalError("x"))
|
||||
Check(
|
||||
"根:SetFatalError 只动 system",
|
||||
Root1.System.FatalError == "x" && Root1.ContextTutorial == Root0.ContextTutorial
|
||||
)
|
||||
val W = RootWiring.ByField("system")!!
|
||||
Check(
|
||||
"根:system 委派到 _9 / w9().xt9",
|
||||
W.SliceClass == "_9" && W.Reducer == "w9().xt9" &&
|
||||
W.Actions.toSet() == setOf("DoShowMessage", "SetFatalError")
|
||||
)
|
||||
}
|
||||
|
||||
// 55 切片 reducer:ContextTutorial(Mst / Jst().tth,4 字段;5 个动作)
|
||||
run {
|
||||
val S0 = ContextTutorialStateSlice()
|
||||
Check(
|
||||
"切片 ContextTutorial:默认空表空 Map",
|
||||
S0.CurrentElement == null && S0.LoadedElements.isEmpty() &&
|
||||
S0.UnViewedElements.isEmpty() && S0.MissionToElement.isEmpty()
|
||||
)
|
||||
val S1 = ReduceContextTutorial(S0, LoadCurrentElement("e1"))
|
||||
Check("切片 ContextTutorial:LoadCurrentElement 写当前元素", S1.CurrentElement == "e1")
|
||||
val S2 = ReduceContextTutorial(
|
||||
ReduceContextTutorial(S1, SetUnViewedElements(listOf("a", "b"))),
|
||||
MarkElementAsViewed("a"),
|
||||
)
|
||||
Check(
|
||||
"切片 ContextTutorial:MarkElementAsViewed 从待看列表删一个",
|
||||
S2.UnViewedElements == listOf<Any?>("b")
|
||||
)
|
||||
val S3 = ReduceContextTutorial(
|
||||
ReduceContextTutorial(S2, SetLoadedElements(mapOf<Any?, Any?>("k" to 1))),
|
||||
SetMissionToElement(mapOf("m" to "e")),
|
||||
)
|
||||
Check(
|
||||
"切片 ContextTutorial:loadedElements / missionToElement 整体替换",
|
||||
S3.LoadedElements == mapOf<Any?, Any?>("k" to 1) &&
|
||||
S3.MissionToElement == mapOf("m" to "e")
|
||||
)
|
||||
Check(
|
||||
"切片 ContextTutorial:无关动作不改状态",
|
||||
ReduceContextTutorial(S3, AddFrags(1)) == S3
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, LoadCurrentElement("z"))
|
||||
Check(
|
||||
"根:LoadCurrentElement 只动 contextTutorial",
|
||||
Root1.ContextTutorial.CurrentElement == "z" && Root1.System == Root0.System
|
||||
)
|
||||
val W = RootWiring.ByField("contextTutorial")!!
|
||||
Check(
|
||||
"根:contextTutorial 委派到 Mst / Jst().tth 且 5 个动作",
|
||||
W.SliceClass == "Mst" && W.Reducer == "Jst().tth" &&
|
||||
W.Actions.toSet() == setOf(
|
||||
"LoadCurrentElement", "SetUnViewedElements", "MarkElementAsViewed",
|
||||
"SetLoadedElements", "SetMissionToElement",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// 56 切片 reducer:BattleTutorial(rE / Q.sq8,3 字段;4 个动作)
|
||||
run {
|
||||
val S0 = BattleTutorialStateSlice()
|
||||
Check(
|
||||
"切片 BattleTutorial:默认值完整",
|
||||
S0.Message == null && S0.FragsCount == 0 && !S0.MovementHasStarted
|
||||
)
|
||||
val S1 = ReduceBattleTutorial(S0, ShowMessage("m"))
|
||||
Check("切片 BattleTutorial:ShowMessage 写 message", S1.Message == "m")
|
||||
Check(
|
||||
"切片 BattleTutorial:SetFragsCount 写击杀数",
|
||||
ReduceBattleTutorial(S1, SetFragsCount(3)).FragsCount == 3
|
||||
)
|
||||
val S2 = ReduceBattleTutorial(S1, MarkMovementStarted)
|
||||
Check("切片 BattleTutorial:MarkMovementStarted 置位", S2.MovementHasStarted)
|
||||
Check(
|
||||
"切片 BattleTutorial:ResetBattleTutorial 整片复位",
|
||||
ReduceBattleTutorial(S2, ResetBattleTutorial) == BattleTutorialStateSlice()
|
||||
)
|
||||
Check(
|
||||
"切片 BattleTutorial:无关动作不改状态",
|
||||
ReduceBattleTutorial(S2, AddFrags(1)) == S2
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, MarkMovementStarted)
|
||||
Check(
|
||||
"根:MarkMovementStarted 只动 battleTutorial",
|
||||
Root1.BattleTutorial.MovementHasStarted && Root1.Spectator == Root0.Spectator
|
||||
)
|
||||
val W = RootWiring.ByField("battleTutorial")!!
|
||||
Check(
|
||||
"根:battleTutorial 委派到 rE / Q.sq8 且 4 个动作",
|
||||
W.SliceClass == "rE" && W.Reducer == "Q.sq8" &&
|
||||
W.Actions.toSet() == setOf(
|
||||
"ShowMessage", "SetFragsCount", "MarkMovementStarted", "ResetBattleTutorial",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// 57 切片 reducer:Spectator(HA / Li.jqm,4 字段;6 个动作)
|
||||
run {
|
||||
val S0 = SpectatorStateSlice()
|
||||
Check(
|
||||
"切片 Spectator:默认非观战、列表可见",
|
||||
!S0.IsSpectator && S0.Spectators.isEmpty() && S0.SpectatorsListVisible
|
||||
)
|
||||
val S1 = ReduceSpectator(S0, SetSpectator(true))
|
||||
Check("切片 Spectator:SetSpectator 写布尔", S1.IsSpectator)
|
||||
val S2 = ReduceSpectator(S1, AddSpectator(1L, "uid1", true, false))
|
||||
Check(
|
||||
"切片 Spectator:AddSpectator 追加 SpectatorInfo",
|
||||
S2.Spectators.size == 1 &&
|
||||
(S2.Spectators[0] as SpectatorInfo).userId == 1L
|
||||
)
|
||||
val S3 = ReduceSpectator(S2, AddSpectator(2L, "uid2", false, false))
|
||||
Check("切片 Spectator:第二个观战者入列", S3.Spectators.size == 2)
|
||||
Check(
|
||||
"切片 Spectator:RemoveSpectator 按 userId 删",
|
||||
ReduceSpectator(S3, RemoveSpectator(1L)).Spectators.size == 1
|
||||
)
|
||||
Check(
|
||||
"切片 Spectator:SetSpectators 整表替换",
|
||||
ReduceSpectator(S3, SetSpectators(listOf("x"))).Spectators == listOf<Any?>("x")
|
||||
)
|
||||
Check(
|
||||
"切片 Spectator:SetSpectatorsListVisible 写可见性",
|
||||
!ReduceSpectator(S3, SetSpectatorsListVisible(false)).SpectatorsListVisible
|
||||
)
|
||||
Check(
|
||||
"切片 Spectator:UpdateHudLayout 写布局",
|
||||
ReduceSpectator(S3, UpdateHudLayout("hud")).SpectatorHudLayout == "hud"
|
||||
)
|
||||
Check("切片 Spectator:无关动作不改状态", ReduceSpectator(S3, AddFrags(1)) == S3)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, SetSpectator(true))
|
||||
Check(
|
||||
"根:SetSpectator 只动 spectator",
|
||||
Root1.Spectator.IsSpectator && Root1.BattleTutorial == Root0.BattleTutorial
|
||||
)
|
||||
val W = RootWiring.ByField("spectator")!!
|
||||
Check(
|
||||
"根:spectator 委派到 HA / Li.jqm 且 6 个动作",
|
||||
W.SliceClass == "HA" && W.Reducer == "Li.jqm" &&
|
||||
W.Actions.toSet() == setOf(
|
||||
"SetSpectator", "UpdateHudLayout", "SetSpectators", "AddSpectator",
|
||||
"RemoveSpectator", "SetSpectatorsListVisible",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// 58 切片 reducer:TwoStepVerification(x9 / _f.atb,6 字段;5 个动作)
|
||||
run {
|
||||
val S0 = TwoStepVerificationStateSlice()
|
||||
Check(
|
||||
"切片 TwoStepVerification:默认值完整",
|
||||
!S0.IsUse2FA && !S0.IsActivated2FA && S0.QrCodeDataURI == null &&
|
||||
S0.SharedSecret == null && S0.VerificationStatus == null &&
|
||||
!S0.Enable2FaRequest
|
||||
)
|
||||
val S1 = ReduceTwoStepVerification(S0, SetUse2FA(true))
|
||||
Check("切片 TwoStepVerification:SetUse2FA 写开关", S1.IsUse2FA)
|
||||
val S2 = ReduceTwoStepVerification(S1, SetSecretAndQRCode("secret", "data"))
|
||||
Check(
|
||||
"切片 TwoStepVerification:SetSecretAndQRCode 同时写两字段",
|
||||
S2.SharedSecret == "secret" && S2.QrCodeDataURI == "data"
|
||||
)
|
||||
Check(
|
||||
"切片 TwoStepVerification:VerificationStatus(false) 写失败",
|
||||
ReduceTwoStepVerification(S2, VerificationStatus(false)).VerificationStatus == false
|
||||
)
|
||||
Check(
|
||||
"切片 TwoStepVerification:VerificationStatus(true) 视为已启用",
|
||||
ReduceTwoStepVerification(S2, VerificationStatus(true)).IsActivated2FA
|
||||
)
|
||||
Check(
|
||||
"切片 TwoStepVerification:VerificationStatus(null) 清空状态",
|
||||
ReduceTwoStepVerification(
|
||||
ReduceTwoStepVerification(S2, VerificationStatus(false)),
|
||||
VerificationStatus(null),
|
||||
).VerificationStatus == null
|
||||
)
|
||||
Check(
|
||||
"切片 TwoStepVerification:ActivationStatus2FA / Enable2FaRequest",
|
||||
!ReduceTwoStepVerification(S2, ActivationStatus2FA(false)).IsActivated2FA &&
|
||||
ReduceTwoStepVerification(S2, Enable2FaRequest(true)).Enable2FaRequest
|
||||
)
|
||||
Check(
|
||||
"切片 TwoStepVerification:无关动作不改状态",
|
||||
ReduceTwoStepVerification(S2, AddFrags(1)) == S2
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, SetUse2FA(true))
|
||||
Check(
|
||||
"根:SetUse2FA 只动 twoStepVerificationState",
|
||||
Root1.TwoStepVerificationState.IsUse2FA && Root1.Spectator == Root0.Spectator
|
||||
)
|
||||
val W = RootWiring.ByField("twoStepVerificationState")!!
|
||||
Check(
|
||||
"根:twoStepVerificationState 委派到 x9 / _f.atb 且 5 个动作",
|
||||
W.SliceClass == "x9" && W.Reducer == "_f.atb" &&
|
||||
W.Actions.toSet() == setOf(
|
||||
"SetUse2FA", "ActivationStatus2FA", "SetSecretAndQRCode",
|
||||
"VerificationStatus", "Enable2FaRequest",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// 59 切片 reducer:AntiAddiction(UC / W.iq8,8 字段;5 个动作)
|
||||
run {
|
||||
val S0 = AntiAddictionStateSlice()
|
||||
Check(
|
||||
"切片 AntiAddiction:默认值完整",
|
||||
!S0.IsEnableRealNameCheck && !S0.UnknownUserId && S0.UrlForEnterUserId == null &&
|
||||
S0.PlayingTimeInMinutes == 0 && S0.AlertMessage == "" &&
|
||||
S0.IdNumber == "" && S0.RealName == "" && S0.ValidateStatus == null
|
||||
)
|
||||
val S1 = ReduceAntiAddiction(S0, EnableRealNameCheck)
|
||||
Check("切片 AntiAddiction:EnableRealNameCheck 置位", S1.IsEnableRealNameCheck)
|
||||
val S2 = ReduceAntiAddiction(S1, RequireUserIdVerification("https://u"))
|
||||
Check(
|
||||
"切片 AntiAddiction:RequireUserIdVerification 写 unknown+url",
|
||||
S2.UnknownUserId && S2.UrlForEnterUserId == "https://u"
|
||||
)
|
||||
val S3 = ReduceAntiAddiction(S2, UpdatePlayingTime(180, "休息"))
|
||||
Check(
|
||||
"切片 AntiAddiction:UpdatePlayingTime 写时长与提示",
|
||||
S3.PlayingTimeInMinutes == 180 && S3.AlertMessage == "休息"
|
||||
)
|
||||
val S4 = ReduceAntiAddiction(S3, SetRealNameAndIdNumber("张三", "110"))
|
||||
Check(
|
||||
"切片 AntiAddiction:SetRealNameAndIdNumber 写实名与证件号",
|
||||
S4.RealName == "张三" && S4.IdNumber == "110"
|
||||
)
|
||||
Check(
|
||||
"切片 AntiAddiction:实名参数为 null 时保留旧值",
|
||||
ReduceAntiAddiction(S4, SetRealNameAndIdNumber(null, null)) == S4
|
||||
)
|
||||
Check(
|
||||
"切片 AntiAddiction:SetValidateAntiAddictionUserDataStatus 写状态",
|
||||
ReduceAntiAddiction(S4, SetValidateAntiAddictionUserDataStatus("ok"))
|
||||
.ValidateStatus == "ok"
|
||||
)
|
||||
Check("切片 AntiAddiction:无关动作不改状态", ReduceAntiAddiction(S4, AddFrags(1)) == S4)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, EnableRealNameCheck)
|
||||
Check(
|
||||
"根:EnableRealNameCheck 只动 antiAddiction",
|
||||
Root1.AntiAddiction.IsEnableRealNameCheck && Root1.Moderation == Root0.Moderation
|
||||
)
|
||||
val W = RootWiring.ByField("antiAddiction")!!
|
||||
Check(
|
||||
"根:antiAddiction 委派到 UC / W.iq8 且 5 个动作",
|
||||
W.SliceClass == "UC" && W.Reducer == "W.iq8" &&
|
||||
W.Actions.toSet() == setOf(
|
||||
"EnableRealNameCheck", "RequireUserIdVerification", "UpdatePlayingTime",
|
||||
"SetRealNameAndIdNumber", "SetValidateAntiAddictionUserDataStatus",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// 60 切片 reducer:Moderation(NI / Ei.oqh,11 字段;13 个动作)
|
||||
run {
|
||||
val S0 = ModerationStateSlice()
|
||||
Check(
|
||||
"切片 Moderation:默认值完整",
|
||||
!S0.ModeratorMode && !S0.BattleModeratorMode && !S0.EventOrganizerMode &&
|
||||
S0.ModerationToolBattleUrlTemplate == "" &&
|
||||
S0.ModerationToolUserUrlTemplate == "" && S0.BattleInfo == null &&
|
||||
!S0.ForceShowBattleInfo && S0.SystemMessage == "" &&
|
||||
!S0.ForceShowSystemMessage && !S0.ForceShowBlockUserMenu &&
|
||||
S0.SelectedUsers.isEmpty()
|
||||
)
|
||||
val S1 = ReduceModeration(S0, SetModeratorModes(true, false, true))
|
||||
Check(
|
||||
"切片 Moderation:SetModeratorModes 写三个开关",
|
||||
S1.ModeratorMode && !S1.BattleModeratorMode && S1.EventOrganizerMode
|
||||
)
|
||||
Check(
|
||||
"切片 Moderation:SetModerationUrlTemplates 写两个模板",
|
||||
ReduceModeration(S1, SetModerationUrlTemplates("b", "u"))
|
||||
.ModerationToolBattleUrlTemplate == "b"
|
||||
)
|
||||
val S2 = ReduceModeration(S1, ShowBattleInfo("info"))
|
||||
Check(
|
||||
"切片 Moderation:ShowBattleInfo 写面板并强制显示",
|
||||
S2.BattleInfo == "info" && S2.ForceShowBattleInfo
|
||||
)
|
||||
Check(
|
||||
"切片 Moderation:HideBattleInfo 取消强制显示",
|
||||
!ReduceModeration(S2, HideBattleInfo).ForceShowBattleInfo
|
||||
)
|
||||
val S3 = ReduceModeration(
|
||||
ReduceModeration(S2, AddSelectedUser(1L, 5, "a")),
|
||||
AddSelectedUserFromChat(1L, 9, "a2"),
|
||||
)
|
||||
Check(
|
||||
"切片 Moderation:选中用户按 userId 去重后追加",
|
||||
S3.SelectedUsers.size == 1 &&
|
||||
(S3.SelectedUsers[0] as ModerationUserRecord).userRank == 9
|
||||
)
|
||||
Check(
|
||||
"切片 Moderation:RemoveSelectedUser 按 userId 删",
|
||||
ReduceModeration(
|
||||
ReduceModeration(S3, AddSelectedUser(2L, 1, "b")),
|
||||
RemoveSelectedUser(1L),
|
||||
).SelectedUsers.size == 1
|
||||
)
|
||||
Check(
|
||||
"切片 Moderation:ClearSelectedUsers / ResetSelectedUsers 清空",
|
||||
ReduceModeration(S3, ClearSelectedUsers).SelectedUsers.isEmpty() &&
|
||||
ReduceModeration(S3, ResetSelectedUsers).SelectedUsers.isEmpty()
|
||||
)
|
||||
val S4 = ReduceModeration(S3, ShowModerationSystemMessage("hello"))
|
||||
Check(
|
||||
"切片 Moderation:ShowModerationSystemMessage 写消息并强制显示",
|
||||
S4.SystemMessage == "hello" && S4.ForceShowSystemMessage
|
||||
)
|
||||
Check(
|
||||
"切片 Moderation:HideModerationSystemMessage 取消强制显示",
|
||||
!ReduceModeration(S4, HideModerationSystemMessage).ForceShowSystemMessage
|
||||
)
|
||||
Check(
|
||||
"切片 Moderation:ShowBlockUserMenu / HideBlockUserMenu 切换",
|
||||
ReduceModeration(S4, ShowBlockUserMenu).ForceShowBlockUserMenu &&
|
||||
!ReduceModeration(S4, HideBlockUserMenu).ForceShowBlockUserMenu
|
||||
)
|
||||
Check("切片 Moderation:无关动作不改状态", ReduceModeration(S4, AddFrags(1)) == S4)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, ShowBlockUserMenu)
|
||||
Check(
|
||||
"根:ShowBlockUserMenu 只动 moderation",
|
||||
Root1.Moderation.ForceShowBlockUserMenu && Root1.AntiAddiction == Root0.AntiAddiction
|
||||
)
|
||||
val W = RootWiring.ByField("moderation")!!
|
||||
Check(
|
||||
"根:moderation 委派到 NI / Ei.oqh 且 13 个动作",
|
||||
W.SliceClass == "NI" && W.Reducer == "Ei.oqh" && W.Actions.size == 13
|
||||
)
|
||||
}
|
||||
|
||||
// 61 切片 reducer:MigrationState($it / Uv.rtg,7 字段;11 个动作)
|
||||
run {
|
||||
val S0 = MigrationStateSlice()
|
||||
Check(
|
||||
"切片 MigrationState:默认值完整",
|
||||
!S0.RequestLogin && S0.Login == "" && S0.ForceLogin == null &&
|
||||
S0.Password == "" &&
|
||||
S0.LoginStatus == MigrationLoginStatus.UNKNOWN &&
|
||||
S0.RegisterStatus == MigrationRegisterStatus.UNKNOWN &&
|
||||
S0.AdvisedUids.isEmpty()
|
||||
)
|
||||
val S1 = ReduceMigrationState(S0, SetUid("alice"))
|
||||
Check(
|
||||
"切片 MigrationState:SetUid 写 login 并复位状态",
|
||||
S1.Login == "alice" &&
|
||||
S1.LoginStatus == MigrationLoginStatus.UNKNOWN &&
|
||||
S1.RegisterStatus == MigrationRegisterStatus.UNKNOWN
|
||||
)
|
||||
Check(
|
||||
"切片 MigrationState:ForceSetUid 写 forceLogin",
|
||||
ReduceMigrationState(S1, ForceSetUid("forced")).ForceLogin == "forced"
|
||||
)
|
||||
Check(
|
||||
"切片 MigrationState:SetPassword 写 password",
|
||||
ReduceMigrationState(S1, SetPassword("pwd")).Password == "pwd"
|
||||
)
|
||||
Check(
|
||||
"切片 MigrationState:UidIsFree/UidIsIncorrect/UidTooShort 写 loginStatus",
|
||||
ReduceMigrationState(S1, UidIsFree).LoginStatus == MigrationLoginStatus.FREE &&
|
||||
ReduceMigrationState(S1, UidIsIncorrect).LoginStatus ==
|
||||
MigrationLoginStatus.INCORRECT &&
|
||||
ReduceMigrationState(S1, UidTooShort).LoginStatus ==
|
||||
MigrationLoginStatus.SHORT_NAME
|
||||
)
|
||||
val S2 = ReduceMigrationState(S1, EnteredUidIsBusy(listOf("u1")))
|
||||
Check(
|
||||
"切片 MigrationState:EnteredUidIsBusy 写 BUSY 与 advisedUids",
|
||||
S2.LoginStatus == MigrationLoginStatus.BUSY && S2.AdvisedUids == listOf<Any?>("u1")
|
||||
)
|
||||
Check(
|
||||
"切片 MigrationState:注册状态两支",
|
||||
ReduceMigrationState(S1, RegisterPasswordIncorrect).RegisterStatus ==
|
||||
MigrationRegisterStatus.PASSWORD_INCORRECT &&
|
||||
ReduceMigrationState(S1, RegisterFailed).RegisterStatus ==
|
||||
MigrationRegisterStatus.FAILED
|
||||
)
|
||||
Check(
|
||||
"切片 MigrationState:ResetUidStatus / ResetAuthenticationForm",
|
||||
ReduceMigrationState(S2, ResetUidStatus).LoginStatus ==
|
||||
MigrationLoginStatus.UNKNOWN &&
|
||||
ReduceMigrationState(S2, ResetAuthenticationForm).Login == ""
|
||||
)
|
||||
Check(
|
||||
"切片 MigrationState:无关动作不改状态",
|
||||
ReduceMigrationState(S2, AddFrags(1)) == S2
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, SetUid("bob"))
|
||||
Check(
|
||||
"根:SetUid 同时动 migrationState 与 register",
|
||||
Root1.MigrationState.Login == "bob" && Root1.Register.Login == "bob" &&
|
||||
Root1.System == Root0.System
|
||||
)
|
||||
val W = RootWiring.ByField("migrationState")!!
|
||||
Check(
|
||||
"根:migrationState 委派到 \$it / Uv.rtg 且 11 个动作",
|
||||
W.SliceClass == "\$it" && W.Reducer == "Uv.rtg" && W.Actions.size == 11
|
||||
)
|
||||
}
|
||||
|
||||
// 62 切片 reducer:Register(Cit / cp.stg,16 字段;19 个动作)
|
||||
run {
|
||||
val S0 = RegisterStateSlice()
|
||||
Check(
|
||||
"切片 Register:默认值完整",
|
||||
!S0.IsDisabled && S0.Login == "" && S0.ForceLogin == null && S0.Password == "" &&
|
||||
S0.UidValidationStatus == UidStatus.UNKNOWN &&
|
||||
S0.RegisterStatus == RegistrationStatus.UNKNOWN &&
|
||||
S0.AdvisedUids.isEmpty() && S0.SocialNetworkAvailability.isEmpty() &&
|
||||
S0.SocialNetworkClientIds == emptyMap<String, Any?>() &&
|
||||
S0.SocialNetworkOAuthData == null && S0.MinPasswordLength == 6 &&
|
||||
S0.MaxPasswordLength == 20 && !S0.PasswordNeedLower &&
|
||||
!S0.PasswordNeedUpper && !S0.PasswordNeedDigit && S0.OpenedPassword
|
||||
)
|
||||
val S1 = ReduceRegister(S0, DisableRegister)
|
||||
Check("切片 Register:DisableRegister 置灰", S1.IsDisabled)
|
||||
val S2 = ReduceRegister(S1, SetUid("alice"))
|
||||
Check(
|
||||
"切片 Register:SetUid 写 login 并复位 uid 状态",
|
||||
S2.Login == "alice" && S2.UidValidationStatus == UidStatus.UNKNOWN
|
||||
)
|
||||
Check(
|
||||
"切片 Register:原状态为 INCORRECT 时保留 registerStatus,否则复位",
|
||||
ReduceRegister(
|
||||
ReduceRegister(
|
||||
ReduceRegister(S2, RegisterFailed),
|
||||
UidIsIncorrect,
|
||||
),
|
||||
SetUid("alice2"),
|
||||
).RegisterStatus == RegistrationStatus.FAILED &&
|
||||
ReduceRegister(
|
||||
ReduceRegister(
|
||||
ReduceRegister(S2, RegisterFailed),
|
||||
ResetUidStatus,
|
||||
),
|
||||
SetUid("alice2"),
|
||||
).RegisterStatus == RegistrationStatus.UNKNOWN
|
||||
)
|
||||
val S3 = ReduceRegister(S2, EnteredUidIsBusy(listOf("u1")))
|
||||
Check(
|
||||
"切片 Register:EnteredUidIsBusy 写 BUSY + advisedUids",
|
||||
S3.UidValidationStatus == UidStatus.BUSY && S3.AdvisedUids == listOf<Any?>("u1")
|
||||
)
|
||||
Check(
|
||||
"切片 Register:uid 三个状态臂",
|
||||
ReduceRegister(S2, UidIsFree).UidValidationStatus == UidStatus.FREE &&
|
||||
ReduceRegister(S2, UidIsIncorrect).UidValidationStatus == UidStatus.INCORRECT &&
|
||||
ReduceRegister(S2, UidTooShort).UidValidationStatus == UidStatus.SHORT_NAME
|
||||
)
|
||||
Check(
|
||||
"切片 Register:注册状态四臂",
|
||||
ReduceRegister(S2, RegisterPasswordCorrect).RegisterStatus ==
|
||||
RegistrationStatus.PASSWORD_CORRECT &&
|
||||
ReduceRegister(S2, RegisterPasswordIncorrect).RegisterStatus ==
|
||||
RegistrationStatus.PASSWORD_INCORRECT &&
|
||||
ReduceRegister(S2, RegisterFailed).RegisterStatus == RegistrationStatus.FAILED &&
|
||||
ReduceRegister(S2, ResetRegisterStatus).RegisterStatus ==
|
||||
RegistrationStatus.UNKNOWN
|
||||
)
|
||||
val S4 = ReduceRegister(
|
||||
ReduceRegister(S2, SetPasswordRestrictions(8, 32, true, false, true)),
|
||||
SetOpenedPassword(false),
|
||||
)
|
||||
Check(
|
||||
"切片 Register:密码规则与展开开关",
|
||||
S4.MinPasswordLength == 8 && S4.MaxPasswordLength == 32 &&
|
||||
S4.PasswordNeedLower && !S4.PasswordNeedUpper && S4.PasswordNeedDigit &&
|
||||
!S4.OpenedPassword
|
||||
)
|
||||
Check(
|
||||
"切片 Register:社媒三支",
|
||||
ReduceRegister(S2, SocialNetworkAvailability(mapOf("vk" to true)))
|
||||
.SocialNetworkAvailability == mapOf("vk" to true) &&
|
||||
ReduceRegister(S2, SocialNetworkClientIds("cid"))
|
||||
.SocialNetworkClientIds == "cid" &&
|
||||
ReduceRegister(S2, ReceiveOAuthUri("oauth"))
|
||||
.SocialNetworkOAuthData == "oauth"
|
||||
)
|
||||
run {
|
||||
val R = ReduceRegister(S3, ResetAuthenticationForm)
|
||||
Check(
|
||||
"切片 Register:ResetAuthenticationForm 清 login 与两个状态",
|
||||
R.Login == "" && R.UidValidationStatus == UidStatus.UNKNOWN &&
|
||||
R.RegisterStatus == RegistrationStatus.UNKNOWN &&
|
||||
R.AdvisedUids == S3.AdvisedUids
|
||||
)
|
||||
}
|
||||
Check("切片 Register:无关动作不改状态", ReduceRegister(S4, AddFrags(1)) == S4)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, RegisterFailed)
|
||||
Check(
|
||||
"根:RegisterFailed 同时动 migrationState 与 register",
|
||||
Root1.Register.RegisterStatus == RegistrationStatus.FAILED &&
|
||||
Root1.MigrationState.RegisterStatus ==
|
||||
MigrationRegisterStatus.FAILED
|
||||
)
|
||||
val W = RootWiring.ByField("register")!!
|
||||
Check(
|
||||
"根:register 委派到 Cit / cp.stg 且 19 个动作",
|
||||
W.SliceClass == "Cit" && W.Reducer == "cp.stg" && W.Actions.size == 19
|
||||
)
|
||||
}
|
||||
|
||||
// 63 切片 reducer:UserReports(Zst / qot.zth,5 字段;6 个动作)
|
||||
run {
|
||||
val S0 = UserReportsStateSlice()
|
||||
Check(
|
||||
"切片 UserReports:默认值完整",
|
||||
!S0.IsEnabled && !S0.HelpdeskTicketsEnabled && S0.AvailableReports == 0 &&
|
||||
S0.AvailableGameReports == 0 && S0.Reports.isEmpty()
|
||||
)
|
||||
val S1 = ReduceUserReports(S0, InitUserReports(true, true, 5, 3))
|
||||
Check(
|
||||
"切片 UserReports:InitUserReports 写四个开关/额度",
|
||||
S1.IsEnabled && S1.HelpdeskTicketsEnabled &&
|
||||
S1.AvailableReports == 5 && S1.AvailableGameReports == 3
|
||||
)
|
||||
Check(
|
||||
"切片 UserReports:SetAvailableReports / SetAvailableGameReports",
|
||||
ReduceUserReports(S1, SetAvailableReports(7)).AvailableReports == 7 &&
|
||||
ReduceUserReports(S1, SetAvailableGameReports(9)).AvailableGameReports == 9
|
||||
)
|
||||
val S2 = ReduceUserReports(S1, ReportProBattleName("b1"))
|
||||
Check(
|
||||
"切片 UserReports:ReportProBattleName 追加 BATTLE_NAME 记录",
|
||||
S2.Reports.size == 1 &&
|
||||
(S2.Reports[0] as ReportEntry).kind == ReportKind.BATTLE_NAME &&
|
||||
(S2.Reports[0] as ReportEntry).targetId == "b1" &&
|
||||
(S2.Reports[0] as ReportEntry).expireTime > 0.0
|
||||
)
|
||||
val S3 = ReduceUserReports(
|
||||
ReduceUserReports(S2, ReportLobbyChatMessage("m1")),
|
||||
ReportBattleChatMessage("m2"),
|
||||
)
|
||||
Check(
|
||||
"切片 UserReports:两种聊天举报各追加一条",
|
||||
S3.Reports.size == 3 &&
|
||||
(S3.Reports[1] as ReportEntry).kind == ReportKind.LOBBY_CHAT_MESSAGE &&
|
||||
(S3.Reports[2] as ReportEntry).kind == ReportKind.BATTLE_CHAT_MESSAGE
|
||||
)
|
||||
Check(
|
||||
"切片 UserReports:无关动作不改状态",
|
||||
ReduceUserReports(S3, AddFrags(1)) == S3
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, ReportProBattleName("b"))
|
||||
Check(
|
||||
"根:ReportProBattleName 只动 userReportsState",
|
||||
Root1.UserReportsState.Reports.size == 1 &&
|
||||
Root1.Register == Root0.Register
|
||||
)
|
||||
val W = RootWiring.ByField("userReportsState")!!
|
||||
Check(
|
||||
"根:userReportsState 委派到 Zst / qot.zth 且 6 个动作",
|
||||
W.SliceClass == "Zst" && W.Reducer == "qot.zth" && W.Actions.size == 6
|
||||
)
|
||||
}
|
||||
|
||||
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