using System.Collections.Generic; using System.Text; using Fighter3D.Core; using Fighter3D.Server; using XWorld.Framework; using XWorld.Framework.Protocol; using XWorld.Server.Host; namespace XWorld.Server.Host.Tests { public class Fighter3DServerRoomTests { private sealed class FakeOutput : IRoomOutput { public readonly List Broadcasts = new List(); public void Broadcast(NetMessage message) => Broadcasts.Add(message); public void SendTo(int playerId, NetMessage message) { } } private static readonly IReadOnlyList TwoHumans = new[] { new PlayerInfo { PlayerId = 10, Name = "A", IsAI = false }, new PlayerInfo { PlayerId = 20, Name = "B", IsAI = false }, }; private static (RoomCtx Ctx, FakeOutput Output, bool[] Ended, RoomEndResult[] Result) BuildCtx() { var output = new FakeOutput(); var ended = new bool[1]; var result = new RoomEndResult[1]; var ctx = new RoomCtx( new DeterministicRandom(42), new ManualClock(), new ConsoleLogger(), new InMemoryStorage(), output, r => { ended[0] = true; result[0] = r; }); return (ctx, output, ended, result); } private static NetMessage ControlsMsg(int axis, FighterButtons buttons) { var writer = new PacketWriter(); writer.WriteVarInt(axis); writer.WriteByte((byte)buttons); return new NetMessage(FighterServerRoom.InputOpcode, writer.ToArray()); } private static FighterState LastSnapshot(FakeOutput output) { var last = output.Broadcasts[output.Broadcasts.Count - 1]; Assert.Equal(FighterServerRoom.SnapshotOpcode, last.Opcode); return new FighterLogic().Decode(last.Payload); } [Fact] public void OnRoomStart_BroadcastsInitialSnapshot() { var (ctx, output, _, _) = BuildCtx(); var room = new FighterServerRoom(); room.OnRoomStart(TwoHumans, ctx); Assert.NotEmpty(output.Broadcasts); var snapshot = LastSnapshot(output); Assert.Equal(FighterPhase.Running, snapshot.Phase); } [Fact] public void RepeatedHeavyAttacks_CanKoAndEndRoomWithWinnerPid() { var (ctx, output, ended, result) = BuildCtx(); var room = new FighterServerRoom(); room.OnRoomStart(TwoHumans, ctx); room.OnMessage(10, ControlsMsg(0, FighterButtons.Heavy)); for (int i = 0; i < 800 && !ended[0]; i++) room.OnTick(1f / 20f); Assert.True(ended[0]); Assert.NotNull(result[0]); Assert.Equal(10, result[0].WinnerPlayerId); Assert.Contains("Fighter3D", Encoding.UTF8.GetString(result[0].ResultBlob)); var snapshot = LastSnapshot(output); Assert.Equal(FighterPhase.Finished, snapshot.Phase); Assert.Equal(0, snapshot.WinnerSeat); } } }