refactor(battlenode): close §A boolean-blindness items (MinedToken, Stock, KeyActionType)

Behavior-preserving; 231 BattleNode tests green.

- MinedToken record struct replaces the transpose-prone (int Idx, long CardId,
  CardOwner IsSelf) tuple returned by KnownListBuilder.Mine*. Positional deconstruct
  keeps the Record*From call sites unchanged.
- enum Stock { Normal, Bypass } replaces the negative `bool noStock` on
  IBattleParticipant.PushAsync and DispatchRoute, threaded through both participants,
  BattleSession, and all handler construction sites.
- enum KeyActionType mirrors the client's SendKeyActionDataManager.KeyActionType;
  the StripKeyActionForOpponent guard compares named values, KeyActionEntry.Type is
  the enum (wire-identical via JsonNumberEnumConverter).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-06-04 22:53:32 -04:00
parent a3e445cf2f
commit e70f32db79
30 changed files with 124 additions and 67 deletions

View File

@@ -55,7 +55,7 @@ internal static class KnownListBuilder
/// <c>idx</c>-is-list guards. This is the only place a freshly-generated card's identity exists on
/// the wire (bullet-3 audit F1; producing code <c>RegisterToken</c>/<c>RegisterActionBase</c>) —
/// the played-card op itself never carries a <c>cardId</c>.</summary>
public static IEnumerable<(int Idx, long CardId, CardOwner IsSelf)> MineAddOps(object? orderList)
public static IEnumerable<MinedToken> MineAddOps(object? orderList)
{
if (orderList is not IEnumerable<object?> ops) yield break;
foreach (var op in ops)
@@ -72,7 +72,7 @@ internal static class KnownListBuilder
if (!add.TryGetValue("idx", out var idxRaw) || idxRaw is not IEnumerable<object?> idxList) continue;
foreach (var i in idxList)
yield return ((int)AsLong(i), cardId, isSelf);
yield return new MinedToken((int)AsLong(i), cardId, isSelf);
}
}
@@ -87,7 +87,7 @@ internal static class KnownListBuilder
/// only gates the strip (<see cref="StripKeyActionForOpponent"/>), not the recording. An add whose
/// candidates contain none of the picks is skipped (defensive — no record, no desync); Echo (no
/// keyAction) yields nothing, leaving it mining-only via <see cref="MineAddOps"/>.</summary>
public static IEnumerable<(int Idx, long CardId, CardOwner IsSelf)> MineChoicePicks(object? orderList, object? keyAction)
public static IEnumerable<MinedToken> MineChoicePicks(object? orderList, object? keyAction)
{
if (orderList is not IEnumerable<object?> ops) yield break;
@@ -127,7 +127,7 @@ internal static class KnownListBuilder
if (!add.TryGetValue("idx", out var idxRaw) || idxRaw is not IEnumerable<object?> idxList) continue;
foreach (var i in idxList)
yield return ((int)AsLong(i), chosen.Value, isSelf);
yield return new MinedToken((int)AsLong(i), chosen.Value, isSelf);
}
}
@@ -144,7 +144,7 @@ internal static class KnownListBuilder
/// <c>candidates</c> (→ MineChoicePicks), a <c>string</c> <c>baseIdx</c> (private-group copy,
/// <c>RegisterCopyToken.cs:19-22</c>), and a <c>baseIdx</c> absent from the chosen map (unknown source
/// → degrade, no desync). <c>isPremium</c> (IsFoil) is cosmetic and ignored.</summary>
public static IEnumerable<(int Idx, long CardId, CardOwner IsSelf)> MineCopyTokens(
public static IEnumerable<MinedToken> MineCopyTokens(
object? orderList,
IReadOnlyDictionary<int, long> selfMap,
IReadOnlyDictionary<int, long> otherMap)
@@ -168,7 +168,7 @@ internal static class KnownListBuilder
if (!add.TryGetValue("idx", out var idxRaw) || idxRaw is not IEnumerable<object?> idxList) continue;
foreach (var i in idxList)
yield return ((int)AsLong(i), cardId, isSelf);
yield return new MinedToken((int)AsLong(i), cardId, isSelf);
}
}
@@ -186,8 +186,8 @@ internal static class KnownListBuilder
{
if (e is not IDictionary<string, object?> d) continue;
d.TryGetValue("type", out var typeRaw);
var type = (int)AsLong(typeRaw);
if (type is not (1 or 5)) continue; // only Choice / HaveBeforeSkillChoice handled
var type = (KeyActionType)(int)AsLong(typeRaw);
if (type is not (KeyActionType.Choice or KeyActionType.HaveBeforeSkillChoice)) continue;
d.TryGetValue("cardId", out var cardIdRaw);
var cardId = AsLong(cardIdRaw);