diff --git a/GServer.Client/Program.cs b/GServer.Client/Program.cs
index 5b5605c..fbc0626 100644
--- a/GServer.Client/Program.cs
+++ b/GServer.Client/Program.cs
@@ -1,73 +1,73 @@
-using System.Net;
-using System.Net.Sockets;
-using GServer.Common;
-using GServer.Common.Networking.Enums;
-using GServer.Common.Networking.Messages.Client;
-using GServer.Common.Networking.Messages.Server;
-
-internal class Program
-{
- private const int SERVER_PORT = 11000;
-
- private static void Main(string[] args)
- {
- IPEndPoint serverEP = new(IPAddress.Any, SERVER_PORT);
-
- TcpClient tcpClient = new();
- tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
- tcpClient.Connect(serverEP);
-
- Console.WriteLine("Username...");
- string username = Console.ReadLine()!;
-
- Console.WriteLine("Password...");
- string password = Console.ReadLine()!;
-
- AuthMessage authMessage = new(username, password);
- _ = tcpClient.Client.Send(authMessage.Serialize());
-
- try
- {
- while (true)
- {
- byte[] bytes = new byte[tcpClient.Client.ReceiveBufferSize];
- _ = tcpClient.Client.Receive(bytes);
-
- MessageMemoryStream stream = new(bytes);
-
- ClientPacketIn packetIn = (ClientPacketIn)stream.ReadByte();
- switch (packetIn)
- {
- case ClientPacketIn.AUTH_RESPONSE:
- AuthResponseMessage authResultMessage = new(stream);
-
- Console.WriteLine("Success = " + authResultMessage.IsSuccessful);
- Console.WriteLine("SessionToken = " + authResultMessage.SessionToken ?? "null");
- Console.WriteLine("FailureReason = " + authResultMessage.FailureReason ?? "null");
-
- break;
-
- case ClientPacketIn.LIST_SERVERS_RESPONSE:
- break;
-
- case ClientPacketIn.UNKNOWN:
- break;
-
- default:
- Console.WriteLine($"Received unsupported packet.");
- break;
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex);
- }
- finally
- {
- tcpClient.Close();
- }
-
-
- }
+using System.Net;
+using System.Net.Sockets;
+using GServer.Common.Networking.Core;
+using GServer.Common.Networking.Enums;
+using GServer.Common.Networking.Messages.Client;
+using GServer.Common.Networking.Messages.Server;
+
+namespace GServer.Client;
+
+public class Program
+{
+ private const int ServerPort = 11000;
+
+ private static void Main(string[] args)
+ {
+ IPEndPoint serverEp = new(IPAddress.Any, ServerPort);
+
+ TcpClient tcpClient = new();
+ tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
+ tcpClient.Connect(serverEp);
+
+ Console.WriteLine("Username...");
+ string username = Console.ReadLine()!;
+
+ Console.WriteLine("Password...");
+ string password = Console.ReadLine()!;
+
+ AuthMessage authMessage = new(username, password);
+ _ = tcpClient.Client.Send(authMessage.Serialize());
+
+ try
+ {
+ while (true)
+ {
+ byte[] bytes = new byte[tcpClient.Client.ReceiveBufferSize];
+ _ = tcpClient.Client.Receive(bytes);
+
+ MessageMemoryStream stream = new(bytes);
+
+ ClientPacketIn packetIn = (ClientPacketIn)stream.ReadByte();
+ switch (packetIn)
+ {
+ case ClientPacketIn.AuthResponse:
+ AuthResponseMessage authResultMessage = new(stream);
+
+ Console.WriteLine("Success = " + authResultMessage.IsSuccessful);
+ Console.WriteLine("SessionToken = " + authResultMessage.SessionToken);
+ Console.WriteLine("FailureReason = " + authResultMessage.FailureReason);
+
+ break;
+
+ case ClientPacketIn.ListServersResponse:
+ break;
+
+ case ClientPacketIn.Unknown:
+ break;
+
+ default:
+ Console.WriteLine("Received unsupported packet.");
+ break;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex);
+ }
+ finally
+ {
+ tcpClient.Close();
+ }
+ }
}
\ No newline at end of file
diff --git a/GServer.Common/Extensions/StringExtensions.cs b/GServer.Common/Extensions/StringExtensions.cs
index 60f35fe..dda135d 100644
--- a/GServer.Common/Extensions/StringExtensions.cs
+++ b/GServer.Common/Extensions/StringExtensions.cs
@@ -1,11 +1,11 @@
using System.Text;
-namespace GServer.Common;
+namespace GServer.Common.Extensions;
public static class StringExtensions
{
- public static byte[] GetASCIIBytes(this string value)
- {
- return Encoding.ASCII.GetBytes(value);
- }
+ public static byte[] GetAsciiBytes(this string value)
+ {
+ return Encoding.ASCII.GetBytes(value);
+ }
}
diff --git a/GServer.Common/Game/Entities/ServerListing.cs b/GServer.Common/Game/Entities/ServerListing.cs
index cbd982e..d56a54a 100644
--- a/GServer.Common/Game/Entities/ServerListing.cs
+++ b/GServer.Common/Game/Entities/ServerListing.cs
@@ -5,7 +5,7 @@ public record ServerListing
public required string Name { get; set; }
public required string Description { get; set; }
public ushort Playercount { get; set; }
- public required string IPAddress { get; set; }
+ public required string IpAddress { get; set; }
public ushort Port { get; set; }
public ServerTier ServerTier { get; set; }
}
diff --git a/GServer.Common/Networking/Core/MessageMemoryStream.cs b/GServer.Common/Networking/Core/MessageMemoryStream.cs
index b2ea9b8..15204b4 100644
--- a/GServer.Common/Networking/Core/MessageMemoryStream.cs
+++ b/GServer.Common/Networking/Core/MessageMemoryStream.cs
@@ -1,6 +1,6 @@
using System.Text;
-namespace GServer.Common;
+namespace GServer.Common.Networking.Core;
public class MessageMemoryStream : MemoryStream
{
@@ -31,7 +31,7 @@ public class MessageMemoryStream : MemoryStream
return BitConverter.ToInt16(buffer);
}
- public string ReadUTF8String(int length)
+ public string ReadUtf8String(int length)
{
byte[] bytes = new byte[length];
_ = Read(bytes, 0, length);
@@ -49,7 +49,7 @@ public class MessageMemoryStream : MemoryStream
Write(bytes, 0, 2);
}
- public void WriteUTF8String(string value)
+ public void WriteUtf8String(string value)
{
byte[] bytes = Encoding.UTF8.GetBytes(value);
Write(bytes, 0, bytes.Length);
diff --git a/GServer.Common/Networking/Enums/ClientPacketIn.cs b/GServer.Common/Networking/Enums/ClientPacketIn.cs
index dc27e8c..e0ab067 100644
--- a/GServer.Common/Networking/Enums/ClientPacketIn.cs
+++ b/GServer.Common/Networking/Enums/ClientPacketIn.cs
@@ -5,12 +5,12 @@ public enum ClientPacketIn : byte
///
/// Represents an auth result from the server.
///
- AUTH_RESPONSE = 1,
+ AuthResponse = 1,
///
/// Contains a list of server listings.
///
- LIST_SERVERS_RESPONSE = 2,
+ ListServersResponse = 2,
- UNKNOWN = 255
+ Unknown = 255
}
\ No newline at end of file
diff --git a/GServer.Common/Networking/Enums/ServerPacketIn.cs b/GServer.Common/Networking/Enums/ServerPacketIn.cs
index 2e710a5..8a46832 100644
--- a/GServer.Common/Networking/Enums/ServerPacketIn.cs
+++ b/GServer.Common/Networking/Enums/ServerPacketIn.cs
@@ -2,6 +2,6 @@ namespace GServer.Common.Networking.Enums;
public enum ServerPacketIn : byte
{
- AUTH = 1,
- LIST_SERVERS = 2
+ Auth = 1,
+ ListServers = 2
}
\ No newline at end of file
diff --git a/GServer.Common/Networking/Messages/BaseMessage.cs b/GServer.Common/Networking/Messages/BaseMessage.cs
index 7289d45..91ebde1 100644
--- a/GServer.Common/Networking/Messages/BaseMessage.cs
+++ b/GServer.Common/Networking/Messages/BaseMessage.cs
@@ -4,7 +4,7 @@ public abstract class BaseMessage
{
protected readonly byte PacketId;
- public BaseMessage(byte packetId)
+ protected BaseMessage(byte packetId)
{
PacketId = packetId;
}
diff --git a/GServer.Common/Networking/Messages/Client/AuthResponseMessage.cs b/GServer.Common/Networking/Messages/Client/AuthResponseMessage.cs
index ad69d4d..3d4668d 100644
--- a/GServer.Common/Networking/Messages/Client/AuthResponseMessage.cs
+++ b/GServer.Common/Networking/Messages/Client/AuthResponseMessage.cs
@@ -1,68 +1,69 @@
-using System.Text;
-using GServer.Common.Networking.Enums;
-
-namespace GServer.Common.Networking.Messages.Client;
-
-public enum AuthResponseFailure : byte
-{
- IncorrectLoginOrPassword,
- Unknown
-}
-
-public class AuthResponseMessage : BaseMessage, IMessage
-{
- public bool IsSuccessful { get; private set; }
-
- ///
- /// Used to authenticate the user. Only set if IsSuccessful is true.
- ///
- public string? SessionToken { get; private set; }
-
- ///
- /// Reason for auth failure. Only set is IsSuccessful is false.
- ///
- public AuthResponseFailure? FailureReason { get; private set; }
-
- public AuthResponseMessage(bool isSuccessful, string? sessionToken = null, AuthResponseFailure? failureReason = null) : base((byte)ClientPacketIn.AUTH_RESPONSE)
- {
- IsSuccessful = isSuccessful;
- SessionToken = sessionToken;
- FailureReason = failureReason;
- }
-
- public AuthResponseMessage(MessageMemoryStream stream) : base((byte)ClientPacketIn.AUTH_RESPONSE)
- {
- IsSuccessful = stream.ReadBoolean();
-
- if (IsSuccessful)
- {
- ushort sessionTokenLen = stream.ReadUInt16();
- SessionToken = stream.ReadUTF8String(sessionTokenLen);
- }
- else
- {
- FailureReason = (AuthResponseFailure)stream.ReadByte();
- }
- }
-
- public byte[] Serialize()
- {
- using MessageMemoryStream stream = new();
-
- stream.WriteByte(PacketId);
- stream.WriteBoolean(IsSuccessful);
-
- if (IsSuccessful)
- {
- short sessionTokenByteLen = (short)Encoding.UTF8.GetByteCount(SessionToken!);
- stream.WriteUInt16(sessionTokenByteLen);
- stream.WriteUTF8String(SessionToken!);
- }
- else
- {
- stream.WriteByte((byte)FailureReason!);
- }
-
- return stream.ToArray();
- }
-}
+using System.Text;
+using GServer.Common.Networking.Core;
+using GServer.Common.Networking.Enums;
+
+namespace GServer.Common.Networking.Messages.Client;
+
+public enum AuthResponseFailure : byte
+{
+ IncorrectLoginOrPassword,
+ Unknown
+}
+
+public class AuthResponseMessage : BaseMessage, IMessage
+{
+ public bool IsSuccessful { get; }
+
+ ///
+ /// Used to authenticate the user. Only set if IsSuccessful is true.
+ ///
+ public string? SessionToken { get; }
+
+ ///
+ /// Reason for auth failure. Only set is IsSuccessful is false.
+ ///
+ public AuthResponseFailure? FailureReason { get; }
+
+ public AuthResponseMessage(bool isSuccessful, string? sessionToken = null, AuthResponseFailure? failureReason = null) : base((byte)ClientPacketIn.AuthResponse)
+ {
+ IsSuccessful = isSuccessful;
+ SessionToken = sessionToken;
+ FailureReason = failureReason;
+ }
+
+ public AuthResponseMessage(MessageMemoryStream stream) : base((byte)ClientPacketIn.AuthResponse)
+ {
+ IsSuccessful = stream.ReadBoolean();
+
+ if (IsSuccessful)
+ {
+ ushort sessionTokenLen = stream.ReadUInt16();
+ SessionToken = stream.ReadUtf8String(sessionTokenLen);
+ }
+ else
+ {
+ FailureReason = (AuthResponseFailure)stream.ReadByte();
+ }
+ }
+
+ public byte[] Serialize()
+ {
+ using MessageMemoryStream stream = new();
+
+ stream.WriteByte(PacketId);
+ stream.WriteBoolean(IsSuccessful);
+
+ if (IsSuccessful)
+ {
+ short sessionTokenByteLen = (short)Encoding.UTF8.GetByteCount(SessionToken!);
+ stream.WriteUInt16(sessionTokenByteLen);
+ stream.WriteUtf8String(SessionToken!);
+ }
+ else
+ {
+ stream.WriteByte((byte)FailureReason!);
+ }
+
+ return stream.ToArray();
+ }
+}
diff --git a/GServer.Common/Networking/Messages/IMessageHandler.cs b/GServer.Common/Networking/Messages/IMessageHandler.cs
index 42e3866..0cb03d4 100644
--- a/GServer.Common/Networking/Messages/IMessageHandler.cs
+++ b/GServer.Common/Networking/Messages/IMessageHandler.cs
@@ -1,4 +1,5 @@
using System.Net.Sockets;
+using GServer.Common.Networking.Core;
namespace GServer.Common.Networking.Messages;
diff --git a/GServer.Common/Networking/Messages/Server/AuthMessage.cs b/GServer.Common/Networking/Messages/Server/AuthMessage.cs
index 0ad0750..fd5ad66 100644
--- a/GServer.Common/Networking/Messages/Server/AuthMessage.cs
+++ b/GServer.Common/Networking/Messages/Server/AuthMessage.cs
@@ -1,26 +1,27 @@
using System.Text;
+using GServer.Common.Networking.Core;
using GServer.Common.Networking.Enums;
namespace GServer.Common.Networking.Messages.Server;
public class AuthMessage : BaseMessage, IMessage
{
- public string Username { get; private set; }
- public string Password { get; private set; }
+ public string Username { get; }
+ public string Password { get; }
- public AuthMessage(string username, string password) : base((byte)ServerPacketIn.AUTH)
+ public AuthMessage(string username, string password) : base((byte)ServerPacketIn.Auth)
{
Username = username;
Password = password;
}
- public AuthMessage(MessageMemoryStream stream) : base((byte)ServerPacketIn.AUTH)
+ public AuthMessage(MessageMemoryStream stream) : base((byte)ServerPacketIn.Auth)
{
byte usernameLen = (byte)stream.ReadByte();
- string username = stream.ReadUTF8String(usernameLen);
+ string username = stream.ReadUtf8String(usernameLen);
byte passwordLen = (byte)stream.ReadByte();
- string password = stream.ReadUTF8String(passwordLen);
+ string password = stream.ReadUtf8String(passwordLen);
Username = username;
Password = password;
diff --git a/GServer.Common/Networking/Messages/Server/ListServersMessage.cs b/GServer.Common/Networking/Messages/Server/ListServersMessage.cs
index e9f394d..cec5bc5 100644
--- a/GServer.Common/Networking/Messages/Server/ListServersMessage.cs
+++ b/GServer.Common/Networking/Messages/Server/ListServersMessage.cs
@@ -4,7 +4,7 @@ namespace GServer.Common.Networking.Messages.Server;
public class ListServersMessage : BaseMessage, IMessage
{
- public ListServersMessage() : base((byte)ServerPacketIn.LIST_SERVERS)
+ public ListServersMessage() : base((byte)ServerPacketIn.ListServers)
{
}
diff --git a/GServer.NCSServer/GServer.NCSServer.csproj b/GServer.NCSServer/GServer.NCSServer.csproj
new file mode 100644
index 0000000..ebc74e5
--- /dev/null
+++ b/GServer.NCSServer/GServer.NCSServer.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/GServer.NCSServer/GameSession.cs b/GServer.NCSServer/GameSession.cs
new file mode 100644
index 0000000..ca24f5a
--- /dev/null
+++ b/GServer.NCSServer/GameSession.cs
@@ -0,0 +1,51 @@
+using System.Net.Sockets;
+using NetCoreServer;
+
+namespace GServer.NCSServer;
+
+public class GameSession : TcpSession
+{
+ public GameSession(TcpServer server) : base(server)
+ {
+ }
+
+ protected override void OnConnected()
+ {
+ Console.WriteLine($"Chat TCP session with Id {Id} connected!");
+ }
+
+ protected override void OnConnecting()
+ {
+ base.OnConnecting();
+ }
+
+ protected override void OnDisconnecting()
+ {
+ base.OnDisconnecting();
+ }
+
+ protected override void OnDisconnected()
+ {
+ Console.WriteLine($"Chat TCP session with Id {Id} disconnected!");
+ }
+
+ protected override void OnReceived(byte[] buffer, long offset, long size)
+ {
+ base.OnReceived(buffer, offset, size);
+ }
+
+ protected override void OnSent(long sent, long pending)
+ {
+ base.OnSent(sent, pending);
+ }
+
+ protected override void OnEmpty()
+ {
+ base.OnEmpty();
+ }
+
+ protected override void OnError(SocketError error)
+ {
+ base.OnError(error);
+ }
+}
\ No newline at end of file
diff --git a/GServer.NCSServer/Program.cs b/GServer.NCSServer/Program.cs
new file mode 100644
index 0000000..d5d844b
--- /dev/null
+++ b/GServer.NCSServer/Program.cs
@@ -0,0 +1,4 @@
+WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
+WebApplication app = builder.Build();
+
+app.Run();
diff --git a/GServer.NCSServer/Properties/launchSettings.json b/GServer.NCSServer/Properties/launchSettings.json
new file mode 100644
index 0000000..e5a5080
--- /dev/null
+++ b/GServer.NCSServer/Properties/launchSettings.json
@@ -0,0 +1,38 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:58673",
+ "sslPort": 44396
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:5051",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:7192;http://localhost:5051",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/GServer.NCSServer/appsettings.Development.json b/GServer.NCSServer/appsettings.Development.json
new file mode 100644
index 0000000..ff66ba6
--- /dev/null
+++ b/GServer.NCSServer/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/GServer.NCSServer/appsettings.json b/GServer.NCSServer/appsettings.json
new file mode 100644
index 0000000..4d56694
--- /dev/null
+++ b/GServer.NCSServer/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/GServer.Server/GServer.Server.csproj b/GServer.Server/GServer.Server.csproj
index 8de6103..29b7a00 100644
--- a/GServer.Server/GServer.Server.csproj
+++ b/GServer.Server/GServer.Server.csproj
@@ -1,7 +1,7 @@
-
-
+
+
diff --git a/GServer.Server/GameServerOptions.cs b/GServer.Server/GameServerOptions.cs
index 6dd047f..e9e2911 100644
--- a/GServer.Server/GameServerOptions.cs
+++ b/GServer.Server/GameServerOptions.cs
@@ -2,5 +2,4 @@
public class GameServerOptions
{
- public int PacketLength { get; set; }
}
diff --git a/GServer.Server/Program.cs b/GServer.Server/Program.cs
index bbaadc9..3155efa 100644
--- a/GServer.Server/Program.cs
+++ b/GServer.Server/Program.cs
@@ -1,15 +1,23 @@
using System.Net;
-using GServer.Server;
+namespace GServer.Server;
+
+// ReSharper disable once ClassNeverInstantiated.Global
internal sealed class Program
{
- private const int LISTEN_PORT = 11000;
+ private const int ListenPort = 11000;
private static void Main(string[] args)
{
- TCPGameServer server = new(new IPEndPoint(IPAddress.Any, LISTEN_PORT), new GameServerOptions());
+
CancellationTokenSource cancellationTokenSource = new();
- server.Start(cancellationTokenSource.Token).Wait();
+ Thread serverWorker = new(delegate()
+ {
+ TcpGameServer server = new(new IPEndPoint(IPAddress.Any, ListenPort), new GameServerOptions());
+ server.Start();
+ });
+
+ serverWorker.Start();
}
}
\ No newline at end of file
diff --git a/GServer.Server/Services/ServerListService.cs b/GServer.Server/Services/ServerListService.cs
deleted file mode 100644
index f11b38d..0000000
--- a/GServer.Server/Services/ServerListService.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using GServer.Common.Game.Entities;
-
-namespace GServer.Server.Services;
-
-public class ServerListService
-{
- public ServerListService()
- {
- }
-
- public IEnumerable List()
- {
- return [
- new ServerListing
- {
- Name = "Smallville",
- Description = "A tiny development server!",
- IPAddress = "localhost",
- Port = 11001,
- Playercount = 1,
- }
- ];
- }
-}
\ No newline at end of file
diff --git a/GServer.Server/TCPGameServer.cs b/GServer.Server/TCPGameServer.cs
deleted file mode 100644
index 3e49f81..0000000
--- a/GServer.Server/TCPGameServer.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-using System.Net;
-using System.Net.Sockets;
-using GServer.Common;
-using GServer.Common.Networking.Messages;
-
-namespace GServer.Server;
-
-public class TCPGameServer : IDisposable
-{
- private readonly TcpListener _tcpListener;
- private readonly IPEndPoint _endPoint;
- private readonly GameServerOptions _options;
- private readonly IMessageHandler _messageHandler;
-
- public TCPGameServer(IPEndPoint endPoint, GameServerOptions options)
- {
- _endPoint = endPoint;
- _options = options;
-
- _tcpListener = new TcpListener(endPoint);
- _messageHandler = new TCPMessageHandler();
- }
-
- ///
- /// Bind the server to the given endpoint.
- ///
- public async Task Start(CancellationToken cancellationToken)
- {
- Console.WriteLine("Starting TCPGameServer listener...");
- _tcpListener.Start();
- _ = cancellationToken.Register(_tcpListener.Stop);
- Console.WriteLine($"TCPGameServer listening on {_endPoint}");
-
- while (!cancellationToken.IsCancellationRequested)
- {
- try
- {
- using TcpClient tcpClient = await _tcpListener.AcceptTcpClientAsync(cancellationToken);
-
- await ProcessAsync(tcpClient);
-
- }
- catch (SocketException) when (cancellationToken.IsCancellationRequested)
- {
- Console.WriteLine("TcpListener stopped listening because cancellation was requested.");
- }
- catch
- {
- throw;
- }
- finally
- {
- _tcpListener.Stop();
- }
- }
-
- }
-
- ///
- /// Begin processing messages
- ///
- ///
- public async Task ProcessAsync(TcpClient tcpClient)
- {
- try
- {
- using NetworkStream stream = tcpClient.GetStream();
-
- byte[] data = new byte[tcpClient.ReceiveBufferSize];
- int bytesRead = 0;
- int chunkSize = 1;
-
- // Read everything into the data buffer
- while (bytesRead < data.Length && chunkSize > 0)
- {
- bytesRead +=
- chunkSize =
- await stream.ReadAsync(data.AsMemory(bytesRead, data.Length - bytesRead));
- }
-
- // Use the in-memory buffer to process the message
- await _messageHandler.HandleMessageAsync(stream.Socket, new MessageMemoryStream(data));
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex);
- }
- }
-
- public void Dispose()
- {
- GC.SuppressFinalize(this);
- }
-}
\ No newline at end of file
diff --git a/GServer.Server/TcpGameServer.cs b/GServer.Server/TcpGameServer.cs
new file mode 100644
index 0000000..326f4b7
--- /dev/null
+++ b/GServer.Server/TcpGameServer.cs
@@ -0,0 +1,75 @@
+using System.Net;
+using System.Net.Sockets;
+using GServer.Common.Networking.Core;
+using GServer.Common.Networking.Messages;
+
+namespace GServer.Server;
+
+public class TcpGameServer(IPEndPoint endPoint, GameServerOptions options) : IDisposable
+{
+ private readonly GameServerOptions _options = options;
+ private readonly TcpListener _tcpListener = new(endPoint);
+ private readonly IMessageHandler _messageHandler = new TcpMessageHandler();
+
+ ///
+ /// Bind the server to the given endpoint.
+ ///
+ public void Start()
+ {
+ Console.WriteLine($"Starting ${nameof(TcpGameServer)} listener...");
+ _tcpListener.Start();
+ Console.WriteLine($"{nameof(TcpGameServer)} listening on {endPoint}");
+
+ while (true)
+ {
+ try
+ {
+ Console.WriteLine("Waiting for a connection...");
+
+ _tcpListener.AcceptTcpClient();
+ Console.WriteLine("Client accepted!");
+
+ Thread worker = new Thread(new ParameterizedThreadStart(HandleClient!));
+ worker.Start();
+ }
+ finally
+ {
+ _tcpListener.Stop();
+ }
+ }
+ }
+
+ private void HandleClient(object clientObj)
+ {
+ TcpClient tcpClient = (TcpClient)clientObj;
+
+ try
+ {
+ using NetworkStream stream = tcpClient.GetStream();
+
+ byte[] data = new byte[tcpClient.ReceiveBufferSize];
+ while (stream.Read(data, 0, data.Length) != 0)
+ {
+ // Use the in-memory buffer to process the message
+ _messageHandler.HandleMessageAsync(stream.Socket, new MessageMemoryStream(data)).Wait();
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex);
+ }
+ }
+
+ private async void Stop()
+ {
+ Console.WriteLine($"Stopping ${nameof(TcpGameServer)} listener...");
+ _tcpListener.Stop();
+ Console.WriteLine($"Stopped ${nameof(TcpGameServer)} listener.");
+ }
+
+ public void Dispose()
+ {
+ Stop();
+ GC.SuppressFinalize(this);
+ }
+}
\ No newline at end of file
diff --git a/GServer.Server/TCPMessageHandler.cs b/GServer.Server/TcpMessageHandler.cs
similarity index 73%
rename from GServer.Server/TCPMessageHandler.cs
rename to GServer.Server/TcpMessageHandler.cs
index 30886be..6555972 100644
--- a/GServer.Server/TCPMessageHandler.cs
+++ b/GServer.Server/TcpMessageHandler.cs
@@ -1,5 +1,5 @@
using System.Net.Sockets;
-using GServer.Common;
+using GServer.Common.Networking.Core;
using GServer.Common.Networking.Enums;
using GServer.Common.Networking.Messages;
using GServer.Common.Networking.Messages.Client;
@@ -7,12 +7,8 @@ using GServer.Common.Networking.Messages.Server;
namespace GServer.Server;
-public class TCPMessageHandler : IMessageHandler
+public class TcpMessageHandler : IMessageHandler
{
- public TCPMessageHandler()
- {
- }
-
public async Task HandleMessageAsync(Socket clientSocket, MessageMemoryStream messageStream)
{
ServerPacketIn serverPacketIn = (ServerPacketIn)messageStream.ReadByte();
@@ -21,11 +17,11 @@ public class TCPMessageHandler : IMessageHandler
switch (serverPacketIn)
{
- case ServerPacketIn.AUTH:
+ case ServerPacketIn.Auth:
AuthMessage msg = new(messageStream);
- AuthResponseMessage resp = msg.Username == "aaronyarbz" && msg.Password == "password123"
- ? new(true, Guid.NewGuid().ToString(), null)
+ AuthResponseMessage resp = msg is { Username: "aaronyarbz", Password: "password123" }
+ ? new(true, Guid.NewGuid().ToString(), failureReason: null)
: new(false, null, AuthResponseFailure.IncorrectLoginOrPassword);
byte[] buffer = resp.Serialize();
@@ -33,7 +29,7 @@ public class TCPMessageHandler : IMessageHandler
break;
- case ServerPacketIn.LIST_SERVERS:
+ case ServerPacketIn.ListServers:
throw new NotImplementedException();
default:
diff --git a/GServer.Server/UDPGameServer.cs b/GServer.Server/UDPGameServer.cs
deleted file mode 100644
index a62e680..0000000
--- a/GServer.Server/UDPGameServer.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-using System.Net;
-using System.Net.Sockets;
-using GServer.Common;
-using GServer.Common.Networking.Enums;
-
-namespace GServer.Server;
-
-public class UDPGameServer : IDisposable
-{
- public readonly UdpClient UdpClient;
-
- private readonly IPEndPoint _endPoint;
-
- public UDPGameServer(IPEndPoint endPoint)
- {
- _endPoint = endPoint;
-
- UdpClient = new UdpClient();
- UdpClient.Client.SetSocketOption(
- SocketOptionLevel.Socket,
- SocketOptionName.ReuseAddress,
- true);
- }
-
- ///
- /// Bind the server to the given endpoint.
- ///
- public void Start()
- {
- UdpClient.Client.Bind(_endPoint);
- Console.WriteLine($"UDPGameServer listening on {_endPoint}");
- }
-
- ///
- /// Begin processing messages
- ///
- ///
- public async Task ProcessAsync()
- {
- try
- {
- UdpReceiveResult res = await UdpClient.ReceiveAsync();
- byte[] bytes = res.Buffer;
- MessageMemoryStream stream = new(bytes);
- await HandleMessageAsync(stream, res.RemoteEndPoint);
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex);
- }
- }
-
- private async Task HandleMessageAsync(MessageMemoryStream stream, IPEndPoint remoteEndPoint)
- {
- byte serverPacketInByte = (byte)stream.ReadByte();
- ServerPacketIn serverPacketIn = (ServerPacketIn)serverPacketInByte;
-
- Console.WriteLine($"Handling UDP message {serverPacketInByte} from {remoteEndPoint}...");
-
- throw serverPacketIn switch
- {
- ServerPacketIn.AUTH => new NotImplementedException(),
- ServerPacketIn.LIST_SERVERS => new NotImplementedException(),
- _ => new NotImplementedException($"Received unsupported packet {serverPacketInByte}"),
- };
- }
-
- public void Dispose()
- {
- UdpClient.Close();
- UdpClient.Dispose();
- GC.SuppressFinalize(this);
- }
-}
\ No newline at end of file
diff --git a/GServer.sln b/GServer.sln
index e661656..59bf784 100644
--- a/GServer.sln
+++ b/GServer.sln
@@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GServer.Server", "GServer.S
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GServer.Client", "GServer.Client\GServer.Client.csproj", "{C105363D-E719-4296-94A2-01170E603889}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GServer.NCSServer", "GServer.NCSServer\GServer.NCSServer.csproj", "{29CBF617-0334-4DC0-A61E-6F03796AF66F}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -27,6 +29,10 @@ Global
{C105363D-E719-4296-94A2-01170E603889}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C105363D-E719-4296-94A2-01170E603889}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C105363D-E719-4296-94A2-01170E603889}.Release|Any CPU.Build.0 = Release|Any CPU
+ {29CBF617-0334-4DC0-A61E-6F03796AF66F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {29CBF617-0334-4DC0-A61E-6F03796AF66F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {29CBF617-0334-4DC0-A61E-6F03796AF66F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {29CBF617-0334-4DC0-A61E-6F03796AF66F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE