diff --git a/MinecraftClient/McTcpClient.cs b/MinecraftClient/McTcpClient.cs index fed884a1..e1e5c6bd 100644 --- a/MinecraftClient/McTcpClient.cs +++ b/MinecraftClient/McTcpClient.cs @@ -8,6 +8,7 @@ using System.IO; using System.Net; using MinecraftClient.Protocol; using MinecraftClient.Proxy; +using MinecraftClient.Protocol.Handlers.Forge; namespace MinecraftClient { @@ -54,9 +55,9 @@ namespace MinecraftClient /// The server port to use /// Minecraft protocol version to use - public McTcpClient(string username, string uuid, string sessionID, int protocolversion, string server_ip, ushort port) + public McTcpClient(string username, string uuid, string sessionID, int protocolversion, ForgeInfo forgeInfo, string server_ip, ushort port) { - StartClient(username, uuid, sessionID, server_ip, port, protocolversion, false, ""); + StartClient(username, uuid, sessionID, server_ip, port, protocolversion, forgeInfo, false, ""); } /// @@ -70,9 +71,9 @@ namespace MinecraftClient /// Minecraft protocol version to use /// The text or command to send. - public McTcpClient(string username, string uuid, string sessionID, string server_ip, ushort port, int protocolversion, string command) + public McTcpClient(string username, string uuid, string sessionID, string server_ip, ushort port, int protocolversion, ForgeInfo forgeInfo, string command) { - StartClient(username, uuid, sessionID, server_ip, port, protocolversion, true, command); + StartClient(username, uuid, sessionID, server_ip, port, protocolversion, forgeInfo, true, command); } /// @@ -87,7 +88,7 @@ namespace MinecraftClient /// If set to true, the client will send a single command and then disconnect from the server /// The text or command to send. Will only be sent if singlecommand is set to true. - private void StartClient(string user, string uuid, string sessionID, string server_ip, ushort port, int protocolversion, bool singlecommand, string command) + private void StartClient(string user, string uuid, string sessionID, string server_ip, ushort port, int protocolversion, ForgeInfo forgeInfo, bool singlecommand, string command) { bool retry = false; this.sessionid = sessionID; @@ -113,7 +114,7 @@ namespace MinecraftClient { client = ProxyHandler.newTcpClient(host, port); client.ReceiveBufferSize = 1024 * 1024; - handler = Protocol.ProtocolHandler.getProtocolHandler(client, protocolversion, this); + handler = Protocol.ProtocolHandler.getProtocolHandler(client, protocolversion, forgeInfo, this); Console.WriteLine("Version is supported.\nLogging in..."); try diff --git a/MinecraftClient/MinecraftClient.csproj b/MinecraftClient/MinecraftClient.csproj index 9e1fc0c7..2e2ad727 100644 --- a/MinecraftClient/MinecraftClient.csproj +++ b/MinecraftClient/MinecraftClient.csproj @@ -114,6 +114,7 @@ + diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs index a9e4575d..302e50bb 100644 --- a/MinecraftClient/Program.cs +++ b/MinecraftClient/Program.cs @@ -5,6 +5,7 @@ using System.Text; using MinecraftClient.Protocol; using System.Reflection; using System.Threading; +using MinecraftClient.Protocol.Handlers.Forge; namespace MinecraftClient { @@ -145,6 +146,7 @@ namespace MinecraftClient //Get server version int protocolversion = 0; + ForgeInfo forgeInfo = null; if (Settings.ServerVersion != "" && Settings.ServerVersion.ToLower() != "auto") { @@ -166,7 +168,7 @@ namespace MinecraftClient if (protocolversion == 0) { Console.WriteLine("Retrieving Server Info..."); - if (!ProtocolHandler.GetServerInfo(Settings.ServerIP, Settings.ServerPort, ref protocolversion)) + if (!ProtocolHandler.GetServerInfo(Settings.ServerIP, Settings.ServerPort, ref protocolversion, ref forgeInfo)) { HandleFailure("Failed to ping this IP.", true, ChatBots.AutoRelog.DisconnectReason.ConnectionLost); return; @@ -180,9 +182,9 @@ namespace MinecraftClient //Start the main TCP client if (Settings.SingleCommand != "") { - Client = new McTcpClient(Settings.Username, UUID, sessionID, Settings.ServerIP, Settings.ServerPort, protocolversion, Settings.SingleCommand); + Client = new McTcpClient(Settings.Username, UUID, sessionID, Settings.ServerIP, Settings.ServerPort, protocolversion, forgeInfo, Settings.SingleCommand); } - else Client = new McTcpClient(Settings.Username, UUID, sessionID, protocolversion, Settings.ServerIP, Settings.ServerPort); + else Client = new McTcpClient(Settings.Username, UUID, sessionID, protocolversion, forgeInfo, Settings.ServerIP, Settings.ServerPort); //Update console title if (Settings.ConsoleTitle != "") diff --git a/MinecraftClient/Protocol/Handlers/Forge/ForgeInfo.cs b/MinecraftClient/Protocol/Handlers/Forge/ForgeInfo.cs new file mode 100755 index 00000000..dd3a83de --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/Forge/ForgeInfo.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MinecraftClient.Protocol.Handlers.Forge +{ + /// + /// Contains information about a modded server install. + /// + public class ForgeInfo + { + /// + /// Represents an individual forge mod. + /// + public class ForgeMod + { + public ForgeMod(String ModID, String Version) + { + this.ModID = ModID; + this.Version = Version; + } + + public readonly String ModID; + public readonly String Version; + + public override string ToString() + { + return ModID + " v" + Version; + } + } + + public List Mods; + + /// + /// Create a new ForgeInfo from the given data. + /// + /// The modinfo JSON tag. + internal ForgeInfo(Json.JSONData data) + { + // Example ModInfo (with spacing): + + // "modinfo": { + // "type": "FML", + // "modList": [{ + // "modid": "mcp", + // "version": "9.05" + // }, { + // "modid": "FML", + // "version": "8.0.99.99" + // }, { + // "modid": "Forge", + // "version": "11.14.3.1512" + // }, { + // "modid": "rpcraft", + // "version": "Beta 1.3 - 1.8.0" + // }] + // } + + this.Mods = new List(); + foreach (Json.JSONData mod in data.Properties["modList"].DataArray) + { + String modid = mod.Properties["modid"].StringValue; + String version = mod.Properties["version"].StringValue; + + this.Mods.Add(new ForgeMod(modid, version)); + } + } + } +} diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index bb826930..c11479a3 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -7,6 +7,7 @@ using System.Threading; using MinecraftClient.Crypto; using MinecraftClient.Proxy; using System.Security.Cryptography; +using MinecraftClient.Protocol.Handlers.Forge; namespace MinecraftClient.Protocol.Handlers { @@ -25,18 +26,22 @@ namespace MinecraftClient.Protocol.Handlers private bool encrypted = false; private int protocolversion; + // Server forge info -- may be null. + private ForgeInfo forgeInfo; + IMinecraftComHandler handler; Thread netRead; IAesStream s; TcpClient c; - public Protocol18Handler(TcpClient Client, int ProtocolVersion, IMinecraftComHandler Handler) + public Protocol18Handler(TcpClient Client, int ProtocolVersion, IMinecraftComHandler Handler, ForgeInfo ForgeInfo) { ConsoleIO.SetAutoCompleteEngine(this); ChatParser.InitTranslations(); this.c = Client; this.protocolversion = ProtocolVersion; this.handler = Handler; + this.forgeInfo = ForgeInfo; } private Protocol18Handler(TcpClient Client) @@ -730,7 +735,7 @@ namespace MinecraftClient.Protocol.Handlers /// /// True if ping was successful - public static bool doPing(string host, int port, ref int protocolversion) + public static bool doPing(string host, int port, ref int protocolversion, ref ForgeInfo forgeInfo) { string version = ""; TcpClient tcp = ProxyHandler.newTcpClient(host, port); @@ -766,21 +771,37 @@ namespace MinecraftClient.Protocol.Handlers Json.JSONData jsonData = Json.ParseJson(result); if (jsonData.Type == Json.JSONData.DataType.Object && jsonData.Properties.ContainsKey("version")) { - jsonData = jsonData.Properties["version"]; + Json.JSONData versionData = jsonData.Properties["version"]; //Retrieve display name of the Minecraft version - if (jsonData.Properties.ContainsKey("name")) - version = jsonData.Properties["name"].StringValue; + if (versionData.Properties.ContainsKey("name")) + version = versionData.Properties["name"].StringValue; //Retrieve protocol version number for handling this server - if (jsonData.Properties.ContainsKey("protocol")) - protocolversion = atoi(jsonData.Properties["protocol"].StringValue); + if (versionData.Properties.ContainsKey("protocol")) + protocolversion = atoi(versionData.Properties["protocol"].StringValue); //Automatic fix for BungeeCord 1.8 reporting itself as 1.7... if (protocolversion < 47 && version.Split(' ', '/').Contains("1.8")) protocolversion = ProtocolHandler.MCVer2ProtocolVersion("1.8.0"); ConsoleIO.WriteLineFormatted("§8Server version : " + version + " (protocol v" + protocolversion + ")."); + + // Check for forge on the server. + if (jsonData.Properties.ContainsKey("modinfo") && jsonData.Properties["modinfo"].Type == Json.JSONData.DataType.Object) + { + Json.JSONData modData = jsonData.Properties["modinfo"]; + if (modData.Properties.ContainsKey("type") && modData.Properties["type"].StringValue == "FML") + { + forgeInfo = new ForgeInfo(modData); + + ConsoleIO.WriteLineFormatted("§8Server is running forge. Mod list:"); + foreach (ForgeInfo.ForgeMod mod in forgeInfo.Mods) + { + ConsoleIO.WriteLineFormatted("§8 " + mod.ToString()); + } + } + } return true; } } diff --git a/MinecraftClient/Protocol/ProtocolHandler.cs b/MinecraftClient/Protocol/ProtocolHandler.cs index dcd507d7..067ab4bf 100644 --- a/MinecraftClient/Protocol/ProtocolHandler.cs +++ b/MinecraftClient/Protocol/ProtocolHandler.cs @@ -6,6 +6,7 @@ using MinecraftClient.Protocol.Handlers; using MinecraftClient.Proxy; using System.Net.Sockets; using System.Net.Security; +using MinecraftClient.Protocol.Handlers.Forge; namespace MinecraftClient.Protocol { @@ -23,16 +24,17 @@ namespace MinecraftClient.Protocol /// Will contain protocol version, if ping successful /// TRUE if ping was successful - public static bool GetServerInfo(string serverIP, ushort serverPort, ref int protocolversion) + public static bool GetServerInfo(string serverIP, ushort serverPort, ref int protocolversion, ref ForgeInfo forgeInfo) { bool success = false; int protocolversionTmp = 0; + ForgeInfo forgeInfoTmp = null; if (AutoTimeout.Perform(() => { try { if (Protocol16Handler.doPing(serverIP, serverPort, ref protocolversionTmp) - || Protocol18Handler.doPing(serverIP, serverPort, ref protocolversionTmp)) + || Protocol18Handler.doPing(serverIP, serverPort, ref protocolversionTmp, ref forgeInfoTmp)) { success = true; } @@ -40,11 +42,12 @@ namespace MinecraftClient.Protocol } catch (Exception e) { - ConsoleIO.WriteLineFormatted("§8" + e.Message); + ConsoleIO.WriteLineFormatted("§8" + e.ToString()); } }, TimeSpan.FromSeconds(30))) { protocolversion = protocolversionTmp; + forgeInfo = forgeInfoTmp; return success; } else @@ -62,14 +65,14 @@ namespace MinecraftClient.Protocol /// Handler with the appropriate callbacks /// - public static IMinecraftCom getProtocolHandler(TcpClient Client, int ProtocolVersion, IMinecraftComHandler Handler) + public static IMinecraftCom getProtocolHandler(TcpClient Client, int ProtocolVersion, ForgeInfo forgeInfo, IMinecraftComHandler Handler) { int[] supportedVersions_Protocol16 = { 51, 60, 61, 72, 73, 74, 78 }; if (Array.IndexOf(supportedVersions_Protocol16, ProtocolVersion) > -1) return new Protocol16Handler(Client, ProtocolVersion, Handler); int[] supportedVersions_Protocol18 = { 4, 5, 47 }; if (Array.IndexOf(supportedVersions_Protocol18, ProtocolVersion) > -1) - return new Protocol18Handler(Client, ProtocolVersion, Handler); + return new Protocol18Handler(Client, ProtocolVersion, Handler, forgeInfo); throw new NotSupportedException("The protocol version no." + ProtocolVersion + " is not supported."); }