alchemy

Member
What about we generalize an API that would provide current online players on a Shard so we plug it to this forum active shard or discord list?
 
Not exactly, I just thought thats what you wanted to replicate / suggested. Missed your point, my bad!
 
It's really no secret, you just send some simple data over TCP to request the status packet.
The server knows that it doesn't need to fully perform a login handshake for this type of request.

Here is a DotNET 8 implementation that returns the packet results from a TCP request;

Status Object:
C#:
public record struct ServerStatus(int Players, int Items, int Mobiles, uint UptimeStamp, TimeSpan Uptime, long Memory);

Status Request:
C#:
public static async Task<ServerStatus> RequestServerStatusAsync(string host, int port, TimeSpan timeout)
{
	try
	{
		using var tcp = new TcpClient
		{
			NoDelay = true,
			ReceiveTimeout = (int)timeout.TotalMilliseconds,
		};

		await tcp.ConnectAsync(host, port);

		var stream = tcp.GetStream();

		// Seed: 255.255.255.255
		stream.WriteByte(0xFF);
		stream.WriteByte(0xFF);
		stream.WriteByte(0xFF);
		stream.WriteByte(0xFF);

		// Packet ID: Admin Network
		stream.WriteByte(0xF1);

		// Command ID: Request Compact Server Info
		stream.WriteByte(0xFE);

		var buffer = ArrayPool<byte>.Shared.Rent(27);

		try
		{
			var read = await stream.ReadAtLeastAsync(buffer, 27);

			if (read == 27 && buffer[0] == 0x51)
			{
				var data = buffer.AsMemory();

				var length = BinaryPrimitives.ReadUInt16BigEndian(data.Span.Slice(1));

				if (length == read)
				{
					var players = BinaryPrimitives.ReadInt32BigEndian(data.Span.Slice(3));
					var items = BinaryPrimitives.ReadInt32BigEndian(data.Span.Slice(7));
					var mobiles = BinaryPrimitives.ReadInt32BigEndian(data.Span.Slice(11));
					var uptime = BinaryPrimitives.ReadUInt32BigEndian(data.Span.Slice(15));
					var memory1 = BinaryPrimitives.ReadUInt32BigEndian(data.Span.Slice(19));
					var memory2 = BinaryPrimitives.ReadUInt32BigEndian(data.Span.Slice(23));

					return new ServerStatus(players, items, mobiles, uptime, TimeSpan.FromSeconds(uptime), ((long)memory1 << 32) | memory2);
				}
			}
		}
		finally
		{
			ArrayPool<byte>.Shared.Return(buffer, true);
		}
	}
	catch
	{
	}

	return default;
}

Implementation:
C#:
ServerStatus status = await RequestServerStatusAsync("127.0.0.1", 2593, TimeSpan.FromSeconds(3));

The ServUO Shard Portal uses this same technique, it's just written in PHP and requests a slightly different packet (that is practically identical, but formatted as a string)
 

Active Shards

Donations

Total amount
$0.00
Goal
$1,000.00
Back