Quality pass from the 2026-06-04 BattleNode review (audit in the outer
repo). All changes are behavior-preserving — identical wire bytes,
verified by the full 1008-test suite staying green.
- Name scattered magic numbers: crypto key/IV lengths, outbound-sequencer
base, WS receive buffer / EIO ping / SID length, polite-close timeout,
upgrade-credential keys, battle-id digit math, deterministic-turn spin.
- resultCode = 1 -> (int)ReceiveNodeResultCode.Success across body records.
- Pong "3" -> EngineIoPacketType.Pong; remove dead NoOpBotParticipant.Touch
(replace with #pragma warning disable CS0067).
- Wire-flag enums, serialized as numbers via JsonNumberEnumConverter:
turnState -> TurnState{First,Second}, isSelf -> CardOwner{Opponent,Self},
open -> ChoiceVisibility{Hidden,Open}.
- isOfficial / isInvoke -> bool / bool? via new NumericBoolJsonConverter
(reads/writes 0/1; TDD'd). Scoped to the BattleNode wire boundary only;
MatchContext and the HTTP/AI-start path stay int (AI-start uses -1 as a
sentinel, so it is not boolean).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
30 lines
1.5 KiB
C#
30 lines
1.5 KiB
C#
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
|
|
namespace SVSim.BattleNode.Protocol;
|
|
|
|
/// <summary>
|
|
/// Serializes a <see cref="bool"/> as the wire's numeric 0/1. The client reads these flags via
|
|
/// <c>Convert.ToInt32</c> / <c>Convert.ToBoolean</c> (e.g. <c>isOfficial</c>, <c>isInvoke</c>) —
|
|
/// never as a JSON <c>true</c>/<c>false</c> token — so a real <c>bool</c> property must still emit
|
|
/// a number. Read accepts a JSON number (0 = false, non-zero = true) and, defensively, a
|
|
/// <c>true</c>/<c>false</c> token or a numeric string. Applied per-field via
|
|
/// <c>[JsonConverter(typeof(NumericBoolJsonConverter))]</c>; works on <c>bool?</c> too (System.Text.Json
|
|
/// wraps a <c>JsonConverter<bool></c> for the nullable case).
|
|
/// </summary>
|
|
public sealed class NumericBoolJsonConverter : JsonConverter<bool>
|
|
{
|
|
public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
|
=> reader.TokenType switch
|
|
{
|
|
JsonTokenType.Number => reader.GetInt64() != 0,
|
|
JsonTokenType.True => true,
|
|
JsonTokenType.False => false,
|
|
JsonTokenType.String => long.TryParse(reader.GetString(), out var n) && n != 0,
|
|
_ => throw new JsonException($"Cannot convert token {reader.TokenType} to a numeric bool"),
|
|
};
|
|
|
|
public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options)
|
|
=> writer.WriteNumberValue(value ? 1 : 0);
|
|
}
|