Files
SVSimServer/SVSim.BattleNode/Sessions/Dispatch/BattleFrames.cs
gamer147 7d4da69f22 refactor(battlenode): low-churn §B/§D/§E/§F quality cleanups
Behavior-preserving; 231 BattleNode tests green.

- §D: MsgEnvelope.Try -> RetryAttempt (drops keyword-escape; wire key stays "try");
  SocketIoFrame.AckResponse arg -> pubSeqEcho.
- §B: Gungnir.EmitInterval -> BattleNodeOptions.AliveEmitInterval (unused literal
  moved to its config home); deck-idx 4L -> InitialHand.Length + 1.
- §E: shared Wire.WireJsonOptions.CamelCase replaces the duplicated camelCase
  JsonSerializerOptions in EngineIoHandshake and MsgEnvelope.
- §F: do-NOT-consistency-fix polarity notes on TurnEndFinalHandler (From wins)
  and RetireKillHandler (From loses).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 23:06:44 -04:00

77 lines
2.7 KiB
C#

using SVSim.BattleNode.Lifecycle;
using SVSim.BattleNode.Protocol;
using SVSim.BattleNode.Protocol.Bodies;
namespace SVSim.BattleNode.Sessions.Dispatch;
/// <summary>Server-synthesized control/broadcast frames + inbound-body helpers, relocated verbatim
/// from BattleSession so the per-URI handlers can build them. Pure: no session state.</summary>
internal static class BattleFrames
{
internal static MsgEnvelope BuildAck(NetworkBattleUri uri) => new(
uri,
ViewerId: ServerBattleFrames.FakeOpponentViewerId,
Uuid: WireConstants.ServerUuid,
Bid: null,
RetryAttempt: 0,
Cat: EmitCategory.General,
PubSeq: null,
PlaySeq: null,
Body: new ResultCodeOnlyBody());
internal static MsgEnvelope BuildTurnEndBroadcast() => new(
NetworkBattleUri.TurnEnd,
ViewerId: ServerBattleFrames.FakeOpponentViewerId,
Uuid: WireConstants.ServerUuid,
Bid: null,
RetryAttempt: 0,
Cat: EmitCategory.Battle,
PubSeq: null,
PlaySeq: null,
Body: new TurnEndBody(TurnState: TurnState.First));
internal static MsgEnvelope BuildJudgeBroadcast() => new(
NetworkBattleUri.Judge,
ViewerId: ServerBattleFrames.FakeOpponentViewerId,
Uuid: WireConstants.ServerUuid,
Bid: null,
RetryAttempt: 0,
Cat: EmitCategory.Battle,
PubSeq: null,
PlaySeq: null,
Body: new JudgeBody(Spin: BattleFrameDefaults.OpponentJudgeSpin));
internal static MsgEnvelope BuildBattleFinish(BattleResult result) => new(
NetworkBattleUri.BattleFinish,
ViewerId: ServerBattleFrames.FakeOpponentViewerId,
Uuid: WireConstants.ServerUuid,
Bid: null,
RetryAttempt: 0,
Cat: EmitCategory.Battle,
PubSeq: null,
PlaySeq: null,
Body: new BattleFinishBody(Result: result));
internal static IReadOnlyList<long> ExtractIdxList(MsgEnvelope env)
{
if (env.Body is not RawBody rawBody) return Array.Empty<long>();
if (rawBody.Entries.TryGetValue("idxList", out var raw) && raw is System.Collections.IEnumerable seq && raw is not string)
{
var result = new List<long>();
foreach (var item in seq)
{
switch (item)
{
case long l: result.Add(l); break;
case int i: result.Add(i); break;
case double d: result.Add((long)d); break;
case decimal m: result.Add((long)m); break;
case string s when long.TryParse(s, out var p): result.Add(p); break;
}
}
return result;
}
return Array.Empty<long>();
}
}