diff --git a/MinecraftClient/ChatBot.cs b/MinecraftClient/ChatBot.cs index b00e64ec..0fafcb6b 100644 --- a/MinecraftClient/ChatBot.cs +++ b/MinecraftClient/ChatBot.cs @@ -745,14 +745,12 @@ namespace MinecraftClient } /// - /// Dig block + /// Attempt to dig a block at the specified location /// - /// 0 to start digging, 1 to cancel, 2 to finish ( https://wiki.vg/Protocol#Player_Digging ) /// Location - /// Block face - protected void DigBlock(int status, Location location, Direction blockFace) + protected bool DigBlock(Location location) { - Handler.DigBlock(status, location, blockFace); + return Handler.DigBlock(location); } /// @@ -977,9 +975,9 @@ namespace MinecraftClient /// Item type /// Item count /// TRUE if item given successfully - protected bool CreativeGive(int slot, ItemType itemType, int count, Dictionary NBT = null) + protected bool CreativeGive(int slot, ItemType itemType, int count, Dictionary nbt = null) { - return Handler.DoCreativeGive(slot, itemType, count, NBT); + return Handler.DoCreativeGive(slot, itemType, count, nbt); } /// diff --git a/MinecraftClient/Commands/ChangeSlot.cs b/MinecraftClient/Commands/ChangeSlot.cs index e012bbd7..a9f0061e 100644 --- a/MinecraftClient/Commands/ChangeSlot.cs +++ b/MinecraftClient/Commands/ChangeSlot.cs @@ -12,7 +12,9 @@ namespace MinecraftClient.Commands public override string Run(McClient handler, string command, Dictionary localVars) { - if (!handler.GetInventoryEnabled()) return "Please enable InventoryHandling in the config file first."; + if (!handler.GetTerrainEnabled()) + return "Please enable InventoryHandling in the config file first."; + if (hasArg(command)) { short slot; diff --git a/MinecraftClient/Commands/Dig.cs b/MinecraftClient/Commands/Dig.cs new file mode 100644 index 00000000..d3dfc7f4 --- /dev/null +++ b/MinecraftClient/Commands/Dig.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MinecraftClient.Mapping; + +namespace MinecraftClient.Commands +{ + public class Dig : Command + { + public override string CMDName { get { return "dig"; } } + public override string CMDDesc { get { return "dig : attempt to break a block"; } } + + public override string Run(McClient handler, string command, Dictionary localVars) + { + if (!handler.GetTerrainEnabled()) + return "Please enable Terrain and Movements to use this command."; + + if (hasArg(command)) + { + string[] args = getArgs(command); + if (args.Length == 3) + { + try + { + int x = int.Parse(args[0]); + int y = int.Parse(args[1]); + int z = int.Parse(args[2]); + Location blockToBreak = new Location(x, y, z); + if (blockToBreak.DistanceSquared(handler.GetCurrentLocation()) >= 16) + return "You are too far away from this block."; + if (handler.GetWorld().GetBlock(blockToBreak).Type == Material.Air) + return "No block at this location (Air)"; + if (handler.DigBlock(blockToBreak)) + return String.Format("Attempting to dig block at {0} {1} {2}", x, y, z); + else return "Failed to start digging block."; + } + catch (FormatException) { return CMDDesc; } + } + else return CMDDesc; + } + else return CMDDesc; + } + } +} diff --git a/MinecraftClient/Inventory/Item.cs b/MinecraftClient/Inventory/Item.cs index 0aefaadb..29198e88 100644 --- a/MinecraftClient/Inventory/Item.cs +++ b/MinecraftClient/Inventory/Item.cs @@ -30,7 +30,7 @@ namespace MinecraftClient.Inventory /// /// Item Type ID /// Item Count - /// Item Metadata + /// Item Metadata public Item(int id, int count, Dictionary nbt) { this.Type = (ItemType)id; diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index bee01020..7ca3c7d6 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -953,11 +953,11 @@ namespace MinecraftClient /// Destination inventory slot /// Item type /// Item count - /// Item NBT + /// Item NBT /// TRUE if item given successfully - public bool DoCreativeGive(int slot, ItemType itemType, int count, Dictionary NBT = null) + public bool DoCreativeGive(int slot, ItemType itemType, int count, Dictionary nbt = null) { - return handler.SendCreativeInventoryAction(slot, itemType, count, NBT); + return handler.SendCreativeInventoryAction(slot, itemType, count, nbt); } /// @@ -1023,14 +1023,25 @@ namespace MinecraftClient } /// - /// Dig block. This method needs to be called at least twice: Once to begin digging, then a second time to finish digging + /// Attempt to dig a block at the specified location /// - /// 0 to start digging, 1 to cancel, 2 to finish ( https://wiki.vg/Protocol#Player_Digging ) /// Location of block to dig - /// Block face (e.g. Direction.Up when digging from above) - public bool DigBlock(int status, Location location, Direction blockFace) + public bool DigBlock(Location location) { - return handler.SendPlayerDigging(status, location, blockFace); + if (GetTerrainEnabled()) + { + // TODO select best face from current player location + Direction blockFace = Direction.Down; + + // Look at block before attempting to break it + UpdateLocation(GetCurrentLocation(), location); + + // Send dig start and dig end, will need to wait for server response to know dig result + // See https://wiki.vg/How_to_Write_a_Client#Digging for more details + return handler.SendPlayerDigging(0, location, blockFace) + && handler.SendPlayerDigging(2, location, blockFace); + } + else return false; } /// @@ -1045,25 +1056,21 @@ namespace MinecraftClient CurrentSlot = Convert.ToByte(slot); return handler.SendHeldItemChange(slot); } - else - { - return false; - } + else return false; } /// /// Update sign text /// - /// sign location - /// text one - /// text two - /// text three - /// text1 four + /// sign location + /// text one + /// text two + /// text three + /// text1 four public bool UpdateSign(Location location, string line1, string line2, string line3, string line4) { - if (line1.Length <= 23 & line2.Length <= 23 & line3.Length <= 23 & line4.Length <= 23) - return handler.SendUpdateSign(location, line1, line2, line3, line4); - else { return false; } + // TODO Open sign editor first https://wiki.vg/Protocol#Open_Sign_Editor + return handler.SendUpdateSign(location, line1, line2, line3, line4); } #endregion diff --git a/MinecraftClient/MinecraftClient.csproj b/MinecraftClient/MinecraftClient.csproj index 7d0ef066..9d89fbef 100644 --- a/MinecraftClient/MinecraftClient.csproj +++ b/MinecraftClient/MinecraftClient.csproj @@ -93,6 +93,7 @@ + diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs index b2ef0c6c..f46537c6 100644 --- a/MinecraftClient/Program.cs +++ b/MinecraftClient/Program.cs @@ -27,7 +27,7 @@ namespace MinecraftClient /// static class Program { - private static McClient Client; + private static McClient client; public static string[] startupargs; public const string Version = MCHighestVersion; @@ -264,9 +264,9 @@ namespace MinecraftClient //Start the main TCP client if (Settings.SingleCommand != "") { - Client = new McClient(session.PlayerName, session.PlayerID, session.ID, Settings.ServerIP, Settings.ServerPort, protocolversion, forgeInfo, Settings.SingleCommand); + client = new McClient(session.PlayerName, session.PlayerID, session.ID, Settings.ServerIP, Settings.ServerPort, protocolversion, forgeInfo, Settings.SingleCommand); } - else Client = new McClient(session.PlayerName, session.PlayerID, session.ID, protocolversion, forgeInfo, Settings.ServerIP, Settings.ServerPort); + else client = new McClient(session.PlayerName, session.PlayerID, session.ID, protocolversion, forgeInfo, Settings.ServerIP, Settings.ServerPort); //Update console title if (Settings.ConsoleTitle != "") @@ -309,7 +309,7 @@ namespace MinecraftClient { new Thread(new ThreadStart(delegate { - if (Client != null) { Client.Disconnect(); ConsoleIO.Reset(); } + if (client != null) { client.Disconnect(); ConsoleIO.Reset(); } if (offlinePrompt != null) { offlinePrompt.Abort(); offlinePrompt = null; ConsoleIO.Reset(); } if (delaySeconds > 0) { @@ -328,7 +328,7 @@ namespace MinecraftClient { new Thread(new ThreadStart(delegate { - if (Client != null) { Client.Disconnect(); ConsoleIO.Reset(); } + if (client != null) { client.Disconnect(); ConsoleIO.Reset(); } if (offlinePrompt != null) { offlinePrompt.Abort(); offlinePrompt = null; ConsoleIO.Reset(); } if (Settings.playerHeadAsIcon) { ConsoleIcon.revertToMCCIcon(); } Environment.Exit(0); diff --git a/MinecraftClient/Protocol/Handlers/DataTypes.cs b/MinecraftClient/Protocol/Handlers/DataTypes.cs index a33c5545..5a077073 100644 --- a/MinecraftClient/Protocol/Handlers/DataTypes.cs +++ b/MinecraftClient/Protocol/Handlers/DataTypes.cs @@ -336,8 +336,8 @@ namespace MinecraftClient.Protocol.Handlers { int itemID = ReadNextVarInt(cache); byte itemCount = ReadNextByte(cache); - Dictionary NBT = ReadNextNbt(cache); - return new Item(itemID, itemCount, NBT); + Dictionary nbt = ReadNextNbt(cache); + return new Item(itemID, itemCount, nbt); } else return null; } @@ -349,8 +349,8 @@ namespace MinecraftClient.Protocol.Handlers return null; byte itemCount = ReadNextByte(cache); short itemDamage = ReadNextShort(cache); - Dictionary NBT = ReadNextNbt(cache); - return new Item(itemID, itemCount, NBT); + Dictionary nbt = ReadNextNbt(cache); + return new Item(itemID, itemCount, nbt); } } @@ -398,14 +398,14 @@ namespace MinecraftClient.Protocol.Handlers /// private Dictionary ReadNextNbt(Queue cache, bool root) { - Dictionary NbtData = new Dictionary(); + Dictionary nbtData = new Dictionary(); if (root) { if (cache.Peek() == 0) // TAG_End { cache.Dequeue(); - return NbtData; + return nbtData; } if (cache.Peek() != 10) // TAG_Compound throw new System.IO.InvalidDataException("Failed to decode NBT: Does not start with TAG_Compound"); @@ -414,7 +414,7 @@ namespace MinecraftClient.Protocol.Handlers // NBT root name string rootName = Encoding.ASCII.GetString(ReadData(ReadNextUShort(cache), cache)); if (!String.IsNullOrEmpty(rootName)) - NbtData[""] = rootName; + nbtData[""] = rootName; } while (true) @@ -422,14 +422,14 @@ namespace MinecraftClient.Protocol.Handlers int fieldType = ReadNextByte(cache); if (fieldType == 0) // TAG_End - return NbtData; + return nbtData; int fieldNameLength = ReadNextUShort(cache); string fieldName = Encoding.ASCII.GetString(ReadData(fieldNameLength, cache)); object fieldValue = ReadNbtField(cache, fieldType); // This will override previous tags with the same name - NbtData[fieldName] = fieldValue; + nbtData[fieldName] = fieldValue; } } diff --git a/MinecraftClient/Protocol/Handlers/Protocol16.cs b/MinecraftClient/Protocol/Handlers/Protocol16.cs index 9c14ffec..c6fe04d5 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol16.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol16.cs @@ -703,7 +703,7 @@ namespace MinecraftClient.Protocol.Handlers return false; //Currently not implemented } - public bool SendCreativeInventoryAction(int slot, ItemType item, int count, Dictionary NBT) + public bool SendCreativeInventoryAction(int slot, ItemType item, int count, Dictionary nbt) { return false; //Currently not implemented } diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index 7e35711a..9e0dafb3 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -1500,13 +1500,13 @@ namespace MinecraftClient.Protocol.Handlers catch (ObjectDisposedException) { return false; } } - public bool SendCreativeInventoryAction(int slot, ItemType itemType, int count, Dictionary NBT) + public bool SendCreativeInventoryAction(int slot, ItemType itemType, int count, Dictionary nbt) { try { List packet = new List(); packet.AddRange(dataTypes.GetShort((short)slot)); - packet.AddRange(dataTypes.GetItemSlot(new Item((int)itemType, count, NBT))); + packet.AddRange(dataTypes.GetItemSlot(new Item((int)itemType, count, nbt))); SendPacket(PacketOutgoingType.CreativeInventoryAction, packet); return true; } @@ -1549,6 +1549,7 @@ namespace MinecraftClient.Protocol.Handlers catch (System.IO.IOException) { return false; } catch (ObjectDisposedException) { return false; } } + public bool SendCloseWindow(int windowId) { try @@ -1565,10 +1566,20 @@ namespace MinecraftClient.Protocol.Handlers catch (System.IO.IOException) { return false; } catch (ObjectDisposedException) { return false; } } + public bool SendUpdateSign(Location sign, string line1, string line2, string line3, string line4) { try { + if (line1.Length > 23) + line1 = line1.Substring(0, 23); + if (line2.Length > 23) + line2 = line1.Substring(0, 23); + if (line3.Length > 23) + line3 = line1.Substring(0, 23); + if (line4.Length > 23) + line4 = line1.Substring(0, 23); + List packet = new List(); packet.AddRange(dataTypes.GetLocation(sign)); packet.AddRange(dataTypes.GetString(line1)); diff --git a/MinecraftClient/Protocol/IMinecraftCom.cs b/MinecraftClient/Protocol/IMinecraftCom.cs index b190384f..546b0dc5 100644 --- a/MinecraftClient/Protocol/IMinecraftCom.cs +++ b/MinecraftClient/Protocol/IMinecraftCom.cs @@ -156,8 +156,9 @@ namespace MinecraftClient.Protocol /// Destination inventory slot /// Item type /// Item count + /// Optional item NBT /// TRUE if item given successfully - bool SendCreativeInventoryAction(int slot, ItemType itemType, int count, Dictionary NBT); + bool SendCreativeInventoryAction(int slot, ItemType itemType, int count, Dictionary nbt); /// /// Plays animation @@ -183,7 +184,7 @@ namespace MinecraftClient.Protocol bool SendPlayerBlockPlacement(int hand, Location location, Direction face); /// - /// Send player blog digging packet to the server + /// Send player blog digging packet to the server. This packet needs to be called at least twice: Once to begin digging, then a second time to finish digging /// /// 0 to start digging, 1 to cancel, 2 to finish ( https://wiki.vg/Protocol#Player_Digging ) /// Location