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);
		// Packet Length: 4 Bytes
		stream.WriteByte(0x00);
		stream.WriteByte(0x04);
		// 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.
