Skip to content

Instantly share code, notes, and snippets.

@glombek
Forked from barneygale/gist:1235274
Last active December 16, 2015 20:48
Show Gist options
  • Save glombek/5494697 to your computer and use it in GitHub Desktop.
Save glombek/5494697 to your computer and use it in GitHub Desktop.
A class to ping a Minecraft server for its description, player count and maximum player count. Based on barneygale's PHP code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
namespace Minecraft
{
public class MinecraftServerInfo
{
const string NonNumericRegex = "[^.0-9]";
/// <summary>
/// A class to ping a Minecraft server for its description, player count and maximum player count.
/// </summary>
/// <param name="host">Address of server to ping.</param>
/// <param name="port">Port on which the Minecraft server sits.</param>
/// <param name="sendTimeout">How long to wait when sending the ping (in milliseconds).</param>
/// <param name="recieveTimeout">How long to wait when reciving the ping response (in milliseconds).</param>
public MinecraftServerInfo(string host, int port = 25565, int sendTimeout = 0, int recieveTimeout = 30000)
{
HostName = host;
Port = port;
SendTimeout = sendTimeout;
RecieveTimeout = recieveTimeout;
Refresh();
}
/// <summary>
/// Refresh the data about this server.
/// </summary>
public void Refresh()
{
//Set up our TCP Client
TcpClient tcpClient = new TcpClient();
//Set the timeouts
tcpClient.SendTimeout = SendTimeout;
tcpClient.ReceiveTimeout = RecieveTimeout;
//Reset values
Online = false;
PlayerCount = 0;
try
{
tcpClient.Connect(HostName, Port);
NetworkStream stream = tcpClient.GetStream();
//Send server list ping
stream.Write(new byte[] { 0xFE }, 0, 1);
//Read data into buffer
byte[] buffer = new byte[256];
while (tcpClient.Connected)
{
int readBytes = stream.Read(buffer, 0, 256);
if (readBytes == 0)
break;
}
//Check we've got a 0xFF Disconnect
if (buffer[0] != 255)
{
Online = false;
}
else
{
//Server is online
Online = true;
//Remove the packet ident (0xFF) and the short containing the length of the string
buffer = buffer.Skip(3).ToArray();
//Decode UCS-2 string
string str = System.Text.Encoding.BigEndianUnicode.GetString(buffer);
//Split into array
string[] parts = str.Split('§');
//Set values
Description = parts[0].Trim();
PlayerCount = int.Parse(Regex.Replace(parts[1], "[^.0-9]", ""));
MaxPlayerCount = int.Parse(Regex.Replace(parts[2], "[^.0-9]", ""));
}
}
catch {
//Online is already set to false.
//We assume the server is offline if any errors occur.
}
finally
{
//close the client
tcpClient.Close();
}
}
/// <summary>
/// The port being pinged.
/// </summary>
public int Port { get; set; }
/// <summary>
/// The hostname being tested.
/// </summary>
public string HostName { get; set; }
public int RecieveTimeout { get; set; }
public int SendTimeout { get; set; }
/// <summary>
/// Whether we can reach the server or not.
/// </summary>
public bool Online { get; set; }
/// <summary>
/// The server's MOTD.
/// This will always be null if Online has never been true. This information is kept after a Refresh.
/// </summary>
public string Description { get; set; }
/// <summary>
/// Number of online players.
/// This will always be 0 if Online is false.
/// </summary>
public int PlayerCount { get; set; }
/// <summary>
/// Maximum number of players for this server.
/// This will always be 0 if Online has never been true. This information is kept after a Refresh.
/// </summary>
public int MaxPlayerCount { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment