diff options
| author | Sarah Bradley <git@sarahduck.ca> | 2023-12-16 19:43:58 -0800 |
|---|---|---|
| committer | Sarah Bradley <git@sarahduck.ca> | 2023-12-16 19:43:58 -0800 |
| commit | dbba03fe210a80f7d89d3ad021ec901a9196a537 (patch) | |
| tree | 836e884541434a39bbbc74e0b645ffc79edd9c7c /NetServer.cs | |
| parent | 2793b94040a473538f01723d5ca5f53c4535e2af (diff) | |
Redid networking with LiteNetLib
Diffstat (limited to 'NetServer.cs')
| -rw-r--r-- | NetServer.cs | 170 |
1 files changed, 86 insertions, 84 deletions
diff --git a/NetServer.cs b/NetServer.cs index cab6a00..a0910ba 100644 --- a/NetServer.cs +++ b/NetServer.cs @@ -1,110 +1,112 @@ -using System.Buffers.Binary; -using System.Collections.Concurrent; -using System.Net; -using System.Net.NetworkInformation; -using System.Net.Sockets; -using System.Text; -using System.Threading.Channels; +using LiteNetLib; +using LiteNetLib.Utils; namespace OnekoOnline.Net; -static class Server +class Server { public static bool ServerRunning = false; - static readonly ConcurrentDictionary<int, ServerUser> users = []; + readonly Dictionary<int, ServerUser> users = []; + readonly EventBasedNetListener Listener; + readonly NetManager NetServer; - public static async void Init(int port) + public Server(int Port, int MaxConnections, string ServerPassword = "") { - TcpListener listener = new(IPAddress.Any, port); - listener.Start(10); - ServerRunning = true; - - while (ServerRunning) - { - TcpClient tcpSocket = await listener.AcceptTcpClientAsync(); - UdpClient udpSocket = new((IPEndPoint)tcpSocket.Client.RemoteEndPoint!); - - ServerUser newUser = new(tcpSocket.GetHashCode(), tcpSocket, udpSocket); - - Console.WriteLine("Accepted a connection from: " + tcpSocket.Client.RemoteEndPoint); - - await Task.Factory.StartNew(() => SetupUser(newUser)); - } - } - - static async Task SetupUser(ServerUser user) - { - await Task.WhenAny(ExchangeUserData(user), Task.Delay(7000)); - - if (user.ExchangedData) { - //Send current user data - foreach (ServerUser otherUser in users.Values.Where(u => u.ExchangedData)) { - //Send username and spritesheet - await NetBase.SendReliableData(new Packet(PacketType.OnekoSpritesheet, otherUser.SpriteSheet!, otherUser.Id), user.Tcp.GetStream()); - await NetBase.SendReliableData(new Packet(PacketType.Username, Encoding.UTF8.GetBytes(otherUser.Username!), otherUser.Id), user.Tcp.GetStream()); - //Ask users to take your data - await otherUser.ToSend.Writer.WriteAsync(new Packet(PacketType.Username, Encoding.UTF8.GetBytes(user.Username!), user.Id)); - await otherUser.ToSend.Writer.WriteAsync(new Packet(PacketType.OnekoSpritesheet, user.SpriteSheet!, user.Id)); - Console.WriteLine($"Sent {otherUser.Username}'s Data to {user.Username}"); + 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 connection from {peer.EndPoint}!"); + users.Add(peer.Id, new ServerUser(peer.Id, peer)); + }; + + Listener.PeerDisconnectedEvent += (peer, info) => { + Console.WriteLine($"{peer.EndPoint} 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.OnekoSpritesheet && dataReader.AvailableBytes > 30000) return; + else if (info.Type != PacketType.OnekoSpritesheet && dataReader.AvailableBytes > 500) return; + + if (info.Type == PacketType.OnekoSpritesheet) user.SpriteSheet = dataReader.GetRemainingBytes(); + else if (info.Type == PacketType.Username) user.Username = dataReader.GetString(64); + + if (user.ExchangedData && !user.sentId) { + NetDataWriter writer = new(); + //Send ID + writer.Put(user.Id); + fromPeer.Send(writer, DeliveryMethod.ReliableUnordered); + user.sentId = true; + + Console.WriteLine($"{fromPeer.EndPoint} is {user.Username}!"); + + foreach (ServerUser toSend in users.Values) + { + if (!toSend.ExchangedData || toSend == user) continue; + + //Send all current users spritesheets to this user. + writer.ResetWithInfo(new PacketInfo(PacketType.OnekoSpritesheet, toSend.Id), toSend.SpriteSheet!.Length); + writer.Put(toSend.SpriteSheet); + fromPeer.Send(writer, DeliveryMethod.ReliableUnordered); + + writer.ResetWithInfo(new PacketInfo(PacketType.Username, toSend.Id)); + writer.Put(toSend.Username); + fromPeer.Send(writer, DeliveryMethod.ReliableUnordered); + + //Send all current users this users spritesheet + writer.ResetWithInfo(new PacketInfo(PacketType.OnekoSpritesheet, user.Id), user.SpriteSheet!.Length); + writer.Put(user.SpriteSheet); + toSend.Peer.Send(writer, DeliveryMethod.ReliableUnordered); + + writer.ResetWithInfo(new PacketInfo(PacketType.Username, user.Id)); + writer.Put(user.Username); + toSend.Peer.Send(writer, DeliveryMethod.ReliableUnordered); + } + } + }; - users.GetOrAdd(user.Id, user); - await Task.Factory.StartNew(() => UpdateUser(user)); - } else { - Console.WriteLine($"{user.Tcp.Client.RemoteEndPoint} failed to send required data, terminating connection."); - user.Dispose(); - } + Console.WriteLine("Server Initialized!"); } - static async Task ExchangeUserData(ServerUser user) + public void Poll() { - while (!user.ExchangedData) - { - Packet packet = await NetBase.GetReliableData(user.Tcp.GetStream()); - - if (packet.Data.Length > 50000) break; - - if (packet.Type == PacketType.Username) { - user.Username = Encoding.UTF8.GetString(packet.Data); - } else if (packet.Type == PacketType.OnekoSpritesheet) { - user.SpriteSheet = packet.Data; - } - } - - if (!user.ExchangedData) return; - - //Send ID - byte[] idData = new byte[sizeof(int)]; - BinaryPrimitives.WriteInt32LittleEndian(idData, user.Id); - await NetBase.SendReliableData(new Packet(PacketType.UserId, idData, 0), user.Tcp.GetStream()); - - Console.WriteLine($"{user.Tcp.Client.RemoteEndPoint} is {user.Username}!"); + NetServer.PollEvents(); } - static async Task UpdateUser(ServerUser user) + public void Disconnect() { - while (user.Tcp.Connected) { - Packet toSend = await user.ToSend.Reader.ReadAsync(user.UpdateCancel.Token); - await NetBase.SendReliableData(toSend, user.Tcp.GetStream(), user.UpdateCancel.Token); - } - //users.TryRemove(user.Id, out _); - //user.Dispose(); + NetServer.DisconnectAll(); } } -class ServerUser(int id, TcpClient tcp, UdpClient udp) : User(id), IDisposable +class ServerUser(int id, NetPeer peer) : User(id), IDisposable { //Network - public readonly TcpClient Tcp = tcp; - public readonly UdpClient Udp = udp; - public readonly Channel<Packet> ToSend = Channel.CreateUnbounded<Packet>(); - public CancellationTokenSource UpdateCancel = new(); + public readonly NetPeer Peer = peer; + public bool sentId = false; public void Dispose() { - UpdateCancel.Cancel(); - Tcp.Dispose(); - Udp.Dispose(); + Peer.Disconnect(); } }
\ No newline at end of file |
