using LiteNetLib; using LiteNetLib.Utils; namespace OnekoOnline.Net; class Server { public static bool ServerRunning = false; readonly Dictionary users = []; readonly EventBasedNetListener Listener; readonly NetManager NetServer; public Server(int Port, int MaxConnections, string ServerPassword = "") { Listener = new(); NetServer = new(Listener); ServerRunning = NetServer.Start(Port); if (!ServerRunning) return; Listener.ConnectionRequestEvent += request => { if (NetServer.ConnectedPeersCount < MaxConnections) request.AcceptIfKey(ServerPassword); else request.Reject(); }; Listener.PeerConnectedEvent += peer => { Console.WriteLine($"New attempted connection from {peer}."); users.Add(peer.Id, new ServerUser(peer.Id, peer)); }; Listener.PeerDisconnectedEvent += (peer, info) => { Console.WriteLine($"{peer} Disconnected! Reason: {info.Reason}"); users.Remove(peer.Id); NetDataWriter writer = new(); //Send all users a disconnect message foreach (ServerUser user in users.Values) { user.Peer.Send(new PacketInfo(PacketType.Disconnect, peer.Id).Serialize(), DeliveryMethod.ReliableUnordered); } }; Listener.NetworkReceiveEvent += (fromPeer, dataReader, channel, DeliveryMethod) => { PacketInfo info = dataReader.GetPacketInfo(); ServerUser user = users[fromPeer.Id]; //Size limits for packet types if (info.Type == PacketType.UserInfo && dataReader.AvailableBytes > 50000) return; else if (info.Type != PacketType.UserInfo && dataReader.AvailableBytes > 500) return; NetDataWriter writer = new(); if (info.Type == PacketType.UserInfo) { string Username = dataReader.PeekString(40); if (string.IsNullOrEmpty(Username)) return; writer.ResetWithInfo(new PacketInfo(PacketType.UserInfo, user.Id)); writer.Put(dataReader.GetRemainingBytes()); user.UserInfo = writer.CopyData(); if (!user.Initialized) { //Send ID writer.ResetWithInfo(new PacketInfo(PacketType.UserId, -1)); writer.Put(user.Id); fromPeer.Send(writer, DeliveryMethod.ReliableUnordered); user.Initialized = true; Console.WriteLine($"{fromPeer} Connected as {Username}!"); foreach (ServerUser toSend in users.Values) { if (!toSend.Initialized || toSend == user) continue; //Send all current users info to the new user. fromPeer.Send(toSend.UserInfo, DeliveryMethod.ReliableUnordered); //Send all previous users this new users info toSend.Peer.Send(user.UserInfo, DeliveryMethod.ReliableUnordered); } } } else if (info.Type == PacketType.OnekoState || info.Type == PacketType.MouseState) { writer.ResetWithInfo(new PacketInfo(info.Type, fromPeer.Id)); writer.Put(dataReader.GetRemainingBytes()); foreach (ServerUser toSend in users.Values) { if (!toSend.Initialized || toSend == user) continue; toSend.Peer.Send(writer, DeliveryMethod); } } }; Console.WriteLine("Server Initialized!"); } public void Poll() { NetServer.PollEvents(); } public void Disconnect() { NetServer.DisconnectAll(); } } class ServerUser(int id, NetPeer peer) : User(id), IDisposable { //Network public readonly NetPeer Peer = peer; public byte[]? UserInfo; public void Dispose() { Peer.Disconnect(); } }