feat: wip: support list server req and resp

This commit is contained in:
Aaron Yarborough 2025-02-20 22:44:36 +00:00
parent acb1e43b08
commit fb863fb7e0
5 changed files with 171 additions and 80 deletions

View file

@ -1,5 +1,6 @@
using System.Net;
using System.Net.Sockets;
using GServer.Common.Game.Entities;
using GServer.Common.Networking.Core;
using GServer.Common.Networking.Enums;
using GServer.Common.Networking.Messages.Client;
@ -7,10 +8,12 @@ using GServer.Common.Networking.Messages.Server;
namespace GServer.Client;
public class Program
public static class Program
{
private const int ServerPort = 11000;
private static string? _sessionToken;
private static void Main(string[] args)
{
IPEndPoint serverEp = new(IPAddress.Any, ServerPort);
@ -18,46 +21,70 @@ public class Program
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)
while (_sessionToken is null)
{
byte[] bytes = new byte[tcpClient.Client.ReceiveBufferSize];
_ = tcpClient.Client.Receive(bytes);
Console.WriteLine("Username...");
string username = Console.ReadLine()!;
MessageMemoryStream stream = new(bytes);
Console.WriteLine("Password...");
string password = Console.ReadLine()!;
ClientPacketIn packetIn = (ClientPacketIn)stream.ReadByte();
switch (packetIn)
AuthMessage authMessage = new(username, password);
_ = tcpClient.Client.Send(authMessage.Serialize());
while (true)
{
case ClientPacketIn.AuthResponse:
AuthResponseMessage authResultMessage = new(stream);
Console.WriteLine("Listening for message...");
byte[] bytes = new byte[tcpClient.Client.ReceiveBufferSize];
_ = tcpClient.Client.Receive(bytes);
Console.WriteLine("Success = " + authResultMessage.IsSuccessful);
Console.WriteLine("SessionToken = " + authResultMessage.SessionToken);
Console.WriteLine("FailureReason = " + authResultMessage.FailureReason);
MessageMemoryStream stream = new(bytes);
break;
ClientPacketIn packetIn = (ClientPacketIn)stream.ReadByte();
switch (packetIn)
{
case ClientPacketIn.AuthResponse:
AuthResponseMessage authResultMessage = new(stream);
case ClientPacketIn.ListServersResponse:
break;
Console.WriteLine("Success = " + authResultMessage.IsSuccessful);
Console.WriteLine("SessionToken = " + authResultMessage.SessionToken);
Console.WriteLine("FailureReason = " + authResultMessage.FailureReason);
case ClientPacketIn.Unknown:
break;
// Request server list as soon as login has succeeded
default:
Console.WriteLine("Received unsupported packet.");
break;
if (authResultMessage.IsSuccessful)
{
Console.WriteLine("Getting server list...");
_ = tcpClient.Client.Send(new[] { (byte)ServerPacketIn.ListServers });
}
break;
case ClientPacketIn.ListServersResponse:
ListServersResponseMessage listServersResponseMessage = new(stream);
Console.WriteLine("Here are the servers!");
foreach (ServerListing server in listServersResponseMessage.ServerListings)
{
Console.WriteLine(server.Name);
Console.WriteLine($"Desc: {server.Description}");
Console.WriteLine($"Address: {server.IpAddress}:{server.Port}");
Console.WriteLine($"Tier: {server.ServerTier}");
}
break;
case ClientPacketIn.Unknown:
break;
default:
Console.WriteLine("Received unsupported packet.");
break;
}
}
}
}
@ -70,4 +97,5 @@ public class Program
tcpClient.Close();
}
}
}
}

View file

