using System.Collections.ObjectModel; using LiteNetLib; using LiteNetLib.Utils; namespace OnekoOnline.Net; class Client { public static readonly string UserName = OnekoOnline.Config.GetValue("UserName", "Oneko"); public int Id {get; private set;} = -1; public bool Connected => NetClient?.ConnectedPeersCount > 0 && Id != -1; readonly EventBasedNetListener Listener; readonly NetManager NetClient; public NetPeer ConnectedServer => NetClient.FirstPeer; readonly Dictionary users = []; public ReadOnlyDictionary Users => users.AsReadOnly(); static public Action? UserConnected; static public Action? UserDisconnected; static public Action? PacketRecived; static public Action? ServerDisconnected; public Client(string ServerAddress, int port, string ServerPassword) { if (ServerAddress == "") throw new Exception("Server Address invalid!"); Listener = new(); NetClient = new(Listener); NetClient.Start(); NetClient.Connect(ServerAddress, port, ServerPassword); Listener.PeerConnectedEvent += peer => { Console.WriteLine("Connected to the Server!"); NetDataWriter writer = new(); writer.Put(new PacketInfo(PacketType.OnekoSpritesheet, Id)); writer.Put(OnekoLocal.Instance!.SpriteSheet.Serialize()); peer.Send(writer, DeliveryMethod.ReliableUnordered); writer.ResetWithInfo(new PacketInfo(PacketType.Username, Id)); writer.Put(UserName); peer.Send(writer, DeliveryMethod.ReliableUnordered); }; Listener.PeerDisconnectedEvent += (peer, info) => { ServerDisconnected?.Invoke(); users.Clear(); Console.WriteLine("Server Disconnected! You're offline!"); }; Listener.NetworkReceiveEvent += (fromPeer, reader, channel, DeliveryMethod) => { if (reader.AvailableBytes < PacketInfo.SizeOf) return; PacketInfo info = reader.GetPacketInfo(); if (info.Type == PacketType.UserId) { Id = reader.GetInt(); return; } User? from; if (!users.TryGetValue(info.FromId, out from)) { from = new(info.FromId); users.Add(from.Id, from); } if (info.Type == PacketType.Disconnect) { //Disconnect user that has disconnected if (from.Username != null) Console.WriteLine($"User {from.Username} left."); users.Remove(info.FromId); UserDisconnected?.Invoke(from); return; } else if (info.Type == PacketType.OnekoSpritesheet) from.SpriteSheet = reader.GetRemainingBytes(); else if (info.Type == PacketType.Username) from.Username = reader.GetString(); if (from.ExchangedData && !from.Initialized) { //Announce user connection Console.WriteLine($"User {from.Username} joined!"); from.Initialized = true; UserConnected?.Invoke(from); } NetDataReader newReader = new(reader.GetRemainingBytes()); PacketRecived?.Invoke(newReader, from, info.Type); }; } public void Poll() { NetClient.PollEvents(); } public void Disconnect() { NetClient.DisconnectAll(); } }