using System;
using System.Collections.Generic;
using Luneraria.Core;
using Luneraria.Net;
using NUnit.Framework;
namespace Luneraria.Net.Tests
{
/// Round-trip checks for the wire codec (LuneWire) and a localhost TCP session.
public sealed class LuneWireTests
{
[Test]
public void CommandRoundTrips()
{
Command original = Command.Buy("g01", "mid");
string line = LuneWire.Encode(LuneNet.KSubmit, new object[] { 3, original });
string kind;
object payload;
LuneWire.Decode(line, out kind, out payload);
Assert.AreEqual(LuneNet.KSubmit, kind);
var parts = (object[])payload;
Assert.AreEqual(3, parts[0]);
var copy = (Command)parts[1];
Assert.AreEqual("buy", copy.Type);
Assert.AreEqual("g01", copy.TypeId);
Assert.AreEqual("mid", copy.Lane);
}
[Test]
public void StateRoundTrips()
{
var state = new NetState
{
Phase = Phase.Planning,
Round = 7,
Winner = LuneMatch.Ongoing,
EndNote = "Ancient von Blau zerstört.",
LastSettlement = new Settlement { Round = 6, Income = 90, EndReason = "cleared", CombatTime = 12.5, Boss = "won" }
};
state.BuildingHp["blau_ancient"] = 1200.5;
state.BuildingHp["rot_top_outer"] = 0.0;
state.DestroyedCores.Add(1);
state.Boss.NextAvailableRound = 4;
state.Boss.Claim = new BossClaim { Team = 0, WonRound = 3, DeployRound = 5, ChooserSlot = 1, Lane = "mid" };
var row = new NetPlayerRow
{
Slot = 1,
Name = "Anna",
IsHuman = true,
Gold = 340,
Ready = false,
Earned = 400,
Spent = 60,
NextSeq = 4,
Undo = 1,
Draft = new Draft { Gold = 300, NextSeq = 4, BossLane = "top" }
};
row.Roster.Add(new RosterEntry { Uid = "p1-1", Seq = 1, TypeId = "w01", Lane = "mid", Invested = 50, Fresh = true });
row.Hero = new HeroState { Uid = "p1-2", Seq = 2, HeroId = "held_ringborke", Lane = "mid", Xp = 12, Invested = 200, Fresh = false };
row.Hero.Items.Add("glutklinge");
row.Bookings.Add(new Booking { Uid = "p1-3", Seq = 3, ChampionId = "ch_belagerung", Lane = "bot", Cost = 80, DeployRound = 8 });
row.Draft.Roster.Add(new RosterEntry { Uid = "p1-4", Seq = 4, TypeId = "g01", Lane = "top", Invested = 45, Fresh = true });
row.Draft.NewBookings.Add(new Booking { Uid = "p1-5", Seq = 5, ChampionId = "ch_sturm", Lane = "mid", Cost = 70 });
state.Players.Add(row);
string line = LuneWire.Encode(LuneNet.KState, state);
string kind;
object payload;
LuneWire.Decode(line, out kind, out payload);
var copy = (NetState)payload;
Assert.AreEqual(Phase.Planning, copy.Phase);
Assert.AreEqual(7, copy.Round);
Assert.AreEqual("Ancient von Blau zerstört.", copy.EndNote);
Assert.AreEqual(1200.5, copy.BuildingHp["blau_ancient"], 1e-9);
Assert.AreEqual(0.0, copy.BuildingHp["rot_top_outer"], 1e-9);
Assert.AreEqual(1, copy.DestroyedCores[0]);
Assert.AreEqual(4, copy.Boss.NextAvailableRound);
Assert.AreEqual("mid", copy.Boss.Claim.Lane);
Assert.AreEqual(12.5, copy.LastSettlement.CombatTime, 1e-9);
NetPlayerRow player = copy.Players[0];
Assert.AreEqual("Anna", player.Name);
Assert.AreEqual(340, player.Gold);
Assert.AreEqual("p1-1", player.Roster[0].Uid);
Assert.IsTrue(player.Roster[0].Fresh);
Assert.AreEqual("held_ringborke", player.Hero.HeroId);
Assert.AreEqual("glutklinge", player.Hero.Items[0]);
Assert.AreEqual("ch_belagerung", player.Bookings[0].ChampionId);
Assert.AreEqual(300, player.Draft.Gold);
Assert.AreEqual("top", player.Draft.BossLane);
Assert.AreEqual("g01", player.Draft.Roster[0].TypeId);
Assert.AreEqual("ch_sturm", player.Draft.NewBookings[0].ChampionId);
}
[Test]
public void UnitsAndFrameRoundTrip()
{
var unit = new NetUnitRecord
{
Id = 12,
Kind = "hero",
Team = 0,
TeamIndex = 2,
OwnerSlot = 1,
Uid = "p1-2",
Lane = "mid",
Zone = "lane",
X = 3.5,
Y = -1.25,
Facing = 1.5,
Hp = 80,
MaxHp = 100,
Alive = true,
Def = new UnitDef { Id = "held_ringborke", DisplayName = "Ringborke", Cost = 200, MaxHp = 100, Damage = 12, Tier = "" }
};
unit.Def.Talents.Add("t_roots");
string line = LuneWire.Encode(LuneNet.KUnitsSpawned, new List { unit });
string kind;
object payload;
LuneWire.Decode(line, out kind, out payload);
var list = (List)payload;
Assert.AreEqual(1, list.Count);
Assert.AreEqual("hero", list[0].Kind);
Assert.AreEqual(3.5, list[0].X, 1e-9);
Assert.AreEqual("held_ringborke", list[0].Def.Id);
Assert.AreEqual("t_roots", list[0].Def.Talents[0]);
var floats = new float[LuneNet.FrameStride];
for (int i = 0; i < floats.Length; i++)
floats[i] = i + 0.5f;
byte[] frame = LuneWire.EncodeFrame(9, 1.25, floats, new[] { 10f, 0f });
int serial;
double elapsed;
float[] units;
float[] hp;
LuneWire.DecodeFrame(frame, out serial, out elapsed, out units, out hp);
Assert.AreEqual(9, serial);
Assert.AreEqual(1.25, elapsed, 1e-9);
Assert.AreEqual(LuneNet.FrameStride, units.Length);
Assert.AreEqual(2.5f, units[2]);
Assert.AreEqual(2, hp.Length);
}
[Test]
public void LobbyAndOptionsRoundTrip()
{
var roster = new List
{
new LobbyEntry { Peer = 1, Slot = 0, Name = "Host", Ready = false, Bot = false },
new LobbyEntry { Peer = 0, Slot = 1, Name = "Bot", Ready = true, Bot = true }
};
string line = LuneWire.Encode(LuneNet.KLobby, roster);
string kind;
object payload;
LuneWire.Decode(line, out kind, out payload);
var copy = (List)payload;
Assert.AreEqual(2, copy.Count);
Assert.AreEqual("Host", copy[0].Name);
Assert.IsTrue(copy[1].Bot);
var options = new MatchOptions { Seed = 42, HumanSlot = 0, Bunds = new List { "glutpakt", "wurzelbund" } };
line = LuneWire.Encode(LuneNet.KSetup, new object[] { options, 3, roster });
LuneWire.Decode(line, out kind, out payload);
var parts = (object[])payload;
var optionsCopy = (MatchOptions)parts[0];
Assert.AreEqual(42, optionsCopy.Seed);
Assert.AreEqual(3, parts[1]);
Assert.AreEqual(2, optionsCopy.Bunds.Count);
}
}
}