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); } } }