diff --git a/MinecraftClient/ChatBot.cs b/MinecraftClient/ChatBot.cs
index 41e29bad..13832f04 100644
--- a/MinecraftClient/ChatBot.cs
+++ b/MinecraftClient/ChatBot.cs
@@ -212,6 +212,14 @@ namespace MinecraftClient
/// Player UUID
/// New Game Mode (0: Survival, 1: Creative, 2: Adventure, 3: Spectator).
public virtual void OnGamemodeUpdate(string playername, Guid uuid, int gamemode) { }
+
+ ///
+ /// Called when the Latency has been updated for a player
+ ///
+ /// Player Name
+ /// Player UUID
+ /// Latency.
+ public virtual void OnLatencyUpdate(string playername, Guid uuid, int latency) { }
/* =================================================================== */
/* ToolBox - Methods below might be useful while creating your bot. */
diff --git a/MinecraftClient/McTcpClient.cs b/MinecraftClient/McTcpClient.cs
index 44086df7..82e312bf 100644
--- a/MinecraftClient/McTcpClient.cs
+++ b/MinecraftClient/McTcpClient.cs
@@ -1635,7 +1635,23 @@ namespace MinecraftClient
foreach (ChatBot bot in bots.ToArray())
bot.OnExplosion(location, strength, affectedBlocks);
}
-
+
+ ///
+ /// Called when Latency is updated
+ ///
+ /// player uuid
+ /// Latency
+ public void OnLatencyUpdate(Guid uuid, int latency)
+ {
+ string playerName = null;
+ if (onlinePlayers.ContainsKey(uuid))
+ {
+ playerName = onlinePlayers[uuid];
+ foreach (ChatBot bot in bots.ToArray())
+ bot.OnLatencyUpdate(playerName, uuid, latency);
+ }
+ }
+
///
/// Called when Experience bar is updated
///
diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs
index 8f129203..0b30cef4 100644
--- a/MinecraftClient/Protocol/Handlers/Protocol18.cs
+++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs
@@ -448,7 +448,8 @@ namespace MinecraftClient.Protocol.Handlers
handler.OnGamemodeUpdate(uuid, gamemode);
break;
case 0x02: //Update latency
- dataTypes.ReadNextVarInt(packetData);
+ int latency = dataTypes.ReadNextVarInt(packetData);
+ handler.OnLatencyUpdate(uuid, latency); //Update latency;
break;
case 0x03: //Update display name
if (dataTypes.ReadNextBool(packetData))
@@ -1390,6 +1391,8 @@ namespace MinecraftClient.Protocol.Handlers
Container inventory = handler.GetInventory(windowId);
if (inventory.Items.ContainsKey(slotId))
inventory.Items[slotId].Count--; // server won't update us after dropped
+ if (inventory.Items[slotId].Count == 0)
+ inventory.Items.Remove(slotId);
break;
case WindowActionType.DropItemStack:
button = 1;
diff --git a/MinecraftClient/Protocol/IMinecraftComHandler.cs b/MinecraftClient/Protocol/IMinecraftComHandler.cs
index 34b3c916..d04f9fd4 100644
--- a/MinecraftClient/Protocol/IMinecraftComHandler.cs
+++ b/MinecraftClient/Protocol/IMinecraftComHandler.cs
@@ -222,7 +222,14 @@ namespace MinecraftClient.Protocol
/// Affected player's UUID
/// New game mode
void OnGamemodeUpdate(Guid uuid, int gamemode);
-
+
+ ///
+ /// Called when a player's latency has changed
+ ///
+ /// Affected player's UUID
+ /// latency
+ void OnLatencyUpdate(Guid uuid, int latency);
+
///
/// Called when Experience bar is updated
///
diff --git a/MinecraftClient/WinAPI/ConsoleIcon.cs b/MinecraftClient/WinAPI/ConsoleIcon.cs
index a320580c..c18ab21c 100644
--- a/MinecraftClient/WinAPI/ConsoleIcon.cs
+++ b/MinecraftClient/WinAPI/ConsoleIcon.cs
@@ -21,6 +21,32 @@ namespace MinecraftClient.WinAPI
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetConsoleIcon(IntPtr hIcon);
+ ///
+ /// Asynchronously download the player's skin and set the head as console icon
+ ///
+ public enum WinMessages : uint
+ {
+ ///
+ /// An application sends the WM_SETICON message to associate a new large or small icon with a window.
+ /// The system displays the large icon in the ALT+TAB dialog box, and the small icon in the window caption.
+ ///
+ SETICON = 0x0080,
+ }
+
+ [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
+ private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);
+
+
+ private static void SetWindowIcon(System.Drawing.Icon icon)
+ {
+ IntPtr mwHandle = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
+ IntPtr result01 = SendMessage(mwHandle, (int)WinMessages.SETICON, 0, icon.Handle);
+ IntPtr result02 = SendMessage(mwHandle, (int)WinMessages.SETICON, 1, icon.Handle);
+ }
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern bool SetConsoleIcon(IntPtr hIcon);
+
///
/// Asynchronously download the player's skin and set the head as console icon
///
@@ -31,7 +57,7 @@ namespace MinecraftClient.WinAPI
{
Thread t = new Thread(new ThreadStart(delegate
{
- HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create("http://skins.minecraft.net/MinecraftSkins/" + playerName + ".png");
+ HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create("https://minotar.net/helm/" + playerName + "/100.png");
try
{
using (HttpWebResponse httpWebReponse = (HttpWebResponse)httpWebRequest.GetResponse())
@@ -40,6 +66,7 @@ namespace MinecraftClient.WinAPI
{
Bitmap skin = new Bitmap(Image.FromStream(httpWebReponse.GetResponseStream())); //Read skin from network
skin = skin.Clone(new Rectangle(8, 8, 8, 8), skin.PixelFormat); //Crop skin
+ SetWindowIcon(Icon.FromHandle(skin.GetHicon()));
SetConsoleIcon(skin.GetHicon()); //Set skin as icon
}
catch (ArgumentException) { /* Invalid image in HTTP response */ }