@ -31,6 +31,13 @@ public class MessageMemoryStream : MemoryStream
return BitConverter.ToInt16(buffer);
}
public long ReadInt64()
{
byte[] buffer = new byte[8];
_ = Read(buffer, 0, 8);
return BitConverter.ToInt64(buffer);
}
public string ReadUtf8String(int length)
{
byte[] bytes = new byte[length];

View file

@ -0,0 +1,69 @@
using GServer.Common.Game.Entities;
using GServer.Common.Networking.Core;
using GServer.Common.Networking.Enums;
namespace GServer.Common.Networking.Messages.Server;
public class ListServersResponseMessage : BaseMessage, IMessage<ListServersResponseMessage>
{
public ServerListing[] ServerListings;
public const int SERVER_NAME_BYTES = 50;
public const int SERVER_DESCRIPTION_BYTES = 1000;
public const int SERVER_IP_BYTES = 15;
public ListServersResponseMessage(ServerListing[] serverListings) : base((byte)ClientPacketIn.ListServersResponse)
{
ServerListings = serverListings;
}
public ListServersResponseMessage(MessageMemoryStream stream) : base((byte)ClientPacketIn.ListServersResponse)
{
List<ServerListing> serverListings = [];
while (stream.Position != stream.Length)
{
// TODO: remove this from the packet as I don't think it's needed
// long blockSize = stream.ReadInt64();
ServerListing serverListing = new()
{
Name = stream.ReadUtf8String(SERVER_NAME_BYTES),
Description = stream.ReadUtf8String(SERVER_DESCRIPTION_BYTES),
Playercount = stream.ReadUInt16(),
IpAddress = stream.ReadUtf8String(SERVER_IP_BYTES),
Port = stream.ReadUInt16(),
ServerTier = (ServerTier)stream.ReadByte()
};
serverListings.Add(serverListing);
}
ServerListings = serverListings.ToArray();
}
public byte[] Serialize()
{
using MessageMemoryStream stream = new();
stream.WriteByte(PacketId);
foreach (ServerListing listing in ServerListings)
{
using MessageMemoryStream listingStream = new();
listingStream.WriteUtf8StringOfSize(SERVER_NAME_BYTES, listing.Name);
listingStream.WriteUtf8StringOfSize(SERVER_DESCRIPTION_BYTES, listing.Description);
listingStream.WriteUInt16(listing.Playercount);
listingStream.WriteUtf8StringOfSize(15, listing.IpAddress);
listingStream.WriteUInt16(listing.Port);
listingStream.WriteByte((byte)listing.ServerTier);
long listingBlockSize = listingStream.Length;
stream.WriteInt64(listingBlockSize);
stream.WriteBytes(listingStream.ToArray());
}
return stream.ToArray();
}
}

View file

@ -1,42 +0,0 @@
using GServer.Common.Game.Entities;
using GServer.Common.Networking.Core;
using GServer.Common.Networking.Enums;
namespace GServer.Common.Networking.Messages.Server;
public class ListServersMessage : BaseMessage, IMessage<ListServersMessage>
{
public ServerListing[] ServerListings;
public const int SERVER_NAME_BYTES = 50;
public ListServersMessage(ServerListing[] serverListings) : base((byte)ServerPacketIn.ListServers)
{
ServerListings = serverListings;
}
public byte[] Serialize()
{
using MessageMemoryStream stream = new();
stream.WriteByte(PacketId);
foreach (ServerListing listing in ServerListings)
{
using MessageMemoryStream listingStream = new();
listingStream.WriteUtf8StringOfSize(50, listing.Name);
listingStream.WriteUtf8StringOfSize(1000, listing.Description);
listingStream.WriteUInt16(listing.Playercount);
listingStream.WriteUtf8StringOfSize(15, listing.IpAddress);
listingStream.WriteUInt16(listing.Port);
listingStream.WriteByte((byte)listing.ServerTier);
long listingBlockSize = listingStream.Length;
stream.WriteInt64(listingBlockSize);
stream.WriteBytes(listingStream.ToArray());
}
return stream.ToArray();
}
}

View file

@ -1,4 +1,6 @@
using System.Net.Sockets;
using GServer.Common;
using GServer.Common.Game.Entities;
using GServer.Common.Networking.Core;
using GServer.Common.Networking.Enums;
using GServer.Common.Networking.Messages;
@ -26,24 +28,51 @@ public class TcpMessageHandler(
switch (serverPacketIn)
{
case ServerPacketIn.Auth:
{
AuthMessage msg = new(messageStream);
bool isPasswordCorrect = authService.IsPasswordCorrect(msg.Username, msg.Password);
AuthResponseMessage resp = isPasswordCorrect
? new(true, Guid.NewGuid().ToString(), failureReason: null)
: new(false, null, AuthResponseFailure.IncorrectLoginOrPassword);
byte[] buffer = resp.Serialize();
_ = await clientSocket.SendAsync(buffer);
? new AuthResponseMessage(true, Guid.NewGuid().ToString(), failureReason: null)
: new AuthResponseMessage(false, null, AuthResponseFailure.IncorrectLoginOrPassword);
await SendMessageAsync(resp, clientSocket);
break;
}
case ServerPacketIn.ListServers:
throw new NotImplementedException();
{
ServerListing[] serverListings =
[
new()
{
Name = "Testbed",
Description = "A server to hone your development skills and test new ideas.",
IpAddress = "255.255.255.255",
Port = 1337,
Playercount = 12,
ServerTier = ServerTier.Default
}
];
ListServersResponseMessage resp = new(serverListings);
await SendMessageAsync(resp, clientSocket);
break;
}
default:
Console.WriteLine($"Received unsupported packet.");
break;
}
}
}
private static async Task SendMessageAsync<TMessage>(
TMessage message,
Socket clientSocket) where TMessage : IMessage<TMessage>
{
byte[] buffer = message.Serialize();
_ = await clientSocket.SendAsync(buffer);
}
}