diff --git a/.gitignore b/.gitignore
index f911c9a3..307f491a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
/MinecraftClient.suo
/MinecraftClientGUI.v11.suo
/MinecraftClientGUI.suo
+/MinecraftClient.userprefs
diff --git a/MinecraftClient/AutoTimeout.cs b/MinecraftClient/AutoTimeout.cs
new file mode 100644
index 00000000..c0fe5368
--- /dev/null
+++ b/MinecraftClient/AutoTimeout.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Threading;
+
+namespace MinecraftClient
+{
+ ///
+ /// Allow easy timeout on pieces of code
+ ///
+ ///
+ /// By ORelio - (c) 2014 - CDDL 1.0
+ ///
+ public class AutoTimeout
+ {
+ ///
+ /// Perform the specified action with specified timeout
+ ///
+ /// Action to run
+ /// Maximum timeout in milliseconds
+ /// True if the action finished whithout timing out
+ public static bool Perform(Action action, int timeout)
+ {
+ return Perform(action, TimeSpan.FromMilliseconds(timeout));
+ }
+
+ ///
+ /// Perform the specified action with specified timeout
+ ///
+ /// Action to run
+ /// Maximum timeout
+ /// True if the action finished whithout timing out
+ public static bool Perform(Action action, TimeSpan timeout)
+ {
+ Thread thread = new Thread(new ThreadStart(action));
+ thread.Start();
+ bool success = thread.Join(timeout);
+ if (!success)
+ thread.Abort();
+ return success;
+ }
+ }
+}
\ No newline at end of file
diff --git a/MinecraftClient/ChatBot.cs b/MinecraftClient/ChatBot.cs
index 4d94ad03..d591c419 100644
--- a/MinecraftClient/ChatBot.cs
+++ b/MinecraftClient/ChatBot.cs
@@ -204,6 +204,26 @@ namespace MinecraftClient
return isValidName(sender);
}
+ //Detect HeroChat PMsend
+ //From Someone: message
+ else if (text.StartsWith("From "))
+ {
+ sender = text.Substring(5).Split(':')[0];
+ message = text.Substring(text.IndexOf(':') + 2);
+ return isValidName(sender);
+ }
+
+ //Detect HeroChat Messages
+ //[Channel] [Rank] User: Message
+ else if (text.StartsWith("[") && text.Contains(':') && tmp.Length > 2)
+ {
+ int name_end = text.IndexOf(':');
+ int name_start = text.Substring(0, name_end).LastIndexOf(']') + 2;
+ sender = text.Substring(name_start, name_end - name_start);
+ message = text.Substring(name_end + 2);
+ return isValidName(sender);
+ }
+
else return false;
}
catch (IndexOutOfRangeException) { return false; }
diff --git a/MinecraftClient/ChatBots/Alerts.cs b/MinecraftClient/ChatBots/Alerts.cs
index 4be3b16c..b60a39ee 100644
--- a/MinecraftClient/ChatBots/Alerts.cs
+++ b/MinecraftClient/ChatBots/Alerts.cs
@@ -2,125 +2,96 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.IO;
namespace MinecraftClient.ChatBots
{
///
/// This bot make the console beep on some specified words. Useful to detect when someone is talking to you, for example.
///
-
public class Alerts : ChatBot
{
private string[] dictionary = new string[0];
private string[] excludelist = new string[0];
- public override void Initialize()
+ ///
+ /// Import alerts from the specified file
+ ///
+ ///
+ ///
+ private static string[] FromFile(string file)
{
- if (System.IO.File.Exists(Settings.Alerts_MatchesFile))
+ if (File.Exists(file))
{
- List tmp_dictionary = new List();
- string[] file_lines = System.IO.File.ReadAllLines(Settings.Alerts_MatchesFile);
- foreach (string line in file_lines)
- if (line.Trim().Length > 0 && !tmp_dictionary.Contains(line.ToLower()))
- tmp_dictionary.Add(line.ToLower());
- dictionary = tmp_dictionary.ToArray();
+ //Read all lines from file, remove lines with no text, convert to lowercase,
+ //remove duplicate entries, convert to a string array, and return the result.
+ return File.ReadAllLines(file)
+ .Where(line => !String.IsNullOrWhiteSpace(line))
+ .Select(line => line.ToLower())
+ .Distinct().ToArray();
}
- else LogToConsole("File not found: " + Settings.Alerts_MatchesFile);
-
- if (System.IO.File.Exists(Settings.Alerts_ExcludesFile))
+ else
{
- List tmp_excludelist = new List();
- string[] file_lines = System.IO.File.ReadAllLines(Settings.Alerts_ExcludesFile);
- foreach (string line in file_lines)
- if (line.Trim().Length > 0 && !tmp_excludelist.Contains(line.Trim().ToLower()))
- tmp_excludelist.Add(line.ToLower());
- excludelist = tmp_excludelist.ToArray();
+ LogToConsole("File not found: " + Settings.Alerts_MatchesFile);
+ return new string[0];
}
- else LogToConsole("File not found : " + Settings.Alerts_ExcludesFile);
}
+ ///
+ /// Intitialize the Alerts bot
+ ///
+ public override void Initialize()
+ {
+ dictionary = FromFile(Settings.Alerts_MatchesFile);
+ excludelist = FromFile(Settings.Alerts_ExcludesFile);
+ }
+
+ ///
+ /// Process text received from the server to display alerts
+ ///
+ /// Received text
public override void GetText(string text)
{
- text = getVerbatim(text);
- string comp = text.ToLower();
- foreach (string alert in dictionary)
+ //Remove color codes and convert to lowercase
+ text = getVerbatim(text).ToLower();
+
+ //Proceed only if no exclusions are found in text
+ if (!excludelist.Any(exclusion => text.Contains(exclusion)))
{
- if (comp.Contains(alert))
+ //Show an alert for each alert item found in text, if any
+ foreach (string alert in dictionary.Where(alert => text.Contains(alert)))
{
- bool ok = true;
+ if (Settings.Alerts_Beep_Enabled)
+ Console.Beep(); //Text found !
- foreach (string exclusion in excludelist)
+ if (ConsoleIO.basicIO) //Using a GUI? Pass text as is.
+ ConsoleIO.WriteLine(text.Replace(alert, "§c" + alert + "§r"));
+
+ else //Using Consome Prompt : Print text with alert highlighted
{
- if (comp.Contains(exclusion))
+ string[] splitted = text.Split(new string[] { alert }, StringSplitOptions.None);
+
+ if (splitted.Length > 0)
{
- ok = false;
- break;
- }
- }
-
- if (ok)
- {
- if (Settings.Alerts_Beep_Enabled) { Console.Beep(); } //Text found !
-
- if (ConsoleIO.basicIO) { ConsoleIO.WriteLine(comp.Replace(alert, "§c" + alert + "§r")); }
- else
- {
-
- #region Displaying the text with the interesting part highlighted
-
Console.BackgroundColor = ConsoleColor.DarkGray;
Console.ForegroundColor = ConsoleColor.White;
+ ConsoleIO.Write(splitted[0]);
- //Will be used for text displaying
- string[] temp = comp.Split(alert.Split(','), StringSplitOptions.None);
- int p = 0;
-
- //Special case : alert in the beginning of the text
- string test = "";
- for (int i = 0; i < alert.Length; i++)
- {
- test += comp[i];
- }
- if (test == alert)
+ for (int i = 1; i < splitted.Length; i++)
{
Console.BackgroundColor = ConsoleColor.Yellow;
Console.ForegroundColor = ConsoleColor.Red;
- for (int i = 0; i < alert.Length; i++)
- {
- ConsoleIO.Write(text[p]);
- p++;
- }
- }
+ ConsoleIO.Write(alert);
- //Displaying the rest of the text
- for (int i = 0; i < temp.Length; i++)
- {
Console.BackgroundColor = ConsoleColor.DarkGray;
Console.ForegroundColor = ConsoleColor.White;
- for (int j = 0; j < temp[i].Length; j++)
- {
- ConsoleIO.Write(text[p]);
- p++;
- }
- Console.BackgroundColor = ConsoleColor.Yellow;
- Console.ForegroundColor = ConsoleColor.Red;
- try
- {
- for (int j = 0; j < alert.Length; j++)
- {
- ConsoleIO.Write(text[p]);
- p++;
- }
- }
- catch (IndexOutOfRangeException) { }
+ ConsoleIO.Write(splitted[i]);
}
- Console.BackgroundColor = ConsoleColor.Black;
- Console.ForegroundColor = ConsoleColor.Gray;
- ConsoleIO.Write('\n');
-
- #endregion
-
}
+
+ Console.BackgroundColor = ConsoleColor.Black;
+ Console.ForegroundColor = ConsoleColor.Gray;
+ ConsoleIO.Write('\n');
}
}
}
diff --git a/MinecraftClient/ChatBots/ChatLog.cs b/MinecraftClient/ChatBots/ChatLog.cs
index c20d6d4d..7d4acc07 100644
--- a/MinecraftClient/ChatBots/ChatLog.cs
+++ b/MinecraftClient/ChatBots/ChatLog.cs
@@ -92,7 +92,9 @@ namespace MinecraftClient.ChatBots
if (dateandtime)
tosave = getTimestamp() + ' ' + tosave;
- Directory.CreateDirectory(Path.GetDirectoryName(logfile));
+ string directory = Path.GetDirectoryName(logfile);
+ if (!String.IsNullOrEmpty(directory) && !Directory.Exists(directory))
+ Directory.CreateDirectory(directory);
FileStream stream = new FileStream(logfile, FileMode.OpenOrCreate);
StreamWriter writer = new StreamWriter(stream);
stream.Seek(0, SeekOrigin.End);
diff --git a/MinecraftClient/ChatBots/RemoteControl.cs b/MinecraftClient/ChatBots/RemoteControl.cs
index 818bab6f..dfdf5d2a 100644
--- a/MinecraftClient/ChatBots/RemoteControl.cs
+++ b/MinecraftClient/ChatBots/RemoteControl.cs
@@ -15,7 +15,7 @@ namespace MinecraftClient.ChatBots
{
text = getVerbatim(text);
string command = "", sender = "";
- if (isPrivateMessage(text, ref command, ref sender) && Settings.Bots_Owners.Contains(sender.ToLower()))
+ if (isPrivateMessage(text, ref command, ref sender) && Settings.Bots_Owners.Contains(sender.ToLower().Trim()))
{
string response = "";
performInternalCommand(command, ref response);
@@ -24,7 +24,9 @@ namespace MinecraftClient.ChatBots
SendPrivateMessage(sender, response);
}
}
- else if (Settings.RemoteCtrl_AutoTpaccept && isTeleportRequest(text, ref sender) && Settings.Bots_Owners.Contains(sender.ToLower()))
+ else if (Settings.RemoteCtrl_AutoTpaccept
+ && isTeleportRequest(text, ref sender)
+ && (Settings.RemoteCtrl_AutoTpaccept_Everyone || Settings.Bots_Owners.Contains(sender.ToLower().Trim())))
{
SendText("/tpaccept");
}
diff --git a/MinecraftClient/Commands/List.cs b/MinecraftClient/Commands/List.cs
new file mode 100644
index 00000000..116085d0
--- /dev/null
+++ b/MinecraftClient/Commands/List.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MinecraftClient.Commands
+{
+ public class List : Command
+ {
+ public override string CMDName { get { return "list"; } }
+ public override string CMDDesc { get { return "list: get the player list."; } }
+
+ public override string Run(McTcpClient handler, string command)
+ {
+ return "PlayerList: " + String.Join(", ", handler.getOnlinePlayers());
+ }
+ }
+}
+
diff --git a/MinecraftClient/McTcpClient.cs b/MinecraftClient/McTcpClient.cs
index ceaedfb9..2ba5c7d5 100644
--- a/MinecraftClient/McTcpClient.cs
+++ b/MinecraftClient/McTcpClient.cs
@@ -20,6 +20,7 @@ namespace MinecraftClient
private static List cmd_names = new List();
private static Dictionary cmds = new Dictionary();
private List bots = new List();
+ private Dictionary onlinePlayers = new Dictionary();
private static List scripts_on_hold = new List();
public void BotLoad(ChatBot b) { b.SetHandler(this); bots.Add(b); b.Initialize(); Settings.SingleCommand = ""; }
public void BotUnLoad(ChatBot b) { bots.RemoveAll(item => object.ReferenceEquals(item, b)); }
@@ -53,7 +54,7 @@ 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, short port)
+ public McTcpClient(string username, string uuid, string sessionID, int protocolversion, string server_ip, ushort port)
{
StartClient(username, uuid, sessionID, server_ip, port, protocolversion, false, "");
}
@@ -69,7 +70,7 @@ namespace MinecraftClient
/// Minecraft protocol version to use
/// The text or command to send.
- public McTcpClient(string username, string uuid, string sessionID, string server_ip, short port, int protocolversion, string command)
+ public McTcpClient(string username, string uuid, string sessionID, string server_ip, ushort port, int protocolversion, string command)
{
StartClient(username, uuid, sessionID, server_ip, port, protocolversion, true, command);
}
@@ -86,7 +87,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, short port, int protocolversion, bool singlecommand, string command)
+ private void StartClient(string user, string uuid, string sessionID, string server_ip, ushort port, int protocolversion, bool singlecommand, string command)
{
this.sessionid = sessionID;
this.uuid = uuid;
@@ -125,7 +126,9 @@ namespace MinecraftClient
}
else
{
- foreach (ChatBot bot in scripts_on_hold) { bots.Add(bot); }
+ foreach (ChatBot bot in scripts_on_hold)
+ bot.SetHandler(this);
+ bots.AddRange(scripts_on_hold);
scripts_on_hold.Clear();
Console.WriteLine("Server was successfully joined.\nType '"
@@ -280,8 +283,11 @@ namespace MinecraftClient
if (bot is ChatBots.Script)
scripts_on_hold.Add((ChatBots.Script)bot);
- handler.Disconnect();
- handler.Dispose();
+ if (handler != null)
+ {
+ handler.Disconnect();
+ handler.Dispose();
+ }
if (cmdprompt != null)
cmdprompt.Abort();
@@ -397,5 +403,36 @@ namespace MinecraftClient
{
return handler.SendRespawnPacket();
}
+
+ ///
+ /// Triggered when a new player joins the game
+ ///
+ /// UUID of the player
+ /// Name of the player
+
+ public void OnPlayerJoin(Guid uuid, string name)
+ {
+ onlinePlayers[uuid] = name;
+ }
+
+ ///
+ /// Triggered when a player has left the game
+ ///
+ /// UUID of the player
+
+ public void OnPlayerLeave(Guid uuid)
+ {
+ onlinePlayers.Remove(uuid);
+ }
+
+ ///
+ /// Get a set of online player names
+ ///
+ /// Online player names
+
+ public string[] getOnlinePlayers()
+ {
+ return onlinePlayers.Values.Distinct().ToArray();
+ }
}
}
diff --git a/MinecraftClient/MinecraftClient.csproj b/MinecraftClient/MinecraftClient.csproj
index 4bbb262f..c174cb1e 100644
--- a/MinecraftClient/MinecraftClient.csproj
+++ b/MinecraftClient/MinecraftClient.csproj
@@ -71,6 +71,7 @@
+
@@ -131,6 +132,7 @@
+
diff --git a/MinecraftClient/Protocol/Handlers/Protocol16.cs b/MinecraftClient/Protocol/Handlers/Protocol16.cs
index 54733664..740342f5 100644
--- a/MinecraftClient/Protocol/Handlers/Protocol16.cs
+++ b/MinecraftClient/Protocol/Handlers/Protocol16.cs
@@ -6,6 +6,7 @@ using System.Net.Sockets;
using System.Threading;
using MinecraftClient.Crypto;
using MinecraftClient.Proxy;
+using System.Security.Cryptography;
namespace MinecraftClient.Protocol.Handlers
{
@@ -157,7 +158,11 @@ namespace MinecraftClient.Protocol.Handlers
if (readNextInt() == 2022) { handler.OnTextReceived("You are dead. Type /reco to respawn & reconnect."); }
if (protocolversion >= 72) { readData(4); } else readData(1);
break;
- case 0xC9: readNextString(); readData(3); break;
+ case 0xC9:
+ string name = readNextString(); bool online = readNextByte() != 0x00; readData(2);
+ Guid FakeUUID = new Guid(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(name)).Take(16).ToArray());
+ if (online) { handler.OnPlayerJoin(FakeUUID, name); } else { handler.OnPlayerLeave(FakeUUID); }
+ break;
case 0xCA: if (protocolversion >= 72) { readData(9); } else readData(3); break;
case 0xCB: autocomplete_result = readNextString(); autocomplete_received = true; break;
case 0xCC: readNextString(); readData(4); break;
diff --git a/MinecraftClient/Protocol/Handlers/Protocol17.cs b/MinecraftClient/Protocol/Handlers/Protocol17.cs
index 387c8bfc..a514ffc5 100644
--- a/MinecraftClient/Protocol/Handlers/Protocol17.cs
+++ b/MinecraftClient/Protocol/Handlers/Protocol17.cs
@@ -6,6 +6,7 @@ using System.Net.Sockets;
using System.Threading;
using MinecraftClient.Crypto;
using MinecraftClient.Proxy;
+using System.Security.Cryptography;
namespace MinecraftClient.Protocol.Handlers
{
@@ -96,6 +97,17 @@ namespace MinecraftClient.Protocol.Handlers
case 0x02:
handler.OnTextReceived(ChatParser.ParseText(readNextString()));
break;
+ case 0x38:
+ string name = readNextString();
+ bool online = readNextBool();
+ short ping = readNextShort();
+ Guid FakeUUID = new Guid(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(name)).Take(16).ToArray());
+ if (online)
+ {
+ handler.OnPlayerJoin(FakeUUID, name);
+ }
+ else handler.OnPlayerLeave(FakeUUID);
+ break;
case 0x3A:
int autocomplete_count = readNextVarInt();
string tab_list = "";
@@ -186,6 +198,44 @@ namespace MinecraftClient.Protocol.Handlers
else return "";
}
+ ///
+ /// Read a uuid from the network
+ ///
+ /// Cache of bytes to read from
+ /// The uuid
+
+ private Guid readNextUUID()
+ {
+ byte[] cache = new byte[16];
+ Receive(cache, 0, 16, SocketFlags.None);
+ return new Guid(cache);
+ }
+
+ ///
+ /// Read a short from the network
+ ///
+ ///
+
+ private short readNextShort()
+ {
+ byte[] tmp = new byte[2];
+ Receive(tmp, 0, 2, SocketFlags.None);
+ Array.Reverse(tmp);
+ return BitConverter.ToInt16(tmp, 0);
+ }
+
+ ///
+ /// Read a boolean from the network
+ ///
+ ///
+
+ private bool readNextBool()
+ {
+ byte[] tmp = new byte[1];
+ Receive(tmp, 0, 1, SocketFlags.None);
+ return tmp[0] != 0x00;
+ }
+
///
/// Read a byte array from the network
///
@@ -545,14 +595,13 @@ namespace MinecraftClient.Protocol.Handlers
{
protocolversion = atoi(tmp_ver[1]);
- // Handle if "name" exists twice, like when connecting to a server with another user logged in.
+ //Handle if "name" exists twice, eg when connecting to a server with another user logged in.
version = (tmp_name.Length == 2) ? tmp_name[1].Split('"')[0] : tmp_name[2].Split('"')[0];
- if (result.Contains("modinfo\":"))
- {
- //Server is running Forge (which is not supported)
- version = "Forge " + version;
- protocolversion = 0;
- }
+
+ //Automatic fix for BungeeCord 1.8 not properly reporting protocol version
+ if (protocolversion < 47 && version.Split(' ').Contains("1.8"))
+ protocolversion = ProtocolHandler.MCVer2ProtocolVersion("1.8.0");
+
ConsoleIO.WriteLineFormatted("§8Server version : " + version + " (protocol v" + protocolversion + ").");
return true;
}
diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs
index d7cc91bc..a1eb60f3 100644
--- a/MinecraftClient/Protocol/Handlers/Protocol18.cs
+++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs
@@ -137,13 +137,31 @@ namespace MinecraftClient.Protocol.Handlers
{
switch (packetID)
{
- case 0x00:
+ case 0x00: //Keep-Alive
SendPacket(0x00, getVarInt(readNextVarInt(ref packetData)));
break;
- case 0x02:
+ case 0x02: //Chat message
handler.OnTextReceived(ChatParser.ParseText(readNextString(ref packetData)));
break;
- case 0x3A:
+ case 0x38: //Player List update
+ int action = readNextVarInt(ref packetData);
+ int numActions = readNextVarInt(ref packetData);
+ Guid uuid = readNextUUID(ref packetData);
+ switch (action)
+ {
+ case 0x00: //Player Join
+ string name = readNextString(ref packetData);
+ handler.OnPlayerJoin(uuid, name);
+ break;
+ case 0x04: //Player Leave
+ handler.OnPlayerLeave(uuid);
+ break;
+ default:
+ //Unknown player list item type
+ break;
+ }
+ break;
+ case 0x3A: //Tab-Complete Result
int autocomplete_count = readNextVarInt(ref packetData);
string tab_list = "";
for (int i = 0; i < autocomplete_count; i++)
@@ -157,10 +175,10 @@ namespace MinecraftClient.Protocol.Handlers
if (tab_list.Length > 0)
ConsoleIO.WriteLineFormatted("§8" + tab_list, false);
break;
- case 0x40:
+ case 0x40: //Kick Packet
handler.OnConnectionLost(ChatBot.DisconnectReason.InGameKick, ChatParser.ParseText(readNextString(ref packetData)));
return false;
- case 0x46:
+ case 0x46: //Network Compression Treshold Info
compression_treshold = readNextVarInt(ref packetData);
break;
default:
@@ -256,6 +274,17 @@ namespace MinecraftClient.Protocol.Handlers
else return "";
}
+ ///
+ /// Read a uuid from a cache of bytes and remove it from the cache
+ ///
+ /// Cache of bytes to read from
+ /// The uuid
+
+ private Guid readNextUUID(ref byte[] cache)
+ {
+ return new Guid(readData(16, ref cache));
+ }
+
///
/// Read a byte array from a cache of bytes and remove it from the cache
///
@@ -624,65 +653,5 @@ namespace MinecraftClient.Protocol.Handlers
while (wait_left > 0 && !autocomplete_received) { System.Threading.Thread.Sleep(100); wait_left--; }
return autocomplete_result;
}
-
- ///
- /// Ping a Minecraft server to get information about the server
- ///
- /// True if ping was successful
-
- public static bool doPing(string host, int port, ref int protocolversion)
- {
- string version = "";
- TcpClient tcp = ProxyHandler.newTcpClient(host, port);
- tcp.ReceiveBufferSize = 1024 * 1024;
-
- byte[] packet_id = getVarInt(0);
- byte[] protocol_version = getVarInt(4);
- byte[] server_adress_val = Encoding.UTF8.GetBytes(host);
- byte[] server_adress_len = getVarInt(server_adress_val.Length);
- byte[] server_port = BitConverter.GetBytes((ushort)port); Array.Reverse(server_port);
- byte[] next_state = getVarInt(1);
- byte[] packet = concatBytes(packet_id, protocol_version, server_adress_len, server_adress_val, server_port, next_state);
- byte[] tosend = concatBytes(getVarInt(packet.Length), packet);
-
- tcp.Client.Send(tosend, SocketFlags.None);
-
- byte[] status_request = getVarInt(0);
- byte[] request_packet = concatBytes(getVarInt(status_request.Length), status_request);
-
- tcp.Client.Send(request_packet, SocketFlags.None);
-
- int packetID = -1;
- byte[] packetData = new byte[] { };
- Protocol18Handler ComTmp = new Protocol18Handler(tcp);
- ComTmp.readNextPacket(ref packetID, ref packetData);
- if (packetData.Length > 0) //Verify Response length
- {
- if (packetID == 0x00) //Read Packet ID
- {
- string result = ComTmp.readNextString(ref packetData); //Get the Json data
- if (result[0] == '{' && result.Contains("protocol\":") && result.Contains("name\":\""))
- {
- string[] tmp_ver = result.Split(new string[] { "protocol\":" }, StringSplitOptions.None);
- string[] tmp_name = result.Split(new string[] { "name\":\"" }, StringSplitOptions.None);
-
- if (tmp_ver.Length >= 2 && tmp_name.Length >= 2)
- {
- protocolversion = atoi(tmp_ver[1]);
- version = tmp_name[1].Split('"')[0];
- if (result.Contains("modinfo\":"))
- {
- //Server is running Forge (which is not supported)
- version = "Forge " + version;
- protocolversion = 0;
- }
- ConsoleIO.WriteLineFormatted("§8Server version : " + version + " (protocol v" + protocolversion + ").");
- return true;
- }
- }
- }
- }
- return false;
- }
}
}
diff --git a/MinecraftClient/Protocol/IMinecraftComHandler.cs b/MinecraftClient/Protocol/IMinecraftComHandler.cs
index cc2b6055..f74d22a4 100644
--- a/MinecraftClient/Protocol/IMinecraftComHandler.cs
+++ b/MinecraftClient/Protocol/IMinecraftComHandler.cs
@@ -21,6 +21,7 @@ namespace MinecraftClient.Protocol
string getUsername();
string getUserUUID();
string getSessionID();
+ string[] getOnlinePlayers();
///
/// This method is called when the protocol handler receives a chat message
@@ -28,6 +29,21 @@ namespace MinecraftClient.Protocol
void OnTextReceived(string text);
+ ///
+ /// This method is called when a new player joins the game
+ ///
+ /// UUID of the player
+ /// Name of the player
+
+ void OnPlayerJoin(Guid uuid, string name);
+
+ ///
+ /// This method is called when a player has left the game
+ ///
+ /// UUID of the player
+
+ void OnPlayerLeave(Guid uuid);
+
///
/// This method is called when the connection has been lost
///
diff --git a/MinecraftClient/Protocol/ProtocolHandler.cs b/MinecraftClient/Protocol/ProtocolHandler.cs
index ce3a704b..08b309f3 100644
--- a/MinecraftClient/Protocol/ProtocolHandler.cs
+++ b/MinecraftClient/Protocol/ProtocolHandler.cs
@@ -23,7 +23,7 @@ namespace MinecraftClient.Protocol
/// Will contain protocol version, if ping successful
/// TRUE if ping was successful
- public static bool GetServerInfo(string serverIP, short serverPort, ref int protocolversion)
+ public static bool GetServerInfo(string serverIP, ushort serverPort, ref int protocolversion)
{
try
{
@@ -108,6 +108,7 @@ namespace MinecraftClient.Protocol
case "1.7.10":
return 5;
case "1.8.0":
+ case "1.8.1":
return 47;
default:
return 0;
@@ -229,30 +230,37 @@ namespace MinecraftClient.Protocol
private static int doHTTPSPost(string host, string endpoint, string request, ref string result)
{
- TcpClient client = ProxyHandler.newTcpClient(host, 443);
- SslStream stream = new SslStream(client.GetStream());
- stream.AuthenticateAsClient(host);
-
- List http_request = new List();
- http_request.Add("POST " + endpoint + " HTTP/1.1");
- http_request.Add("Host: " + host);
- http_request.Add("User-Agent: MCC/" + Program.Version);
- http_request.Add("Content-Type: application/json");
- http_request.Add("Content-Length: " + Encoding.ASCII.GetBytes(request).Length);
- http_request.Add("Connection: close");
- http_request.Add("");
- http_request.Add(request);
-
- stream.Write(Encoding.ASCII.GetBytes(String.Join("\r\n", http_request.ToArray())));
- System.IO.StreamReader sr = new System.IO.StreamReader(stream);
- string raw_result = sr.ReadToEnd();
-
- if (raw_result.StartsWith("HTTP/1.1"))
+ string postResult = null;
+ int statusCode = 520;
+ AutoTimeout.Perform(() =>
{
- result = raw_result.Substring(raw_result.IndexOf("\r\n\r\n") + 4);
- return Settings.str2int(raw_result.Split(' ')[1]);
- }
- else return 520; //Web server is returning an unknown error
+ TcpClient client = ProxyHandler.newTcpClient(host, 443);
+ SslStream stream = new SslStream(client.GetStream());
+ stream.AuthenticateAsClient(host);
+
+ List http_request = new List();
+ http_request.Add("POST " + endpoint + " HTTP/1.1");
+ http_request.Add("Host: " + host);
+ http_request.Add("User-Agent: MCC/" + Program.Version);
+ http_request.Add("Content-Type: application/json");
+ http_request.Add("Content-Length: " + Encoding.ASCII.GetBytes(request).Length);
+ http_request.Add("Connection: close");
+ http_request.Add("");
+ http_request.Add(request);
+
+ stream.Write(Encoding.ASCII.GetBytes(String.Join("\r\n", http_request.ToArray())));
+ System.IO.StreamReader sr = new System.IO.StreamReader(stream);
+ string raw_result = sr.ReadToEnd();
+
+ if (raw_result.StartsWith("HTTP/1.1"))
+ {
+ postResult = raw_result.Substring(raw_result.IndexOf("\r\n\r\n") + 4);
+ statusCode = Settings.str2int(raw_result.Split(' ')[1]);
+ }
+ else statusCode = 520; //Web server is returning an unknown error
+ }, 15000);
+ result = postResult;
+ return statusCode;
}
///
diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs
index 6ccbe85e..09e508f1 100644
--- a/MinecraftClient/Settings.cs
+++ b/MinecraftClient/Settings.cs
@@ -20,7 +20,7 @@ namespace MinecraftClient
public static string Username = "";
public static string Password = "";
public static string ServerIP = "";
- public static short ServerPort = 25565;
+ public static ushort ServerPort = 25565;
public static string ServerVersion = "";
public static string SingleCommand = "";
public static string ConsoleTitle = "";
@@ -86,11 +86,12 @@ namespace MinecraftClient
//Remote Control
public static bool RemoteCtrl_Enabled = false;
public static bool RemoteCtrl_AutoTpaccept = true;
+ public static bool RemoteCtrl_AutoTpaccept_Everyone = false;
//Custom app variables and Minecraft accounts
private static Dictionary AppVars = new Dictionary();
private static Dictionary> Accounts = new Dictionary>();
- private static Dictionary> Servers = new Dictionary>();
+ private static Dictionary> Servers = new Dictionary>();
private enum ParseMode { Default, Main, AppVars, Proxy, AntiAFK, Hangman, Alerts, ChatLog, AutoRelog, ScriptScheduler, RemoteControl };
@@ -154,8 +155,8 @@ namespace MinecraftClient
case "botowners":
Bots_Owners.Clear();
- foreach (string name in argValue.ToLower().Replace(" ", "").Split(','))
- Bots_Owners.Add(name);
+ foreach (string name in argValue.ToLower().Split(','))
+ Bots_Owners.Add(name.Trim());
break;
case "internalcmdchar":
@@ -186,7 +187,7 @@ namespace MinecraftClient
{
//Backup current server info
string server_host_temp = ServerIP;
- short server_port_temp = ServerPort;
+ ushort server_port_temp = ServerPort;
foreach (string server_line in File.ReadAllLines(argValue))
{
@@ -198,7 +199,7 @@ namespace MinecraftClient
&& !server_data[0].Contains('.')
&& setServerIP(server_data[1]))
Servers[server_data[0]]
- = new KeyValuePair(ServerIP, ServerPort);
+ = new KeyValuePair(ServerIP, ServerPort);
}
//Restore current server info
@@ -271,6 +272,7 @@ namespace MinecraftClient
{
case "enabled": RemoteCtrl_Enabled = str2bool(argValue); break;
case "autotpaccept": RemoteCtrl_AutoTpaccept = str2bool(argValue); break;
+ case "tpaccepteveryone": RemoteCtrl_AutoTpaccept_Everyone = str2bool(argValue); break;
}
break;
@@ -399,7 +401,8 @@ namespace MinecraftClient
+ "\r\n"
+ "[RemoteControl]\r\n"
+ "enabled=false\r\n"
- + "autotpaccept=true\r\n", Encoding.UTF8);
+ + "autotpaccept=true\r\n"
+ + "tpaccepteveryone=false\r\n", Encoding.UTF8);
}
public static int str2int(string str) { try { return Convert.ToInt32(str); } catch { return 0; } }
@@ -432,13 +435,13 @@ namespace MinecraftClient
server = server.ToLower();
string[] sip = server.Split(':');
string host = sip[0];
- short port = 25565;
+ ushort port = 25565;
if (sip.Length > 1)
{
try
{
- port = Convert.ToInt16(sip[1]);
+ port = Convert.ToUInt16(sip[1]);
}
catch (FormatException) { return false; }
}
diff --git a/MinecraftClient/config/README.txt b/MinecraftClient/config/README.txt
index 2a07bdd2..a6a705e3 100644
--- a/MinecraftClient/config/README.txt
+++ b/MinecraftClient/config/README.txt
@@ -60,7 +60,7 @@ In scripts and remote control, no slash is needed to perform the command.
- respawn : Use this to respawn if you are dead (like clicking "respawn" ingame)
- log : display some text in the console (useful for scripts)
- set varname=value : set a value which can be used as %varname% in further commands
- - wait