feat(state): 迁移 matchmaking
This commit is contained in:
1 parent
9e51b695aa
commit
71aa9a5256
8 files changed
+267
-23
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` 动作名。
|
||||
- 已迁移切片 **79/89**:
|
||||
- 已迁移切片 **80/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)
|
||||
@@ -398,12 +398,17 @@
|
||||
没有缓存条目的 userId 不新建(原 reducer 直接返回原状态)。
|
||||
用户数据模型直接复用生成物 `RemoteUserData`,战斗 / 在线 / 会员状态用
|
||||
`BattleNotifierData` / `OnlineNotifierData` / `PremiumNotifierData`。
|
||||
- `matchmaking` → `TH` / `JH().qrx`(`MatchmakingReducer.kt`):19 字段,9 个实例臂。
|
||||
`Configure` 一次写 12 个字段(模式表 / 禁用列表 / 节日与活动 / 团队人数);
|
||||
`WasRegistered` 写等待时间与模式并清 `requestSent`;`EnterToBattleApply` 同时置两个进行中位;
|
||||
`WH`→`ResetMatchmakingProgress`、`tW`/`nW`→`StartLoadingBattle`/`CancelLoadingBattle`;
|
||||
模式表复用生成物 `MatchmakingModeRank`,`rankIndexToMinGS` 收口为 `Map<String, Int>`。
|
||||
- `launchParams` → `(pass-through)`:原根 reducer 对 `hpx_1` 没有调用,缺省是 `ag()` 空 Map;
|
||||
`RootState.LaunchParams` 收口为 `LaunchParamsStateSlice = Map<String, String>`,不新增 reducer/动作。
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 78 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **10 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 79/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **859 项全绿**,含 89 槽位完整性、78 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 79 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **9 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 80/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **871 项全绿**,含 89 槽位完整性、79 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
以及用 `action_trace_merged.json` 真实派发的两条商店动作(`SetCoinPaymentProviderUrl` / `ToggleShopActivity`)回放。
|
||||
- 委派表里的已知形态:`shop` / `home` / `localBattleUserState` / `partner` 是内联 IIFE,
|
||||
已按字段具名为 `(inline@<field>)` 并从函数体抓到顶层动作名(69 / 1 / 2 / 11 个);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generatedAt": "2026-10-24T12:12:10.770Z",
|
||||
"generatedAt": "2026-10-24T12:37:28.603Z",
|
||||
"module": "module_10032.js",
|
||||
"RootState": {
|
||||
"Class": "z6",
|
||||
@@ -85,7 +85,8 @@
|
||||
"battleMessage",
|
||||
"maps",
|
||||
"battleChat",
|
||||
"remoteUserDataStorage"
|
||||
"remoteUserDataStorage",
|
||||
"matchmaking"
|
||||
],
|
||||
"AnonymousActions": [
|
||||
{
|
||||
@@ -1413,6 +1414,24 @@
|
||||
"Name": "ResetBattleChat",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "new Q6() 整片复位"
|
||||
},
|
||||
{
|
||||
"Local": "WH",
|
||||
"Name": "ResetMatchmakingProgress",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "matchmakingAndLoadingBattleInProgress=false、startLoadingBattle=false、requestSent=false"
|
||||
},
|
||||
{
|
||||
"Local": "tW",
|
||||
"Name": "StartLoadingBattle",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "startLoadingBattle=true(`n.brw(cd, cd, cd, cd, !0)`)"
|
||||
},
|
||||
{
|
||||
"Local": "nW",
|
||||
"Name": "CancelLoadingBattle",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "startLoadingBattle=false(`n.brw(cd, cd, cd, cd, !1)`)"
|
||||
}
|
||||
],
|
||||
"Markers": [
|
||||
@@ -2180,18 +2199,18 @@
|
||||
"Reducer": "JH().qrx",
|
||||
"Delegate": "JH().qrx(t, n.cpw_1)",
|
||||
"Actions": [
|
||||
"?WH",
|
||||
"?nW",
|
||||
"?tW",
|
||||
"CancelLoadingBattle",
|
||||
"Configure",
|
||||
"EnterToBattleApply",
|
||||
"Play",
|
||||
"ResetMatchmakingProgress",
|
||||
"SelectMatchmakingMode",
|
||||
"SetRankIndexToMinGS",
|
||||
"StartLoadingBattle",
|
||||
"WasRegistered"
|
||||
],
|
||||
"Default": "new TH()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "battleCreateState",
|
||||
|
||||
@@ -323,6 +323,10 @@ const AnonymousActionNames = new Map([
|
||||
['utt', 'CloseBattleChatInput'],
|
||||
['stt', 'ToggleBattleChatHistory'],
|
||||
['rtt', 'ResetBattleChat'],
|
||||
// matchmaking 切片(TH / XH.qrx):WH/tW/nW 没有 toString。
|
||||
['WH', 'ResetMatchmakingProgress'],
|
||||
['tW', 'StartLoadingBattle'],
|
||||
['nW', 'CancelLoadingBattle'],
|
||||
]);
|
||||
|
||||
// 非动作的 `instanceof`:屏幕标识类,用于 GoTo 分支判断(不是 dispatch 的动作)。
|
||||
@@ -806,6 +810,7 @@ const Migrated = {
|
||||
Type: 'RemoteUserDataStorageStateSlice',
|
||||
Reduce: 'ReduceRemoteUserDataStorage',
|
||||
},
|
||||
matchmaking: { Type: 'MatchmakingStateSlice', Reduce: 'ReduceMatchmaking' },
|
||||
};
|
||||
|
||||
for (const R of Rows) R.Migrated = Object.prototype.hasOwnProperty.call(Migrated, R.Field);
|
||||
@@ -1218,6 +1223,9 @@ const AppSettingsAnonymousEffects = {
|
||||
utt: 'isInputActive=false(`n.ctl(cd, cd, cd, cd, !1)`)',
|
||||
stt: 'isHistoryOpen=!isHistoryOpen(`n.ctl(cd, cd, cd, cd, cd, !n.atl_1)`)',
|
||||
rtt: 'new Q6() 整片复位',
|
||||
WH: 'matchmakingAndLoadingBattleInProgress=false、startLoadingBattle=false、requestSent=false',
|
||||
tW: 'startLoadingBattle=true(`n.brw(cd, cd, cd, cd, !0)`)',
|
||||
nW: 'startLoadingBattle=false(`n.brw(cd, cd, cd, cd, !1)`)',
|
||||
};
|
||||
|
||||
fs.writeFileSync(
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
// MatchmakingReducer.kt —— 匹配大厅切片(对应 module_10032 的 TH 状态 + XH.qrx)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 TH:19 个字段,toString 名 "MatchmakingState(…)";copy 是 brw(19 字段 + 回调)。
|
||||
// 根委派:`JH().qrx(t, n.cpw_1)`。
|
||||
// reducer(7 个实例臂):
|
||||
// MH(Play) → requestSent=true
|
||||
// NH(Configure) → 模式表 / 禁用列表 / 节日与活动 12 个字段
|
||||
// LH(SelectMatchmakingMode)→ selectedMatchmakingMode
|
||||
// DH(WasRegistered) → 4th=true、avgWaitTimeInSeconds、mode、requestSent=false
|
||||
// GH(EnterToBattleApply) → 4th=true、5th=true
|
||||
// WH(无 toString) → 4th=false、5th=false、requestSent=false
|
||||
// tW / nW(无 toString) → startLoadingBattle = true / false
|
||||
// VH(SetRankIndexToMinGS) → rankIndexToMinGS
|
||||
//
|
||||
// 模式表模型直接复用生成物 `MatchmakingModeRank`(matchmakingMode, rank)。
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.Configure
|
||||
import App.State.EnterToBattleApply
|
||||
import App.State.MatchmakingModeRank
|
||||
import App.State.Play
|
||||
import App.State.SelectMatchmakingMode
|
||||
import App.State.SetRankIndexToMinGS
|
||||
import App.State.WasRegistered
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
/** 原 `WH`:退出匹配 / 进入战斗失败,清掉进行中的标记。 */
|
||||
object ResetMatchmakingProgress
|
||||
|
||||
/** 原 `tW` / `nW`:开始 / 取消读条。 */
|
||||
object StartLoadingBattle
|
||||
object CancelLoadingBattle
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class MatchmakingStateSlice(
|
||||
val MatchmakingModeRanks: List<MatchmakingModeRank> = emptyList(),
|
||||
val SelectedMatchmakingMode: Any? = null,
|
||||
val DisabledModes: Set<Any?> = emptySet(),
|
||||
val MatchmakingAndLoadingBattleInProgress: Boolean = false,
|
||||
val StartLoadingBattle: Boolean = false,
|
||||
val HolidayEnabled: Boolean = false,
|
||||
val HolidayTitle: String = "",
|
||||
val HolidayIcon: Any? = null,
|
||||
val EventBigTile: Any? = null,
|
||||
val HolidayDescription: String = "",
|
||||
val MinRankForProBattle: Int = Int.MAX_VALUE,
|
||||
val AvgWaitTimeInSeconds: Any? = 0,
|
||||
val Mode: Any? = null,
|
||||
val MaxUsersInGroup: Int = 3,
|
||||
val GroupsInEventMode: Boolean = false,
|
||||
val EventEndDate: Any? = null,
|
||||
val BorderColorForEventButton: Any? = null,
|
||||
val RequestSent: Boolean = false,
|
||||
val RankIndexToMinGS: Map<String, Int> = emptyMap(),
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceMatchmaking(
|
||||
State0: MatchmakingStateSlice,
|
||||
Action: Any,
|
||||
): MatchmakingStateSlice = when (Action) {
|
||||
is Play -> State0.copy(RequestSent = true)
|
||||
is Configure -> State0.copy(
|
||||
MatchmakingModeRanks = Action.modes,
|
||||
DisabledModes = Action.disabledModes.toSet(),
|
||||
HolidayEnabled = Action.holidayEnabled,
|
||||
HolidayTitle = Action.holidayTitle,
|
||||
HolidayIcon = Action.holidayIcon,
|
||||
EventBigTile = Action.eventBigTile,
|
||||
HolidayDescription = Action.holidayDescription,
|
||||
MinRankForProBattle = Action.minRankForProBattle,
|
||||
MaxUsersInGroup = Action.maxUsersInGroup,
|
||||
GroupsInEventMode = Action.groupsInEventMode,
|
||||
EventEndDate = Action.eventEndDate,
|
||||
BorderColorForEventButton = Action.borderColorForEventButton,
|
||||
)
|
||||
is SelectMatchmakingMode ->
|
||||
State0.copy(SelectedMatchmakingMode = Action.matchmakingMode)
|
||||
is WasRegistered -> State0.copy(
|
||||
MatchmakingAndLoadingBattleInProgress = true,
|
||||
AvgWaitTimeInSeconds = Action.avgWaitTimeInSeconds,
|
||||
Mode = Action.mode,
|
||||
RequestSent = false,
|
||||
)
|
||||
is EnterToBattleApply -> State0.copy(
|
||||
MatchmakingAndLoadingBattleInProgress = true,
|
||||
StartLoadingBattle = true,
|
||||
)
|
||||
is ResetMatchmakingProgress -> State0.copy(
|
||||
MatchmakingAndLoadingBattleInProgress = false,
|
||||
StartLoadingBattle = false,
|
||||
RequestSent = false,
|
||||
)
|
||||
is StartLoadingBattle -> State0.copy(StartLoadingBattle = true)
|
||||
is CancelLoadingBattle -> State0.copy(StartLoadingBattle = false)
|
||||
is SetRankIndexToMinGS -> State0.copy(RankIndexToMinGS = Action.rankIndexToMinGS)
|
||||
else -> State0
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// RootReducer.kt —— 根 reducer 骨架(对应 module_10032 的根状态 z6 / TOState 与根 reducer k6)
|
||||
//
|
||||
// 原包 k6 对 89 个切片逐个调用各自的 reducer,再 `return n.cti(...)`(copy 出新状态)。
|
||||
// 这里采用同一形状。已迁移的 79 个切片里,78 个真正调用 reducer,launchParams 只做类型收口:
|
||||
// 这里采用同一形状。已迁移的 80 个切片里,79 个真正调用 reducer,launchParams 只做类型收口:
|
||||
//
|
||||
// inviteState → ReduceInvite(aD / pD.er5)
|
||||
// loginByPassword → ReduceLoginByPassword(gD / MD.cr6)
|
||||
@@ -81,9 +81,10 @@
|
||||
// maps → ReduceMaps(OA / Oi.sql,根委派 `Oi.sql(t, n.bpw_1)`)
|
||||
// battleChat → ReduceBattleChat(Q6 / Hf.wtg,根委派 `Hf.wtg(t, n.rpw_1)`)
|
||||
// remoteUserDataStorage → ReduceRemoteUserDataStorage($Q / vh.isl,根委派 `vh.isl(t, n.zpv_1)`)
|
||||
// matchmaking → ReduceMatchmaking(TH / JH().qrx,根委派 `JH().qrx(t, n.cpw_1)`)
|
||||
// launchParams → 无 reducer(原根 reducer 原样透传;默认 `ag()` = emptyMap())
|
||||
//
|
||||
// 其余 10 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 其余 9 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 所以一次 copy 里串起全部已迁移 reducer,与按动作路由再归约的结果一致。
|
||||
// 迁移进度与每个字段的证据见生成物 RootWiring.kt(不要手改)。
|
||||
package App.State
|
||||
@@ -125,6 +126,7 @@ import App.State.Reducers.ReduceLocalBattleUser
|
||||
import App.State.Reducers.ReduceLoginByPassword
|
||||
import App.State.Reducers.ReduceLootBoxes
|
||||
import App.State.Reducers.ReduceMainQuest
|
||||
import App.State.Reducers.ReduceMatchmaking
|
||||
import App.State.Reducers.ReduceMaps
|
||||
import App.State.Reducers.ReduceAvailabilityByRank
|
||||
import App.State.Reducers.ReduceLobbyLoader
|
||||
@@ -258,6 +260,7 @@ object RootReducer {
|
||||
Maps = ReduceMaps(State0.Maps, Action),
|
||||
BattleChat = ReduceBattleChat(State0.BattleChat, Action),
|
||||
RemoteUserDataStorage = ReduceRemoteUserDataStorage(State0.RemoteUserDataStorage, Action),
|
||||
Matchmaking = ReduceMatchmaking(State0.Matchmaking, Action),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ import App.State.Reducers.LoginByPasswordStateSlice
|
||||
import App.State.Reducers.LootBoxesStateSlice
|
||||
import App.State.Reducers.MainQuestStateSlice
|
||||
import App.State.Reducers.MapsStateSlice
|
||||
import App.State.Reducers.MatchmakingStateSlice
|
||||
import App.State.Reducers.MigrationStateSlice
|
||||
import App.State.Reducers.ModalScreenStateSlice
|
||||
import App.State.Reducers.ModerationStateSlice
|
||||
@@ -147,8 +148,8 @@ data class RootState(
|
||||
val BattlesSelect: Any? = null,
|
||||
/** 原 maps(OA / Oi.sql)。已迁移。 */
|
||||
val Maps: MapsStateSlice = MapsStateSlice(),
|
||||
/** 原 matchmaking(TH / JH().qrx)。未迁移:原样透传。 */
|
||||
val Matchmaking: Any? = null,
|
||||
/** 原 matchmaking(TH / JH().qrx)。已迁移。 */
|
||||
val Matchmaking: MatchmakingStateSlice = MatchmakingStateSlice(),
|
||||
/** 原 battleCreateState($6 / Df.ttg)。未迁移:原样透传。 */
|
||||
val BattleCreateState: Any? = null,
|
||||
/** 原 battleSearchState(Itt / Htt().vtg)。已迁移。 */
|
||||
|
||||
@@ -44,7 +44,7 @@ object RootWiring {
|
||||
SliceWiring("remoteUserDataStorage", "zpv_1", "\$Q", "vh.isl", "vh.isl(t, n.zpv_1)", listOf("UpdateClanTags", "UpdateOnlineStatus", "UpdatePremiumStatus", "UpdateRanks", "UpdateUids", "UserEnterBattle", "UserLeaveBattle", "UserLeaveGroup")),
|
||||
SliceWiring("battlesSelect", "apw_1", "fA", "Mi.vqk", "Mi.vqk(t, n.apw_1)", listOf("?dA", "?gA", "AddBattle", "AddUser", "AddUsers", "ChangeName", "EnterToBattleInfo", "InitProBattleRewardLimit", "LimitReached", "RemoveBattle", "RemoveUser", "RoundFinish", "RoundStarted", "SetReEnterProtectBattleId", "SwapTeam", "UpdateFund", "UpdateSuspicion", "UpdateTeamScore", "UpdateUserScore", "UpdateUserSuspicion")),
|
||||
SliceWiring("maps", "bpw_1", "OA", "Oi.sql", "Oi.sql(t, n.bpw_1)", listOf("AddMap")),
|
||||
SliceWiring("matchmaking", "cpw_1", "TH", "JH().qrx", "JH().qrx(t, n.cpw_1)", listOf("?WH", "?nW", "?tW", "Configure", "EnterToBattleApply", "Play", "SelectMatchmakingMode", "SetRankIndexToMinGS", "WasRegistered")),
|
||||
SliceWiring("matchmaking", "cpw_1", "TH", "JH().qrx", "JH().qrx(t, n.cpw_1)", listOf("CancelLoadingBattle", "Configure", "EnterToBattleApply", "Play", "ResetMatchmakingProgress", "SelectMatchmakingMode", "SetRankIndexToMinGS", "StartLoadingBattle", "WasRegistered")),
|
||||
SliceWiring("battleCreateState", "dpw_1", "\$6", "Df.ttg", "Df.ttg(t, n.dpw_1, n.bpw_1, n.ypu_1)", listOf("?A6", "?B6", "?C6", "?D6", "?E6", "?F6", "?I6", "?L6", "?M6", "?N6", "?P6", "?R6", "?T6", "?U6", "Configure", "CreateBattle", "SetRestrictions")),
|
||||
SliceWiring("battleSearchState", "epw_1", "Itt", "Htt().vtg", "Htt().vtg(t, n.epw_1)", listOf("ClearSelectedBattle", "EnterToBattle", "Fight", "RemoveBattle", "SelectBattle", "SelectBattleFormat", "SetFilter", "SetSearch", "SetSuspiciousFilter")),
|
||||
SliceWiring("lobbyLoader", "fpw_1", "KW", "Bs.es1", "Bs.es1(t, n.fpw_1)", listOf("HideLoader", "ShowLoader")),
|
||||
@@ -106,7 +106,7 @@ object RootWiring {
|
||||
)
|
||||
|
||||
/** 已迁移(强类型;launchParams 为透传,不调用 reducer)的字段。 */
|
||||
val Migrated: Set<String> = setOf("inviteState", "loginByPassword", "twitchState", "home", "localBattleUserState", "shop", "screen", "lootBoxes", "garage", "garagePreview", "entrance", "user", "settings", "accountSettings", "proBattle", "language", "announcement", "launchParams", "news", "notifications", "quests", "lobbyLoader", "purchaseDialogState", "promoCode", "supportUrl", "rulesUpdated", "notificationByCountry", "availabilityByRank", "icons", "questCategories", "mainQuest", "securitySettings", "referralEvent", "tipsState", "rankUpDialogState", "battleResult", "captchaState", "modalScreen", "droppableGold", "eventGoods", "creatorTagState", "rewardedVideosState", "passwordChangeState", "system", "contextTutorial", "battleTutorial", "spectator", "twoStepVerificationState", "antiAddiction", "moderation", "migrationState", "register", "userReportsState", "friends", "suppliesState", "clanUserInfo", "battleInviteState", "partner", "userRenameState", "battlePauseState", "battleViewState", "tankActionsLogState", "suppliesTutorial", "clanChatState", "battleSearchState", "battleStatistics", "soundSettings", "gameSettings", "keyboardSettings", "touchscreenHudSettings", "graphicsSettings", "controlSettings", "battleSettings", "contractState", "tankBuilderState", "battleMessage", "maps", "battleChat", "remoteUserDataStorage")
|
||||
val Migrated: Set<String> = setOf("inviteState", "loginByPassword", "twitchState", "home", "localBattleUserState", "shop", "screen", "lootBoxes", "garage", "garagePreview", "entrance", "user", "settings", "accountSettings", "proBattle", "language", "announcement", "launchParams", "news", "notifications", "quests", "lobbyLoader", "purchaseDialogState", "promoCode", "supportUrl", "rulesUpdated", "notificationByCountry", "availabilityByRank", "icons", "questCategories", "mainQuest", "securitySettings", "referralEvent", "tipsState", "rankUpDialogState", "battleResult", "captchaState", "modalScreen", "droppableGold", "eventGoods", "creatorTagState", "rewardedVideosState", "passwordChangeState", "system", "contextTutorial", "battleTutorial", "spectator", "twoStepVerificationState", "antiAddiction", "moderation", "migrationState", "register", "userReportsState", "friends", "suppliesState", "clanUserInfo", "battleInviteState", "partner", "userRenameState", "battlePauseState", "battleViewState", "tankActionsLogState", "suppliesTutorial", "clanChatState", "battleSearchState", "battleStatistics", "soundSettings", "gameSettings", "keyboardSettings", "touchscreenHudSettings", "graphicsSettings", "controlSettings", "battleSettings", "contractState", "tankBuilderState", "battleMessage", "maps", "battleChat", "remoteUserDataStorage", "matchmaking")
|
||||
|
||||
/** 未迁移字段:归约时原样透传,作为后续迁移清单。 */
|
||||
val Unmigrated: List<SliceWiring> get() = All.filter { it.Field !in Migrated }
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
// System / ContextTutorial / BattleTutorial / Spectator / TwoStepVerification / AntiAddiction /
|
||||
// Moderation / MigrationState / Register / UserReports /
|
||||
// Friends / Supplies / ClanUserInfo / BattleInvite / Partner / UserRename /
|
||||
// BattlePause / BattleView / TankActionsLog / SuppliesTutorial / ClanChat / BattleSearch / BattleStatistics / SoundSettings / GameSettings / KeyboardSettings / TouchscreenHudSettings / GraphicsSettings / ControlSettings / BattleSettings / ContractState / TankBuilder / BattleMessage / Maps / BattleChat / RemoteUserDataStorage;
|
||||
// BattlePause / BattleView / TankActionsLog / SuppliesTutorial / ClanChat / BattleSearch / BattleStatistics / SoundSettings / GameSettings / KeyboardSettings / TouchscreenHudSettings / GraphicsSettings / ControlSettings / BattleSettings / ContractState / TankBuilder / BattleMessage / Maps / BattleChat / RemoteUserDataStorage / Matchmaking;
|
||||
// ㉑ launchParams 是纯透传切片(无 reducer/动作),只做 Map 类型收口;⑭ 根 reducer 的 89 槽位委派
|
||||
//
|
||||
// 用法:$env:TANKIOFFLINE_STATE_TEST='1'; node …(见 TankiOffline/tools/RunStateTest.ps1)
|
||||
@@ -756,6 +756,17 @@ import App.State.UpdateUids
|
||||
import App.State.UserEnterBattle
|
||||
import App.State.UserLeaveBattle
|
||||
import App.State.UserLeaveGroup
|
||||
import App.State.EnterToBattleApply
|
||||
import App.State.MatchmakingModeRank
|
||||
import App.State.Play
|
||||
import App.State.SelectMatchmakingMode
|
||||
import App.State.SetRankIndexToMinGS
|
||||
import App.State.WasRegistered
|
||||
import App.State.Reducers.CancelLoadingBattle
|
||||
import App.State.Reducers.MatchmakingStateSlice
|
||||
import App.State.Reducers.ReduceMatchmaking
|
||||
import App.State.Reducers.ResetMatchmakingProgress
|
||||
import App.State.Reducers.StartLoadingBattle
|
||||
import App.State.Reducers.UserRankBounds
|
||||
import App.State.Reducers.UserStateSlice
|
||||
import App.State.Reducers.ClearHullData
|
||||
@@ -1183,7 +1194,7 @@ object StateCheck {
|
||||
Check("切片 LocalBattleUser:接 Store 派发后状态已归约", Store.State.IsReArmorTemporaryDisabled)
|
||||
}
|
||||
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 79 个已迁移切片(78 归约 + launchParams 透传)
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 80 个已迁移切片(79 归约 + launchParams 透传)
|
||||
run {
|
||||
Check("根:根状态 89 个切片槽位", RootWiring.All.size == 89)
|
||||
Check(
|
||||
@@ -1247,7 +1258,7 @@ object StateCheck {
|
||||
LocalBattleW.Reducer == "(inline@localBattleUserState)"
|
||||
)
|
||||
Check(
|
||||
"根:迁移表 = 79 个已迁移字段,其余 10 个待迁",
|
||||
"根:迁移表 = 80 个已迁移字段,其余 9 个待迁",
|
||||
RootReducer.Migrated ==
|
||||
setOf(
|
||||
"inviteState", "loginByPassword", "twitchState", "home",
|
||||
@@ -1271,9 +1282,9 @@ object StateCheck {
|
||||
"soundSettings", "gameSettings", "keyboardSettings", "touchscreenHudSettings",
|
||||
"graphicsSettings", "controlSettings", "battleSettings", "contractState",
|
||||
"tankBuilderState", "battleMessage", "maps", "battleChat",
|
||||
"remoteUserDataStorage",
|
||||
"remoteUserDataStorage", "matchmaking",
|
||||
) &&
|
||||
RootWiring.Unmigrated.size == 10
|
||||
RootWiring.Unmigrated.size == 9
|
||||
)
|
||||
|
||||
// 一次 ReduceRoot 里多个切片各归约自己的动作,互不串片
|
||||
@@ -1329,7 +1340,7 @@ object StateCheck {
|
||||
S5.User.Uid == "user-1" && S5.Screen.Current == NamedScreen("Preloader")
|
||||
)
|
||||
Check("根:无关动作返回等值状态", ReduceRoot(S5, AddFrags(1)) == S5)
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 79/89")
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 80/89")
|
||||
|
||||
val Store = ReduxStore(RootState(), { S, A -> ReduceRoot(S, A) })
|
||||
Store.Dispatch(SetStatus("LOGGING_IN"))
|
||||
@@ -6546,6 +6557,101 @@ object StateCheck {
|
||||
)
|
||||
}
|
||||
|
||||
// 90 切片 reducer:Matchmaking(TH / JH().qrx,19 字段;9 个动作)
|
||||
run {
|
||||
val S0 = MatchmakingStateSlice()
|
||||
Check(
|
||||
"切片 Matchmaking:默认值完整",
|
||||
S0.MatchmakingModeRanks.isEmpty() && S0.SelectedMatchmakingMode == null &&
|
||||
S0.DisabledModes.isEmpty() && !S0.MatchmakingAndLoadingBattleInProgress &&
|
||||
!S0.StartLoadingBattle && !S0.HolidayEnabled && S0.HolidayTitle == "" &&
|
||||
S0.HolidayIcon == null && S0.EventBigTile == null &&
|
||||
S0.HolidayDescription == "" && S0.MinRankForProBattle == Int.MAX_VALUE &&
|
||||
S0.AvgWaitTimeInSeconds == 0 && S0.Mode == null && S0.MaxUsersInGroup == 3 &&
|
||||
!S0.GroupsInEventMode && S0.EventEndDate == null &&
|
||||
S0.BorderColorForEventButton == null && !S0.RequestSent &&
|
||||
S0.RankIndexToMinGS.isEmpty()
|
||||
)
|
||||
val S1 = ReduceMatchmaking(S0, Configure(
|
||||
modes = listOf(MatchmakingModeRank("dm", 1)),
|
||||
disabledModes = listOf("tdm"),
|
||||
holidayEnabled = true,
|
||||
holidayTitle = "NY",
|
||||
holidayIcon = "icon",
|
||||
eventBigTile = "tile",
|
||||
holidayDescription = "desc",
|
||||
minRankForProBattle = 5,
|
||||
maxUsersInGroup = 4,
|
||||
groupsInEventMode = true,
|
||||
eventEndDate = "date",
|
||||
borderColorForEventButton = "#fff",
|
||||
))
|
||||
Check(
|
||||
"切片 Matchmaking:Configure 写 12 个字段",
|
||||
S1.MatchmakingModeRanks == listOf(MatchmakingModeRank("dm", 1)) &&
|
||||
S1.DisabledModes == setOf<Any?>("tdm") && S1.HolidayEnabled &&
|
||||
S1.HolidayTitle == "NY" && S1.HolidayIcon == "icon" &&
|
||||
S1.EventBigTile == "tile" && S1.HolidayDescription == "desc" &&
|
||||
S1.MinRankForProBattle == 5 && S1.MaxUsersInGroup == 4 &&
|
||||
S1.GroupsInEventMode && S1.EventEndDate == "date" &&
|
||||
S1.BorderColorForEventButton == "#fff"
|
||||
)
|
||||
Check(
|
||||
"切片 Matchmaking:SelectMatchmakingMode 写选中模式",
|
||||
ReduceMatchmaking(S1, SelectMatchmakingMode("dm")).SelectedMatchmakingMode == "dm"
|
||||
)
|
||||
Check(
|
||||
"切片 Matchmaking:Play 只置 requestSent",
|
||||
ReduceMatchmaking(S1, Play(true, null, null)).RequestSent
|
||||
)
|
||||
val S2 = ReduceMatchmaking(S1, WasRegistered(42, "dm"))
|
||||
Check(
|
||||
"切片 Matchmaking:WasRegistered 写等待时间 / 模式并清 requestSent",
|
||||
S2.MatchmakingAndLoadingBattleInProgress &&
|
||||
S2.AvgWaitTimeInSeconds == 42 && S2.Mode == "dm" && !S2.RequestSent
|
||||
)
|
||||
Check(
|
||||
"切片 Matchmaking:EnterToBattleApply 同时置两个进行中位",
|
||||
ReduceMatchmaking(S1, EnterToBattleApply(7L)).let {
|
||||
it.MatchmakingAndLoadingBattleInProgress && it.StartLoadingBattle
|
||||
}
|
||||
)
|
||||
Check(
|
||||
"切片 Matchmaking:ResetMatchmakingProgress 清三个位",
|
||||
ReduceMatchmaking(S2, ResetMatchmakingProgress).let {
|
||||
!it.MatchmakingAndLoadingBattleInProgress && !it.StartLoadingBattle &&
|
||||
!it.RequestSent
|
||||
}
|
||||
)
|
||||
Check(
|
||||
"切片 Matchmaking:读条开关两态",
|
||||
ReduceMatchmaking(S1, StartLoadingBattle).StartLoadingBattle &&
|
||||
!ReduceMatchmaking(S1, CancelLoadingBattle).StartLoadingBattle
|
||||
)
|
||||
Check(
|
||||
"切片 Matchmaking:SetRankIndexToMinGS 写表",
|
||||
ReduceMatchmaking(S1, SetRankIndexToMinGS(mapOf("1" to 100)))
|
||||
.RankIndexToMinGS == mapOf("1" to 100)
|
||||
)
|
||||
Check(
|
||||
"切片 Matchmaking:无关动作不改状态",
|
||||
ReduceMatchmaking(S2, AddFrags(1)) == S2
|
||||
)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, StartLoadingBattle)
|
||||
Check(
|
||||
"根:StartLoadingBattle 只动 matchmaking",
|
||||
Root1.Matchmaking.StartLoadingBattle &&
|
||||
Root1.RemoteUserDataStorage == Root0.RemoteUserDataStorage
|
||||
)
|
||||
val W = RootWiring.ByField("matchmaking")!!
|
||||
Check(
|
||||
"根:matchmaking 委派到 TH / JH().qrx 且 9 个动作",
|
||||
W.SliceClass == "TH" && W.Reducer == "JH().qrx" && W.Actions.size == 9
|
||||
)
|
||||
}
|
||||
|
||||
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