diff --git a/MinecraftClient/ChatBot.cs b/MinecraftClient/ChatBot.cs index 538b91c2..e5f92b35 100644 --- a/MinecraftClient/ChatBot.cs +++ b/MinecraftClient/ChatBot.cs @@ -156,6 +156,8 @@ namespace MinecraftClient /// Entity with updated location public virtual void OnEntityMove(Mapping.Entity entity) { } + public virtual void OnInternalCommand(string commandName,string commandParams, string Result) { } + /// /// Called when an entity spawned nearby /// @@ -662,6 +664,32 @@ namespace MinecraftClient { return Handler.GetInventoryEnabled(); } + public Dictionary GetInventories() + { + return Handler.GetInventories(); + } + + /// + /// start Sneaking + /// + protected bool Sneak(bool on) + { + return SendEntityAction(on ? Protocol.EntityActionType.StartSneaking : Protocol.EntityActionType.StopSneaking); + } + /// + /// Send Entity Action + /// + private bool SendEntityAction(Protocol.EntityActionType entityAction) + { + return Handler.sendEntityAction(entityAction); + } + /// + /// SetSlot + /// + protected void SetSlot(int slotNum) + { + Handler.ChangeSlot((short) slotNum); + } /// /// Get the current Minecraft World @@ -862,7 +890,7 @@ namespace MinecraftClient /// Use item currently in the player's hand (active inventory bar slot) /// /// - protected bool UseItemOnHand() + protected bool UseItemInHand() { return Handler.UseItemOnHand(); } diff --git a/MinecraftClient/ChatBots/AutoEat.cs b/MinecraftClient/ChatBots/AutoEat.cs index 7597ab90..0a32d7ac 100644 --- a/MinecraftClient/ChatBots/AutoEat.cs +++ b/MinecraftClient/ChatBots/AutoEat.cs @@ -83,7 +83,7 @@ namespace MinecraftClient.ChatBots } } } - if (found) UseItemOnHand(); + if (found) UseItemInHand(); return found; } } diff --git a/MinecraftClient/ChatBots/AutoFishing.cs b/MinecraftClient/ChatBots/AutoFishing.cs index 92d22165..dc2d7432 100644 --- a/MinecraftClient/ChatBots/AutoFishing.cs +++ b/MinecraftClient/ChatBots/AutoFishing.cs @@ -95,7 +95,7 @@ namespace MinecraftClient.ChatBots { LogToConsole(GetTimestamp() + ": Caught a fish!"); // retract fishing rod - UseItemOnHand(); + UseItemInHand(); if (inventoryEnabled) { if (!hasFishingRod()) @@ -110,7 +110,7 @@ namespace MinecraftClient.ChatBots // retract fishing rod need some time Thread.Sleep(800); // throw again - UseItemOnHand(); + UseItemInHand(); }); } diff --git a/MinecraftClient/ChatBots/ChatLog.cs b/MinecraftClient/ChatBots/ChatLog.cs index 38faec79..dbd028e3 100644 --- a/MinecraftClient/ChatBots/ChatLog.cs +++ b/MinecraftClient/ChatBots/ChatLog.cs @@ -12,11 +12,12 @@ namespace MinecraftClient.ChatBots public class ChatLog : ChatBot { - public enum MessageFilter { AllText, AllMessages, OnlyChat, OnlyWhispers }; + public enum MessageFilter { AllText, AllMessages, OnlyChat, OnlyWhispers, OnlyInternalCommands }; private bool dateandtime; private bool saveOther = true; private bool saveChat = true; private bool savePrivate = true; + private bool saveInternal = true; private string logfile; /// @@ -52,6 +53,12 @@ namespace MinecraftClient.ChatBots savePrivate = true; saveChat = false; break; + case MessageFilter.OnlyInternalCommands: + saveOther = false; + savePrivate = false; + saveChat = false; + saveInternal = true; + break; } if (String.IsNullOrEmpty(file) || file.IndexOfAny(Path.GetInvalidPathChars()) >= 0) { @@ -68,6 +75,7 @@ namespace MinecraftClient.ChatBots case "messages": return MessageFilter.AllMessages; case "chat": return MessageFilter.OnlyChat; case "private": return MessageFilter.OnlyWhispers; + case "internal": return MessageFilter.OnlyInternalCommands; default: return MessageFilter.AllText; } } @@ -92,6 +100,14 @@ namespace MinecraftClient.ChatBots } } + public override void OnInternalCommand(string commandName,string commandParams, string result) + { + if (saveInternal) + { + save(string.Format("Internal {0}({1}): {2}", commandName, commandParams, result)); + } + } + private void save(string tosave) { if (dateandtime) diff --git a/MinecraftClient/Commands/Sneak.cs b/MinecraftClient/Commands/Sneak.cs new file mode 100644 index 00000000..51067b53 --- /dev/null +++ b/MinecraftClient/Commands/Sneak.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MinecraftClient.Commands +{ + public class Sneak : Command + { + private bool sneaking = false; + public override string CMDName { get { return "Sneak"; } } + public override string CMDDesc { get { return "Sneak: Toggles sneaking"; } } + + public override string Run(McTcpClient handler, string command, Dictionary localVars) + { + Console.WriteLine(command); + if (sneaking) + { + var result = handler.sendEntityAction(Protocol.EntityActionType.StopSneaking); + sneaking = false; + return result ? "Success" : "Fail"; + } + else + { + var result = handler.sendEntityAction(Protocol.EntityActionType.StartSneaking); + sneaking = true; + return result ? "Success" : "Fail"; + } + + } + } +} \ No newline at end of file diff --git a/MinecraftClient/McTcpClient.cs b/MinecraftClient/McTcpClient.cs index d95af69d..9881148a 100644 --- a/MinecraftClient/McTcpClient.cs +++ b/MinecraftClient/McTcpClient.cs @@ -6,6 +6,7 @@ using System.Net.Sockets; using System.Threading; using System.IO; using System.Net; +using MinecraftClient.ChatBots; using MinecraftClient.Protocol; using MinecraftClient.Proxy; using MinecraftClient.Protocol.Handlers.Forge; @@ -170,6 +171,7 @@ namespace MinecraftClient if (Settings.AutoAttack_Enabled) { BotLoad(new ChatBots.AutoAttack()); } if (Settings.AutoFishing_Enabled) { BotLoad(new ChatBots.AutoFishing()); } if (Settings.AutoEat_Enabled) { BotLoad(new ChatBots.AutoEat(Settings.AutoEat_hungerThreshold)); } + //Add your ChatBot here by uncommenting and adapting //BotLoad(new ChatBots.YourBot()); } @@ -324,6 +326,7 @@ namespace MinecraftClient } while (true); } + /// /// Perform an internal MCC command (not a server command, use SendText() instead for that!) @@ -334,6 +337,7 @@ namespace MinecraftClient /// TRUE if the command was indeed an internal MCC command public bool PerformInternalCommand(string command, ref string response_msg, Dictionary localVars = null) { + /* Load commands from the 'Commands' namespace */ if (cmds.Count == 0) @@ -382,12 +386,28 @@ namespace MinecraftClient else if (cmds.ContainsKey(command_name)) { response_msg = cmds[command_name].Run(this, command, localVars); + foreach (ChatBot bot in bots.ToArray()) + { + try + { + bot.OnInternalCommand(command_name, string.Join(" ",Command.getArgs(command)),response_msg); + } + catch (Exception e) + { + if (!(e is ThreadAbortException)) + { + ConsoleIO.WriteLogLine("OnInternalCommand: Got error from " + bot.ToString() + ": " + e.ToString()); + } + else throw; //ThreadAbortException should not be caught + } + } } else { response_msg = "Unknown command '" + command_name + "'. Use '" + (Settings.internalCmdChar == ' ' ? "" : "" + Settings.internalCmdChar) + "help' for help."; return false; } + return true; } @@ -1356,6 +1376,7 @@ namespace MinecraftClient } } + /// /// Called when an entity moved over 8 block. /// @@ -1469,6 +1490,14 @@ namespace MinecraftClient playerEntityID = EntityID; } + /// + /// Send the Entity Action packet with the Specified ID + /// + /// TRUE if the item was successfully used + public bool sendEntityAction(EntityActionType entityAction) + { + return handler.SendEntityAction(playerEntityID, (int) entityAction); + } /// /// Use the item currently in the player's hand /// diff --git a/MinecraftClient/MinecraftClient.csproj b/MinecraftClient/MinecraftClient.csproj index b13b53a3..ed121f24 100644 --- a/MinecraftClient/MinecraftClient.csproj +++ b/MinecraftClient/MinecraftClient.csproj @@ -103,6 +103,7 @@ + @@ -119,6 +120,7 @@ + diff --git a/MinecraftClient/Protocol/EntityActionType.cs b/MinecraftClient/Protocol/EntityActionType.cs new file mode 100644 index 00000000..7d560e07 --- /dev/null +++ b/MinecraftClient/Protocol/EntityActionType.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MinecraftClient.Protocol +{ + public enum EntityActionType + { + StartSneaking, + StopSneaking, + LeaveBed, + StartSprinting, + StopSprinting + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/PacketOutgoingType.cs b/MinecraftClient/Protocol/Handlers/PacketOutgoingType.cs index 753558fa..5236aada 100644 --- a/MinecraftClient/Protocol/Handlers/PacketOutgoingType.cs +++ b/MinecraftClient/Protocol/Handlers/PacketOutgoingType.cs @@ -17,6 +17,7 @@ namespace MinecraftClient.Protocol.Handlers ClientSettings, PluginMessage, TabComplete, + EntityAction, PlayerPosition, PlayerPositionAndLook, TeleportConfirm, @@ -27,4 +28,4 @@ namespace MinecraftClient.Protocol.Handlers CloseWindow, PlayerBlockPlacement } -} +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/Protocol16.cs b/MinecraftClient/Protocol/Handlers/Protocol16.cs index 58b2aa1f..f5f0d07d 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol16.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol16.cs @@ -239,6 +239,10 @@ namespace MinecraftClient.Protocol.Handlers } else return ""; } + public bool SendEntityAction(int PlayerEntityID, int ActionID) + { + return false; + } private byte[] readNextByteArray() { diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index fab2c9fc..d63241a1 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -965,6 +965,22 @@ namespace MinecraftClient.Protocol.Handlers catch (System.IO.IOException) { return false; } catch (ObjectDisposedException) { return false; } } + + public bool SendEntityAction(int PlayerEntityID, int ActionID) + { + try + { + List fields = new List(); + fields.AddRange(dataTypes.GetVarInt(PlayerEntityID)); + fields.AddRange(dataTypes.GetVarInt(ActionID)); + fields.AddRange(dataTypes.GetVarInt(0)); + SendPacket(PacketOutgoingType.EntityAction, fields); + return true; + } + catch (SocketException) { return false; } + catch (System.IO.IOException) { return false; } + catch (ObjectDisposedException) { return false; } + } /// /// Send a respawn packet to the server diff --git a/MinecraftClient/Protocol/Handlers/Protocol18PacketTypes.cs b/MinecraftClient/Protocol/Handlers/Protocol18PacketTypes.cs index 68ffef0a..feac66ab 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18PacketTypes.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18PacketTypes.cs @@ -310,6 +310,7 @@ namespace MinecraftClient.Protocol.Handlers case PacketOutgoingType.TeleportConfirm: throw new InvalidOperationException("Teleport confirm is not supported in protocol " + protocol); case PacketOutgoingType.ClickWindow: return 0x0E; case PacketOutgoingType.CloseWindow: return 0x0D; + case PacketOutgoingType.EntityAction: return 0x0B; } } else if (protocol <= Protocol18Handler.MC1112Version) // MC 1.9, 1,10 and 1.11 @@ -330,6 +331,7 @@ namespace MinecraftClient.Protocol.Handlers case PacketOutgoingType.InteractEntity: return 0x0A; case PacketOutgoingType.ClickWindow: return 0x07; case PacketOutgoingType.CloseWindow: return 0x08; + case PacketOutgoingType.EntityAction: return 0x0B; } } else if (protocol <= Protocol18Handler.MC112Version) // MC 1.12 @@ -350,6 +352,7 @@ namespace MinecraftClient.Protocol.Handlers case PacketOutgoingType.InteractEntity: return 0x0B; case PacketOutgoingType.ClickWindow: return 0x07; case PacketOutgoingType.CloseWindow: return 0x08; + case PacketOutgoingType.EntityAction: return 0x0B; } } else if (protocol <= Protocol18Handler.MC1122Version) // 1.12.2 @@ -370,6 +373,7 @@ namespace MinecraftClient.Protocol.Handlers case PacketOutgoingType.InteractEntity: return 0x0A; case PacketOutgoingType.ClickWindow: return 0x07; case PacketOutgoingType.CloseWindow: return 0x08; + case PacketOutgoingType.EntityAction: return 0x0B; } } else if (protocol < Protocol18Handler.MC114Version) // MC 1.13 to 1.13.2 @@ -390,6 +394,7 @@ namespace MinecraftClient.Protocol.Handlers case PacketOutgoingType.InteractEntity: return 0x0D; case PacketOutgoingType.ClickWindow: return 0x08; case PacketOutgoingType.CloseWindow: return 0x09; + case PacketOutgoingType.EntityAction: return 0x19; } } else // MC 1.14 to 1.15 @@ -412,6 +417,7 @@ namespace MinecraftClient.Protocol.Handlers case PacketOutgoingType.PlayerBlockPlacement: return 0x2C; case PacketOutgoingType.ClickWindow: return 0x09; case PacketOutgoingType.CloseWindow: return 0x0A; + case PacketOutgoingType.EntityAction: return 0x19; } } diff --git a/MinecraftClient/Protocol/IMinecraftCom.cs b/MinecraftClient/Protocol/IMinecraftCom.cs index 1b876db1..00e57790 100644 --- a/MinecraftClient/Protocol/IMinecraftCom.cs +++ b/MinecraftClient/Protocol/IMinecraftCom.cs @@ -85,7 +85,15 @@ namespace MinecraftClient.Protocol /// packet Data /// True if message was successfully sent bool SendPluginChannelPacket(string channel, byte[] data); - + + /// + /// Send Entity Action packet to the server. + /// + /// PlayerID + /// Type of packet to send + /// True if packet was successfully sent + bool SendEntityAction(int EntityID, int type); + /// /// Send a held item change packet to the server. /// diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs index fca92a25..2afcafd9 100644 --- a/MinecraftClient/Settings.cs +++ b/MinecraftClient/Settings.cs @@ -466,7 +466,6 @@ namespace MinecraftClient case "matchesfile": AutoRespond_Matches = argValue; break; } break; - case ParseMode.AutoAttack: switch (argName.ToLower()) { @@ -689,12 +688,13 @@ namespace MinecraftClient + "\r\n" + "[AutoFishing]\r\n" + "# Entity Handling NEED to be enabled first\r\n" - + "enabled=false" + + "enabled=false\r\n" + "\r\n" + "[AutoEat]\r\n" + "# Inventory Handling NEED to be enabled first\r\n" + "enabled=false\r\n" - + "threshold=6", Encoding.UTF8); + + "threshold=6\r\n" + + "\r\n", Encoding.UTF8); } ///