From 195e162c7db2d29ea1859cf10f323366fdcfe2d4 Mon Sep 17 00:00:00 2001 From: ORelio Date: Sat, 28 Mar 2020 00:48:41 +0100 Subject: [PATCH] Add code documentation, move and rename a few methods --- MinecraftClient/ChatBots/AutoAttack.cs | 10 +- MinecraftClient/ChatBots/AutoFishing.cs | 15 +- MinecraftClient/Mapping/Entity.cs | 132 ++++++++++-------- MinecraftClient/McTcpClient.cs | 55 ++++++-- .../Protocol/Handlers/Protocol16.cs | 19 +-- .../Protocol/Handlers/Protocol18.cs | 8 +- MinecraftClient/Protocol/IMinecraftCom.cs | 48 +++++++ .../Protocol/IMinecraftComHandler.cs | 87 +++++++++++- MinecraftClient/config/README.md | 2 +- README.md | 6 +- 10 files changed, 286 insertions(+), 96 deletions(-) diff --git a/MinecraftClient/ChatBots/AutoAttack.cs b/MinecraftClient/ChatBots/AutoAttack.cs index 2f03d26c..19d62538 100644 --- a/MinecraftClient/ChatBots/AutoAttack.cs +++ b/MinecraftClient/ChatBots/AutoAttack.cs @@ -6,6 +6,9 @@ using System.Text; namespace MinecraftClient.ChatBots { + /// + /// The AutoAttack bot will automatically attack any hostile mob close to the player + /// class AutoAttack : ChatBot { private Dictionary entitiesToAttack = new Dictionary(); // mobs within attack range @@ -48,7 +51,7 @@ namespace MinecraftClient.ChatBots public override void OnEntitySpawn(Entity entity) { - if (entity.GetMobName() != "") + if (entity.IsHostile()) { entitiesToTrack.Add(entity.ID, entity); } @@ -64,10 +67,9 @@ namespace MinecraftClient.ChatBots { if (entitiesToTrack.ContainsKey(entity.ID)) { - Double distance = Entity.CalculateDistance(GetCurrentLocation(), entity.Location); - if(distance < attackRange) + if (GetCurrentLocation().Distance(entity.Location) < attackRange) { - if(!entitiesToAttack.ContainsKey(entity.ID)) + if (!entitiesToAttack.ContainsKey(entity.ID)) entitiesToAttack.Add(entity.ID, entity); } } diff --git a/MinecraftClient/ChatBots/AutoFishing.cs b/MinecraftClient/ChatBots/AutoFishing.cs index a17bd258..e91d30e2 100644 --- a/MinecraftClient/ChatBots/AutoFishing.cs +++ b/MinecraftClient/ChatBots/AutoFishing.cs @@ -8,6 +8,10 @@ using MinecraftClient.Mapping; namespace MinecraftClient.ChatBots { + /// + /// The AutoFishing bot semi-automates fishing. + /// The player needs to have a fishing rod in hand, then manually send it using the UseItem command. + /// class AutoFishing : ChatBot { private Entity fishingRod; @@ -32,7 +36,7 @@ namespace MinecraftClient.ChatBots { if (entity.TypeID == 102) { - if (Entity.CalculateDistance(GetCurrentLocation(), entity.Location) < 2 && !isFishing) + if (GetCurrentLocation().Distance(entity.Location) < 2 && !isFishing) { ConsoleIO.WriteLine("Threw a fishing rod"); fishingRod = entity; @@ -41,6 +45,7 @@ namespace MinecraftClient.ChatBots } } } + public override void OnEntityDespawn(Entity entity) { if(entity.TypeID == 102) @@ -51,6 +56,7 @@ namespace MinecraftClient.ChatBots } } } + public override void OnEntityMove(Entity entity) { if (isFishing) @@ -107,9 +113,14 @@ namespace MinecraftClient.ChatBots }); } + /// + /// Check whether the player has a fishing rod in inventory + /// + /// TRUE if the player has a fishing rod public bool hasFishingRod() { - if (!inventoryEnabled) return false; + if (!inventoryEnabled) + return false; int start = 36; int end = 44; Inventory.Container container = GetPlayerInventory(); diff --git a/MinecraftClient/Mapping/Entity.cs b/MinecraftClient/Mapping/Entity.cs index 5439d271..f069d885 100644 --- a/MinecraftClient/Mapping/Entity.cs +++ b/MinecraftClient/Mapping/Entity.cs @@ -5,97 +5,117 @@ using System.Text; namespace MinecraftClient.Mapping { + /// + /// Represents an entity evolving into a Minecraft world + /// public class Entity { + /// + /// ID of the entity on the Minecraft server + /// public int ID; - public int TypeID; + + /// + /// Entity type determined by Minecraft Console Client + /// public EntityType Type; - public string Name; + + /// + /// Entity type ID (more precise than Type, but may change between Minecraft versions) + /// + public int TypeID; + + /// + /// Entity location in the Minecraft world + /// public Location Location; + + /// + /// Create a new entity based on Entity ID and location + /// + /// Entity ID + /// Entity location public Entity(int ID, Location location) { this.ID = ID; this.Location = location; } + + /// + /// Create a new entity based on Entity ID, Entity Type and location + /// + /// Entity ID + /// Entity Type ID + /// Entity location public Entity(int ID, int TypeID, Location location) { this.ID = ID; this.TypeID = TypeID; - this.Name = GetMobName(TypeID); this.Location = location; } + + /// + /// Create a new entity based on Entity ID, Entity Type and location + /// + /// Entity ID + /// Entity Type ID + /// Entity Type Enum + /// Entity location public Entity(int ID, int TypeID, EntityType type, Location location) { this.ID = ID; this.TypeID = TypeID; this.Type = type; - this.Name = GetMobName(TypeID); this.Location = location; } + + /// + /// Create a new entity based on Entity ID, Entity Type and location + /// + /// Entity ID + /// Entity Type Enum + /// Entity location public Entity(int ID, EntityType type, Location location) { this.ID = ID; this.Type = type; this.Location = location; } - public Entity(int ID, int TypeID, string Name, Location location) - { - this.ID = ID; - this.TypeID = TypeID; - this.Name = Name; - this.Location = location; - } - /// - /// Calculate the distance between two coordinate + /// Return TRUE if the Entity is an hostile mob /// - /// - /// - /// - public static double CalculateDistance(Location l1, Location l2) + /// New mobs added in newer Minecraft versions might be absent from the list + /// TRUE if hostile + public bool IsHostile() { - return Math.Sqrt(Math.Pow(l2.X - l1.X, 2) + Math.Pow(l2.Y - l1.Y, 2) + Math.Pow(l2.Z - l1.Z, 2)); - } - /// - /// Get the mob name by entity type ID. - /// - /// - /// - public static string GetMobName(int EntityType) - { - // only mobs in this list will be auto attacked - switch (EntityType) + switch (TypeID) { - case 5: return "Blaze"; - case 12: return "Creeper"; - case 16: return "Drowned"; - case 23: return "Evoker"; - case 29: return "Ghast"; - case 31: return "Guardian"; - case 33: return "Husk"; - case 41: return "Magma Cube"; - case 57: return "Zombie Pigman"; - case 63: return "Shulker"; - case 65: return "Silverfish"; - case 66: return "Skeleton"; - case 68: return "Slime"; - case 75: return "Stray"; - case 84: return "Vex"; - case 87: return "Vindicator"; - case 88: return "Pillager"; - case 90: return "Witch"; - case 92: return "Wither Skeleton"; - case 95: return "Zombie"; - case 97: return "Zombie Villager"; - case 98: return "Phantom"; - case 99: return "Ravager"; - default: return ""; + case 5: return true; // Blaze; + case 12: return true; // Creeper + case 16: return true; // Drowned + case 23: return true; // Evoker + case 29: return true; // Ghast + case 31: return true; // Guardian + case 33: return true; // Husk + case 41: return true; // Magma Cube + case 57: return true; // Zombie Pigman + case 63: return true; // Shulker + case 65: return true; // Silverfish + case 66: return true; // Skeleton + case 68: return true; // Slime + case 75: return true; // Stray + case 84: return true; // Vex + case 87: return true; // Vindicator + case 88: return true; // Pillager + case 90: return true; // Witch + case 92: return true; // Wither Skeleton + case 95: return true; // Zombie + case 97: return true; // Zombie Villager + case 98: return true; // Phantom + case 99: return true; // Ravager + default: return false; } } - public string GetMobName() - { - return GetMobName(TypeID); - } } } diff --git a/MinecraftClient/McTcpClient.cs b/MinecraftClient/McTcpClient.cs index 05585454..0047e205 100644 --- a/MinecraftClient/McTcpClient.cs +++ b/MinecraftClient/McTcpClient.cs @@ -565,6 +565,12 @@ namespace MinecraftClient return entityHandlingEnabled; } + /// + /// Enable or disable Entity handling. + /// Please note that Enabling will be deferred until next relog. + /// + /// Enabled + /// TRUE if the setting was applied immediately, FALSE if delayed. public bool SetEntityHandlingEnabled(bool enabled) { if (!enabled) @@ -594,7 +600,6 @@ namespace MinecraftClient { return playerInventory; } - // TODO: add command for displaying player inventory /// /// Called when the server sends a new player location, @@ -791,8 +796,8 @@ namespace MinecraftClient /// /// When received window items from server. /// - /// - /// + /// Inventory type + /// Item list public void OnWindowItems(int type, Dictionary itemList) { // 0 is player inventory @@ -800,15 +805,28 @@ namespace MinecraftClient playerInventory.Items = itemList; } - public void OnSetSlot(byte WindowID, short SlotID, bool Present) + /// + /// When a slot is cleared inside window items + /// + /// Window ID + /// Slot ID + public void OnSlotClear(byte WindowID, short SlotID) { - if(WindowID == 0) + if (WindowID == 0 && playerInventory.Items.ContainsKey(SlotID)) { - if (playerInventory.Items.ContainsKey(SlotID)) - playerInventory.Items.Remove(SlotID); + playerInventory.Items.Remove(SlotID); } } - public void OnSetSlot(byte WindowID, short SlotID, bool Present, int ItemID, byte Count, Dictionary NBT) + + /// + /// When a slot is set inside window items + /// + /// Window ID + /// Slot ID + /// Item ID + /// Item Count + /// Item Metadata + public void OnSetSlot(byte WindowID, short SlotID, int ItemID, byte Count, Dictionary NBT) { if (WindowID == 0) { @@ -912,8 +930,6 @@ namespace MinecraftClient pitch = null; } } - - } /// @@ -1275,12 +1291,16 @@ namespace MinecraftClient /// /// Set client player's ID for later receiving player's own properties /// - /// + /// Player Entity ID public void SetPlayerEntityID(int EntityID) { playerEntityID = EntityID; } + /// + /// Use the item currently in the player's hand + /// + /// TRUE if the item was successfully used public bool UseItemOnHand() { return handler.SendUseItemPacket(0); @@ -1296,13 +1316,24 @@ namespace MinecraftClient { return handler.SendInteractEntityPacket(EntityID, type); } - // not work :( + + /// + /// Place the block at hand in the Minecraft world + /// + /// Location to place block to + /// TRUE if successfully placed public bool PlaceBlock(Location location) { + //WORK IN PROGRESS. MAY NOT WORK YET ConsoleIO.WriteLine(location.ToString()); return handler.SendPlayerBlockPlacement(0, location, 1, 0.5f, 0.5f, 0.5f, false); } + /// + /// Change active slot in the player inventory + /// + /// Slot to activate (0 to 8) + /// public bool ChangeSlot(short slot) { if (slot >= 0 && slot <= 8) diff --git a/MinecraftClient/Protocol/Handlers/Protocol16.cs b/MinecraftClient/Protocol/Handlers/Protocol16.cs index 03ad7561..5c2eb0a4 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol16.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol16.cs @@ -641,30 +641,34 @@ namespace MinecraftClient.Protocol.Handlers return false; //Currently not implemented } - //Currently not implemented public bool SendInteractEntityPacket(int EntityID, int type) { - return false; + return false; //Currently not implemented } + public bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z, int hand) { - return false; + return false; //Currently not implemented } + public bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z) { - return false; + return false; //Currently not implemented } + public bool SendUseItemPacket(int hand) { - return false; + return false; //Currently not implemented } + public bool SendPlayerBlockPlacement(int hand, Location location, int face, float CursorX, float CursorY, float CursorZ, bool insideBlock) { - return false; + return false; //Currently not implemented } + public bool SendHeldItemChange(short slot) { - return false; + return false; //Currently not implemented } /// @@ -672,7 +676,6 @@ namespace MinecraftClient.Protocol.Handlers /// /// Channel to send packet on /// packet Data - public bool SendPluginChannelPacket(string channel, byte[] data) { try { diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index 152910e6..89dbdcdb 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -589,7 +589,7 @@ namespace MinecraftClient.Protocol.Handlers short ItemID = dataTypes.ReadNextShort(packetData); if (ItemID == -1) { - handler.OnSetSlot(WindowID, SlotID, false); + handler.OnSlotClear(WindowID, SlotID); } else { @@ -601,7 +601,7 @@ namespace MinecraftClient.Protocol.Handlers { NBT = dataTypes.ReadNextNbt(packetData); } - handler.OnSetSlot(WindowID, SlotID, true, ItemID, Count, NBT); + handler.OnSetSlot(WindowID, SlotID, ItemID, Count, NBT); } } else @@ -615,11 +615,11 @@ namespace MinecraftClient.Protocol.Handlers int ItemID = dataTypes.ReadNextVarInt(packetData); byte Count = dataTypes.ReadNextByte(packetData); Dictionary NBT = dataTypes.ReadNextNbt(packetData); - handler.OnSetSlot(WindowID, SlotID, Present, ItemID, Count, NBT); + handler.OnSetSlot(WindowID, SlotID, ItemID, Count, NBT); } else { - handler.OnSetSlot(WindowID, SlotID, Present); + handler.OnSlotClear(WindowID, SlotID); } } } diff --git a/MinecraftClient/Protocol/IMinecraftCom.cs b/MinecraftClient/Protocol/IMinecraftCom.cs index afded88e..60aa7a33 100644 --- a/MinecraftClient/Protocol/IMinecraftCom.cs +++ b/MinecraftClient/Protocol/IMinecraftCom.cs @@ -85,14 +85,62 @@ namespace MinecraftClient.Protocol /// True if message was successfully sent bool SendPluginChannelPacket(string channel, byte[] data); + /// + /// Send a held item change packet to the server. + /// + /// New active slot in the inventory hotbar + /// True if packet was successfully sent bool SendHeldItemChange(short slot); + /// + /// Send an entity interaction packet to the server. + /// + /// Entity ID to interact with + /// Type of interaction (0: interact, 1: attack, 2: interact at) + /// True if packet was successfully sent bool SendInteractEntityPacket(int EntityID, int type); + + /// + /// Send an entity interaction packet to the server. + /// + /// Entity ID to interact with + /// Type of interaction (0: interact, 1: attack, 2: interact at) + /// X coordinate for "interact at" + /// Y coordinate for "interact at" + /// Z coordinate for "interact at" + /// Player hand (0: main hand, 1: off hand) + /// True if packet was successfully sent bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z, int hand); + + /// + /// Send an entity interaction packet to the server. + /// + /// Entity ID to interact with + /// Type of interaction (0: interact, 1: attack, 2: interact at) + /// X coordinate for "interact at" + /// Y coordinate for "interact at" + /// Z coordinate for "interact at" + /// True if packet was successfully sent bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z); + /// + /// Send a use item packet to the server + /// + /// 0: main hand, 1: off hand + /// True if packet was successfully sent bool SendUseItemPacket(int hand); + /// + /// Send player block placement packet to the server + /// + /// 0: main hand, 1: off hand + /// Location to place block at + /// Block face + /// Cursor X + /// Cursor Y + /// Cursor Z + /// TRUE if inside block + /// True if packet was successfully sent bool SendPlayerBlockPlacement(int hand, Location location, int face, float CursorX, float CursorY, float CursorZ, bool insideBlock); } } diff --git a/MinecraftClient/Protocol/IMinecraftComHandler.cs b/MinecraftClient/Protocol/IMinecraftComHandler.cs index 0c060076..2771a664 100644 --- a/MinecraftClient/Protocol/IMinecraftComHandler.cs +++ b/MinecraftClient/Protocol/IMinecraftComHandler.cs @@ -128,27 +128,102 @@ namespace MinecraftClient.Protocol /// The data from the channel void OnPluginChannelMessage(string channel, byte[] data); + /// + /// Called when a non-living entity has spawned + /// + /// Entity ID + /// Entity Type ID + /// Entity UUID + /// Entity location void OnSpawnEntity(int EntityID, int EntityType, Guid UUID, Location location); + /// + /// Called when a living entity has spawned + /// + /// Entity ID + /// Entity Type ID + /// Entity UUID + /// Entity location void OnSpawnLivingEntity(int EntityID, int EntityType, Guid UUID, Location location); + /// + /// Called when a player has spawned + /// + /// Entity ID + /// Entity UUID + /// Entity location + /// Player head yaw + /// Player head pitch void OnSpawnPlayer(int EntityID, Guid UUID, Location location, byte Yaw, byte Pitch); + /// + /// Called when entities have despawned + /// + /// List of Entity ID that have despawned void OnDestroyEntities(int[] EntityID); + /// + /// Called when an entity moved by coordinate offset + /// + /// Entity ID + /// X offset + /// Y offset + /// Z offset + /// TRUE if on ground void OnEntityPosition(int EntityID, Double Dx, Double Dy, Double Dz,bool onGround); - void OnEntityProperties(int EntityID, Dictionary prop); - - void OnTimeUpdate(long WorldAge, long TimeOfDay); - + /// + /// Called when an entity moved to fixed coordinates + /// + /// Entity ID + /// X + /// Y + /// Z + /// TRUE if on ground void OnEntityTeleport(int EntityID, Double X, Double Y, Double Z, bool onGround); + /// + /// Called when additional properties have been received for an entity + /// + /// Entity ID + /// Dictionary of properties + void OnEntityProperties(int EntityID, Dictionary prop); + + /// + /// Called when the world age has been updated + /// + /// World age + /// Time of Day + void OnTimeUpdate(long WorldAge, long TimeOfDay); + + /// + /// Called when inventory items have been received + /// + /// Inventory type + /// Item list void OnWindowItems(int type, Dictionary itemList); - void OnSetSlot(byte WindowID, short SlotID, bool Present); - void OnSetSlot(byte WindowID, short SlotID, bool Present, int ItemID, byte Count, Dictionary NBT); + /// + /// Called when a single slot has been cleared inside an inventory + /// + /// Inventory ID + /// Slot ID + void OnSlotClear(byte WindowID, short SlotID); + /// + /// Called when a single slot has been updated inside an inventory + /// + /// Inventory ID + /// Slot ID + /// Item ID + /// Item Count + /// Item Metadata + void OnSetSlot(byte WindowID, short SlotID, int ItemID, byte Count, Dictionary NBT); + + /// + /// Called when the Player entity ID has been received from the server + /// + /// Player entity ID void SetPlayerEntityID(int EntityID); } } diff --git a/MinecraftClient/config/README.md b/MinecraftClient/config/README.md index 88d00c8b..c0371f67 100644 --- a/MinecraftClient/config/README.md +++ b/MinecraftClient/config/README.md @@ -261,7 +261,7 @@ Also, remember that when you connect to a server with this program, you will app This means that **you can die if you log in in an unsafe place on a survival server!** Use the script scheduler bot to send a teleport command after logging in. -You have been reminded that **you may get banned** by your server for using this program. Use accordinly with server rules. +We remind you that **you may get banned** by your server for using this program. Use accordingly with server rules. License ------ diff --git a/README.md b/README.md index 9e54ccde..34f2b17c 100644 --- a/README.md +++ b/README.md @@ -32,15 +32,15 @@ Edit `MinecraftClient.csproj` to set the Build target to `Release` on [line 4](h ### On Windows -1. Locate MSBuild.exe for .NET 4 inside `C:\Windows\Microsoft.NET\Framework\v4.X.XXXXX` +1. Locate `MSBuild.exe` for .NET 4 inside `C:\Windows\Microsoft.NET\Framework\v4.X.XXXXX` 2. Drag and drop `MinecraftClient.csproj` over `MSBuild.exe` to launch the build -3. If the build succeededs, you can find `MinecraftClient.exe` under `MinecraftClient\bin\Release` +3. If the build succeeds, you can find `MinecraftClient.exe` under `MinecraftClient\bin\Release` ### On Mac and Linux 1. Install the [Mono Framework](https://www.mono-project.com/download/stable/#download-lin) if not already installed 2. Run `msbuild MinecraftClient.csproj` in a terminal -3. If the build succeededs, you can find `MinecraftClient.exe` under `MinecraftClient\bin\Release` +3. If the build succeeds, you can find `MinecraftClient.exe` under `MinecraftClient\bin\Release` ## How to contribute