diff options
| author | Sarah Bradley <git@sarahduck.ca> | 2023-12-01 20:33:42 -0800 |
|---|---|---|
| committer | Sarah Bradley <git@sarahduck.ca> | 2023-12-01 20:33:42 -0800 |
| commit | 2793b94040a473538f01723d5ca5f53c4535e2af (patch) | |
| tree | cb30f0dae20bda6ef9d1c005325bfd9c986b3c8f /NetServer.cs | |
What I've got so far
Diffstat (limited to 'NetServer.cs')
| -rw-r--r-- | NetServer.cs | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/NetServer.cs b/NetServer.cs new file mode 100644 index 0000000..cab6a00 --- /dev/null +++ b/NetServer.cs @@ -0,0 +1,110 @@ +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; + +namespace OnekoOnline.Net; + +static class Server +{ + public static bool ServerRunning = false; + + static readonly ConcurrentDictionary<int, ServerUser> users = []; + + public static async void Init(int port) + { + 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}"); + } + + 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(); + } + } + + static async Task ExchangeUserData(ServerUser user) + { + 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}!"); + } + + static async Task UpdateUser(ServerUser user) + { + 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(); + } +} + +class ServerUser(int id, TcpClient tcp, UdpClient udp) : 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 void Dispose() + { + UpdateCancel.Cancel(); + Tcp.Dispose(); + Udp.Dispose(); + } +}
\ No newline at end of file |
