Created
July 27, 2013 12:03
-
-
Save AlexArchive/6094678 to your computer and use it in GitHub Desktop.
Resolves a Minecraft Server's Information. This includes Message Of the Day (MOTD), Server Version, Player Count, Maximum Players
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public sealed class Program | |
{ | |
private static void Main() | |
{ | |
Console.Write("Server End Point: "); | |
var userInput = Console.ReadLine(); | |
if (userInput != null) | |
{ | |
var endPoint = new IPEndPoint(IPAddress.Parse(userInput), 25565); | |
var resolver = new ServerInformationResolver(); | |
var serverInfo = resolver.ResolveServerInformation(endPoint); | |
Console.WriteLine(); | |
Console.WriteLine(serverInfo.ToStringAutomatic()); | |
} | |
Console.ReadKey(); | |
} | |
} | |
public class ServerInformation | |
{ | |
public Version Version { get; private set; } | |
public string MessageOfTheDay { get; private set; } | |
public int PlayersOnline { get; private set; } | |
public int MaximumPlayers { get; private set; } | |
public ServerInformation(Version version, string messageOfTheDay, int playersOnline, int maximumPlayers) | |
{ | |
Version = version; | |
MessageOfTheDay = messageOfTheDay; | |
MaximumPlayers = maximumPlayers; | |
PlayersOnline = playersOnline; | |
} | |
} | |
public class ServerInformationResolver | |
{ | |
private readonly Socket _socket = | |
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); | |
public ServerInformation ResolveServerInformation(EndPoint remoteEndPoint) | |
{ | |
_socket.Connect(remoteEndPoint); | |
var pullInformationMessage = BuildPullServerInformationMessage(); | |
_socket.Send(pullInformationMessage, 0, pullInformationMessage.Length, SocketFlags.None); | |
var pushInformationMessage = new byte[256]; | |
var bytesRead = _socket.Receive(pushInformationMessage, 0, pushInformationMessage.Length, SocketFlags.None); | |
var rawServerInformation = new byte[bytesRead]; | |
Buffer.BlockCopy(pushInformationMessage, 5, rawServerInformation, 0, rawServerInformation.Length); | |
var parsedServerInformation = | |
Encoding.BigEndianUnicode.GetString(rawServerInformation).Split(new[] { '\u0000' }); | |
var serverInformation = BuildServerInformation(parsedServerInformation); | |
return serverInformation; | |
} | |
private static ServerInformation BuildServerInformation(IList<string> parsedServerInformation) | |
{ | |
var serverVersion = Version.Parse(parsedServerInformation[2]); | |
var messageOfTheDay = SanetizeMessageOfTheDay(parsedServerInformation[3]); | |
var playersOnline = int.Parse(parsedServerInformation[4]); | |
var maximumPlayers = int.Parse(parsedServerInformation[5]); | |
return new ServerInformation(serverVersion, messageOfTheDay, playersOnline, maximumPlayers); | |
} | |
private static byte[] BuildPullServerInformationMessage() | |
{ | |
const int PacketID = 0xFE; | |
var serverListPingPacket = new byte[] { PacketID, 1 }; | |
return serverListPingPacket; | |
} | |
private static string SanetizeMessageOfTheDay(string messageOfTheDay) | |
{ | |
//TODO: Sanetize Input | |
return messageOfTheDay; | |
} | |
} | |
public static class DebuggingExtensions | |
{ | |
public static string ToStringAutomatic<T>(this T obj) | |
{ | |
const string Seperator = "\r\n"; | |
const BindingFlags BindingFlags = BindingFlags.Instance | BindingFlags.Public; | |
var objProperties = | |
from property in obj.GetType().GetProperties(BindingFlags) | |
where property.CanRead | |
select string.Format("{0} : {1}", property.Name, property.GetValue(obj, null)); | |
return string.Join(Seperator, objProperties); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment