public record struct ServerStatus(int Players, int Items, int Mobiles, uint UptimeStamp, TimeSpan Uptime, long Memory);
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;
}
ServerStatus status = await RequestServerStatusAsync("127.0.0.1", 2593, TimeSpan.FromSeconds(3));
We use essential cookies to make this site work, and optional cookies to enhance your experience.