refactor(battle-node): replace int IsSelf with CardOwner enum on mined-token tuples
MineAddOps/MineChoicePicks/MineCopyTokens return types and all extraction casts changed from int to CardOwner. The 4 routing comparisons in BattleSessionState now read isSelf == CardOwner.Self instead of isSelf == 1. No wire or behavioral change — CardOwner was already in use on the wire-facing side (OppoTargetEntry, UnapprovedCardEntry); this extends it to the internal mining path so the bare-int transpose risk is gone. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using SVSim.BattleNode.Lifecycle;
|
||||
using SVSim.BattleNode.Protocol;
|
||||
using SVSim.BattleNode.Sessions;
|
||||
|
||||
namespace SVSim.BattleNode.Sessions.Dispatch;
|
||||
@@ -84,7 +85,7 @@ internal sealed class BattleSessionState
|
||||
public void RecordTokensFrom(IBattleParticipant from, IBattleParticipant other, object? orderList)
|
||||
{
|
||||
foreach (var (idx, cardId, isSelf) in KnownListBuilder.MineAddOps(orderList))
|
||||
RecordToken(isSelf == 1 ? from : other, idx, cardId);
|
||||
RecordToken(isSelf == CardOwner.Self ? from : other, idx, cardId);
|
||||
}
|
||||
|
||||
/// <summary>Mine + record choice/Discover-token picks (<see cref="KnownListBuilder.MineChoicePicks"/>)
|
||||
@@ -95,7 +96,7 @@ internal sealed class BattleSessionState
|
||||
public void RecordChoicePicksFrom(IBattleParticipant from, IBattleParticipant other, object? orderList, object? keyAction)
|
||||
{
|
||||
foreach (var (idx, cardId, isSelf) in KnownListBuilder.MineChoicePicks(orderList, keyAction))
|
||||
RecordToken(isSelf == 1 ? from : other, idx, cardId);
|
||||
RecordToken(isSelf == CardOwner.Self ? from : other, idx, cardId);
|
||||
}
|
||||
|
||||
/// <summary>Mine + record copy/clone-token identities (<see cref="KnownListBuilder.MineCopyTokens"/>)
|
||||
@@ -112,6 +113,6 @@ internal sealed class BattleSessionState
|
||||
var selfMap = GetOrSeedDeckMap(from);
|
||||
var otherMap = GetOrSeedDeckMap(other);
|
||||
foreach (var (idx, cardId, isSelf) in KnownListBuilder.MineCopyTokens(orderList, selfMap, otherMap))
|
||||
RecordToken(isSelf == 1 ? from : other, idx, cardId);
|
||||
RecordToken(isSelf == CardOwner.Self ? from : other, idx, cardId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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, int IsSelf)> MineAddOps(object? orderList)
|
||||
public static IEnumerable<(int Idx, long CardId, CardOwner IsSelf)> MineAddOps(object? orderList)
|
||||
{
|
||||
if (orderList is not IEnumerable<object?> ops) yield break;
|
||||
foreach (var op in ops)
|
||||
@@ -64,7 +64,7 @@ internal static class KnownListBuilder
|
||||
if (!opDict.TryGetValue("add", out var addRaw) || addRaw is not IDictionary<string, object?> add) continue;
|
||||
|
||||
add.TryGetValue("isSelf", out var isSelfRaw);
|
||||
var isSelf = (int)AsLong(isSelfRaw);
|
||||
var isSelf = (CardOwner)(int)AsLong(isSelfRaw);
|
||||
|
||||
if (!add.TryGetValue("card", out var cardRaw) || cardRaw is not IDictionary<string, object?> card) continue;
|
||||
if (!card.TryGetValue("cardId", out var cardIdRaw)) continue; // candidates/isChoice → no identity yet
|
||||
@@ -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, int IsSelf)> MineChoicePicks(object? orderList, object? keyAction)
|
||||
public static IEnumerable<(int Idx, long CardId, CardOwner IsSelf)> MineChoicePicks(object? orderList, object? keyAction)
|
||||
{
|
||||
if (orderList is not IEnumerable<object?> ops) yield break;
|
||||
|
||||
@@ -123,7 +123,7 @@ internal static class KnownListBuilder
|
||||
if (chosen is null) continue; // no pick in this op's pool — skip (no desync, just no record)
|
||||
|
||||
add.TryGetValue("isSelf", out var isSelfRaw);
|
||||
var isSelf = (int)AsLong(isSelfRaw);
|
||||
var isSelf = (CardOwner)(int)AsLong(isSelfRaw);
|
||||
|
||||
if (!add.TryGetValue("idx", out var idxRaw) || idxRaw is not IEnumerable<object?> idxList) continue;
|
||||
foreach (var i in idxList)
|
||||
@@ -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, int IsSelf)> MineCopyTokens(
|
||||
public static IEnumerable<(int Idx, long CardId, CardOwner IsSelf)> MineCopyTokens(
|
||||
object? orderList,
|
||||
IReadOnlyDictionary<int, long> selfMap,
|
||||
IReadOnlyDictionary<int, long> otherMap)
|
||||
@@ -162,8 +162,8 @@ internal static class KnownListBuilder
|
||||
var baseIdx = (int)AsLong(baseRaw);
|
||||
|
||||
add.TryGetValue("isSelf", out var isSelfRaw);
|
||||
var isSelf = (int)AsLong(isSelfRaw);
|
||||
var map = isSelf == 1 ? selfMap : otherMap;
|
||||
var isSelf = (CardOwner)(int)AsLong(isSelfRaw);
|
||||
var map = isSelf == CardOwner.Self ? selfMap : otherMap;
|
||||
if (!map.TryGetValue(baseIdx, out var cardId)) continue; // unknown source → degrade
|
||||
|
||||
if (!add.TryGetValue("idx", out var idxRaw) || idxRaw is not IEnumerable<object?> idxList) continue;
|
||||
|
||||
Reference in New Issue
Block a user