using System; using System.Diagnostics; using System.Threading; using LiteNetLib; using LiteNetLib.Utils; using ONDClient.Map; using PacketLib; namespace ONDClient.Net; public static class Client { public enum ConnectionState { IDLE, CONNECTING, CONNECTED, ACCEPTED, GAME_STARTING, DISCONNECTED, GAME_IN_PROGRESS, ERROR } public static string StatusText{ get; private set; } public static ConnectionState State { get; set; } = ConnectionState.IDLE; public static ClientPlayer Player { get; } = new(); public static ClientPlayer Opponent { get; } = new(); private static EventBasedNetListener listener = new(); private static NetManager client; private static NetPeer server; private static NetDataWriter writer; private static NetPacketProcessor processor; public static ClientPlayer GetPlayer(int pid) => Player.State.Pid == pid ? Player : Opponent; public static void Init() { writer = new NetDataWriter(); processor = new NetPacketProcessor(); NestedTypeManager.AutoRegister(processor); processor.SubscribeReusable(OnJoinAccept); processor.SubscribeReusable(OnPlayerUpdate); processor.SubscribeReusable(OnMapInit); processor.SubscribeReusable(OnOpponentInit); client = new NetManager(listener){ AutoRecycle = true }; listener.NetworkReceiveEvent += (peer, reader, channel, method) => { OnNetworkReceive(peer, reader, method); }; listener.PeerConnectedEvent += peer => { Console.WriteLine("Connected to Server"); server = peer; State = ConnectionState.CONNECTED; SendPacket(new JoinPacket {Username = Player.Username == "" ? "Anonymous" : Player.Username}, DeliveryMethod.ReliableOrdered); }; listener.PeerDisconnectedEvent += (peer, info) => { State = ConnectionState.IDLE; Console.WriteLine("Disconnected from Server:\n" + info.Reason); State = ConnectionState.DISCONNECTED; StatusText = info.Reason.ToString(); }; } public static void Connect(string endPoint, int port) { State = ConnectionState.CONNECTING; client.Start(); Console.WriteLine($"Connecting to server @ {endPoint}:{port}"); new Thread(() => client.Connect(endPoint, port, "")).Start(); } public static void SendPacket(T packet, DeliveryMethod deliveryMethod) where T : class, new() { if (server != null) { writer.Reset(); processor.Write(writer, packet); server.Send(writer, deliveryMethod); } } public static void SendCommands(PlayerCommand[] pCommands) { SendPacket(new PlayerCommandPacket{Commands = pCommands}, DeliveryMethod.ReliableOrdered); } private static void OnNetworkReceive(NetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod) { processor.ReadAllPackets(reader, peer); } private static void OnJoinAccept(JoinAcceptPacket packet) { Console.WriteLine($"Accepted by server, pid: {packet.State.Pid}"); State = ConnectionState.ACCEPTED; Player.State = packet.State; } public static void Update() { client.PollEvents(); } public static void OnPlayerUpdate(UpdatePlayerPacket packet) { EventProcessor.Evaluate(packet.Events); } public static void Disconnect() { if (client == null || client.ConnectedPeersCount == 0) return; client.DisconnectAll(); client.Stop(); State = ConnectionState.IDLE; } public static void StartServer() { Process.Start("ONDServer"); } #nullable enable private static void OnMapInit(MapInitPacket packet) { ClientMapManager.InitMap(packet.Connectors, packet.YourTiles, packet.OpponentTiles, packet.LitTiles, packet.UpsideDown); } private static void OnOpponentInit(OpponentInitPacket packet) { Opponent.State = packet.State; Opponent.Username = packet.Username; State = ConnectionState.GAME_STARTING; } }