//MCCScript 1.0 //using MinecraftClient.Inventory; //using MinecraftClient.Mapping; //using MinecraftClient.Scripting; //using System.Collections.Generic; //using System.Threading; //using System; //using Brigadier.NET.Builder; //using MinecraftClient.CommandHandler.Patch; //using Brigadier.NET; //using MinecraftClient.CommandHandler; //using System.Linq; MCC.LoadBot(new SugarCaneFarmer()); //MCCScript Extensions class SugarCaneFarmerBase : ChatBot { /// /// MoveToLocation() + waiting until the bot is near the location. /// /// Location to walk to /// Distance of blocks from the goal that is accepted as "arrived" /// True if walking was successful public bool WaitForMoveToLocation(Location pos, float tolerance = 2f) { if (MoveToLocation(new Location(pos.X, pos.Y, pos.Z))) { while (GetCurrentLocation().Distance(pos) > tolerance) { Thread.Sleep(200); } return true; } else { return false; } } /// /// DigBlock + waiting until the block is broken /// /// Location of the block that should be broken /// Switch to the correct tool, if it is in hotbar /// Minimum time until the client gives up /// True if mining was successful public bool WaitForDigBlock(Location block, bool useCorrectTool = false, int digTimeout = 1000) { if (Material2Tool.IsUnbreakable(GetWorld().GetBlock(block).Type)) return false; if (useCorrectTool && GetInventoryEnabled()) { // Search this tool in hotbar and select the correct slot SelectCorrectSlotInHotbar( // Returns the correct tool for this type Material2Tool.GetCorrectToolForBlock( // returns the type of the current block GetWorld().GetBlock(block).Type)); } // Unable to check when breaking is over. if (DigBlock(block)) { short i = 0; // Maximum wait time of 10 sec. while (GetWorld().GetBlock(block).Type != Material.Air && i <= digTimeout) { Thread.Sleep(100); i++; } return i <= digTimeout; } else { return false; } } /// /// Selects the corect tool in the hotbar /// /// List of tools that can be applied to mine a block public void SelectCorrectSlotInHotbar(ItemType[] tools) { if (GetInventoryEnabled()) { foreach (ItemType tool in tools) { int[] tempArray = GetPlayerInventory().SearchItem(tool); // Check whether an item could be found and make sure that it is in // a hotbar slot (36-44). if (tempArray.Length > 0 && tempArray[0] > 35) { // Changeslot takes numbers from 0-8 ChangeSlot(Convert.ToInt16(tempArray[0] - 36)); break; } } } else { LogToConsole("Activate Inventory Handling."); } } /// /// Returns the head position from the current location /// public static Func GetHeadLocation = locFeet => new Location(locFeet.X, locFeet.Y + 1, locFeet.Z); } class SugarCaneFarmer : SugarCaneFarmerBase { public const string CommandName = "sugarcane"; public enum CoordinateType { X, Y, Z }; /// /// Used to stop the farming process on demand. /// private bool farming = true; /// /// Returns all sugar canes that are above a solid block and another sugar cane /// /// Radius of the search /// Order of the returned sugar canes /// list of sugar canes, sorted after given parameter private List collectSugarCaneBlocks(int radius, CoordinateType coordinateOrder = CoordinateType.X) { IEnumerable breakingCoordinates = GetWorld().FindBlock( new Location(Math.Floor(GetCurrentLocation().X), Math.Floor(GetCurrentLocation().Y), Math.Floor(GetCurrentLocation().Z)), Material.SugarCane, radius).Where(block => GetWorld().GetBlock(new Location(block.X, block.Y - 1, block.Z)).Type == Material.SugarCane && GetWorld().GetBlock(new Location(block.X, block.Y - 2, block.Z)).Type.IsSolid()); switch (coordinateOrder) { case CoordinateType.Z: return breakingCoordinates.OrderBy(coordinate => coordinate.Z).ToList(); case CoordinateType.Y: return breakingCoordinates.OrderBy(coordinate => coordinate.Y).ToList(); default: return breakingCoordinates.OrderBy(coordinate => coordinate.X).ToList(); } } public override void Initialize() { LogToConsole("Sugar Cane farming bot created by Daenges."); Handler.dispatcher.Register(l => l.Literal(CommandName) .Then(l => l.Argument("Commands", Arguments.GreedyString()) .Executes(r => { CommandHandler(Arguments.GetString(r, "Commands").Split(' ', StringSplitOptions.TrimEntries)); return r.Source.SetAndReturn(CmdResult.Status.Done); })) ); } public override void OnUnload() { Handler.dispatcher.Unregister(CommandName); } /// /// Start the farming process /// /// Range of farming /// In which order the plants should be farmed private void startBot(int range, CoordinateType sortOrder) { List sugarCanePositions; // create a loop so the bot keeps farming if nothing else is stated // uses the same range as initially given do { sugarCanePositions = collectSugarCaneBlocks(range, sortOrder); LogToConsole(string.Format("Found: {0} Sugar Cane", sugarCanePositions.Count)); if (sugarCanePositions.Count > 0) { foreach (Location loc in sugarCanePositions) { if (!farming) break; if (GetHeadLocation(GetCurrentLocation()).Distance(loc) > 5) { if (!WaitForMoveToLocation(new Location(loc.X, loc.Y - 1, loc.Z))) { LogToConsole("Moving failed."); continue; } } if (!WaitForDigBlock(new Location(loc.X, loc.Y, loc.Z))) LogDebugToConsole("Unable to break this block: " + loc.ToString()); } } else { LogToConsole("Nothing found. Stop farming..."); } if (farming && sugarCanePositions.Count > 0) LogToConsole("Finished farming. Searching for further work... Use '/sugarcane stop' to stop farming."); } while (farming && sugarCanePositions.Count > 0); farming = true; LogToConsole("[FARMING STOPPED]"); } private string CommandHandler(string[] args) { if (args.Length == 1) { if (args[0] == "stop") { farming = false; return "Stop farming..."; } else { int range; try { range = Convert.ToInt32(args[0]); } catch (Exception) { return "Range must be a number"; } Thread workThread = new Thread(() => startBot(range, CoordinateType.X)); workThread.Start(); return "Start farming."; } } else if (args.Length == 2) { int range; try { range = Convert.ToInt32(args[0]); } catch (Exception) { return "Range must be a number"; } Thread workThread; if (args[1].ToLower() == "x") workThread = new Thread(() => startBot(range, CoordinateType.X)); else if (args[1].ToLower() == "y") workThread = new Thread(() => startBot(range, CoordinateType.Y)); else workThread = new Thread(() => startBot(range, CoordinateType.Z)); workThread.Start(); return "Start farming."; } else return "Usage: /sugarcane [range x|y|z]/[stop]"; } }