diff --git a/.gitignore b/.gitignore index d7b8f483..7dc3aaa6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ # User-specific stuff .idea/ .vs/ -baritone/ *.iml *.ipr diff --git a/README.md b/README.md index 4e31c23a..0c3a4ff5 100644 --- a/README.md +++ b/README.md @@ -1,73 +1,43 @@ -# altoclef +# AltoClef +*Plays block game.* -Plays block game. +*Powered by Baritone.* -Powered by Baritone. +A client side bot that tries to beat Minecraft on its own... -A client side bot that can accomplish any Minecraft task that is relatively simple and can be split into smaller -tasks. "Relatively Simple" is a vague term, so check the list of current capabilities to see examples. +**This fork is still under development and is nowhere near perfect, if you have any questions, suggestions, ideas or find a bug don't hesitate to reach out! +You can use the [issues](https://github.com/MiranCZ/altoclef/issues). Or contact me on discord!** Became [the first bot to beat Minecraft fully autonomously](https://youtu.be/baAa6s8tahA) on May 24, 2021. **Join the [Discord Server](https://discord.gg/JdFP4Kqdqc)** for discussions/updates/goofs & gaffs +## About this fork +This fork aims to optimize `BeatMinecraftTask` by trying to fix a lot of cases where the bot gets stuck and improving some of the tasks. + +You can look at the [changelog](changelog.md) if you are interested. + +Because I rewrote a good portion of the `BeatMinecraftTask` a lot of the config settings don't work. Although I plan to implement configs in the future of course. + ## How it works -Take a look at this [Guide from the wiki](https://github.com/gaucho-matrero/altoclef/wiki/1:-Documentation:-Big-Picture) +Take a look at this [Guide from the wiki](https://github.com/MiranCZ/altoclef/wiki/1:-Documentation:-Big-Picture) or this [Video explanation](https://youtu.be/q5OmcinQ2ck?t=387) -## Current capabilities, Examples: - -- Obtain 400+ Items from a fresh survival world, like diamond armor, cake, and nether brick stairs -- Dodge mob projectiles and force field mobs away while accomplishing arbitrary tasks -- Collect + smelt food from animals, hay, & crops -- Receive commands from chat whispers via /msg. Whitelist + Blacklist configurable (hereby dubbed the Butler System). - Here's - a [Butler system demo video](https://drive.google.com/file/d/1axVYYMJ5VjmVHaWlCifFHTwiXlFssOUc/view?usp=sharing) -- Simple config file that can be reloaded via command (check .minecraft directory) -- Beat the entire game on its own (no user input.) -- Print the entire bee movie script with signs in a straight line, automatically collecting signs + bridging materials - along the way. -- Become the terminator: Run away from players while unarmed, gather diamond gear in secret, then return and wreak - havoc. ## Download **Note:** After installing, please move/delete your old baritone configurations if you have any. Preexisting baritone configurations will interfere with altoclef and introduce bugs. This will be fixed in the future. -### Nightly Release (Recommended) (has the latest bug fixes) - -Start by downloading [the Latest Long Term Release](https://github.com/gaucho-matrero/altoclef/releases), -then [Download the Nightly](https://nightly.link/gaucho-matrero/altoclef/workflows/gradle/main/Artifacts.zip) & -replace `altoclef-4.0-SNAPSHOT.jar`. - -If the Nightly Link doesn't work, check the latest [Build Action](https://github.com/gaucho-matrero/altoclef/actions) -that succeeded and download `Artifacts.zip` (you must be signed into GitHub). Replace your -existing `altoclef-4.0-SNAPSHOT.jar` with the one found in `Artifacts.zip` - -### Long Term Release - -[Check releases](https://github.com/gaucho-matrero/altoclef/releases). Note you will need to copy over both jar files -for the mod to work. - -### Meloweh's Extra Features Release (Unofficial) - -Has some schematic support, command macros and a few utility features. Will eventually be merged, but if you can try it -out now if you'd like: - -- [AltoClef jar](https://github.com/Meloweh/altoclef/releases) -- [Baritone jar](https://github.com/Meloweh/baritone/releases) +[Check releases](https://github.com/MiranCZ/altoclef/releases) ### Versions -This is a **fabric only** mod, currently only available for **Minecraft 1.19.2-1.19.4**. - -For older MC versions, try [multiconnect](https://www.curseforge.com/minecraft/mc-mods/multiconnect) (NOTE: multiconnect -is untested and not affiliated with altoclef, use at your own risk!) +This is a **fabric only** mod, currently only available only for **Minecraft 1.20.2**. ## [Usage Guide](usage.md) -## [TODO's/Future Features](todos.md) +## [TODO's/Future Features](TODO.md) ## [Development Guide](develop.md) diff --git a/TODO.md b/TODO.md new file mode 100644 index 00000000..17dcc85d --- /dev/null +++ b/TODO.md @@ -0,0 +1,14 @@ +# TODO + +### Misc +- Implement configs. +- Allow any bed color when crafting beds from wool. +- Add cherry blossom wood as a valid wood type or something? It doesn't seem to work properly atm. +- Maybe add some sort of system that finds and uses seed of the current world? + + +### Common death causes +- Improve escaping from lava. +- Do not hit pigmen in the nether (or implement a special behaviour when do). +- Prevent from looking endermen in the eyes. +- Maybe avoid bastions somehow? diff --git a/changelog.md b/changelog.md new file mode 100644 index 00000000..2dca28b6 --- /dev/null +++ b/changelog.md @@ -0,0 +1,60 @@ +# Change Log +*(this list may not contain all the changes, but I tried to list most of them)* + +### Misc +- Fixed set gamma not working +- Blacklist wool in ancient cities +- Removed wandering and looking through chunks when looking for stronghold causing massive lag spikes +- Removed render distance manipulation +- Improved and fixed a lot of cases, where the bot gets stuck in an infinite loop/dies +- Removed usage of twisting vines +- Improved one cycle + +### Removed usage of blast furnace +The bot currently gets **11** iron, (**6** for two buckets, **3** for pickaxe, **1** for shield, **1** for flint and steel) and **5** gold for golden helmet. + +Blast furnace makes your smelting twice as fast, but it comes at a cost of crafting it. + +To craft a blast furnace you need **5** iron and **3** smooth stone (done by smelting **3** normal stone). + +So you need to smelt **11** items to craft a blast furnace (**5** iron, **3** cobblestone to make stone and **3** stone to make smooth stone). + +Without a blast furnace you just need to smelt **11** items, with a blast furnace you need to smelt **11** items for even making it and additional **5.5** items for tools (**11** items two times faster). + +**So it is currently not worth making a blast furnace even when we don't consider additional resources we use such as coal etc.** + +### Rewrote most of `BeatMinecraftTask` + +I changed the way tasks are selected to be more dynamic. + +Each task gets some priority and is executed according to it, +if you want to understand this more in depth you can look at the [wiki](https://github.com/MiranCZ/altoclef/wiki/2:-Documentation:-The-task-priority-system). + +### Useless items +The bot has a long handwritten list (hopefully a config in the future as well) of useless items that it throws out as soon as it picks them up. + +### Chest looting +It now loots almost any chest, not a just ones from ruined portals and dessert temples. + +### Rewrote BlockTracker +The new block tracker now keeps track of all blocks in loaded chunks instead of only scanning the ones the bot needs atm. + +I plan on adding a config for this (amongst other things in the future, but its currently hardcoded). + +It is not super optimized and I might edit it in the future. + + +### Iron pickaxe saving +Sometimes the bot would break its iron pickaxe before getting a diamond one. This caused it to mine additional 3 iron and craft another iron pickaxe. + +Instead, I made it so that the bot doesn't use the iron pickaxe, when it doesn't need to once it gets to a low durability. + +### Improved status overlay +The new status overlay is a bit smaller and has some color coding. + +It also includes name of the class that is executing the tasks as well as the current task chain and its priority. + +**OLD:** +![old_overlay.png]() +**NEW:** +![new_overlay.png]() diff --git a/gradle.properties b/gradle.properties index 1521f087..c750e5f2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,4 +17,4 @@ maven_group=gaucho-matrero.altoclef archives_base_name=altoclef # Dependencies # check this on https://modmuss50.me/fabric.html -fabric_version=0.91.2+1.20.2 +fabric_version=0.91.6+1.20.2 diff --git a/src/main/java/adris/altoclef/AltoClef.java b/src/main/java/adris/altoclef/AltoClef.java index 21c49757..27d7d8a8 100644 --- a/src/main/java/adris/altoclef/AltoClef.java +++ b/src/main/java/adris/altoclef/AltoClef.java @@ -1,7 +1,8 @@ package adris.altoclef; -import adris.altoclef.butler.Butler; + import adris.altoclef.chains.*; +import adris.altoclef.commands.BlockScanner; import adris.altoclef.commandsystem.CommandExecutor; import adris.altoclef.control.InputControls; import adris.altoclef.control.PlayerExtraController; @@ -35,10 +36,7 @@ import net.minecraft.item.Items; import org.lwjgl.glfw.GLFW; -import java.util.ArrayDeque; -import java.util.Arrays; -import java.util.List; -import java.util.Queue; +import java.util.*; import java.util.function.Consumer; /** @@ -50,33 +48,35 @@ public class AltoClef implements ModInitializer { private static final Queue> _postInitQueue = new ArrayDeque<>(); // Central Managers - private static CommandExecutor _commandExecutor; - private TaskRunner _taskRunner; - private TrackerManager _trackerManager; - private BotBehaviour _botBehaviour; - private PlayerExtraController _extraController; + private static CommandExecutor commandExecutor; + private TaskRunner taskRunner; + private TrackerManager trackerManager; + private BotBehaviour botBehaviour; + private PlayerExtraController extraController; // Task chains - private UserTaskChain _userTaskChain; - private FoodChain _foodChain; - private MobDefenseChain _mobDefenseChain; - private MLGBucketFallChain _mlgBucketChain; + private UserTaskChain userTaskChain; + private FoodChain foodChain; + private MobDefenseChain mobDefenseChain; + private MLGBucketFallChain mlgBucketChain; + private UnstuckChain unstuckChain; // Trackers - private ItemStorageTracker _storageTracker; - private ContainerSubTracker _containerSubTracker; - private EntityTracker _entityTracker; - private BlockTracker _blockTracker; - private SimpleChunkTracker _chunkTracker; - private MiscBlockTracker _miscBlockTracker; + private ItemStorageTracker storageTracker; + private ContainerSubTracker containerSubTracker; + private EntityTracker entityTracker; + private BlockScanner blockScanner; + private SimpleChunkTracker chunkTracker; + private MiscBlockTracker miscBlockTracker; // Renderers - private CommandStatusOverlay _commandStatusOverlay; + private CommandStatusOverlay commandStatusOverlay; // Settings - private adris.altoclef.Settings _settings; + private adris.altoclef.Settings settings; // Misc managers/input - private MessageSender _messageSender; - private InputControls _inputControls; - private SlotHandler _slotHandler; - // Butler - private Butler _butler; + private MessageSender messageSender; + private InputControls inputControls; + private SlotHandler slotHandler; + + //TODO refactor this later + public static AltoClef INSTANCE; // Are we in game (playing in a server/world) public static boolean inGame() { @@ -87,7 +87,7 @@ public static boolean inGame() { * Executes commands (ex. `@get`/`@gamer`) */ public static CommandExecutor getCommandExecutor() { - return _commandExecutor; + return commandExecutor; } @Override @@ -96,6 +96,7 @@ public void onInitialize() { // However, some things (like resources) may still be uninitialized. // As such, nothing will be loaded here but basic initialization. EventBus.subscribe(TitleScreenEntryEvent.class, evt -> onInitializeLoad()); + INSTANCE = this; } public void onInitializeLoad() { @@ -105,45 +106,44 @@ public void onInitializeLoad() { initializeBaritoneSettings(); // Central Managers - _commandExecutor = new CommandExecutor(this); - _taskRunner = new TaskRunner(this); - _trackerManager = new TrackerManager(this); - _botBehaviour = new BotBehaviour(this); - _extraController = new PlayerExtraController(this); + commandExecutor = new CommandExecutor(this); + taskRunner = new TaskRunner(this); + trackerManager = new TrackerManager(this); + botBehaviour = new BotBehaviour(this); + extraController = new PlayerExtraController(this); // Task chains - _userTaskChain = new UserTaskChain(_taskRunner); - _mobDefenseChain = new MobDefenseChain(_taskRunner); - new DeathMenuChain(_taskRunner); - new PlayerInteractionFixChain(_taskRunner); - _mlgBucketChain = new MLGBucketFallChain(_taskRunner); - new WorldSurvivalChain(_taskRunner); - _foodChain = new FoodChain(_taskRunner); + userTaskChain = new UserTaskChain(taskRunner); + mobDefenseChain = new MobDefenseChain(taskRunner); + new DeathMenuChain(taskRunner); + new PlayerInteractionFixChain(taskRunner); + mlgBucketChain = new MLGBucketFallChain(taskRunner); + unstuckChain = new UnstuckChain(taskRunner); + new WorldSurvivalChain(taskRunner); + foodChain = new FoodChain(taskRunner); // Trackers - _storageTracker = new ItemStorageTracker(this, _trackerManager, container -> _containerSubTracker = container); - _entityTracker = new EntityTracker(_trackerManager); - _blockTracker = new BlockTracker(this, _trackerManager); - _chunkTracker = new SimpleChunkTracker(this); - _miscBlockTracker = new MiscBlockTracker(this); + storageTracker = new ItemStorageTracker(this, trackerManager, container -> containerSubTracker = container); + entityTracker = new EntityTracker(trackerManager); + blockScanner = new BlockScanner(this); + chunkTracker = new SimpleChunkTracker(this); + miscBlockTracker = new MiscBlockTracker(this); // Renderers - _commandStatusOverlay = new CommandStatusOverlay(); + commandStatusOverlay = new CommandStatusOverlay(); // Misc managers - _messageSender = new MessageSender(); - _inputControls = new InputControls(); - _slotHandler = new SlotHandler(this); - - _butler = new Butler(this); + messageSender = new MessageSender(); + inputControls = new InputControls(); + slotHandler = new SlotHandler(this); initializeCommands(); // Load settings adris.altoclef.Settings.load(newSettings -> { - _settings = newSettings; + settings = newSettings; // Baritone's `acceptableThrowawayItems` should match our own. - List baritoneCanPlace = Arrays.stream(_settings.getThrowawayItems(this, true)) + List baritoneCanPlace = Arrays.stream(settings.getThrowawayItems(this, true)) .filter(item -> item != Items.SOUL_SAND && item != Items.MAGMA_BLOCK && item != Items.SAND && item != Items.GRAVEL).toList(); getClientBaritoneSettings().acceptableThrowawayItems.value.addAll(baritoneCanPlace); @@ -153,8 +153,8 @@ public void onInitializeLoad() { getCommandExecutor().executeWithPrefix(getModSettings().getIdleCommand()); } // Don't break blocks or place blocks where we are explicitly protected. - getExtraBaritoneSettings().avoidBlockBreak(blockPos -> _settings.isPositionExplicitlyProtected(blockPos)); - getExtraBaritoneSettings().avoidBlockPlace(blockPos -> _settings.isPositionExplicitlyProtected(blockPos)); + getExtraBaritoneSettings().avoidBlockBreak(blockPos -> settings.isPositionExplicitlyProtected(blockPos)); + getExtraBaritoneSettings().avoidBlockPlace(blockPos -> settings.isPositionExplicitlyProtected(blockPos)); }); // Receive + cancel chat @@ -185,36 +185,33 @@ public void onInitializeLoad() { private void onClientTick() { runEnqueuedPostInits(); - _inputControls.onTickPre(); + inputControls.onTickPre(); // Cancel shortcut if (InputHelper.isKeyPressed(GLFW.GLFW_KEY_LEFT_CONTROL) && InputHelper.isKeyPressed(GLFW.GLFW_KEY_K)) { - _userTaskChain.cancel(this); - if (_taskRunner.getCurrentTaskChain() != null) { - _taskRunner.getCurrentTaskChain().stop(this); + userTaskChain.cancel(this); + if (taskRunner.getCurrentTaskChain() != null) { + taskRunner.getCurrentTaskChain().stop(this); } } // TODO: should this go here? - _storageTracker.setDirty(); - _containerSubTracker.onServerTick(); - _miscBlockTracker.tick(); + storageTracker.setDirty(); + containerSubTracker.onServerTick(); + miscBlockTracker.tick(); + trackerManager.tick(); + blockScanner.tick(); + taskRunner.tick(); - _trackerManager.tick(); - _blockTracker.preTickTask(); - _taskRunner.tick(); - _blockTracker.postTickTask(); + messageSender.tick(); - _butler.tick(); - _messageSender.tick(); - - _inputControls.onTickPost(); + inputControls.onTickPost(); } /// GETTERS AND SETTERS private void onClientRenderOverlay(MatrixStack matrixStack) { - _commandStatusOverlay.render(this, matrixStack); + commandStatusOverlay.render(this, matrixStack); } private void initializeBaritoneSettings() { @@ -228,12 +225,17 @@ private void initializeBaritoneSettings() { getClientBaritoneSettings().allowParkourPlace.value = false; getClientBaritoneSettings().allowDiagonalDescend.value = false; getClientBaritoneSettings().allowDiagonalAscend.value = false; - getClientBaritoneSettings().blocksToAvoid.value = List.of(Blocks.FLOWERING_AZALEA, Blocks.AZALEA, + getClientBaritoneSettings().blocksToAvoid.value = new LinkedList<>(List.of(Blocks.FLOWERING_AZALEA, Blocks.AZALEA, Blocks.POWDER_SNOW, Blocks.BIG_DRIPLEAF, Blocks.BIG_DRIPLEAF_STEM, Blocks.CAVE_VINES, Blocks.CAVE_VINES_PLANT, Blocks.TWISTING_VINES, Blocks.TWISTING_VINES_PLANT, Blocks.SWEET_BERRY_BUSH, Blocks.WARPED_ROOTS, Blocks.VINE, Blocks.GRASS, Blocks.FERN, Blocks.TALL_GRASS, Blocks.LARGE_FERN, Blocks.SMALL_AMETHYST_BUD, Blocks.MEDIUM_AMETHYST_BUD, Blocks.LARGE_AMETHYST_BUD, - Blocks.AMETHYST_CLUSTER, Blocks.SCULK, Blocks.SCULK_VEIN); + Blocks.AMETHYST_CLUSTER, Blocks.SCULK, Blocks.SCULK_VEIN)); + + // dont try to break nether portal block + getClientBaritoneSettings().blocksToAvoidBreaking.value.add(Blocks.NETHER_PORTAL); + getClientBaritoneSettings().blocksToDisallowBreaking.value.add(Blocks.NETHER_PORTAL); + // Let baritone move items to hotbar to use them // Reduces a bit of far rendering to save FPS getClientBaritoneSettings().fadePath.value = true; @@ -262,7 +264,7 @@ private void initializeBaritoneSettings() { private void initializeCommands() { try { // This creates the commands. If you want any more commands feel free to initialize new command lists. - new AltoClefCommands(); + AltoClefCommands.init(); } catch (Exception e) { e.printStackTrace(); } @@ -273,56 +275,56 @@ private void initializeCommands() { * (task chains run the task tree) */ public TaskRunner getTaskRunner() { - return _taskRunner; + return taskRunner; } /** * The user task chain (runs your command. Ex. Get Diamonds, Beat the Game) */ public UserTaskChain getUserTaskChain() { - return _userTaskChain; + return userTaskChain; } /** * Controls bot behaviours, like whether to temporarily "protect" certain blocks or items */ public BotBehaviour getBehaviour() { - return _botBehaviour; + return botBehaviour; } /** * Tracks items in your inventory and in storage containers. */ public ItemStorageTracker getItemStorage() { - return _storageTracker; + return storageTracker; } /** * Tracks loaded entities */ public EntityTracker getEntityTracker() { - return _entityTracker; + return entityTracker; } /** - * Tracks blocks and their positions + * Tracks blocks and their positions - better version of BlockTracker */ - public BlockTracker getBlockTracker() { - return _blockTracker; + public BlockScanner getBlockScanner() { + return blockScanner; } /** * Tracks of whether a chunk is loaded/visible or not */ public SimpleChunkTracker getChunkTracker() { - return _chunkTracker; + return chunkTracker; } /** * Tracks random block things, like the last nether portal we used */ public MiscBlockTracker getMiscBlockTracker() { - return _miscBlockTracker; + return miscBlockTracker; } /** @@ -353,28 +355,22 @@ public AltoClefSettings getExtraBaritoneSettings() { * AltoClef Settings */ public adris.altoclef.Settings getModSettings() { - return _settings; + return settings; } - /** - * Butler controller. Keeps track of users and lets you receive user messages - */ - public Butler getButler() { - return _butler; - } /** * Sends chat messages (avoids auto-kicking) */ public MessageSender getMessageSender() { - return _messageSender; + return messageSender; } /** * Does Inventory/container slot actions */ public SlotHandler getSlotHandler() { - return _slotHandler; + return slotHandler; } /** @@ -402,14 +398,14 @@ public ClientPlayerInteractionManager getController() { * Extra controls not present in ClientPlayerInteractionManager. This REALLY should be made static or combined with something else. */ public PlayerExtraController getControllerExtras() { - return _extraController; + return extraController; } /** * Manual control over input actions (ex. jumping, attacking) */ public InputControls getInputControls() { - return _inputControls; + return inputControls; } /** @@ -424,35 +420,39 @@ public void runUserTask(Task task) { * Run a user task */ public void runUserTask(Task task, Runnable onFinish) { - _userTaskChain.runTask(this, task, onFinish); + userTaskChain.runTask(this, task, onFinish); } /** * Cancel currently running user task */ public void cancelUserTask() { - _userTaskChain.cancel(this); + userTaskChain.cancel(this); } /** * Takes control away to eat food */ public FoodChain getFoodChain() { - return _foodChain; + return foodChain; } /** * Takes control away to defend against mobs */ public MobDefenseChain getMobDefenseChain() { - return _mobDefenseChain; + return mobDefenseChain; } /** * Takes control away to perform bucket saves */ public MLGBucketFallChain getMLGBucketChain() { - return _mlgBucketChain; + return mlgBucketChain; + } + + public UnstuckChain getUnstuckChain() { + return unstuckChain; } public void log(String message) { @@ -464,7 +464,6 @@ public void log(String message) { */ public void log(String message, MessagePriority priority) { Debug.logMessage(message); - _butler.onLog(message, priority); } public void logWarning(String message) { @@ -476,7 +475,6 @@ public void logWarning(String message) { */ public void logWarning(String message, MessagePriority priority) { Debug.logWarning(message); - _butler.onLogWarning(message, priority); } private void runEnqueuedPostInits() { diff --git a/src/main/java/adris/altoclef/AltoClefCommands.java b/src/main/java/adris/altoclef/AltoClefCommands.java index dbd8417c..270c2bcb 100644 --- a/src/main/java/adris/altoclef/AltoClefCommands.java +++ b/src/main/java/adris/altoclef/AltoClefCommands.java @@ -1,6 +1,8 @@ package adris.altoclef; import adris.altoclef.commands.*; +import adris.altoclef.commands.random.CycleTestCommand; +import adris.altoclef.commands.random.ScanCommand; import adris.altoclef.commandsystem.CommandException; /** @@ -8,38 +10,19 @@ */ public class AltoClefCommands { - public AltoClefCommands() throws CommandException { + public static void init() throws CommandException { // List commands here AltoClef.getCommandExecutor().registerNewCommand( new HelpCommand(), - new GetCommand(), - new FollowCommand(), - new GiveCommand(), - new EquipCommand(), - new DepositCommand(), - new StashCommand(), - new GotoCommand(), - new IdleCommand(), - new CoordsCommand(), new StatusCommand(), - new InventoryCommand(), - new LocateStructureCommand(), new StopCommand(), + new SetGammaCommand(), new TestCommand(), - new FoodCommand(), - new MeatCommand(), - new ReloadSettingsCommand(), new GamerCommand(), new MarvionCommand(), - new PunkCommand(), - new HeroCommand(), - new SetGammaCommand(), - new ListCommand(), - new CoverWithSandCommand(), - new CoverWithBlocksCommand(), - new SelfCareCommand() - //new TestMoveInventoryCommand(), - // new TestSwapInventoryCommand() + new ReloadSettingsCommand(), + //new CycleTestCommand(), + new ScanCommand() ); } } diff --git a/src/main/java/adris/altoclef/BotBehaviour.java b/src/main/java/adris/altoclef/BotBehaviour.java index a217232d..16f9eaba 100644 --- a/src/main/java/adris/altoclef/BotBehaviour.java +++ b/src/main/java/adris/altoclef/BotBehaviour.java @@ -257,7 +257,7 @@ private State current() { return _states.peek(); } - class State { + private class State { /// Baritone Params public double followOffsetDistance; public List protectedItems = new ArrayList<>(); diff --git a/src/main/java/adris/altoclef/Debug.java b/src/main/java/adris/altoclef/Debug.java index b7599db8..6c698b4e 100644 --- a/src/main/java/adris/altoclef/Debug.java +++ b/src/main/java/adris/altoclef/Debug.java @@ -29,7 +29,7 @@ public static void logMessage(String message, boolean prefix) { message = "\u00A72\u00A7l\u00A7o" + getLogPrefix() + "\u00A7r" + message; } MinecraftClient.getInstance().player.sendMessage(Text.of(message), false); - //MinecraftClient.getInstance().player.sendChatMessage(msg); + } else { logInternal(message); } @@ -49,7 +49,7 @@ public static void logWarning(String message) { if (MinecraftClient.getInstance() != null && MinecraftClient.getInstance().player != null) { String msg = "\u00A72\u00A7l\u00A7o" + getLogPrefix() + "\u00A7c" + message + "\u00A7r"; MinecraftClient.getInstance().player.sendMessage(Text.of(msg), false); - //MinecraftClient.getInstance().player.sendChatMessage(msg); + } } } diff --git a/src/main/java/adris/altoclef/Playground.java b/src/main/java/adris/altoclef/Playground.java index 42766eab..5e42ca97 100644 --- a/src/main/java/adris/altoclef/Playground.java +++ b/src/main/java/adris/altoclef/Playground.java @@ -1,9 +1,7 @@ package adris.altoclef; -import adris.altoclef.butler.WhisperChecker; import adris.altoclef.tasks.CraftGenericManuallyTask; import adris.altoclef.tasks.construction.PlaceBlockNearbyTask; -import adris.altoclef.tasks.construction.PlaceSignTask; import adris.altoclef.tasks.construction.PlaceStructureBlockTask; import adris.altoclef.tasks.construction.compound.ConstructIronGolemTask; import adris.altoclef.tasks.construction.compound.ConstructNetherPortalObsidianTask; @@ -24,10 +22,6 @@ import adris.altoclef.tasks.speedrun.KillEnderDragonTask; import adris.altoclef.tasks.speedrun.KillEnderDragonWithBedsTask; import adris.altoclef.tasks.speedrun.WaitForDragonAndPearlTask; -import adris.altoclef.tasks.stupid.BeeMovieTask; -import adris.altoclef.tasks.stupid.ReplaceBlocksTask; -import adris.altoclef.tasks.stupid.SCP173Task; -import adris.altoclef.tasks.stupid.TerminatorTask; import adris.altoclef.util.*; import adris.altoclef.util.helpers.WorldHelper; import net.minecraft.block.Block; @@ -128,12 +122,6 @@ public static void TEMP_TEST_FUNCTION(AltoClef mod, String arg) { // None specified Debug.logWarning("Please specify a test (ex. stacked, bed, terminate)"); break; - case "sign": - mod.runUserTask(new PlaceSignTask("Hello there!")); - break; - case "sign2": - mod.runUserTask(new PlaceSignTask(new BlockPos(10, 3, 10), "Hello there!")); - break; case "pickup": mod.runUserTask(new PickupDroppedItemTask(new ItemTarget(Items.IRON_ORE, 3), true)); break; @@ -155,15 +143,6 @@ public static void TEMP_TEST_FUNCTION(AltoClef mod, String arg) { //mod.runUserTask(new PlaceStructureBlockTask(new BlockPos(472, 24, -324))); break; } - case "deadmeme": - File file = new File("test.txt"); - try { - FileReader reader = new FileReader(file); - mod.runUserTask(new BeeMovieTask("bruh", mod.getPlayer().getBlockPos(), reader)); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - break; case "stacked": // It should only need: // 24 (armor) + 3*3 (pick) + 2 = 35 diamonds @@ -191,9 +170,6 @@ public static void TEMP_TEST_FUNCTION(AltoClef mod, String arg) { case "temples": mod.runUserTask(new RavageDesertTemplesTask()); break; - case "outer": - mod.runUserTask(new GetToOuterEndIslandsTask()); - break; case "smelt": ItemTarget target = new ItemTarget("iron_ingot", 4); ItemTarget material = new ItemTarget("iron_ore", 4); @@ -298,17 +274,6 @@ public static void TEMP_TEST_FUNCTION(AltoClef mod, String arg) { case "stronghold": mod.runUserTask(new GoToStrongholdPortalTask(12)); break; - case "terminate": - mod.runUserTask(new TerminatorTask(mod.getPlayer().getBlockPos(), 900)); - break; - case "replace": - // Creates a mini valley of crafting tables. - BlockPos from = mod.getPlayer().getBlockPos().add(new Vec3i(-100, -20, -100)); - BlockPos to = mod.getPlayer().getBlockPos().add(new Vec3i(100, 255, 100)); - Block[] toFind = new Block[]{Blocks.GRASS_BLOCK};// Blocks.COBBLESTONE}; - ItemTarget toReplace = new ItemTarget("crafting_table");//"stone"); - mod.runUserTask(new ReplaceBlocksTask(toReplace, from, to, toFind)); - break; case "bed": mod.runUserTask(new PlaceBedAndSetSpawnTask()); break; @@ -324,9 +289,6 @@ public static void TEMP_TEST_FUNCTION(AltoClef mod, String arg) { case "chest": mod.runUserTask(new StoreInAnyContainerTask(true, new ItemTarget(Items.DIAMOND, 3))); break; - case "173": - mod.runUserTask(new SCP173Task()); - break; case "example": mod.runUserTask(new ExampleTask2()); break; @@ -351,21 +313,6 @@ public static void TEMP_TEST_FUNCTION(AltoClef mod, String arg) { GhastEntity ghast = ghasts.get(0); mod.runUserTask(new ShootArrowSimpleProjectileTask(ghast)); break; - case "whisper": { - File check = new File("whisper.txt"); - try { - FileInputStream fis = new FileInputStream(check); - Scanner sc = new Scanner(fis); - String me = sc.nextLine(), - template = sc.nextLine(), - message = sc.nextLine(); - WhisperChecker.MessageResult result = WhisperChecker.tryParse(me, template, message); - Debug.logMessage("Got message: " + result); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - break; - } default: mod.logWarning("Test not found: \"" + arg + "\"."); break; diff --git a/src/main/java/adris/altoclef/Settings.java b/src/main/java/adris/altoclef/Settings.java index 0ab8f603..7e1312a8 100644 --- a/src/main/java/adris/altoclef/Settings.java +++ b/src/main/java/adris/altoclef/Settings.java @@ -15,6 +15,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.google.common.collect.Streams; import net.minecraft.item.Item; +import net.minecraft.item.ItemGroup; import net.minecraft.item.Items; import net.minecraft.util.math.BlockPos; @@ -72,7 +73,7 @@ public class Settings implements IFailableConfigFile { /** * If true, will show a timer. */ - private boolean showTimer = false; + private boolean showTimer = true; /** * The delay between moving items for crafting/furnace/any kind of inventory movement. @@ -378,7 +379,7 @@ public class Settings implements IFailableConfigFile { /** * If true, a blast furnace will be used in smelting if an item to smelt is applicable. */ - private boolean useBlastFurnace = true; + private boolean useBlastFurnace = false; /** * If true, will only accept items found in `supportedFuels` as fuel when smelting. diff --git a/src/main/java/adris/altoclef/butler/Butler.java b/src/main/java/adris/altoclef/butler/Butler.java deleted file mode 100644 index 4b2fb1d3..00000000 --- a/src/main/java/adris/altoclef/butler/Butler.java +++ /dev/null @@ -1,168 +0,0 @@ -package adris.altoclef.butler; - -import adris.altoclef.AltoClef; -import adris.altoclef.Debug; -import adris.altoclef.eventbus.EventBus; -import adris.altoclef.eventbus.events.ChatMessageEvent; -import adris.altoclef.eventbus.events.TaskFinishedEvent; -import adris.altoclef.ui.MessagePriority; -import net.minecraft.network.message.MessageType; - -import java.util.Objects; - -/** - * The butler system lets authorized players send commands to the bot to execute. - *

- * This effectively makes the bot function as a servant, or butler. - *

- * Authorization is defined in "altoclef_butler_whitelist.txt" and "altoclef_butler_blacklist.txt" - * and depends on the "useButlerWhitelist" and "useButlerBlacklist" settings in "altoclef_settings.json" - */ -public class Butler { - - private static final String BUTLER_MESSAGE_START = "` "; - - private final AltoClef _mod; - - private final WhisperChecker _whisperChecker = new WhisperChecker(); - - private final UserAuth _userAuth; - - private String _currentUser = null; - - // Utility variables for command logic - private boolean _commandInstantRan = false; - private boolean _commandFinished = false; - - public Butler(AltoClef mod) { - _mod = mod; - _userAuth = new UserAuth(mod); - - // Revoke our current user whenever a task finishes. - EventBus.subscribe(TaskFinishedEvent.class, evt -> { - if (_currentUser != null) { - _currentUser = null; - } - }); - - // Receive system events - EventBus.subscribe(ChatMessageEvent.class, evt -> { - boolean debug = ButlerConfig.getInstance().whisperFormatDebug; - String message = evt.messageContent(); - String sender = evt.senderName(); - MessageType messageType = evt.messageType(); - String receiver = mod.getPlayer().getName().getString(); - if (sender != null && !Objects.equals(sender, receiver) && messageType.chat().style().isItalic() - && messageType.chat().style().getColor() != null - && Objects.equals(messageType.chat().style().getColor().getName(), "gray")) { - String wholeMessage = sender + " " + receiver + " " + message; - if (debug) { - Debug.logMessage("RECEIVED WHISPER: \"" + wholeMessage + "\"."); - } - _mod.getButler().receiveMessage(wholeMessage, receiver); - } - }); - } - - private void receiveMessage(String msg, String receiver) { - // Format: whispers to you: - // Format: whispers: - WhisperChecker.MessageResult result = this._whisperChecker.receiveMessage(_mod, receiver, msg); - if (result != null) { - this.receiveWhisper(result.from, result.message); - } else if (ButlerConfig.getInstance().whisperFormatDebug) { - Debug.logMessage(" Not Parsing: MSG format not found."); - } - } - - private void receiveWhisper(String username, String message) { - - boolean debug = ButlerConfig.getInstance().whisperFormatDebug; - // Ignore messages from other bots. - if (message.startsWith(BUTLER_MESSAGE_START)) { - if (debug) { - Debug.logMessage(" Rejecting: MSG is detected to be sent from another bot."); - } - return; - } - - if (_userAuth.isUserAuthorized(username)) { - executeWhisper(username, message); - } else { - if (debug) { - Debug.logMessage(" Rejecting: User \"" + username + "\" is not authorized."); - } - if (ButlerConfig.getInstance().sendAuthorizationResponse) { - sendWhisper(username, ButlerConfig.getInstance().failedAuthorizationResposne.replace("{from}", username), MessagePriority.UNAUTHORIZED); - } - } - } - - @SuppressWarnings("BooleanMethodIsAlwaysInverted") - public boolean isUserAuthorized(String username) { - return _userAuth.isUserAuthorized(username); - } - - public void onLog(String message, MessagePriority priority) { - if (_currentUser != null) { - sendWhisper(message, priority); - } - } - - public void onLogWarning(String message, MessagePriority priority) { - if (_currentUser != null) { - sendWhisper("[WARNING:] " + message, priority); - } - } - - public void tick() { - // Nothing for now. - } - - public String getCurrentUser() { - return _currentUser; - } - - public boolean hasCurrentUser() { - return _currentUser != null; - } - - private void executeWhisper(String username, String message) { - String prevUser = _currentUser; - _commandInstantRan = true; - _commandFinished = false; - _currentUser = username; - sendWhisper("Command Executing: " + message, MessagePriority.TIMELY); - String prefix = ButlerConfig.getInstance().requirePrefixMsg ? _mod.getModSettings().getCommandPrefix() : ""; - AltoClef.getCommandExecutor().execute(prefix + message, () -> { - // On finish - sendWhisper("Command Finished: " + message, MessagePriority.TIMELY); - if (!_commandInstantRan) { - _currentUser = null; - } - _commandFinished = true; - }, e -> { - sendWhisper("TASK FAILED: " + e.getMessage(), MessagePriority.ASAP); - e.printStackTrace(); - _currentUser = null; - _commandInstantRan = false; - }); - _commandInstantRan = false; - // Only set the current user if we're still running. - if (_commandFinished) { - _currentUser = prevUser; - } - } - - private void sendWhisper(String message, MessagePriority priority) { - if (_currentUser != null) { - sendWhisper(_currentUser, message, priority); - } else { - Debug.logWarning("Failed to send butler message as there are no users present: " + message); - } - } - - private void sendWhisper(String username, String message, MessagePriority priority) { - _mod.getMessageSender().enqueueWhisper(username, BUTLER_MESSAGE_START + message, priority); - } -} diff --git a/src/main/java/adris/altoclef/butler/ButlerConfig.java b/src/main/java/adris/altoclef/butler/ButlerConfig.java deleted file mode 100644 index 58558029..00000000 --- a/src/main/java/adris/altoclef/butler/ButlerConfig.java +++ /dev/null @@ -1,68 +0,0 @@ -package adris.altoclef.butler; - -import adris.altoclef.util.helpers.ConfigHelper; - -public class ButlerConfig { - - private static ButlerConfig _instance = new ButlerConfig(); - - static { - ConfigHelper.loadConfig("configs/butler.json", ButlerConfig::new, ButlerConfig.class, newConfig -> _instance = newConfig); - } - - /** - * If true, will use blacklist for rejecting users from using your player as a butler - */ - public boolean useButlerBlacklist = true; - /** - * If true, will use whitelist to only accept users from said whitelist. - */ - public boolean useButlerWhitelist = false; - /** - * Servers have different messaging plugins that change the way messages are displayed. - * Rather than attempt to implement all of them and introduce a big security risk, - * you may define custom whisper formats that the butler will watch out for. - *

- * Within curly brackets are three special parts: - *

- * {from}: Who the message was sent from - * {to}: Who the message was sent to, butler will ignore if this is not your username. - * {message}: The message. - *

- *

- * WARNING: The butler will only accept non-chat messages as commands, but don't make this too lenient, - * else you may risk unauthorized control to the bot. Basically, make sure that only whispers can - * create the following messages. - */ - public String[] whisperFormats = new String[]{ - "{from} {to} {message}" - }; - /** - * If set to true, will print information about whispers that are parsed and those - * that have failed parsing. - *

- * Enable this if you need help setting up the whisper format. - */ - public boolean whisperFormatDebug = true; - /** - * Determines if failure messages should be sent to a non-authorized entity attempting to use butler - *

- * Disable this if you need to stay undercover. - */ - public boolean sendAuthorizationResponse = true; - /** - * The response sent in a failed execution due to non-authorization - * {from}: the username of the player who triggered the failed authorization response - */ - public String failedAuthorizationResposne = "Sorry {from} but you are not authorized!"; - /** - * Use this to choose if the prefix should be required in messages - *

- * Disable this if you want to be able to send normal messages and not butler commands. - */ - public boolean requirePrefixMsg = false; - - public static ButlerConfig getInstance() { - return _instance; - } -} diff --git a/src/main/java/adris/altoclef/butler/UserAuth.java b/src/main/java/adris/altoclef/butler/UserAuth.java deleted file mode 100644 index 1255ca31..00000000 --- a/src/main/java/adris/altoclef/butler/UserAuth.java +++ /dev/null @@ -1,43 +0,0 @@ -package adris.altoclef.butler; - -import adris.altoclef.AltoClef; -import adris.altoclef.util.helpers.ConfigHelper; - -public class UserAuth { - private static final String BLACKLIST_PATH = "altoclef_butler_blacklist.txt"; - private static final String WHITELIST_PATH = "altoclef_butler_whitelist.txt"; - private final AltoClef _mod; - private UserListFile _blacklist; - private UserListFile _whitelist; - - public UserAuth(AltoClef mod) { - _mod = mod; - - ConfigHelper.ensureCommentedListFileExists(BLACKLIST_PATH, """ - Add butler blacklisted players here. - Make sure useButlerBlacklist is set to true in the settings file. - Anything after a pound sign (#) will be ignored."""); - ConfigHelper.ensureCommentedListFileExists(WHITELIST_PATH, """ - Add butler whitelisted players here. - Make sure useButlerWhitelist is set to true in the settings file. - Anything after a pound sign (#) will be ignored."""); - - UserListFile.load(BLACKLIST_PATH, newList -> _blacklist = newList); - UserListFile.load(WHITELIST_PATH, newList -> _whitelist = newList); - } - - public boolean isUserAuthorized(String username) { - - // Blacklist gets first priority. - if (ButlerConfig.getInstance().useButlerBlacklist && _blacklist.containsUser(username)) { - return false; - } - if (ButlerConfig.getInstance().useButlerWhitelist) { - return _whitelist.containsUser(username); - } - - // By default accept everyone. - return true; - } - -} diff --git a/src/main/java/adris/altoclef/butler/UserListFile.java b/src/main/java/adris/altoclef/butler/UserListFile.java deleted file mode 100644 index ed4393fd..00000000 --- a/src/main/java/adris/altoclef/butler/UserListFile.java +++ /dev/null @@ -1,30 +0,0 @@ -package adris.altoclef.butler; - -import adris.altoclef.util.helpers.ConfigHelper; -import adris.altoclef.util.serialization.IListConfigFile; - -import java.util.HashSet; -import java.util.function.Consumer; - -public class UserListFile implements IListConfigFile { - - private final HashSet _users = new HashSet<>(); - - public static void load(String path, Consumer onLoad) { - ConfigHelper.loadListConfig(path, UserListFile::new, onLoad); - } - - public boolean containsUser(String username) { - return _users.contains(username); - } - - @Override - public void onLoadStart() { - _users.clear(); - } - - @Override - public void addLine(String line) { - _users.add(line); - } -} diff --git a/src/main/java/adris/altoclef/butler/WhisperChecker.java b/src/main/java/adris/altoclef/butler/WhisperChecker.java deleted file mode 100644 index a6dd4a6f..00000000 --- a/src/main/java/adris/altoclef/butler/WhisperChecker.java +++ /dev/null @@ -1,101 +0,0 @@ -package adris.altoclef.butler; - -import adris.altoclef.AltoClef; -import adris.altoclef.Debug; -import adris.altoclef.util.time.TimerGame; - -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class WhisperChecker { - - private static final TimerGame _repeatTimer = new TimerGame(0.1); - - private static String _lastMessage = null; - - public static MessageResult tryParse(String ourUsername, String whisperFormat, String message) { - List parts = new ArrayList<>(Arrays.asList("{from}", "{to}", "{message}")); - - // Sort by the order of appearance in whisperFormat. - parts.sort(Comparator.comparingInt(whisperFormat::indexOf)); - parts.removeIf(part -> !whisperFormat.contains(part)); - - String regexFormat = Pattern.quote(whisperFormat); - for (String part : parts) { - regexFormat = regexFormat.replace(part, "(.+)"); - } - if (regexFormat.startsWith("\\Q")) regexFormat = regexFormat.substring("\\Q".length()); - if (regexFormat.endsWith("\\E")) regexFormat = regexFormat.substring(0, regexFormat.length() - "\\E".length()); - //Debug.logInternal("FORMAT: " + regexFormat + " tested on " + message); - Pattern p = Pattern.compile(regexFormat); - Matcher m = p.matcher(message); - Map values = new HashMap<>(); - if (m.matches()) { - for (int i = 0; i < m.groupCount(); ++i) { - // parts is sorted, so the order should lign up. - if (i >= parts.size()) { - Debug.logError("Invalid whisper format parsing: " + whisperFormat + " for message: " + message); - break; - } - //Debug.logInternal(" GOT: " + parts.get(i) + " -> " + m.group(i + 1)); - values.put(parts.get(i), m.group(i + 1)); - } - } - - if (values.containsKey("{to}")) { - // Make sure the "to" target is us. - String toUser = values.get("{to}"); - if (!toUser.equals(ourUsername)) { - Debug.logInternal("Rejected message since it is sent to " + toUser + " and not " + ourUsername); - return null; - } - } - if (values.containsKey("{from}") && values.containsKey("{message}")) { - MessageResult result = new MessageResult(); - result.from = values.get("{from}"); - result.message = values.get("{message}"); - return result; - } - return null; - } - - public MessageResult receiveMessage(AltoClef mod, String ourUsername, String msg) { - String foundMiddlePart = ""; - int index = -1; - - boolean duplicate = (msg.equals(_lastMessage)); - if (duplicate && !_repeatTimer.elapsed()) { - _repeatTimer.reset(); - // It's probably an actual duplicate. IDK why we get those but yeah. - return null; - } - - _lastMessage = msg; - - for (String format : ButlerConfig.getInstance().whisperFormats) { - MessageResult check = tryParse(ourUsername, format, msg); - if (check != null) { - String user = check.from; - String message = check.message; - if (user == null || message == null) break; - return check; - } - } - - return null; - } - - public static class MessageResult { - public String from; - public String message; - - @Override - public String toString() { - return "MessageResult{" + - "from='" + from + '\'' + - ", message='" + message + '\'' + - '}'; - } - } -} diff --git a/src/main/java/adris/altoclef/chains/FoodChain.java b/src/main/java/adris/altoclef/chains/FoodChain.java index 22d8d538..4ba1ed57 100644 --- a/src/main/java/adris/altoclef/chains/FoodChain.java +++ b/src/main/java/adris/altoclef/chains/FoodChain.java @@ -10,7 +10,9 @@ import baritone.api.utils.input.Input; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.entity.Entity; import net.minecraft.entity.effect.StatusEffects; +import net.minecraft.entity.mob.HostileEntity; import net.minecraft.item.FoodComponent; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -23,18 +25,18 @@ @SuppressWarnings("OptionalUsedAsFieldOrParameterType") public class FoodChain extends SingleTaskChain { - private static FoodChainConfig _config; - private static boolean _hasFood; + private static FoodChainConfig config; + private static boolean hasFood; static { - ConfigHelper.loadConfig("configs/food_chain_settings.json", FoodChainConfig::new, FoodChainConfig.class, newConfig -> _config = newConfig); + ConfigHelper.loadConfig("configs/food_chain_settings.json", FoodChainConfig::new, FoodChainConfig.class, newConfig -> config = newConfig); } - private final DragonBreathTracker _dragonBreathTracker = new DragonBreathTracker(); - private boolean _isTryingToEat = false; - private boolean _requestFillup = false; - private boolean _needsFood = false; - private Optional _cachedPerfectFood = Optional.empty(); + private final DragonBreathTracker dragonBreathTracker = new DragonBreathTracker(); + private boolean isTryingToEat = false; + private boolean requestFillup = false; + private boolean needsFood = false; + private Optional cachedPerfectFood = Optional.empty(); private boolean shouldStop = false; public FoodChain(TaskRunner runner) { @@ -48,25 +50,31 @@ protected void onTaskFinish(AltoClef mod) { private void startEat(AltoClef mod, Item food) { //Debug.logInternal("EATING " + toUse.getTranslationKey() + " : " + test); - _isTryingToEat = true; - _requestFillup = true; + if (mod.getPlayer().isBlocking()) { + mod.log("want to eat, trying to stop shielding..."); + mod.getInputControls().release(Input.CLICK_RIGHT); + return; + } + + isTryingToEat = true; + requestFillup = true; mod.getSlotHandler().forceEquipItem(new Item[]{food}, true); //"true" because it's food mod.getInputControls().hold(Input.CLICK_RIGHT); mod.getExtraBaritoneSettings().setInteractionPaused(true); } private void stopEat(AltoClef mod) { - if (_isTryingToEat) { + if (isTryingToEat) { if (mod.getItemStorage().hasItem(Items.SHIELD) || mod.getItemStorage().hasItemInOffhand(Items.SHIELD)) { if (StorageHelper.getItemStackInSlot(PlayerSlot.OFFHAND_SLOT).getItem() != Items.SHIELD) { mod.getSlotHandler().forceEquipItemToOffhand(Items.SHIELD); } else { - _isTryingToEat = false; - _requestFillup = false; + isTryingToEat = false; + requestFillup = false; } } else { - _isTryingToEat = false; - _requestFillup = false; + isTryingToEat = false; + requestFillup = false; } mod.getInputControls().release(Input.CLICK_RIGHT); mod.getExtraBaritoneSettings().setInteractionPaused(false); @@ -74,7 +82,7 @@ private void stopEat(AltoClef mod) { } public boolean isTryingToEat() { - return _isTryingToEat; + return isTryingToEat; } @Override @@ -87,9 +95,9 @@ public float getPriority(AltoClef mod) { stopEat(mod); return Float.NEGATIVE_INFINITY; } - _dragonBreathTracker.updateBreath(mod); + dragonBreathTracker.updateBreath(mod); for (BlockPos playerIn : WorldHelper.getBlocksTouchingPlayer(mod)) { - if (_dragonBreathTracker.isTouchingDragonBreath(playerIn)) { + if (dragonBreathTracker.isTouchingDragonBreath(playerIn)) { stopEat(mod); return Float.NEGATIVE_INFINITY; } @@ -113,26 +121,31 @@ public float getPriority(AltoClef mod) { - We're kind of hungry and have food that fits perfectly */ // We're in danger, don't eat now!! - if (!mod.getMLGBucketChain().doneMLG() || mod.getMLGBucketChain().isFallingOhNo(mod) || + if (!mod.getMLGBucketChain().doneMLG() || mod.getMLGBucketChain().isFalling(mod) || mod.getPlayer().isBlocking() || shouldStop) { stopEat(mod); return Float.NEGATIVE_INFINITY; } Pair> calculation = calculateFood(mod); int _cachedFoodScore = calculation.getLeft(); - _cachedPerfectFood = calculation.getRight(); - _hasFood = _cachedFoodScore > 0; + cachedPerfectFood = calculation.getRight(); + hasFood = _cachedFoodScore > 0; // If we requested a fillup but we're full, stop. - if (_requestFillup && mod.getPlayer().getHungerManager().getFoodLevel() >= 20) { - _requestFillup = false; + if (requestFillup && mod.getPlayer().getHungerManager().getFoodLevel() >= 20) { + requestFillup = false; } // If we no longer have food, we no longer can eat. - if (!_hasFood) { - _requestFillup = false; + if (!hasFood) { + requestFillup = false; } - if (_hasFood && (needsToEat() || _requestFillup) && _cachedPerfectFood.isPresent() && - !mod.getMLGBucketChain().isChorusFruiting() && !mod.getPlayer().isBlocking()) { - Item toUse = _cachedPerfectFood.get(); + + //FIXME should check if currently fighting + if (hasFood && (needsToEat() || requestFillup) && cachedPerfectFood.isPresent() && + !mod.getMLGBucketChain().isChorusFruiting() && !mod.getPlayer().isBlocking()/* && + !areEnemiesNearby(mod)*/) { + + Item toUse = cachedPerfectFood.get(); + // Make sure we're not facing a container if (!LookHelper.tryAvoidingInteractable(mod)) { return Float.NEGATIVE_INFINITY; @@ -144,8 +157,8 @@ public float getPriority(AltoClef mod) { Settings settings = mod.getModSettings(); - if (_needsFood || _cachedFoodScore < settings.getMinimumFoodAllowed()) { - _needsFood = _cachedFoodScore < settings.getFoodUnitsToCollect(); + if (needsFood || _cachedFoodScore < settings.getMinimumFoodAllowed()) { + needsFood = _cachedFoodScore < settings.getFoodUnitsToCollect(); // Only collect if we don't have enough food. // If the user inputs invalid settings, the bot would get stuck here. @@ -160,6 +173,16 @@ public float getPriority(AltoClef mod) { return Float.NEGATIVE_INFINITY; } + private boolean areEnemiesNearby(AltoClef mod) { + for (Entity entity : mod.getEntityTracker().getCloseEntities()) { + if (entity instanceof HostileEntity hostile && hostile.distanceTo(mod.getPlayer()) < (isTryingToEat?14:7)) { + return true; + } + } + + return false; + } + @Override public boolean isActive() { // We're always checking for food. @@ -181,36 +204,40 @@ public boolean needsToEat() { if (!hasFood() || shouldStop) { return false; } + + ClientPlayerEntity player = MinecraftClient.getInstance().player; assert player != null; int foodLevel = player.getHungerManager().getFoodLevel(); float health = player.getHealth(); - if (health <= 10 && foodLevel <= 19) { - return true; - } - //Debug.logMessage("FOOD: " + foodLevel + " -- HEALTH: " + health); if (foodLevel >= 20) { // We can't eat. return false; - } else { - // Eat if we're desperate/need to heal ASAP - if (player.isOnFire() || player.hasStatusEffect(StatusEffects.WITHER) || health < _config.alwaysEatWhenWitherOrFireAndHealthBelow) { - return true; - } else if (foodLevel > _config.alwaysEatWhenBelowHunger) { - if (health < _config.alwaysEatWhenBelowHealth) { - return true; - } - } else { - // We have half hunger + } + + if (health <= 10) { + return true; + } + //Debug.logMessage("FOOD: " + foodLevel + " -- HEALTH: " + health); + + // Eat if we're desperate/need to heal ASAP + if (player.isOnFire() || player.hasStatusEffect(StatusEffects.WITHER) || health < config.alwaysEatWhenWitherOrFireAndHealthBelow) { + return true; + } else if (foodLevel > config.alwaysEatWhenBelowHunger) { + if (health < config.alwaysEatWhenBelowHealth) { return true; } + } else { + // We have half hunger + return true; } + // Eat if we're units hungry and we have a perfect fit. - if (foodLevel < _config.alwaysEatWhenBelowHungerAndPerfectFit && _cachedPerfectFood.isPresent()) { + if (foodLevel < config.alwaysEatWhenBelowHungerAndPerfectFit && cachedPerfectFood.isPresent()) { int need = 20 - foodLevel; - Item best = _cachedPerfectFood.get(); + Item best = cachedPerfectFood.get(); int fills = (best.getFoodComponent() != null) ? best.getFoodComponent().getHunger() : -1; return fills == need; } @@ -250,16 +277,16 @@ private Pair> calculateFood(AltoClef mod) { float saturationWasted = food.getSaturationModifier() - gainedSaturation; float hungerWasted = food.getHunger() - gainedHunger; - boolean prioritizeSaturation = health < _config.prioritizeSaturationWhenBelowHealth; - float saturationGoodScore = prioritizeSaturation ? gainedSaturation * _config.foodPickPrioritizeSaturationSaturationMultiplier : gainedSaturation; - float saturationLossPenalty = prioritizeSaturation ? 0 : saturationWasted * _config.foodPickSaturationWastePenaltyMultiplier; - float hungerLossPenalty = hungerWasted * _config.foodPickHungerWastePenaltyMultiplier; - float hungerNotFilledPenalty = hungerNotFilled * _config.foodPickHungerNotFilledPenaltyMultiplier; + boolean prioritizeSaturation = health < config.prioritizeSaturationWhenBelowHealth; + float saturationGoodScore = prioritizeSaturation ? gainedSaturation * config.foodPickPrioritizeSaturationSaturationMultiplier : gainedSaturation; + float saturationLossPenalty = prioritizeSaturation ? 0 : saturationWasted * config.foodPickSaturationWastePenaltyMultiplier; + float hungerLossPenalty = hungerWasted * config.foodPickHungerWastePenaltyMultiplier; + float hungerNotFilledPenalty = hungerNotFilled * config.foodPickHungerNotFilledPenaltyMultiplier; float score = saturationGoodScore - saturationLossPenalty - hungerLossPenalty - hungerNotFilledPenalty; if (stack.getItem() == Items.ROTTEN_FLESH) { - score -= _config.foodPickRottenFleshPenalty; + score -= config.foodPickRottenFleshPenalty; } if (score > bestFoodScore) { bestFoodScore = score; @@ -279,7 +306,7 @@ public boolean needsToEatCritical() { } public boolean hasFood() { - return _hasFood; + return hasFood; } public void shouldStop(boolean shouldStopInput) { diff --git a/src/main/java/adris/altoclef/chains/MLGBucketFallChain.java b/src/main/java/adris/altoclef/chains/MLGBucketFallChain.java index 2be6b249..8a5ed8b9 100644 --- a/src/main/java/adris/altoclef/chains/MLGBucketFallChain.java +++ b/src/main/java/adris/altoclef/chains/MLGBucketFallChain.java @@ -39,10 +39,10 @@ protected void onTaskFinish(AltoClef mod) { @Override public float getPriority(AltoClef mod) { if (!AltoClef.inGame()) return Float.NEGATIVE_INFINITY; - if (isFallingOhNo(mod)) { + if (isFalling(mod)) { _tryCollectWaterTimer.reset(); setTask(new MLGBucketTask()); - _lastMLG = (MLGBucketTask) _mainTask; + _lastMLG = (MLGBucketTask) mainTask; return 100; } else if (!_tryCollectWaterTimer.elapsed()) { // Why -0.5? Cause it's slower than -0.7. // We just placed water, try to collect it. @@ -128,7 +128,7 @@ public boolean isChorusFruiting() { return _doingChorusFruit; } - public boolean isFallingOhNo(AltoClef mod) { + public boolean isFalling(AltoClef mod) { if (!mod.getModSettings().shouldAutoMLGBucket()) { return false; } diff --git a/src/main/java/adris/altoclef/chains/MobDefenseChain.java b/src/main/java/adris/altoclef/chains/MobDefenseChain.java index e0ef537a..81d48ed7 100644 --- a/src/main/java/adris/altoclef/chains/MobDefenseChain.java +++ b/src/main/java/adris/altoclef/chains/MobDefenseChain.java @@ -10,6 +10,7 @@ import adris.altoclef.tasks.movement.RunAwayFromHostilesTask; import adris.altoclef.tasks.speedrun.DragonBreathTracker; import adris.altoclef.tasksystem.TaskRunner; +import adris.altoclef.util.Dimension; import adris.altoclef.util.baritone.CachedProjectile; import adris.altoclef.util.helpers.*; import adris.altoclef.util.slots.PlayerSlot; @@ -46,16 +47,16 @@ public class MobDefenseChain extends SingleTaskChain { private static final double ARROW_KEEP_DISTANCE_HORIZONTAL = 2;//4; private static final double ARROW_KEEP_DISTANCE_VERTICAL = 10;//15; private static final double SAFE_KEEP_DISTANCE = 8; - private static boolean _shielding = false; - private final DragonBreathTracker _dragonBreathTracker = new DragonBreathTracker(); - private final KillAura _killAura = new KillAura(); - private final HashMap _closeAnnoyingEntities = new HashMap<>(); - private Entity _targetEntity; - private boolean _doingFunkyStuff = false; - private boolean _wasPuttingOutFire = false; - private CustomBaritoneGoalTask _runAwayTask; + private static boolean shielding = false; + private final DragonBreathTracker dragonBreathTracker = new DragonBreathTracker(); + private final KillAura killAura = new KillAura(); + private final HashMap closeAnnoyingEntities = new HashMap<>(); + private Entity targetEntity; + private boolean doingFunkyStuff = false; + private boolean wasPuttingOutFire = false; + private CustomBaritoneGoalTask runAwayTask; - private float _cachedLastPriority; + private float cachedLastPriority; public MobDefenseChain(TaskRunner runner) { super(runner); @@ -71,7 +72,7 @@ public static double getCreeperSafety(Vec3d pos, CreeperEntity creeper) { } private static void startShielding(AltoClef mod) { - _shielding = true; + shielding = true; mod.getInputControls().hold(Input.SNEAK); mod.getInputControls().hold(Input.CLICK_RIGHT); mod.getClientBaritone().getPathingBehavior().requestPause(); @@ -80,13 +81,13 @@ private static void startShielding(AltoClef mod) { ItemStack handItem = StorageHelper.getItemStackInSlot(PlayerSlot.getEquipSlot()); if (handItem.isFood()) { List spaceSlots = mod.getItemStorage().getItemStacksPlayerInventory(false); - if (!spaceSlots.isEmpty()) { - for (ItemStack spaceSlot : spaceSlots) { - if (spaceSlot.isEmpty()) { - mod.getSlotHandler().clickSlot(PlayerSlot.getEquipSlot(), 0, SlotActionType.QUICK_MOVE); - return; - } + + for (ItemStack spaceSlot : spaceSlots) { + if (spaceSlot.isEmpty()) { + mod.getSlotHandler().clickSlot(PlayerSlot.getEquipSlot(), 0, SlotActionType.QUICK_MOVE); + return; } + } Optional garbage = StorageHelper.getGarbageSlot(mod); garbage.ifPresent(slot -> mod.getSlotHandler().forceEquipItem(StorageHelper.getItemStackInSlot(slot).getItem())); @@ -96,12 +97,12 @@ private static void startShielding(AltoClef mod) { @Override public float getPriority(AltoClef mod) { - _cachedLastPriority = getPriorityInner(mod); - return _cachedLastPriority; + cachedLastPriority = getPriorityInner(mod); + return cachedLastPriority; } private void stopShielding(AltoClef mod) { - if (_shielding) { + if (shielding) { ItemStack cursor = StorageHelper.getItemStackInCursorSlot(); if (cursor.isFood()) { Optional toMoveTo = mod.getItemStorage().getSlotThatCanFitInPlayerInventory(cursor, false).or(() -> StorageHelper.getGarbageSlot(mod)); @@ -113,14 +114,14 @@ private void stopShielding(AltoClef mod) { mod.getInputControls().release(Input.SNEAK); mod.getInputControls().release(Input.CLICK_RIGHT); mod.getExtraBaritoneSettings().setInteractionPaused(false); - _shielding = false; + shielding = false; } } private boolean escapeDragonBreath(AltoClef mod) { - _dragonBreathTracker.updateBreath(mod); + dragonBreathTracker.updateBreath(mod); for (BlockPos playerIn : WorldHelper.getBlocksTouchingPlayer(mod)) { - if (_dragonBreathTracker.isTouchingDragonBreath(playerIn)) { + if (dragonBreathTracker.isTouchingDragonBreath(playerIn)) { return true; } } @@ -141,23 +142,20 @@ public float getPriorityInner(AltoClef mod) { // Doing you a favor by disabling avoidance - // Pause if we're not loaded into a world. - if (!AltoClef.inGame()) return Float.NEGATIVE_INFINITY; - // Put out fire if we're standing on one like an idiot BlockPos fireBlock = isInsideFireAndOnFire(mod); if (fireBlock != null) { putOutFire(mod, fireBlock); - _wasPuttingOutFire = true; + wasPuttingOutFire = true; } else { // Stop putting stuff out if we no longer need to put out a fire. mod.getClientBaritone().getInputOverrideHandler().setInputForceState(Input.CLICK_LEFT, false); - _wasPuttingOutFire = false; + wasPuttingOutFire = false; } - if (mod.getFoodChain().needsToEat() || mod.getMLGBucketChain().isFallingOhNo(mod) || + if (mod.getFoodChain().needsToEat() || mod.getMLGBucketChain().isFalling(mod) || !mod.getMLGBucketChain().doneMLG() || mod.getMLGBucketChain().isChorusFruiting()) { - _killAura.stopShielding(mod); + killAura.stopShielding(mod); stopShielding(mod); return Float.NEGATIVE_INFINITY; } @@ -173,12 +171,12 @@ public float getPriorityInner(AltoClef mod) { // Run away if a weird mob is close by. Optional universallyDangerous = getUniversallyDangerousMob(mod); if (universallyDangerous.isPresent() && mod.getPlayer().getHealth() <= 10) { - _runAwayTask = new RunAwayFromHostilesTask(DANGER_KEEP_DISTANCE, true); - setTask(_runAwayTask); + runAwayTask = new RunAwayFromHostilesTask(DANGER_KEEP_DISTANCE, true); + setTask(runAwayTask); return 70; } - _doingFunkyStuff = false; + doingFunkyStuff = false; PlayerSlot offhandSlot = PlayerSlot.OFFHAND_SLOT; Item offhandItem = StorageHelper.getItemStackInSlot(offhandSlot).getItem(); // Run away from creepers @@ -186,10 +184,10 @@ public float getPriorityInner(AltoClef mod) { if (blowingUp != null) { if (!mod.getFoodChain().needsToEat() && (mod.getItemStorage().hasItem(Items.SHIELD) || mod.getItemStorage().hasItemInOffhand(Items.SHIELD)) && - !mod.getEntityTracker().entityFound(PotionEntity.class) && _runAwayTask == null + !mod.getEntityTracker().entityFound(PotionEntity.class) && runAwayTask == null && !mod.getPlayer().getItemCooldownManager().isCoolingDown(offhandItem) && mod.getClientBaritone().getPathingBehavior().isSafeToCancel()) { - _doingFunkyStuff = true; + doingFunkyStuff = true; LookHelper.lookAt(mod, blowingUp.getEyePos()); ItemStack shieldSlot = StorageHelper.getItemStackInSlot(PlayerSlot.OFFHAND_SLOT); if (shieldSlot.getItem() != Items.SHIELD) { @@ -198,10 +196,10 @@ public float getPriorityInner(AltoClef mod) { startShielding(mod); } } else { - _doingFunkyStuff = true; + doingFunkyStuff = true; //Debug.logMessage("RUNNING AWAY!"); - _runAwayTask = new RunAwayFromCreepersTask(CREEPER_KEEP_DISTANCE); - setTask(_runAwayTask); + runAwayTask = new RunAwayFromCreepersTask(CREEPER_KEEP_DISTANCE); + setTask(runAwayTask); return 50 + blowingUp.getClientFuseTime(1) * 50; } } else { @@ -212,7 +210,7 @@ public float getPriorityInner(AltoClef mod) { // Block projectiles with shield if (!mod.getFoodChain().needsToEat() && mod.getModSettings().isDodgeProjectiles() && isProjectileClose(mod) && (mod.getItemStorage().hasItem(Items.SHIELD) || mod.getItemStorage().hasItemInOffhand(Items.SHIELD)) && - !mod.getEntityTracker().entityFound(PotionEntity.class) && _runAwayTask == null + !mod.getEntityTracker().entityFound(PotionEntity.class) && runAwayTask == null && !mod.getPlayer().getItemCooldownManager().isCoolingDown(offhandItem) && mod.getClientBaritone().getPathingBehavior().isSafeToCancel()) { ItemStack shieldSlot = StorageHelper.getItemStackInSlot(PlayerSlot.OFFHAND_SLOT); @@ -227,21 +225,21 @@ public float getPriorityInner(AltoClef mod) { } } // Dodge projectiles - if (mod.getPlayer().getHealth() <= 10 || _runAwayTask != null || mod.getEntityTracker().entityFound(PotionEntity.class) || + if (mod.getPlayer().getHealth() <= 10 || runAwayTask != null || mod.getEntityTracker().entityFound(PotionEntity.class) || (!mod.getItemStorage().hasItem(Items.SHIELD) && !mod.getItemStorage().hasItemInOffhand(Items.SHIELD))) { if (!mod.getFoodChain().needsToEat() && mod.getModSettings().isDodgeProjectiles() && isProjectileClose(mod)) { - _doingFunkyStuff = true; + doingFunkyStuff = true; //Debug.logMessage("DODGING"); - _runAwayTask = new DodgeProjectilesTask(ARROW_KEEP_DISTANCE_HORIZONTAL, ARROW_KEEP_DISTANCE_VERTICAL); - setTask(_runAwayTask); + runAwayTask = new DodgeProjectilesTask(ARROW_KEEP_DISTANCE_HORIZONTAL, ARROW_KEEP_DISTANCE_VERTICAL); + setTask(runAwayTask); return 65; } } // Dodge all mobs cause we boutta die son if (isInDanger(mod) && !escapeDragonBreath(mod) && !mod.getFoodChain().isShouldStop()) { - if (_targetEntity == null) { - _runAwayTask = new RunAwayFromHostilesTask(DANGER_KEEP_DISTANCE, true); - setTask(_runAwayTask); + if (targetEntity == null) { + runAwayTask = new RunAwayFromHostilesTask(DANGER_KEEP_DISTANCE, true); + setTask(runAwayTask); return 70; } } @@ -249,84 +247,86 @@ public float getPriorityInner(AltoClef mod) { if (mod.getModSettings().shouldDealWithAnnoyingHostiles()) { // Deal with hostiles because they are annoying. List hostiles = mod.getEntityTracker().getHostiles(); - // TODO: I don't think this lock is necessary at all. + hostiles.sort(Comparator.comparingDouble((entity)-> mod.getPlayer().distanceTo(entity))); + SwordItem bestSword = null; - Item[] SWORDS = new Item[]{Items.NETHERITE_SWORD, Items.DIAMOND_SWORD, Items.IRON_SWORD, Items.GOLDEN_SWORD, - Items.STONE_SWORD, Items.WOODEN_SWORD}; + Item[] SWORDS = new Item[]{Items.NETHERITE_SWORD, Items.DIAMOND_SWORD, Items.IRON_SWORD, Items.GOLDEN_SWORD, Items.STONE_SWORD, Items.WOODEN_SWORD}; + for (Item item : SWORDS) { if (mod.getItemStorage().hasItem(item)) { bestSword = (SwordItem) item; + break; } } List toDealWith = new ArrayList<>(); // TODO: I don't think this lock is necessary at all. - if (!hostiles.isEmpty()) { - synchronized (BaritoneHelper.MINECRAFT_LOCK) { - for (Entity hostile : hostiles) { - int annoyingRange = (hostile instanceof SkeletonEntity || hostile instanceof WitchEntity || hostile - instanceof PillagerEntity || hostile instanceof PiglinEntity || hostile instanceof StrayEntity) ? 15 : 8; - boolean isClose = hostile.isInRange(mod.getPlayer(), annoyingRange); - if (isClose) { - isClose = LookHelper.seesPlayer(hostile, mod.getPlayer(), annoyingRange); - } + synchronized (BaritoneHelper.MINECRAFT_LOCK) { + for (Entity hostile : hostiles) { + + // special case for the end + if (hostile instanceof EndermanEntity enderman && enderman.getTarget() != mod.getPlayer() && WorldHelper.getCurrentDimension() == Dimension.END) { + continue; + } - // Give each hostile a timer, if they're close for too long deal with them. - if (isClose) { - if (!_closeAnnoyingEntities.containsKey(hostile)) { - boolean wardenAttacking = hostile instanceof WardenEntity; - boolean witherAttacking = hostile instanceof WitherEntity; - boolean endermanAttacking = hostile instanceof EndermanEntity; - boolean blazeAttacking = hostile instanceof BlazeEntity; - boolean witherSkeletonAttacking = hostile instanceof WitherSkeletonEntity; - boolean hoglinAttacking = hostile instanceof HoglinEntity; - boolean zoglinAttacking = hostile instanceof ZoglinEntity; - boolean piglinBruteAttacking = hostile instanceof PiglinBruteEntity; - boolean vindicatorAttacking = hostile instanceof VindicatorEntity; - if (blazeAttacking || witherSkeletonAttacking || hoglinAttacking || zoglinAttacking || - piglinBruteAttacking || endermanAttacking || witherAttacking || wardenAttacking || vindicatorAttacking) { - if (mod.getPlayer().getHealth() <= 10) { - _closeAnnoyingEntities.put(hostile, new TimerGame(0)); - } else { - _closeAnnoyingEntities.put(hostile, new TimerGame(Float.POSITIVE_INFINITY)); - } + int annoyingRange = (hostile instanceof SkeletonEntity || hostile instanceof WitchEntity || hostile + instanceof PillagerEntity || hostile instanceof PiglinEntity || hostile instanceof StrayEntity) ? 15 : 8; + + boolean isClose = hostile.isInRange(mod.getPlayer(), annoyingRange) && LookHelper.seesPlayer(hostile, mod.getPlayer(), annoyingRange); + + + // Give each hostile a timer, if they're close for too long deal with them. + if (isClose) { + if (!closeAnnoyingEntities.containsKey(hostile)) { + boolean wardenAttacking = hostile instanceof WardenEntity; + boolean witherAttacking = hostile instanceof WitherEntity; + boolean endermanAttacking = hostile instanceof EndermanEntity; + boolean blazeAttacking = hostile instanceof BlazeEntity; + boolean witherSkeletonAttacking = hostile instanceof WitherSkeletonEntity; + boolean hoglinAttacking = hostile instanceof HoglinEntity; + boolean zoglinAttacking = hostile instanceof ZoglinEntity; + boolean piglinBruteAttacking = hostile instanceof PiglinBruteEntity; + boolean vindicatorAttacking = hostile instanceof VindicatorEntity; + if (blazeAttacking || witherSkeletonAttacking || hoglinAttacking || zoglinAttacking || + piglinBruteAttacking || endermanAttacking || witherAttacking || wardenAttacking || vindicatorAttacking) { + if (mod.getPlayer().getHealth() <= 10) { + closeAnnoyingEntities.put(hostile, new TimerGame(0)); } else { - _closeAnnoyingEntities.put(hostile, new TimerGame(0)); + closeAnnoyingEntities.put(hostile, new TimerGame(Float.POSITIVE_INFINITY)); } - _closeAnnoyingEntities.get(hostile).reset(); - } - if (_closeAnnoyingEntities.get(hostile).elapsed()) { - toDealWith.add(hostile); + } else { + closeAnnoyingEntities.put(hostile, new TimerGame(0)); } - } else { - _closeAnnoyingEntities.remove(hostile); + closeAnnoyingEntities.get(hostile).reset(); + } + if (closeAnnoyingEntities.get(hostile).elapsed()) { + toDealWith.add(hostile); } + } else { + closeAnnoyingEntities.remove(hostile); } } } // Clear dead/non existing hostiles List toRemove = new ArrayList<>(); - if (!_closeAnnoyingEntities.keySet().isEmpty()) { - for (Entity check : _closeAnnoyingEntities.keySet()) { - if (!check.isAlive()) { - toRemove.add(check); - } + for (Entity check : closeAnnoyingEntities.keySet()) { + if (!check.isAlive()) { + toRemove.add(check); } } - if (!toRemove.isEmpty()) { - for (Entity remove : toRemove) _closeAnnoyingEntities.remove(remove); - } + + for (Entity remove : toRemove) closeAnnoyingEntities.remove(remove); + int numberOfProblematicEntities = toDealWith.size(); - if (!toDealWith.isEmpty()) { - for (Entity ToDealWith : toDealWith) { - if (ToDealWith.getClass() == SlimeEntity.class || ToDealWith.getClass() == MagmaCubeEntity.class) { - numberOfProblematicEntities = 1; - break; - } + + for (Entity ToDealWith : toDealWith) { + if (ToDealWith.getClass() == SlimeEntity.class || ToDealWith.getClass() == MagmaCubeEntity.class) { + numberOfProblematicEntities = 1; + break; } } if (numberOfProblematicEntities > 0) { @@ -352,39 +352,32 @@ public float getPriorityInner(AltoClef mod) { // full netherite has 12 bonus toughness int armor = mod.getPlayer().getArmor(); float damage = bestSword == null ? 0 : (1 + bestSword.getMaterial().getAttackDamage()); - boolean hasShield = mod.getItemStorage().hasItem(Items.SHIELD) || - mod.getItemStorage().hasItemInOffhand(Items.SHIELD); + boolean hasShield = mod.getItemStorage().hasItem(Items.SHIELD) || mod.getItemStorage().hasItemInOffhand(Items.SHIELD); + int shield = hasShield ? 20 : 0; + int canDealWith = (int) Math.ceil((armor * 3.6 / 20.0) + (damage * 0.8) + (shield)); canDealWith += 1; if (canDealWith > numberOfProblematicEntities) { // We can deal with it. - _runAwayTask = null; - for (Entity ToDealWith : toDealWith) { - if (ToDealWith instanceof SkeletonEntity || ToDealWith instanceof WitchEntity || - ToDealWith instanceof PillagerEntity || ToDealWith instanceof PiglinEntity || - ToDealWith instanceof StrayEntity) { - setTask(new KillEntitiesTask(ToDealWith.getClass())); - return 65; - } - setTask(new KillEntitiesTask(ToDealWith.getClass())); - return 65; - } + runAwayTask = null; + + setTask(new KillEntitiesTask(toDealWith.get(0).getClass())); return 65; } else { // We can't deal with it - _runAwayTask = new RunAwayFromHostilesTask(DANGER_KEEP_DISTANCE, true); - setTask(_runAwayTask); + runAwayTask = new RunAwayFromHostilesTask(DANGER_KEEP_DISTANCE, true); + setTask(runAwayTask); return 80; } } } - // By default if we aren't "immediately" in danger but were running away, keep running away until we're good. - if (_runAwayTask != null && !_runAwayTask.isFinished(mod)) { - setTask(_runAwayTask); - return _cachedLastPriority; + // By default, if we aren't "immediately" in danger but were running away, keep running away until we're good. + if (runAwayTask != null && !runAwayTask.isFinished(mod)) { + setTask(runAwayTask); + return cachedLastPriority; } else { - _runAwayTask = null; + runAwayTask = null; } return 0; } @@ -428,45 +421,42 @@ private void putOutFire(AltoClef mod, BlockPos pos) { private void doForceField(AltoClef mod) { - _killAura.tickStart(); + killAura.tickStart(); // Hit all hostiles close to us. List entities = mod.getEntityTracker().getCloseEntities(); try { - if (!entities.isEmpty()) { - for (Entity entity : entities) { - boolean shouldForce = false; - if (mod.getBehaviour().shouldExcludeFromForcefield(entity)) continue; - if (entity instanceof MobEntity) { - if (EntityHelper.isGenerallyHostileToPlayer(mod, entity)) { - if (LookHelper.seesPlayer(entity, mod.getPlayer(), 10)) { - shouldForce = true; - } - } - } else if (entity instanceof FireballEntity) { - // Ghast ball - shouldForce = true; - } else if (entity instanceof PlayerEntity player && mod.getBehaviour().shouldForceFieldPlayers()) { - if (!player.equals(mod.getPlayer())) { - String name = player.getName().getString(); - if (!mod.getButler().isUserAuthorized(name)) { - shouldForce = true; - } + + for (Entity entity : entities) { + boolean shouldForce = false; + if (mod.getBehaviour().shouldExcludeFromForcefield(entity)) continue; + if (entity instanceof MobEntity) { + if (EntityHelper.isGenerallyHostileToPlayer(mod, entity)) { + if (LookHelper.seesPlayer(entity, mod.getPlayer(), 10)) { + shouldForce = true; } } - if (shouldForce) { - applyForceField(entity); + } else if (entity instanceof FireballEntity) { + // Ghast ball + shouldForce = true; + } else if (entity instanceof PlayerEntity player && mod.getBehaviour().shouldForceFieldPlayers()) { + if (!player.equals(mod.getPlayer())) { + shouldForce = true; } } + if (shouldForce) { + applyForceField(entity); + } } + } catch (Exception e) { e.printStackTrace(); } - _killAura.tickEnd(mod); + killAura.tickEnd(mod); } private void applyForceField(Entity entity) { - _killAura.applyAura(entity); + killAura.applyAura(entity); } private CreeperEntity getClosestFusingCreeper(AltoClef mod) { @@ -474,19 +464,19 @@ private CreeperEntity getClosestFusingCreeper(AltoClef mod) { CreeperEntity target = null; try { List creepers = mod.getEntityTracker().getTrackedEntities(CreeperEntity.class); - if (!creepers.isEmpty()) { - for (CreeperEntity creeper : creepers) { - if (creeper == null) continue; - if (creeper.getClientFuseTime(1) < 0.001) continue; - - // We want to pick the closest creeper, but FIRST pick creepers about to blow - // At max fuse, the cost goes to basically zero. - double safety = getCreeperSafety(mod.getPlayer().getPos(), creeper); - if (safety < worstSafety) { - target = creeper; - } + + for (CreeperEntity creeper : creepers) { + if (creeper == null) continue; + if (creeper.getClientFuseTime(1) < 0.001) continue; + + // We want to pick the closest creeper, but FIRST pick creepers about to blow + // At max fuse, the cost goes to basically zero. + double safety = getCreeperSafety(mod.getPlayer().getPos(), creeper); + if (safety < worstSafety) { + target = creeper; } } + } catch (ConcurrentModificationException | ArrayIndexOutOfBoundsException | NullPointerException e) { // IDK why but these exceptions happen sometimes. It's extremely bizarre and I have no idea why. Debug.logWarning("Weird Exception caught and ignored while scanning for creepers: " + e.getMessage()); @@ -498,56 +488,54 @@ private CreeperEntity getClosestFusingCreeper(AltoClef mod) { private boolean isProjectileClose(AltoClef mod) { List projectiles = mod.getEntityTracker().getProjectiles(); try { - if (!projectiles.isEmpty()) { - for (CachedProjectile projectile : projectiles) { - if (projectile.position.squaredDistanceTo(mod.getPlayer().getPos()) < 150) { - boolean isGhastBall = projectile.projectileType == FireballEntity.class; - if (isGhastBall) { - Optional ghastBall = mod.getEntityTracker().getClosestEntity(FireballEntity.class); - Optional ghast = mod.getEntityTracker().getClosestEntity(GhastEntity.class); - if (ghastBall.isPresent() && ghast.isPresent() && _runAwayTask == null - && mod.getClientBaritone().getPathingBehavior().isSafeToCancel()) { - mod.getClientBaritone().getPathingBehavior().requestPause(); - LookHelper.lookAt(mod, ghast.get().getEyePos()); - } - return false; - // Ignore ghast balls - } - if (projectile.projectileType == DragonFireballEntity.class) { - // Ignore dragon fireballs - return false; + + for (CachedProjectile projectile : projectiles) { + if (projectile.position.squaredDistanceTo(mod.getPlayer().getPos()) < 150) { + boolean isGhastBall = projectile.projectileType == FireballEntity.class; + if (isGhastBall) { + Optional ghastBall = mod.getEntityTracker().getClosestEntity(FireballEntity.class); + Optional ghast = mod.getEntityTracker().getClosestEntity(GhastEntity.class); + if (ghastBall.isPresent() && ghast.isPresent() && runAwayTask == null + && mod.getClientBaritone().getPathingBehavior().isSafeToCancel()) { + mod.getClientBaritone().getPathingBehavior().requestPause(); + LookHelper.lookAt(mod, ghast.get().getEyePos()); } - if (projectile.projectileType == ArrowEntity.class || projectile.projectileType == SpectralArrowEntity.class || projectile.projectileType == SmallFireballEntity.class) { - // check if the velocity of the projectile is going away from us - // oh no fancy math - Vec3d velocity = projectile.velocity; - Vec3d delta = mod.getPlayer().getPos().subtract(projectile.position); - double epsilon = 0.25; - if (abs(velocity.dotProduct(delta)) <= epsilon) { - // Arrow is going away from us, ignore it. - continue; - } + return false; + // Ignore ghast balls + } + if (projectile.projectileType == DragonFireballEntity.class) { + // Ignore dragon fireballs + return false; + } + if (projectile.projectileType == ArrowEntity.class || projectile.projectileType == SpectralArrowEntity.class || projectile.projectileType == SmallFireballEntity.class) { + // check if the projectile is going away from us + // not so fancy math... this should work better than the previous approach (I hope just adding the velocity doesn't cause any issues..) + PlayerEntity player = mod.getPlayer(); + if (player.squaredDistanceTo(projectile.position) < player.squaredDistanceTo(projectile.position.add(projectile.velocity))) { + continue; } + } - Vec3d expectedHit = ProjectileHelper.calculateArrowClosestApproach(projectile, mod.getPlayer()); + Vec3d expectedHit = ProjectileHelper.calculateArrowClosestApproach(projectile, mod.getPlayer()); - Vec3d delta = mod.getPlayer().getPos().subtract(expectedHit); + Vec3d delta = mod.getPlayer().getPos().subtract(expectedHit); - //Debug.logMessage("EXPECTED HIT OFFSET: " + delta + " ( " + projectile.gravity + ")"); + //Debug.logMessage("EXPECTED HIT OFFSET: " + delta + " ( " + projectile.gravity + ")"); - double horizontalDistanceSq = delta.x * delta.x + delta.z * delta.z; - double verticalDistance = abs(delta.y); - if (horizontalDistanceSq < ARROW_KEEP_DISTANCE_HORIZONTAL * ARROW_KEEP_DISTANCE_HORIZONTAL && verticalDistance < ARROW_KEEP_DISTANCE_VERTICAL) { - if (_runAwayTask == null && mod.getClientBaritone().getPathingBehavior().isSafeToCancel()) { - mod.getClientBaritone().getPathingBehavior().requestPause(); - LookHelper.lookAt(mod, projectile.position); - } - return true; + double horizontalDistanceSq = delta.x * delta.x + delta.z * delta.z; + double verticalDistance = abs(delta.y); + if (horizontalDistanceSq < ARROW_KEEP_DISTANCE_HORIZONTAL * ARROW_KEEP_DISTANCE_HORIZONTAL && verticalDistance < ARROW_KEEP_DISTANCE_VERTICAL) { + if (runAwayTask == null && mod.getClientBaritone().getPathingBehavior().isSafeToCancel()) { + mod.getClientBaritone().getPathingBehavior().requestPause(); + LookHelper.lookAt(mod, projectile.position); } + return true; } } } - } catch (ConcurrentModificationException ignored) { + + } catch (ConcurrentModificationException e) { + Debug.logWarning(e.getMessage()); } return false; } @@ -620,20 +608,20 @@ private boolean isInDanger(AltoClef mod) { (mod.getPlayer().hasStatusEffect(StatusEffects.POISON) && witch.isEmpty())) { return true; } - if (isVulnurable(mod)) { + if (isVulnerable(mod)) { // If hostile mobs are nearby... try { ClientPlayerEntity player = mod.getPlayer(); List hostiles = mod.getEntityTracker().getHostiles(); - if (!hostiles.isEmpty()) { - synchronized (BaritoneHelper.MINECRAFT_LOCK) { - for (Entity entity : hostiles) { - if (entity.isInRange(player, SAFE_KEEP_DISTANCE) && !mod.getBehaviour().shouldExcludeFromForcefield(entity) && EntityHelper.isAngryAtPlayer(mod, entity)) { - return true; - } + + synchronized (BaritoneHelper.MINECRAFT_LOCK) { + for (Entity entity : hostiles) { + if (entity.isInRange(player, SAFE_KEEP_DISTANCE) && !mod.getBehaviour().shouldExcludeFromForcefield(entity) && EntityHelper.isAngryAtPlayer(mod, entity)) { + return true; } } } + } catch (Exception e) { Debug.logWarning("Weird multithread exception. Will fix later."); } @@ -641,7 +629,9 @@ private boolean isInDanger(AltoClef mod) { return false; } - private boolean isVulnurable(AltoClef mod) { + ; + + private boolean isVulnerable(AltoClef mod) { int armor = mod.getPlayer().getArmor(); float health = mod.getPlayer().getHealth(); if (armor <= 15 && health < 3) return true; @@ -650,27 +640,27 @@ private boolean isVulnurable(AltoClef mod) { } public void setTargetEntity(Entity entity) { - _targetEntity = entity; + targetEntity = entity; } public void resetTargetEntity() { - _targetEntity = null; + targetEntity = null; } public void setForceFieldRange(double range) { - _killAura.setRange(range); + killAura.setRange(range); } public void resetForceField() { - _killAura.setRange(Double.POSITIVE_INFINITY); + killAura.setRange(Double.POSITIVE_INFINITY); } public boolean isDoingAcrobatics() { - return _doingFunkyStuff; + return doingFunkyStuff; } public boolean isPuttingOutFire() { - return _wasPuttingOutFire; + return wasPuttingOutFire; } @Override diff --git a/src/main/java/adris/altoclef/chains/PlayerInteractionFixChain.java b/src/main/java/adris/altoclef/chains/PlayerInteractionFixChain.java index 5a49219b..ceb7a839 100644 --- a/src/main/java/adris/altoclef/chains/PlayerInteractionFixChain.java +++ b/src/main/java/adris/altoclef/chains/PlayerInteractionFixChain.java @@ -12,7 +12,9 @@ import adris.altoclef.util.time.TimerGame; import baritone.api.utils.Rotation; import baritone.api.utils.input.Input; +import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.ChatScreen; import net.minecraft.client.gui.screen.DeathScreen; @@ -20,6 +22,8 @@ import net.minecraft.client.gui.screen.Screen; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.item.PickaxeItem; import net.minecraft.screen.slot.SlotActionType; import java.util.Optional; diff --git a/src/main/java/adris/altoclef/chains/SingleTaskChain.java b/src/main/java/adris/altoclef/chains/SingleTaskChain.java index ce9d00ac..9f7ca250 100644 --- a/src/main/java/adris/altoclef/chains/SingleTaskChain.java +++ b/src/main/java/adris/altoclef/chains/SingleTaskChain.java @@ -9,50 +9,49 @@ public abstract class SingleTaskChain extends TaskChain { - private final Stopwatch _taskStopwatch = new Stopwatch(); - protected Task _mainTask = null; - private boolean _interrupted = false; + protected Task mainTask = null; + private boolean interrupted = false; - private AltoClef _mod; + private final AltoClef mod; public SingleTaskChain(TaskRunner runner) { super(runner); - _mod = runner.getMod(); + mod = runner.getMod(); } @Override protected void onTick(AltoClef mod) { if (!isActive()) return; - if (_interrupted) { - _interrupted = false; - if (_mainTask != null) { - _mainTask.reset(); + if (interrupted) { + interrupted = false; + if (mainTask != null) { + mainTask.reset(); } } - if (_mainTask != null) { - if ((_mainTask.isFinished(mod)) || _mainTask.stopped()) { + if (mainTask != null) { + if ((mainTask.isFinished(mod)) || mainTask.stopped()) { onTaskFinish(mod); } else { - _mainTask.tick(mod, this); + mainTask.tick(mod, this); } } } protected void onStop(AltoClef mod) { - if (isActive() && _mainTask != null) { - _mainTask.stop(mod); - _mainTask = null; + if (isActive() && mainTask != null) { + mainTask.stop(mod); + mainTask = null; } } public void setTask(Task task) { - if (_mainTask == null || !_mainTask.equals(task)) { - if (_mainTask != null) { - _mainTask.stop(_mod, task); + if (mainTask == null || !mainTask.equals(task)) { + if (mainTask != null) { + mainTask.stop(mod, task); } - _mainTask = task; + mainTask = task; if (task != null) task.reset(); } } @@ -60,7 +59,7 @@ public void setTask(Task task) { @Override public boolean isActive() { - return _mainTask != null; + return mainTask != null; } protected abstract void onTaskFinish(AltoClef mod); @@ -71,17 +70,17 @@ public void onInterrupt(AltoClef mod, TaskChain other) { Debug.logInternal("Chain Interrupted: " + this + " by " + other); } // Stop our task. When we're started up again, let our task know we need to run. - _interrupted = true; - if (_mainTask != null && _mainTask.isActive()) { - _mainTask.interrupt(mod, null); + interrupted = true; + if (mainTask != null && mainTask.isActive()) { + mainTask.interrupt(mod, null); } } protected boolean isCurrentlyRunning(AltoClef mod) { - return !_interrupted && _mainTask.isActive() && !_mainTask.isFinished(mod); + return !interrupted && mainTask.isActive() && !mainTask.isFinished(mod); } public Task getCurrentTask() { - return _mainTask; + return mainTask; } } diff --git a/src/main/java/adris/altoclef/chains/UnstuckChain.java b/src/main/java/adris/altoclef/chains/UnstuckChain.java new file mode 100644 index 00000000..de644b83 --- /dev/null +++ b/src/main/java/adris/altoclef/chains/UnstuckChain.java @@ -0,0 +1,101 @@ +package adris.altoclef.chains; + +import adris.altoclef.AltoClef; +import adris.altoclef.tasks.movement.SafeRandomShimmyTask; +import adris.altoclef.tasksystem.TaskRunner; +import adris.altoclef.util.helpers.StorageHelper; +import adris.altoclef.util.time.TimerGame; +import baritone.api.utils.input.Input; +import net.minecraft.block.Blocks; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.math.Vec3d; + +import java.util.LinkedList; + +public class UnstuckChain extends SingleTaskChain { + + private boolean isProbablyStuck = false; + private LinkedList posHistory = new LinkedList<>(); + private TimerGame forceTimer = new TimerGame(2); + + public UnstuckChain(TaskRunner runner) { + super(runner); + } + + + private void checkStuckInWater(AltoClef mod) { + // is not in water + if (!mod.getWorld().getBlockState(mod.getPlayer().getSteppingPos()).getBlock().equals(Blocks.WATER) + && !mod.getWorld().getBlockState(mod.getPlayer().getSteppingPos().down()).getBlock().equals(Blocks.WATER)) + return; + + // do NOT do anything if underwater + if (mod.getPlayer().getAir() < mod.getPlayer().getMaxAir()) { + posHistory.clear(); + return; + } + + if (posHistory.size() < 100) return; + + Vec3d pos1 = posHistory.get(0); + for (int i = 1; i < 100; i++) { + Vec3d pos2 = posHistory.get(i); + if (Math.abs(pos1.getX() - pos2.getX()) > 0.75 || Math.abs(pos1.getZ() - pos2.getZ()) > 0.75 || pos1.equals(pos2)) { + return; + } + } + + isProbablyStuck = true; + // setTask(new SafeRandomShimmyTask()); + mod.getInputControls().tryPress(Input.CLICK_LEFT); + } + + @Override + public float getPriority(AltoClef mod) { + isProbablyStuck = false; + + if (!AltoClef.inGame() || MinecraftClient.getInstance().isPaused() || !mod.getUserTaskChain().isActive()) + return Float.NEGATIVE_INFINITY; + + if (StorageHelper.isBlastFurnaceOpen() || StorageHelper.isSmokerOpen() || StorageHelper.isChestOpen() || StorageHelper.isBigCraftingOpen()) { + return Float.NEGATIVE_INFINITY; + } + + + PlayerEntity player = mod.getPlayer(); + posHistory.addFirst(player.getPos()); + if (posHistory.size() > 500) { + posHistory.removeLast(); + } + if (posHistory.size() < 10) return Float.NEGATIVE_INFINITY; + + checkStuckInWater(mod); + + + if (isProbablyStuck || !forceTimer.elapsed()) { + if (isProbablyStuck && forceTimer.elapsed()) { + forceTimer.reset(); + } else { + posHistory.clear(); + } + return 55; + } + return Float.NEGATIVE_INFINITY; + } + + @Override + public boolean isActive() { + return true; + } + + @Override + protected void onTaskFinish(AltoClef mod) { + + } + + @Override + public String getName() { + return "Unstuck Chain"; + } +} diff --git a/src/main/java/adris/altoclef/chains/UserTaskChain.java b/src/main/java/adris/altoclef/chains/UserTaskChain.java index be1a07e0..af20dff6 100644 --- a/src/main/java/adris/altoclef/chains/UserTaskChain.java +++ b/src/main/java/adris/altoclef/chains/UserTaskChain.java @@ -10,7 +10,6 @@ // A task chain that runs a user defined task at the same priority. // This basically replaces our old Task Runner. -@SuppressWarnings("ALL") public class UserTaskChain extends SingleTaskChain { private final Stopwatch _taskStopwatch = new Stopwatch(); @@ -38,7 +37,7 @@ private static String prettyPrintTimeDuration(double seconds) { if (minutes != 0) { result += (minutes % 60) + " minutes "; } - if (!result.equals("")) { + if (!result.isEmpty()) { result += "and "; } result += String.format("%.3f", (seconds % 60)); @@ -49,13 +48,13 @@ private static String prettyPrintTimeDuration(double seconds) { protected void onTick(AltoClef mod) { // Pause if we're not loaded into a world. - if (!mod.inGame()) return; + if (!AltoClef.inGame()) return; super.onTick(mod); } public void cancel(AltoClef mod) { - if (_mainTask != null && _mainTask.isActive()) { + if (mainTask != null && mainTask.isActive()) { stop(mod); onTaskFinish(mod); } @@ -100,14 +99,13 @@ protected void onTaskFinish(AltoClef mod) { mod.getClientBaritone().getInputOverrideHandler().clearAllKeys(); } double seconds = _taskStopwatch.time(); - Task oldTask = _mainTask; - _mainTask = null; + Task oldTask = mainTask; + mainTask = null; if (_currentOnFinish != null) { - //noinspection unchecked _currentOnFinish.run(); } // our `onFinish` might have triggered more tasks. - boolean actuallyDone = _mainTask == null; + boolean actuallyDone = mainTask == null; if (actuallyDone) { if (!_runningIdleTask) { Debug.logMessage("User task FINISHED. Took %s seconds.", prettyPrintTimeDuration(seconds)); diff --git a/src/main/java/adris/altoclef/chains/WorldSurvivalChain.java b/src/main/java/adris/altoclef/chains/WorldSurvivalChain.java index 097b71d7..d32c4a72 100644 --- a/src/main/java/adris/altoclef/chains/WorldSurvivalChain.java +++ b/src/main/java/adris/altoclef/chains/WorldSurvivalChain.java @@ -51,7 +51,7 @@ public float getPriority(AltoClef mod) { // Lava Escape if (isInLavaOhShit(mod) && mod.getBehaviour().shouldEscapeLava()) { - setTask(new EscapeFromLavaTask()); + setTask(new EscapeFromLavaTask(mod)); return 100; } @@ -63,7 +63,7 @@ public float getPriority(AltoClef mod) { // Extinguish with water if (mod.getModSettings().shouldExtinguishSelfWithWater()) { - if (!(_mainTask instanceof EscapeFromLavaTask && isCurrentlyRunning(mod)) && mod.getPlayer().isOnFire() && !mod.getPlayer().hasStatusEffect(StatusEffects.FIRE_RESISTANCE) && !mod.getWorld().getDimension().ultrawarm()) { + if (!(mainTask instanceof EscapeFromLavaTask && isCurrentlyRunning(mod)) && mod.getPlayer().isOnFire() && !mod.getPlayer().hasStatusEffect(StatusEffects.FIRE_RESISTANCE) && !mod.getWorld().getDimension().ultrawarm()) { // Extinguish ourselves if (mod.getItemStorage().hasItem(Items.WATER_BUCKET)) { BlockPos targetWaterPos = mod.getPlayer().getBlockPos(); @@ -84,7 +84,7 @@ public float getPriority(AltoClef mod) { } setTask(new DoToClosestBlockTask(GetToBlockTask::new, Blocks.WATER)); return 90; - } else if (mod.getItemStorage().hasItem(Items.BUCKET) && _extinguishWaterPosition != null && mod.getBlockTracker().blockIsValid(_extinguishWaterPosition, Blocks.WATER)) { + } else if (mod.getItemStorage().hasItem(Items.BUCKET) && _extinguishWaterPosition != null && mod.getBlockScanner().isBlockAtPosition(_extinguishWaterPosition, Blocks.WATER)) { // Pick up the water setTask(new InteractWithBlockTask(new ItemTarget(Items.BUCKET, 1), Direction.UP, _extinguishWaterPosition.down(), true)); return 60; diff --git a/src/main/java/adris/altoclef/commands/BlockScanner.java b/src/main/java/adris/altoclef/commands/BlockScanner.java new file mode 100644 index 00000000..94fb767f --- /dev/null +++ b/src/main/java/adris/altoclef/commands/BlockScanner.java @@ -0,0 +1,447 @@ +package adris.altoclef.commands; + +import adris.altoclef.AltoClef; +import adris.altoclef.Debug; +import adris.altoclef.eventbus.EventBus; +import adris.altoclef.eventbus.events.BlockPlaceEvent; +import adris.altoclef.trackers.blacklisting.WorldLocateBlacklist; +import adris.altoclef.util.Dimension; +import adris.altoclef.util.helpers.BaritoneHelper; +import adris.altoclef.util.helpers.WorldHelper; +import adris.altoclef.util.time.TimerGame; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraft.world.chunk.WorldChunk; + +import java.util.*; +import java.util.function.Predicate; + +public class BlockScanner { + + private static boolean LOG = false; + private static final int RESCAN_TICK_DELAY = 4 * 20; + private static final int CACHED_POSITIONS_PER_BLOCK = 40; + + private final AltoClef mod; + private final HashMap scannedChunks = new HashMap<>(); + private final TimerGame rescanTimer = new TimerGame(1); + private final HashMap> cachedCloseBlocks = new HashMap<>(); + private final HashMap> newBlocks = new HashMap<>(); + private final WorldLocateBlacklist blacklist = new WorldLocateBlacklist(); + private HashMap> cachedBlocks = new HashMap<>(); + private boolean scanning = false; + private boolean forceStop = false; + private Dimension scanDimension = Dimension.OVERWORLD; + private World scanWorld = null; + + + public BlockScanner(AltoClef mod) { + this.mod = mod; + + EventBus.subscribe(BlockPlaceEvent.class, evt -> addBlock(evt.blockState.getBlock(), evt.blockPos)); + } + + + public void addBlock(Block block, BlockPos pos) { + if (!isBlockAtPosition(pos, block)) { + Debug.logInternal("INVALID SET: " + block + " " + pos); + return; + } + + if (cachedCloseBlocks.containsKey(block)) { + cachedCloseBlocks.get(block).add(pos); + } else { + HashSet set = new HashSet<>(); + set.add(pos); + + cachedCloseBlocks.put(block, set); + } + } + + + public void requestBlockUnreachable(BlockPos pos, int allowedFailures) { + blacklist.blackListItem(mod, pos, allowedFailures); + } + + //TODO replace four with config + public void requestBlockUnreachable(BlockPos pos) { + blacklist.blackListItem(mod, pos, 4); + } + + + public boolean isUnreachable(BlockPos pos) { + return blacklist.unreachable(pos); + } + + public List getKnownLocations(Block... blocks) { + List locations = new LinkedList<>(); + + for (Block block : blocks) { + if (!cachedCloseBlocks.containsKey(block)) continue; + + locations.addAll(cachedCloseBlocks.get(block)); + } + locations.removeIf(this::isUnreachable); + + return locations; + } + + /** + * Scans a radius for the closest block of a given type . + * + * @param pos The center of this radius + * @param range Radius to scan for + * @param blocks What blocks to check for + */ + public Optional getNearestWithinRange(Vec3d pos, double range, Block... blocks) { + Optional nearest = getNearestBlock(pos, blocks); + + if (nearest.isEmpty() || nearest.get().isWithinDistance(pos, range)) return nearest; + + return Optional.empty(); + } + + public Optional getNearestWithinRange(BlockPos pos, double range, Block... blocks) { + return getNearestWithinRange(new Vec3d(pos.getX(), pos.getY(), pos.getZ()), range, blocks); + } + + + public boolean anyFound(Block... blocks) { + return anyFound((block) -> true, blocks); + } + + + public boolean anyFound(Predicate isValidTest, Block... blocks) { + for (Block block : blocks) { + if (!cachedCloseBlocks.containsKey(block)) continue; + + for (BlockPos pos : cachedCloseBlocks.get(block)) { + if (isValidTest.test(pos) && mod.getWorld().getBlockState(pos).getBlock().equals(block) && !this.isUnreachable(pos)) + return true; + } + } + + return false; + } + + public Optional getNearestBlock(Block... blocks) { + // Add juuust a little, to prevent digging down all the time/bias towards blocks BELOW the player + return getNearestBlock(mod.getPlayer().getPos().add(0, 0.6f, 0), blocks); + } + + public Optional getNearestBlock(Vec3d pos, Block... blocks) { + return getNearestBlock(pos, p -> true, blocks); + } + + public Optional getNearestBlock(Predicate isValidTest, Block... blocks) { + return getNearestBlock(mod.getPlayer().getPos().add(0, 0.6f, 0), isValidTest, blocks); + } + + public Optional getNearestBlock(Vec3d pos, Predicate isValidTest, Block... blocks) { + Optional closest = Optional.empty(); + + for (Block block : blocks) { + Optional p = getNearestBlock(block, isValidTest, pos); + + if (p.isPresent()) { + if (closest.isEmpty()) closest = p; + else { + if (BaritoneHelper.calculateGenericHeuristic(pos, WorldHelper.toVec3d(closest.get())) > BaritoneHelper.calculateGenericHeuristic(pos, WorldHelper.toVec3d(p.get()))) { + closest = p; + } + } + } + } + + return closest; + } + + public Optional getNearestBlock(Block block, Vec3d fromPos) { + return getNearestBlock(block, (pos) -> true, fromPos); + } + + public Optional getNearestBlock(Block block, Predicate isValidTest, Vec3d fromPos) { + BlockPos pos = null; + double nearest = Double.POSITIVE_INFINITY; + + if (!cachedCloseBlocks.containsKey(block)) { + return Optional.empty(); + } + + for (BlockPos p : cachedCloseBlocks.get(block)) { + //ensure the block is there (can change upon rescan) + if (!mod.getWorld().getBlockState(p).getBlock().equals(block)) continue; + if (!isValidTest.test(p) || isUnreachable(p)) continue; + + double dist = BaritoneHelper.calculateGenericHeuristic(fromPos, WorldHelper.toVec3d(p)); + + if (dist < nearest) { + nearest = dist; + pos = p; + } + } + + return pos != null ? Optional.of(pos) : Optional.empty(); + } + + public boolean anyFoundWithinDistance(double distance, Block... blocks) { + return anyFoundWithinDistance(mod.getPlayer().getPos().add(0, 0.6f, 0), distance, blocks); + } + + public boolean anyFoundWithinDistance(Vec3d pos, double distance, Block... blocks) { + Optional blockPos = getNearestBlock(blocks); + return blockPos.map(value -> value.isWithinDistance(pos, distance)).orElse(false); + } + + public double distanceToClosest(Block... blocks) { + return distanceToClosest(mod.getPlayer().getPos().add(0, 0.6f, 0), blocks); + } + + public double distanceToClosest(Vec3d pos, Block... blocks) { + Optional blockPos = getNearestBlock(blocks); + return blockPos.map(value -> Math.sqrt(value.getSquaredDistance(pos))).orElse(Double.POSITIVE_INFINITY); + } + + // Checks if 'pos' one of 'blocks' block + // Returns false if incorrect or undetermined/unsure + public boolean isBlockAtPosition(BlockPos pos, Block... blocks) { + if (isUnreachable(pos)) { + return false; + } + + if (!mod.getChunkTracker().isChunkLoaded(pos)) { + return false; + } + + ClientWorld world = MinecraftClient.getInstance().world; + if (world == null) { + return false; + } + try { + for (Block block : blocks) { + if (world.isAir(pos) && WorldHelper.isAir(block)) { + return true; + } + BlockState state = world.getBlockState(pos); + if (state.getBlock() == block) { + return true; + } + } + return false; + } catch (NullPointerException e) { + // Probably out of chunk. This means we can't judge its state. + return false; + } + } + + public void reset() { + cachedCloseBlocks.clear(); + newBlocks.clear(); + scannedChunks.clear(); + rescanTimer.forceElapse(); + blacklist.clear(); + forceStop = true; + } + + public void tick() { + if (mod.getWorld() == null || mod.getPlayer() == null) return; + //be maximally aware of the closest blocks around you + scanCloseBlocks(); + if (!rescanTimer.elapsed() || scanning) return; + + if (scanDimension != WorldHelper.getCurrentDimension() || mod.getWorld() != scanWorld) { + if (LOG) { + mod.log("BlockScanner: new dimension or world detected, resetting data!"); + } + reset(); + scanWorld = mod.getWorld(); + scanDimension = WorldHelper.getCurrentDimension(); + } + + cachedBlocks = new HashMap<>(newBlocks.size()); + for (Map.Entry> entry : newBlocks.entrySet()) { + cachedBlocks.put(entry.getKey(), (HashSet) entry.getValue().clone()); + } + + if (LOG) { + mod.log("Updating BlockScanner.. size: " + cachedCloseBlocks.size() + " : " + cachedBlocks.size()); + } + + scanning = true; + forceStop = false; + new Thread(() -> { + try { + rescan(Integer.MAX_VALUE, Integer.MAX_VALUE); + } catch (Exception e) { + scanning = false; + rescanTimer.reset(); + e.printStackTrace(); + } + }).start(); + } + + private void scanCloseBlocks() { + for (Map.Entry> entry : cachedBlocks.entrySet()) { + if (!cachedCloseBlocks.containsKey(entry.getKey())) { + cachedCloseBlocks.put(entry.getKey(), new HashSet<>()); + } + cachedCloseBlocks.get(entry.getKey()).clear(); + + cachedCloseBlocks.get(entry.getKey()).addAll(entry.getValue()); + + } + + BlockPos pos = mod.getPlayer().getBlockPos(); + World world = mod.getPlayer().getWorld(); + + for (int x = pos.getX() - 8; x <= pos.getX() + 8; x++) { + for (int y = pos.getY() - 8; y < pos.getY() + 8; y++) { + for (int z = pos.getZ() - 8; z <= pos.getZ() + 8; z++) { + BlockPos p = new BlockPos(x, y, z); + BlockState state = world.getBlockState(p); + if (world.getBlockState(p).isAir()) continue; + + Block block = state.getBlock(); + + if (cachedCloseBlocks.containsKey(block)) { + cachedCloseBlocks.get(block).add(p); + } else { + HashSet set = new HashSet<>(); + set.add(p); + cachedCloseBlocks.put(block, set); + } + } + } + } + } + + private void rescan(int maxCount, int cutOffRadius) { + long ms = System.currentTimeMillis(); + + ChunkPos playerChunkPos = mod.getPlayer().getChunkPos(); + Vec3d playerPos = mod.getPlayer().getPos(); + + HashSet visited = new HashSet<>(); + Queue queue = new ArrayDeque<>(); + queue.add(new Node(playerChunkPos, 0)); + + while (!queue.isEmpty() && visited.size() < maxCount && !forceStop) { + Node node = queue.poll(); + + if (node.distance > cutOffRadius || visited.contains(node.pos) || !mod.getWorld().getChunkManager().isChunkLoaded(node.pos.x, node.pos.z)) + continue; + + boolean isPriorityChunk = getChunkDist(node.pos, playerChunkPos) <= 2; + if (!isPriorityChunk && scannedChunks.containsKey(node.pos) && mod.getWorld().getTime() - scannedChunks.get(node.pos) < RESCAN_TICK_DELAY) + continue; + + visited.add(node.pos); + scanChunk(node.pos, playerChunkPos); + + queue.add(new Node(new ChunkPos(node.pos.x + 1, node.pos.z + 1), node.distance + 1)); + queue.add(new Node(new ChunkPos(node.pos.x - 1, node.pos.z + 1), node.distance + 1)); + queue.add(new Node(new ChunkPos(node.pos.x - 1, node.pos.z - 1), node.distance + 1)); + queue.add(new Node(new ChunkPos(node.pos.x + 1, node.pos.z - 1), node.distance + 1)); + } + if (forceStop) { + forceStop = false; + return; + } + + for (Iterator iterator = scannedChunks.keySet().iterator(); iterator.hasNext(); ) { + ChunkPos pos = iterator.next(); + int distance = getChunkDist(pos, playerChunkPos); + + if (distance > cutOffRadius) { + iterator.remove(); + } + } + + for (HashSet set : newBlocks.values()) { + if (set.size() < CACHED_POSITIONS_PER_BLOCK) { + continue; + } + + getFirstFewPositions(set, playerPos); + } + + if (LOG) { + mod.log("Rescanned in: " + (System.currentTimeMillis() - ms) + " ms; visited: " + visited.size() + " chunks"); + } + rescanTimer.reset(); + scanning = false; + } + + private int getChunkDist(ChunkPos pos1, ChunkPos pos2) { + return Math.abs(pos1.x - pos2.x) + Math.abs(pos1.z - pos2.z); + } + + + //TODO rename + private void getFirstFewPositions(HashSet set, Vec3d playerPos) { + Queue queue = new PriorityQueue<>(Comparator.comparingDouble((pos) -> -BaritoneHelper.calculateGenericHeuristic(playerPos, WorldHelper.toVec3d(pos)))); + + for (BlockPos pos : set) { + queue.add(pos); + + if (queue.size() > CACHED_POSITIONS_PER_BLOCK) { + queue.poll(); + } + } + + set.clear(); + + for (int i = 0; i < CACHED_POSITIONS_PER_BLOCK; i++) { + set.add(queue.poll()); + } + } + + /** + * scans a chunk and adds block positions corresponding to a specific block in a list + * + * @param chunkPos position of the scanned chunk + */ + private void scanChunk(ChunkPos chunkPos, ChunkPos playerChunkPos) { + World world = mod.getWorld(); + WorldChunk chunk = mod.getWorld().getChunk(chunkPos.x,chunkPos.z); + scannedChunks.put(chunkPos, world.getTime()); + + boolean isPriorityChunk = getChunkDist(chunkPos, playerChunkPos) <= 2; + + for (int x = chunkPos.getStartX(); x <= chunkPos.getEndX(); x++) { + for (int y = world.getBottomY(); y < world.getTopY(); y++) { + for (int z = chunkPos.getStartZ(); z <= chunkPos.getEndZ(); z++) { + BlockPos p = new BlockPos(x, y, z); + if (this.isUnreachable(p) || world.isOutOfHeightLimit(p)) continue; + + BlockState state = chunk.getBlockState(p); + if (state.isAir()) continue; + + Block block = state.getBlock(); + if (newBlocks.containsKey(block)) { + HashSet set = newBlocks.get(block); + + if ((set.size() > CACHED_POSITIONS_PER_BLOCK * 750 && !isPriorityChunk)) continue; + + set.add(p); + } else { + HashSet set = new HashSet<>(); + set.add(p); + newBlocks.put(block, set); + } + } + } + } + } + + private record Node(ChunkPos pos, int distance) { + } + + +} diff --git a/src/main/java/adris/altoclef/commands/CoordsCommand.java b/src/main/java/adris/altoclef/commands/CoordsCommand.java deleted file mode 100644 index 14b04e7d..00000000 --- a/src/main/java/adris/altoclef/commands/CoordsCommand.java +++ /dev/null @@ -1,18 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.commandsystem.ArgParser; -import adris.altoclef.commandsystem.Command; -import adris.altoclef.util.helpers.WorldHelper; - -public class CoordsCommand extends Command { - public CoordsCommand() { - super("coords", "Get the bot's current coordinates"); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) { - mod.log("CURRENT COORDINATES: " + mod.getPlayer().getBlockPos().toShortString() + " (Current dimension: " + WorldHelper.getCurrentDimension() + ")"); - finish(); - } -} diff --git a/src/main/java/adris/altoclef/commands/CoverWithBlocksCommand.java b/src/main/java/adris/altoclef/commands/CoverWithBlocksCommand.java deleted file mode 100644 index fb9a549b..00000000 --- a/src/main/java/adris/altoclef/commands/CoverWithBlocksCommand.java +++ /dev/null @@ -1,18 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.commandsystem.ArgParser; -import adris.altoclef.commandsystem.Command; -import adris.altoclef.commandsystem.CommandException; -import adris.altoclef.tasks.construction.CoverWithBlocksTask; - -public class CoverWithBlocksCommand extends Command { - public CoverWithBlocksCommand() { - super("coverwithblocks", "Cover nether lava with blocks"); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - mod.runUserTask(new CoverWithBlocksTask(), this::finish); - } -} diff --git a/src/main/java/adris/altoclef/commands/CoverWithSandCommand.java b/src/main/java/adris/altoclef/commands/CoverWithSandCommand.java deleted file mode 100644 index 60b6d61b..00000000 --- a/src/main/java/adris/altoclef/commands/CoverWithSandCommand.java +++ /dev/null @@ -1,18 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.commandsystem.ArgParser; -import adris.altoclef.commandsystem.Command; -import adris.altoclef.commandsystem.CommandException; -import adris.altoclef.tasks.construction.CoverWithSandTask; - -public class CoverWithSandCommand extends Command { - public CoverWithSandCommand() { - super("coverwithsand", "Cover nether lava with sand"); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - mod.runUserTask(new CoverWithSandTask(), this::finish); - } -} diff --git a/src/main/java/adris/altoclef/commands/CustomCommand.java b/src/main/java/adris/altoclef/commands/CustomCommand.java deleted file mode 100644 index 3af5f0c6..00000000 --- a/src/main/java/adris/altoclef/commands/CustomCommand.java +++ /dev/null @@ -1,69 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.commandsystem.Arg; -import adris.altoclef.commandsystem.ArgParser; -import adris.altoclef.commandsystem.Command; -import adris.altoclef.commandsystem.CommandException; -import adris.altoclef.util.helpers.ConfigHelper; - -import java.util.Arrays; - -public class CustomCommand extends Command { - private static CustomTaskConfig _ctc; - - static { - ConfigHelper.loadConfig("configs/CustomTasks.json", CustomTaskConfig::new, CustomTaskConfig.class, newConfig -> _ctc = newConfig); - } - - - public CustomCommand() throws CommandException { - super(_ctc.prefix, "does a custom action", new Arg(String.class, "task name")); - } - - public static CustomTaskConfig getConfig() { - return _ctc; - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - CustomTaskConfig dupliate = _ctc; - - String customCommand = parser.get(String.class); - - StringBuilder commandToExecute = new StringBuilder(); - int commandIndex = -1; - for (int i = 0; i < _ctc.customTasks.length; i++) { - if (_ctc.customTasks[i].name.equalsIgnoreCase(customCommand)) { - commandIndex = i; - break; - } - } - if (commandIndex > -1) { - for (int i = 0; i < _ctc.customTasks[commandIndex].tasks.length; i++) { - if (i > 0) { - commandToExecute.append(";"); - } - commandToExecute.append(_ctc.customTasks[commandIndex].tasks[i].command).append(" "); - if (_ctc.customTasks[commandIndex].tasks[i].command.equals("get") || _ctc.customTasks[commandIndex].tasks[i].command.equals("equip")) { - //parameters have two inside arrays so we need to be careful here - - commandToExecute.append("["); - for (int j = 0; j < _ctc.customTasks[commandIndex].tasks[i].parameters.length; j++) { - commandToExecute.append(Arrays.toString(_ctc.customTasks[commandIndex].tasks[i].parameters[j]).replaceAll("\\[", "").replaceAll("]", "").replaceAll(",", "")); - if (j < _ctc.customTasks[commandIndex].tasks[i].parameters.length - 1) { - commandToExecute.append("?"); - - } - } - commandToExecute.append("]"); - } else { - commandToExecute.append(Arrays.toString(_ctc.customTasks[commandIndex].tasks[i].parameters[0]).replaceAll("\\[", "").replaceAll("]", "")); - } - } - AltoClef.getCommandExecutor().execute(mod.getModSettings().getCommandPrefix() + commandToExecute.toString().replaceAll(",", "").replaceAll("\\?", ",")); - } else { - - } - } -} diff --git a/src/main/java/adris/altoclef/commands/CustomTaskConfig.java b/src/main/java/adris/altoclef/commands/CustomTaskConfig.java deleted file mode 100644 index 5c3c3c72..00000000 --- a/src/main/java/adris/altoclef/commands/CustomTaskConfig.java +++ /dev/null @@ -1,17 +0,0 @@ -package adris.altoclef.commands; - -class CustomTaskConfig { - public String prefix = "custom2"; - public CustomTaskEntry[] customTasks = new CustomTaskEntry[0]; - - static class CustomTaskEntry { - public String name; - public String description; - public CustomSubTaskEntry[] tasks; - - static class CustomSubTaskEntry { - public String command; - public String[][] parameters; - } - } -} diff --git a/src/main/java/adris/altoclef/commands/DepositCommand.java b/src/main/java/adris/altoclef/commands/DepositCommand.java deleted file mode 100644 index 0cae1b20..00000000 --- a/src/main/java/adris/altoclef/commands/DepositCommand.java +++ /dev/null @@ -1,46 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.commandsystem.*; -import adris.altoclef.tasks.container.StoreInAnyContainerTask; -import adris.altoclef.util.ItemTarget; -import adris.altoclef.util.helpers.StorageHelper; -import adris.altoclef.util.slots.PlayerSlot; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.ToolItem; -import org.apache.commons.lang3.ArrayUtils; - -public class DepositCommand extends Command { - public DepositCommand() throws CommandException { - super("deposit", "Deposit ALL of our items", new Arg(ItemList.class, "items (empty for ALL non gear items)", null, 0, false)); - } - - public static ItemTarget[] getAllNonEquippedOrToolItemsAsTarget(AltoClef mod) { - return StorageHelper.getAllInventoryItemsAsTargets(slot -> { - // Ignore armor - if (ArrayUtils.contains(PlayerSlot.ARMOR_SLOTS, slot)) - return false; - ItemStack stack = StorageHelper.getItemStackInSlot(slot); - // Ignore tools - if (!stack.isEmpty()) { - Item item = stack.getItem(); - return !(item instanceof ToolItem); - } - return false; - }); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - ItemList itemList = parser.get(ItemList.class); - ItemTarget[] items; - if (itemList == null) { - items = getAllNonEquippedOrToolItemsAsTarget(mod); - } else { - items = itemList.items; - } - - mod.runUserTask(new StoreInAnyContainerTask(false, items), this::finish); - } -} diff --git a/src/main/java/adris/altoclef/commands/EquipCommand.java b/src/main/java/adris/altoclef/commands/EquipCommand.java deleted file mode 100644 index e6def4f8..00000000 --- a/src/main/java/adris/altoclef/commands/EquipCommand.java +++ /dev/null @@ -1,69 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.commandsystem.*; -import adris.altoclef.tasks.misc.EquipArmorTask; -import adris.altoclef.util.ItemTarget; -import net.minecraft.item.ArmorItem; -import net.minecraft.item.Item; -import net.minecraft.item.Items; - -public class EquipCommand extends Command { - public EquipCommand() throws CommandException { - super("equip", "Equips armor", new Arg(ItemList.class, "[armors]")); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - ItemTarget[] items; - if (parser.getArgUnits().length == 1) { - switch (parser.getArgUnits()[0].toLowerCase()) { //Hot commands for the default full armor sets - case "leather" -> items = - new ItemTarget[]{new ItemTarget(Items.LEATHER_HELMET), - new ItemTarget(Items.LEATHER_CHESTPLATE), - new ItemTarget(Items.LEATHER_LEGGINGS), - new ItemTarget(Items.LEATHER_BOOTS)}; - case "iron" -> items = - new ItemTarget[]{new ItemTarget(Items.IRON_HELMET), - new ItemTarget(Items.IRON_CHESTPLATE), - new ItemTarget(Items.IRON_LEGGINGS), - new ItemTarget(Items.IRON_BOOTS)}; - case "gold" -> items = - new ItemTarget[]{new ItemTarget(Items.GOLDEN_HELMET), - new ItemTarget(Items.GOLDEN_CHESTPLATE), - new ItemTarget(Items.GOLDEN_LEGGINGS), - new ItemTarget(Items.GOLDEN_BOOTS)}; - case "diamond" -> items = - new ItemTarget[]{new ItemTarget(Items.DIAMOND_HELMET) - , new ItemTarget(Items.DIAMOND_CHESTPLATE), - new ItemTarget(Items.DIAMOND_LEGGINGS), - new ItemTarget(Items.DIAMOND_BOOTS)}; - case "netherite" -> items = - new ItemTarget[]{new ItemTarget(Items.NETHERITE_HELMET), new ItemTarget(Items.NETHERITE_CHESTPLATE), new ItemTarget(Items.NETHERITE_LEGGINGS), new ItemTarget(Items.NETHERITE_BOOTS)}; - default -> { - items = parser.get(ItemList.class).items; // if only one thing was provided, and it isn't an armor set, try to work it out. - } - } - } else { - items = parser.get(ItemList.class).items; // a list of items was provided - } - for (ItemTarget item : items) { - for (Item i : item.getMatches()) { - if (!(i instanceof ArmorItem)) { - items = null; // flag items as "bad" if any of the items are not ArmorItems - break; - } - } - if (items == null) { - break; - } - } - - - if (items != null) - mod.runUserTask(new EquipArmorTask(items), this::finish); // do not run the equip task with non armor items. - else - throw new CommandException("You must provide armor items."); //inform the user that they can only use armor items. - //TODO Possibly add in a variable to tell the user what was wrong. However, this is less helpful if a list of items is wrong. - } -} diff --git a/src/main/java/adris/altoclef/commands/FollowCommand.java b/src/main/java/adris/altoclef/commands/FollowCommand.java deleted file mode 100644 index 3702a568..00000000 --- a/src/main/java/adris/altoclef/commands/FollowCommand.java +++ /dev/null @@ -1,29 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.commandsystem.Arg; -import adris.altoclef.commandsystem.ArgParser; -import adris.altoclef.commandsystem.Command; -import adris.altoclef.commandsystem.CommandException; -import adris.altoclef.tasks.movement.FollowPlayerTask; - -public class FollowCommand extends Command { - public FollowCommand() throws CommandException { - super("follow", "Follows you or someone else", new Arg(String.class, "username", null, 0)); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - String username = parser.get(String.class); - if (username == null) { - if (mod.getButler().hasCurrentUser()) { - username = mod.getButler().getCurrentUser(); - } else { - mod.logWarning("No butler user currently present. Running this command with no user argument can ONLY be done via butler."); - finish(); - return; - } - } - mod.runUserTask(new FollowPlayerTask(username), this::finish); - } -} \ No newline at end of file diff --git a/src/main/java/adris/altoclef/commands/FoodCommand.java b/src/main/java/adris/altoclef/commands/FoodCommand.java deleted file mode 100644 index 4c463f44..00000000 --- a/src/main/java/adris/altoclef/commands/FoodCommand.java +++ /dev/null @@ -1,19 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.commandsystem.Arg; -import adris.altoclef.commandsystem.ArgParser; -import adris.altoclef.commandsystem.Command; -import adris.altoclef.commandsystem.CommandException; -import adris.altoclef.tasks.resources.CollectFoodTask; - -public class FoodCommand extends Command { - public FoodCommand() throws CommandException { - super("food", "Collects a certain amount of food", new Arg<>(Integer.class, "count")); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - mod.runUserTask(new CollectFoodTask(parser.get(Integer.class)), this::finish); - } -} \ No newline at end of file diff --git a/src/main/java/adris/altoclef/commands/GamerCommand.java b/src/main/java/adris/altoclef/commands/GamerCommand.java index b44dd0db..4ca89b7d 100644 --- a/src/main/java/adris/altoclef/commands/GamerCommand.java +++ b/src/main/java/adris/altoclef/commands/GamerCommand.java @@ -3,15 +3,15 @@ import adris.altoclef.AltoClef; import adris.altoclef.commandsystem.ArgParser; import adris.altoclef.commandsystem.Command; -import adris.altoclef.tasks.speedrun.BeatMinecraft2Task; +import adris.altoclef.tasks.speedrun.beatgame.BeatMinecraftTask; public class GamerCommand extends Command { public GamerCommand() { - super("gamer", "Beats the game"); + super("gamer", "Beats the game (Miran version)"); } @Override protected void call(AltoClef mod, ArgParser parser) { - mod.runUserTask(new BeatMinecraft2Task(), this::finish); + mod.runUserTask(new BeatMinecraftTask(mod), this::finish); } -} +} \ No newline at end of file diff --git a/src/main/java/adris/altoclef/commands/GetCommand.java b/src/main/java/adris/altoclef/commands/GetCommand.java deleted file mode 100644 index 6f5ac6c1..00000000 --- a/src/main/java/adris/altoclef/commands/GetCommand.java +++ /dev/null @@ -1,46 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.TaskCatalogue; -import adris.altoclef.commandsystem.*; -import adris.altoclef.tasksystem.Task; -import adris.altoclef.ui.MessagePriority; -import adris.altoclef.util.ItemTarget; - -public class GetCommand extends Command { - - public GetCommand() throws CommandException { - super("get", "Get an item/resource", - new Arg(ItemList.class, "items")); - } - - private static void OnResourceDoesNotExist(AltoClef mod, String resource) { - mod.log("\"" + resource + "\" is not a catalogued resource. Can't get it yet, sorry! If it's a generic block try using baritone.", MessagePriority.OPTIONAL); - mod.log("Use @list to get a list of available resources.", MessagePriority.OPTIONAL); - } - - private void GetItems(AltoClef mod, ItemTarget... items) { - Task targetTask; - if (items == null || items.length == 0) { - mod.log("You must specify at least one item!"); - finish(); - return; - } - if (items.length == 1) { - targetTask = TaskCatalogue.getItemTask(items[0]); - } else { - targetTask = TaskCatalogue.getSquashedItemTask(items); - } - if (targetTask != null) { - mod.runUserTask(targetTask, this::finish); - } else { - finish(); - } - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - ItemList items = parser.get(ItemList.class); - GetItems(mod, items.items); - } -} \ No newline at end of file diff --git a/src/main/java/adris/altoclef/commands/GiveCommand.java b/src/main/java/adris/altoclef/commands/GiveCommand.java deleted file mode 100644 index bb835eee..00000000 --- a/src/main/java/adris/altoclef/commands/GiveCommand.java +++ /dev/null @@ -1,60 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.Debug; -import adris.altoclef.TaskCatalogue; -import adris.altoclef.commandsystem.Arg; -import adris.altoclef.commandsystem.ArgParser; -import adris.altoclef.commandsystem.Command; -import adris.altoclef.commandsystem.CommandException; -import adris.altoclef.tasks.entity.GiveItemToPlayerTask; -import adris.altoclef.util.ItemTarget; -import adris.altoclef.util.helpers.ItemHelper; -import net.minecraft.item.ItemStack; - -public class GiveCommand extends Command { - public GiveCommand() throws CommandException { - super("give", "Collects an item and gives it to you or someone else", new Arg(String.class, "username", null, 2), new Arg(String.class, "item"), new Arg(Integer.class, "count", 1, 1)); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - String username = parser.get(String.class); - if (username == null) { - if (mod.getButler().hasCurrentUser()) { - username = mod.getButler().getCurrentUser(); - } else { - mod.logWarning("No butler user currently present. Running this command with no user argument can ONLY be done via butler."); - finish(); - return; - } - } - String item = parser.get(String.class); - int count = parser.get(Integer.class); - ItemTarget target = null; - if (TaskCatalogue.taskExists(item)) { - // Registered item with task. - target = TaskCatalogue.getItemTarget(item, count); - } else { - // Unregistered item, might still be in inventory though. - for (int i = 0; i < mod.getPlayer().getInventory().size(); ++i) { - ItemStack stack = mod.getPlayer().getInventory().getStack(i); - if (!stack.isEmpty()) { - String name = ItemHelper.stripItemName(stack.getItem()); - if (name.equals(item)) { - target = new ItemTarget(stack.getItem(), count); - break; - } - } - } - } - if (target != null) { - Debug.logMessage("USER: " + username + " : ITEM: " + item + " x " + count); - mod.runUserTask(new GiveItemToPlayerTask(username, target), this::finish); - } else { - mod.log("Item not found or task does not exist for item: " + item); - finish(); - } - } - -} \ No newline at end of file diff --git a/src/main/java/adris/altoclef/commands/GotoCommand.java b/src/main/java/adris/altoclef/commands/GotoCommand.java deleted file mode 100644 index f0f6bd0f..00000000 --- a/src/main/java/adris/altoclef/commands/GotoCommand.java +++ /dev/null @@ -1,44 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.commandsystem.*; -import adris.altoclef.tasks.movement.DefaultGoToDimensionTask; -import adris.altoclef.tasks.movement.GetToBlockTask; -import adris.altoclef.tasks.movement.GetToXZTask; -import adris.altoclef.tasks.movement.GetToYTask; -import adris.altoclef.tasksystem.Task; -import net.minecraft.util.math.BlockPos; - -/** - * Out of all the commands, this one probably demonstrates - * why we need a better arg parsing system. Please. - */ -public class GotoCommand extends Command { - - public GotoCommand() throws CommandException { - // x z - // x y z - // x y z dimension - // (dimension) - // (x z dimension) - super("goto", "Tell bot to travel to a set of coordinates", - new Arg(GotoTarget.class, "[x y z dimension]/[x z dimension]/[y dimension]/[dimension]/[x y z]/[x z]/[y]") - ); - } - - public static Task getMovementTaskFor(GotoTarget target) { - return switch (target.getType()) { - case XYZ -> - new GetToBlockTask(new BlockPos(target.getX(), target.getY(), target.getZ()), target.getDimension()); - case XZ -> new GetToXZTask(target.getX(), target.getZ(), target.getDimension()); - case Y -> new GetToYTask(target.getY(), target.getDimension()); - case NONE -> new DefaultGoToDimensionTask(target.getDimension()); - }; - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - GotoTarget target = parser.get(GotoTarget.class); - mod.runUserTask(getMovementTaskFor(target), this::finish); - } -} diff --git a/src/main/java/adris/altoclef/commands/HelpCommand.java b/src/main/java/adris/altoclef/commands/HelpCommand.java index e03006cd..dc5e1173 100644 --- a/src/main/java/adris/altoclef/commands/HelpCommand.java +++ b/src/main/java/adris/altoclef/commands/HelpCommand.java @@ -15,18 +15,16 @@ public HelpCommand() { protected void call(AltoClef mod, ArgParser parser) { mod.log("########## HELP: ##########", MessagePriority.OPTIONAL); int padSize = 10; - for (Command c : mod.getCommandExecutor().allCommands()) { + for (Command c : AltoClef.getCommandExecutor().allCommands()) { StringBuilder line = new StringBuilder(); //line.append(""); line.append(c.getName()).append(": "); int toAdd = padSize - c.getName().length(); - for (int i = 0; i < toAdd; ++i) { - line.append(" "); - } + line.append(" ".repeat(Math.max(0, toAdd))); line.append(c.getDescription()); mod.log(line.toString(), MessagePriority.OPTIONAL); } mod.log("###########################", MessagePriority.OPTIONAL); finish(); } -} +} \ No newline at end of file diff --git a/src/main/java/adris/altoclef/commands/HeroCommand.java b/src/main/java/adris/altoclef/commands/HeroCommand.java deleted file mode 100644 index 14600522..00000000 --- a/src/main/java/adris/altoclef/commands/HeroCommand.java +++ /dev/null @@ -1,18 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.commandsystem.ArgParser; -import adris.altoclef.commandsystem.Command; -import adris.altoclef.commandsystem.CommandException; -import adris.altoclef.tasks.entity.HeroTask; - -public class HeroCommand extends Command { - public HeroCommand() { - super("hero", "Kill all hostile mobs"); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - mod.runUserTask(new HeroTask(), this::finish); - } -} diff --git a/src/main/java/adris/altoclef/commands/IdleCommand.java b/src/main/java/adris/altoclef/commands/IdleCommand.java deleted file mode 100644 index fde2af95..00000000 --- a/src/main/java/adris/altoclef/commands/IdleCommand.java +++ /dev/null @@ -1,17 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.commandsystem.ArgParser; -import adris.altoclef.commandsystem.Command; -import adris.altoclef.tasks.movement.IdleTask; - -public class IdleCommand extends Command { - public IdleCommand() { - super("idle", "Stand still"); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) { - mod.runUserTask(new IdleTask(), this::finish); - } -} diff --git a/src/main/java/adris/altoclef/commands/InventoryCommand.java b/src/main/java/adris/altoclef/commands/InventoryCommand.java deleted file mode 100644 index 3044fc3b..00000000 --- a/src/main/java/adris/altoclef/commands/InventoryCommand.java +++ /dev/null @@ -1,59 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.TaskCatalogue; -import adris.altoclef.commandsystem.Arg; -import adris.altoclef.commandsystem.ArgParser; -import adris.altoclef.commandsystem.Command; -import adris.altoclef.commandsystem.CommandException; -import adris.altoclef.ui.MessagePriority; -import adris.altoclef.util.helpers.ItemHelper; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; - -import java.util.HashMap; - -public class InventoryCommand extends Command { - public InventoryCommand() throws CommandException { - super("inventory", "Prints the bot's inventory OR returns how many of an item the bot has", new Arg(String.class, "item", null, 1)); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - String item = parser.get(String.class); - if (item == null) { - // Print inventory - // Get item counts - HashMap counts = new HashMap<>(); - for (int i = 0; i < mod.getPlayer().getInventory().size(); ++i) { - ItemStack stack = mod.getPlayer().getInventory().getStack(i); - if (!stack.isEmpty()) { - String name = ItemHelper.stripItemName(stack.getItem()); - if (!counts.containsKey(name)) counts.put(name, 0); - counts.put(name, counts.get(name) + stack.getCount()); - } - } - // Print - mod.log("INVENTORY: ", MessagePriority.OPTIONAL); - for (String name : counts.keySet()) { - mod.log(name + " : " + counts.get(name), MessagePriority.OPTIONAL); - } - mod.log("(inventory list sent) ", MessagePriority.OPTIONAL); - } else { - // Print item quantity - Item[] matches = TaskCatalogue.getItemMatches(item); - if (matches == null || matches.length == 0) { - mod.logWarning("Item \"" + item + "\" is not catalogued/recognized."); - finish(); - return; - } - int count = mod.getItemStorage().getItemCount(matches); - if (count == 0) { - mod.log(item + " COUNT: (none)"); - } else { - mod.log(item + " COUNT: " + count); - } - } - finish(); - } -} \ No newline at end of file diff --git a/src/main/java/adris/altoclef/commands/ListCommand.java b/src/main/java/adris/altoclef/commands/ListCommand.java deleted file mode 100644 index cbb59a98..00000000 --- a/src/main/java/adris/altoclef/commands/ListCommand.java +++ /dev/null @@ -1,23 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.TaskCatalogue; -import adris.altoclef.commandsystem.ArgParser; -import adris.altoclef.commandsystem.Command; -import adris.altoclef.commandsystem.CommandException; -import adris.altoclef.ui.MessagePriority; - -import java.util.Arrays; - -public class ListCommand extends Command { - public ListCommand() { - super("list", "List all obtainable items"); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - mod.log("#### LIST OF ALL OBTAINABLE ITEMS ####", MessagePriority.OPTIONAL); - mod.log(Arrays.toString(TaskCatalogue.resourceNames().toArray()), MessagePriority.OPTIONAL); - mod.log("############# END LIST ###############", MessagePriority.OPTIONAL); - } -} diff --git a/src/main/java/adris/altoclef/commands/LocateStructureCommand.java b/src/main/java/adris/altoclef/commands/LocateStructureCommand.java deleted file mode 100644 index c8fbfd86..00000000 --- a/src/main/java/adris/altoclef/commands/LocateStructureCommand.java +++ /dev/null @@ -1,34 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.commandsystem.Arg; -import adris.altoclef.commandsystem.ArgParser; -import adris.altoclef.commandsystem.Command; -import adris.altoclef.commandsystem.CommandException; -import adris.altoclef.tasks.movement.GoToStrongholdPortalTask; -import adris.altoclef.tasks.movement.LocateDesertTempleTask; - -public class LocateStructureCommand extends Command { - - public LocateStructureCommand() throws CommandException { - super("locate_structure", "Locate a world generated structure.", new Arg(Structure.class, "structure")); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - Structure structure = parser.get(Structure.class); - switch (structure) { - case STRONGHOLD: - mod.runUserTask(new GoToStrongholdPortalTask(1), this::finish); - break; - case DESERT_TEMPLE: - mod.runUserTask(new LocateDesertTempleTask(), this::finish); - break; - } - } - - public enum Structure { - DESERT_TEMPLE, - STRONGHOLD - } -} \ No newline at end of file diff --git a/src/main/java/adris/altoclef/commands/MarvionCommand.java b/src/main/java/adris/altoclef/commands/MarvionCommand.java index 5ff363e5..a508d705 100644 --- a/src/main/java/adris/altoclef/commands/MarvionCommand.java +++ b/src/main/java/adris/altoclef/commands/MarvionCommand.java @@ -3,15 +3,16 @@ import adris.altoclef.AltoClef; import adris.altoclef.commandsystem.ArgParser; import adris.altoclef.commandsystem.Command; -import adris.altoclef.tasks.speedrun.MarvionBeatMinecraftTask; public class MarvionCommand extends Command { + public MarvionCommand() { - super("marvion", "Beats the game (Marvion version)"); + super("marvion", "Unsupported leaving it here in case anyone uses it"); } @Override protected void call(AltoClef mod, ArgParser parser) { - mod.runUserTask(new MarvionBeatMinecraftTask(), this::finish); + mod.logWarning("This command does not exist, if you want to beat the game use '@gamer'"); } -} \ No newline at end of file + +} diff --git a/src/main/java/adris/altoclef/commands/MeatCommand.java b/src/main/java/adris/altoclef/commands/MeatCommand.java deleted file mode 100644 index 12eda048..00000000 --- a/src/main/java/adris/altoclef/commands/MeatCommand.java +++ /dev/null @@ -1,19 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.commandsystem.Arg; -import adris.altoclef.commandsystem.ArgParser; -import adris.altoclef.commandsystem.Command; -import adris.altoclef.commandsystem.CommandException; -import adris.altoclef.tasks.resources.CollectMeatTask; - -public class MeatCommand extends Command { - public MeatCommand() throws CommandException { - super("meat", "Collects a certain amount of meat", new Arg<>(Integer.class, "count")); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - mod.runUserTask(new CollectMeatTask(parser.get(Integer.class)), this::finish); - } -} \ No newline at end of file diff --git a/src/main/java/adris/altoclef/commands/PunkCommand.java b/src/main/java/adris/altoclef/commands/PunkCommand.java deleted file mode 100644 index ee7898af..00000000 --- a/src/main/java/adris/altoclef/commands/PunkCommand.java +++ /dev/null @@ -1,20 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.commandsystem.Arg; -import adris.altoclef.commandsystem.ArgParser; -import adris.altoclef.commandsystem.Command; -import adris.altoclef.commandsystem.CommandException; -import adris.altoclef.tasks.entity.KillPlayerTask; - -public class PunkCommand extends Command { - public PunkCommand() throws CommandException { - super("punk", "Punk 'em", new Arg(String.class, "playerName")); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - String playerName = parser.get(String.class); - mod.runUserTask(new KillPlayerTask(playerName), this::finish); - } -} \ No newline at end of file diff --git a/src/main/java/adris/altoclef/commands/SelfCareCommand.java b/src/main/java/adris/altoclef/commands/SelfCareCommand.java deleted file mode 100644 index 257fe2b1..00000000 --- a/src/main/java/adris/altoclef/commands/SelfCareCommand.java +++ /dev/null @@ -1,17 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.commandsystem.ArgParser; -import adris.altoclef.commandsystem.Command; -import adris.altoclef.tasks.entity.SelfCareTask; - -public class SelfCareCommand extends Command { - public SelfCareCommand() { - super("selfcare", "Care for self (Not finished and tested yet)"); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) { - mod.runUserTask(new SelfCareTask(), this::finish); - } -} diff --git a/src/main/java/adris/altoclef/commands/SetGammaCommand.java b/src/main/java/adris/altoclef/commands/SetGammaCommand.java index 472a0bd9..436b91e4 100644 --- a/src/main/java/adris/altoclef/commands/SetGammaCommand.java +++ b/src/main/java/adris/altoclef/commands/SetGammaCommand.java @@ -17,7 +17,12 @@ public SetGammaCommand() throws CommandException { @Override protected void call(AltoClef mod, ArgParser parser) throws CommandException { double gammaValue = parser.get(Double.class); - Debug.logMessage("Gamma set to " + gammaValue); - MinecraftClient.getInstance().options.getGamma().setValue(gammaValue); + changeGamma(gammaValue); } -} + + public static void changeGamma(double value) { + Debug.logMessage("Gamma set to " + value); + MinecraftClient.getInstance().options.getGamma().setValue(value); + } + +} \ No newline at end of file diff --git a/src/main/java/adris/altoclef/commands/StashCommand.java b/src/main/java/adris/altoclef/commands/StashCommand.java deleted file mode 100644 index 52f7a2cb..00000000 --- a/src/main/java/adris/altoclef/commands/StashCommand.java +++ /dev/null @@ -1,48 +0,0 @@ -package adris.altoclef.commands; - -import adris.altoclef.AltoClef; -import adris.altoclef.commandsystem.*; -import adris.altoclef.tasks.container.StoreInStashTask; -import adris.altoclef.util.BlockRange; -import adris.altoclef.util.ItemTarget; -import adris.altoclef.util.helpers.WorldHelper; -import net.minecraft.util.math.BlockPos; - -public class StashCommand extends Command { - public StashCommand() throws CommandException { - // stash [item list] - super("stash", "Store an item in a chest/container stash. Will deposit ALL non-equipped items if item list is empty.", - new Arg(Integer.class, "x_start"), - new Arg(Integer.class, "y_start"), - new Arg(Integer.class, "z_start"), - new Arg(Integer.class, "x_end"), - new Arg(Integer.class, "y_end"), - new Arg(Integer.class, "z_end"), - new Arg(ItemList.class, "items (empty for ALL)", null, 6, false)); - } - - @Override - protected void call(AltoClef mod, ArgParser parser) throws CommandException { - BlockPos start = new BlockPos( - parser.get(Integer.class), - parser.get(Integer.class), - parser.get(Integer.class) - ); - BlockPos end = new BlockPos( - parser.get(Integer.class), - parser.get(Integer.class), - parser.get(Integer.class) - ); - - ItemList itemList = parser.get(ItemList.class); - ItemTarget[] items; - if (itemList == null) { - items = DepositCommand.getAllNonEquippedOrToolItemsAsTarget(mod); - } else { - items = itemList.items; - } - - - mod.runUserTask(new StoreInStashTask(true, new BlockRange(start, end, WorldHelper.getCurrentDimension()), items), this::finish); - } -} diff --git a/src/main/java/adris/altoclef/commands/StatusCommand.java b/src/main/java/adris/altoclef/commands/StatusCommand.java index 4618d31f..0d74a012 100644 --- a/src/main/java/adris/altoclef/commands/StatusCommand.java +++ b/src/main/java/adris/altoclef/commands/StatusCommand.java @@ -15,7 +15,7 @@ public StatusCommand() { @Override protected void call(AltoClef mod, ArgParser parser) { List tasks = mod.getUserTaskChain().getTasks(); - if (tasks.size() == 0) { + if (tasks.isEmpty()) { mod.log("No tasks currently running."); } else { mod.log("CURRENT TASK: " + tasks.get(0).toString()); diff --git a/src/main/java/adris/altoclef/commands/random/CycleTestCommand.java b/src/main/java/adris/altoclef/commands/random/CycleTestCommand.java new file mode 100644 index 00000000..1800e773 --- /dev/null +++ b/src/main/java/adris/altoclef/commands/random/CycleTestCommand.java @@ -0,0 +1,19 @@ +package adris.altoclef.commands.random; + +import adris.altoclef.AltoClef; +import adris.altoclef.commandsystem.ArgParser; +import adris.altoclef.commandsystem.Command; +import adris.altoclef.tasks.construction.compound.ConstructNetherPortalSpeedrunTask; +import adris.altoclef.tasks.speedrun.OneCycleTask; + +public class CycleTestCommand extends Command { + + public CycleTestCommand() { + super("cycle", "One cycles the dragon B)"); + } + + @Override + protected void call(AltoClef mod, ArgParser parser) { + mod.runUserTask(new OneCycleTask(), this::finish); + } +} diff --git a/src/main/java/adris/altoclef/commands/random/ScanCommand.java b/src/main/java/adris/altoclef/commands/random/ScanCommand.java new file mode 100644 index 00000000..13e3f6d6 --- /dev/null +++ b/src/main/java/adris/altoclef/commands/random/ScanCommand.java @@ -0,0 +1,52 @@ +package adris.altoclef.commands.random; + +import adris.altoclef.AltoClef; +import adris.altoclef.commands.BlockScanner; +import adris.altoclef.commandsystem.Arg; +import adris.altoclef.commandsystem.ArgParser; +import adris.altoclef.commandsystem.Command; +import adris.altoclef.commandsystem.CommandException; +import net.minecraft.block.Block; +import net.minecraft.block.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.World; + +import java.lang.reflect.Field; +import java.util.HashSet; + +public class ScanCommand extends Command { + + public ScanCommand() throws CommandException { + super("scan", "Locates nearest block", new Arg<>(String.class, "block", "DIRT", 0)); + } + + @Override + protected void call(AltoClef mod, ArgParser parser) throws CommandException { + String blockStr = parser.get(String.class); + + Field[] declaredFields = Blocks.class.getDeclaredFields(); + Block block = null; + + for (Field field : declaredFields) { + System.out.println(field); + try { + if (field.getName().equalsIgnoreCase(blockStr)) { + block = (Block) field.get(Blocks.class); + } + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + + } + + if (block == null) { + mod.logWarning("Block named: " + blockStr + " not found :("); + return; + } + + BlockScanner blockScanner = mod.getBlockScanner(); + mod.log(blockScanner.getNearestBlock(block,mod.getPlayer().getPos())+""); + } + +} \ No newline at end of file diff --git a/src/main/java/adris/altoclef/control/KillAura.java b/src/main/java/adris/altoclef/control/KillAura.java index a1ee9538..82c5c464 100644 --- a/src/main/java/adris/altoclef/control/KillAura.java +++ b/src/main/java/adris/altoclef/control/KillAura.java @@ -28,65 +28,69 @@ */ public class KillAura { // Smart aura data - private final List _targets = new ArrayList<>(); - private final TimerGame _hitDelay = new TimerGame(0.2); - boolean _shielding = false; - private double _forceFieldRange = Double.POSITIVE_INFINITY; - private Entity _forceHit = null; + private final List targets = new ArrayList<>(); + private final TimerGame hitDelay = new TimerGame(0.2); + boolean shielding = false; + private double forceFieldRange = Double.POSITIVE_INFINITY; + private Entity forceHit = null; public static void equipWeapon(AltoClef mod) { List invStacks = mod.getItemStorage().getItemStacksPlayerInventory(true); - if (!invStacks.isEmpty()) { - float handDamage = Float.NEGATIVE_INFINITY; - for (ItemStack invStack : invStacks) { - if (invStack.getItem() instanceof SwordItem item) { - float itemDamage = item.getMaterial().getAttackDamage(); - Item handItem = StorageHelper.getItemStackInSlot(PlayerSlot.getEquipSlot()).getItem(); - if (handItem instanceof SwordItem handToolItem) { - handDamage = handToolItem.getMaterial().getAttackDamage(); - } - if (itemDamage > handDamage) { - mod.getSlotHandler().forceEquipItem(item); - } else { - mod.getSlotHandler().forceEquipItem(handItem); - } + float handDamage = Float.NEGATIVE_INFINITY; + for (ItemStack invStack : invStacks) { + if (invStack.getItem() instanceof SwordItem item) { + + float itemDamage = item.getMaterial().getAttackDamage(); + Item handItem = StorageHelper.getItemStackInSlot(PlayerSlot.getEquipSlot()).getItem(); + + if (handItem instanceof SwordItem handToolItem) { + handDamage = handToolItem.getMaterial().getAttackDamage(); } + + if (itemDamage > handDamage) { + mod.getSlotHandler().forceEquipItem(item); + } else { + mod.getSlotHandler().forceEquipItem(handItem); + } + } } } public void tickStart() { - _targets.clear(); - _forceHit = null; + targets.clear(); + forceHit = null; } public void applyAura(Entity entity) { - _targets.add(entity); + targets.add(entity); // Always hit ghast balls. - if (entity instanceof FireballEntity) _forceHit = entity; + if (entity instanceof FireballEntity) forceHit = entity; } public void setRange(double range) { - _forceFieldRange = range; + forceFieldRange = range; } public void tickEnd(AltoClef mod) { - Optional entities = _targets.stream().min(StlHelper.compareValues(entity -> entity.squaredDistanceTo(mod.getPlayer()))); - if (entities.isPresent() && mod.getPlayer().getHealth() >= 10 && + Optional entity = targets.stream().min(StlHelper.compareValues(e -> e.squaredDistanceTo(mod.getPlayer()))); + if (entity.isPresent() && mod.getPlayer().getHealth() >= 10 && !mod.getEntityTracker().entityFound(PotionEntity.class) && !mod.getFoodChain().needsToEat() && - (Double.isInfinite(_forceFieldRange) || entities.get().squaredDistanceTo(mod.getPlayer()) < _forceFieldRange * _forceFieldRange || - entities.get().squaredDistanceTo(mod.getPlayer()) < 40) && - !mod.getMLGBucketChain().isFallingOhNo(mod) && mod.getMLGBucketChain().doneMLG() && - !mod.getMLGBucketChain().isChorusFruiting()) { + (Double.isInfinite(forceFieldRange) || entity.get().squaredDistanceTo(mod.getPlayer()) < forceFieldRange * forceFieldRange || + entity.get().squaredDistanceTo(mod.getPlayer()) < 40) && + !mod.getMLGBucketChain().isFalling(mod) && mod.getMLGBucketChain().doneMLG() && !mod.getMLGBucketChain().isChorusFruiting()) { + PlayerSlot offhandSlot = PlayerSlot.OFFHAND_SLOT; Item offhandItem = StorageHelper.getItemStackInSlot(offhandSlot).getItem(); - if (entities.get().getClass() != CreeperEntity.class && entities.get().getClass() != HoglinEntity.class && - entities.get().getClass() != ZoglinEntity.class && entities.get().getClass() != WardenEntity.class && - entities.get().getClass() != WitherEntity.class + + if (entity.get().getClass() != CreeperEntity.class && entity.get().getClass() != HoglinEntity.class && + entity.get().getClass() != ZoglinEntity.class && entity.get().getClass() != WardenEntity.class && + entity.get().getClass() != WitherEntity.class && (mod.getItemStorage().hasItem(Items.SHIELD) || mod.getItemStorage().hasItemInOffhand(Items.SHIELD)) && !mod.getPlayer().getItemCooldownManager().isCoolingDown(offhandItem) && mod.getClientBaritone().getPathingBehavior().isSafeToCancel()) { - LookHelper.lookAt(mod, entities.get().getEyePos()); + + LookHelper.lookAt(mod, entity.get().getEyePos()); ItemStack shieldSlot = StorageHelper.getItemStackInSlot(PlayerSlot.OFFHAND_SLOT); if (shieldSlot.getItem() != Items.SHIELD) { mod.getSlotHandler().forceEquipItemToOffhand(Items.SHIELD); @@ -104,26 +108,26 @@ public void tickEnd(AltoClef mod) { performFastestAttack(mod); break; case SMART: - if (_targets.size() <= 2 || _targets.stream().allMatch(entity -> entity instanceof SkeletonEntity) || - _targets.stream().allMatch(entity -> entity instanceof WitchEntity) || - _targets.stream().allMatch(entity -> entity instanceof PillagerEntity) || - _targets.stream().allMatch(entity -> entity instanceof PiglinEntity) || - _targets.stream().allMatch(entity -> entity instanceof StrayEntity) || - _targets.stream().allMatch(entity -> entity instanceof BlazeEntity)) { + if (targets.size() <= 2 || targets.stream().allMatch(e -> e instanceof SkeletonEntity) || + targets.stream().allMatch(e -> e instanceof WitchEntity) || + targets.stream().allMatch(e -> e instanceof PillagerEntity) || + targets.stream().allMatch(e -> e instanceof PiglinEntity) || + targets.stream().allMatch(e -> e instanceof StrayEntity) || + targets.stream().allMatch(e -> e instanceof BlazeEntity)) { performDelayedAttack(mod); } else { - if (!mod.getFoodChain().needsToEat() && !mod.getMLGBucketChain().isFallingOhNo(mod) && + if (!mod.getFoodChain().needsToEat() && !mod.getMLGBucketChain().isFalling(mod) && mod.getMLGBucketChain().doneMLG() && !mod.getMLGBucketChain().isChorusFruiting()) { - // Attack force mobs ALWAYS. - if (_forceHit != null) { - attack(mod, _forceHit, true); + // Attack force mobs ALWAYS. (currently used only for fireballs) + if (forceHit != null) { + attack(mod, forceHit, true); } - if (_hitDelay.elapsed()) { - _hitDelay.reset(); + if (hitDelay.elapsed()) { + hitDelay.reset(); - Optional toHit = _targets.stream().min(StlHelper.compareValues(entity -> entity.squaredDistanceTo(mod.getPlayer()))); + Optional toHit = targets.stream().min(StlHelper.compareValues(e -> e.squaredDistanceTo(mod.getPlayer()))); - toHit.ifPresent(entity -> attack(mod, entity, true)); + toHit.ifPresent(e -> attack(mod, e, true)); } } } @@ -137,17 +141,17 @@ public void tickEnd(AltoClef mod) { } private void performDelayedAttack(AltoClef mod) { - if (!mod.getFoodChain().needsToEat() && !mod.getMLGBucketChain().isFallingOhNo(mod) && + if (!mod.getFoodChain().needsToEat() && !mod.getMLGBucketChain().isFalling(mod) && mod.getMLGBucketChain().doneMLG() && !mod.getMLGBucketChain().isChorusFruiting()) { - if (_forceHit != null) { - attack(mod, _forceHit, true); + if (forceHit != null) { + attack(mod, forceHit, true); } // wait for the attack delay - if (_targets.isEmpty()) { + if (targets.isEmpty()) { return; } - Optional toHit = _targets.stream().min(StlHelper.compareValues(entity -> entity.squaredDistanceTo(mod.getPlayer()))); + Optional toHit = targets.stream().min(StlHelper.compareValues(entity -> entity.squaredDistanceTo(mod.getPlayer()))); if (mod.getPlayer() == null || mod.getPlayer().getAttackCooldownProgress(0) < 1) { return; @@ -158,10 +162,10 @@ private void performDelayedAttack(AltoClef mod) { } private void performFastestAttack(AltoClef mod) { - if (!mod.getFoodChain().needsToEat() && !mod.getMLGBucketChain().isFallingOhNo(mod) && + if (!mod.getFoodChain().needsToEat() && !mod.getMLGBucketChain().isFalling(mod) && mod.getMLGBucketChain().doneMLG() && !mod.getMLGBucketChain().isChorusFruiting()) { // Just attack whenever you can - for (Entity entity : _targets) { + for (Entity entity : targets) { attack(mod, entity); } } @@ -176,7 +180,7 @@ private void attack(AltoClef mod, Entity entity, boolean equipSword) { if (!(entity instanceof FireballEntity)) { LookHelper.lookAt(mod, entity.getEyePos()); } - if (Double.isInfinite(_forceFieldRange) || entity.squaredDistanceTo(mod.getPlayer()) < _forceFieldRange * _forceFieldRange || + if (Double.isInfinite(forceFieldRange) || entity.squaredDistanceTo(mod.getPlayer()) < forceFieldRange * forceFieldRange || entity.squaredDistanceTo(mod.getPlayer()) < 40) { if (entity instanceof FireballEntity) { mod.getControllerExtras().attack(entity); @@ -198,7 +202,7 @@ private void attack(AltoClef mod, Entity entity, boolean equipSword) { } public void startShielding(AltoClef mod) { - _shielding = true; + shielding = true; mod.getInputControls().hold(Input.SNEAK); mod.getInputControls().hold(Input.CLICK_RIGHT); mod.getClientBaritone().getPathingBehavior().requestPause(); @@ -222,7 +226,7 @@ public void startShielding(AltoClef mod) { } public void stopShielding(AltoClef mod) { - if (_shielding) { + if (shielding) { ItemStack cursor = StorageHelper.getItemStackInCursorSlot(); if (cursor.isFood()) { Optional toMoveTo = mod.getItemStorage().getSlotThatCanFitInPlayerInventory(cursor, false).or(() -> StorageHelper.getGarbageSlot(mod)); @@ -235,7 +239,7 @@ public void stopShielding(AltoClef mod) { mod.getInputControls().release(Input.CLICK_RIGHT); mod.getInputControls().release(Input.JUMP); mod.getExtraBaritoneSettings().setInteractionPaused(false); - _shielding = false; + shielding = false; } } diff --git a/src/main/java/adris/altoclef/control/SlotHandler.java b/src/main/java/adris/altoclef/control/SlotHandler.java index 756a4265..777de38e 100644 --- a/src/main/java/adris/altoclef/control/SlotHandler.java +++ b/src/main/java/adris/altoclef/control/SlotHandler.java @@ -22,31 +22,31 @@ public class SlotHandler { - private final AltoClef _mod; + private final AltoClef mod; - private final TimerGame _slotActionTimer = new TimerGame(0); - private boolean _overrideTimerOnce = false; + private final TimerGame slotActionTimer = new TimerGame(0); + private boolean overrideTimerOnce = false; public SlotHandler(AltoClef mod) { - _mod = mod; + this.mod = mod; } private void forceAllowNextSlotAction() { - _overrideTimerOnce = true; + overrideTimerOnce = true; } public boolean canDoSlotAction() { - if (_overrideTimerOnce) { - _overrideTimerOnce = false; + if (overrideTimerOnce) { + overrideTimerOnce = false; return true; } - _slotActionTimer.setInterval(_mod.getModSettings().getContainerItemMoveDelay()); - return _slotActionTimer.elapsed(); + slotActionTimer.setInterval(mod.getModSettings().getContainerItemMoveDelay()); + return slotActionTimer.elapsed(); } public void registerSlotAction() { - _mod.getItemStorage().registerSlotAction(); - _slotActionTimer.reset(); + mod.getItemStorage().registerSlotAction(); + slotActionTimer.reset(); } @@ -77,7 +77,7 @@ private void clickWindowSlot(int windowSlot, int mouseButton, SlotActionType typ int syncId = player.currentScreenHandler.syncId; try { - _mod.getController().clickSlot(syncId, windowSlot, mouseButton, type, player); + mod.getController().clickSlot(syncId, windowSlot, mouseButton, type, player); } catch (Exception e) { Debug.logWarning("Slot Click Error (ignored)"); e.printStackTrace(); @@ -88,13 +88,13 @@ public void forceEquipItemToOffhand(Item toEquip) { if (StorageHelper.getItemStackInSlot(PlayerSlot.OFFHAND_SLOT).getItem() == toEquip) { return; } - List currentItemSlot = _mod.getItemStorage().getSlotsWithItemPlayerInventory(false, + List currentItemSlot = mod.getItemStorage().getSlotsWithItemPlayerInventory(false, toEquip); for (Slot CurrentItemSlot : currentItemSlot) { if (!Slot.isCursor(CurrentItemSlot)) { - _mod.getSlotHandler().clickSlot(CurrentItemSlot, 0, SlotActionType.PICKUP); + mod.getSlotHandler().clickSlot(CurrentItemSlot, 0, SlotActionType.PICKUP); } else { - _mod.getSlotHandler().clickSlot(PlayerSlot.OFFHAND_SLOT, 0, SlotActionType.PICKUP); + mod.getSlotHandler().clickSlot(PlayerSlot.OFFHAND_SLOT, 0, SlotActionType.PICKUP); } } } @@ -105,13 +105,13 @@ public boolean forceEquipItem(Item toEquip) { if (StorageHelper.getItemStackInSlot(PlayerSlot.getEquipSlot()).getItem() == toEquip) return true; // Always equip to the second slot. First + last is occupied by baritone. - _mod.getPlayer().getInventory().selectedSlot = 1; + mod.getPlayer().getInventory().selectedSlot = 1; // If our item is in our cursor, simply move it to the hotbar. boolean inCursor = StorageHelper.getItemStackInSlot(CursorSlot.SLOT).getItem() == toEquip; - List itemSlots = _mod.getItemStorage().getSlotsWithItemScreen(toEquip); - if (itemSlots.size() != 0) { + List itemSlots = mod.getItemStorage().getSlotsWithItemScreen(toEquip); + if (!itemSlots.isEmpty()) { for (Slot ItemSlots : itemSlots) { int hotbar = 1; //_mod.getPlayer().getInventory().swapSlotWithHotbar(); @@ -166,7 +166,7 @@ public boolean forceDeequip(Predicate isBad) { ItemStack cursor = StorageHelper.getItemStackInSlot(CursorSlot.SLOT); if (isBad.test(cursor)) { // Throw away cursor slot OR move - Optional fittableSlots = _mod.getItemStorage().getSlotThatCanFitInPlayerInventory(equip, false); + Optional fittableSlots = mod.getItemStorage().getSlotThatCanFitInPlayerInventory(equip, false); if (fittableSlots.isEmpty()) { // Try to swap items with the first non-bad slot. for (Slot slot : Slot.getCurrentScreenSlots()) { @@ -175,7 +175,7 @@ public boolean forceDeequip(Predicate isBad) { return false; } } - if (ItemHelper.canThrowAwayStack(_mod, cursor)) { + if (ItemHelper.canThrowAwayStack(mod, cursor)) { clickSlotForce(PlayerSlot.UNDEFINED, 0, SlotActionType.PICKUP); return true; } @@ -212,7 +212,7 @@ public boolean forceEquipItem(ItemTarget toEquip, boolean unInterruptable) { if (toEquip == null) return false; //If the bot try to eat - if (_mod.getFoodChain().needsToEat() && !unInterruptable) { //unless we really need to force equip the item + if (mod.getFoodChain().needsToEat() && !unInterruptable) { //unless we really need to force equip the item return false; //don't equip the item for now } @@ -221,7 +221,7 @@ public boolean forceEquipItem(ItemTarget toEquip, boolean unInterruptable) { if (toEquip.matches(StorageHelper.getItemStackInSlot(target).getItem())) return true; for (Item item : toEquip.getMatches()) { - if (_mod.getItemStorage().hasItem(item)) { + if (mod.getItemStorage().hasItem(item)) { if (forceEquipItem(item)) return true; } } diff --git a/src/main/java/adris/altoclef/eventbus/EventBusTest.java b/src/main/java/adris/altoclef/eventbus/EventBusTest.java deleted file mode 100644 index b37006bb..00000000 --- a/src/main/java/adris/altoclef/eventbus/EventBusTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package adris.altoclef.eventbus; - -public class EventBusTest { - - public static void test() { - Subscription a = EventBus.subscribe(TestEvent.class, evt -> System.out.println("A: " + evt.val)); - EventBus.publish(new TestEvent(1)); - Subscription b = EventBus.subscribe(TestEvent.class, evt -> System.out.println("B: " + evt.val)); - EventBus.publish(new TestEvent(2)); - EventBus.unsubscribe(a); - EventBus.publish(new TestEvent(3)); - EventBus.unsubscribe(b); - EventBus.publish(new TestEvent(4)); - } - - static class TestEvent { - public int val; - - public TestEvent(int val) { - this.val = val; - } - } -} diff --git a/src/main/java/adris/altoclef/mixins/BlockModifiedByPlayerMixin.java b/src/main/java/adris/altoclef/mixins/BlockModifiedByPlayerMixin.java index 9b703cb4..1affa034 100644 --- a/src/main/java/adris/altoclef/mixins/BlockModifiedByPlayerMixin.java +++ b/src/main/java/adris/altoclef/mixins/BlockModifiedByPlayerMixin.java @@ -32,14 +32,4 @@ public void onBlockBroken(World world, BlockPos pos, BlockState state, PlayerEnt } } - @Inject( - method = "onPlaced", - at = @At("HEAD") - ) - public void onBlockPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack, CallbackInfo ci) { - // This one is weirdly unreliable. - //Debug.logInternal("[TEMP] global place"); - //StaticMixinHookups.onBlockPlaced(world, pos, state, placer, itemStack); - } - } diff --git a/src/main/java/adris/altoclef/mixins/ClientBlockBreakMixin.java b/src/main/java/adris/altoclef/mixins/ClientBlockBreakMixin.java index 093a7ae2..8556b580 100644 --- a/src/main/java/adris/altoclef/mixins/ClientBlockBreakMixin.java +++ b/src/main/java/adris/altoclef/mixins/ClientBlockBreakMixin.java @@ -8,6 +8,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -17,6 +18,7 @@ public final class ClientBlockBreakMixin { // for SOME REASON baritone triggers a block cancel breaking every other frame, so we have a 2 frame requirement for that? + @Unique private static int _breakCancelFrames; @Inject( diff --git a/src/main/java/adris/altoclef/mixins/ClientInteractWithBlockMixin.java b/src/main/java/adris/altoclef/mixins/ClientInteractWithBlockMixin.java index a681c16b..57ea81e7 100644 --- a/src/main/java/adris/altoclef/mixins/ClientInteractWithBlockMixin.java +++ b/src/main/java/adris/altoclef/mixins/ClientInteractWithBlockMixin.java @@ -1,7 +1,5 @@ package adris.altoclef.mixins; -// ActionResult ClientPlayerInteractionManager.interactBlock(ClientPlayerEntity player, ClientWorld world, Hand hand, BlockHitResult hitResult); - import adris.altoclef.eventbus.EventBus; import adris.altoclef.eventbus.events.BlockInteractEvent; import net.minecraft.client.network.ClientPlayerEntity; diff --git a/src/main/java/adris/altoclef/mixins/ClientPlayerInteractionAccessor.java b/src/main/java/adris/altoclef/mixins/ClientPlayerInteractionAccessor.java deleted file mode 100644 index 0df3162b..00000000 --- a/src/main/java/adris/altoclef/mixins/ClientPlayerInteractionAccessor.java +++ /dev/null @@ -1,11 +0,0 @@ -package adris.altoclef.mixins; - -import net.minecraft.client.network.ClientPlayerInteractionManager; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(ClientPlayerInteractionManager.class) -public interface ClientPlayerInteractionAccessor { - //@Invoker("sendPlayerAction") - //void doSendPlayerAction(PlayerActionC2SPacket.Action action, BlockPos pos, Direction direction); - -} diff --git a/src/main/java/adris/altoclef/mixins/EntryMixin.java b/src/main/java/adris/altoclef/mixins/EntryMixin.java index a59e0d45..a7982dd3 100644 --- a/src/main/java/adris/altoclef/mixins/EntryMixin.java +++ b/src/main/java/adris/altoclef/mixins/EntryMixin.java @@ -5,6 +5,7 @@ import adris.altoclef.eventbus.events.TitleScreenEntryEvent; import net.minecraft.client.gui.screen.TitleScreen; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -12,6 +13,7 @@ @Mixin(TitleScreen.class) public class EntryMixin { + @Unique private static boolean _initialized = false; @Inject(at = @At("HEAD"), method = "init()V") diff --git a/src/main/java/adris/altoclef/mixins/SimpleOptionMixin.java b/src/main/java/adris/altoclef/mixins/SimpleOptionMixin.java new file mode 100644 index 00000000..b8d34ad2 --- /dev/null +++ b/src/main/java/adris/altoclef/mixins/SimpleOptionMixin.java @@ -0,0 +1,33 @@ +package adris.altoclef.mixins; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.option.SimpleOption; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Objects; +import java.util.Optional; + +@Mixin(SimpleOption.class) +public class SimpleOptionMixin { + + + @Shadow + T value; + + @Inject(method = "setValue",at = @At("HEAD"), cancellable = true) + public void inject(T value, CallbackInfo ci) { + if (MinecraftClient.getInstance() == null || MinecraftClient.getInstance().options == null) return; + if (((Object)this) == MinecraftClient.getInstance().options.getGamma()) { + this.value = value; + ci.cancel(); + } + } + +} diff --git a/src/main/java/adris/altoclef/mixins/ToolSetMixin.java b/src/main/java/adris/altoclef/mixins/ToolSetMixin.java new file mode 100644 index 00000000..b2fc2687 --- /dev/null +++ b/src/main/java/adris/altoclef/mixins/ToolSetMixin.java @@ -0,0 +1,61 @@ +package adris.altoclef.mixins; + +import adris.altoclef.AltoClef; +import adris.altoclef.util.helpers.StorageHelper; +import baritone.Baritone; +import baritone.api.Settings; +import baritone.utils.ToolSet; +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +@Mixin(ToolSet.class) +public class ToolSetMixin { + + + @Unique + private static final Settings.Setting trueSetting; + + // create a setting that is always true using reflection + static { + Constructor constructor = Settings.Setting.class.getDeclaredConstructors()[0]; + constructor.setAccessible(true); + + Settings.Setting instance; + try { + instance = (Settings.Setting) constructor.newInstance(Baritone.settings(),true); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + trueSetting = instance; + } + + + + @Redirect(method = "getBestSlot(Lnet/minecraft/block/Block;ZZ)I",at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getDamage()I")) + public int redirected(ItemStack stack,Block block) { + if (StorageHelper.shouldSaveStack(AltoClef.INSTANCE,block,stack)) { + return 100_000; + } + + return stack.getDamage(); + } + + @Redirect(method = "getBestSlot(Lnet/minecraft/block/Block;ZZ)I",at = @At(value = "FIELD", target = "Lbaritone/api/Settings;itemSaver:Lbaritone/api/Settings$Setting;")) + public Settings.Setting redirected(Settings instance,Block block ,@Local ItemStack stack) { + // if (instance.itemSaver.value) return instance.itemSaver; + + if (StorageHelper.shouldSaveStack(AltoClef.INSTANCE,block,stack)) { + return trueSetting; + } + return instance.itemSaver; + } + +} diff --git a/src/main/java/adris/altoclef/mixins/WorldBlockModifiedMixin.java b/src/main/java/adris/altoclef/mixins/WorldBlockModifiedMixin.java index 6dd6f290..8a25e070 100644 --- a/src/main/java/adris/altoclef/mixins/WorldBlockModifiedMixin.java +++ b/src/main/java/adris/altoclef/mixins/WorldBlockModifiedMixin.java @@ -7,6 +7,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -14,6 +15,7 @@ @Mixin(World.class) public class WorldBlockModifiedMixin { + @Unique private static boolean hasBlock(BlockState state, BlockPos pos) { return !state.isAir() && state.isSolidBlock(MinecraftClient.getInstance().world, pos); } @@ -28,5 +30,5 @@ public void onBlockWasChanged(BlockPos pos, BlockState oldBlock, BlockState newB EventBus.publish(evt); } } - //onBlockChanged + } diff --git a/src/main/java/adris/altoclef/tasks/AbstractDoToClosestObjectTask.java b/src/main/java/adris/altoclef/tasks/AbstractDoToClosestObjectTask.java index 2271a4d1..a81dd681 100644 --- a/src/main/java/adris/altoclef/tasks/AbstractDoToClosestObjectTask.java +++ b/src/main/java/adris/altoclef/tasks/AbstractDoToClosestObjectTask.java @@ -16,10 +16,10 @@ */ public abstract class AbstractDoToClosestObjectTask extends Task { - private final HashMap _heuristicMap = new HashMap<>(); - private T _currentlyPursuing = null; - private boolean _wasWandering; - private Task _goalTask = null; + private final HashMap heuristicMap = new HashMap<>(); + private T currentlyPursuing = null; + private boolean wasWandering; + private Task goalTask = null; protected abstract Vec3d getPos(AltoClef mod, T obj); @@ -37,13 +37,13 @@ protected Task getWanderTask(AltoClef mod) { } public void resetSearch() { - _currentlyPursuing = null; - _heuristicMap.clear(); - _goalTask = null; + currentlyPursuing = null; + heuristicMap.clear(); + goalTask = null; } public boolean wasWandering() { - return _wasWandering; + return wasWandering; } private double getCurrentCalculatedHeuristic(AltoClef mod) { @@ -51,55 +51,51 @@ private double getCurrentCalculatedHeuristic(AltoClef mod) { return ticksRemainingOp.orElse(Double.POSITIVE_INFINITY); } - private boolean isMovingToClosestPos(AltoClef mod) { - return _goalTask != null;// && _goalTask.isActive() && !_goalTask.isFinished(mod); - } - @Override protected Task onTick(AltoClef mod) { - _wasWandering = false; + wasWandering = false; // Reset our pursuit if our pursuing object no longer is pursuable. - if (_currentlyPursuing != null && !isValid(mod, _currentlyPursuing)) { + if (currentlyPursuing != null && !isValid(mod, currentlyPursuing)) { // This is probably a good idea, no? - _heuristicMap.remove(_currentlyPursuing); - _currentlyPursuing = null; + heuristicMap.remove(currentlyPursuing); + currentlyPursuing = null; } // Get closest object Optional checkNewClosest = getClosestTo(mod, getOriginPos(mod)); // Receive closest object and position - if (checkNewClosest.isPresent() && !checkNewClosest.get().equals(_currentlyPursuing)) { + if (checkNewClosest.isPresent() && !checkNewClosest.get().equals(currentlyPursuing)) { T newClosest = checkNewClosest.get(); // Different closest object - if (_currentlyPursuing == null) { + if (currentlyPursuing == null) { // We don't have a closest object - _currentlyPursuing = newClosest; + currentlyPursuing = newClosest; } else { - if (isMovingToClosestPos(mod)) { + if (goalTask != null /*isMovingToClosestPos(mod)*/) { setDebugState("Moving towards closest..."); double currentHeuristic = getCurrentCalculatedHeuristic(mod); - double closestDistanceSqr = getPos(mod, _currentlyPursuing).squaredDistanceTo(mod.getPlayer().getPos()); + double closestDistanceSqr = getPos(mod, currentlyPursuing).squaredDistanceTo(mod.getPlayer().getPos()); int lastTick = WorldHelper.getTicks(); - if (!_heuristicMap.containsKey(_currentlyPursuing)) { - _heuristicMap.put(_currentlyPursuing, new CachedHeuristic()); + if (!heuristicMap.containsKey(currentlyPursuing)) { + heuristicMap.put(currentlyPursuing, new CachedHeuristic()); } - CachedHeuristic h = _heuristicMap.get(_currentlyPursuing); + CachedHeuristic h = heuristicMap.get(currentlyPursuing); h.updateHeuristic(currentHeuristic); h.updateDistance(closestDistanceSqr); h.setTickAttempted(lastTick); - if (_heuristicMap.containsKey(newClosest)) { + if (heuristicMap.containsKey(newClosest)) { // Our new object has a past potential heuristic calculated, if it's better try it out. - CachedHeuristic maybeReAttempt = _heuristicMap.get(newClosest); + CachedHeuristic maybeReAttempt = heuristicMap.get(newClosest); double maybeClosestDistance = getPos(mod, newClosest).squaredDistanceTo(mod.getPlayer().getPos()); // Get considerably closer (divide distance by 2) if (maybeReAttempt.getHeuristicValue() < h.getHeuristicValue() || maybeClosestDistance < maybeReAttempt.getClosestDistanceSqr() / 4) { setDebugState("Retrying old heuristic!"); // The currently closest previously calculated heuristic is better, move towards it! - _currentlyPursuing = newClosest; + currentlyPursuing = newClosest; // In theory, this next line shouldn't need to be run, // but it's CRITICAL to making this work for some reason maybeReAttempt.updateDistance(maybeClosestDistance); @@ -107,7 +103,7 @@ protected Task onTick(AltoClef mod) { } else { setDebugState("Trying out NEW pursuit"); // Our new object does not have a heuristic, TRY IT OUT! - _currentlyPursuing = newClosest; + currentlyPursuing = newClosest; } } else { setDebugState("Waiting for move task to kick in..."); @@ -116,17 +112,17 @@ protected Task onTick(AltoClef mod) { } } - if (_currentlyPursuing != null) { - _goalTask = getGoalTask(_currentlyPursuing); - return _goalTask; + if (currentlyPursuing != null) { + goalTask = getGoalTask(currentlyPursuing); + return goalTask; } else { - _goalTask = null; + goalTask = null; } - //noinspection ConstantConditions - if (checkNewClosest.isEmpty() && _currentlyPursuing == null) { + + if (checkNewClosest.isEmpty()) { setDebugState("Waiting for calculations I think (wandering)"); - _wasWandering = true; + wasWandering = true; return getWanderTask(mod); } diff --git a/src/main/java/adris/altoclef/tasks/CraftInInventoryTask.java b/src/main/java/adris/altoclef/tasks/CraftInInventoryTask.java index b1d5598e..ef88d9a9 100644 --- a/src/main/java/adris/altoclef/tasks/CraftInInventoryTask.java +++ b/src/main/java/adris/altoclef/tasks/CraftInInventoryTask.java @@ -47,7 +47,7 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { protected void onResourceStart(AltoClef mod) { _fullCheckFailed = false; ItemStack cursorStack = StorageHelper.getItemStackInCursorSlot(); - if (!cursorStack.isEmpty()) { + if (!cursorStack.isEmpty() && !StorageHelper.isBigCraftingOpen()) { Optional moveTo = mod.getItemStorage().getSlotThatCanFitInPlayerInventory(cursorStack, false); moveTo.ifPresent(slot -> mod.getSlotHandler().clickSlot(slot, 0, SlotActionType.PICKUP)); if (ItemHelper.canThrowAwayStack(mod, cursorStack)) { @@ -114,6 +114,12 @@ protected void onResourceStop(AltoClef mod, Task interruptTask) { } } + // TODO check if this doesnt break something... but generally this shouldnt pickup items + @Override + protected double getPickupRange(AltoClef mod) { + return 0; + } + @Override protected boolean isEqualResource(ResourceTask other) { if (other instanceof CraftInInventoryTask task) { diff --git a/src/main/java/adris/altoclef/tasks/DoToClosestBlockTask.java b/src/main/java/adris/altoclef/tasks/DoToClosestBlockTask.java index 046ad91a..1dec1606 100644 --- a/src/main/java/adris/altoclef/tasks/DoToClosestBlockTask.java +++ b/src/main/java/adris/altoclef/tasks/DoToClosestBlockTask.java @@ -57,7 +57,7 @@ protected Optional getClosestTo(AltoClef mod, Vec3d pos) { if (_getClosest != null) { return _getClosest.apply(pos); } - return mod.getBlockTracker().getNearestTracking(pos, _isValid, _targetBlocks); + return mod.getBlockScanner().getNearestBlock(pos, _isValid, _targetBlocks); } @Override @@ -80,17 +80,17 @@ protected boolean isValid(AltoClef mod, BlockPos obj) { // Our valid predicate if (_isValid != null && !_isValid.test(obj)) return false; // Correct block - return mod.getBlockTracker().blockIsValid(obj, _targetBlocks); + return mod.getBlockScanner().isBlockAtPosition(obj, _targetBlocks); } @Override protected void onStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(_targetBlocks); + } @Override protected void onStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(_targetBlocks); + } @Override diff --git a/src/main/java/adris/altoclef/tasks/GetRidOfExtraWaterBucketTask.java b/src/main/java/adris/altoclef/tasks/GetRidOfExtraWaterBucketTask.java new file mode 100644 index 00000000..6a5441c8 --- /dev/null +++ b/src/main/java/adris/altoclef/tasks/GetRidOfExtraWaterBucketTask.java @@ -0,0 +1,54 @@ +package adris.altoclef.tasks; + +import adris.altoclef.AltoClef; +import adris.altoclef.tasks.resources.CollectBucketLiquidTask; +import adris.altoclef.tasksystem.Task; +import adris.altoclef.util.ItemTarget; +import net.minecraft.item.Items; + +/** + * use when bot has too many water buckets but you dont want to throw them out + */ +public class GetRidOfExtraWaterBucketTask extends Task { + + private boolean needsPickup = false; + + @Override + protected void onStart(AltoClef mod) { + + } + + @Override + protected Task onTick(AltoClef mod) { + if (mod.getItemStorage().getItemCount(Items.WATER_BUCKET) != 0 && !needsPickup) { + return new InteractWithBlockTask(new ItemTarget(Items.WATER_BUCKET, 1),mod.getPlayer().getBlockPos().down(), false); + } + + needsPickup = true; + if (mod.getItemStorage().getItemCount(Items.WATER_BUCKET) < 1) { + return new CollectBucketLiquidTask.CollectWaterBucketTask(1); + } + + return null; + } + + @Override + public boolean isFinished(AltoClef mod) { + return mod.getItemStorage().getItemCount(Items.WATER_BUCKET) == 1 && needsPickup; + } + + @Override + protected void onStop(AltoClef mod, Task interruptTask) { + + } + + @Override + protected boolean isEqual(Task other) { + return other instanceof GetRidOfExtraWaterBucketTask; + } + + @Override + protected String toDebugString() { + return null; + } +} diff --git a/src/main/java/adris/altoclef/tasks/InteractWithBlockTask.java b/src/main/java/adris/altoclef/tasks/InteractWithBlockTask.java index e06d1bfb..31fdbd2b 100644 --- a/src/main/java/adris/altoclef/tasks/InteractWithBlockTask.java +++ b/src/main/java/adris/altoclef/tasks/InteractWithBlockTask.java @@ -66,6 +66,7 @@ public class InteractWithBlockTask extends Task { }; private Task _unstuckTask = null; private ClickResponse _cachedClickStatus = ClickResponse.CANT_REACH; + private int waitingForClickTicks = 0; public InteractWithBlockTask(ItemTarget toUse, Direction direction, BlockPos target, Input interactInput, boolean walkInto, Vec3i interactOffset, boolean shiftClick) { _toUse = toUse; @@ -285,7 +286,7 @@ protected Task onTick(AltoClef mod) { } if (!_moveChecker.check(mod)) { Debug.logMessage("Failed, blacklisting and wandering."); - mod.getBlockTracker().requestBlockUnreachable(_target); + mod.getBlockScanner().requestBlockUnreachable(_target); return _wanderTask; } @@ -309,6 +310,19 @@ protected Task onTick(AltoClef mod) { proc.onLostControl(); } _clickTimer.reset(); + + // try to get unstuck by pressing shift + waitingForClickTicks++; + if (waitingForClickTicks % 25 == 0 && _shiftClick) { + mod.getInputControls().hold(Input.SNEAK); + mod.log("trying to press shift"); + } + + if (waitingForClickTicks > 10*20) { + mod.log("trying to wander"); + waitingForClickTicks = 0; + return _wanderTask; + } } case CLICK_ATTEMPTED -> { setDebugState("Clicking."); diff --git a/src/main/java/adris/altoclef/tasks/ResourceTask.java b/src/main/java/adris/altoclef/tasks/ResourceTask.java index 7513a5e1..ec7ca81e 100644 --- a/src/main/java/adris/altoclef/tasks/ResourceTask.java +++ b/src/main/java/adris/altoclef/tasks/ResourceTask.java @@ -47,6 +47,7 @@ public abstract class ResourceTask extends Task implements ITaskCanForce { // Extra resource parameters private Block[] _mineIfPresent = null; private boolean _forceDimension = false; + private boolean allowContainers = false; private Dimension _targetDimension; private BlockPos _mineLastClosest = null; @@ -80,9 +81,6 @@ public boolean shouldForce(AltoClef mod, Task interruptingCandidate) { protected void onStart(AltoClef mod) { mod.getBehaviour().push(); //removeThrowawayItems(_itemTargets); - if (_mineIfPresent != null) { - mod.getBlockTracker().trackBlock(_mineIfPresent); - } onResourceStart(mod); } @@ -138,7 +136,7 @@ protected Task onTick(AltoClef mod) { } } - double range = mod.getModSettings().getResourcePickupRange(); + double range = getPickupRange(mod); Optional closest = mod.getEntityTracker().getClosestItemDrop(mod.getPlayer().getPos(), _itemTargets); if (range < 0 || (closest.isPresent() && closest.get().isInRange(mod.getPlayer(), range)) || (_pickupTask.isActive() && !_pickupTask.isFinished(mod))) { setDebugState("Picking up"); @@ -148,7 +146,7 @@ protected Task onTick(AltoClef mod) { } // Check for chests and grab resources from them. - if (_currentContainer == null) { + if (_currentContainer == null && allowContainers) { List containersWithItem = mod.getItemStorage().getContainersWithItem(Arrays.stream(_itemTargets).reduce(new Item[0], (items, target) -> ArrayUtils.addAll(items, target.getMatches()), ArrayUtils::addAll)); if (!containersWithItem.isEmpty()) { ContainerCache closest = containersWithItem.stream().min(StlHelper.compareValues(container -> container.getBlockPos().getSquaredDistance(mod.getPlayer().getPos()))).get(); @@ -177,8 +175,8 @@ protected Task onTick(AltoClef mod) { ArrayList satisfiedReqs = new ArrayList<>(Arrays.asList(_mineIfPresent)); satisfiedReqs.removeIf(block -> !StorageHelper.miningRequirementMet(mod, MiningRequirement.getMinimumRequirementForBlock(block))); if (!satisfiedReqs.isEmpty()) { - if (mod.getBlockTracker().anyFound(satisfiedReqs.toArray(Block[]::new))) { - Optional closest = mod.getBlockTracker().getNearestTracking(mod.getPlayer().getPos(), _mineIfPresent); + if (mod.getBlockScanner().anyFound(satisfiedReqs.toArray(Block[]::new))) { + Optional closest = mod.getBlockScanner().getNearestBlock(_mineIfPresent); if (closest.isPresent() && closest.get().isWithinDistance(mod.getPlayer().getPos(), mod.getModSettings().getResourceMineRange())) { _mineLastClosest = closest.get(); } @@ -203,12 +201,13 @@ protected Task onTick(AltoClef mod) { return onResourceTick(mod); } + protected double getPickupRange(AltoClef mod) { + return mod.getModSettings().getResourcePickupRange(); + } + @Override protected void onStop(AltoClef mod, Task interruptTask) { mod.getBehaviour().pop(); - if (_mineIfPresent != null) { - mod.getBlockTracker().stopTracking(_mineIfPresent); - } onResourceStop(mod, interruptTask); } @@ -261,6 +260,14 @@ public ResourceTask forceDimension(Dimension dimension) { return this; } + public void setAllowContainers(boolean value) { + this.allowContainers = value; + } + + public boolean getAllowContainers() { + return allowContainers; + } + protected abstract boolean shouldAvoidPickingUp(AltoClef mod); protected abstract void onResourceStart(AltoClef mod); diff --git a/src/main/java/adris/altoclef/tasks/SafeNetherPortalTask.java b/src/main/java/adris/altoclef/tasks/SafeNetherPortalTask.java new file mode 100644 index 00000000..0840fb37 --- /dev/null +++ b/src/main/java/adris/altoclef/tasks/SafeNetherPortalTask.java @@ -0,0 +1,209 @@ +package adris.altoclef.tasks; + +import adris.altoclef.AltoClef; +import adris.altoclef.tasks.construction.PlaceBlockTask; +import adris.altoclef.tasks.construction.PlaceStructureBlockTask; +import adris.altoclef.tasksystem.Task; +import adris.altoclef.util.helpers.ItemHelper; +import adris.altoclef.util.helpers.LookHelper; +import baritone.api.utils.input.Input; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.client.MinecraftClient; +import net.minecraft.item.Item; +import net.minecraft.state.property.Properties; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; + +import java.util.ArrayList; +import java.util.List; + +public class SafeNetherPortalTask extends Task { + private boolean finished = false; + private List positions = null; + private List directions = null; + private Direction.Axis axis = null; + + @Override + protected void onStart(AltoClef mod) { + mod.getClientBaritone().getInputOverrideHandler().clearAllKeys(); + } + + @Override + protected Task onTick(AltoClef mod) { + if (mod.getPlayer().getPortalCooldown() < 10) { + if (positions != null && directions != null) { + BlockPos pos1 = mod.getPlayer().getSteppingPos().offset(axis, 1); + BlockPos pos2 = mod.getPlayer().getSteppingPos().offset(axis, -1); + + if (mod.getWorld().getBlockState(pos1).isAir() || mod.getWorld().getBlockState(pos1).getBlock().equals(Blocks.SOUL_SAND)) { + boolean passed = false; + for (Direction dir : Direction.values()) { + if (mod.getWorld().getBlockState(pos1.up().offset(dir)).getBlock().equals(Blocks.NETHER_PORTAL)) { + passed = true; + break; + } + } + if (passed) { + return new ReplaceSafeBlock(pos1); + } + } + + if (mod.getWorld().getBlockState(pos2).isAir() || mod.getWorld().getBlockState(pos2).getBlock().equals(Blocks.SOUL_SAND)) { + boolean passed = false; + for (Direction dir : Direction.values()) { + if (mod.getWorld().getBlockState(pos2.up().offset(dir)).getBlock().equals(Blocks.NETHER_PORTAL)) { + passed = true; + break; + } + } + if (passed) { + return new ReplaceSafeBlock(pos2); + } + } + } + finished = true; + setDebugState("We are not in a portal"); + return null; + } + + BlockState state = mod.getWorld().getBlockState(mod.getPlayer().getBlockPos()); + if (positions == null || directions == null) { + if (state.getBlock().equals(Blocks.NETHER_PORTAL)) { + axis = state.get(Properties.HORIZONTAL_AXIS); + + positions = new ArrayList<>(); + positions.add(mod.getPlayer().getBlockPos()); + for (Direction dir : Direction.values()) { + if (dir.getAxis().isVertical()) continue; + + BlockPos pos = mod.getPlayer().getBlockPos().offset(dir); + if (mod.getWorld().getBlockState(pos).getBlock().equals(Blocks.NETHER_PORTAL)) { + positions.add(pos); + } + } + + directions = List.of(Direction.WEST, Direction.EAST); + + if (axis == Direction.Axis.X) { + directions = List.of(Direction.NORTH, Direction.SOUTH); + } + } else { + finished = true; + setDebugState("We are not standing inside a nether portal block"); + } + } else { + + for (BlockPos pos : positions) { + for (Direction dir : directions) { + BlockPos newPos = pos.down().offset(dir); + if (mod.getWorld().getBlockState(newPos).isAir() || mod.getWorld().getBlockState(newPos).getBlock().equals(Blocks.SOUL_SAND)) { + setDebugState("Changing block..."); + return new ReplaceSafeBlock(newPos); + } + } + } + + // did not find any block thats not safe + finished = true; + setDebugState("Portal is safe"); + return null; + } + + + return null; + } + + @Override + protected void onStop(AltoClef mod, Task interruptTask) { + mod.getInputControls().release(Input.MOVE_FORWARD); + mod.getInputControls().release(Input.SNEAK); + mod.getInputControls().release(Input.CLICK_LEFT); + mod.getClientBaritone().getInputOverrideHandler().clearAllKeys(); + } + + @Override + protected boolean isEqual(Task other) { + return other instanceof SafeNetherPortalTask; + } + + @Override + protected String toDebugString() { + return "Making nether portal safe"; + } + + @Override + public boolean isFinished(AltoClef mod) { + return finished; + } + + private static class ReplaceSafeBlock extends Task { + + private final BlockPos pos; + private boolean finished = false; + + public ReplaceSafeBlock(BlockPos pos) { + this.pos = pos; + } + + + @Override + protected void onStart(AltoClef mod) { + mod.getClientBaritone().getInputOverrideHandler().clearAllKeys(); + } + + @Override + protected Task onTick(AltoClef mod) { + if (mod.getWorld().getBlockState(pos).isAir()) { + setDebugState("Placing block..."); + return new PlaceStructureBlockTask(pos); + } + + if (mod.getWorld().getBlockState(pos).getBlock().equals(Blocks.SOUL_SAND)) { + LookHelper.lookAt(mod, pos); + + HitResult result = mod.getPlayer().raycast(3, MinecraftClient.getInstance().getTickDelta(), true); + if (result instanceof BlockHitResult blockHitResult && mod.getWorld().getBlockState(blockHitResult.getBlockPos()).getBlock().equals(Blocks.NETHER_PORTAL)) { + setDebugState("Getting closer to target..."); + mod.getInputControls().hold(Input.MOVE_FORWARD); + mod.getInputControls().hold(Input.SNEAK); + } else { + setDebugState("Breaking block"); + mod.getInputControls().release(Input.MOVE_FORWARD); + mod.getInputControls().release(Input.SNEAK); + mod.getInputControls().hold(Input.CLICK_LEFT); + } + return null; + } + + this.finished = true; + return null; + } + + @Override + protected void onStop(AltoClef mod, Task interruptTask) { + mod.getInputControls().release(Input.MOVE_FORWARD); + mod.getInputControls().release(Input.SNEAK); + mod.getInputControls().release(Input.CLICK_LEFT); + mod.getClientBaritone().getInputOverrideHandler().clearAllKeys(); + } + + @Override + public boolean isFinished(AltoClef mod) { + return finished; + } + + @Override + protected boolean isEqual(Task other) { + return other instanceof ReplaceSafeBlock same && same.pos.equals(this.pos); + } + + @Override + protected String toDebugString() { + return "Making sure " + pos + " is safe"; + } + } + +} diff --git a/src/main/java/adris/altoclef/tasks/construction/CoverWithBlocksTask.java b/src/main/java/adris/altoclef/tasks/construction/CoverWithBlocksTask.java deleted file mode 100644 index cbd81703..00000000 --- a/src/main/java/adris/altoclef/tasks/construction/CoverWithBlocksTask.java +++ /dev/null @@ -1,143 +0,0 @@ -package adris.altoclef.tasks.construction; - -import adris.altoclef.AltoClef; -import adris.altoclef.tasks.movement.DefaultGoToDimensionTask; -import adris.altoclef.tasks.movement.TimeoutWanderTask; -import adris.altoclef.tasks.resources.MineAndCollectTask; -import adris.altoclef.tasksystem.Task; -import adris.altoclef.util.Dimension; -import adris.altoclef.util.ItemTarget; -import adris.altoclef.util.MiningRequirement; -import adris.altoclef.util.helpers.ItemHelper; -import adris.altoclef.util.helpers.StorageHelper; -import adris.altoclef.util.helpers.WorldHelper; -import adris.altoclef.util.slots.Slot; -import adris.altoclef.util.time.TimerGame; -import net.minecraft.block.Block; -import net.minecraft.block.Blocks; -import net.minecraft.block.FallingBlock; -import net.minecraft.block.LeavesBlock; -import net.minecraft.item.BlockItem; -import net.minecraft.item.Item; -import net.minecraft.util.math.BlockPos; - -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.function.Predicate; - -public class CoverWithBlocksTask extends Task { - private static final TimerGame timer = new TimerGame(30); - private static final Task goToNether = new DefaultGoToDimensionTask(Dimension.NETHER); - private static final Task goToOverworld = new DefaultGoToDimensionTask(Dimension.OVERWORLD); - private static Task getBlocks; - private BlockPos lavaPos; - - @Override - protected void onStart(AltoClef mod) { - timer.reset(); - mod.getBlockTracker().trackBlock(Blocks.LAVA); - } - - @Override - protected Task onTick(AltoClef mod) { - Item[] throwAways = mod.getModSettings().getThrowawayItems(mod, true); - Item[] throwAwaysToUse = Arrays.stream(throwAways).filter(item -> !(Block.getBlockFromItem(item) instanceof LeavesBlock) && - !(Block.getBlockFromItem(item) instanceof FallingBlock) && item instanceof BlockItem).toArray(Item[]::new); - int throwAwayCount = mod.getItemStorage().getItemCount(throwAwaysToUse); - if (getBlocks != null && throwAwayCount < 128) { - setDebugState("Getting blocks to cover nether lava."); - timer.reset(); - return getBlocks; - } else { - getBlocks = null; - } - Block[] blocks = ItemHelper.itemsToBlocks(throwAwaysToUse); - if (!mod.getItemStorage().hasItem(throwAwaysToUse) && mod.getBlockTracker().anyFound(blocks)) { - timer.reset(); - ItemTarget throwAwaysTarget = new ItemTarget(throwAwaysToUse); - getBlocks = new MineAndCollectTask(throwAwaysTarget, blocks, MiningRequirement.STONE); - return getBlocks; - } - if (!mod.getItemStorage().hasItem(throwAwaysToUse) && !mod.getBlockTracker().anyFound(blocks)) { - timer.reset(); - if (WorldHelper.getCurrentDimension() == Dimension.OVERWORLD) { - setDebugState("Trying nether to search for blocks."); - return goToNether; - } - if (WorldHelper.getCurrentDimension() == Dimension.NETHER) { - setDebugState("Trying overworld to search for blocks."); - return goToOverworld; - } - } - if (WorldHelper.getCurrentDimension() != Dimension.NETHER) { - setDebugState("Going to nether."); - timer.reset(); - return goToNether; - } - if (coverLavaWithSand(mod) == null) { - setDebugState("Searching valid lava."); - timer.reset(); - return new TimeoutWanderTask(); - } - setDebugState("Covering lava with blocks"); - return coverLavaWithSand(mod); - } - - private Task coverLavaWithSand(AltoClef mod) { - Predicate validLava = blockPos -> - mod.getWorld().getBlockState(blockPos).getFluidState().isStill() && - WorldHelper.isAir(mod, blockPos.up()) && - (!WorldHelper.isBlock(mod, blockPos.north(), Blocks.LAVA) || - !WorldHelper.isBlock(mod, blockPos.south(), Blocks.LAVA) || - !WorldHelper.isBlock(mod, blockPos.east(), Blocks.LAVA) || - !WorldHelper.isBlock(mod, blockPos.west(), Blocks.LAVA) || - !WorldHelper.isBlock(mod, blockPos.north().up(), Blocks.LAVA) || - !WorldHelper.isBlock(mod, blockPos.south().up(), Blocks.LAVA) || - !WorldHelper.isBlock(mod, blockPos.east().up(), Blocks.LAVA) || - !WorldHelper.isBlock(mod, blockPos.west().up(), Blocks.LAVA)); - Optional lava = mod.getBlockTracker().getNearestTracking(validLava, Blocks.LAVA); - if (lava.isPresent()) { - if (lavaPos == null) { - lavaPos = lava.get(); - timer.reset(); - } - if (timer.elapsed()) { - lavaPos = lava.get(); - timer.reset(); - } - if (!WorldHelper.isBlock(mod, lavaPos, Blocks.LAVA) || !WorldHelper.isAir(mod, lavaPos.up()) || - !mod.getWorld().getBlockState(lavaPos).getFluidState().isStill()) { - lavaPos = lava.get(); - timer.reset(); - } - Item[] throwAways = mod.getModSettings().getThrowawayItems(mod, true); - Item[] throwAwaysToUse = Arrays.stream(throwAways).filter(item -> !(Block.getBlockFromItem(item) instanceof LeavesBlock) && - !(Block.getBlockFromItem(item) instanceof FallingBlock) && item instanceof BlockItem).toArray(Item[]::new); - List presentThrowAways = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, throwAwaysToUse); - if (!presentThrowAways.isEmpty()) { - for (Slot presentThrowAway : presentThrowAways) { - Item throwAwayItem = StorageHelper.getItemStackInSlot(presentThrowAway).getItem(); - Block throwAwayBlock = Block.getBlockFromItem(throwAwayItem); - return new PlaceBlockTask(lavaPos, throwAwayBlock); - } - } - } - return null; - } - - @Override - protected void onStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.LAVA); - } - - @Override - protected boolean isEqual(Task other) { - return other instanceof CoverWithBlocksTask; - } - - @Override - protected String toDebugString() { - return "Covering nether lava with blocks"; - } -} diff --git a/src/main/java/adris/altoclef/tasks/construction/CoverWithSandTask.java b/src/main/java/adris/altoclef/tasks/construction/CoverWithSandTask.java deleted file mode 100644 index 3afc0f8a..00000000 --- a/src/main/java/adris/altoclef/tasks/construction/CoverWithSandTask.java +++ /dev/null @@ -1,111 +0,0 @@ -package adris.altoclef.tasks.construction; - -import adris.altoclef.AltoClef; -import adris.altoclef.TaskCatalogue; -import adris.altoclef.tasks.movement.DefaultGoToDimensionTask; -import adris.altoclef.tasks.movement.TimeoutWanderTask; -import adris.altoclef.tasksystem.Task; -import adris.altoclef.util.Dimension; -import adris.altoclef.util.helpers.WorldHelper; -import adris.altoclef.util.time.TimerGame; -import net.minecraft.block.Blocks; -import net.minecraft.item.Items; -import net.minecraft.util.math.BlockPos; - -import java.util.Optional; -import java.util.function.Predicate; - -public class CoverWithSandTask extends Task { - private static final TimerGame timer = new TimerGame(30); - private static final Task getSand = TaskCatalogue.getItemTask(Items.SAND, 128); - private static final Task goToNether = new DefaultGoToDimensionTask(Dimension.NETHER); - private static final Task goToOverworld = new DefaultGoToDimensionTask(Dimension.OVERWORLD); - private BlockPos lavaPos; - - @Override - protected void onStart(AltoClef mod) { - timer.reset(); - mod.getBlockTracker().trackBlock(Blocks.LAVA); - } - - @Override - protected Task onTick(AltoClef mod) { - if (getSand != null && getSand.isActive() && !getSand.isFinished(mod)) { - setDebugState("Getting sands to cover nether lava."); - timer.reset(); - return getSand; - } - if (WorldHelper.getCurrentDimension() == Dimension.OVERWORLD && - mod.getItemStorage().getItemCount(Items.SAND) < 64) { - timer.reset(); - return getSand; - } - if (WorldHelper.getCurrentDimension() == Dimension.OVERWORLD && - mod.getItemStorage().getItemCount(Items.SAND) > 64) { - setDebugState("Going to nether."); - timer.reset(); - return goToNether; - } - if (WorldHelper.getCurrentDimension() == Dimension.NETHER && - !mod.getItemStorage().hasItem(Items.SAND)) { - setDebugState("Going to overworld to get sand."); - timer.reset(); - return goToOverworld; - } - if (coverLavaWithSand(mod) == null) { - setDebugState("Searching valid lava."); - timer.reset(); - return new TimeoutWanderTask(); - } - setDebugState("Covering lava with sand"); - return coverLavaWithSand(mod); - } - - private Task coverLavaWithSand(AltoClef mod) { - Predicate validLava = blockPos -> - mod.getWorld().getBlockState(blockPos).getFluidState().isStill() && - WorldHelper.isAir(mod, blockPos.up()) && - (!WorldHelper.isBlock(mod, blockPos.north(), Blocks.LAVA) || - !WorldHelper.isBlock(mod, blockPos.south(), Blocks.LAVA) || - !WorldHelper.isBlock(mod, blockPos.east(), Blocks.LAVA) || - !WorldHelper.isBlock(mod, blockPos.west(), Blocks.LAVA) || - !WorldHelper.isBlock(mod, blockPos.north().up(), Blocks.LAVA) || - !WorldHelper.isBlock(mod, blockPos.south().up(), Blocks.LAVA) || - !WorldHelper.isBlock(mod, blockPos.east().up(), Blocks.LAVA) || - !WorldHelper.isBlock(mod, blockPos.west().up(), Blocks.LAVA)); - Optional lava = mod.getBlockTracker().getNearestTracking(validLava, Blocks.LAVA); - if (lava.isPresent()) { - if (lavaPos == null) { - lavaPos = lava.get(); - timer.reset(); - } - if (timer.elapsed()) { - lavaPos = lava.get(); - timer.reset(); - } - if (!WorldHelper.isBlock(mod, lavaPos, Blocks.LAVA) || (!WorldHelper.isAir(mod, lavaPos.up()) && - !WorldHelper.isFallingBlock(lavaPos.up())) || - !mod.getWorld().getBlockState(lavaPos).getFluidState().isStill()) { - lavaPos = lava.get(); - timer.reset(); - } - return new PlaceBlockTask(lavaPos.up(), Blocks.SAND); - } - return null; - } - - @Override - protected void onStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.LAVA); - } - - @Override - protected boolean isEqual(Task other) { - return other instanceof CoverWithSandTask; - } - - @Override - protected String toDebugString() { - return "Covering nether lava with sand"; - } -} diff --git a/src/main/java/adris/altoclef/tasks/construction/DestroyBlockTask.java b/src/main/java/adris/altoclef/tasks/construction/DestroyBlockTask.java index 675efe06..26c614ef 100644 --- a/src/main/java/adris/altoclef/tasks/construction/DestroyBlockTask.java +++ b/src/main/java/adris/altoclef/tasks/construction/DestroyBlockTask.java @@ -255,7 +255,7 @@ protected Task onTick(AltoClef mod) { if (entity instanceof PillagerEntity && _pos.isWithinDistance(entity.getPos(), 144)) { Debug.logMessage("Blacklisting pillager wool."); // Request the block at the position to be marked as unreachable - mod.getBlockTracker().requestBlockUnreachable(_pos, 0); + mod.getBlockScanner().requestBlockUnreachable(_pos, 0); } } } @@ -308,7 +308,7 @@ protected Task onTick(AltoClef mod) { if (!_moveChecker.check(mod)) { _moveChecker.reset(); // Request the block at the position to be marked as unreachable - mod.getBlockTracker().requestBlockUnreachable(_pos); + mod.getBlockScanner().requestBlockUnreachable(_pos); } // Check if the block above the position is not solid, the player is above the position, @@ -338,8 +338,10 @@ protected Task onTick(AltoClef mod) { } else { setDebugState("Getting to block..."); if (isMining && mod.getPlayer().isTouchingWater()) { + setDebugState("We are in water... holding break button"); isMining = false; - mod.getBlockTracker().requestBlockUnreachable(_pos); + mod.getBlockScanner().requestBlockUnreachable(_pos); + mod.getInputControls().hold(Input.CLICK_LEFT); } else { isMining = false; } diff --git a/src/main/java/adris/altoclef/tasks/construction/PlaceBlockNearbyTask.java b/src/main/java/adris/altoclef/tasks/construction/PlaceBlockNearbyTask.java index 84f2a41e..bafe4637 100644 --- a/src/main/java/adris/altoclef/tasks/construction/PlaceBlockNearbyTask.java +++ b/src/main/java/adris/altoclef/tasks/construction/PlaceBlockNearbyTask.java @@ -90,7 +90,7 @@ protected Task onTick(AltoClef mod) { // Close screen first ItemStack cursorStack = StorageHelper.getItemStackInCursorSlot(); if (!cursorStack.isEmpty()) { - Optional moveTo = mod.getItemStorage().getSlotThatCanFitInPlayerInventory(cursorStack, false); + /* Optional moveTo = mod.getItemStorage().getSlotThatCanFitInPlayerInventory(cursorStack, false); if (moveTo.isPresent()) { mod.getSlotHandler().clickSlot(moveTo.get(), 0, SlotActionType.PICKUP); return null; @@ -105,7 +105,7 @@ protected Task onTick(AltoClef mod) { mod.getSlotHandler().clickSlot(garbage.get(), 0, SlotActionType.PICKUP); return null; } - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); + mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP);*/ } else { StorageHelper.closeScreen(); } @@ -132,7 +132,7 @@ protected Task onTick(AltoClef mod) { Debug.logMessage("Failed placing, wandering and trying again."); LookHelper.randomOrientation(mod); if (_tryPlace != null) { - mod.getBlockTracker().requestBlockUnreachable(_tryPlace); + mod.getBlockScanner().requestBlockUnreachable(_tryPlace); _tryPlace = null; } return _wander; diff --git a/src/main/java/adris/altoclef/tasks/construction/PlaceBlockTask.java b/src/main/java/adris/altoclef/tasks/construction/PlaceBlockTask.java index aa6ae3de..520cca30 100644 --- a/src/main/java/adris/altoclef/tasks/construction/PlaceBlockTask.java +++ b/src/main/java/adris/altoclef/tasks/construction/PlaceBlockTask.java @@ -32,20 +32,20 @@ public class PlaceBlockTask extends Task implements ITaskRequiresGrounded { private static final int MIN_MATERIALS = 1; private static final int PREFERRED_MATERIALS = 32; - private final BlockPos _target; - private final Block[] _toPlace; - private final boolean _useThrowaways; - private final boolean _autoCollectStructureBlocks; - private final MovementProgressChecker _progressChecker = new MovementProgressChecker(); - private final TimeoutWanderTask _wanderTask = new TimeoutWanderTask(5); // This can get stuck forever, so we increase the range. - private Task _materialTask; - private int _failCount = 0; + private final BlockPos target; + private final Block[] toPlace; + private final boolean useThrowaways; + private final boolean autoCollectStructureBlocks; + private final MovementProgressChecker progressChecker = new MovementProgressChecker(); + private final TimeoutWanderTask wanderTask = new TimeoutWanderTask(5); // This can get stuck forever, so we increase the range. + private Task materialTask; + private int failCount = 0; public PlaceBlockTask(BlockPos target, Block[] toPlace, boolean useThrowaways, boolean autoCollectStructureBlocks) { - _target = target; - _toPlace = toPlace; - _useThrowaways = useThrowaways; - _autoCollectStructureBlocks = autoCollectStructureBlocks; + this.target = target; + this.toPlace = toPlace; + this.useThrowaways = useThrowaways; + this.autoCollectStructureBlocks = autoCollectStructureBlocks; } public PlaceBlockTask(BlockPos target, Block... toPlace) { @@ -63,7 +63,7 @@ public static Task getMaterialTask(int count) { @Override protected void onStart(AltoClef mod) { - _progressChecker.reset(); + progressChecker.reset(); // If we get interrupted by another task, this might cause problems... //_wanderTask.resetWander(); } @@ -89,38 +89,38 @@ protected Task onTick(AltoClef mod) { } } // Perform timeout wander - if (_wanderTask.isActive() && !_wanderTask.isFinished(mod)) { + if (wanderTask.isActive() && !wanderTask.isFinished(mod)) { setDebugState("Wandering."); - _progressChecker.reset(); - return _wanderTask; + progressChecker.reset(); + return wanderTask; } - if (_autoCollectStructureBlocks) { - if (_materialTask != null && _materialTask.isActive() && !_materialTask.isFinished(mod)) { + if (autoCollectStructureBlocks) { + if (materialTask != null && materialTask.isActive() && !materialTask.isFinished(mod)) { setDebugState("No structure items, collecting cobblestone + dirt as default."); if (getMaterialCount(mod) < PREFERRED_MATERIALS) { - return _materialTask; + return materialTask; } else { - _materialTask = null; + materialTask = null; } } //Item[] items = Util.toArray(Item.class, mod.getClientBaritoneSettings().acceptableThrowawayItems.value); if (getMaterialCount(mod) < MIN_MATERIALS) { // TODO: Mine items, extract their resource key somehow. - _materialTask = getMaterialTask(PREFERRED_MATERIALS); - _progressChecker.reset(); - return _materialTask; + materialTask = getMaterialTask(PREFERRED_MATERIALS); + progressChecker.reset(); + return materialTask; } } // Check if we're approaching our point. If we fail, wander for a bit. - if (!_progressChecker.check(mod)) { - _failCount++; + if (!progressChecker.check(mod)) { + failCount++; if (!tryingAlternativeWay()) { Debug.logMessage("Failed to place, wandering timeout."); - return _wanderTask; + return wanderTask; } else { Debug.logMessage("Trying alternative way of placing block..."); } @@ -130,14 +130,14 @@ protected Task onTick(AltoClef mod) { // Place block if (tryingAlternativeWay()) { setDebugState("Alternative way: Trying to go above block to place block."); - return new GetToBlockTask(_target.up(), false); + return new GetToBlockTask(target.up(), false); } else { setDebugState("Letting baritone place a block."); // Perform baritone placement if (!mod.getClientBaritone().getBuilderProcess().isActive()) { Debug.logInternal("Run Structure Build"); ISchematic schematic = new PlaceStructureSchematic(mod); - mod.getClientBaritone().getBuilderProcess().build("structure", schematic, _target); + mod.getClientBaritone().getBuilderProcess().build("structure", schematic, target); } } return null; @@ -153,7 +153,7 @@ protected void onStop(AltoClef mod, Task interruptTask) { @Override protected boolean isEqual(Task other) { if (other instanceof PlaceBlockTask task) { - return task._target.equals(_target) && task._useThrowaways == _useThrowaways && Arrays.equals(task._toPlace, _toPlace); + return task.target.equals(target) && task.useThrowaways == useThrowaways && Arrays.equals(task.toPlace, toPlace); } return false; } @@ -161,20 +161,20 @@ protected boolean isEqual(Task other) { @Override public boolean isFinished(AltoClef mod) { assert MinecraftClient.getInstance().world != null; - if (_useThrowaways) { - return WorldHelper.isSolid(mod, _target); + if (useThrowaways) { + return WorldHelper.isSolid(mod, target); } - BlockState state = mod.getWorld().getBlockState(_target); - return ArrayUtils.contains(_toPlace, state.getBlock()); + BlockState state = mod.getWorld().getBlockState(target); + return ArrayUtils.contains(toPlace, state.getBlock()); } @Override protected String toDebugString() { - return "Place structure" + ArrayUtils.toString(_toPlace) + " at " + _target.toShortString(); + return "Place structure" + ArrayUtils.toString(toPlace) + " at " + target.toShortString(); } private boolean tryingAlternativeWay() { - return _failCount % 4 == 3; + return failCount % 4 == 3; } private class PlaceStructureSchematic extends AbstractSchematic { @@ -193,10 +193,10 @@ public BlockState desiredState(int x, int y, int z, BlockState blockState, List< if (!available.isEmpty()) { for (BlockState possible : available) { if (possible == null) continue; - if (_useThrowaways && _mod.getClientBaritoneSettings().acceptableThrowawayItems.value.contains(possible.getBlock().asItem())) { + if (useThrowaways && _mod.getClientBaritoneSettings().acceptableThrowawayItems.value.contains(possible.getBlock().asItem())) { return possible; } - if (Arrays.asList(_toPlace).contains(possible.getBlock())) { + if (Arrays.asList(toPlace).contains(possible.getBlock())) { return possible; } } diff --git a/src/main/java/adris/altoclef/tasks/construction/PlaceObsidianBucketTask.java b/src/main/java/adris/altoclef/tasks/construction/PlaceObsidianBucketTask.java index 884d0cdb..b0a3e254 100644 --- a/src/main/java/adris/altoclef/tasks/construction/PlaceObsidianBucketTask.java +++ b/src/main/java/adris/altoclef/tasks/construction/PlaceObsidianBucketTask.java @@ -3,14 +3,16 @@ import adris.altoclef.AltoClef; import adris.altoclef.Debug; import adris.altoclef.TaskCatalogue; +import adris.altoclef.commands.BlockScanner; import adris.altoclef.tasks.InteractWithBlockTask; import adris.altoclef.tasks.movement.GetToBlockTask; import adris.altoclef.tasks.movement.TimeoutWanderTask; import adris.altoclef.tasksystem.Task; -import adris.altoclef.trackers.BlockTracker; import adris.altoclef.util.ItemTarget; +import adris.altoclef.util.helpers.ItemHelper; import adris.altoclef.util.helpers.WorldHelper; import adris.altoclef.util.progresscheck.MovementProgressChecker; +import net.minecraft.block.Block; import net.minecraft.block.Blocks; import net.minecraft.item.Items; import net.minecraft.util.math.BlockPos; @@ -107,7 +109,7 @@ protected Task onTick(AltoClef mod) { } // Clear leftover water - if (mod.getBlockTracker().blockIsValid(_pos, Blocks.OBSIDIAN) && mod.getBlockTracker().blockIsValid(_pos.up(), Blocks.WATER)) { + if (mod.getBlockScanner().isBlockAtPosition(_pos, Blocks.OBSIDIAN) && mod.getBlockScanner().isBlockAtPosition(_pos.up(), Blocks.WATER)) { return new ClearLiquidTask(_pos.up()); } @@ -120,7 +122,7 @@ protected Task onTick(AltoClef mod) { // Make sure we have a lava bucket if (!mod.getItemStorage().hasItem(Items.LAVA_BUCKET)) { // The only excuse is that we have lava at our position. - if (!mod.getBlockTracker().blockIsValid(_pos, Blocks.LAVA)) { + if (!mod.getBlockScanner().isBlockAtPosition(_pos, Blocks.LAVA)) { _progressChecker.reset(); return TaskCatalogue.getItemTask(Items.LAVA_BUCKET, 1); } @@ -129,7 +131,7 @@ protected Task onTick(AltoClef mod) { // Check progress if (!_progressChecker.check(mod)) { mod.getClientBaritone().getPathingBehavior().forceCancel(); - mod.getBlockTracker().requestBlockUnreachable(_pos); + mod.getBlockScanner().requestBlockUnreachable(_pos); _progressChecker.reset(); return new TimeoutWanderTask(5); } @@ -139,7 +141,9 @@ protected Task onTick(AltoClef mod) { if (WorldHelper.isSolid(mod, _currentCastTarget)) { _currentCastTarget = null; } else { - return new PlaceStructureBlockTask(_currentCastTarget); + return new PlaceBlockTask(_currentCastTarget, + Arrays.stream(ItemHelper.itemsToBlocks(mod.getModSettings().getThrowawayItems(mod))).filter((b)-> !Arrays.stream(ItemHelper.itemsToBlocks(ItemHelper.LEAVES)).toList().contains(b)).toArray(Block[]::new) + ); } } @@ -245,17 +249,17 @@ protected void onStop(AltoClef mod, Task interruptTask) { @Override public boolean isFinished(AltoClef mod) { // Get the BlockTracker instance from the mod - BlockTracker blockTracker = mod.getBlockTracker(); + BlockScanner blockTracker = mod.getBlockScanner(); // Get the position of the block to check BlockPos pos = _pos; // Check if the block at the specified position is obsidian - boolean isObsidian = blockTracker.blockIsValid(pos, Blocks.OBSIDIAN); + boolean isObsidian = blockTracker.isBlockAtPosition(pos, Blocks.OBSIDIAN); Debug.logInternal("isObsidian: " + isObsidian); // Check if there is no water block above the specified position - boolean isNotWaterAbove = !blockTracker.blockIsValid(pos.up(), Blocks.WATER); + boolean isNotWaterAbove = !blockTracker.isBlockAtPosition(pos.up(), Blocks.WATER); Debug.logInternal("isNotWaterAbove: " + isNotWaterAbove); // The task is considered finished if the block is obsidian and there is no water above diff --git a/src/main/java/adris/altoclef/tasks/construction/PlaceSignTask.java b/src/main/java/adris/altoclef/tasks/construction/PlaceSignTask.java deleted file mode 100644 index 11a82b07..00000000 --- a/src/main/java/adris/altoclef/tasks/construction/PlaceSignTask.java +++ /dev/null @@ -1,170 +0,0 @@ -package adris.altoclef.tasks.construction; - -import adris.altoclef.AltoClef; -import adris.altoclef.Debug; -import adris.altoclef.TaskCatalogue; -import adris.altoclef.tasks.InteractWithBlockTask; -import adris.altoclef.tasksystem.Task; -import adris.altoclef.util.ItemTarget; -import adris.altoclef.util.helpers.ItemHelper; -import adris.altoclef.util.helpers.StorageHelper; -import adris.altoclef.util.slots.Slot; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.ingame.SignEditScreen; -import net.minecraft.item.ItemStack; -import net.minecraft.screen.slot.SlotActionType; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; - -import java.util.Optional; - -public class PlaceSignTask extends Task { - - private final BlockPos _target; - private final String _message; - - private boolean _finished; - - public PlaceSignTask(BlockPos pos, String message) { - _target = pos; - _message = message; - } - - public PlaceSignTask(String message) { - this(null, message); - } - - private static boolean isSign(Block block) { - for (Block check : ItemHelper.WOOD_SIGNS_ALL) { - if (check == block) return true; - } - return false; - } - - @Override - protected void onStart(AltoClef mod) { - _finished = false; - } - - @Override - protected Task onTick(AltoClef mod) { - - if (editingSign()) { - return editSign(mod); - } - - // Make sure we have a sign to place - if (!StorageHelper.hasCataloguedItem(mod, "sign")) { - return TaskCatalogue.getItemTask("sign", 1); - } - - // Place sign - if (placeAnywhere()) { - return new PlaceBlockNearbyTask(ItemHelper.WOOD_SIGNS_ALL); - } else { - - assert MinecraftClient.getInstance().world != null; - BlockState b = MinecraftClient.getInstance().world.getBlockState(_target); - - if (!isSign(b.getBlock()) && !b.isAir() && b.getBlock() != Blocks.WATER && b.getBlock() != Blocks.LAVA) { - return new DestroyBlockTask(_target); - } - - return new InteractWithBlockTask(new ItemTarget("sign", 1), Direction.UP, _target.down(), true); - } - } - - private Task editSign(AltoClef mod) { - SignEditScreen screen = (SignEditScreen) MinecraftClient.getInstance().currentScreen; - assert screen != null; - - StringBuilder currentLine = new StringBuilder(); - - int lines = 0; - - final int SIGN_TEXT_MAX_WIDTH = 90; - - for (char c : _message.toCharArray()) { - currentLine.append(c); - - if (c == '\n' || MinecraftClient.getInstance().textRenderer.getWidth(currentLine.toString()) > SIGN_TEXT_MAX_WIDTH) { - currentLine.delete(0, currentLine.length()); - if (c != '\n') { - currentLine.append(c); - } - lines++; - if (lines >= 4) { - Debug.logWarning("Too much text to fit on sign! Got Cut off."); - break; - } - - // Add newline - screen.keyPressed(257, 36, 0); - //Debug.logMessage("NEW LINE ADDED BEFORE: " + c); - } - // keycode don't matter - //int keyCode = java.awt.event.KeyEvent.getExtendedKeyCodeForChar(c); - screen.charTyped(c, -1); - //screen.keyPressed(keyCode, -1, ) - } - screen.close(); - _finished = true; - - return null; - } - - @Override - protected void onStop(AltoClef mod, Task interruptTask) { - ItemStack cursorStack = StorageHelper.getItemStackInCursorSlot(); - if (!cursorStack.isEmpty()) { - Optional moveTo = mod.getItemStorage().getSlotThatCanFitInPlayerInventory(cursorStack, false); - moveTo.ifPresent(slot -> mod.getSlotHandler().clickSlot(slot, 0, SlotActionType.PICKUP)); - if (ItemHelper.canThrowAwayStack(mod, cursorStack)) { - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); - } - Optional garbage = StorageHelper.getGarbageSlot(mod); - // Try throwing away cursor slot if it's garbage - garbage.ifPresent(slot -> mod.getSlotHandler().clickSlot(slot, 0, SlotActionType.PICKUP)); - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); - } else { - StorageHelper.closeScreen(); - } - } - - @Override - public boolean isFinished(AltoClef mod) { - return _finished; - } - - @Override - protected boolean isEqual(Task other) { - if (other instanceof PlaceSignTask task) { - if (!task._message.equals(_message)) return false; - if ((task._target == null) != (_target == null)) return false; - if (task._target != null) { - return task._target.equals(_target); - } - return true; - } - return false; - } - - @Override - protected String toDebugString() { - if (placeAnywhere()) { - return "Place Sign Anywhere"; - } - return "Place Sign at " + _target.toShortString(); - } - - private boolean placeAnywhere() { - return _target == null; - } - - private boolean editingSign() { - return MinecraftClient.getInstance().currentScreen instanceof SignEditScreen; - } -} diff --git a/src/main/java/adris/altoclef/tasks/construction/compound/ConstructNetherPortalBucketTask.java b/src/main/java/adris/altoclef/tasks/construction/compound/ConstructNetherPortalBucketTask.java index f551f620..ef54cec6 100644 --- a/src/main/java/adris/altoclef/tasks/construction/compound/ConstructNetherPortalBucketTask.java +++ b/src/main/java/adris/altoclef/tasks/construction/compound/ConstructNetherPortalBucketTask.java @@ -7,9 +7,10 @@ import adris.altoclef.tasks.construction.ClearLiquidTask; import adris.altoclef.tasks.construction.DestroyBlockTask; import adris.altoclef.tasks.construction.PlaceObsidianBucketTask; +import adris.altoclef.tasks.movement.GetWithinRangeOfBlockTask; import adris.altoclef.tasks.movement.PickupDroppedItemTask; import adris.altoclef.tasks.movement.TimeoutWanderTask; -import adris.altoclef.tasks.speedrun.MarvionBeatMinecraftTask; +import adris.altoclef.tasks.speedrun.beatgame.BeatMinecraftTask; import adris.altoclef.tasksystem.Task; import adris.altoclef.util.ItemTarget; import adris.altoclef.util.helpers.WorldHelper; @@ -25,8 +26,7 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3i; -import java.util.HashSet; -import java.util.List; +import java.util.*; /** * Build a nether portal by casting each piece with water + lava. @@ -82,23 +82,21 @@ public class ConstructNetherPortalBucketTask extends Task { // This can only really be explained visually, sorry! private static final Vec3i PORTALABLE_REGION_SIZE = new Vec3i(4, 6, 6); private static final Vec3i PORTAL_ORIGIN_RELATIVE_TO_REGION = new Vec3i(1, 0, 2); - private final TimerGame _lavaSearchTimer = new TimerGame(5); - private final MovementProgressChecker _progressChecker = new MovementProgressChecker(); + private final TimerGame lavaSearchTimer = new TimerGame(5); + private final MovementProgressChecker progressChecker = new MovementProgressChecker(); private final TimeoutWanderTask wanderTask = new TimeoutWanderTask(5); // Stored here to cache lava blacklist - private final Task _collectLavaTask = TaskCatalogue.getItemTask(Items.LAVA_BUCKET, 1); - private final TimerGame _refreshTimer = new TimerGame(11); - private BlockPos _portalOrigin = null; + private final Task collectLavaTask = TaskCatalogue.getItemTask(Items.LAVA_BUCKET, 1); + private final TimerGame refreshTimer = new TimerGame(11); + private BlockPos portalOrigin = null; + private Task getToLakeTask = null; + private BlockPos currentDestroyTarget = null; - //private BlockPos _currentLavaTarget = null; - private BlockPos _currentDestroyTarget = null; - private boolean _firstSearch = false; + private boolean firstSearch = false; @Override protected void onStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.LAVA); - - _currentDestroyTarget = null; + currentDestroyTarget = null; mod.getBehaviour().push(); @@ -106,10 +104,10 @@ protected void onStart(AltoClef mod) { // Also avoid placing on the lava + water // Also avoid breaking the cast frame mod.getBehaviour().avoidBlockBreaking(block -> { - if (_portalOrigin != null) { + if (portalOrigin != null) { // Don't break frame for (Vec3i framePosRelative : PORTAL_FRAME) { - BlockPos framePos = _portalOrigin.add(framePosRelative); + BlockPos framePos = portalOrigin.add(framePosRelative); if (block.equals(framePos)) { return mod.getWorld().getBlockState(framePos).getBlock() == Blocks.OBSIDIAN; } @@ -121,73 +119,69 @@ protected void onStart(AltoClef mod) { // Protect some used items mod.getBehaviour().addProtectedItems(Items.WATER_BUCKET, Items.LAVA_BUCKET, Items.FLINT_AND_STEEL, Items.FIRE_CHARGE); - _progressChecker.reset(); + progressChecker.reset(); } @Override protected Task onTick(AltoClef mod) { - if (MarvionBeatMinecraftTask.getConfig().renderDistanceManipulation) { - MinecraftClient.getInstance().options.getViewDistance().setValue(2); - MinecraftClient.getInstance().options.getEntityDistanceScaling().setValue(0.5); - } - if (_portalOrigin != null) { - if (mod.getWorld().getBlockState(_portalOrigin.up()).getBlock() == Blocks.NETHER_PORTAL) { + if (portalOrigin != null) { + if (mod.getWorld().getBlockState(portalOrigin.up()).getBlock() == Blocks.NETHER_PORTAL) { setDebugState("Done constructing nether portal."); - mod.getBlockTracker().addBlock(Blocks.NETHER_PORTAL, _portalOrigin.up()); + mod.getBlockScanner().addBlock(Blocks.NETHER_PORTAL, portalOrigin.up()); return null; } } if (mod.getClientBaritone().getPathingBehavior().isPathing()) { - _progressChecker.reset(); + progressChecker.reset(); } if (wanderTask.isActive() && !wanderTask.isFinished(mod)) { setDebugState("Trying again."); - _progressChecker.reset(); + progressChecker.reset(); return wanderTask; } - if (!_progressChecker.check(mod)) { + if (!progressChecker.check(mod)) { mod.getClientBaritone().getPathingBehavior().forceCancel(); - if (_portalOrigin != null && _currentDestroyTarget != null) { - mod.getBlockTracker().requestBlockUnreachable(_portalOrigin); - mod.getBlockTracker().requestBlockUnreachable(_currentDestroyTarget); - if (mod.getBlockTracker().unreachable(_portalOrigin) && mod.getBlockTracker().unreachable(_currentDestroyTarget)) { - _portalOrigin = null; - _currentDestroyTarget = null; + if (portalOrigin != null && currentDestroyTarget != null) { + mod.getBlockScanner().requestBlockUnreachable(portalOrigin); + mod.getBlockScanner().requestBlockUnreachable(currentDestroyTarget); + if (mod.getBlockScanner().isUnreachable(portalOrigin) && mod.getBlockScanner().isUnreachable(currentDestroyTarget)) { + portalOrigin = null; + currentDestroyTarget = null; } return wanderTask; } } - if (_refreshTimer.elapsed()) { + if (refreshTimer.elapsed()) { Debug.logMessage("Duct tape: Refreshing inventory again just in case"); - _refreshTimer.reset(); + refreshTimer.reset(); mod.getSlotHandler().refreshInventory(); } //If too far, reset. - if (_portalOrigin != null && !_portalOrigin.isWithinDistance(mod.getPlayer().getPos(), 2000)) { - _portalOrigin = null; - _currentDestroyTarget = null; + if (portalOrigin != null && !portalOrigin.isWithinDistance(mod.getPlayer().getPos(), 2000)) { + portalOrigin = null; + currentDestroyTarget = null; } - if (_currentDestroyTarget != null) { - if (!WorldHelper.isSolid(mod, _currentDestroyTarget)) { - _currentDestroyTarget = null; + if (currentDestroyTarget != null) { + if (!WorldHelper.isSolid(mod, currentDestroyTarget)) { + currentDestroyTarget = null; } else { - return new DestroyBlockTask(_currentDestroyTarget); + return new DestroyBlockTask(currentDestroyTarget); } } // Get flint & steel if we don't have one if (!mod.getItemStorage().hasItem(Items.FLINT_AND_STEEL) && !mod.getItemStorage().hasItem(Items.FIRE_CHARGE)) { setDebugState("Getting flint & steel"); - _progressChecker.reset(); + progressChecker.reset(); return TaskCatalogue.getItemTask(Items.FLINT_AND_STEEL, 1); } // Get bucket if we don't have one. int bucketCount = mod.getItemStorage().getItemCount(Items.BUCKET, Items.LAVA_BUCKET, Items.WATER_BUCKET); if (bucketCount < 2) { setDebugState("Getting buckets"); - _progressChecker.reset(); + progressChecker.reset(); // If we have lava/water, get the inverse. Otherwise we dropped a bucket, just get a bucket. if (mod.getItemStorage().hasItem(Items.LAVA_BUCKET)) { return TaskCatalogue.getItemTask(Items.WATER_BUCKET, 1); @@ -200,21 +194,21 @@ protected Task onTick(AltoClef mod) { return TaskCatalogue.getItemTask(Items.BUCKET, 2); } - boolean needsToLookForPortal = _portalOrigin == null; + boolean needsToLookForPortal = portalOrigin == null; if (needsToLookForPortal) { - _progressChecker.reset(); + progressChecker.reset(); // Get water before searching, just for convenience. if (!mod.getItemStorage().hasItem(Items.WATER_BUCKET)) { setDebugState("Getting water"); - _progressChecker.reset(); + progressChecker.reset(); return TaskCatalogue.getItemTask(Items.WATER_BUCKET, 1); } boolean foundSpot = false; - if (_firstSearch || _lavaSearchTimer.elapsed()) { - _firstSearch = false; - _lavaSearchTimer.reset(); + if (firstSearch || lavaSearchTimer.elapsed()) { + firstSearch = false; + lavaSearchTimer.reset(); Debug.logMessage("(Searching for lava lake with portalable spot nearby...)"); BlockPos lavaPos = findLavaLake(mod, mod.getPlayer().getBlockPos()); if (lavaPos != null) { @@ -223,8 +217,11 @@ protected Task onTick(AltoClef mod) { if (foundPortalRegion == null) { Debug.logWarning("Failed to find portalable region nearby. Consider increasing the search timeout range"); } else { - _portalOrigin = foundPortalRegion.add(PORTAL_ORIGIN_RELATIVE_TO_REGION); + portalOrigin = foundPortalRegion.add(PORTAL_ORIGIN_RELATIVE_TO_REGION); foundSpot = true; + + getToLakeTask = new GetWithinRangeOfBlockTask(portalOrigin,7); + return getToLakeTask; } } else { Debug.logMessage("(lava lake not found)"); @@ -237,9 +234,13 @@ protected Task onTick(AltoClef mod) { } } + if (BeatMinecraftTask.isTaskRunning(mod,getToLakeTask)) { + return getToLakeTask; + } + // We have a portal, now build it. for (Vec3i framePosRelative : PORTAL_FRAME) { - BlockPos framePos = _portalOrigin.add(framePosRelative); + BlockPos framePos = portalOrigin.add(framePosRelative); Block frameBlock = mod.getWorld().getBlockState(framePos).getBlock(); if (frameBlock == Blocks.OBSIDIAN) { // Already satisfied, clear water above if need be. @@ -254,24 +255,24 @@ protected Task onTick(AltoClef mod) { // Get lava early so placing it is faster if (!mod.getItemStorage().hasItem(Items.LAVA_BUCKET) && frameBlock != Blocks.LAVA) { setDebugState("Collecting lava"); - _progressChecker.reset(); - return _collectLavaTask; + progressChecker.reset(); + return collectLavaTask; } // We need to place obsidian here. - if (mod.getBlockTracker().unreachable(framePos)) { - _portalOrigin = null; + if (mod.getBlockScanner().isUnreachable(framePos)) { + portalOrigin = null; } return new PlaceObsidianBucketTask(framePos); } // Now, clear the inside. for (Vec3i offs : PORTAL_INTERIOR) { - BlockPos p = _portalOrigin.add(offs); + BlockPos p = portalOrigin.add(offs); assert MinecraftClient.getInstance().world != null; if (!MinecraftClient.getInstance().world.getBlockState(p).isAir()) { setDebugState("Clearing inside of portal"); - _currentDestroyTarget = p; + currentDestroyTarget = p; return null; //return new DestroyBlockTask(p); } @@ -279,12 +280,11 @@ protected Task onTick(AltoClef mod) { setDebugState("Flinting and Steeling"); // Flint and steel it baby - return new InteractWithBlockTask(new ItemTarget(new Item[]{Items.FLINT_AND_STEEL, Items.FIRE_CHARGE}, 1), Direction.UP, _portalOrigin.down(), true); + return new InteractWithBlockTask(new ItemTarget(new Item[]{Items.FLINT_AND_STEEL, Items.FIRE_CHARGE}, 1), Direction.UP, portalOrigin.down(), true); } @Override protected void onStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.LAVA); mod.getBehaviour().pop(); } @@ -302,7 +302,8 @@ private BlockPos findLavaLake(AltoClef mod, BlockPos playerPos) { HashSet alreadyExplored = new HashSet<>(); double nearestSqDistance = Double.POSITIVE_INFINITY; BlockPos nearestLake = null; - List lavas = mod.getBlockTracker().getKnownLocations(Blocks.LAVA); + List lavas = mod.getBlockScanner().getKnownLocations(Blocks.LAVA); + if (!lavas.isEmpty()) { for (BlockPos pos : lavas) { if (alreadyExplored.contains(pos)) continue; @@ -322,35 +323,37 @@ private BlockPos findLavaLake(AltoClef mod, BlockPos playerPos) { return nearestLake; } - // Used to flood-scan for blocks of lava. - private int getNumberOfBlocksAdjacent(HashSet alreadyExplored, BlockPos origin) { - // Base case: We already explored this one - if (alreadyExplored.contains(origin)) return 0; - alreadyExplored.add(origin); - - // Base case: We hit a non-full lava block. - assert MinecraftClient.getInstance().world != null; - BlockState s = MinecraftClient.getInstance().world.getBlockState(origin); - if (s.getBlock() != Blocks.LAVA) { - return 0; - } else { - // We may not be a full lava block - if (!s.getFluidState().isStill()) return 0; - int level = s.getFluidState().getLevel(); - //Debug.logMessage("TEST LEVEL: " + level + ", " + height); - // Only accept FULL SOURCE BLOCKS - if (level != 8) return 0; - } - - BlockPos[] toCheck = new BlockPos[]{origin.north(), origin.south(), origin.east(), origin.west(), origin.up(), origin.down()}; + private int getNumberOfBlocksAdjacent(HashSet alreadyExplored, BlockPos start) { + Queue queue = new ArrayDeque<>(); + queue.add(start); int bonus = 0; - for (BlockPos check : toCheck) { - // This block is new! Explore out from it. - bonus += getNumberOfBlocksAdjacent(alreadyExplored, check); + + while (!queue.isEmpty()) { + BlockPos origin = queue.poll(); + if (alreadyExplored.contains(origin)) continue; + alreadyExplored.add(origin); + + // Base case: We hit a non-full lava block. + assert MinecraftClient.getInstance().world != null; + BlockState s = MinecraftClient.getInstance().world.getBlockState(origin); + if (s.getBlock() != Blocks.LAVA) { + continue; + } else { + // We may not be a full lava block + if (!s.getFluidState().isStill()) continue; + int level = s.getFluidState().getLevel(); + //Debug.logMessage("TEST LEVEL: " + level + ", " + height); + // Only accept FULL SOURCE BLOCKS + if (level != 8) continue; + } + + queue.addAll(List.of(origin.north(), origin.south(), origin.east(), origin.west(), origin.up(), origin.down())); + + bonus++; } - return bonus + 1; + return bonus; } // Get a region that a portal can fit into diff --git a/src/main/java/adris/altoclef/tasks/construction/compound/ConstructNetherPortalObsidianTask.java b/src/main/java/adris/altoclef/tasks/construction/compound/ConstructNetherPortalObsidianTask.java index 93c708cc..3b1d9058 100644 --- a/src/main/java/adris/altoclef/tasks/construction/compound/ConstructNetherPortalObsidianTask.java +++ b/src/main/java/adris/altoclef/tasks/construction/compound/ConstructNetherPortalObsidianTask.java @@ -6,18 +6,26 @@ import adris.altoclef.tasks.InteractWithBlockTask; import adris.altoclef.tasks.construction.DestroyBlockTask; import adris.altoclef.tasks.construction.PlaceBlockTask; +import adris.altoclef.tasks.construction.PlaceStructureBlockTask; +import adris.altoclef.tasks.movement.GetToBlockTask; import adris.altoclef.tasks.movement.TimeoutWanderTask; import adris.altoclef.tasksystem.Task; import adris.altoclef.util.ItemTarget; +import adris.altoclef.util.helpers.ItemHelper; import adris.altoclef.util.helpers.WorldHelper; import adris.altoclef.util.time.TimerGame; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.client.MinecraftClient; +import net.minecraft.item.Item; import net.minecraft.item.Items; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3i; +import net.minecraft.world.World; + +import java.util.LinkedList; +import java.util.Queue; /** * Build a nether portal with obsidian blocks. @@ -118,7 +126,7 @@ protected Task onTick(AltoClef mod) { if (_origin != null) { if (mod.getWorld().getBlockState(_origin.up()).getBlock() == Blocks.NETHER_PORTAL) { setDebugState("Done constructing nether portal."); - mod.getBlockTracker().addBlock(Blocks.NETHER_PORTAL, _origin.up()); + mod.getBlockScanner().addBlock(Blocks.NETHER_PORTAL, _origin.up()); return null; } } @@ -127,7 +135,7 @@ protected Task onTick(AltoClef mod) { if (_origin != null) { for (Vec3i frameOffs : PORTAL_FRAME) { BlockPos framePos = _origin.add(frameOffs); - if (!mod.getBlockTracker().blockIsValid(framePos, Blocks.OBSIDIAN)) { + if (!mod.getBlockScanner().isBlockAtPosition(framePos, Blocks.OBSIDIAN)) { placeTarget = framePos; break; } @@ -160,6 +168,32 @@ protected Task onTick(AltoClef mod) { // Place frame if (placeTarget != null) { + World world = mod.getWorld(); + + if (surroundedByAir(world,placeTarget)) { + LinkedList queue = new LinkedList<>(); + queue.add(placeTarget); + while (surroundedByAir(world, placeTarget)) { + BlockPos pos = queue.removeFirst(); + + if (surroundedByAir(world,pos)) { + queue.add(pos.up()); + queue.add(pos.down()); + queue.add(pos.east()); + queue.add(pos.west()); + queue.add(pos.north()); + queue.add(pos.south()); + } else { + return new PlaceStructureBlockTask(pos); + } + } + + mod.logWarning("Did not find any block to place obsidian on"); + } + + if (!world.getBlockState(placeTarget).isAir() && !world.getBlockState(placeTarget).getBlock().equals(Blocks.OBSIDIAN)) { + return new DestroyBlockTask(placeTarget); + } setDebugState("Placing frame..."); return new PlaceBlockTask(placeTarget, Blocks.OBSIDIAN); } @@ -179,6 +213,11 @@ protected Task onTick(AltoClef mod) { return new InteractWithBlockTask(new ItemTarget(Items.FLINT_AND_STEEL, 1), Direction.UP, _origin.down(), true); } + private boolean surroundedByAir(World world, BlockPos pos) { + return world.getBlockState(pos.west()).isAir() && world.getBlockState(pos.south()).isAir() && world.getBlockState(pos.east()).isAir() && + world.getBlockState(pos.up()).isAir() && world.getBlockState(pos.down()).isAir() && world.getBlockState(pos.north()).isAir(); + } + @Override protected void onStop(AltoClef mod, Task interruptTask) { mod.getBehaviour().pop(); diff --git a/src/main/java/adris/altoclef/tasks/construction/compound/ConstructNetherPortalSpeedrunTask.java b/src/main/java/adris/altoclef/tasks/construction/compound/ConstructNetherPortalSpeedrunTask.java index ab9e60e2..23372d47 100644 --- a/src/main/java/adris/altoclef/tasks/construction/compound/ConstructNetherPortalSpeedrunTask.java +++ b/src/main/java/adris/altoclef/tasks/construction/compound/ConstructNetherPortalSpeedrunTask.java @@ -112,7 +112,6 @@ public class ConstructNetherPortalSpeedrunTask extends adris.altoclef.tasksystem protected void onStart(AltoClef mod) { _isPlacingLiquid = false; _portalFrameBuilt = false; - mod.getBlockTracker().trackBlock(Blocks.LAVA); mod.getBehaviour().push(); //mod.getConfigState().setAllowWalkThroughFlowingWater(true); // Avoid breaking frame. @@ -319,7 +318,6 @@ protected adris.altoclef.tasksystem.Task onTick(AltoClef mod) { @Override protected void onStop(AltoClef mod, adris.altoclef.tasksystem.Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.LAVA); mod.getBehaviour().pop(); } @@ -340,7 +338,7 @@ private BlockPos findLavaLake(AltoClef mod, BlockPos playerPos) { double nearestSqDistance = Double.POSITIVE_INFINITY; BlockPos nearestLake = null; - for (BlockPos pos : mod.getBlockTracker().getKnownLocations(Blocks.LAVA)) { + for (BlockPos pos : mod.getBlockScanner().getKnownLocations(Blocks.LAVA)) { if (alreadyExplored.contains(pos)) continue; double sqDist = playerPos.getSquaredDistance(pos); if (sqDist < nearestSqDistance) { diff --git a/src/main/java/adris/altoclef/tasks/container/AbstractDoToStorageContainerTask.java b/src/main/java/adris/altoclef/tasks/container/AbstractDoToStorageContainerTask.java index 72266c4d..a7253fb3 100644 --- a/src/main/java/adris/altoclef/tasks/container/AbstractDoToStorageContainerTask.java +++ b/src/main/java/adris/altoclef/tasks/container/AbstractDoToStorageContainerTask.java @@ -18,7 +18,7 @@ */ public abstract class AbstractDoToStorageContainerTask extends Task { - private ContainerType _currentContainerType = null; + private ContainerType currentContainerType = null; @Override protected void onStart(AltoClef mod) { @@ -32,28 +32,25 @@ protected Task onTick(AltoClef mod) { // No container found if (containerTarget.isEmpty()) { setDebugState("Wandering"); - _currentContainerType = null; - return onSearchWander(mod); + currentContainerType = null; + return onSearchWander(); } BlockPos targetPos = containerTarget.get(); // We're open - if (_currentContainerType != null && ContainerType.screenHandlerMatches(_currentContainerType)) { + if (currentContainerType != null && ContainerType.screenHandlerMatches(currentContainerType)) { - // Optional lastInteracted = mod.getItemStorage().getLastBlockPosInteraction(); - //if (lastInteracted.isPresent() && lastInteracted.get().equals(targetPos)) { Optional cache = mod.getItemStorage().getContainerAtPosition(targetPos); if (cache.isPresent()) { return onContainerOpenSubtask(mod, cache.get()); } - //} } // Get to the container if (mod.getChunkTracker().isChunkLoaded(targetPos)) { Block type = mod.getWorld().getBlockState(targetPos).getBlock(); - _currentContainerType = ContainerType.getFromBlock(type); + currentContainerType = ContainerType.getFromBlock(type); } if (WorldHelper.isChest(mod, targetPos) && WorldHelper.isSolid(mod, targetPos.up()) && WorldHelper.canBreak(mod, targetPos.up())) { setDebugState("Clearing block above chest"); @@ -74,7 +71,7 @@ protected void onStop(AltoClef mod, Task interruptTask) { // Virtual // TODO: Interface this - protected Task onSearchWander(AltoClef mod) { + protected Task onSearchWander() { return new TimeoutWanderTask(); } } diff --git a/src/main/java/adris/altoclef/tasks/container/CraftInTableTask.java b/src/main/java/adris/altoclef/tasks/container/CraftInTableTask.java index d4d8a7a2..e26ada18 100644 --- a/src/main/java/adris/altoclef/tasks/container/CraftInTableTask.java +++ b/src/main/java/adris/altoclef/tasks/container/CraftInTableTask.java @@ -35,20 +35,20 @@ */ public class CraftInTableTask extends ResourceTask { - private final RecipeTarget[] _targets; + private final RecipeTarget[] targets; - private final DoCraftInTableTask _craftTask; + private final DoCraftInTableTask craftTask; public CraftInTableTask(RecipeTarget[] targets) { super(extractItemTargets(targets)); - _targets = targets; - _craftTask = new DoCraftInTableTask(_targets); + this.targets = targets; + craftTask = new DoCraftInTableTask(this.targets); } public CraftInTableTask(RecipeTarget target, boolean collect, boolean ignoreUncataloguedSlots) { super(new ItemTarget(target.getOutputItem(), target.getTargetCount())); - _targets = new RecipeTarget[]{target}; - _craftTask = new DoCraftInTableTask(_targets, collect, ignoreUncataloguedSlots); + targets = new RecipeTarget[]{target}; + craftTask = new DoCraftInTableTask(targets, collect, ignoreUncataloguedSlots); } public CraftInTableTask(RecipeTarget target) { @@ -98,7 +98,7 @@ protected void onResourceStart(AltoClef mod) { */ @Override protected Task onResourceTick(AltoClef mod) { - return _craftTask; + return craftTask; } /** @@ -148,7 +148,7 @@ protected boolean isEqualResource(ResourceTask other) { // Check if the other task is an instance of CraftInTableTask if (other instanceof CraftInTableTask task) { // Compare the craftTask of the two tasks - return _craftTask.isEqual(task._craftTask); + return craftTask.isEqual(task.craftTask); } // The other task is not a CraftInTableTask, return false return false; @@ -163,7 +163,7 @@ protected boolean isEqualResource(ResourceTask other) { */ @Override protected String toDebugStringName() { - return (_craftTask != null) ? _craftTask.toDebugString() : null; + return (craftTask != null) ? craftTask.toDebugString() : null; } /** @@ -172,7 +172,7 @@ protected String toDebugStringName() { * @return The recipe targets. */ public RecipeTarget[] getRecipeTargets() { - return Arrays.copyOf(_targets, _targets.length); + return Arrays.copyOf(targets, targets.length); } } @@ -299,7 +299,7 @@ protected Task onTick(AltoClef mod) { mod.getBehaviour().addProtectedItems(getMaterialsArray()); // Avoid breaking crafting tables - List craftingTablePositions = mod.getBlockTracker().getKnownLocations(Blocks.CRAFTING_TABLE); + List craftingTablePositions = mod.getBlockScanner().getKnownLocations(Blocks.CRAFTING_TABLE); for (BlockPos craftingTablePos : craftingTablePositions) { mod.getBehaviour().avoidBlockBreaking(craftingTablePos); } @@ -436,7 +436,7 @@ public boolean isFinished(AltoClef mod) { @Override protected double getCostToMakeNew(AltoClef mod) { // Get the nearest crafting table. - Optional closestCraftingTable = mod.getBlockTracker().getNearestTracking(Blocks.CRAFTING_TABLE); + Optional closestCraftingTable = mod.getBlockScanner().getNearestBlock(Blocks.CRAFTING_TABLE); // If a crafting table is within 40 blocks of the player, return positive infinity. if (closestCraftingTable.isPresent() && closestCraftingTable.get().isWithinDistance(mod.getPlayer().getPos(), 40)) { diff --git a/src/main/java/adris/altoclef/tasks/container/DoStuffInContainerTask.java b/src/main/java/adris/altoclef/tasks/container/DoStuffInContainerTask.java index 643be098..95588f1b 100644 --- a/src/main/java/adris/altoclef/tasks/container/DoStuffInContainerTask.java +++ b/src/main/java/adris/altoclef/tasks/container/DoStuffInContainerTask.java @@ -28,22 +28,24 @@ */ public abstract class DoStuffInContainerTask extends Task { - private final ItemTarget _containerTarget; - private final Block[] _containerBlocks; + private final ItemTarget containerTarget; + private final Block[] containerBlocks; + + private final PlaceBlockNearbyTask placeTask; + // If we decided on placing, force place for at least 1 second + // (originally 10) + private final TimerGame placeForceTimer = new TimerGame(1); - private final PlaceBlockNearbyTask _placeTask; - // If we decided on placing, force place for at least 10 seconds - private final TimerGame _placeForceTimer = new TimerGame(10); // If we just placed something, stop placing and try going to the nearest container. - private final TimerGame _justPlacedTimer = new TimerGame(3); - private BlockPos _cachedContainerPosition = null; - private Task _openTableTask; + private final TimerGame justPlacedTimer = new TimerGame(3); + private BlockPos cachedContainerPosition = null; + private Task openTableTask; public DoStuffInContainerTask(Block[] containerBlocks, ItemTarget containerTarget) { - _containerBlocks = containerBlocks; - _containerTarget = containerTarget; + this.containerBlocks = containerBlocks; + this.containerTarget = containerTarget; - _placeTask = new PlaceBlockNearbyTask(_containerBlocks); + placeTask = new PlaceBlockNearbyTask(this.containerBlocks); } public DoStuffInContainerTask(Block containerBlock, ItemTarget containerTarget) { @@ -53,23 +55,21 @@ public DoStuffInContainerTask(Block containerBlock, ItemTarget containerTarget) @Override protected void onStart(AltoClef mod) { mod.getBehaviour().push(); - if (_openTableTask == null) { - _openTableTask = new DoToClosestBlockTask(InteractWithBlockTask::new, _containerBlocks); + if (openTableTask == null) { + openTableTask = new DoToClosestBlockTask(InteractWithBlockTask::new, containerBlocks); } - mod.getBlockTracker().trackBlock(_containerBlocks); - // Protect container since we might place it. - mod.getBehaviour().addProtectedItems(ItemHelper.blocksToItems(_containerBlocks)); + mod.getBehaviour().addProtectedItems(ItemHelper.blocksToItems(containerBlocks)); } @Override protected Task onTick(AltoClef mod) { // If we're placing, keep on placing. - if (mod.getItemStorage().hasItem(ItemHelper.blocksToItems(_containerBlocks)) && _placeTask.isActive() && !_placeTask.isFinished(mod)) { + if (mod.getItemStorage().hasItem(ItemHelper.blocksToItems(containerBlocks)) && placeTask.isActive() && !placeTask.isFinished(mod)) { setDebugState("Placing container"); - return _placeTask; + return placeTask; } if (isContainerOpen(mod)) { @@ -84,17 +84,17 @@ protected Task onTick(AltoClef mod) { Vec3d currentPos = mod.getPlayer().getPos(); BlockPos override = overrideContainerPosition(mod); - if (override != null && mod.getBlockTracker().blockIsValid(override, _containerBlocks)) { + if (override != null && mod.getBlockScanner().isBlockAtPosition(override, containerBlocks)) { // We have an override so go there instead. nearest = Optional.of(override); } else { // Track nearest container - nearest = mod.getBlockTracker().getNearestTracking(currentPos, blockPos -> WorldHelper.canReach(mod, blockPos), _containerBlocks); + nearest = mod.getBlockScanner().getNearestBlock(currentPos, blockPos -> WorldHelper.canReach(mod, blockPos), containerBlocks); } if (nearest.isEmpty()) { // If all else fails, try using our placed task - nearest = Optional.ofNullable(_placeTask.getPlaced()); - if (nearest.isPresent() && !mod.getBlockTracker().blockIsValid(nearest.get(), _containerBlocks)) { + nearest = Optional.ofNullable(placeTask.getPlaced()); + if (nearest.isPresent() && !mod.getBlockScanner().isBlockAtPosition(nearest.get(), containerBlocks)) { nearest = Optional.empty(); } } @@ -105,30 +105,30 @@ protected Task onTick(AltoClef mod) { // Make a new container if going to the container is a pretty bad cost. // Also keep on making the container if we're stuck in some if (costToWalk > getCostToMakeNew(mod)) { - _placeForceTimer.reset(); + placeForceTimer.reset(); } - if (nearest.isEmpty() || (!_placeForceTimer.elapsed() && _justPlacedTimer.elapsed())) { + if (nearest.isEmpty() || (!placeForceTimer.elapsed() && justPlacedTimer.elapsed())) { // It's cheaper to make a new one, or our only option. // We're no longer going to our previous container. - _cachedContainerPosition = null; + cachedContainerPosition = null; // Get if we don't have... - if (!mod.getItemStorage().hasItem(_containerTarget)) { + if (!mod.getItemStorage().hasItem(containerTarget)) { setDebugState("Getting container item"); - return TaskCatalogue.getItemTask(_containerTarget); + return TaskCatalogue.getItemTask(containerTarget); } setDebugState("Placing container..."); - _justPlacedTimer.reset(); + justPlacedTimer.reset(); // Now place! - return _placeTask; + return placeTask; } // This is insanely cursed. // TODO: Finish committing to optionals, this is ugly. - _cachedContainerPosition = nearest.get(); + cachedContainerPosition = nearest.get(); // Walk to it and open it @@ -151,12 +151,12 @@ protected Task onTick(AltoClef mod) { mod.getSlotHandler().clickSlot(toMoveTo.get(), 0, SlotActionType.PICKUP); return null; } - return _openTableTask; + return openTableTask; //return new GetToBlockTask(nearest, true); } public ItemTarget getContainerTarget() { - return _containerTarget; + return containerTarget; } // Virtual @@ -165,20 +165,19 @@ protected BlockPos overrideContainerPosition(AltoClef mod) { } protected BlockPos getTargetContainerPosition() { - return _cachedContainerPosition; + return cachedContainerPosition; } @Override protected void onStop(AltoClef mod, Task interruptTask) { mod.getBehaviour().pop(); - mod.getBlockTracker().stopTracking(_containerBlocks); } @Override protected boolean isEqual(Task other) { if (other instanceof DoStuffInContainerTask task) { - if (!Arrays.equals(task._containerBlocks, _containerBlocks)) return false; - if (!task._containerTarget.equals(_containerTarget)) return false; + if (!Arrays.equals(task.containerBlocks, containerBlocks)) return false; + if (!task.containerTarget.equals(containerTarget)) return false; return isSubTaskEqual(task); } return false; @@ -186,7 +185,7 @@ protected boolean isEqual(Task other) { @Override protected String toDebugString() { - return "Doing stuff in " + _containerTarget + " container"; + return "Doing stuff in " + containerTarget + " container"; } protected abstract boolean isSubTaskEqual(DoStuffInContainerTask other); diff --git a/src/main/java/adris/altoclef/tasks/container/SmeltInBlastFurnaceTask.java b/src/main/java/adris/altoclef/tasks/container/SmeltInBlastFurnaceTask.java index a5c05298..bb28807c 100644 --- a/src/main/java/adris/altoclef/tasks/container/SmeltInBlastFurnaceTask.java +++ b/src/main/java/adris/altoclef/tasks/container/SmeltInBlastFurnaceTask.java @@ -72,7 +72,6 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.BLAST_FURNACE); mod.getBehaviour().push(); if (_targets.length != 1) { Debug.logWarning("Tried smelting multiple targets, only one target is supported at a time!"); @@ -81,14 +80,13 @@ protected void onResourceStart(AltoClef mod) { @Override protected Task onResourceTick(AltoClef mod) { - Optional blastFurnacePos = mod.getBlockTracker().getNearestTracking(Blocks.BLAST_FURNACE); + Optional blastFurnacePos = mod.getBlockScanner().getNearestBlock(Blocks.BLAST_FURNACE); blastFurnacePos.ifPresent(blockPos -> mod.getBehaviour().avoidBlockBreaking(blockPos)); return _doTask; } @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.BLAST_FURNACE); mod.getBehaviour().pop(); // Close blast furnace screen ItemStack cursorStack = StorageHelper.getItemStackInCursorSlot(); diff --git a/src/main/java/adris/altoclef/tasks/container/SmeltInFurnaceTask.java b/src/main/java/adris/altoclef/tasks/container/SmeltInFurnaceTask.java index 59f32573..e66ee806 100644 --- a/src/main/java/adris/altoclef/tasks/container/SmeltInFurnaceTask.java +++ b/src/main/java/adris/altoclef/tasks/container/SmeltInFurnaceTask.java @@ -71,7 +71,6 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.FURNACE); mod.getBehaviour().push(); if (_targets.length != 1) { Debug.logWarning("Tried smelting multiple targets, only one target is supported at a time!"); @@ -80,14 +79,13 @@ protected void onResourceStart(AltoClef mod) { @Override protected Task onResourceTick(AltoClef mod) { - Optional furnacePos = mod.getBlockTracker().getNearestTracking(Blocks.FURNACE); + Optional furnacePos = mod.getBlockScanner().getNearestBlock(Blocks.FURNACE); furnacePos.ifPresent(blockPos -> mod.getBehaviour().avoidBlockBreaking(blockPos)); return _doTask; } @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.FURNACE); mod.getBehaviour().pop(); // Close furnace screen ItemStack cursorStack = StorageHelper.getItemStackInCursorSlot(); @@ -128,28 +126,28 @@ public SmeltTarget[] getTargets() { return _targets; } - @SuppressWarnings("ConditionCoveredByFurtherCondition") + static class DoSmeltInFurnaceTask extends DoStuffInContainerTask { - private final SmeltTarget _target; - private final FurnaceCache _furnaceCache = new FurnaceCache(); - private final ItemTarget _allMaterials; - private boolean _ignoreMaterials; + private final SmeltTarget target; + private final FurnaceCache furnaceCache = new FurnaceCache(); + private final ItemTarget allMaterials; + private boolean ignoreMaterials; public DoSmeltInFurnaceTask(SmeltTarget target) { super(Blocks.FURNACE, new ItemTarget(Items.FURNACE)); - _target = target; - _allMaterials = new ItemTarget(Stream.concat(Arrays.stream(_target.getMaterial().getMatches()), Arrays.stream(_target.getOptionalMaterials())).toArray(Item[]::new), _target.getMaterial().getTargetCount()); + this.target = target; + allMaterials = new ItemTarget(Stream.concat(Arrays.stream(this.target.getMaterial().getMatches()), Arrays.stream(this.target.getOptionalMaterials())).toArray(Item[]::new), this.target.getMaterial().getTargetCount()); } public void ignoreMaterials() { - _ignoreMaterials = true; + ignoreMaterials = true; } @Override protected boolean isSubTaskEqual(DoStuffInContainerTask other) { if (other instanceof DoSmeltInFurnaceTask task) { - return task._target.equals(_target) && task._ignoreMaterials == _ignoreMaterials; + return task.target.equals(target) && task.ignoreMaterials == ignoreMaterials; } return false; } @@ -163,44 +161,44 @@ protected boolean isContainerOpen(AltoClef mod) { protected Task onTick(AltoClef mod) { mod.getBehaviour().addProtectedItems(ItemHelper.PLANKS); mod.getBehaviour().addProtectedItems(Items.COAL); - mod.getBehaviour().addProtectedItems(_allMaterials.getMatches()); - mod.getBehaviour().addProtectedItems(_target.getMaterial().getMatches()); + mod.getBehaviour().addProtectedItems(allMaterials.getMatches()); + mod.getBehaviour().addProtectedItems(target.getMaterial().getMatches()); tryUpdateOpenFurnace(mod); // Include both regular + optional items - ItemTarget materialTarget = _allMaterials; - ItemTarget outputTarget = _target.getItem(); + ItemTarget materialTarget = allMaterials; + ItemTarget outputTarget = target.getItem(); // Materials needed = (mat_target (- 0*mat_in_inventory) - out_in_inventory - mat_in_furnace - out_in_furnace) // ^ 0 * mat_in_inventory because we always care aobut the TARGET materials, not how many LEFT there are. int materialsNeeded = materialTarget.getTargetCount() /*- mod.getItemStorage().getItemCountInventoryOnly(materialTarget.getMatches())*/ // See comment above - mod.getItemStorage().getItemCountInventoryOnly(outputTarget.getMatches()) - - (materialTarget.matches(_furnaceCache.materialSlot.getItem()) ? _furnaceCache.materialSlot.getCount() : 0) - - (outputTarget.matches(_furnaceCache.outputSlot.getItem()) ? _furnaceCache.outputSlot.getCount() : 0); - double totalFuelInFurnace = ItemHelper.getFuelAmount(_furnaceCache.fuelSlot) + _furnaceCache.burningFuelCount + _furnaceCache.burnPercentage; + - (materialTarget.matches(furnaceCache.materialSlot.getItem()) ? furnaceCache.materialSlot.getCount() : 0) + - (outputTarget.matches(furnaceCache.outputSlot.getItem()) ? furnaceCache.outputSlot.getCount() : 0); + double totalFuelInFurnace = ItemHelper.getFuelAmount(furnaceCache.fuelSlot) + furnaceCache.burningFuelCount + furnaceCache.burnPercentage; // Fuel needed = (mat_target - out_in_inventory - out_in_furnace - totalFuelInFurnace) - double fuelNeeded = _ignoreMaterials - ? Math.min(materialTarget.matches(_furnaceCache.materialSlot.getItem()) ? _furnaceCache.materialSlot.getCount() : 0, materialTarget.getTargetCount()) + double fuelNeeded = ignoreMaterials + ? Math.min(materialTarget.matches(furnaceCache.materialSlot.getItem()) ? furnaceCache.materialSlot.getCount() : 0, materialTarget.getTargetCount()) : materialTarget.getTargetCount() /* - mod.getItemStorage().getItemCountInventoryOnly(materialTarget.getMatches()) */ - mod.getItemStorage().getItemCountInventoryOnly(outputTarget.getMatches()) - - (outputTarget.matches(_furnaceCache.outputSlot.getItem()) ? _furnaceCache.outputSlot.getCount() : 0) + - (outputTarget.matches(furnaceCache.outputSlot.getItem()) ? furnaceCache.outputSlot.getCount() : 0) - totalFuelInFurnace; // We don't have enough materials... if (mod.getItemStorage().getItemCountInventoryOnly(materialTarget.getMatches()) < materialsNeeded) { setDebugState("Getting Materials"); - return getMaterialTask(_target.getMaterial()); + return getMaterialTask(target.getMaterial()); } // We don't have enough fuel... - if (_furnaceCache.burningFuelCount <= 0 && StorageHelper.calculateInventoryFuelCount(mod) < fuelNeeded) { + if (furnaceCache.burningFuelCount <= 0 && StorageHelper.calculateInventoryFuelCount(mod) < fuelNeeded) { setDebugState("Getting Fuel"); return new CollectFuelTask(fuelNeeded + 1); } // Make sure our materials are accessible in our inventory - if (StorageHelper.isItemInaccessibleToContainer(mod, _allMaterials)) { - return new MoveInaccessibleItemToInventoryTask(_allMaterials); + if (StorageHelper.isItemInaccessibleToContainer(mod, allMaterials)) { + return new MoveInaccessibleItemToInventoryTask(allMaterials); } // We have fuel and materials. Get to our container and smelt! @@ -274,13 +272,13 @@ protected Task containerSubTask(AltoClef mod) { // Fill in input if needed // Materials needed in slot = (mat_target - out_in_inventory - out_in_furnace) - ItemTarget materialTarget = _allMaterials; + ItemTarget materialTarget = allMaterials; int neededMaterialsInSlot = materialTarget.getTargetCount() - - mod.getItemStorage().getItemCountInventoryOnly(_target.getItem().getMatches()) - - (_target.getItem().matches(output.getItem()) ? output.getCount() : 0); + - mod.getItemStorage().getItemCountInventoryOnly(target.getItem().getMatches()) + - (target.getItem().matches(output.getItem()) ? output.getCount() : 0); // We don't have the right material or we need more - if (!_allMaterials.matches(material.getItem()) || neededMaterialsInSlot > material.getCount()) { + if (!allMaterials.matches(material.getItem()) || neededMaterialsInSlot > material.getCount()) { int materialsAlreadyIn = (materialTarget.matches(material.getItem()) ? material.getCount() : 0); setDebugState("Moving Materials"); return new MoveItemToSlotFromInventoryTask(new ItemTarget(materialTarget, neededMaterialsInSlot - materialsAlreadyIn), FurnaceSlot.INPUT_SLOT_MATERIALS); @@ -312,7 +310,7 @@ protected Task containerSubTask(AltoClef mod) { // If our best is above, prioritize lower values (closestDelta > 0 && delta < closestDelta) || // If our best is below, prioritize higher below values - (closestDelta < 0 && delta < 0 && delta > closestDelta) + (delta < 0 && delta > closestDelta) ) { bestStack = stack; closestDelta = delta; @@ -332,9 +330,9 @@ protected Task containerSubTask(AltoClef mod) { @Override protected double getCostToMakeNew(AltoClef mod) { - if (_furnaceCache.burnPercentage > 0 || _furnaceCache.burningFuelCount > 0 || - _furnaceCache.fuelSlot != null || _furnaceCache.materialSlot != null || - _furnaceCache.outputSlot != null) { + if (furnaceCache.burnPercentage > 0 || furnaceCache.burningFuelCount > 0 || + !furnaceCache.fuelSlot.isEmpty() || !furnaceCache.materialSlot.isEmpty() || + !furnaceCache.outputSlot.isEmpty()) { return 9999999.0; } if (mod.getItemStorage().getItemCount(Items.COBBLESTONE) > 8) { @@ -353,11 +351,11 @@ protected BlockPos overrideContainerPosition(AltoClef mod) { private void tryUpdateOpenFurnace(AltoClef mod) { if (isContainerOpen(mod)) { // Update current furnace cache - _furnaceCache.burnPercentage = StorageHelper.getFurnaceCookPercent(); - _furnaceCache.burningFuelCount = StorageHelper.getFurnaceFuel(); - _furnaceCache.fuelSlot = StorageHelper.getItemStackInSlot(FurnaceSlot.INPUT_SLOT_FUEL); - _furnaceCache.materialSlot = StorageHelper.getItemStackInSlot(FurnaceSlot.INPUT_SLOT_MATERIALS); - _furnaceCache.outputSlot = StorageHelper.getItemStackInSlot(FurnaceSlot.OUTPUT_SLOT); + furnaceCache.burnPercentage = StorageHelper.getFurnaceCookPercent(); + furnaceCache.burningFuelCount = StorageHelper.getFurnaceFuel(); + furnaceCache.fuelSlot = StorageHelper.getItemStackInSlot(FurnaceSlot.INPUT_SLOT_FUEL); + furnaceCache.materialSlot = StorageHelper.getItemStackInSlot(FurnaceSlot.INPUT_SLOT_MATERIALS); + furnaceCache.outputSlot = StorageHelper.getItemStackInSlot(FurnaceSlot.OUTPUT_SLOT); } } } @@ -366,7 +364,7 @@ static class FurnaceCache { public ItemStack materialSlot = ItemStack.EMPTY; public ItemStack fuelSlot = ItemStack.EMPTY; public ItemStack outputSlot = ItemStack.EMPTY; - public double burningFuelCount; - public double burnPercentage; + public double burningFuelCount = 0; + public double burnPercentage = 0; } } diff --git a/src/main/java/adris/altoclef/tasks/container/SmeltInSmokerTask.java b/src/main/java/adris/altoclef/tasks/container/SmeltInSmokerTask.java index cb2a441e..c2044ec0 100644 --- a/src/main/java/adris/altoclef/tasks/container/SmeltInSmokerTask.java +++ b/src/main/java/adris/altoclef/tasks/container/SmeltInSmokerTask.java @@ -1,7 +1,6 @@ package adris.altoclef.tasks.container; import adris.altoclef.AltoClef; -import adris.altoclef.Debug; import adris.altoclef.TaskCatalogue; import adris.altoclef.tasks.ResourceTask; import adris.altoclef.tasks.resources.CollectFuelTask; @@ -38,21 +37,19 @@ */ public class SmeltInSmokerTask extends ResourceTask { - private final SmeltTarget[] _targets; + private final SmeltTarget target; - private final DoSmeltInSmokerTask _doTask; + private final DoSmeltInSmokerTask doTask; - public SmeltInSmokerTask(SmeltTarget[] targets) { - super(extractItemTargets(targets)); - _targets = targets; + public SmeltInSmokerTask(SmeltTarget target) { + super(extractItemTargets(new SmeltTarget[]{target})); + this.target = target; // TODO: Do them in order. boolean ignoreMaterials = false; - _doTask = new DoSmeltInSmokerTask(targets[0], ignoreMaterials); + doTask = new DoSmeltInSmokerTask(target, ignoreMaterials); } - public SmeltInSmokerTask(SmeltTarget target) { - this(new SmeltTarget[]{target}); - } + private static ItemTarget[] extractItemTargets(SmeltTarget[] recipeTargets) { List result = new ArrayList<>(recipeTargets.length); @@ -63,7 +60,7 @@ private static ItemTarget[] extractItemTargets(SmeltTarget[] recipeTargets) { } public void ignoreMaterials() { - _doTask.ignoreMaterials(); + doTask.ignoreMaterials(); } @Override @@ -73,23 +70,18 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.SMOKER); mod.getBehaviour().push(); - if (_targets.length != 1) { - Debug.logWarning("Tried smelting multiple targets, only one target is supported at a time!"); - } } @Override protected Task onResourceTick(AltoClef mod) { - Optional smokerPos = mod.getBlockTracker().getNearestTracking(Blocks.SMOKER); + Optional smokerPos = mod.getBlockScanner().getNearestBlock(Blocks.SMOKER); smokerPos.ifPresent(blockPos -> mod.getBehaviour().avoidBlockBreaking(blockPos)); - return _doTask; + return doTask; } @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.SMOKER); mod.getBehaviour().pop(); // Close smoker screen ItemStack cursorStack = StorageHelper.getItemStackInCursorSlot(); @@ -110,24 +102,24 @@ protected void onResourceStop(AltoClef mod, Task interruptTask) { @Override public boolean isFinished(AltoClef mod) { - return super.isFinished(mod) || _doTask.isFinished(mod); + return super.isFinished(mod) || doTask.isFinished(mod); } @Override protected boolean isEqualResource(ResourceTask other) { if (other instanceof SmeltInSmokerTask task) { - return task._doTask.isEqual(_doTask); + return task.doTask.isEqual(doTask); } return false; } @Override protected String toDebugStringName() { - return _doTask.toDebugString(); + return doTask.toDebugString(); } public SmeltTarget[] getTargets() { - return _targets; + return new SmeltTarget[]{target}; } @SuppressWarnings("ConditionCoveredByFurtherCondition") diff --git a/src/main/java/adris/altoclef/tasks/container/StoreInAnyContainerTask.java b/src/main/java/adris/altoclef/tasks/container/StoreInAnyContainerTask.java index e2b5c8ad..76c567a7 100644 --- a/src/main/java/adris/altoclef/tasks/container/StoreInAnyContainerTask.java +++ b/src/main/java/adris/altoclef/tasks/container/StoreInAnyContainerTask.java @@ -43,7 +43,6 @@ public StoreInAnyContainerTask(boolean getIfNotPresent, ItemTarget... toStore) { @Override protected void onStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(TO_SCAN); _storedItems.startTracking(); _dungeonChests.clear(); _nonDungeonChests.clear(); @@ -100,13 +99,13 @@ protected Task onTick(AltoClef mod) { return true; }; - if (mod.getBlockTracker().anyFound(validContainer, TO_SCAN)) { + if (mod.getBlockScanner().anyFound(validContainer, TO_SCAN)) { setDebugState("Going to container and depositing items"); if (!_progressChecker.check(mod) && _currentChestTry != null) { Debug.logMessage("Failed to open container. Suggesting it may be unreachable."); - mod.getBlockTracker().requestBlockUnreachable(_currentChestTry, 2); + mod.getBlockScanner().requestBlockUnreachable(_currentChestTry, 2); _currentChestTry = null; _progressChecker.reset(); } @@ -150,7 +149,6 @@ public boolean isFinished(AltoClef mod) { @Override protected void onStop(AltoClef mod, Task interruptTask) { _storedItems.stopTracking(); - mod.getBlockTracker().stopTracking(TO_SCAN); } @Override diff --git a/src/main/java/adris/altoclef/tasks/container/StoreInStashTask.java b/src/main/java/adris/altoclef/tasks/container/StoreInStashTask.java index 43155720..052f8980 100644 --- a/src/main/java/adris/altoclef/tasks/container/StoreInStashTask.java +++ b/src/main/java/adris/altoclef/tasks/container/StoreInStashTask.java @@ -35,7 +35,6 @@ public StoreInStashTask(boolean getIfNotPresent, BlockRange stashRange, ItemTarg @Override protected void onStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(TO_SCAN); if (_storedItems == null) { _storedItems = new ContainerStoredTracker(slot -> { Optional currentContainer = mod.getItemStorage().getLastBlockPosInteraction(); @@ -66,7 +65,7 @@ protected Task onTick(AltoClef mod) { }; // Store in valid container - if (mod.getBlockTracker().anyFound(validContainer, TO_SCAN)) { + if (mod.getBlockScanner().anyFound(validContainer, TO_SCAN)) { setDebugState("Storing in closest stash container"); return new DoToClosestBlockTask( (BlockPos bpos) -> new StoreInContainerTask(bpos, false, _storedItems.getUnstoredItemTargetsYouCanStore(mod, _toStore)), @@ -82,7 +81,6 @@ protected Task onTick(AltoClef mod) { @Override protected void onStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(TO_SCAN); _storedItems.stopTracking(); } diff --git a/src/main/java/adris/altoclef/tasks/entity/AbstractDoToEntityTask.java b/src/main/java/adris/altoclef/tasks/entity/AbstractDoToEntityTask.java index b73feba3..2209c04f 100644 --- a/src/main/java/adris/altoclef/tasks/entity/AbstractDoToEntityTask.java +++ b/src/main/java/adris/altoclef/tasks/entity/AbstractDoToEntityTask.java @@ -26,28 +26,28 @@ * The interaction is abstract. */ public abstract class AbstractDoToEntityTask extends Task implements ITaskRequiresGrounded { - protected final MovementProgressChecker _progress = new MovementProgressChecker(); - private final double _maintainDistance; - private final double _combatGuardLowerRange; - private final double _combatGuardLowerFieldRadius; - - public AbstractDoToEntityTask(double maintainDistance, double combatGuardLowerRange, double combatGuardLowerFieldRadius) { - _maintainDistance = maintainDistance; - _combatGuardLowerRange = combatGuardLowerRange; - _combatGuardLowerFieldRadius = combatGuardLowerFieldRadius; + protected final MovementProgressChecker progress = new MovementProgressChecker(); + private final double maintainDistance; + private final double combatGuardLowerRange; + private final double combatGuardLowerFieldRadius; + + protected AbstractDoToEntityTask(double maintainDistance, double combatGuardLowerRange, double combatGuardLowerFieldRadius) { + this.maintainDistance = maintainDistance; + this.combatGuardLowerRange = combatGuardLowerRange; + this.combatGuardLowerFieldRadius = combatGuardLowerFieldRadius; } - public AbstractDoToEntityTask(double maintainDistance) { + protected AbstractDoToEntityTask(double maintainDistance) { this(maintainDistance, 0, Double.POSITIVE_INFINITY); } - public AbstractDoToEntityTask(double combatGuardLowerRange, double combatGuardLowerFieldRadius) { + protected AbstractDoToEntityTask(double combatGuardLowerRange, double combatGuardLowerFieldRadius) { this(-1, combatGuardLowerRange, combatGuardLowerFieldRadius); } @Override protected void onStart(AltoClef mod) { - _progress.reset(); + progress.reset(); ItemStack cursorStack = StorageHelper.getItemStackInCursorSlot(); if (!cursorStack.isEmpty()) { Optional moveTo = mod.getItemStorage().getSlotThatCanFitInPlayerInventory(cursorStack, false); @@ -67,7 +67,7 @@ protected void onStart(AltoClef mod) { @Override protected Task onTick(AltoClef mod) { if (mod.getClientBaritone().getPathingBehavior().isPathing()) { - _progress.reset(); + progress.reset(); } Optional checkEntity = getEntityTarget(mod); @@ -90,37 +90,34 @@ protected Task onTick(AltoClef mod) { double sqDist = entity.squaredDistanceTo(mod.getPlayer()); - if (sqDist < _combatGuardLowerRange * _combatGuardLowerRange) { - mod.getMobDefenseChain().setForceFieldRange(_combatGuardLowerFieldRadius); + if (sqDist < combatGuardLowerRange * combatGuardLowerRange) { + mod.getMobDefenseChain().setForceFieldRange(combatGuardLowerFieldRadius); } else { mod.getMobDefenseChain().resetForceField(); } // If we don't specify a maintain distance, default to within 1 block of our reach. - double maintainDistance = _maintainDistance >= 0 ? _maintainDistance : playerReach - 1; + double maintainDistance = this.maintainDistance >= 0 ? this.maintainDistance : playerReach - 1; boolean tooClose = sqDist < maintainDistance * maintainDistance; // Step away if we're too close - if (tooClose) { - //setDebugState("Maintaining distance"); - if (!mod.getClientBaritone().getCustomGoalProcess().isActive()) { - mod.getClientBaritone().getCustomGoalProcess().setGoalAndPath(new GoalRunAway(maintainDistance, entity.getBlockPos())); - } + if (tooClose && !mod.getClientBaritone().getCustomGoalProcess().isActive()) { + mod.getClientBaritone().getCustomGoalProcess().setGoalAndPath(new GoalRunAway(maintainDistance, entity.getBlockPos())); } if (mod.getControllerExtras().inRange(entity) && result != null && result.getType() == HitResult.Type.ENTITY && !mod.getFoodChain().needsToEat() && - !mod.getMLGBucketChain().isFallingOhNo(mod) && mod.getMLGBucketChain().doneMLG() && + !mod.getMLGBucketChain().isFalling(mod) && mod.getMLGBucketChain().doneMLG() && !mod.getMLGBucketChain().isChorusFruiting() && mod.getClientBaritone().getPathingBehavior().isSafeToCancel() && mod.getPlayer().isOnGround()) { - _progress.reset(); + progress.reset(); return onEntityInteract(mod, entity); } else if (!tooClose) { setDebugState("Approaching target"); - if (!_progress.check(mod)) { - _progress.reset(); + if (!progress.check(mod)) { + progress.reset(); Debug.logMessage("Failed to get to target, blacklisting."); mod.getEntityTracker().requestEntityUnreachable(entity); } @@ -137,9 +134,9 @@ protected Task onTick(AltoClef mod) { @Override protected boolean isEqual(Task other) { if (other instanceof AbstractDoToEntityTask task) { - if (!doubleCheck(task._maintainDistance, _maintainDistance)) return false; - if (!doubleCheck(task._combatGuardLowerFieldRadius, _combatGuardLowerFieldRadius)) return false; - if (!doubleCheck(task._combatGuardLowerRange, _combatGuardLowerRange)) return false; + if (!doubleCheck(task.maintainDistance, maintainDistance)) return false; + if (!doubleCheck(task.combatGuardLowerFieldRadius, combatGuardLowerFieldRadius)) return false; + if (!doubleCheck(task.combatGuardLowerRange, combatGuardLowerRange)) return false; return isSubEqual(task); } return false; diff --git a/src/main/java/adris/altoclef/tasks/entity/AbstractKillEntityTask.java b/src/main/java/adris/altoclef/tasks/entity/AbstractKillEntityTask.java index 9c9a06dc..3dc79b4f 100644 --- a/src/main/java/adris/altoclef/tasks/entity/AbstractKillEntityTask.java +++ b/src/main/java/adris/altoclef/tasks/entity/AbstractKillEntityTask.java @@ -21,15 +21,15 @@ public abstract class AbstractKillEntityTask extends AbstractDoToEntityTask { // Not the "striking" distance, but the "ok we're close enough, lower our guard for other mobs and focus on this one" range. private static final double CONSIDER_COMBAT_RANGE = 10; - public AbstractKillEntityTask() { + protected AbstractKillEntityTask() { this(CONSIDER_COMBAT_RANGE, OTHER_FORCE_FIELD_RANGE); } - public AbstractKillEntityTask(double combatGuardLowerRange, double combatGuardLowerFieldRadius) { + protected AbstractKillEntityTask(double combatGuardLowerRange, double combatGuardLowerFieldRadius) { super(combatGuardLowerRange, combatGuardLowerFieldRadius); } - public AbstractKillEntityTask(double maintainDistance, double combatGuardLowerRange, double combatGuardLowerFieldRadius) { + protected AbstractKillEntityTask(double maintainDistance, double combatGuardLowerRange, double combatGuardLowerFieldRadius) { super(maintainDistance, combatGuardLowerRange, combatGuardLowerFieldRadius); } @@ -72,11 +72,9 @@ protected Task onEntityInteract(AltoClef mod, Entity entity) { // Equip weapon if (!equipWeapon(mod)) { float hitProg = mod.getPlayer().getAttackCooldownProgress(0); - if (hitProg >= 1) { - if (mod.getPlayer().isOnGround() || mod.getPlayer().getVelocity().getY() < 0 || mod.getPlayer().isTouchingWater()) { - LookHelper.lookAt(mod, entity.getEyePos()); - mod.getControllerExtras().attack(entity); - } + if (hitProg >= 1 && (mod.getPlayer().isOnGround() || mod.getPlayer().getVelocity().getY() < 0 || mod.getPlayer().isTouchingWater())) { + LookHelper.lookAt(mod, entity.getEyePos()); + mod.getControllerExtras().attack(entity); } } return null; diff --git a/src/main/java/adris/altoclef/tasks/entity/DoToClosestEntityTask.java b/src/main/java/adris/altoclef/tasks/entity/DoToClosestEntityTask.java index 2e5a47e4..9e60c513 100644 --- a/src/main/java/adris/altoclef/tasks/entity/DoToClosestEntityTask.java +++ b/src/main/java/adris/altoclef/tasks/entity/DoToClosestEntityTask.java @@ -15,7 +15,7 @@ /** * Finds the closest entity and runs a task on that entity */ -@SuppressWarnings("ALL") +@SuppressWarnings("rawtypes") public class DoToClosestEntityTask extends AbstractDoToClosestObjectTask { private final Class[] _targetEntities; diff --git a/src/main/java/adris/altoclef/tasks/entity/KillPlayerTask.java b/src/main/java/adris/altoclef/tasks/entity/KillPlayerTask.java deleted file mode 100644 index 1751f03b..00000000 --- a/src/main/java/adris/altoclef/tasks/entity/KillPlayerTask.java +++ /dev/null @@ -1,65 +0,0 @@ -package adris.altoclef.tasks.entity; - -import adris.altoclef.AltoClef; -import adris.altoclef.tasksystem.Task; -import adris.altoclef.util.progresscheck.IProgressChecker; -import adris.altoclef.util.progresscheck.LinearProgressChecker; -import adris.altoclef.util.progresscheck.ProgressCheckerRetry; -import net.minecraft.entity.Entity; - -import java.util.Optional; - -/** - * Kill a player given their username - */ -public class KillPlayerTask extends AbstractKillEntityTask { - - private final String _playerName; - - private final IProgressChecker _distancePlayerCheck = new ProgressCheckerRetry<>(new LinearProgressChecker(5, -2), 3); - - public KillPlayerTask(String name) { - super(7, 1); - _playerName = name; - } - - @Override - protected Task onTick(AltoClef mod) { - // If we're closer to the player, our task isn't bad. - Optional player = getEntityTarget(mod); - if (player.isEmpty()) { - _distancePlayerCheck.reset(); - } else { - double distSq = player.get().squaredDistanceTo(mod.getPlayer()); - if (distSq < 10 * 10) { - _distancePlayerCheck.reset(); - } - _distancePlayerCheck.setProgress(-1 * distSq); - if (!_distancePlayerCheck.failed()) { - _progress.reset(); - } - } - return super.onTick(mod); - } - - @Override - protected boolean isSubEqual(AbstractDoToEntityTask other) { - if (other instanceof KillPlayerTask task) { - return task._playerName.equals(_playerName); - } - return false; - } - - @Override - protected Optional getEntityTarget(AltoClef mod) { - if (mod.getEntityTracker().isPlayerLoaded(_playerName)) { - return mod.getEntityTracker().getPlayerEntity(_playerName).map(Entity.class::cast); - } - return Optional.empty(); - } - - @Override - protected String toDebugString() { - return "Punking " + _playerName; - } -} diff --git a/src/main/java/adris/altoclef/tasks/entity/SelfCareTask.java b/src/main/java/adris/altoclef/tasks/entity/SelfCareTask.java deleted file mode 100644 index ef22d2ff..00000000 --- a/src/main/java/adris/altoclef/tasks/entity/SelfCareTask.java +++ /dev/null @@ -1,191 +0,0 @@ -package adris.altoclef.tasks.entity; - -import adris.altoclef.AltoClef; -import adris.altoclef.TaskCatalogue; -import adris.altoclef.tasks.misc.EquipArmorTask; -import adris.altoclef.tasks.misc.SleepThroughNightTask; -import adris.altoclef.tasks.movement.GetToEntityTask; -import adris.altoclef.tasks.movement.TimeoutWanderTask; -import adris.altoclef.tasks.resources.CollectFoodTask; -import adris.altoclef.tasksystem.Task; -import adris.altoclef.util.ItemTarget; -import adris.altoclef.util.helpers.ItemHelper; -import adris.altoclef.util.helpers.StorageHelper; -import adris.altoclef.util.helpers.WorldHelper; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.Item; -import net.minecraft.item.Items; - -import java.util.Optional; - -public class SelfCareTask extends Task { - private static final ItemTarget[] woodToolSet = new ItemTarget[]{ - new ItemTarget(Items.WOODEN_SWORD, 1), - new ItemTarget(Items.WOODEN_PICKAXE, 1), - new ItemTarget(Items.WOODEN_AXE, 1), - new ItemTarget(Items.WOODEN_SHOVEL, 1), - }; - private static final ItemTarget[] stoneToolSet = new ItemTarget[]{ - new ItemTarget(Items.STONE_SWORD, 1), - new ItemTarget(Items.STONE_PICKAXE, 1), - new ItemTarget(Items.STONE_AXE, 1), - new ItemTarget(Items.STONE_SHOVEL, 1), - }; - private static final ItemTarget[] ironToolSet = new ItemTarget[]{ - new ItemTarget(Items.IRON_SWORD, 1), - new ItemTarget(Items.IRON_PICKAXE, 1), - new ItemTarget(Items.IRON_AXE, 1), - new ItemTarget(Items.IRON_SHOVEL, 1), - }; - private static final ItemTarget[] diamondToolSet = new ItemTarget[]{ - new ItemTarget(Items.DIAMOND_SWORD, 1), - new ItemTarget(Items.DIAMOND_PICKAXE, 1), - new ItemTarget(Items.DIAMOND_AXE, 1), - new ItemTarget(Items.DIAMOND_SHOVEL, 1) - }; - private static final ItemTarget[] netheriteToolSet = new ItemTarget[]{ - new ItemTarget(Items.NETHERITE_SWORD, 1), - new ItemTarget(Items.NETHERITE_PICKAXE, 1), - new ItemTarget(Items.NETHERITE_AXE, 1), - new ItemTarget(Items.NETHERITE_SHOVEL, 1) - }; - private static final Item[] ironArmorSet = new Item[]{ - Items.IRON_HELMET, Items.IRON_CHESTPLATE, Items.IRON_LEGGINGS, Items.IRON_BOOTS - }; - private static final Item[] diamondArmorSet = new Item[]{ - Items.DIAMOND_HELMET, Items.DIAMOND_CHESTPLATE, Items.DIAMOND_LEGGINGS, Items.DIAMOND_BOOTS - }; - private static final Item[] netheriteArmorSet = new Item[]{ - Items.NETHERITE_HELMET, Items.NETHERITE_CHESTPLATE, Items.NETHERITE_LEGGINGS, Items.NETHERITE_BOOTS - }; - private static final Item[] beds = ItemHelper.BED; - private static final Task getBed = TaskCatalogue.getItemTask("bed", 1); - private static final Task getFood = new CollectFoodTask(100); - private static final Task sleepThroughNight = new SleepThroughNightTask(); - private static final Task equipShield = new EquipArmorTask(Items.SHIELD); - private static Task getToolSet; - private static Task equipArmorSet; - private static String debugStateName; - - private static boolean isTaskNotFinished(AltoClef mod, Task task) { - return task != null && task.isActive() && !task.isFinished(mod); - } - - @Override - protected void onStart(AltoClef mod) { - - } - - @Override - protected Task onTick(AltoClef mod) { - boolean hasWoodToolSet = mod.getItemStorage().hasItem(woodToolSet); - boolean hasStoneToolSet = mod.getItemStorage().hasItem(stoneToolSet); - boolean hasIronToolSet = mod.getItemStorage().hasItem(ironToolSet); - boolean hasBed = mod.getItemStorage().hasItem(beds); - boolean hasShield = StorageHelper.isArmorEquipped(mod, Items.SHIELD); - boolean hasIronArmorSet = StorageHelper.isArmorEquippedAll(mod, ironArmorSet); - boolean hasDiamondToolSet = mod.getItemStorage().hasItem(diamondToolSet); - boolean hasDiamondArmorSet = StorageHelper.isArmorEquippedAll(mod, diamondArmorSet); - boolean hasNetheriteToolSet = mod.getItemStorage().hasItem(netheriteToolSet); - boolean hasNetheriteArmorSet = StorageHelper.isArmorEquippedAll(mod, netheriteArmorSet); - Optional player = mod.getEntityTracker().getClosestEntity(PlayerEntity.class); - if (hasBed && WorldHelper.canSleep()) { - setDebugState("Sleeping through night"); - return sleepThroughNight; - } - if (isTaskNotFinished(mod, getToolSet)) { - setDebugState(debugStateName); - return getToolSet; - } - if (isTaskNotFinished(mod, equipShield)) { - setDebugState(debugStateName); - return equipShield; - } - if (isTaskNotFinished(mod, equipArmorSet)) { - setDebugState(debugStateName); - return equipArmorSet; - } - if (isTaskNotFinished(mod, getBed)) { - setDebugState(debugStateName); - return getBed; - } - if (isTaskNotFinished(mod, getFood)) { - setDebugState(debugStateName); - return getFood; - } - if (!hasWoodToolSet) { - debugStateName = "Getting wood tool set"; - getToolSet = TaskCatalogue.getSquashedItemTask(woodToolSet); - return getToolSet; - } - if (!hasStoneToolSet) { - debugStateName = "Getting stone tool set"; - getToolSet = TaskCatalogue.getSquashedItemTask(stoneToolSet); - return getToolSet; - } - if (!hasBed) { - debugStateName = "Getting bed"; - return getBed; - } - if (!mod.getFoodChain().hasFood()) { - debugStateName = "Getting food"; - return getFood; - } - if (!hasIronToolSet) { - debugStateName = "Getting iron tool set"; - getToolSet = TaskCatalogue.getSquashedItemTask(ironToolSet); - return getToolSet; - } - if (!hasShield) { - debugStateName = "Getting shield"; - return equipShield; - } - if (!hasIronArmorSet) { - debugStateName = "Getting and equipping iron armor set"; - equipArmorSet = new EquipArmorTask(ironArmorSet); - return equipArmorSet; - } - if (!hasDiamondToolSet) { - debugStateName = "Getting diamond tool set"; - getToolSet = TaskCatalogue.getSquashedItemTask(diamondToolSet); - return getToolSet; - } - if (!hasDiamondArmorSet) { - debugStateName = "Getting and equipping diamond armor set"; - equipArmorSet = new EquipArmorTask(diamondArmorSet); - return equipArmorSet; - } - if (!hasNetheriteToolSet) { - debugStateName = "Getting netherite tool set"; - getToolSet = TaskCatalogue.getSquashedItemTask(netheriteToolSet); - return getToolSet; - } - if (!hasNetheriteArmorSet) { - debugStateName = "Getting and equipping netherite armor set"; - equipArmorSet = new EquipArmorTask(netheriteArmorSet); - return equipArmorSet; - } - if (player.isPresent()) { - setDebugState("Following player"); - return new GetToEntityTask(player.get(), 2); - } - setDebugState("Wandering until a player is found"); - return new TimeoutWanderTask(); - } - - @Override - protected void onStop(AltoClef mod, Task interruptTask) { - - } - - @Override - protected boolean isEqual(Task other) { - return other instanceof SelfCareTask; - } - - @Override - protected String toDebugString() { - return "Caring self"; - } -} diff --git a/src/main/java/adris/altoclef/tasks/entity/ShootArrowSimpleProjectileTask.java b/src/main/java/adris/altoclef/tasks/entity/ShootArrowSimpleProjectileTask.java index d706c610..b0b82960 100644 --- a/src/main/java/adris/altoclef/tasks/entity/ShootArrowSimpleProjectileTask.java +++ b/src/main/java/adris/altoclef/tasks/entity/ShootArrowSimpleProjectileTask.java @@ -2,13 +2,11 @@ import adris.altoclef.AltoClef; import adris.altoclef.Debug; -import adris.altoclef.tasks.speedrun.BeatMinecraft2Task; import adris.altoclef.tasksystem.Task; import adris.altoclef.util.helpers.LookHelper; import adris.altoclef.util.time.TimerGame; import baritone.api.utils.Rotation; import baritone.api.utils.input.Input; -import net.minecraft.client.MinecraftClient; import net.minecraft.entity.Entity; import net.minecraft.entity.projectile.ArrowEntity; import net.minecraft.item.Item; @@ -115,10 +113,6 @@ protected Task onTick(AltoClef mod) { } } - if (BeatMinecraft2Task.getConfig().renderDistanceManipulation && MinecraftClient.getInstance().options.getSimulationDistance().getValue() < 32) { - // For farther entities, the arrow may get stuck in the air, so we need to increase the simulation distance - MinecraftClient.getInstance().options.getSimulationDistance().setValue(32); - } mod.getInputControls().release(Input.CLICK_RIGHT); // Release the arrow shot = true; } diff --git a/src/main/java/adris/altoclef/tasks/examples/ExampleTask2.java b/src/main/java/adris/altoclef/tasks/examples/ExampleTask2.java index 7e710684..02c824be 100644 --- a/src/main/java/adris/altoclef/tasks/examples/ExampleTask2.java +++ b/src/main/java/adris/altoclef/tasks/examples/ExampleTask2.java @@ -16,8 +16,6 @@ public class ExampleTask2 extends Task { @Override protected void onStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.OAK_LOG); - // Extra credit: Bot will NOT damage trees. mod.getBehaviour().push(); mod.getBehaviour().avoidBlockBreaking(blockPos -> { @@ -41,8 +39,8 @@ protected Task onTick(AltoClef mod) { return new GetToBlockTask(_target); } - if (mod.getBlockTracker().anyFound(Blocks.OAK_LOG)) { - Optional nearest = mod.getBlockTracker().getNearestTracking(mod.getPlayer().getPos(), Blocks.OAK_LOG); + if (mod.getBlockScanner().anyFound(Blocks.OAK_LOG)) { + Optional nearest = mod.getBlockScanner().getNearestBlock(Blocks.OAK_LOG); if (nearest.isPresent()) { // Figure out leaves BlockPos check = new BlockPos(nearest.get()); @@ -60,7 +58,6 @@ protected Task onTick(AltoClef mod) { @Override protected void onStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.OAK_LOG); mod.getBehaviour().pop(); } diff --git a/src/main/java/adris/altoclef/tasks/misc/PlaceBedAndSetSpawnTask.java b/src/main/java/adris/altoclef/tasks/misc/PlaceBedAndSetSpawnTask.java index 81dcf9cd..54ce9643 100644 --- a/src/main/java/adris/altoclef/tasks/misc/PlaceBedAndSetSpawnTask.java +++ b/src/main/java/adris/altoclef/tasks/misc/PlaceBedAndSetSpawnTask.java @@ -118,9 +118,6 @@ public PlaceBedAndSetSpawnTask stayInBed() { */ @Override protected void onStart(AltoClef mod) { - // Track bed blocks - mod.getBlockTracker().trackBlock(ItemHelper.itemsToBlocks(ItemHelper.BED)); - // Push the current behaviour mod.getBehaviour().push(); @@ -214,11 +211,6 @@ protected Task onTick(AltoClef mod) { Debug.logMessage("Searching new bed region."); _currentBedRegion = null; } - if (mod.getPlayer().isTouchingWater() && mod.getItemStorage().hasItem(ItemHelper.BED)) { - setDebugState("We are in water. Wandering"); - _currentBedRegion = null; - return new TimeoutWanderTask(); - } if (WorldHelper.isInNetherPortal(mod)) { setDebugState("We are in nether portal. Wandering"); _currentBedRegion = null; @@ -246,7 +238,7 @@ protected Task onTick(AltoClef mod) { return null; } } - if (mod.getBlockTracker().anyFound(blockPos -> (WorldHelper.canReach(mod, blockPos) && + if (mod.getBlockScanner().anyFound(blockPos -> (WorldHelper.canReach(mod, blockPos) && blockPos.isWithinDistance(mod.getPlayer().getPos(), 40) && mod.getItemStorage().hasItem(ItemHelper.BED)) || (WorldHelper.canReach(mod, blockPos) && !mod.getItemStorage().hasItem(ItemHelper.BED)), ItemHelper.itemsToBlocks(ItemHelper.BED))) { @@ -295,11 +287,18 @@ protected Task onTick(AltoClef mod) { return new InteractWithBlockTask(_bedForSpawnPoint); }, ItemHelper.itemsToBlocks(ItemHelper.BED)); } + + if (mod.getPlayer().isTouchingWater() && mod.getItemStorage().hasItem(ItemHelper.BED)) { + setDebugState("We are in water. Wandering"); + _currentBedRegion = null; + return new TimeoutWanderTask(); + } + if (_currentBedRegion != null) { for (Vec3i BedPlacePos : BED_PLACE_POS_OFFSET) { Block getBlock = mod.getWorld().getBlockState(_currentBedRegion.add(BedPlacePos)).getBlock(); if (getBlock instanceof BedBlock) { - mod.getBlockTracker().addBlock(getBlock, _currentBedRegion.add(BedPlacePos)); + mod.getBlockScanner().addBlock(getBlock, _currentBedRegion.add(BedPlacePos)); break; } } @@ -404,9 +403,6 @@ protected Task onTick(AltoClef mod) { */ @Override protected void onStop(AltoClef mod, Task interruptTask) { - // Stop tracking beds - mod.getBlockTracker().stopTracking(ItemHelper.itemsToBlocks(ItemHelper.BED)); - // Pop the behaviour stack mod.getBehaviour().pop(); diff --git a/src/main/java/adris/altoclef/tasks/misc/RavageDesertTemplesTask.java b/src/main/java/adris/altoclef/tasks/misc/RavageDesertTemplesTask.java index ee8b5b77..2efecd7d 100644 --- a/src/main/java/adris/altoclef/tasks/misc/RavageDesertTemplesTask.java +++ b/src/main/java/adris/altoclef/tasks/misc/RavageDesertTemplesTask.java @@ -47,7 +47,6 @@ public RavageDesertTemplesTask() { @Override protected void onStart(AltoClef mod) { mod.getBehaviour().push(); - mod.getBlockTracker().trackBlock(Blocks.STONE_PRESSURE_PLATE); } @Override @@ -76,7 +75,6 @@ protected Task onTick(AltoClef mod) { @Override protected void onStop(AltoClef mod, Task task) { - mod.getBlockTracker().stopTracking(Blocks.STONE_PRESSURE_PLATE); mod.getBehaviour().pop(); } diff --git a/src/main/java/adris/altoclef/tasks/misc/RavageRuinedPortalsTask.java b/src/main/java/adris/altoclef/tasks/misc/RavageRuinedPortalsTask.java index 46e19caa..37e64127 100644 --- a/src/main/java/adris/altoclef/tasks/misc/RavageRuinedPortalsTask.java +++ b/src/main/java/adris/altoclef/tasks/misc/RavageRuinedPortalsTask.java @@ -53,7 +53,6 @@ public RavageRuinedPortalsTask() { @Override protected void onStart(AltoClef mod) { mod.getBehaviour().push(); - mod.getBlockTracker().trackBlock(Blocks.CHEST); } @Override @@ -71,7 +70,6 @@ protected Task onTick(AltoClef mod) { @Override protected void onStop(AltoClef mod, Task task) { - mod.getBlockTracker().stopTracking(Blocks.CHEST); mod.getBehaviour().pop(); } @@ -107,6 +105,6 @@ private Optional locateClosestUnopenedRuinedPortalChest(AltoClef mod) if (WorldHelper.getCurrentDimension() != Dimension.OVERWORLD) { return Optional.empty(); } - return mod.getBlockTracker().getNearestTracking(blockPos -> !_notRuinedPortalChests.contains(blockPos) && WorldHelper.isUnopenedChest(mod, blockPos) && canBeLootablePortalChest(mod, blockPos), Blocks.CHEST); + return mod.getBlockScanner().getNearestBlock(blockPos -> !_notRuinedPortalChests.contains(blockPos) && WorldHelper.isUnopenedChest(mod, blockPos) && canBeLootablePortalChest(mod, blockPos), Blocks.CHEST); } } diff --git a/src/main/java/adris/altoclef/tasks/movement/DefaultGoToDimensionTask.java b/src/main/java/adris/altoclef/tasks/movement/DefaultGoToDimensionTask.java index 67e17211..1e2e3453 100644 --- a/src/main/java/adris/altoclef/tasks/movement/DefaultGoToDimensionTask.java +++ b/src/main/java/adris/altoclef/tasks/movement/DefaultGoToDimensionTask.java @@ -29,7 +29,7 @@ public DefaultGoToDimensionTask(Dimension target) { @Override protected void onStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.NETHER_PORTAL); + } @Override @@ -71,7 +71,7 @@ protected Task onTick(AltoClef mod) { @Override protected void onStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.NETHER_PORTAL); + } @Override @@ -131,8 +131,8 @@ private Task goToEndTask(AltoClef mod) { } private boolean netherPortalIsClose(AltoClef mod) { - if (mod.getBlockTracker().anyFound(Blocks.NETHER_PORTAL)) { - Optional closest = mod.getBlockTracker().getNearestTracking(mod.getPlayer().getPos(), Blocks.NETHER_PORTAL); + if (mod.getBlockScanner().anyFound(Blocks.NETHER_PORTAL)) { + Optional closest = mod.getBlockScanner().getNearestBlock( Blocks.NETHER_PORTAL); return closest.isPresent() && closest.get().isWithinDistance(mod.getPlayer().getPos(), 2000); } return false; diff --git a/src/main/java/adris/altoclef/tasks/movement/EnterNetherPortalTask.java b/src/main/java/adris/altoclef/tasks/movement/EnterNetherPortalTask.java index 2376b113..a3b8da4e 100644 --- a/src/main/java/adris/altoclef/tasks/movement/EnterNetherPortalTask.java +++ b/src/main/java/adris/altoclef/tasks/movement/EnterNetherPortalTask.java @@ -16,22 +16,22 @@ import java.util.function.Predicate; public class EnterNetherPortalTask extends Task { - private final Task _getPortalTask; - private final Dimension _targetDimension; + private final Task getPortalTask; + private final Dimension targetDimension; - private final TimerGame _portalTimeout = new TimerGame(10); - private final TimeoutWanderTask _wanderTask = new TimeoutWanderTask(5); + private final TimerGame portalTimeout = new TimerGame(10); + private final TimeoutWanderTask wanderTask = new TimeoutWanderTask(5); - private final Predicate _goodPortal; + private final Predicate goodPortal; - private boolean _leftPortal; + private boolean leftPortal; public EnterNetherPortalTask(Task getPortalTask, Dimension targetDimension, Predicate goodPortal) { if (targetDimension == Dimension.END) throw new IllegalArgumentException("Can't build a nether portal to the end."); - _getPortalTask = getPortalTask; - _targetDimension = targetDimension; - _goodPortal = goodPortal; + this.getPortalTask = getPortalTask; + this.targetDimension = targetDimension; + this.goodPortal = goodPortal; } public EnterNetherPortalTask(Dimension targetDimension, Predicate goodPortal) { @@ -48,26 +48,25 @@ public EnterNetherPortalTask(Dimension targetDimension) { @Override protected void onStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.NETHER_PORTAL); - _leftPortal = false; - _portalTimeout.reset(); - _wanderTask.resetWander(); + leftPortal = false; + portalTimeout.reset(); + wanderTask.resetWander(); } @Override protected Task onTick(AltoClef mod) { - if (_wanderTask.isActive() && !_wanderTask.isFinished(mod)) { + if (wanderTask.isActive() && !wanderTask.isFinished(mod)) { setDebugState("Exiting portal for a bit."); - _portalTimeout.reset(); - _leftPortal = true; - return _wanderTask; + portalTimeout.reset(); + leftPortal = true; + return wanderTask; } if (mod.getWorld().getBlockState(mod.getPlayer().getBlockPos()).getBlock() == Blocks.NETHER_PORTAL) { - if (_portalTimeout.elapsed() && !_leftPortal) { - return _wanderTask; + if (portalTimeout.elapsed() && !leftPortal) { + return wanderTask; } setDebugState("Waiting inside portal"); mod.getClientBaritone().getExploreProcess().onLostControl(); @@ -82,28 +81,31 @@ protected Task onTick(AltoClef mod) { mod.getInputControls().release(Input.MOVE_FORWARD); return null; } else { - _portalTimeout.reset(); + portalTimeout.reset(); } Predicate standablePortal = blockPos -> { if (mod.getWorld().getBlockState(blockPos).getBlock() == Blocks.NETHER_PORTAL) { - return true; + return goodPortal.test(blockPos); } // REQUIRE that there be solid ground beneath us, not more portal. if (!mod.getChunkTracker().isChunkLoaded(blockPos)) { // Eh just assume it's good for now - return true; + return goodPortal.test(blockPos); } BlockPos below = blockPos.down(); - boolean canStand = WorldHelper.isSolid(mod, below) && !mod.getBlockTracker().blockIsValid(below, Blocks.NETHER_PORTAL); - return canStand && _goodPortal.test(blockPos); + boolean canStand = WorldHelper.isSolid(mod, below) && !mod.getBlockScanner().isBlockAtPosition(below, Blocks.NETHER_PORTAL); + return canStand && goodPortal.test(blockPos); }; - if (mod.getBlockTracker().anyFound(standablePortal, Blocks.NETHER_PORTAL)) { + if (mod.getBlockScanner().anyFound(standablePortal, Blocks.NETHER_PORTAL)) { setDebugState("Going to found portal"); return new DoToClosestBlockTask(blockPos -> new GetToBlockTask(blockPos, false), standablePortal, Blocks.NETHER_PORTAL); } - if (!mod.getBlockTracker().anyFound(standablePortal, Blocks.NETHER_PORTAL)) { + + //this probably isn't needed here, the check should fail everytime + + if (!mod.getBlockScanner().anyFound(standablePortal, Blocks.NETHER_PORTAL)) { setDebugState("Making new nether portal."); if (WorldHelper.getCurrentDimension() == Dimension.OVERWORLD) { return new ConstructNetherPortalBucketTask(); @@ -112,23 +114,23 @@ protected Task onTick(AltoClef mod) { } } setDebugState("Getting our portal"); - return _getPortalTask; + return getPortalTask; } @Override protected void onStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.NETHER_PORTAL); + } @Override public boolean isFinished(AltoClef mod) { - return WorldHelper.getCurrentDimension() == _targetDimension; + return WorldHelper.getCurrentDimension() == targetDimension; } @Override protected boolean isEqual(Task other) { if (other instanceof EnterNetherPortalTask task) { - return (Objects.equals(task._getPortalTask, _getPortalTask) && Objects.equals(task._targetDimension, _targetDimension)); + return (Objects.equals(task.getPortalTask, getPortalTask) && Objects.equals(task.targetDimension, targetDimension)); } return false; } diff --git a/src/main/java/adris/altoclef/tasks/movement/EscapeFromLavaTask.java b/src/main/java/adris/altoclef/tasks/movement/EscapeFromLavaTask.java index 6bc9afbe..9ff68ce1 100644 --- a/src/main/java/adris/altoclef/tasks/movement/EscapeFromLavaTask.java +++ b/src/main/java/adris/altoclef/tasks/movement/EscapeFromLavaTask.java @@ -1,25 +1,52 @@ package adris.altoclef.tasks.movement; import adris.altoclef.AltoClef; +import adris.altoclef.Debug; +import adris.altoclef.tasks.InteractWithBlockTask; +import adris.altoclef.tasks.construction.PlaceBlockNearbyTask; +import adris.altoclef.tasks.construction.PlaceBlockTask; import adris.altoclef.tasksystem.Task; +import adris.altoclef.util.ItemTarget; +import adris.altoclef.util.helpers.ItemHelper; +import adris.altoclef.util.helpers.LookHelper; +import adris.altoclef.util.helpers.WorldHelper; import adris.altoclef.util.progresscheck.MovementProgressChecker; import baritone.api.pathing.goals.Goal; +import baritone.api.utils.Rotation; import baritone.api.utils.input.Input; import baritone.pathing.movement.MovementHelper; +import net.minecraft.block.Block; import net.minecraft.block.Blocks; import net.minecraft.client.MinecraftClient; -import net.minecraft.util.math.BlockPos; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.item.*; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.Pair; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.*; +import net.minecraft.world.RaycastContext; + +import java.util.Objects; +import java.util.Optional; +import java.util.function.Predicate; public class EscapeFromLavaTask extends CustomBaritoneGoalTask { - private final float _strength; + private final float strength; + private int ticks = 0; + private final Predicate avoidPlacingRiskyBlock; - public EscapeFromLavaTask(float strength) { - _strength = strength; + public EscapeFromLavaTask(AltoClef mod,float strength) { + this.strength = strength; + avoidPlacingRiskyBlock = (blockPos -> mod.getPlayer().getBoundingBox().intersects(new Box(blockPos)) + && (mod.getWorld().getBlockState(mod.getPlayer().getBlockPos().down()).getBlock() == Blocks.LAVA || mod.getPlayer().isInLava())); } - public EscapeFromLavaTask() { - this(100); + + public EscapeFromLavaTask(AltoClef mod) { + this(mod, 100); } @Override @@ -33,23 +60,173 @@ protected void onStart(AltoClef mod) { mod.getBehaviour().setBlockBreakAdditionalPenalty(0); // Normally 2 // do NOT ever wander _checker = new MovementProgressChecker((int) Float.POSITIVE_INFINITY); + + // avoid trying to place block right under us if there is lava + mod.getExtraBaritoneSettings().avoidBlockPlace(avoidPlacingRiskyBlock); } @Override protected Task onTick(AltoClef mod) { - // Sprint through lava + jump, it's faster - if (mod.getPlayer().isInLava() || mod.getWorld().getBlockState(mod.getPlayer().getBlockPos().down()).getBlock() == Blocks.LAVA) { + // if (mod.getWorld().getBlockState(mod.getPlayer().getBlockPos().up()).getBlock().equals(Blocks.LAVA)) { mod.getInputControls().hold(Input.JUMP); mod.getInputControls().hold(Input.SPRINT); + /* setDebugState("escaping submerged lava"); + return null; + }*/ + + Optional food = calculateFood(mod); + if (food.isPresent() && mod.getPlayer().getHungerManager().getFoodLevel() < 20) { + // can be interrupted by block placing, but we should try to eat whenever we can + if (mod.getPlayer().isBlocking()) { + mod.log("want to eat, trying to stop shielding..."); + mod.getInputControls().release(Input.CLICK_RIGHT); + } else { + mod.getSlotHandler().forceEquipItem(new Item[]{food.get()}, true); + mod.getInputControls().hold(Input.CLICK_RIGHT); + } + } + + + // Sprint through lava + jump, it's faster + if (mod.getPlayer().isInLava() || mod.getWorld().getBlockState(mod.getPlayer().getBlockPos().down()).getBlock() == Blocks.LAVA) { + + setDebugState("run away from lava"); + + BlockPos steppingPos = mod.getPlayer().getSteppingPos(); + if (!mod.getWorld().getBlockState(steppingPos.east()).getBlock().equals(Blocks.LAVA) || + !mod.getWorld().getBlockState(steppingPos.west()).getBlock().equals(Blocks.LAVA) || + !mod.getWorld().getBlockState(steppingPos.south()).getBlock().equals(Blocks.LAVA) || + !mod.getWorld().getBlockState(steppingPos.north()).getBlock().equals(Blocks.LAVA) || + !mod.getWorld().getBlockState(steppingPos.east().north()).getBlock().equals(Blocks.LAVA) || + !mod.getWorld().getBlockState(steppingPos.east().south()).getBlock().equals(Blocks.LAVA) || + !mod.getWorld().getBlockState(steppingPos.west().north()).getBlock().equals(Blocks.LAVA) || + !mod.getWorld().getBlockState(steppingPos.west().south()).getBlock().equals(Blocks.LAVA)) { + + return super.onTick(mod); + } + + for (float pitch = 25; pitch < 90; pitch += 1f) { + for (float yaw = -180; yaw < 180; yaw += 1f) { + HitResult result = raycast(mod, 4, pitch, yaw); + if (result.getType() == HitResult.Type.BLOCK) { + BlockHitResult blockHitResult = (BlockHitResult) result; + BlockPos pos = blockHitResult.getBlockPos(); + + if (pos.getY() > mod.getPlayer().getSteppingPos().getY()) continue; + + Direction facing = blockHitResult.getSide(); + + if (facing == Direction.UP) continue; + LookHelper.lookAt(mod, new Rotation(yaw,pitch)); + + if (mod.getItemStorage().hasItem(Items.NETHERRACK)) { + mod.getSlotHandler().forceEquipItem(Items.NETHERRACK); + } else { + mod.getSlotHandler().forceEquipItem(mod.getClientBaritoneSettings().acceptableThrowawayItems.value.toArray(new Item[0])); + } + mod.log(pos+""); + mod.log(facing+""); + + + mod.getInputControls().tryPress(Input.CLICK_RIGHT); + return null; + } + } + } + } + return super.onTick(mod); } + // similar to FoodChain + // TODO add config for this + private Optional calculateFood(AltoClef mod) { + Item bestFood = null; + double bestFoodScore = Double.NEGATIVE_INFINITY; + ClientPlayerEntity player = mod.getPlayer(); + + float hunger = player != null ? player.getHungerManager().getFoodLevel() : 20; + float saturation = player != null ? player.getHungerManager().getSaturationLevel() : 20; + // Get best food item + calculate food total + for (ItemStack stack : mod.getItemStorage().getItemStacksPlayerInventory(true)) { + if (stack.isFood()) { + //screw that, we are in lava, eat whatever we can + // Ignore protected items + // if (!ItemHelper.canThrowAwayStack(mod, stack)) continue; + + // Ignore spider eyes + if (stack.getItem() == Items.SPIDER_EYE) { + continue; + } + + float score = getScore(stack, hunger, saturation); + if (score > bestFoodScore) { + bestFoodScore = score; + bestFood = stack.getItem(); + } + } + } + + return Optional.ofNullable(bestFood); + } + + private static float getScore(ItemStack stack, float hunger, float saturation) { + FoodComponent food = stack.getItem().getFoodComponent(); + + assert food != null; + float hungerIfEaten = Math.min(hunger + food.getHunger(), 20); + float saturationIfEaten = Math.min(hungerIfEaten, saturation + food.getSaturationModifier()); + float gainedSaturation = (saturationIfEaten - saturation); + + float hungerNotFilled = 20 - hungerIfEaten; + float saturationGoodScore = gainedSaturation * 10; + float hungerNotFilledPenalty = hungerNotFilled * 2; + + float score = saturationGoodScore - hungerNotFilledPenalty; + + if (stack.getItem() == Items.ROTTEN_FLESH) { + score = 0; + } + return score; + } + + + public HitResult raycast(AltoClef mod,double maxDistance, float pitch, float yaw) { + Vec3d cameraPos = mod.getPlayer().getCameraPosVec(MinecraftClient.getInstance().getTickDelta()); + Vec3d rotationVector = getRotationVector(pitch,yaw); + + Vec3d vec3d3 = cameraPos.add(rotationVector.x * maxDistance, rotationVector.y * maxDistance, rotationVector.z * maxDistance); + return mod.getPlayer().getWorld() + .raycast( + new RaycastContext( + cameraPos, vec3d3, RaycastContext.ShapeType.OUTLINE, + false ? RaycastContext.FluidHandling.ANY : RaycastContext.FluidHandling.NONE, mod.getPlayer() + ) + ); + } + protected final Vec3d getRotationVector(float pitch, float yaw) { + float f = pitch * (float) (Math.PI / 180.0); + float g = -yaw * (float) (Math.PI / 180.0); + float h = MathHelper.cos(g); + float i = MathHelper.sin(g); + float j = MathHelper.cos(f); + float k = MathHelper.sin(f); + return new Vec3d((double)(i * j), (double)(-k), (double)(h * j)); + } + + @Override protected void onStop(AltoClef mod, Task interruptTask) { mod.getBehaviour().pop(); mod.getInputControls().release(Input.JUMP); mod.getInputControls().release(Input.SPRINT); + mod.getInputControls().release(Input.CLICK_RIGHT); + + // remove our custom place avoider + synchronized (mod.getExtraBaritoneSettings().getPlaceMutex()) { + mod.getExtraBaritoneSettings().getPlaceAvoiders().remove(avoidPlacingRiskyBlock); + } } @Override @@ -98,9 +275,9 @@ public boolean isInGoal(int x, int y, int z) { @Override public double heuristic(int x, int y, int z) { if (isLava(x, y, z)) { - return _strength; + return strength; } else if (isLavaAdjacent(x, y, z)) { - return _strength * 0.5f; + return strength * 0.5f; } if (isWater(x, y, z)) { return -100; diff --git a/src/main/java/adris/altoclef/tasks/movement/FastTravelTask.java b/src/main/java/adris/altoclef/tasks/movement/FastTravelTask.java index ce8e52ea..71cef47b 100644 --- a/src/main/java/adris/altoclef/tasks/movement/FastTravelTask.java +++ b/src/main/java/adris/altoclef/tasks/movement/FastTravelTask.java @@ -3,12 +3,13 @@ import adris.altoclef.AltoClef; import adris.altoclef.TaskCatalogue; import adris.altoclef.tasks.construction.compound.ConstructNetherPortalObsidianTask; -import adris.altoclef.tasks.speedrun.MarvionBeatMinecraftTask; +import adris.altoclef.tasks.speedrun.beatgame.BeatMinecraftTask; import adris.altoclef.tasksystem.Task; import adris.altoclef.util.Dimension; import adris.altoclef.util.ItemTarget; import adris.altoclef.util.helpers.WorldHelper; import adris.altoclef.util.time.TimerGame; +import net.minecraft.block.Blocks; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.DeathScreen; import net.minecraft.item.Item; @@ -26,9 +27,9 @@ public class FastTravelTask extends Task { private static final double IN_NETHER_CLOSE_ENOUGH_THRESHOLD = 15; // Collect flint+steel and diamond pickaxe before entering. Or just walk. - private final boolean _collectPortalMaterialsIfAbsent; - private final BlockPos _target; - private final Integer _threshold; + private final boolean collectPortalMaterialsIfAbsent; + private final BlockPos target; + private final Integer threshold; // If we fail to move to the precise center after we're "close enough" to our threshold, just call it quits and place the portal. private final TimerGame _attemptToMoveToIdealNetherCoordinateTimeout = new TimerGame(15); private boolean _forceOverworldWalking; @@ -42,9 +43,9 @@ public class FastTravelTask extends Task { * @param collectPortalMaterialsIfAbsent if we don't have (10 obsidian or a diamond pickaxe) and (a flint and steel or fire charge), collect these items. Otherwise just walk the whole way. */ public FastTravelTask(BlockPos overworldTarget, Integer threshold, boolean collectPortalMaterialsIfAbsent) { - _target = overworldTarget; - _threshold = null; - _collectPortalMaterialsIfAbsent = collectPortalMaterialsIfAbsent; + target = overworldTarget; + this.threshold = null; + this.collectPortalMaterialsIfAbsent = collectPortalMaterialsIfAbsent; } /** @@ -60,17 +61,16 @@ public FastTravelTask(BlockPos overworldTarget, boolean collectPortalMaterialsIf @Override protected void onStart(AltoClef mod) { - _goToOverworldTask = new EnterNetherPortalTask(new ConstructNetherPortalObsidianTask(), Dimension.OVERWORLD, checkPos -> { - // Make sure the portal we enter is NOT close to our exit portal... - Optional lastPortal = mod.getMiscBlockTracker().getLastUsedNetherPortal(Dimension.NETHER); - return lastPortal.isEmpty() || !WorldHelper.inRangeXZ(lastPortal.get(), checkPos, 3); - }); + BlockPos netherTarget = new BlockPos(target.getX() / 8, target.getY(), target.getZ() / 8); + + _goToOverworldTask = new EnterNetherPortalTask(new ConstructNetherPortalObsidianTask(), Dimension.OVERWORLD, + checkPos -> WorldHelper.inRangeXZ(checkPos,netherTarget,7)); } @Override protected Task onTick(AltoClef mod) { - BlockPos netherTarget = new BlockPos(_target.getX() / 8, _target.getY(), _target.getZ() / 8); + BlockPos netherTarget = new BlockPos(target.getX() / 8, target.getY(), target.getZ() / 8); boolean canBuildPortal = mod.getItemStorage().hasItem(Items.DIAMOND_PICKAXE) || mod.getItemStorage().getItemCount(Items.OBSIDIAN) >= 10; boolean canLightPortal = mod.getItemStorage().hasItem(Items.FLINT_AND_STEEL, Items.FIRE_CHARGE); @@ -84,14 +84,19 @@ protected Task onTick(AltoClef mod) { case OVERWORLD -> { _attemptToMoveToIdealNetherCoordinateTimeout.reset(); // WALK - if (_forceOverworldWalking || WorldHelper.inRangeXZ(mod.getPlayer(), _target, getOverworldThreshold(mod))) { + if (_forceOverworldWalking || WorldHelper.inRangeXZ(mod.getPlayer(), target, getOverworldThreshold(mod))) { _forceOverworldWalking = true; setDebugState("Walking: We're close enough to our target"); - return new GetToBlockTask(_target); + + if (mod.getBlockScanner().anyFound(Blocks.END_PORTAL_FRAME)) { + setDebugState("Walking to portal"); + return new GetToBlockTask(mod.getBlockScanner().getNearestBlock(Blocks.END_PORTAL_FRAME).get()); + } + return new GetToBlockTask(target); } // SUPPLIES if (!canBuildPortal || !canLightPortal) { - if (_collectPortalMaterialsIfAbsent) { + if (collectPortalMaterialsIfAbsent) { setDebugState("Collecting portal building materials"); if (!canBuildPortal) return TaskCatalogue.getItemTask(Items.DIAMOND_PICKAXE, 1); @@ -99,7 +104,7 @@ protected Task onTick(AltoClef mod) { return TaskCatalogue.getItemTask(Items.FLINT_AND_STEEL, 1); } else { setDebugState("Walking: We don't have portal building materials"); - return new GetToBlockTask(_target); + return new GetToBlockTask(target); } } // GO TO NETHER @@ -118,9 +123,7 @@ protected Task onTick(AltoClef mod) { // If we're going to the overworld, keep going. if (_goToOverworldTask.isActive() && !_goToOverworldTask.isFinished(mod)) { setDebugState("Going back to overworld"); - if (MarvionBeatMinecraftTask.getConfig().renderDistanceManipulation) { - MinecraftClient.getInstance().options.getViewDistance().setValue(32); - } + return _goToOverworldTask; } @@ -141,6 +144,7 @@ protected Task onTick(AltoClef mod) { return _goToOverworldTask; } } + _attemptToMoveToIdealNetherCoordinateTimeout.reset(); setDebugState("Traveling to ideal coordinates"); return new GetToXZTask(netherTarget.getX(), netherTarget.getZ()); @@ -184,10 +188,10 @@ protected Task onTick(AltoClef mod) { private int getOverworldThreshold(AltoClef mod) { int threshold; //noinspection ReplaceNullCheck - if (_threshold == null) { + if (this.threshold == null) { threshold = mod.getModSettings().getNetherFastTravelWalkingRange(); } else { - threshold = _threshold; + threshold = this.threshold; } // We should never leave the nether and STILL be outside our walk zone. threshold = Math.max((int) (IN_NETHER_CLOSE_ENOUGH_THRESHOLD * 8) + 32, threshold); @@ -204,13 +208,13 @@ protected void onStop(AltoClef mod, Task interruptTask) { @Override protected boolean isEqual(Task other) { if (other instanceof FastTravelTask task) { - return task._target.equals(_target) && task._collectPortalMaterialsIfAbsent == _collectPortalMaterialsIfAbsent && Objects.equals(task._threshold, _threshold); + return task.target.equals(target) && task.collectPortalMaterialsIfAbsent == collectPortalMaterialsIfAbsent && Objects.equals(task.threshold, threshold); } return false; } @Override protected String toDebugString() { - return "Fast travelling to " + _target.toShortString(); + return "Fast travelling to " + target.toShortString(); } } diff --git a/src/main/java/adris/altoclef/tasks/movement/GetToBlockTask.java b/src/main/java/adris/altoclef/tasks/movement/GetToBlockTask.java index 585674ab..005f1f68 100644 --- a/src/main/java/adris/altoclef/tasks/movement/GetToBlockTask.java +++ b/src/main/java/adris/altoclef/tasks/movement/GetToBlockTask.java @@ -5,6 +5,7 @@ import adris.altoclef.tasksystem.Task; import adris.altoclef.util.Dimension; import adris.altoclef.util.helpers.WorldHelper; +import adris.altoclef.util.time.TimerGame; import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.GoalBlock; import net.minecraft.util.math.BlockPos; @@ -14,6 +15,8 @@ public class GetToBlockTask extends CustomBaritoneGoalTask implements ITaskRequi private final BlockPos _position; private final boolean _preferStairs; private final Dimension _dimension; + private int finishedTicks = 0; + private final TimerGame wanderTimer = new TimerGame(2); public GetToBlockTask(BlockPos position, boolean preferStairs) { this(position, preferStairs, null); @@ -38,6 +41,22 @@ protected Task onTick(AltoClef mod) { if (_dimension != null && WorldHelper.getCurrentDimension() != _dimension) { return new DefaultGoToDimensionTask(_dimension); } + + if (isFinished(mod)) { + finishedTicks++; + } else { + finishedTicks = 0; + } + if (finishedTicks > 10*20) { + wanderTimer.reset(); + mod.logWarning("GetToBlock was finished for 10 seconds yet is still being called, wandering"); + finishedTicks = 0; + return new TimeoutWanderTask(); + } + if (!wanderTimer.elapsed()) { + return new TimeoutWanderTask(); + } + return super.onTick(mod); } @@ -86,6 +105,6 @@ protected Goal newGoal(AltoClef mod) { @Override protected void onWander(AltoClef mod) { super.onWander(mod); - mod.getBlockTracker().requestBlockUnreachable(_position); + mod.getBlockScanner().requestBlockUnreachable(_position); } } diff --git a/src/main/java/adris/altoclef/tasks/movement/GetToOuterEndIslandsTask.java b/src/main/java/adris/altoclef/tasks/movement/GetToOuterEndIslandsTask.java deleted file mode 100644 index e368d297..00000000 --- a/src/main/java/adris/altoclef/tasks/movement/GetToOuterEndIslandsTask.java +++ /dev/null @@ -1,115 +0,0 @@ -package adris.altoclef.tasks.movement; - -import adris.altoclef.AltoClef; -import adris.altoclef.Debug; -import adris.altoclef.tasks.InteractWithBlockTask; -import adris.altoclef.tasks.resources.GetBuildingMaterialsTask; -import adris.altoclef.tasks.speedrun.BeatMinecraft2Task; -import adris.altoclef.tasks.squashed.CataloguedResourceTask; -import adris.altoclef.tasksystem.Task; -import adris.altoclef.util.Dimension; -import adris.altoclef.util.ItemTarget; -import adris.altoclef.util.baritone.GoalAnd; -import adris.altoclef.util.helpers.StorageHelper; -import adris.altoclef.util.helpers.WorldHelper; -import baritone.api.pathing.goals.GoalComposite; -import baritone.api.pathing.goals.GoalGetToBlock; -import baritone.api.pathing.goals.GoalYLevel; -import net.minecraft.block.Blocks; -import net.minecraft.item.Items; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; -import net.minecraft.util.math.Vec3i; - -public class GetToOuterEndIslandsTask extends Task { - public final int END_ISLAND_START_RADIUS = 800; - public final Vec3i[] OFFSETS = { - new Vec3i(1, -1, 1), - new Vec3i(1, -1, -1), - new Vec3i(-1, -1, 1), - new Vec3i(-1, -1, -1), - new Vec3i(2, -1, 0), - new Vec3i(0, -1, 2), - new Vec3i(-2, -1, 0), - new Vec3i(0, -1, -2) - }; - private Task _beatTheGame; - - public GetToOuterEndIslandsTask() { - - } - - @Override - protected void onStart(AltoClef mod) { - mod.getBehaviour().push(); - mod.getBlockTracker().trackBlock(Blocks.END_GATEWAY); - _beatTheGame = new BeatMinecraft2Task(); - } - - @Override - protected Task onTick(AltoClef mod) { - if (mod.getBlockTracker().anyFound(Blocks.END_GATEWAY)) { - if (!mod.getItemStorage().hasItemInventoryOnly(Items.ENDER_PEARL)) { - setDebugState("Getting an ender pearl"); - return new CataloguedResourceTask(new ItemTarget(Items.ENDER_PEARL, 1)); - } - BlockPos gateway = mod.getBlockTracker().getNearestTracking(Blocks.END_GATEWAY).get(); - int blocksNeeded = Math.abs(mod.getPlayer().getBlockY() - gateway.getY()) + - Math.abs(mod.getPlayer().getBlockX() - gateway.getX()) + - Math.abs(mod.getPlayer().getBlockZ() - gateway.getZ()) - 3; - if (StorageHelper.getBuildingMaterialCount(mod) < blocksNeeded) { - setDebugState("Getting building materials"); - return new GetBuildingMaterialsTask(blocksNeeded); - } - GoalAnd goal = makeGoal(gateway); - Debug.logMessage(mod.getPlayer().getBlockPos().toString()); - if (!goal.isInGoal(mod.getPlayer().getBlockPos()) || !mod.getPlayer().isOnGround()) { - mod.getClientBaritone().getCustomGoalProcess().setGoal(goal); - if (!mod.getClientBaritone().getPathingBehavior().isPathing()) { - mod.getClientBaritone().getCustomGoalProcess().path(); - } - setDebugState("Getting close to gateway..."); - return null; - } - setDebugState("Throwing the pearl inside"); - return new InteractWithBlockTask(Items.ENDER_PEARL, gateway); - } - setDebugState("Beating the Game to get to an end gateway"); - return _beatTheGame; - } - - @Override - protected void onStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.END_GATEWAY); - mod.getBehaviour().pop(); - } - - @Override - protected boolean isEqual(Task other) { - return other instanceof GetToOuterEndIslandsTask; - } - - @Override - public boolean isFinished(AltoClef mod) { - return WorldHelper.getCurrentDimension() == Dimension.END && - !WorldHelper.inRangeXZ(new Vec3d(0, 64, 0), mod.getPlayer().getPos(), END_ISLAND_START_RADIUS); - } - - @Override - protected String toDebugString() { - return "Going to outer end islands"; - } - - private GoalAnd makeGoal(BlockPos gateway) { - return new GoalAnd(new GoalComposite( - new GoalGetToBlock(gateway.add(OFFSETS[0])), - new GoalGetToBlock(gateway.add(OFFSETS[1])), - new GoalGetToBlock(gateway.add(OFFSETS[2])), - new GoalGetToBlock(gateway.add(OFFSETS[3])), - new GoalGetToBlock(gateway.add(OFFSETS[4])), - new GoalGetToBlock(gateway.add(OFFSETS[5])), - new GoalGetToBlock(gateway.add(OFFSETS[6])), - new GoalGetToBlock(gateway.add(OFFSETS[7])) - ), new GoalYLevel(74)); - } -} diff --git a/src/main/java/adris/altoclef/tasks/movement/GetWithinRangeOfBlockTask.java b/src/main/java/adris/altoclef/tasks/movement/GetWithinRangeOfBlockTask.java index 3e5bfcec..b10254cd 100644 --- a/src/main/java/adris/altoclef/tasks/movement/GetWithinRangeOfBlockTask.java +++ b/src/main/java/adris/altoclef/tasks/movement/GetWithinRangeOfBlockTask.java @@ -8,29 +8,29 @@ public class GetWithinRangeOfBlockTask extends CustomBaritoneGoalTask { - private final BlockPos _blockPos; - private final int _range; + public final BlockPos blockPos; + public final int range; public GetWithinRangeOfBlockTask(BlockPos blockPos, int range) { - _blockPos = blockPos; - _range = range; + this.blockPos = blockPos; + this.range = range; } @Override protected Goal newGoal(AltoClef mod) { - return new GoalNear(_blockPos, _range); + return new GoalNear(blockPos, range); } @Override protected boolean isEqual(Task other) { if (other instanceof GetWithinRangeOfBlockTask task) { - return task._blockPos.equals(_blockPos) && task._range == _range; + return task.blockPos.equals(blockPos) && task.range == range; } return false; } @Override protected String toDebugString() { - return "Getting within " + _range + " blocks of " + _blockPos.toShortString(); + return "Getting within " + range + " blocks of " + blockPos.toShortString(); } } diff --git a/src/main/java/adris/altoclef/tasks/movement/GoToStrongholdPortalTask.java b/src/main/java/adris/altoclef/tasks/movement/GoToStrongholdPortalTask.java index e231799d..cba93a4b 100644 --- a/src/main/java/adris/altoclef/tasks/movement/GoToStrongholdPortalTask.java +++ b/src/main/java/adris/altoclef/tasks/movement/GoToStrongholdPortalTask.java @@ -3,6 +3,7 @@ import adris.altoclef.AltoClef; import adris.altoclef.tasksystem.Task; import adris.altoclef.util.Dimension; +import adris.altoclef.util.helpers.StorageHelper; import adris.altoclef.util.helpers.WorldHelper; import net.minecraft.block.Blocks; import net.minecraft.item.Items; @@ -11,7 +12,7 @@ public class GoToStrongholdPortalTask extends Task { - private final LocateStrongholdCoordinatesTask _locateCoordsTask; + private LocateStrongholdCoordinatesTask _locateCoordsTask; private final int _targetEyes; private final int MINIMUM_EYES = 12; private BlockPos _strongholdCoordinates; @@ -24,7 +25,7 @@ public GoToStrongholdPortalTask(int targetEyes) { @Override protected void onStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.END_PORTAL_FRAME); + } @Override @@ -35,6 +36,9 @@ protected Task onTick(AltoClef mod) { If there search it */ if (_strongholdCoordinates == null) { + // in case any screen is open, prevents from getting stuck + StorageHelper.closeScreen(); + _strongholdCoordinates = _locateCoordsTask.getStrongholdCoordinates().orElse(null); if (_strongholdCoordinates == null) { if (mod.getItemStorage().getItemCount(Items.ENDER_EYE) < MINIMUM_EYES && mod.getEntityTracker().itemDropped(Items.ENDER_EYE)) { @@ -45,9 +49,17 @@ protected Task onTick(AltoClef mod) { return _locateCoordsTask; } } + + if (mod.getPlayer().getPos().distanceTo(WorldHelper.toVec3d(_strongholdCoordinates)) < 10 && !mod.getBlockScanner().anyFound(Blocks.END_PORTAL_FRAME)) { + mod.log("Something went wrong whilst triangulating the stronghold... either the action got disrupted or the second eye went to a different stronghold"); + mod.log("We will try to triangulate again now..."); + _strongholdCoordinates = null; + _locateCoordsTask = new LocateStrongholdCoordinatesTask(_targetEyes); + return null; + } // Search stone brick chunks, but while we're wandering, go to the nether setDebugState("Searching for Stronghold..."); - return new SearchChunkForBlockTask(Blocks.STONE_BRICKS) { + /*return new SearchChunkForBlockTask(Blocks.STONE_BRICKS) { @Override protected Task onTick(AltoClef mod) { if (WorldHelper.getCurrentDimension() != Dimension.OVERWORLD) { @@ -60,12 +72,13 @@ protected Task onTick(AltoClef mod) { protected Task getWanderTask(AltoClef mod) { return new FastTravelTask(_strongholdCoordinates, 300, true); } - }; + };*/ + return new FastTravelTask(_strongholdCoordinates, 300, true); } @Override protected void onStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.END_PORTAL_FRAME); + } @Override diff --git a/src/main/java/adris/altoclef/tasks/movement/LocateDesertTempleTask.java b/src/main/java/adris/altoclef/tasks/movement/LocateDesertTempleTask.java index f1a8dff2..aa9962b9 100644 --- a/src/main/java/adris/altoclef/tasks/movement/LocateDesertTempleTask.java +++ b/src/main/java/adris/altoclef/tasks/movement/LocateDesertTempleTask.java @@ -13,8 +13,6 @@ public class LocateDesertTempleTask extends Task { @Override protected void onStart(AltoClef mod) { - // Track desert pyramid blocks - mod.getBlockTracker().trackBlock(Blocks.STONE_PRESSURE_PLATE); } @Override @@ -32,7 +30,6 @@ protected Task onTick(AltoClef mod) { @Override protected void onStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.STONE_PRESSURE_PLATE); } @Override diff --git a/src/main/java/adris/altoclef/tasks/movement/LocateStrongholdCoordinatesTask.java b/src/main/java/adris/altoclef/tasks/movement/LocateStrongholdCoordinatesTask.java index 3e7f9de5..c21284b5 100644 --- a/src/main/java/adris/altoclef/tasks/movement/LocateStrongholdCoordinatesTask.java +++ b/src/main/java/adris/altoclef/tasks/movement/LocateStrongholdCoordinatesTask.java @@ -54,7 +54,7 @@ static Vec3i calculateIntersection(Vec3d start1, Vec3d direction1, Vec3d start2, // Solved for s1 + d1 * t1 = s2 + d2 * t2 double t2 = ((d1.z * s2.x) - (d1.z * s1.x) - (d1.x * s2.z) + (d1.x * s1.z)) / ((d1.x * d2.z) - (d1.z * d2.x)); BlockPos blockPos = BlockPos.ofFloored(start2.add(direction2.multiply(t2))); - return new Vec3i(blockPos.getX(), blockPos.getY(), blockPos.getZ()); + return new Vec3i(blockPos.getX(), 0, blockPos.getZ()); } @Override @@ -84,6 +84,7 @@ protected Task onTick(AltoClef mod) { if (mod.getEntityTracker().entityFound(EyeOfEnderEntity.class)) { if (_currentThrownEye == null || !_currentThrownEye.isAlive()) { Debug.logMessage("New eye direction"); + Debug.logMessage(_currentThrownEye==null?"null":"is not alive"); List enderEyes = mod.getEntityTracker().getTrackedEntities(EyeOfEnderEntity.class); if (!enderEyes.isEmpty()) { for (EyeOfEnderEntity enderEye : enderEyes) { diff --git a/src/main/java/adris/altoclef/tasks/movement/TimeoutWanderTask.java b/src/main/java/adris/altoclef/tasks/movement/TimeoutWanderTask.java index 1d79eb6d..82afb53f 100644 --- a/src/main/java/adris/altoclef/tasks/movement/TimeoutWanderTask.java +++ b/src/main/java/adris/altoclef/tasks/movement/TimeoutWanderTask.java @@ -3,7 +3,7 @@ import adris.altoclef.AltoClef; import adris.altoclef.Debug; import adris.altoclef.tasks.entity.KillEntitiesTask; -import adris.altoclef.tasks.speedrun.MarvionBeatMinecraftTask; +import adris.altoclef.tasks.speedrun.beatgame.BeatMinecraftTask; import adris.altoclef.tasksystem.ITaskRequiresGrounded; import adris.altoclef.tasksystem.Task; import adris.altoclef.util.helpers.ItemHelper; @@ -204,25 +204,13 @@ protected Task onTick(AltoClef mod) { switch (WorldHelper.getCurrentDimension()) { case END -> { if (_timer.getDuration() >= 30) { - if (MarvionBeatMinecraftTask.getConfig().renderDistanceManipulation) { - MinecraftClient.getInstance().options.getViewDistance().setValue(12); - MinecraftClient.getInstance().options.getEntityDistanceScaling().setValue(1.0); - } _timer.reset(); } } case OVERWORLD, NETHER -> { if (_timer.getDuration() >= 30) { - if (MarvionBeatMinecraftTask.getConfig().renderDistanceManipulation) { - MinecraftClient.getInstance().options.getViewDistance().setValue(12); - MinecraftClient.getInstance().options.getEntityDistanceScaling().setValue(1.0); - } } if (_timer.elapsed()) { - if (MarvionBeatMinecraftTask.getConfig().renderDistanceManipulation) { - MinecraftClient.getInstance().options.getViewDistance().setValue(32); - MinecraftClient.getInstance().options.getEntityDistanceScaling().setValue(5.0); - } _timer.reset(); } } diff --git a/src/main/java/adris/altoclef/tasks/resources/CarveThenCollectTask.java b/src/main/java/adris/altoclef/tasks/resources/CarveThenCollectTask.java index cb3db9da..a4f2a831 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CarveThenCollectTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CarveThenCollectTask.java @@ -43,8 +43,7 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(_targetBlocks); - mod.getBlockTracker().trackBlock(_toCarveBlocks); + } @Override @@ -58,7 +57,7 @@ protected Task onResourceTick(AltoClef mod) { // Place carved items down // If our target block is placed, break it! - if (mod.getBlockTracker().anyFound(_targetBlocks)) { + if (mod.getBlockScanner().anyFound(_targetBlocks)) { setDebugState("Breaking carved/target block"); return new DoToClosestBlockTask(DestroyBlockTask::new, _targetBlocks); } @@ -68,7 +67,7 @@ protected Task onResourceTick(AltoClef mod) { return TaskCatalogue.getItemTask(_carveWith); } // If our carve block is spotted, carve it. - if (mod.getBlockTracker().anyFound(_toCarveBlocks)) { + if (mod.getBlockScanner().anyFound(_toCarveBlocks)) { setDebugState("Carving block"); return new DoToClosestBlockTask(blockPos -> new InteractWithBlockTask(_carveWith, blockPos, false), _toCarveBlocks); } @@ -86,8 +85,7 @@ protected Task onResourceTick(AltoClef mod) { @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(_targetBlocks); - mod.getBlockTracker().stopTracking(_toCarveBlocks); + } @Override diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectAmethystBlockTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectAmethystBlockTask.java index 194dc53d..c42d3f55 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectAmethystBlockTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectAmethystBlockTask.java @@ -27,8 +27,6 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.BUDDING_AMETHYST); - // Bot will not break Budding Amethyst mod.getBehaviour().push(); mod.getBehaviour().avoidBlockBreaking(blockPos -> { @@ -49,7 +47,6 @@ protected Task onResourceTick(AltoClef mod) { @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.BUDDING_AMETHYST); mod.getBehaviour().pop(); } diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectBedTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectBedTask.java index f2a9790e..489c27df 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectBedTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectBedTask.java @@ -42,22 +42,11 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { return false; } - @Override - protected void onResourceStart(AltoClef mod) { - super.onResourceStart(mod); - mod.getBlockTracker().trackBlock(BEDS); - } - - @Override - protected void onResourceStop(AltoClef mod, Task interruptTask) { - super.onResourceStop(mod, interruptTask); - mod.getBlockTracker().stopTracking(BEDS); - } @Override protected Task onResourceTick(AltoClef mod) { // Break beds from the world if possible, that would be pretty fast. - if (mod.getBlockTracker().anyFound(BEDS)) { + if (mod.getBlockScanner().anyFound(BEDS)) { // Failure + blacklisting is encapsulated within THIS task return new MineAndCollectTask(new ItemTarget(ItemHelper.BED, 1), BEDS, MiningRequirement.HAND); } diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectBlazeRodsTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectBlazeRodsTask.java index dc69ed70..2772104d 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectBlazeRodsTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectBlazeRodsTask.java @@ -52,7 +52,7 @@ private static boolean isHoveringAboveLavaOrTooHigh(AltoClef mod, Entity entity) @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.SPAWNER); + } @Override @@ -111,7 +111,7 @@ protected Task onResourceTick(AltoClef mod) { } else { // Put out fire that might mess with us. - Optional nearestFire = mod.getBlockTracker().getNearestWithinRange(_foundBlazeSpawner, 5, Blocks.FIRE); + Optional nearestFire = mod.getBlockScanner().getNearestWithinRange(_foundBlazeSpawner, 5, Blocks.FIRE); if (nearestFire.isPresent()) { setDebugState("Clearing fire around spawner to prevent loss of blaze rods."); return new PutOutFireTask(nearestFire.get()); @@ -122,12 +122,9 @@ protected Task onResourceTick(AltoClef mod) { } } else { // Search for blaze - for (BlockPos pos : mod.getBlockTracker().getKnownLocations(Blocks.SPAWNER)) { - if (isValidBlazeSpawner(mod, pos)) { - _foundBlazeSpawner = pos; - break; - } - } + Optional pos = mod.getBlockScanner().getNearestBlock(blockPos->isValidBlazeSpawner(mod, blockPos),Blocks.SPAWNER); + + pos.ifPresent(blockPos -> _foundBlazeSpawner = blockPos); } // We need to find our fortress. @@ -146,7 +143,7 @@ private boolean isValidBlazeSpawner(AltoClef mod, BlockPos pos) { @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.SPAWNER); + } @Override @@ -156,7 +153,7 @@ protected boolean isEqualResource(ResourceTask other) { @Override protected String toDebugStringName() { - return "Collect " + _count + " blaze rods"; + return "Collect blaze rods - "+AltoClef.INSTANCE.getItemStorage().getItemCount(Items.BLAZE_ROD)+"/"+_count; } @Override diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectBucketLiquidTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectBucketLiquidTask.java index f47744ab..3aef1ac0 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectBucketLiquidTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectBucketLiquidTask.java @@ -61,7 +61,6 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @SuppressWarnings("ConstantConditions") @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(_toCollect); // Track fluids mod.getBehaviour().push(); mod.getBehaviour().setRayTracingFluidHandling(RaycastContext.FluidHandling.SOURCE_ONLY); @@ -137,7 +136,7 @@ protected Task onResourceTick(AltoClef mod) { }; // Find nearest water and right click it - if (mod.getBlockTracker().anyFound(isSourceLiquid, _toCollect)) { + if (mod.getBlockScanner().anyFound(isSourceLiquid, _toCollect)) { // We want to MINIMIZE this distance to liquid. setDebugState("Trying to collect..."); //Debug.logMessage("TEST: " + RayTraceUtils.fluidHandling); @@ -152,21 +151,31 @@ protected Task onResourceTick(AltoClef mod) { mod.getClientBaritone().getExploreProcess().onLostControl(); mod.getClientBaritone().getCustomGoalProcess().onLostControl(); Debug.logMessage("Failed to break, blacklisting."); - mod.getBlockTracker().requestBlockUnreachable(blockPos); + mod.getBlockScanner().requestBlockUnreachable(blockPos); _blacklist.add(blockPos); } return new DestroyBlockTask(blockPos.up()); } + if (tries > 75) { + if (timeoutTimer.elapsed()) { + tries = 0; + } + mod.log("trying to wander "+timeoutTimer.getDuration()); + return new TimeoutWanderTask(); + } + timeoutTimer.reset(); + // We can reach the block. if (LookHelper.getReach(blockPos).isPresent() && mod.getClientBaritone().getPathingBehavior().isSafeToCancel()) { + tries++; return new InteractWithBlockTask(new ItemTarget(Items.BUCKET, 1), blockPos, _toCollect != Blocks.LAVA, new Vec3i(0, 1, 0)); } // Get close enough. // up because if we go below we'll try to move next to the liquid (for lava, not a good move) if (this.thisOrChildAreTimedOut() && !wasWandering) { - mod.getBlockTracker().requestBlockUnreachable(blockPos.up()); + mod.getBlockScanner().requestBlockUnreachable(blockPos.up()); wasWandering = true; } return new GetCloseToBlockTask(blockPos.up()); @@ -183,10 +192,11 @@ protected Task onResourceTick(AltoClef mod) { return new TimeoutWanderTask(); } + int tries = 0; + TimerGame timeoutTimer = new TimerGame(2); @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(_toCollect); mod.getBehaviour().pop(); //mod.getClientBaritone().getInputOverrideHandler().setInputForceState(Input.CLICK_RIGHT, false); mod.getExtraBaritoneSettings().setInteractionPaused(false); diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectCoarseDirtTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectCoarseDirtTask.java index ac2e6ba7..6300e09e 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectCoarseDirtTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectCoarseDirtTask.java @@ -29,13 +29,12 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.COARSE_DIRT); } @Override protected Task onResourceTick(AltoClef mod) { double c = Math.ceil((double) (_count - mod.getItemStorage().getItemCount(Items.COARSE_DIRT)) / 4) * 2; // Minimum number of dirt / gravel needed to complete the recipe, accounting for coarse dirt already collected. - Optional closest = mod.getBlockTracker().getNearestTracking(mod.getPlayer().getPos(), Blocks.COARSE_DIRT); + Optional closest = mod.getBlockScanner().getNearestBlock(Blocks.COARSE_DIRT); // If not enough dirt and gravel for the recipe, and coarse dirt within a certain distance, collect coarse dirt if (!(mod.getItemStorage().getItemCount(Items.DIRT) >= c && @@ -52,7 +51,6 @@ protected Task onResourceTick(AltoClef mod) { @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.COARSE_DIRT); } @Override diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectCocoaBeansTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectCocoaBeansTask.java index a68adadb..3d2f7845 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectCocoaBeansTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectCocoaBeansTask.java @@ -32,7 +32,6 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.COCOA); } @Override @@ -54,7 +53,7 @@ protected Task onResourceTick(AltoClef mod) { }; // Break mature cocoa blocks - if (mod.getBlockTracker().anyFound(validCocoa, Blocks.COCOA)) { + if (mod.getBlockScanner().anyFound(validCocoa, Blocks.COCOA)) { setDebugState("Breaking cocoa blocks"); return new DoToClosestBlockTask(DestroyBlockTask::new, validCocoa, Blocks.COCOA); } @@ -71,7 +70,6 @@ protected Task onResourceTick(AltoClef mod) { @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.COCOA); } @Override diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectCropTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectCropTask.java index db814694..423dd657 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectCropTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectCropTask.java @@ -67,7 +67,7 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(_cropBlock); + } @Override @@ -122,7 +122,7 @@ protected Task onResourceTick(AltoClef mod) { }; // Dimension - if (isInWrongDimension(mod) && !mod.getBlockTracker().anyFound(validCrop, _cropBlock)) { + if (isInWrongDimension(mod) && !mod.getBlockScanner().anyFound(validCrop, _cropBlock)) { return getToCorrectDimensionTask(mod); } @@ -140,7 +140,7 @@ protected Task onResourceTick(AltoClef mod) { @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(_cropBlock); + } @Override diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectFlintTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectFlintTask.java index 59c1885e..92393126 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectFlintTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectFlintTask.java @@ -31,14 +31,13 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.GRAVEL); } @Override protected Task onResourceTick(AltoClef mod) { // We might just want to mine the closest gravel. - Optional closest = mod.getBlockTracker().getNearestTracking(mod.getPlayer().getPos(), validGravel -> WorldHelper.fallingBlockSafeToBreak(validGravel) && WorldHelper.canBreak(mod, validGravel), Blocks.GRAVEL); + Optional closest = mod.getBlockScanner().getNearestBlock(mod.getPlayer().getPos(), validGravel -> WorldHelper.fallingBlockSafeToBreak(validGravel) && WorldHelper.canBreak(mod, validGravel), Blocks.GRAVEL); if (closest.isPresent() && closest.get().isWithinDistance(mod.getPlayer().getPos(), CLOSE_ENOUGH_FLINT)) { return new DoToClosestBlockTask(DestroyBlockTask::new, Blocks.GRAVEL); } @@ -55,7 +54,6 @@ protected Task onResourceTick(AltoClef mod) { @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.GRAVEL); } @Override diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectFoodTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectFoodTask.java index 17e3e08b..a9b0d035 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectFoodTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectFoodTask.java @@ -10,14 +10,14 @@ import adris.altoclef.tasks.container.SmeltInSmokerTask; import adris.altoclef.tasks.movement.PickupDroppedItemTask; import adris.altoclef.tasks.movement.TimeoutWanderTask; -import adris.altoclef.tasks.speedrun.MarvionBeatMinecraftTask; +import adris.altoclef.tasks.speedrun.beatgame.BeatMinecraftTask; import adris.altoclef.tasksystem.Task; import adris.altoclef.util.CraftingRecipe; import adris.altoclef.util.ItemTarget; import adris.altoclef.util.RecipeTarget; -import adris.altoclef.util.SmeltTarget; import adris.altoclef.util.helpers.StorageHelper; import adris.altoclef.util.helpers.WorldHelper; +import adris.altoclef.util.slots.Slot; import adris.altoclef.util.slots.SmokerSlot; import adris.altoclef.util.time.TimerGame; import net.minecraft.block.*; @@ -42,21 +42,16 @@ public class CollectFoodTask extends Task { - // Actually screw fish baritone does NOT play nice underwater. - // Fish kinda suck to harvest so heavily penalize them. - private static final double FISH_PENALTY = 0 * 0.03; // Represents order of preferred mobs to least preferred - private static final CookableFoodTarget[] COOKABLE_FOODS = new CookableFoodTarget[]{ + public static final CookableFoodTarget[] COOKABLE_FOODS = new CookableFoodTarget[]{ new CookableFoodTarget("beef", CowEntity.class), new CookableFoodTarget("porkchop", PigEntity.class), - new CookableFoodTargetFish("salmon", SalmonEntity.class), new CookableFoodTarget("chicken", ChickenEntity.class), - new CookableFoodTargetFish("cod", CodEntity.class), new CookableFoodTarget("mutton", SheepEntity.class) }; - private static final Item[] ITEMS_TO_PICK_UP = new Item[]{ + public static final Item[] ITEMS_TO_PICK_UP = new Item[]{ Items.ENCHANTED_GOLDEN_APPLE, Items.GOLDEN_APPLE, Items.GOLDEN_CARROT, @@ -64,18 +59,18 @@ public class CollectFoodTask extends Task { Items.BAKED_POTATO }; - private static final CropTarget[] CROPS = new CropTarget[]{ + public static final CropTarget[] CROPS = new CropTarget[]{ new CropTarget(Items.WHEAT, Blocks.WHEAT), new CropTarget(Items.CARROT, Blocks.CARROTS) }; - private final double _unitsNeeded; - private final TimerGame _checkNewOptionsTimer = new TimerGame(10); - private SmeltInSmokerTask _smeltTask = null; - private Task _currentResourceTask = null; + private final double unitsNeeded; + private final TimerGame checkNewOptionsTimer = new TimerGame(10); + private final SmeltInSmokerTask smeltTask = null; + private Task currentResourceTask = null; public CollectFoodTask(double unitsNeeded) { - _unitsNeeded = unitsNeeded; + this.unitsNeeded = unitsNeeded; } private static double getFoodPotential(ItemStack food) { @@ -88,6 +83,17 @@ private static double getFoodPotential(ItemStack food) { return count * cookable.getCooked().getFoodComponent().getHunger(); } } + + //bread logic + assert Items.BREAD.getFoodComponent() != null; + + if (food.getItem().equals(Items.HAY_BLOCK)) { + return 3*Items.BREAD.getFoodComponent().getHunger()*count; + } + if (food.getItem().equals(Items.WHEAT)) { + return (double) (Items.BREAD.getFoodComponent().getHunger() * count) /3; + } + // We're just an ordinary item. if (food.getItem().isFood()) { assert food.getItem().getFoodComponent() != null; @@ -98,7 +104,7 @@ private static double getFoodPotential(ItemStack food) { // Gets the units of food if we were to convert all of our raw resources to food. @SuppressWarnings("RedundantCast") - private static double calculateFoodPotential(AltoClef mod) { + public static double calculateFoodPotential(AltoClef mod) { double potentialFood = 0; for (ItemStack food : mod.getItemStorage().getItemStacksPlayerInventory(true)) { potentialFood += getFoodPotential(food); @@ -119,9 +125,6 @@ protected void onStart(AltoClef mod) { mod.getBehaviour().push(); // Protect ALL food mod.getBehaviour().addProtectedItems(ITEMS_TO_PICK_UP); - for (CropTarget crop : CROPS) { - mod.getBlockTracker().trackBlock(crop.cropBlock); - } // Allow us to consume food. /* @@ -131,61 +134,40 @@ protected void onStart(AltoClef mod) { } */ mod.getBehaviour().addProtectedItems(Items.HAY_BLOCK, Items.SWEET_BERRIES); - - mod.getBlockTracker().trackBlock(Blocks.HAY_BLOCK); - mod.getBlockTracker().trackBlock(Blocks.SWEET_BERRY_BUSH); } @Override protected Task onTick(AltoClef mod) { - if (mod.getEntityTracker().entityFound(ChickenEntity.class)) { - Optional chickens = mod.getEntityTracker().getClosestEntity(ChickenEntity.class); - if (chickens.isPresent()) { - Iterable entities = mod.getWorld().getEntities(); - for (Entity entity : entities) { - if (entity instanceof HostileEntity || entity instanceof SlimeEntity) { - if (chickens.get().hasPassenger(entity)) { - if (mod.getEntityTracker().isEntityReachable(entity)) { - Debug.logMessage("Blacklisting chicken jockey."); - mod.getEntityTracker().requestEntityUnreachable(chickens.get()); - } - } - } - } - } - } - List haysPos = mod.getBlockTracker().getKnownLocations(Blocks.HAY_BLOCK); + blackListChickenJockeys(mod); + + List haysPos = mod.getBlockScanner().getKnownLocations(Blocks.HAY_BLOCK); for (BlockPos HaysPos : haysPos) { BlockPos haysUpPos = HaysPos.up(); if (mod.getWorld().getBlockState(haysUpPos).getBlock() == Blocks.CARVED_PUMPKIN) { Debug.logMessage("Blacklisting pillage hay bales."); - mod.getBlockTracker().requestBlockUnreachable(HaysPos, 0); + mod.getBlockScanner().requestBlockUnreachable(HaysPos, 0); } } // If we were previously smelting, keep on smelting. - if (_smeltTask != null && _smeltTask.isActive() && !_smeltTask.isFinished(mod)) { + if (smeltTask != null && smeltTask.isActive() && !smeltTask.isFinished(mod)) { // TODO: If we don't have cooking materials, cancel. setDebugState("Cooking..."); - if (MarvionBeatMinecraftTask.getConfig().renderDistanceManipulation) { - MinecraftClient.getInstance().options.getViewDistance().setValue(2); - MinecraftClient.getInstance().options.getEntityDistanceScaling().setValue(0.5); - } - return _smeltTask; + return smeltTask; } - if (_checkNewOptionsTimer.elapsed()) { + if (checkNewOptionsTimer.elapsed()) { // Try a new resource task - _checkNewOptionsTimer.reset(); - _currentResourceTask = null; + checkNewOptionsTimer.reset(); + currentResourceTask = null; } - if (_currentResourceTask != null && _currentResourceTask.isActive() && !_currentResourceTask.isFinished(mod) && !_currentResourceTask.thisOrChildAreTimedOut()) { - return _currentResourceTask; + if (currentResourceTask != null && currentResourceTask.isActive() && !currentResourceTask.isFinished(mod) && !currentResourceTask.thisOrChildAreTimedOut()) { + return currentResourceTask; } // Calculate potential double potentialFood = calculateFoodPotential(mod); - if (potentialFood >= _unitsNeeded) { + if (potentialFood >= unitsNeeded) { // Convert our raw foods // PLAN: // - If we have hay/wheat, make it into bread @@ -197,35 +179,35 @@ protected Task onTick(AltoClef mod) { Item[] w = new Item[]{Items.WHEAT}; Item[] o = null; // jank - _currentResourceTask = new CraftInTableTask(new RecipeTarget(Items.BREAD, 99999999, CraftingRecipe.newShapedRecipe("bread", new Item[][]{w, w, w, o, o, o, o, o, o}, 1)), false, false); - return _currentResourceTask; + currentResourceTask = new CraftInTableTask(new RecipeTarget(Items.BREAD, 99999999, CraftingRecipe.newShapedRecipe("bread", new Item[][]{w, w, w, o, o, o, o, o, o}, 1)), false, false); + return currentResourceTask; } if (mod.getItemStorage().getItemCount(Items.HAY_BLOCK) >= 1) { setDebugState("Crafting Wheat"); Item[] o = null; - _currentResourceTask = new CraftInInventoryTask(new RecipeTarget(Items.WHEAT, 99999999, CraftingRecipe.newShapedRecipe("wheat", new Item[][]{new Item[]{Items.HAY_BLOCK}, o, o, o}, 9)), false, false); - return _currentResourceTask; + currentResourceTask = new CraftInInventoryTask(new RecipeTarget(Items.WHEAT, 99999999, CraftingRecipe.newShapedRecipe("wheat", new Item[][]{new Item[]{Items.HAY_BLOCK}, o, o, o}, 9)), false, false); + return currentResourceTask; } // Convert raw foods -> cooked foods - for (CookableFoodTarget cookable : COOKABLE_FOODS) { + /*for (CookableFoodTarget cookable : COOKABLE_FOODS) { int rawCount = mod.getItemStorage().getItemCount(cookable.getRaw()); if (rawCount > 0) { //Debug.logMessage("STARTING COOK OF " + cookable.getRaw().getTranslationKey()); int toSmelt = rawCount + mod.getItemStorage().getItemCount(cookable.getCooked()); - _smeltTask = new SmeltInSmokerTask(new SmeltTarget(new ItemTarget(cookable.cookedFood, toSmelt), new ItemTarget(cookable.rawFood, rawCount))); - _smeltTask.ignoreMaterials(); - return _smeltTask; + smeltTask = new SmeltInSmokerTask(new SmeltTarget(new ItemTarget(cookable.cookedFood, toSmelt), new ItemTarget(cookable.rawFood, rawCount))); + smeltTask.ignoreMaterials(); + return smeltTask; } - } + }*/ } else { // Pick up food items from ground for (Item item : ITEMS_TO_PICK_UP) { Task t = this.pickupTaskOrNull(mod, item); if (t != null) { setDebugState("Picking up Food: " + item.getTranslationKey()); - _currentResourceTask = t; - return _currentResourceTask; + currentResourceTask = t; + return currentResourceTask; } } // Pick up raw/cooked foods on ground @@ -234,16 +216,16 @@ protected Task onTick(AltoClef mod) { if (t == null) t = this.pickupTaskOrNull(mod, cookable.getCooked(), 40); if (t != null) { setDebugState("Picking up Cookable food"); - _currentResourceTask = t; - return _currentResourceTask; + currentResourceTask = t; + return currentResourceTask; } } // Hay blocks Task hayTaskBlock = this.pickupBlockTaskOrNull(mod, Blocks.HAY_BLOCK, Items.HAY_BLOCK, 300); if (hayTaskBlock != null) { setDebugState("Collecting Hay"); - _currentResourceTask = hayTaskBlock; - return _currentResourceTask; + currentResourceTask = hayTaskBlock; + return currentResourceTask; } // Crops for (CropTarget target : CROPS) { @@ -269,23 +251,25 @@ protected Task onTick(AltoClef mod) { }), 96); if (t != null) { setDebugState("Harvesting " + target.cropItem.getTranslationKey()); - _currentResourceTask = t; - return _currentResourceTask; + currentResourceTask = t; + return currentResourceTask; } } // Cooked foods double bestScore = 0; Entity bestEntity = null; Item bestRawFood = null; + Predicate notBaby = entity -> entity instanceof LivingEntity livingEntity && !livingEntity.isBaby(); + for (CookableFoodTarget cookable : COOKABLE_FOODS) { if (!mod.getEntityTracker().entityFound(cookable.mobToKill)) continue; - Optional nearest = mod.getEntityTracker().getClosestEntity(mod.getPlayer().getPos(), cookable.mobToKill); + Optional nearest = mod.getEntityTracker().getClosestEntity(mod.getPlayer().getPos(),notBaby ,cookable.mobToKill); if (nearest.isEmpty()) continue; // ?? This crashed once? int hungerPerformance = cookable.getCookedUnits(); double sqDistance = nearest.get().squaredDistanceTo(mod.getPlayer()); double score = (double) 100 * hungerPerformance / (sqDistance); if (cookable.isFish()) { - score *= FISH_PENALTY; + score = 0; } if (score > bestScore) { bestScore = score; @@ -295,17 +279,16 @@ protected Task onTick(AltoClef mod) { } if (bestEntity != null) { setDebugState("Killing " + bestEntity.getType().getTranslationKey()); - Predicate notBaby = entity -> entity instanceof LivingEntity livingEntity && !livingEntity.isBaby(); - _currentResourceTask = killTaskOrNull(bestEntity, notBaby, bestRawFood); - return _currentResourceTask; + currentResourceTask = killTaskOrNull(bestEntity, notBaby, bestRawFood); + return currentResourceTask; } // Sweet berries (separate from crops because they should have a lower priority than everything else cause they suck) Task berryPickup = pickupBlockTaskOrNull(mod, Blocks.SWEET_BERRY_BUSH, Items.SWEET_BERRIES, 96); if (berryPickup != null) { setDebugState("Getting sweet berries (no better foods are present)"); - _currentResourceTask = berryPickup; - return _currentResourceTask; + currentResourceTask = berryPickup; + return currentResourceTask; } } @@ -314,32 +297,46 @@ protected Task onTick(AltoClef mod) { return new TimeoutWanderTask(); } + static void blackListChickenJockeys(AltoClef mod) { + if (mod.getEntityTracker().entityFound(ChickenEntity.class)) { + Optional chickens = mod.getEntityTracker().getClosestEntity(ChickenEntity.class); + if (chickens.isPresent()) { + Iterable entities = mod.getWorld().getEntities(); + for (Entity entity : entities) { + if (entity instanceof HostileEntity || entity instanceof SlimeEntity) { + if (chickens.get().hasPassenger(entity)) { + if (mod.getEntityTracker().isEntityReachable(entity)) { + Debug.logMessage("Blacklisting chicken jockey."); + mod.getEntityTracker().requestEntityUnreachable(chickens.get()); + } + } + } + } + } + } + } + @Override protected void onStop(AltoClef mod, Task interruptTask) { mod.getBehaviour().pop(); - mod.getBlockTracker().stopTracking(Blocks.HAY_BLOCK); - mod.getBlockTracker().stopTracking(Blocks.SWEET_BERRY_BUSH); - for (CropTarget crop : CROPS) { - mod.getBlockTracker().stopTracking(crop.cropBlock); - } } @Override public boolean isFinished(AltoClef mod) { - return StorageHelper.calculateInventoryFoodScore(mod) >= _unitsNeeded; + return StorageHelper.calculateInventoryFoodScore(mod) >= unitsNeeded; } @Override protected boolean isEqual(Task other) { if (other instanceof CollectFoodTask task) { - return task._unitsNeeded == _unitsNeeded; + return task.unitsNeeded == unitsNeeded; } return false; } @Override protected String toDebugString() { - return "Collect " + _unitsNeeded + " units of food."; + return "Collect " + unitsNeeded + " units of food."; } /** @@ -351,7 +348,7 @@ private Task pickupBlockTaskOrNull(AltoClef mod, Block blockToCheck, Item itemTo if (!WorldHelper.canBreak(mod, blockPos)) return false; return accept.test(blockPos); }; - Optional nearestBlock = mod.getBlockTracker().getNearestTracking(mod.getPlayer().getPos(), acceptPlus, blockToCheck); + Optional nearestBlock = mod.getBlockScanner().getNearestBlock(mod.getPlayer().getPos(), acceptPlus, blockToCheck); if (nearestBlock.isPresent() && !nearestBlock.get().isWithinDistance(mod.getPlayer().getPos(), maxRange)) { nearestBlock = Optional.empty(); @@ -361,15 +358,14 @@ private Task pickupBlockTaskOrNull(AltoClef mod, Block blockToCheck, Item itemTo if (mod.getEntityTracker().itemDropped(itemToGrab)) { nearestDrop = mod.getEntityTracker().getClosestItemDrop(mod.getPlayer().getPos(), itemToGrab); } - boolean spotted = nearestBlock.isPresent() || nearestDrop.isPresent(); - // Collect hay until we have enough. - if (spotted) { - if (nearestDrop.isPresent()) { - return new PickupDroppedItemTask(itemToGrab, Integer.MAX_VALUE); - } else { - return new DoToClosestBlockTask(DestroyBlockTask::new, acceptPlus, blockToCheck); - } + + if (nearestDrop.isPresent()) { + return pickupTaskOrNull(mod,itemToGrab); } + if (nearestBlock.isPresent()) { + return new DoToClosestBlockTask(DestroyBlockTask::new, acceptPlus, blockToCheck); + } + return null; } @@ -392,9 +388,33 @@ private Task pickupTaskOrNull(AltoClef mod, Item itemToGrab, double maxRange) { } if (nearestDrop.isPresent()) { if (nearestDrop.get().isInRange(mod.getPlayer(), maxRange)) { + if (mod.getItemStorage().getSlotsThatCanFitInPlayerInventory(nearestDrop.get().getStack(), false).isEmpty()) { + Optional slot = StorageHelper.getGarbageSlot(mod); + + // tf am I supposed to do if its empty + if (slot.isPresent()) { + ItemStack stack = StorageHelper.getItemStackInSlot(slot.get()); + if (stack.getItem().isFood()) { + // calculate priority, if the item laying on the ground has lower priority than the one we are gonna throw out because of it + // dont pick it up, otherwise we would get stuck in an infinite loop + int inventoryCost = stack.getItem().getFoodComponent().getHunger() * stack.getCount(); + + double hunger = 0; + if (itemToGrab.isFood()) { + hunger = itemToGrab.getFoodComponent().getHunger(); + } else if (itemToGrab.equals(Items.WHEAT)) { + hunger += Items.BREAD.getFoodComponent().getHunger()/3d; + } else { + mod.log("unknown food item: "+itemToGrab); + } + int groundCost = (int) (hunger * nearestDrop.get().getStack().getCount()); + + if (inventoryCost > groundCost) return null; + } + } + } return new PickupDroppedItemTask(new ItemTarget(itemToGrab), true); } - //return new GetToBlockTask(nearestDrop.getBlockPos(), false); } return null; } @@ -404,7 +424,7 @@ private Task pickupTaskOrNull(AltoClef mod, Item itemToGrab) { } @SuppressWarnings("rawtypes") - private static class CookableFoodTarget { + public static class CookableFoodTarget { public String rawFood; public String cookedFood; public Class mobToKill; @@ -419,7 +439,7 @@ public CookableFoodTarget(String rawFood, Class mobToKill) { this(rawFood, "cooked_" + rawFood, mobToKill); } - private Item getRaw() { + public Item getRaw() { return Objects.requireNonNull(TaskCatalogue.getItemMatches(rawFood))[0]; } @@ -450,7 +470,7 @@ public boolean isFish() { } } - private static class CropTarget { + public static class CropTarget { public Item cropItem; public Block cropBlock; diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectFuelTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectFuelTask.java index 8e885c90..63593a81 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectFuelTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectFuelTask.java @@ -11,10 +11,10 @@ // TODO: Make this collect more than just coal. It should smartly pick alternative sources if coal is too far away or if we simply cannot get a wooden pick. public class CollectFuelTask extends Task { - private final double _targetFuel; + private final double targetFuel; public CollectFuelTask(double targetFuel) { - _targetFuel = targetFuel; + this.targetFuel = targetFuel; } @Override @@ -29,7 +29,7 @@ protected Task onTick(AltoClef mod) { case OVERWORLD -> { // Just collect coal for now. setDebugState("Collecting coal."); - return TaskCatalogue.getItemTask(Items.COAL, (int) Math.ceil(_targetFuel / 8)); + return TaskCatalogue.getItemTask(Items.COAL, (int) Math.ceil(targetFuel / 8)); } case END -> { setDebugState("Going to overworld, since, well, no more fuel can be found here."); @@ -39,7 +39,6 @@ protected Task onTick(AltoClef mod) { setDebugState("Going to overworld, since we COULD use wood but wood confuses the bot. A bug at the moment."); return new DefaultGoToDimensionTask(Dimension.OVERWORLD); } - //return TaskCatalogue.getItemTask("planks", (int) Math.ceil(_targetFuel)); } setDebugState("INVALID DIMENSION: " + WorldHelper.getCurrentDimension()); return null; @@ -53,18 +52,18 @@ protected void onStop(AltoClef mod, Task interruptTask) { @Override protected boolean isEqual(Task other) { if (other instanceof CollectFuelTask task) { - return Math.abs(task._targetFuel - _targetFuel) < 0.01; + return Math.abs(task.targetFuel - targetFuel) < 0.01; } return false; } @Override public boolean isFinished(AltoClef mod) { - return mod.getItemStorage().getItemCountInventoryOnly(Items.COAL) >= _targetFuel; + return mod.getItemStorage().getItemCountInventoryOnly(Items.COAL) >= targetFuel; } @Override protected String toDebugString() { - return "Collect Fuel: x" + _targetFuel; + return "Collect Fuel: x" + targetFuel; } } diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectGoldIngotTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectGoldIngotTask.java index d50e88b6..21850da1 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectGoldIngotTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectGoldIngotTask.java @@ -19,11 +19,11 @@ public class CollectGoldIngotTask extends ResourceTask { - private final int _count; + private final int count; public CollectGoldIngotTask(int count) { super(Items.GOLD_INGOT, count); - _count = count; + this.count = count; } @Override @@ -41,35 +41,35 @@ protected Task onResourceTick(AltoClef mod) { if (WorldHelper.getCurrentDimension() == Dimension.OVERWORLD) { if (mod.getModSettings().shouldUseBlastFurnace()) { if (mod.getItemStorage().hasItem(Items.BLAST_FURNACE) || - mod.getBlockTracker().anyFound(Blocks.BLAST_FURNACE) || + mod.getBlockScanner().anyFound(Blocks.BLAST_FURNACE) || mod.getEntityTracker().itemDropped(Items.BLAST_FURNACE)) { - return new SmeltInBlastFurnaceTask(new SmeltTarget(new ItemTarget(Items.GOLD_INGOT, _count), new ItemTarget(Items.RAW_GOLD, _count))); + return new SmeltInBlastFurnaceTask(new SmeltTarget(new ItemTarget(Items.GOLD_INGOT, count), new ItemTarget(Items.RAW_GOLD, count))); } - if (_count < 5) { - return new SmeltInFurnaceTask(new SmeltTarget(new ItemTarget(Items.GOLD_INGOT, _count), new ItemTarget(Items.RAW_GOLD, _count))); + if (count < 5) { + return new SmeltInFurnaceTask(new SmeltTarget(new ItemTarget(Items.GOLD_INGOT, count), new ItemTarget(Items.RAW_GOLD, count))); } mod.getBehaviour().addProtectedItems(Items.COBBLESTONE, Items.STONE, Items.SMOOTH_STONE); - Optional furnacePos = mod.getBlockTracker().getNearestTracking(Blocks.FURNACE); + Optional furnacePos = mod.getBlockScanner().getNearestBlock(Blocks.FURNACE); furnacePos.ifPresent(blockPos -> mod.getBehaviour().avoidBlockBreaking(blockPos)); if (mod.getItemStorage().getItemCount(Items.IRON_INGOT) >= 5) { return TaskCatalogue.getItemTask(Items.BLAST_FURNACE, 1); } return new SmeltInFurnaceTask(new SmeltTarget(new ItemTarget(Items.IRON_INGOT, 5), new ItemTarget(Items.RAW_IRON, 5))); } - return new SmeltInFurnaceTask(new SmeltTarget(new ItemTarget(Items.GOLD_INGOT, _count), new ItemTarget(Items.RAW_GOLD, _count))); + return new SmeltInFurnaceTask(new SmeltTarget(new ItemTarget(Items.GOLD_INGOT, count), new ItemTarget(Items.RAW_GOLD, count))); } else if (WorldHelper.getCurrentDimension() == Dimension.NETHER) { // If we have enough nuggets, craft them. int nuggs = mod.getItemStorage().getItemCount(Items.GOLD_NUGGET); - int nuggs_needed = _count * 9 - mod.getItemStorage().getItemCount(Items.GOLD_INGOT) * 9; + int nuggs_needed = count * 9 - mod.getItemStorage().getItemCount(Items.GOLD_INGOT) * 9; if (nuggs >= nuggs_needed) { ItemTarget n = new ItemTarget(Items.GOLD_NUGGET); CraftingRecipe recipe = CraftingRecipe.newShapedRecipe("gold_ingot", new ItemTarget[]{ n, n, n, n, n, n, n, n, n }, 1); - return new CraftInTableTask(new RecipeTarget(Items.GOLD_INGOT, _count, recipe)); + return new CraftInTableTask(new RecipeTarget(Items.GOLD_INGOT, count, recipe)); } // Mine nuggets - return new MineAndCollectTask(new ItemTarget(Items.GOLD_NUGGET, _count * 9), new Block[]{Blocks.NETHER_GOLD_ORE}, MiningRequirement.WOOD); + return new MineAndCollectTask(new ItemTarget(Items.GOLD_NUGGET, count * 9), new Block[]{Blocks.NETHER_GOLD_ORE}, MiningRequirement.WOOD); } else { return new DefaultGoToDimensionTask(Dimension.OVERWORLD); } @@ -82,11 +82,11 @@ protected void onResourceStop(AltoClef mod, Task interruptTask) { @Override protected boolean isEqualResource(ResourceTask other) { - return other instanceof CollectGoldIngotTask && ((CollectGoldIngotTask) other)._count == _count; + return other instanceof CollectGoldIngotTask && ((CollectGoldIngotTask) other).count == count; } @Override protected String toDebugStringName() { - return "Collecting " + _count + " gold."; + return "Collecting " + count + " gold."; } } diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectGoldNuggetsTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectGoldNuggetsTask.java index fa7633d8..defb39d9 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectGoldNuggetsTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectGoldNuggetsTask.java @@ -14,11 +14,11 @@ public class CollectGoldNuggetsTask extends ResourceTask { - private final int _count; + private final int count; public CollectGoldNuggetsTask(int count) { super(Items.GOLD_NUGGET, count); - _count = count; + this.count = count; } @Override @@ -37,17 +37,17 @@ protected Task onResourceTick(AltoClef mod) { case OVERWORLD -> { setDebugState("Getting gold ingots to convert to nuggets"); int potentialNuggies = mod.getItemStorage().getItemCount(Items.GOLD_NUGGET) + mod.getItemStorage().getItemCount(Items.GOLD_INGOT) * 9; - if (potentialNuggies >= _count && mod.getItemStorage().hasItem(Items.GOLD_INGOT)) { + if (potentialNuggies >= count && mod.getItemStorage().hasItem(Items.GOLD_INGOT)) { // Craft gold ingots to nuggets - return new CraftInInventoryTask(new RecipeTarget(Items.GOLD_NUGGET, _count, CraftingRecipe.newShapedRecipe("golden_nuggets", new ItemTarget[]{new ItemTarget(Items.GOLD_INGOT, 1), null, null, null}, 9))); + return new CraftInInventoryTask(new RecipeTarget(Items.GOLD_NUGGET, count, CraftingRecipe.newShapedRecipe("golden_nuggets", new ItemTarget[]{new ItemTarget(Items.GOLD_INGOT, 1), null, null, null}, 9))); } // Get gold ingots - int nuggiesStillNeeded = _count - potentialNuggies; + int nuggiesStillNeeded = count - potentialNuggies; return TaskCatalogue.getItemTask(Items.GOLD_INGOT, (int) Math.ceil((double) nuggiesStillNeeded / 9.0)); } case NETHER -> { setDebugState("Mining nuggies"); - return new MineAndCollectTask(Items.GOLD_NUGGET, _count, new Block[]{Blocks.NETHER_GOLD_ORE, Blocks.GILDED_BLACKSTONE}, MiningRequirement.WOOD); + return new MineAndCollectTask(Items.GOLD_NUGGET, count, new Block[]{Blocks.NETHER_GOLD_ORE, Blocks.GILDED_BLACKSTONE}, MiningRequirement.WOOD); } case END -> { setDebugState("Going to overworld"); @@ -71,6 +71,6 @@ protected boolean isEqualResource(ResourceTask other) { @Override protected String toDebugStringName() { - return "Collecting " + _count + " nuggets"; + return "Collecting " + count + " nuggets"; } } diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectHayBlockTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectHayBlockTask.java index 22484c16..de491345 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectHayBlockTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectHayBlockTask.java @@ -15,11 +15,11 @@ // TODO: This can technically be removed, as it's a mine task followed by a collect task. public class CollectHayBlockTask extends ResourceTask { - private final int _count; + private final int count; public CollectHayBlockTask(int count) { super(Items.HAY_BLOCK, count); - _count = count; + this.count = count; } @Override @@ -29,23 +29,23 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.HAY_BLOCK); + } @Override protected Task onResourceTick(AltoClef mod) { - if (mod.getBlockTracker().anyFound(Blocks.HAY_BLOCK)) { - return new MineAndCollectTask(Items.HAY_BLOCK, _count, new Block[]{Blocks.HAY_BLOCK}, MiningRequirement.HAND); + if (mod.getBlockScanner().anyFound(Blocks.HAY_BLOCK)) { + return new MineAndCollectTask(Items.HAY_BLOCK, count, new Block[]{Blocks.HAY_BLOCK}, MiningRequirement.HAND); } ItemTarget w = new ItemTarget(Items.WHEAT, 1); - return new CraftInTableTask(new RecipeTarget(Items.HAY_BLOCK, _count, CraftingRecipe.newShapedRecipe("hay_block", new ItemTarget[]{w, w, w, w, w, w, w, w, w}, 1))); + return new CraftInTableTask(new RecipeTarget(Items.HAY_BLOCK, count, CraftingRecipe.newShapedRecipe("hay_block", new ItemTarget[]{w, w, w, w, w, w, w, w, w}, 1))); } @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.HAY_BLOCK); + } @Override @@ -55,6 +55,6 @@ protected boolean isEqualResource(ResourceTask other) { @Override protected String toDebugStringName() { - return "Collecting " + _count + " hay blocks."; + return "Collecting " + count + " hay blocks."; } } diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectHoneycombTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectHoneycombTask.java index 0f37a57e..9ddc3b54 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectHoneycombTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectHoneycombTask.java @@ -18,37 +18,36 @@ import java.util.Optional; public class CollectHoneycombTask extends ResourceTask { - private final boolean _campfire; - private final int _count; - private BlockPos _nest; + private final boolean campfire; + private final int count; + private BlockPos nest; public CollectHoneycombTask(int targetCount) { super(Items.HONEYCOMB, targetCount); - _campfire = true; - _count = targetCount; + campfire = true; + count = targetCount; } public CollectHoneycombTask(int targetCount, boolean useCampfire) { super(Items.HONEYCOMB, targetCount); - _campfire = useCampfire; - _count = targetCount; + campfire = useCampfire; + count = targetCount; } @Override protected void onResourceStart(AltoClef mod) { mod.getBehaviour().push(); - mod.getBlockTracker().trackBlock(Blocks.BEE_NEST); } @Override protected Task onResourceTick(AltoClef mod) { - if (_nest == null) { - Optional getNearestNest = mod.getBlockTracker().getNearestTracking(Blocks.BEE_NEST); - if (getNearestNest.isPresent()) _nest = getNearestNest.get(); + if (nest == null) { + Optional getNearestNest = mod.getBlockScanner().getNearestBlock(Blocks.BEE_NEST); + if (getNearestNest.isPresent()) nest = getNearestNest.get(); } // If we are STILL null - if (_nest == null) { - if (_campfire && !mod.getItemStorage().hasItemInventoryOnly(Items.CAMPFIRE)) { + if (nest == null) { + if (campfire && !mod.getItemStorage().hasItemInventoryOnly(Items.CAMPFIRE)) { // May as well get a campfire setDebugState("Can't find nest, getting campfire first..."); return new CataloguedResourceTask(new ItemTarget(Items.CAMPFIRE, 1)); @@ -56,32 +55,31 @@ protected Task onResourceTick(AltoClef mod) { setDebugState("Alright, we're searching"); return new SearchChunkForBlockTask(Blocks.BEE_NEST); } - if (_campfire && !isCampfireUnderNest(mod, _nest)) { + if (campfire && !isCampfireUnderNest(mod, nest)) { if (!mod.getItemStorage().hasItemInventoryOnly(Items.CAMPFIRE)) { setDebugState("Getting a campfire"); return new CataloguedResourceTask(new ItemTarget(Items.CAMPFIRE, 1)); } setDebugState("Placing campfire"); - return new PlaceBlockTask(_nest.down(2), Blocks.CAMPFIRE); + return new PlaceBlockTask(nest.down(2), Blocks.CAMPFIRE); } if (!mod.getItemStorage().hasItemInventoryOnly(Items.SHEARS)) { setDebugState("Getting shears"); return new CataloguedResourceTask(new ItemTarget(Items.SHEARS, 1)); } - if (mod.getWorld().getBlockState(_nest).get(Properties.HONEY_LEVEL) != 5) { - if (!_nest.isWithinDistance(mod.getPlayer().getPos(), 20)) { + if (mod.getWorld().getBlockState(nest).get(Properties.HONEY_LEVEL) != 5) { + if (!nest.isWithinDistance(mod.getPlayer().getPos(), 20)) { setDebugState("Getting close to nest"); - return new GetCloseToBlockTask(_nest); + return new GetCloseToBlockTask(nest); } setDebugState("Waiting for nest to get honey..."); return null; } - return new InteractWithBlockTask(Items.SHEARS, _nest); + return new InteractWithBlockTask(Items.SHEARS, nest); } @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.BEE_NEST); mod.getBehaviour().pop(); } @@ -92,7 +90,7 @@ protected boolean isEqualResource(ResourceTask other) { @Override protected String toDebugStringName() { - return "Collecting " + _count + " Honeycombs " + (_campfire ? "Peacefully" : "Recklessly"); + return "Collecting " + count + " Honeycombs " + (campfire ? "Peacefully" : "Recklessly"); } @Override diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectIronIngotTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectIronIngotTask.java index f39b21ec..9472dad2 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectIronIngotTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectIronIngotTask.java @@ -16,11 +16,11 @@ public class CollectIronIngotTask extends ResourceTask { - private final int _count; + private final int count; public CollectIronIngotTask(int count) { super(Items.IRON_INGOT, count); - _count = count; + this.count = count; } @Override @@ -31,43 +31,41 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { mod.getBehaviour().push(); - mod.getBlockTracker().trackBlock(Blocks.FURNACE, Blocks.BLAST_FURNACE); } @Override protected Task onResourceTick(AltoClef mod) { if (mod.getModSettings().shouldUseBlastFurnace()) { if (mod.getItemStorage().hasItem(Items.BLAST_FURNACE) || - mod.getBlockTracker().anyFound(Blocks.BLAST_FURNACE) || + mod.getBlockScanner().anyFound(Blocks.BLAST_FURNACE) || mod.getEntityTracker().itemDropped(Items.BLAST_FURNACE)) { - return new SmeltInBlastFurnaceTask(new SmeltTarget(new ItemTarget(Items.IRON_INGOT, _count), new ItemTarget(Items.RAW_IRON, _count))); + return new SmeltInBlastFurnaceTask(new SmeltTarget(new ItemTarget(Items.IRON_INGOT, count), new ItemTarget(Items.RAW_IRON, count))); } - if (_count < 5) { - return new SmeltInFurnaceTask(new SmeltTarget(new ItemTarget(Items.IRON_INGOT, _count), new ItemTarget(Items.RAW_IRON, _count))); + if (count < 5) { + return new SmeltInFurnaceTask(new SmeltTarget(new ItemTarget(Items.IRON_INGOT, count), new ItemTarget(Items.RAW_IRON, count))); } - Optional furnacePos = mod.getBlockTracker().getNearestTracking(Blocks.FURNACE); + Optional furnacePos = mod.getBlockScanner().getNearestBlock(Blocks.FURNACE); furnacePos.ifPresent(blockPos -> mod.getBehaviour().avoidBlockBreaking(blockPos)); if (mod.getItemStorage().getItemCount(Items.IRON_INGOT) >= 5) { return TaskCatalogue.getItemTask(Items.BLAST_FURNACE, 1); } return new SmeltInFurnaceTask(new SmeltTarget(new ItemTarget(Items.IRON_INGOT, 5), new ItemTarget(Items.RAW_IRON, 5))); } - return new SmeltInFurnaceTask(new SmeltTarget(new ItemTarget(Items.IRON_INGOT, _count), new ItemTarget(Items.RAW_IRON, _count))); + return new SmeltInFurnaceTask(new SmeltTarget(new ItemTarget(Items.IRON_INGOT, count), new ItemTarget(Items.RAW_IRON, count))); } @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { mod.getBehaviour().pop(); - mod.getBlockTracker().stopTracking(Blocks.FURNACE, Blocks.BLAST_FURNACE); } @Override protected boolean isEqualResource(ResourceTask other) { - return other instanceof CollectIronIngotTask && ((CollectIronIngotTask) other)._count == _count; + return other instanceof CollectIronIngotTask same && same.count == count; } @Override protected String toDebugStringName() { - return "Collecting " + _count + " iron."; + return "Collecting " + count + " iron."; } } diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectMagmaCreamTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectMagmaCreamTask.java index 955dff62..1b90f093 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectMagmaCreamTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectMagmaCreamTask.java @@ -12,11 +12,11 @@ import net.minecraft.item.Items; public class CollectMagmaCreamTask extends ResourceTask { - private final int _count; + private final int count; public CollectMagmaCreamTask(int count) { super(Items.MAGMA_CREAM, count); - _count = count; + this.count = count; } @Override @@ -42,7 +42,7 @@ protected Task onResourceTick(AltoClef mod) { * Go to overworld lol */ int currentCream = mod.getItemStorage().getItemCount(Items.MAGMA_CREAM); - int neededCream = _count - currentCream; + int neededCream = count - currentCream; switch (WorldHelper.getCurrentDimension()) { case NETHER -> { if (mod.getEntityTracker().entityFound(MagmaCubeEntity.class)) { @@ -89,6 +89,6 @@ protected boolean isEqualResource(ResourceTask other) { @Override protected String toDebugStringName() { - return "Collecting " + _count + " Magma cream."; + return "Collecting " + count + " Magma cream."; } } diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectMeatTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectMeatTask.java index 05be9083..698e8dca 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectMeatTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectMeatTask.java @@ -1,12 +1,10 @@ package adris.altoclef.tasks.resources; import adris.altoclef.AltoClef; -import adris.altoclef.Debug; import adris.altoclef.TaskCatalogue; import adris.altoclef.tasks.container.SmeltInSmokerTask; import adris.altoclef.tasks.movement.PickupDroppedItemTask; import adris.altoclef.tasks.movement.TimeoutWanderTask; -import adris.altoclef.tasks.speedrun.MarvionBeatMinecraftTask; import adris.altoclef.tasksystem.Task; import adris.altoclef.util.ItemTarget; import adris.altoclef.util.SmeltTarget; @@ -14,12 +12,9 @@ import adris.altoclef.util.helpers.StorageHelper; import adris.altoclef.util.slots.SmokerSlot; import adris.altoclef.util.time.TimerGame; -import net.minecraft.client.MinecraftClient; import net.minecraft.entity.Entity; import net.minecraft.entity.ItemEntity; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.mob.HostileEntity; -import net.minecraft.entity.mob.SlimeEntity; import net.minecraft.entity.passive.ChickenEntity; import net.minecraft.entity.passive.CowEntity; import net.minecraft.entity.passive.PigEntity; @@ -34,19 +29,19 @@ import java.util.function.Predicate; public class CollectMeatTask extends Task { - private static final CookableFoodTarget[] COOKABLE_FOODS = new CookableFoodTarget[]{ + public static final CookableFoodTarget[] COOKABLE_FOODS = new CookableFoodTarget[]{ new CookableFoodTarget("beef", CowEntity.class), new CookableFoodTarget("porkchop", PigEntity.class), new CookableFoodTarget("chicken", ChickenEntity.class), new CookableFoodTarget("mutton", SheepEntity.class) }; - private final double _unitsNeeded; - private final TimerGame _checkNewOptionsTimer = new TimerGame(10); - private SmeltInSmokerTask _smeltTask = null; - private Task _currentResourceTask = null; + private final double unitsNeeded; + private final TimerGame checkNewOptionsTimer = new TimerGame(10); + private SmeltInSmokerTask smeltTask = null; + private Task currentResourceTask = null; public CollectMeatTask(double unitsNeeded) { - _unitsNeeded = unitsNeeded; + this.unitsNeeded = unitsNeeded; } private static double getFoodPotential(ItemStack food) { @@ -83,44 +78,25 @@ protected void onStart(AltoClef mod) { @Override protected Task onTick(AltoClef mod) { - if (mod.getEntityTracker().entityFound(ChickenEntity.class)) { - Optional chickens = mod.getEntityTracker().getClosestEntity(ChickenEntity.class); - if (chickens.isPresent()) { - Iterable entities = mod.getWorld().getEntities(); - for (Entity entity : entities) { - if (entity instanceof HostileEntity || entity instanceof SlimeEntity) { - if (chickens.get().hasPassenger(entity)) { - if (mod.getEntityTracker().isEntityReachable(entity)) { - Debug.logMessage("Blacklisting chicken jockey."); - mod.getEntityTracker().requestEntityUnreachable(chickens.get()); - } - } - } - } - } - } + CollectFoodTask.blackListChickenJockeys(mod); // If we were previously smelting, keep on smelting. - if (_smeltTask != null && _smeltTask.isActive() && !_smeltTask.isFinished(mod)) { + if (smeltTask != null && smeltTask.isActive() && !smeltTask.isFinished(mod)) { setDebugState("Cooking..."); - if (MarvionBeatMinecraftTask.getConfig().renderDistanceManipulation) { - MinecraftClient.getInstance().options.getViewDistance().setValue(2); - MinecraftClient.getInstance().options.getEntityDistanceScaling().setValue(0.5); - } - return _smeltTask; + return smeltTask; } else { - _smeltTask = null; + smeltTask = null; } - if (_checkNewOptionsTimer.elapsed()) { + if (checkNewOptionsTimer.elapsed()) { // Try a new resource task - _checkNewOptionsTimer.reset(); - _currentResourceTask = null; + checkNewOptionsTimer.reset(); + currentResourceTask = null; } - if (_currentResourceTask != null && _currentResourceTask.isActive() && !_currentResourceTask.isFinished(mod) && !_currentResourceTask.thisOrChildAreTimedOut()) { - return _currentResourceTask; + if (currentResourceTask != null && currentResourceTask.isActive() && !currentResourceTask.isFinished(mod) && !currentResourceTask.thisOrChildAreTimedOut()) { + return currentResourceTask; } // Calculate potential double potentialFood = calculateFoodPotential(mod); - if (potentialFood >= _unitsNeeded) { + if (potentialFood >= unitsNeeded) { // Convert our raw foods // PLAN: // - If we have raw foods, smelt all of them @@ -130,9 +106,9 @@ protected Task onTick(AltoClef mod) { if (rawCount > 0) { //Debug.logMessage("STARTING COOK OF " + cookable.getRaw().getTranslationKey()); int toSmelt = rawCount + mod.getItemStorage().getItemCount(cookable.getCooked()); - _smeltTask = new SmeltInSmokerTask(new SmeltTarget(new ItemTarget(cookable.cookedFood, toSmelt), new ItemTarget(cookable.rawFood, rawCount))); - _smeltTask.ignoreMaterials(); - return _smeltTask; + smeltTask = new SmeltInSmokerTask(new SmeltTarget(new ItemTarget(cookable.cookedFood, toSmelt), new ItemTarget(cookable.rawFood, rawCount))); + smeltTask.ignoreMaterials(); + return smeltTask; } } } else { @@ -142,8 +118,8 @@ protected Task onTick(AltoClef mod) { if (t == null) t = this.pickupTaskOrNull(mod, cookable.getCooked(), 40); if (t != null) { setDebugState("Picking up Cookable food"); - _currentResourceTask = t; - return _currentResourceTask; + currentResourceTask = t; + return currentResourceTask; } } // Cooked foods @@ -166,8 +142,8 @@ protected Task onTick(AltoClef mod) { if (bestEntity != null) { setDebugState("Killing " + bestEntity.getType().getTranslationKey()); Predicate notBaby = entity -> entity instanceof LivingEntity livingEntity && !livingEntity.isBaby(); - _currentResourceTask = killTaskOrNull(bestEntity, notBaby, bestRawFood); - return _currentResourceTask; + currentResourceTask = killTaskOrNull(bestEntity, notBaby, bestRawFood); + return currentResourceTask; } } for (Item raw : ItemHelper.RAW_FOODS) { @@ -175,8 +151,8 @@ protected Task onTick(AltoClef mod) { Optional cooked = ItemHelper.getCookedFood(raw); if (cooked.isPresent()) { int targetCount = mod.getItemStorage().getItemCount(cooked.get()) + mod.getItemStorage().getItemCount(raw); - _smeltTask = new SmeltInSmokerTask(new SmeltTarget(new ItemTarget(cooked.get(), targetCount), new ItemTarget(raw, targetCount))); - return _smeltTask; + smeltTask = new SmeltInSmokerTask(new SmeltTarget(new ItemTarget(cooked.get(), targetCount), new ItemTarget(raw, targetCount))); + return smeltTask; } } } @@ -214,23 +190,23 @@ protected void onStop(AltoClef mod, Task interruptTask) { @Override public boolean isFinished(AltoClef mod) { - return StorageHelper.calculateInventoryFoodScore(mod) >= _unitsNeeded && _smeltTask == null; + return StorageHelper.calculateInventoryFoodScore(mod) >= unitsNeeded && smeltTask == null; } @Override protected boolean isEqual(Task other) { if (other instanceof CollectMeatTask task) { - return task._unitsNeeded == _unitsNeeded; + return task.unitsNeeded == unitsNeeded; } return false; } @Override protected String toDebugString() { - return "Collect " + _unitsNeeded + " units of meat."; + return "Collect " + unitsNeeded + " units of meat."; } - private static class CookableFoodTarget { + public static class CookableFoodTarget { public String rawFood; public String cookedFood; public Class mobToKill; @@ -245,11 +221,11 @@ public CookableFoodTarget(String rawFood, Class mobToKill) { this(rawFood, "cooked_" + rawFood, mobToKill); } - private Item getRaw() { + public Item getRaw() { return Objects.requireNonNull(TaskCatalogue.getItemMatches(rawFood))[0]; } - private Item getCooked() { + public Item getCooked() { return Objects.requireNonNull(TaskCatalogue.getItemMatches(cookedFood))[0]; } diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectMilkTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectMilkTask.java index 8d27f4d7..a206be16 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectMilkTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectMilkTask.java @@ -15,11 +15,11 @@ public class CollectMilkTask extends ResourceTask { - private final int _count; + private final int count; public CollectMilkTask(int targetCount) { super(Items.MILK_BUCKET, targetCount); - _count = targetCount; + count = targetCount; } @Override @@ -56,7 +56,7 @@ protected boolean isEqualResource(ResourceTask other) { @Override protected String toDebugStringName() { - return "Collecting " + _count + " milk buckets."; + return "Collecting " + count + " milk buckets."; } static class MilkCowTask extends AbstractDoToEntityTask { diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectNetherBricksTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectNetherBricksTask.java index 43a1cd3c..884d31e2 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectNetherBricksTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectNetherBricksTask.java @@ -28,7 +28,7 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.NETHER_BRICKS); + } @Override @@ -40,7 +40,7 @@ protected Task onResourceTick(AltoClef mod) { * Otherwise craft them from the "nether_brick" item. */ - if (mod.getBlockTracker().anyFound(Blocks.NETHER_BRICKS)) { + if (mod.getBlockScanner().anyFound(Blocks.NETHER_BRICKS)) { return new MineAndCollectTask(Items.NETHER_BRICKS, _count, new Block[]{Blocks.NETHER_BRICKS}, MiningRequirement.WOOD); } @@ -50,7 +50,7 @@ protected Task onResourceTick(AltoClef mod) { @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.NETHER_BRICKS); + } @Override diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectObsidianTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectObsidianTask.java index 354341c6..3bc8d94f 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectObsidianTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectObsidianTask.java @@ -69,10 +69,6 @@ protected void onResourceStart(AltoClef mod) { mod.getBehaviour().setRayTracingFluidHandling(RaycastContext.FluidHandling.SOURCE_ONLY); - mod.getBlockTracker().trackBlock(Blocks.OBSIDIAN); - //mod.getBlockTracker().trackBlock(Blocks.WATER); - //mod.getBlockTracker().trackBlock(Blocks.LAVA); - // Avoid placing on the lava block we're trying to mine. mod.getBehaviour().avoidBlockPlacing(pos -> { if (_lavaWaitCurrentPos != null) { @@ -125,7 +121,7 @@ protected adris.altoclef.tasksystem.Task onResourceTick(AltoClef mod) { } } */ - if (/*obsidianNearby || */mod.getBlockTracker().anyFound(goodObsidian, Blocks.OBSIDIAN) || mod.getEntityTracker().itemDropped(Items.OBSIDIAN)) { + if (/*obsidianNearby || */mod.getBlockScanner().anyFound(goodObsidian, Blocks.OBSIDIAN) || mod.getEntityTracker().itemDropped(Items.OBSIDIAN)) { /* // Clear nearby water BlockPos nearestObby = mod.getBlockTracker().getNearestTracking(mod.getPlayer().getPos(), Blocks.OBSIDIAN); @@ -182,9 +178,6 @@ protected adris.altoclef.tasksystem.Task onResourceTick(AltoClef mod) { @Override protected void onResourceStop(AltoClef mod, adris.altoclef.tasksystem.Task interruptTask) { - //mod.getBlockTracker().stopTracking(Blocks.LAVA); - //mod.getBlockTracker().stopTracking(Blocks.WATER); - mod.getBlockTracker().stopTracking(Blocks.OBSIDIAN); mod.getBehaviour().pop(); } diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectPlanksTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectPlanksTask.java index 6891703b..814e23de 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectPlanksTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectPlanksTask.java @@ -5,8 +5,10 @@ import adris.altoclef.tasks.CraftInInventoryTask; import adris.altoclef.tasks.ResourceTask; import adris.altoclef.tasksystem.Task; +import adris.altoclef.trackers.storage.ItemStorageTracker; import adris.altoclef.util.*; import adris.altoclef.util.helpers.ItemHelper; +import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage; import net.minecraft.item.Item; import java.util.ArrayList; @@ -50,6 +52,14 @@ private static CraftingRecipe generatePlankRecipe(Item[] logs) { ); } + @Override + protected double getPickupRange(AltoClef mod) { + ItemStorageTracker storage = mod.getItemStorage(); + if (storage.getItemCount(ItemHelper.LOG)*4>_targetCount) return 10; + + return 50; + } + @Override protected boolean shouldAvoidPickingUp(AltoClef mod) { return false; diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectSticksTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectSticksTask.java index fbae13ae..0fe0f702 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectSticksTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectSticksTask.java @@ -4,10 +4,12 @@ import adris.altoclef.tasks.CraftInInventoryTask; import adris.altoclef.tasks.ResourceTask; import adris.altoclef.tasksystem.Task; +import adris.altoclef.trackers.storage.ItemStorageTracker; import adris.altoclef.util.CraftingRecipe; import adris.altoclef.util.ItemTarget; import adris.altoclef.util.MiningRequirement; import adris.altoclef.util.RecipeTarget; +import adris.altoclef.util.helpers.ItemHelper; import net.minecraft.block.Block; import net.minecraft.block.Blocks; import net.minecraft.item.Items; @@ -32,15 +34,30 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { mod.getBehaviour().push(); - mod.getBlockTracker().trackBlock(Blocks.DEAD_BUSH); + } + + @Override + protected double getPickupRange(AltoClef mod) { + ItemStorageTracker storage = mod.getItemStorage(); + if (storage.getItemCount(ItemHelper.PLANKS)*4+storage.getItemCount(ItemHelper.LOG)*4*4 > _targetCount) return 10; + + return 35; } @Override protected Task onResourceTick(AltoClef mod) { - Optional nearestBush = mod.getBlockTracker().getNearestTracking(Blocks.DEAD_BUSH); + // try to craft sticks from bamboo + if (mod.getItemStorage().getItemCount(Items.BAMBOO) >= 2) { + return new CraftInInventoryTask(new RecipeTarget(Items.STICK, Math.min(mod.getItemStorage().getItemCount(Items.BAMBOO)/2,_targetCount), CraftingRecipe.newShapedRecipe("sticks", new ItemTarget[]{new ItemTarget("bamboo"), null, new ItemTarget("bamboo"), null}, 1))); + } + + Optional nearestBush = mod.getBlockScanner().getNearestBlock(Blocks.DEAD_BUSH); // If there's a dead bush within range, go get it if (nearestBush.isPresent() && nearestBush.get().isWithinDistance(mod.getPlayer().getPos(), 20)) { - return new MineAndCollectTask(Items.DEAD_BUSH, 999999, new Block[]{Blocks.DEAD_BUSH}, MiningRequirement.HAND); + ResourceTask task = new MineAndCollectTask(Items.DEAD_BUSH, 1, new Block[]{Blocks.DEAD_BUSH}, MiningRequirement.HAND); + task.setAllowContainers(false); + + return task; } // else craft from wood return new CraftInInventoryTask(new RecipeTarget(Items.STICK, _targetCount, CraftingRecipe.newShapedRecipe("sticks", new ItemTarget[]{new ItemTarget("planks"), null, new ItemTarget("planks"), null}, 4))); @@ -48,7 +65,6 @@ protected Task onResourceTick(AltoClef mod) { @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.DEAD_BUSH); mod.getBehaviour().pop(); } diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectStrippedLogTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectStrippedLogTask.java index b3a85d8e..f27a8ed1 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectStrippedLogTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectStrippedLogTask.java @@ -48,8 +48,6 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(ItemHelper.itemsToBlocks(_strippedLogs)); - mod.getBlockTracker().trackBlock(ItemHelper.itemsToBlocks(_strippableLogs)); } @Override @@ -59,13 +57,13 @@ protected Task onResourceTick(AltoClef mod) { return TaskCatalogue.getItemTask(Items.WOODEN_AXE, 1); } if (mod.getItemStorage().getItemCount(_strippedLogs) < _targetCount) { - Optional strippedLogBlockPos = mod.getBlockTracker().getNearestTracking(ItemHelper.itemsToBlocks(_strippedLogs)); + Optional strippedLogBlockPos = mod.getBlockScanner().getNearestBlock(ItemHelper.itemsToBlocks(_strippedLogs)); if (strippedLogBlockPos.isPresent()) { setDebugState("Getting stripped log"); return new MineAndCollectTask(new ItemTarget(_strippedLogs), ItemHelper.itemsToBlocks(_strippedLogs), MiningRequirement.HAND); } } - Optional strippableLogBlockPos = mod.getBlockTracker().getNearestTracking(ItemHelper.itemsToBlocks(_strippableLogs)); + Optional strippableLogBlockPos = mod.getBlockScanner().getNearestBlock(ItemHelper.itemsToBlocks(_strippableLogs)); if (strippableLogBlockPos.isPresent()) { setDebugState("Stripping log"); return new InteractWithBlockTask(new ItemTarget(_axes), strippableLogBlockPos.get()); @@ -76,8 +74,6 @@ protected Task onResourceTick(AltoClef mod) { @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(ItemHelper.itemsToBlocks(_strippedLogs)); - mod.getBlockTracker().stopTracking(ItemHelper.itemsToBlocks(_strippableLogs)); } @Override diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectWheatSeedsTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectWheatSeedsTask.java index f2e0b843..7c6a839f 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectWheatSeedsTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectWheatSeedsTask.java @@ -24,13 +24,12 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.WHEAT); } @Override protected Task onResourceTick(AltoClef mod) { // If wheat block found, collect wheat but don't pick up the wheat. - if (mod.getBlockTracker().anyFound(Blocks.WHEAT)) { + if (mod.getBlockScanner().anyFound(Blocks.WHEAT)) { return new CollectCropTask(Items.AIR, 999, Blocks.WHEAT, Items.WHEAT_SEEDS); } // Otherwise, break grass blocks. diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectWheatTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectWheatTask.java index a1edb1e7..4cbca791 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectWheatTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectWheatTask.java @@ -28,7 +28,7 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.HAY_BLOCK); + } @Override @@ -39,7 +39,7 @@ protected Task onResourceTick(AltoClef mod) { setDebugState("Crafting wheat"); return new CraftInInventoryTask(new RecipeTarget(Items.WHEAT, _count, CraftingRecipe.newShapedRecipe("wheat", new ItemTarget[]{new ItemTarget(Items.HAY_BLOCK, 1), null, null, null}, 9))); } - if (mod.getBlockTracker().anyFound(Blocks.HAY_BLOCK) || mod.getEntityTracker().itemDropped(Items.HAY_BLOCK)) { + if (mod.getBlockScanner().anyFound(Blocks.HAY_BLOCK) || mod.getEntityTracker().itemDropped(Items.HAY_BLOCK)) { return new MineAndCollectTask(Items.HAY_BLOCK, 99999999, new Block[]{Blocks.HAY_BLOCK}, MiningRequirement.HAND); } // Collect wheat @@ -48,7 +48,7 @@ protected Task onResourceTick(AltoClef mod) { @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.HAY_BLOCK); + } @Override diff --git a/src/main/java/adris/altoclef/tasks/resources/CollectWoolTask.java b/src/main/java/adris/altoclef/tasks/resources/CollectWoolTask.java index 7027980e..4f00d8a1 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CollectWoolTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CollectWoolTask.java @@ -53,7 +53,7 @@ protected boolean shouldAvoidPickingUp(AltoClef mod) { @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(ItemHelper.itemsToBlocks(_wools)); + } @Override @@ -65,7 +65,7 @@ protected Task onResourceTick(AltoClef mod) { // If we find a wool block, break it. Block[] woolBlocks = ItemHelper.itemsToBlocks(_wools); - if (mod.getBlockTracker().anyFound(woolBlocks)) { + if (mod.getBlockScanner().anyFound(woolBlocks)) { return new MineAndCollectTask(new ItemTarget(_wools), woolBlocks, MiningRequirement.HAND); } @@ -94,7 +94,7 @@ protected Task onResourceTick(AltoClef mod) { @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(ItemHelper.itemsToBlocks(_wools)); + } @Override diff --git a/src/main/java/adris/altoclef/tasks/resources/CraftWithMatchingWoolTask.java b/src/main/java/adris/altoclef/tasks/resources/CraftWithMatchingWoolTask.java index bf38a6e7..f5219eac 100644 --- a/src/main/java/adris/altoclef/tasks/resources/CraftWithMatchingWoolTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/CraftWithMatchingWoolTask.java @@ -7,24 +7,23 @@ import java.util.function.Function; -// This is literally identical to its parent, but we give it a name for psychological reasons public abstract class CraftWithMatchingWoolTask extends CraftWithMatchingMaterialsTask { - private final Function _getMajorityMaterial; - private final Function _getTargetItem; + private final Function getMajorityMaterial; + private final Function getTargetItem; public CraftWithMatchingWoolTask(ItemTarget target, Function getMajorityMaterial, Function getTargetItem, CraftingRecipe recipe, boolean[] sameMask) { super(target, recipe, sameMask); - _getMajorityMaterial = getMajorityMaterial; - _getTargetItem = getTargetItem; + this.getMajorityMaterial = getMajorityMaterial; + this.getTargetItem = getTargetItem; } @Override protected Item getSpecificItemCorrespondingToMajorityResource(Item majority) { for (ItemHelper.ColorfulItems colorfulItem : ItemHelper.getColorfulItems()) { - if (_getMajorityMaterial.apply(colorfulItem) == majority) { - return _getTargetItem.apply(colorfulItem); + if (getMajorityMaterial.apply(colorfulItem) == majority) { + return getTargetItem.apply(colorfulItem); } } return null; diff --git a/src/main/java/adris/altoclef/tasks/resources/GetSmithingTemplateTask.java b/src/main/java/adris/altoclef/tasks/resources/GetSmithingTemplateTask.java index e74195f1..dbed78ad 100644 --- a/src/main/java/adris/altoclef/tasks/resources/GetSmithingTemplateTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/GetSmithingTemplateTask.java @@ -25,7 +25,7 @@ public GetSmithingTemplateTask(int count) { @Override protected void onResourceStart(AltoClef mod) { - mod.getBlockTracker().trackBlock(Blocks.CHEST); + } @Override @@ -40,7 +40,7 @@ protected Task onResourceTick(AltoClef mod) { // _bastionloc = null; // } if (_chestloc == null) { - for (BlockPos pos : mod.getBlockTracker().getKnownLocations(Blocks.CHEST)) { + for (BlockPos pos : mod.getBlockScanner().getKnownLocations(Blocks.CHEST)) { if (WorldHelper.isInteractableBlock(mod, pos)) { _chestloc = pos; break; @@ -54,7 +54,7 @@ protected Task onResourceTick(AltoClef mod) { return new DestroyBlockTask(_chestloc); } else { _chestloc = null; - for (BlockPos pos : mod.getBlockTracker().getKnownLocations(Blocks.CHEST)) { + for (BlockPos pos : mod.getBlockScanner().getKnownLocations(Blocks.CHEST)) { if (WorldHelper.isInteractableBlock(mod, pos)) { _chestloc = pos; break; @@ -69,7 +69,6 @@ protected Task onResourceTick(AltoClef mod) { @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(Blocks.CHEST); } @Override diff --git a/src/main/java/adris/altoclef/tasks/resources/KillEndermanTask.java b/src/main/java/adris/altoclef/tasks/resources/KillEndermanTask.java index edbcc1b5..4cd13e47 100644 --- a/src/main/java/adris/altoclef/tasks/resources/KillEndermanTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/KillEndermanTask.java @@ -4,11 +4,21 @@ import adris.altoclef.tasks.ResourceTask; import adris.altoclef.tasks.entity.KillEntitiesTask; import adris.altoclef.tasks.entity.KillEntityTask; +import adris.altoclef.tasks.movement.GetCloseToBlockTask; +import adris.altoclef.tasks.movement.GetToBlockTask; +import adris.altoclef.tasks.movement.GetWithinRangeOfBlockTask; +import adris.altoclef.tasks.movement.TimeoutWanderTask; import adris.altoclef.tasksystem.Task; +import adris.altoclef.util.Dimension; import adris.altoclef.util.ItemTarget; +import adris.altoclef.util.helpers.WorldHelper; import adris.altoclef.util.time.TimerGame; +import net.minecraft.block.Blocks; import net.minecraft.entity.mob.EndermanEntity; import net.minecraft.item.Items; +import net.minecraft.util.math.BlockPos; + +import java.util.Optional; public class KillEndermanTask extends ResourceTask { @@ -19,6 +29,7 @@ public class KillEndermanTask extends ResourceTask { public KillEndermanTask(int count) { super(new ItemTarget(Items.ENDER_PEARL, count)); _count = count; + forceDimension(Dimension.NETHER); } @Override @@ -35,9 +46,27 @@ protected void onResourceStart(AltoClef mod) { protected Task onResourceTick(AltoClef mod) { // Dimension if (!mod.getEntityTracker().entityFound(EndermanEntity.class)) { - return getToCorrectDimensionTask(mod); + if (WorldHelper.getCurrentDimension() != Dimension.NETHER) { + return getToCorrectDimensionTask(mod); + } + //nearest warped forest related block + Optional nearest = mod.getBlockScanner().getNearestBlock(Blocks.TWISTING_VINES, Blocks.TWISTING_VINES_PLANT, Blocks.WARPED_HYPHAE, Blocks.WARPED_NYLIUM); + if (nearest.isPresent()) { + if (WorldHelper.inRangeXZ(nearest.get(),mod.getPlayer().getBlockPos(), 40)) { + setDebugState("Waiting for endermen to spawn..."); + return null; + } + + setDebugState("Getting to warped forest biome"); + return new GetWithinRangeOfBlockTask(nearest.get(),35); + } + + setDebugState("Warped forest biome not found"); + return new TimeoutWanderTask(); } + + // Kill the angry one for (EndermanEntity entity : mod.getEntityTracker().getTrackedEntities(EndermanEntity.class)) { final int TOO_FAR_AWAY = 256; @@ -66,6 +95,6 @@ protected boolean isEqualResource(ResourceTask other) { @Override protected String toDebugStringName() { - return "Hunting enderman for " + _count + " pearls."; + return "Hunting endermen for pearls - "+AltoClef.INSTANCE.getItemStorage().getItemCount(Items.ENDER_PEARL)+"/"+_count; } } \ No newline at end of file diff --git a/src/main/java/adris/altoclef/tasks/resources/MineAndCollectTask.java b/src/main/java/adris/altoclef/tasks/resources/MineAndCollectTask.java index a68f6662..c4212b06 100644 --- a/src/main/java/adris/altoclef/tasks/resources/MineAndCollectTask.java +++ b/src/main/java/adris/altoclef/tasks/resources/MineAndCollectTask.java @@ -72,7 +72,6 @@ public static Block[] itemTargetToBlockList(ItemTarget[] targets) { @Override protected void onResourceStart(AltoClef mod) { mod.getBehaviour().push(); - mod.getBlockTracker().trackBlock(_blocksToMine); // We're mining, so don't throw away pickaxes. mod.getBehaviour().addProtectedItems(Items.WOODEN_PICKAXE, Items.STONE_PICKAXE, Items.IRON_PICKAXE, Items.DIAMOND_PICKAXE, Items.NETHERITE_PICKAXE); @@ -97,7 +96,7 @@ protected Task onResourceTick(AltoClef mod) { } // Wrong dimension check. - if (_subtask.wasWandering() && isInWrongDimension(mod) && !mod.getBlockTracker().anyFound(_blocksToMine)) { + if (_subtask.wasWandering() && isInWrongDimension(mod) && !mod.getBlockScanner().anyFound(_blocksToMine)) { return getToCorrectDimensionTask(mod); } @@ -106,7 +105,6 @@ protected Task onResourceTick(AltoClef mod) { @Override protected void onResourceStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(_blocksToMine); mod.getBehaviour().pop(); } @@ -179,9 +177,9 @@ protected Vec3d getPos(AltoClef mod, Object obj) { @Override protected Optional getClosestTo(AltoClef mod, Vec3d pos) { - Optional closestBlock = mod.getBlockTracker().getNearestTracking(pos, check -> { + Optional closestBlock = mod.getBlockScanner().getNearestBlock(pos, check -> { if (_blacklist.contains(check)) return false; - if (mod.getBlockTracker().unreachable(check)) return false; + if (mod.getBlockScanner().isUnreachable(check)) return false; return WorldHelper.canBreak(mod, check); }, _blocks); @@ -190,8 +188,8 @@ protected Optional getClosestTo(AltoClef mod, Vec3d pos) { closestDrop = mod.getEntityTracker().getClosestItemDrop(pos, _targets); } - double blockSq = closestBlock.isEmpty() ? Double.POSITIVE_INFINITY : closestBlock.get().getSquaredDistance(pos); - double dropSq = closestDrop.isEmpty() ? Double.POSITIVE_INFINITY : closestDrop.get().squaredDistanceTo(pos) + 10; // + 5 to make the bot stop mining a bit less + double blockSq = closestBlock.map(blockPos -> blockPos.getSquaredDistance(pos)).orElse(Double.POSITIVE_INFINITY); + double dropSq = closestDrop.map(itemEntity -> itemEntity.squaredDistanceTo(pos) + 10).orElse(Double.POSITIVE_INFINITY); // + 5 to make the bot stop mining a bit less // We can't mine right now. if (mod.getExtraBaritoneSettings().isInteractionPaused()) { @@ -218,7 +216,7 @@ protected Task onTick(AltoClef mod) { if (_miningPos != null && !_progressChecker.check(mod)) { mod.getClientBaritone().getPathingBehavior().forceCancel(); Debug.logMessage("Failed to mine block. Suggesting it may be unreachable."); - mod.getBlockTracker().requestBlockUnreachable(_miningPos, 2); + mod.getBlockScanner().requestBlockUnreachable(_miningPos, 2); _blacklist.add(_miningPos); _miningPos = null; _progressChecker.reset(); @@ -245,7 +243,7 @@ protected Task getGoalTask(Object obj) { @Override protected boolean isValid(AltoClef mod, Object obj) { if (obj instanceof BlockPos b) { - return mod.getBlockTracker().blockIsValid(b, _blocks) && WorldHelper.canBreak(mod, b); + return mod.getBlockScanner().isBlockAtPosition(b, _blocks) && WorldHelper.canBreak(mod, b); } if (obj instanceof ItemEntity drop) { Item item = drop.getStack().getItem(); diff --git a/src/main/java/adris/altoclef/tasks/slot/MoveItemToSlotTask.java b/src/main/java/adris/altoclef/tasks/slot/MoveItemToSlotTask.java index ec8c48c2..efeea521 100644 --- a/src/main/java/adris/altoclef/tasks/slot/MoveItemToSlotTask.java +++ b/src/main/java/adris/altoclef/tasks/slot/MoveItemToSlotTask.java @@ -66,7 +66,8 @@ protected Task onTick(AltoClef mod) { } } if (toPlace.isEmpty()) { - Debug.logError("Called MoveItemToSlotTask when item/not enough item is available! valid items: " + StlHelper.toString(validItems, Item::getTranslationKey)); + Debug.logWarning("Called MoveItemToSlotTask when item/not enough item is available! valid items: " + StlHelper.toString(validItems, Item::getTranslationKey)); + this.stop(mod); return null; } mod.getSlotHandler().clickSlot(toPlace.get(), 0, SlotActionType.PICKUP); diff --git a/src/main/java/adris/altoclef/tasks/speedrun/BeatMinecraft2Task.java b/src/main/java/adris/altoclef/tasks/speedrun/BeatMinecraft2Task.java deleted file mode 100644 index b1b31b33..00000000 --- a/src/main/java/adris/altoclef/tasks/speedrun/BeatMinecraft2Task.java +++ /dev/null @@ -1,813 +0,0 @@ -package adris.altoclef.tasks.speedrun; - -import adris.altoclef.AltoClef; -import adris.altoclef.Debug; -import adris.altoclef.TaskCatalogue; -import adris.altoclef.tasks.DoToClosestBlockTask; -import adris.altoclef.tasks.InteractWithBlockTask; -import adris.altoclef.tasks.construction.DestroyBlockTask; -import adris.altoclef.tasks.container.DoStuffInContainerTask; -import adris.altoclef.tasks.container.LootContainerTask; -import adris.altoclef.tasks.container.SmeltInFurnaceTask; -import adris.altoclef.tasks.misc.EquipArmorTask; -import adris.altoclef.tasks.misc.LootDesertTempleTask; -import adris.altoclef.tasks.misc.PlaceBedAndSetSpawnTask; -import adris.altoclef.tasks.misc.SleepThroughNightTask; -import adris.altoclef.tasks.movement.*; -import adris.altoclef.tasks.resources.*; -import adris.altoclef.tasksystem.Task; -import adris.altoclef.util.Dimension; -import adris.altoclef.util.ItemTarget; -import adris.altoclef.util.MiningRequirement; -import adris.altoclef.util.SmeltTarget; -import adris.altoclef.util.helpers.ConfigHelper; -import adris.altoclef.util.helpers.ItemHelper; -import adris.altoclef.util.helpers.StorageHelper; -import adris.altoclef.util.helpers.WorldHelper; -import adris.altoclef.util.time.TimerGame; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.block.EndPortalFrameBlock; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.CreditsScreen; -import net.minecraft.entity.ItemEntity; -import net.minecraft.entity.mob.EndermanEntity; -import net.minecraft.entity.mob.SilverfishEntity; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtElement; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; -import net.minecraft.util.math.Vec3i; -import org.apache.commons.lang3.ArrayUtils; - -import java.util.*; -import java.util.function.Predicate; -import java.util.stream.Stream; - -@SuppressWarnings("ALL") -public class BeatMinecraft2Task extends Task { - - private static final Block[] TRACK_BLOCKS = new Block[]{ - Blocks.END_PORTAL_FRAME, - Blocks.END_PORTAL, - Blocks.CRAFTING_TABLE, // For pearl trading + gold crafting - Blocks.CHEST, // For ruined portals - Blocks.SPAWNER, // For silverfish, - Blocks.STONE_PRESSURE_PLATE // For desert temples - }; - private static final Item[] COLLECT_EYE_ARMOR = new Item[]{ - Items.DIAMOND_HELMET, Items.DIAMOND_CHESTPLATE, Items.DIAMOND_LEGGINGS, - Items.GOLDEN_BOOTS - }; - private static final Item[] COLLECT_EYE_ARMOR_END = ItemHelper.DIAMOND_ARMORS; - private static final ItemTarget[] COLLECT_EYE_GEAR = combine( - toItemTargets(Items.DIAMOND_SWORD), - toItemTargets(Items.DIAMOND_PICKAXE, 3), - toItemTargets(Items.CRAFTING_TABLE) - ); - private static final ItemTarget[] COLLECT_EYE_GEAR_MIN = combine( - toItemTargets(Items.DIAMOND_SWORD), - toItemTargets(Items.DIAMOND_PICKAXE, 1) - ); - private static final ItemTarget[] IRON_GEAR = combine( - toItemTargets(Items.IRON_SWORD), - toItemTargets(Items.IRON_PICKAXE, 2) - ); - private static final ItemTarget[] IRON_GEAR_MIN = combine( - toItemTargets(Items.IRON_SWORD) - ); - private static final int END_PORTAL_FRAME_COUNT = 12; - private static final double END_PORTAL_BED_SPAWN_RANGE = 8; - // We don't want curse of binding - private static final Predicate _noCurseOfBinding = stack -> { - boolean hasBinding = false; - for (NbtElement elm : stack.getEnchantments()) { - NbtCompound comp = (NbtCompound) elm; - if (comp.getString("id").equals("minecraft:binding_curse")) { - return false; - } - } - return true; - }; - private static BeatMinecraftConfig _config; - - static { - ConfigHelper.loadConfig("configs/beat_minecraft.json", BeatMinecraftConfig::new, BeatMinecraftConfig.class, newConfig -> _config = newConfig); - } - - private final HashMap _cachedEndItemDrops = new HashMap<>(); - // For some reason, after death there's a frame where the game thinks there are NO items in the end. - private final TimerGame _cachedEndItemNothingWaitTime = new TimerGame(2); - private final Task _buildMaterialsTask; - private final PlaceBedAndSetSpawnTask _setBedSpawnTask = new PlaceBedAndSetSpawnTask(); - private final GoToStrongholdPortalTask _locateStrongholdTask; - private final Task _goToNetherTask = new DefaultGoToDimensionTask(Dimension.NETHER); // To keep the portal build cache. - private final Task _getOneBedTask = TaskCatalogue.getItemTask("bed", 1); - private final Task _sleepThroughNightTask = new SleepThroughNightTask(); - private final Task _killDragonBedStratsTask = new KillEnderDragonWithBedsTask(new WaitForDragonAndPearlTask()); - // End specific dragon breath avoidance - private final DragonBreathTracker _dragonBreathTracker = new DragonBreathTracker(); - private BlockPos _endPortalCenterLocation; - private boolean _ranStrongholdLocator; - private boolean _endPortalOpened; - private BlockPos _bedSpawnLocation; - private List _notRuinedPortalChests = new ArrayList<>(); - private int _cachedFilledPortalFrames = 0; - // Controls whether we CAN walk on the end portal. - private boolean _enterindEndPortal = false; - private Task _foodTask; - private Task _gearTask; - private Task _lootTask; - private boolean _collectingEyes; - private boolean _escapingDragonsBreath; - - public BeatMinecraft2Task() { - _locateStrongholdTask = new GoToStrongholdPortalTask(_config.targetEyes); - _buildMaterialsTask = new GetBuildingMaterialsTask(_config.buildMaterialCount); - } - - public static BeatMinecraftConfig getConfig() { - return _config; - } - - private static List getFrameBlocks(BlockPos endPortalCenter) { - Vec3i[] frameOffsets = new Vec3i[]{ - new Vec3i(2, 0, 1), - new Vec3i(2, 0, 0), - new Vec3i(2, 0, -1), - new Vec3i(-2, 0, 1), - new Vec3i(-2, 0, 0), - new Vec3i(-2, 0, -1), - new Vec3i(1, 0, 2), - new Vec3i(0, 0, 2), - new Vec3i(-1, 0, 2), - new Vec3i(1, 0, -2), - new Vec3i(0, 0, -2), - new Vec3i(-1, 0, -2) - }; - return Arrays.stream(frameOffsets).map(endPortalCenter::add).toList(); - } - - private static boolean isEndPortalFrameFilled(AltoClef mod, BlockPos pos) { - if (!mod.getChunkTracker().isChunkLoaded(pos)) - return false; - BlockState state = mod.getWorld().getBlockState(pos); - if (state.getBlock() != Blocks.END_PORTAL_FRAME) { - Debug.logWarning("BLOCK POS " + pos + " DOES NOT CONTAIN END PORTAL FRAME! This is probably due to a bug/incorrect assumption."); - return false; - } - return state.get(EndPortalFrameBlock.EYE); - } - - // Just a helpful utility to reduce reuse recycle. - private static boolean shouldForce(AltoClef mod, Task task) { - return task != null && task.isActive() && !task.isFinished(mod); - } - - private static ItemTarget[] toItemTargets(Item... items) { - return Arrays.stream(items).map(item -> new ItemTarget(item, 1)).toArray(ItemTarget[]::new); - } - - private static ItemTarget[] toItemTargets(Item item, int count) { - return new ItemTarget[]{new ItemTarget(item, count)}; - } - - private static ItemTarget[] combine(ItemTarget[]... targets) { - List result = new ArrayList<>(); - for (ItemTarget[] ts : targets) { - result.addAll(Arrays.asList(ts)); - } - return result.toArray(ItemTarget[]::new); - } - - @Override - protected void onStart(AltoClef mod) { - - // Add a warning to make sure the user at least knows to change the settings. - String settingsWarningTail = "in \".minecraft/altoclef_settings.json\". @gamer may break if you don't add this! (sorry!)"; - if (!ArrayUtils.contains(mod.getModSettings().getThrowawayItems(mod), Items.END_STONE)) { - Debug.logWarning("\"end_stone\" is not part of your \"throwawayItems\" list " + settingsWarningTail); - } - if (!mod.getModSettings().shouldThrowawayUnusedItems()) { - Debug.logWarning("\"throwawayUnusedItems\" is not set to true " + settingsWarningTail); - } - - mod.getBlockTracker().trackBlock(TRACK_BLOCKS); - mod.getBlockTracker().trackBlock(ItemHelper.itemsToBlocks(ItemHelper.BED)); - mod.getBehaviour().push(); - mod.getBehaviour().addProtectedItems(Items.ENDER_EYE, Items.BLAZE_ROD, Items.ENDER_PEARL, Items.CRAFTING_TABLE); - mod.getBehaviour().addProtectedItems(ItemHelper.BED); - // Allow walking on end portal - mod.getBehaviour().allowWalkingOn(blockPos -> _enterindEndPortal && mod.getChunkTracker().isChunkLoaded(blockPos) && mod.getWorld().getBlockState(blockPos).getBlock() == Blocks.END_PORTAL); - - // Avoid dragon breath - mod.getBehaviour().avoidWalkingThrough(blockPos -> { - return WorldHelper.getCurrentDimension() == Dimension.END && !_escapingDragonsBreath && _dragonBreathTracker.isTouchingDragonBreath(blockPos); - }); - - // Don't break the bed we placed near the end portal - mod.getBehaviour().avoidBlockBreaking(blockPos -> { - if (_bedSpawnLocation != null) { - return blockPos.equals(WorldHelper.getBedHead(mod, _bedSpawnLocation)) || blockPos.equals(WorldHelper.getBedFoot(mod, _bedSpawnLocation)); - } - return false; - }); - } - - @Override - protected Task onTick(AltoClef mod) { - /* - if in the overworld: - if end portal found: - if end portal opened: - @make sure we have iron gear and enough beds to kill the dragon first, considering whether that gear was dropped in the end - @enter end portal - else if we have enough eyes of ender: - @fill in the end portal - else if we have enough eyes of ender: - @locate the end portal - else: - if we don't have diamond gear: - if we have no food: - @get a little bit of food - @get diamond gear - @go to the nether - if in the nether: - if we don't have enough blaze rods: - @kill blazes till we do - else if we don't have enough pearls: - @kill enderman till we do - else: - @leave the nether - if in the end: - if we have a bed: - @do bed strats - else: - @just hit the dragon normally - */ - - // By default, don't walk over end portals. - _enterindEndPortal = false; - - Predicate isCraftingTableTask = task -> { - if (task instanceof DoStuffInContainerTask cont) { - return cont.getContainerTarget().matches(Items.CRAFTING_TABLE); - } - return false; - }; - - // Portable crafting table. - // If we're NOT using our crafting table right now and there's one nearby, grab it. - if (!_endPortalOpened && WorldHelper.getCurrentDimension() != Dimension.END && _config.rePickupCraftingTable && !mod.getItemStorage().hasItem(Items.CRAFTING_TABLE) && !thisOrChildSatisfies(isCraftingTableTask) - && (mod.getBlockTracker().anyFound(blockPos -> WorldHelper.canBreak(mod, blockPos), Blocks.CRAFTING_TABLE) - || mod.getEntityTracker().itemDropped(Items.CRAFTING_TABLE))) { - setDebugState("Pick up crafting table while we're at it"); - return new MineAndCollectTask(Items.CRAFTING_TABLE, 1, new Block[]{Blocks.CRAFTING_TABLE}, MiningRequirement.HAND); - } - - // End stuff. - if (WorldHelper.getCurrentDimension() == Dimension.END) { - - // Dragons breath avoidance - _dragonBreathTracker.updateBreath(mod); - for (BlockPos playerIn : WorldHelper.getBlocksTouchingPlayer(mod)) { - if (_dragonBreathTracker.isTouchingDragonBreath(playerIn)) { - setDebugState("ESCAPE dragons breath"); - _escapingDragonsBreath = true; - return _dragonBreathTracker.getRunAwayTask(); - } - } - _escapingDragonsBreath = false; - - // If we find an ender portal, just GO to it!!! - if (mod.getBlockTracker().anyFound(Blocks.END_PORTAL)) { - setDebugState("WOOHOO"); - _enterindEndPortal = true; - return new DoToClosestBlockTask( - blockPos -> new GetToBlockTask(blockPos.up()), - Blocks.END_PORTAL - ); - } - - // If we have bed, do bed strats, otherwise punk normally. - updateCachedEndItems(mod); - // Grab beds - if (mod.getEntityTracker().itemDropped(ItemHelper.BED) && mod.getItemStorage().getItemCount(ItemHelper.BED) < _config.requiredBeds) - return new PickupDroppedItemTask(new ItemTarget(ItemHelper.BED), true); - // Grab tools - if (!mod.getItemStorage().hasItem(Items.IRON_PICKAXE, Items.DIAMOND_PICKAXE)) { - if (mod.getEntityTracker().itemDropped(Items.IRON_PICKAXE)) - return new PickupDroppedItemTask(Items.IRON_PICKAXE, 1); - if (mod.getEntityTracker().itemDropped(Items.DIAMOND_PICKAXE)) - return new PickupDroppedItemTask(Items.DIAMOND_PICKAXE, 1); - } - if (!mod.getItemStorage().hasItem(Items.WATER_BUCKET) && mod.getEntityTracker().itemDropped(Items.WATER_BUCKET)) - return new PickupDroppedItemTask(Items.WATER_BUCKET, 1); - // Grab armor - for (Item armorCheck : COLLECT_EYE_ARMOR_END) { - if (!StorageHelper.isArmorEquipped(mod, armorCheck)) { - if (mod.getItemStorage().hasItem(armorCheck)) { - return new EquipArmorTask(armorCheck); - } - if (mod.getEntityTracker().itemDropped(armorCheck)) { - return new PickupDroppedItemTask(armorCheck, 1); - } - } - } - if (mod.getItemStorage().hasItem(ItemHelper.BED) || (_killDragonBedStratsTask.isActive() && !_killDragonBedStratsTask.isFinished(mod))) { - setDebugState("Bed strats"); - return _killDragonBedStratsTask; - } - setDebugState("No beds, regular strats."); - return new KillEnderDragonTask(); - } else { - // We're not in the end so reset our "end cache" timer - _cachedEndItemNothingWaitTime.reset(); - } - - // Check for end portals. Always. - if (!endPortalOpened(mod, _endPortalCenterLocation) && WorldHelper.getCurrentDimension() == Dimension.OVERWORLD) { - Optional endPortal = mod.getBlockTracker().getNearestTracking(Blocks.END_PORTAL); - if (endPortal.isPresent()) { - _endPortalCenterLocation = endPortal.get(); - _endPortalOpened = true; - } else { - // TODO: Test that this works, for some reason the bot gets stuck near the stronghold and it keeps "Searching" for the portal - _endPortalCenterLocation = doSimpleSearchForEndPortal(mod); - } - } - - // Sleep through night. - if (_config.sleepThroughNight && !_endPortalOpened && WorldHelper.getCurrentDimension() == Dimension.OVERWORLD) { - if (WorldHelper.canSleep()) { - setDebugState("Sleeping through night"); - return _sleepThroughNightTask; - } - if (!mod.getItemStorage().hasItem(ItemHelper.BED)) { - if (mod.getBlockTracker().anyFound(blockPos -> WorldHelper.canBreak(mod, blockPos), ItemHelper.itemsToBlocks(ItemHelper.BED)) - || shouldForce(mod, _getOneBedTask)) { - setDebugState("Grabbing a bed we found to sleep through the night."); - return _getOneBedTask; - } - } - } - - // Do we need more eyes? - boolean noEyesPlease = (endPortalOpened(mod, _endPortalCenterLocation) || WorldHelper.getCurrentDimension() == Dimension.END); - int filledPortalFrames = getFilledPortalFrames(mod, _endPortalCenterLocation); - int eyesNeededMin = noEyesPlease ? 0 : _config.minimumEyes - filledPortalFrames; - int eyesNeeded = noEyesPlease ? 0 : _config.targetEyes - filledPortalFrames; - int eyes = mod.getItemStorage().getItemCount(Items.ENDER_EYE); - if (eyes < eyesNeededMin || (!_ranStrongholdLocator && _collectingEyes && eyes < eyesNeeded)) { - _collectingEyes = true; - return getEyesOfEnderTask(mod, eyesNeeded); - } else { - _collectingEyes = false; - } - - // We have eyes. Locate our portal + enter. - switch (WorldHelper.getCurrentDimension()) { - case OVERWORLD -> { - // If we found our end portal... - if (endPortalFound(mod, _endPortalCenterLocation)) { - - // Destroy silverfish spawner - if (StorageHelper.miningRequirementMetInventory(mod, MiningRequirement.WOOD)) { - Optional silverfish = mod.getBlockTracker().getNearestTracking(blockPos -> { - return WorldHelper.getSpawnerEntity(mod, blockPos) instanceof SilverfishEntity; - }, Blocks.SPAWNER); - if (silverfish.isPresent()) { - return new DestroyBlockTask(silverfish.get()); - } - } - - // Get remaining beds. - if (needsBeds(mod)) { - setDebugState("Collecting beds."); - return getBedTask(mod); - } - if (_config.placeSpawnNearEndPortal) { - if (!spawnSetNearPortal(mod, _endPortalCenterLocation)) { - setDebugState("Setting spawn near end portal"); - return setSpawnNearPortalTask(mod); - } - } - if (endPortalOpened(mod, _endPortalCenterLocation)) { - // Does our (current inventory) + (end dropped items inventory) satisfy (base requirements)? - // If not, obtain (base requirements) - (end dropped items). - setDebugState("Getting equipment for End"); - if (!hasItemOrDroppedInEnd(mod, Items.IRON_SWORD) && !hasItemOrDroppedInEnd(mod, Items.DIAMOND_SWORD)) { - return TaskCatalogue.getItemTask(Items.IRON_SWORD, 1); - } - if (!hasItemOrDroppedInEnd(mod, Items.WATER_BUCKET)) { - return TaskCatalogue.getItemTask(Items.WATER_BUCKET, 1); - } - if (!hasItemOrDroppedInEnd(mod, Items.IRON_PICKAXE) && !hasItemOrDroppedInEnd(mod, Items.DIAMOND_PICKAXE)) { - return TaskCatalogue.getItemTask(Items.DIAMOND_PICKAXE, 1); - } - if (needsBuildingMaterials(mod)) { - return _buildMaterialsTask; - } - - // We're as ready as we'll ever be, hop into the portal! - setDebugState("Entering End"); - _enterindEndPortal = true; - return new DoToClosestBlockTask( - blockPos -> new GetToBlockTask(blockPos.up()), - Blocks.END_PORTAL - ); - } else { - - // Open the portal! (we have enough eyes, do it) - setDebugState("Opening End Portal"); - return new DoToClosestBlockTask( - blockPos -> new InteractWithBlockTask(Items.ENDER_EYE, blockPos), - blockPos -> !isEndPortalFrameFilled(mod, blockPos), - Blocks.END_PORTAL_FRAME - ); - } - } else { - // Get beds before starting our portal location. - if (WorldHelper.getCurrentDimension() == Dimension.OVERWORLD && needsBeds(mod)) { - setDebugState("Getting beds before stronghold search."); - return getBedTask(mod); - } - // Portal Location - setDebugState("Locating End Portal..."); - _ranStrongholdLocator = true; - return _locateStrongholdTask; - } - } - case NETHER -> { - // Portal Location - setDebugState("Locating End Portal..."); - if (needsBuildingMaterials(mod)) { - return _buildMaterialsTask; - } - return _locateStrongholdTask; - } - } - - return null; - } - - private boolean needsBuildingMaterials(AltoClef mod) { - return StorageHelper.getBuildingMaterialCount(mod) < _config.minBuildMaterialCount || shouldForce(mod, _buildMaterialsTask); - } - - private void updateCachedEndItems(AltoClef mod) { - List droppedItems = mod.getEntityTracker().getDroppedItems(); - // If we have no items, it COULD be because we're dead. Wait a little. - if (droppedItems.isEmpty()) { - if (!_cachedEndItemNothingWaitTime.elapsed()) { - return; - } - } else { - _cachedEndItemNothingWaitTime.reset(); - } - _cachedEndItemDrops.clear(); - for (ItemEntity entity : droppedItems) { - Item item = entity.getStack().getItem(); - int count = entity.getStack().getCount(); - _cachedEndItemDrops.put(item, _cachedEndItemDrops.getOrDefault(item, 0) + count); - } - } - - private int getEndCachedCount(Item item) { - return _cachedEndItemDrops.getOrDefault(item, 0); - } - - private boolean droppedInEnd(Item item) { - return getEndCachedCount(item) > 0; - } - - private boolean hasItemOrDroppedInEnd(AltoClef mod, Item item) { - return mod.getItemStorage().hasItem(item) || droppedInEnd(item); - } - - private List lootableItems(AltoClef mod) { - List lootable = new ArrayList<>(); - lootable.add(Items.GOLDEN_APPLE); - lootable.add(Items.ENCHANTED_GOLDEN_APPLE); - lootable.add(Items.GLISTERING_MELON_SLICE); - lootable.add(Items.GOLDEN_CARROT); - lootable.add(Items.OBSIDIAN); - if (!StorageHelper.isArmorEquipped(mod, Items.GOLDEN_BOOTS) && !mod.getItemStorage().hasItemInventoryOnly(Items.GOLDEN_BOOTS)) { - lootable.add(Items.GOLDEN_BOOTS); - } - if ((mod.getItemStorage().getItemCountInventoryOnly(Items.GOLD_INGOT) < 4 && !StorageHelper.isArmorEquipped(mod, Items.GOLDEN_BOOTS) && !mod.getItemStorage().hasItemInventoryOnly(Items.GOLDEN_BOOTS)) || _config.barterPearlsInsteadOfEndermanHunt) { - lootable.add(Items.GOLD_INGOT); - } - if (!mod.getItemStorage().hasItemInventoryOnly(Items.FLINT_AND_STEEL)) { - lootable.add(Items.FLINT_AND_STEEL); - if (!mod.getItemStorage().hasItemInventoryOnly(Items.FIRE_CHARGE)) { - lootable.add(Items.FIRE_CHARGE); - } - } - if (!mod.getItemStorage().hasItemInventoryOnly(Items.BUCKET) && !mod.getItemStorage().hasItemInventoryOnly(Items.WATER_BUCKET)) { - lootable.add(Items.IRON_INGOT); - } - if (!StorageHelper.itemTargetsMetInventory(mod, COLLECT_EYE_GEAR_MIN)) { - lootable.add(Items.DIAMOND); - } - if (!mod.getItemStorage().hasItemInventoryOnly(Items.FLINT)) { - lootable.add(Items.FLINT); - } - return lootable; - } - - @Override - protected void onStop(AltoClef mod, Task interruptTask) { - mod.getBlockTracker().stopTracking(TRACK_BLOCKS); - mod.getBlockTracker().stopTracking(ItemHelper.itemsToBlocks(ItemHelper.BED)); - mod.getBehaviour().pop(); - } - - @Override - protected boolean isEqual(Task other) { - return other instanceof BeatMinecraft2Task; - } - - @Override - protected String toDebugString() { - return "Beating the Game."; - } - - private boolean endPortalFound(AltoClef mod, BlockPos endPortalCenter) { - if (endPortalCenter == null) { - return false; - } - if (endPortalOpened(mod, endPortalCenter)) { - return true; - } - return getFrameBlocks(endPortalCenter).stream().allMatch(frame -> mod.getBlockTracker().blockIsValid(frame, Blocks.END_PORTAL_FRAME)); - } - - private boolean endPortalOpened(AltoClef mod, BlockPos endPortalCenter) { - return _endPortalOpened && endPortalCenter != null && mod.getBlockTracker().blockIsValid(endPortalCenter, Blocks.END_PORTAL); - } - - private boolean spawnSetNearPortal(AltoClef mod, BlockPos endPortalCenter) { - return _bedSpawnLocation != null && mod.getBlockTracker().blockIsValid(_bedSpawnLocation, ItemHelper.itemsToBlocks(ItemHelper.BED)); - } - - private int getFilledPortalFrames(AltoClef mod, BlockPos endPortalCenter) { - // If we have our end portal, this doesn't matter. - if (endPortalFound(mod, endPortalCenter)) { - return END_PORTAL_FRAME_COUNT; - } - if (endPortalFound(mod, endPortalCenter)) { - List frameBlocks = getFrameBlocks(endPortalCenter); - // If EVERY portal frame is loaded, consider updating our cached filled portal count. - if (frameBlocks.stream().allMatch(blockPos -> mod.getChunkTracker().isChunkLoaded(blockPos))) { - _cachedFilledPortalFrames = frameBlocks.stream().reduce(0, (count, blockPos) -> - count + (isEndPortalFrameFilled(mod, blockPos) ? 1 : 0), - Integer::sum); - } - return _cachedFilledPortalFrames; - } - return 0; - } - - private boolean canBeLootablePortalChest(AltoClef mod, BlockPos blockPos) { - if (mod.getWorld().getBlockState(blockPos.up(1)).getBlock() == Blocks.WATER || blockPos.getY() < 50) { - return false; - } - for (BlockPos check : WorldHelper.scanRegion(mod, blockPos.add(-4, -2, -4), blockPos.add(4, 2, 4))) { - if (mod.getWorld().getBlockState(check).getBlock() == Blocks.NETHERRACK) { - return true; - } - } - _notRuinedPortalChests.add(blockPos); - return false; - } - - private Optional locateClosestUnopenedRuinedPortalChest(AltoClef mod) { - if (WorldHelper.getCurrentDimension() != Dimension.OVERWORLD) { - return Optional.empty(); - } - return mod.getBlockTracker().getNearestTracking(blockPos -> !_notRuinedPortalChests.contains(blockPos) && WorldHelper.isUnopenedChest(mod, blockPos) && mod.getPlayer().getBlockPos().isWithinDistance(blockPos, 150) && canBeLootablePortalChest(mod, blockPos), Blocks.CHEST); - } - - private Task getEyesOfEnderTask(AltoClef mod, int targetEyes) { - if (mod.getEntityTracker().itemDropped(Items.ENDER_EYE)) { - setDebugState("Picking up Dropped Eyes"); - return new PickupDroppedItemTask(Items.ENDER_EYE, targetEyes); - } - - int eyeCount = mod.getItemStorage().getItemCount(Items.ENDER_EYE); - - int blazePowderCount = mod.getItemStorage().getItemCount(Items.BLAZE_POWDER); - int blazeRodCount = mod.getItemStorage().getItemCount(Items.BLAZE_ROD); - int blazeRodTarget = (int) Math.ceil(((double) targetEyes - eyeCount - blazePowderCount) / 2.0); - int enderPearlTarget = targetEyes - eyeCount; - boolean needsBlazeRods = blazeRodCount < blazeRodTarget; - boolean needsBlazePowder = eyeCount + blazePowderCount < targetEyes; - boolean needsEnderPearls = mod.getItemStorage().getItemCount(Items.ENDER_PEARL) < enderPearlTarget; - - if (needsBlazePowder && !needsBlazeRods) { - // We have enough blaze rods. - setDebugState("Crafting blaze powder"); - return TaskCatalogue.getItemTask(Items.BLAZE_POWDER, targetEyes - eyeCount); - } - - if (!needsBlazePowder && !needsEnderPearls) { - // Craft ender eyes - setDebugState("Crafting Ender Eyes"); - return TaskCatalogue.getItemTask(Items.ENDER_EYE, targetEyes); - } - - // Get blaze rods + pearls... - switch (WorldHelper.getCurrentDimension()) { - case OVERWORLD -> { - // Make sure we have gear, then food. - for (Item diamond : COLLECT_EYE_ARMOR) { - if (mod.getItemStorage().hasItem(diamond) && !StorageHelper.isArmorEquipped(mod, diamond)) { - return new EquipArmorTask(COLLECT_EYE_ARMOR); - } - } - if (shouldForce(mod, _lootTask)) { - return _lootTask; - } - if (_config.searchRuinedPortals) { - // Check for ruined portals - Optional chest = locateClosestUnopenedRuinedPortalChest(mod); - if (chest.isPresent()) { - setDebugState("Looting ruined portal chest for goodies"); - _lootTask = new LootContainerTask(chest.get(), lootableItems(mod), _noCurseOfBinding); - return _lootTask; - } - } - if (_config.searchDesertTemples && StorageHelper.miningRequirementMetInventory(mod, MiningRequirement.WOOD)) { - // Check for desert temples - BlockPos temple = WorldHelper.getADesertTemple(mod); - if (temple != null) { - setDebugState("Looting desert temple for goodies"); - _lootTask = new LootDesertTempleTask(temple, lootableItems(mod)); - return _lootTask; - } - } - if (shouldForce(mod, _gearTask) && !StorageHelper.isArmorEquippedAll(mod, COLLECT_EYE_ARMOR)) { - setDebugState("Getting gear for Ender Eye journey"); - return _gearTask; - } - if (shouldForce(mod, _foodTask)) { - setDebugState("Getting Food for Ender Eye journey"); - return _foodTask; - } - // Smelt remaining raw food - if (_config.alwaysCookRawFood) { - for (Item raw : ItemHelper.RAW_FOODS) { - if (mod.getItemStorage().hasItem(raw)) { - Optional cooked = ItemHelper.getCookedFood(raw); - if (cooked.isPresent()) { - int targetCount = mod.getItemStorage().getItemCount(cooked.get()) + mod.getItemStorage().getItemCount(raw); - setDebugState("Smelting raw food: " + ItemHelper.stripItemName(raw)); - return new SmeltInFurnaceTask(new SmeltTarget(new ItemTarget(cooked.get(), targetCount), new ItemTarget(raw, targetCount))); - } - } - } - } - - boolean eyeGearSatisfied = StorageHelper.itemTargetsMet(mod, COLLECT_EYE_GEAR_MIN) && StorageHelper.isArmorEquippedAll(mod, COLLECT_EYE_ARMOR); - // Start with iron - if (!StorageHelper.itemTargetsMet(mod, IRON_GEAR_MIN) && !eyeGearSatisfied) { - _gearTask = TaskCatalogue.getSquashedItemTask(IRON_GEAR); - return _gearTask; - } - - // If we happen to find beds... - if (needsBeds(mod) && anyBedsFound(mod)) { - setDebugState("A bed was found, grabbing that first."); - return getBedTask(mod); - } - - // Then get food - if (StorageHelper.calculateInventoryFoodScore(mod) < _config.minFoodUnits) { - _foodTask = new CollectFoodTask(_config.foodUnits); - return _foodTask; - } - - // Then get diamond - if (!eyeGearSatisfied) { - _gearTask = TaskCatalogue.getSquashedItemTask(Stream.concat(Arrays.stream(COLLECT_EYE_ARMOR).filter(item -> !mod.getItemStorage().hasItem(item) && !StorageHelper.isArmorEquipped(mod, item)).map(item -> new ItemTarget(item, 1)), Arrays.stream(COLLECT_EYE_GEAR)).toArray(ItemTarget[]::new)); - return _gearTask; - } - // Then go to the nether. - setDebugState("Going to Nether"); - return _goToNetherTask; - } - case NETHER -> { - if (needsBlazeRods) { - setDebugState("Getting Blaze Rods"); - return getBlazeRodsTask(mod, blazeRodTarget); - } - setDebugState("Getting Ender Pearls"); - return getEnderPearlTask(mod, enderPearlTarget); - } - case END -> throw new UnsupportedOperationException("You're in the end. Don't collect eyes here."); - } - return null; - } - - private Task setSpawnNearPortalTask(AltoClef mod) { - if (_setBedSpawnTask.isSpawnSet()) { - _bedSpawnLocation = _setBedSpawnTask.getBedSleptPos(); - } else { - _bedSpawnLocation = null; - } - if (shouldForce(mod, _setBedSpawnTask)) { - // Set spawnpoint and set our bed spawn when it happens. - setDebugState("Setting spawnpoint now."); - return _setBedSpawnTask; - } - // Get close to portal. If we're close enough, set our bed spawn somewhere nearby. - if (WorldHelper.inRangeXZ(mod.getPlayer(), WorldHelper.toVec3d(_endPortalCenterLocation), END_PORTAL_BED_SPAWN_RANGE)) { - return _setBedSpawnTask; - } else { - setDebugState("Approaching portal (to set spawnpoint)"); - return new GetToXZTask(_endPortalCenterLocation.getX(), _endPortalCenterLocation.getZ()); - } - } - - private Task getBlazeRodsTask(AltoClef mod, int count) { - if (mod.getEntityTracker().itemDropped(Items.BLAZE_POWDER)) { - return new PickupDroppedItemTask(Items.BLAZE_POWDER, 1); - } - return new CollectBlazeRodsTask(count); - } - - private Task getEnderPearlTask(AltoClef mod, int count) { - if (_config.barterPearlsInsteadOfEndermanHunt) { - // Equip golden boots before trading... - if (!StorageHelper.isArmorEquipped(mod, Items.GOLDEN_BOOTS)) { - return new EquipArmorTask(Items.GOLDEN_BOOTS); - } - int goldBuffer = 32; - return new TradeWithPiglinsTask(32, Items.ENDER_PEARL, count); - } else { - if (mod.getEntityTracker().entityFound(EndermanEntity.class) || mod.getEntityTracker().itemDropped(Items.ENDER_PEARL)) { - return new KillAndLootTask(EndermanEntity.class, new ItemTarget(Items.ENDER_PEARL, count)); - } - // Search for warped forests this way... - return new SearchChunkForBlockTask(Blocks.WARPED_NYLIUM); - } - } - - private int getTargetBeds(AltoClef mod) { - boolean needsToSetSpawn = _config.placeSpawnNearEndPortal && - ( - !spawnSetNearPortal(mod, _endPortalCenterLocation) - && !shouldForce(mod, _setBedSpawnTask) - ); - int bedsInEnd = 0; - for (Item bed : ItemHelper.BED) { - bedsInEnd += _cachedEndItemDrops.getOrDefault(bed, 0); - } - - return _config.requiredBeds + (needsToSetSpawn ? 1 : 0) - bedsInEnd; - } - - private boolean needsBeds(AltoClef mod) { - int inEnd = 0; - for (Item item : ItemHelper.BED) { - inEnd += _cachedEndItemDrops.getOrDefault(item, 0); - } - return (mod.getItemStorage().getItemCount(ItemHelper.BED) + inEnd) < getTargetBeds(mod); - } - - private Task getBedTask(AltoClef mod) { - int targetBeds = getTargetBeds(mod); - // Collect beds. If we want to set our spawn, collect 1 more. - setDebugState("Collecting " + targetBeds + " beds"); - if (!mod.getItemStorage().hasItem(Items.SHEARS) && !anyBedsFound(mod)) { - return TaskCatalogue.getItemTask(Items.SHEARS, 1); - } - return TaskCatalogue.getItemTask("bed", targetBeds); - } - - private boolean anyBedsFound(AltoClef mod) { - return mod.getBlockTracker().anyFound(ItemHelper.itemsToBlocks(ItemHelper.BED)); - } - - private BlockPos doSimpleSearchForEndPortal(AltoClef mod) { - List frames = mod.getBlockTracker().getKnownLocations(Blocks.END_PORTAL_FRAME); - if (frames.size() >= END_PORTAL_FRAME_COUNT) { - // Get the center of the frames. - Vec3d average = frames.stream() - .reduce(Vec3d.ZERO, (accum, bpos) -> accum.add(bpos.getX() + 0.5, bpos.getY() + 0.5, bpos.getZ() + 0.5), Vec3d::add) - .multiply(1.0f / frames.size()); - return new BlockPos((int) average.x, (int) average.y, (int) average.z); - } - return null; - } - - @Override - public boolean isFinished(AltoClef mod) { - return MinecraftClient.getInstance().currentScreen instanceof CreditsScreen; - } -} \ No newline at end of file diff --git a/src/main/java/adris/altoclef/tasks/speedrun/BeatMinecraftConfig.java b/src/main/java/adris/altoclef/tasks/speedrun/BeatMinecraftConfig.java index 7729e0ff..f97b7a84 100644 --- a/src/main/java/adris/altoclef/tasks/speedrun/BeatMinecraftConfig.java +++ b/src/main/java/adris/altoclef/tasks/speedrun/BeatMinecraftConfig.java @@ -3,9 +3,9 @@ public class BeatMinecraftConfig { public int targetEyes = 14; // how many eyes of ender to collect public int minimumEyes = 12; // the MINIMUM amount of eyes of ender to have, assuming we don't have our stronghold portal opened yet - public boolean placeSpawnNearEndPortal = true; + public boolean placeSpawnNearEndPortal = false; public boolean barterPearlsInsteadOfEndermanHunt; - public boolean sleepThroughNight = true; + public boolean sleepThroughNight = false; public boolean rePickupCraftingTable = true; public boolean searchRuinedPortals = true; public boolean searchDesertTemples = true; @@ -18,7 +18,6 @@ public class BeatMinecraftConfig { public double dragonHeadCloseEnoughClickBedRange = 5.3; public boolean ironGearBeforeDiamondGear = true; public boolean getShield = true; - public boolean renderDistanceManipulation = true; public boolean rePickupSmoker = true; public boolean rePickupFurnace = true; } diff --git a/src/main/java/adris/altoclef/tasks/speedrun/KillEnderDragonTask.java b/src/main/java/adris/altoclef/tasks/speedrun/KillEnderDragonTask.java index 0f4c6459..fd430400 100644 --- a/src/main/java/adris/altoclef/tasks/speedrun/KillEnderDragonTask.java +++ b/src/main/java/adris/altoclef/tasks/speedrun/KillEnderDragonTask.java @@ -68,7 +68,6 @@ private static Task getPickupTaskIfAny(AltoClef mod, Item... itemsToPickup) { @Override protected void onStart(AltoClef mod) { mod.getBehaviour().push(); - mod.getBlockTracker().trackBlock(Blocks.END_PORTAL); // Don't forcefield endermen. mod.getBehaviour().addForceFieldExclusion(entity -> entity instanceof EndermanEntity || entity instanceof EnderDragonEntity || entity instanceof EnderDragonPart); mod.getBehaviour().setPreferredStairs(true); @@ -120,7 +119,7 @@ protected Task onTick(AltoClef mod) { } // If there is a portal, enter it. - if (mod.getBlockTracker().anyFound(Blocks.END_PORTAL)) { + if (mod.getBlockScanner().anyFound(Blocks.END_PORTAL)) { setDebugState("Entering portal to beat the game."); return new DoToClosestBlockTask( blockPos -> new GetToBlockTask(blockPos.up(), false), @@ -170,7 +169,6 @@ protected Task onTick(AltoClef mod) { @Override protected void onStop(AltoClef mod, Task interruptTask) { mod.getBehaviour().pop(); - mod.getBlockTracker().stopTracking(Blocks.END_PORTAL); } @Override diff --git a/src/main/java/adris/altoclef/tasks/speedrun/KillEnderDragonWithBedsTask.java b/src/main/java/adris/altoclef/tasks/speedrun/KillEnderDragonWithBedsTask.java index 2c4dbf9b..66222373 100644 --- a/src/main/java/adris/altoclef/tasks/speedrun/KillEnderDragonWithBedsTask.java +++ b/src/main/java/adris/altoclef/tasks/speedrun/KillEnderDragonWithBedsTask.java @@ -2,37 +2,47 @@ import adris.altoclef.AltoClef; import adris.altoclef.Debug; -import adris.altoclef.tasks.InteractWithBlockTask; +import adris.altoclef.tasks.construction.DestroyBlockTask; +import adris.altoclef.tasks.construction.PlaceBlockTask; import adris.altoclef.tasks.movement.GetToBlockTask; import adris.altoclef.tasks.movement.GetToXZTask; import adris.altoclef.tasksystem.Task; import adris.altoclef.util.helpers.ItemHelper; import adris.altoclef.util.helpers.LookHelper; import adris.altoclef.util.helpers.WorldHelper; +import adris.altoclef.util.time.TimerGame; import baritone.api.utils.input.Input; +import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.entity.boss.dragon.EnderDragonEntity; +import net.minecraft.entity.boss.dragon.EnderDragonPart; import net.minecraft.entity.boss.dragon.phase.Phase; import net.minecraft.entity.boss.dragon.phase.PhaseType; +import net.minecraft.item.Items; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; +import java.util.Arrays; import java.util.List; public class KillEnderDragonWithBedsTask extends Task { - private final Task _whenNotPerchingTask; - - private BlockPos _endPortalTop; - private Task _positionTask; - - private boolean _isDragonDead = false; + private final Task whenNotPerchingTask; + TimerGame placeBedTimer = new TimerGame(0.6); + TimerGame waiTimer = new TimerGame(0.3); + TimerGame waitBeforePlaceTimer = new TimerGame(0.5); + boolean waited = false; + double prevDist = 100; + private BlockPos endPortalTop; + private Task freePortalTopTask = null; + private Task placeObsidianTask = null; + private boolean dragonDead = false; public KillEnderDragonWithBedsTask(IDragonWaiter notPerchingOverride) { - _whenNotPerchingTask = (Task) notPerchingOverride; + whenNotPerchingTask = (Task) notPerchingOverride; } - private static BlockPos locateExitPortalTop(AltoClef mod) { + public static BlockPos locateExitPortalTop(AltoClef mod) { if (!mod.getChunkTracker().isChunkLoaded(new BlockPos(0, 64, 0))) return null; int height = WorldHelper.getGroundHeight(mod, 0, 0, Blocks.BEDROCK); if (height != -1) return new BlockPos(0, height, 0); @@ -41,7 +51,8 @@ private static BlockPos locateExitPortalTop(AltoClef mod) { @Override protected void onStart(AltoClef mod) { - + // do not block our view + mod.getBehaviour().avoidBlockPlacing((pos)->Math.abs(pos.getX())+Math.abs(pos.getZ()) <= 3 && (pos.getX() != 0 && pos.getZ() != 0)); } @Override @@ -59,29 +70,51 @@ Get in position (XZ) Else: // Perform "Default Wander" mode and avoid dragon breath. */ - if (_endPortalTop == null) { - _endPortalTop = locateExitPortalTop(mod); - if (_endPortalTop != null) { - ((IDragonWaiter) _whenNotPerchingTask).setExitPortalTop(_endPortalTop); + if (endPortalTop == null) { + endPortalTop = locateExitPortalTop(mod); + if (endPortalTop != null) { + ((IDragonWaiter) whenNotPerchingTask).setExitPortalTop(endPortalTop); } } - if (_endPortalTop == null) { + if (endPortalTop == null) { setDebugState("Searching for end portal top."); return new GetToXZTask(0, 0); } - if (_isDragonDead) { + BlockPos obsidianTarget = endPortalTop.up().offset(Direction.NORTH); + if (!mod.getWorld().getBlockState(obsidianTarget).getBlock().equals(Blocks.OBSIDIAN)) { + if (WorldHelper.inRangeXZ(mod.getPlayer().getPos(), new Vec3d(0, 0, 0), 10)) { + if (placeObsidianTask == null) { + placeObsidianTask = new PlaceBlockTask(obsidianTarget, Blocks.OBSIDIAN); + } + return placeObsidianTask; + } else { + return new GetToXZTask(0, 0); + } + } + BlockState stateAtPortal = mod.getWorld().getBlockState(endPortalTop.up()); + if (!stateAtPortal.isAir() && !stateAtPortal.getBlock().equals(Blocks.FIRE) && + !Arrays.stream(ItemHelper.itemsToBlocks(ItemHelper.BED)).toList().contains(stateAtPortal.getBlock())) { + + if (freePortalTopTask == null) { + freePortalTopTask = new DestroyBlockTask(endPortalTop.up()); + } + return freePortalTopTask; + } + + + if (dragonDead) { setDebugState("Waiting for overworld portal to spawn."); - return null; + return new GetToBlockTask(endPortalTop.down(4).west()); } - if (!mod.getEntityTracker().entityFound(EnderDragonEntity.class) || _isDragonDead) { + if (!mod.getEntityTracker().entityFound(EnderDragonEntity.class) || dragonDead) { setDebugState("No dragon found."); - if (!WorldHelper.inRangeXZ(mod.getPlayer(), _endPortalTop, 1)) { - setDebugState("Going to end portal top at" + _endPortalTop.toString() + "."); - return new GetToBlockTask(_endPortalTop); + if (!WorldHelper.inRangeXZ(mod.getPlayer(), endPortalTop, 1)) { + setDebugState("Going to end portal top at" + endPortalTop.toString() + "."); + return new GetToBlockTask(endPortalTop); } } List dragons = mod.getEntityTracker().getTrackedEntities(EnderDragonEntity.class); @@ -94,90 +127,121 @@ Get in position (XZ) if (mod.getPlayer().getPitch() != -90) { mod.getPlayer().setPitch(-90); } - _isDragonDead = true; + dragonDead = true; return null; } boolean perching = dragonPhase.getType() == PhaseType.LANDING || dragonPhase.isSittingOrHovering() || dragonPhase.getType() == PhaseType.LANDING_APPROACH; - if (dragon.getY() < _endPortalTop.getY() + 2) { + if (dragon.getY() < endPortalTop.getY() + 2) { // Dragon is already perched. perching = false; } - ((IDragonWaiter) _whenNotPerchingTask).setPerchState(perching); + ((IDragonWaiter) whenNotPerchingTask).setPerchState(perching); // When the dragon is not perching... - if (_whenNotPerchingTask.isActive() && !_whenNotPerchingTask.isFinished(mod)) { + if (whenNotPerchingTask.isActive() && !whenNotPerchingTask.isFinished(mod)) { setDebugState("Dragon not perching, performing special behavior..."); - return _whenNotPerchingTask; + return whenNotPerchingTask; } if (perching) { - mod.getFoodChain().shouldStop(true); - BlockPos targetStandPosition = _endPortalTop.add(-1, -1, 0); - BlockPos playerPosition = mod.getPlayer().getBlockPos(); - // If we're not positioned (above is OK), go there and make sure we're at the right height. - if (_positionTask != null && _positionTask.isActive() && !_positionTask.isFinished(mod)) { - setDebugState("Going to position for bed cycle..."); - return _positionTask; - } - if ((!WorldHelper.inRangeXZ(WorldHelper.toVec3d(targetStandPosition), mod.getPlayer().getPos(), 0.75)) -// && mod.getPlayer().getVelocity().getX() == 0 && mod.getPlayer().getVelocity().getY() == 0 && mod.getPlayer().getVelocity().getZ() == 0 - ) { - _positionTask = new GetToBlockTask(targetStandPosition); - Debug.logMessage("Going to position for bed cycle..."); - setDebugState("Moving to target stand position"); - return _positionTask; - } - // We're positioned. Perform bed strats! - BlockPos bedTargetPosition = _endPortalTop.up(); - boolean bedPlaced = mod.getBlockTracker().blockIsValid(bedTargetPosition, ItemHelper.itemsToBlocks(ItemHelper.BED)); - if (!bedPlaced) { - setDebugState("Placing bed"); - // If no bed, place bed. - // Fire messes up our "reach" so we just assume we're good when we're above a height. - boolean canPlace = LookHelper.getCameraPos(mod).y > bedTargetPosition.getY(); - //Optional placeReach = LookHelper.getReach(bedTargetPosition.down(), Direction.UP); - if (canPlace) { - // Look at and place! - if (mod.getSlotHandler().forceEquipItem(ItemHelper.BED, true)) { - LookHelper.lookAt(mod, bedTargetPosition.down(), Direction.UP, true); - //mod.getClientBaritone().getLookBehavior().updateTarget(placeReach.get(), true); - //if (mod.getClientBaritone().getPlayerContext().isLookingAt(bedTargetPosition.down())) { - // There could be fire so eh place right away - mod.getInputControls().tryPress(Input.CLICK_RIGHT); - //} - } - } else { - if (mod.getPlayer().isOnGround()) { - // Jump - mod.getInputControls().tryPress(Input.JUMP); - } - } - } else { - setDebugState("Wait for it..."); - // Make sure we're standing on the ground so we don't blow ourselves up lmfao - if (!mod.getPlayer().isOnGround()) { - // Wait to fall - return null; - } - // Wait for dragon head to be close enough to the bed's head... - BlockPos bedfoot = WorldHelper.getBedFoot(mod, bedTargetPosition); - assert bedfoot != null; - Vec3d headPos = dragon.head.getBoundingBox().getCenter(); // dragon.head.getPos(); - double dist = headPos.distanceTo(WorldHelper.toVec3d(bedfoot)); - Debug.logMessage("Dist: " + dist + " Health: " + dragon.getHealth()); - - if (dist < BeatMinecraft2Task.getConfig().dragonHeadCloseEnoughClickBedRange) { - // Interact with the bed. - return new InteractWithBlockTask(bedTargetPosition); - } - // Wait for it... - } - return null; + return performOneCycle(mod, dragon); } } } mod.getFoodChain().shouldStop(false); // Start our "Not perching task" - return _whenNotPerchingTask; + return whenNotPerchingTask; + } + + private Task performOneCycle(AltoClef mod, EnderDragonEntity dragon) { + mod.getFoodChain().shouldStop(true); + if (mod.getInputControls().isHeldDown(Input.SNEAK)) { + mod.getInputControls().release(Input.SNEAK); + } + // do not let shield fuck up our moment :3 + mod.getSlotHandler().forceEquipItemToOffhand(Items.AIR); + + BlockPos endPortalTop = KillEnderDragonWithBedsTask.locateExitPortalTop(mod).up(); + BlockPos obsidian = null; + Direction dir = null; + + for (Direction direction : new Direction[]{Direction.EAST, Direction.WEST, Direction.NORTH, Direction.SOUTH}) { + if (mod.getWorld().getBlockState(endPortalTop.offset(direction)).getBlock().equals(Blocks.OBSIDIAN)) { + obsidian = endPortalTop.offset(direction); + dir = direction.getOpposite(); + break; + } + } + + if (dir == null) { + mod.log("no obisidan? :("); + return null; + } + + Direction offsetDir = dir.getAxis() == Direction.Axis.X ? Direction.SOUTH : Direction.WEST; + BlockPos targetBlock = endPortalTop.down(3).offset(offsetDir, 3).offset(dir); + + double d = distanceIgnoreY(WorldHelper.toVec3d(targetBlock), mod.getPlayer().getPos()); + if (d > 0.7 || mod.getPlayer().getBlockPos().down().getY() > endPortalTop.getY()-4) { + mod.log(d + ""); + return new GetToBlockTask(targetBlock); + } else if (!waited) { + waited = true; + waitBeforePlaceTimer.reset(); + } + if (!waitBeforePlaceTimer.elapsed()) { + mod.log(waitBeforePlaceTimer.getDuration() + " waiting..."); + return null; + } + + LookHelper.lookAt(mod, obsidian, dir); + + BlockPos bedHead = WorldHelper.getBedHead(mod, endPortalTop); + mod.getSlotHandler().forceEquipItem(ItemHelper.BED); + + if (bedHead == null) { + if (placeBedTimer.elapsed() && Math.abs(dragon.getY() - endPortalTop.getY()) < 10) { + mod.getInputControls().tryPress(Input.CLICK_RIGHT); + waiTimer.reset(); + } + return null; + } + if (!waiTimer.elapsed()) { + return null; + } + + // most of these numbers were arbitrarily added through some testing, its possible not all of these cases need to be tested + // it seems to work fairly well tho, so I would rather not touch it :p + Vec3d dragonHeadPos = dragon.head.getBoundingBox().getCenter(); + Vec3d bedHeadPos = WorldHelper.toVec3d(bedHead); + + double dist = dragonHeadPos.distanceTo(bedHeadPos); + double distXZ = distanceIgnoreY(dragonHeadPos, bedHeadPos); + + EnderDragonPart body = dragon.getBodyParts()[2]; + + double destroyDistance = Math.abs(body.getBoundingBox().getMin(Direction.Axis.Y) - bedHeadPos.getY()); + boolean tooClose = destroyDistance < 1.1; + boolean skip = destroyDistance > 3 && dist > 4.5 && distXZ > 2.5; + + mod.log(destroyDistance + " : " + dist + " : " + distXZ); + + if ((dist < 1.5 || (prevDist < distXZ && destroyDistance < 4 && prevDist < 2.9)) || (destroyDistance < 2 && dist < 4) + || (destroyDistance < 1.7 && dist < 4.5) || tooClose || (destroyDistance < 2.4 && distXZ < 3.7) || (destroyDistance < 3.5 && distXZ < 2.4)) { + + if (!skip) { + mod.getInputControls().tryPress(Input.CLICK_RIGHT); + placeBedTimer.reset(); + } + } + + prevDist = distXZ; + return null; + } + + public double distanceIgnoreY(Vec3d vec, Vec3d vec1) { + double d = vec.x - vec1.x; + double f = vec.z - vec1.z; + return Math.sqrt(d * d + f * f); } @Override diff --git a/src/main/java/adris/altoclef/tasks/speedrun/MarvionBeatMinecraftTask.java b/src/main/java/adris/altoclef/tasks/speedrun/MarvionBeatMinecraftTask.java deleted file mode 100644 index 12a28a1e..00000000 --- a/src/main/java/adris/altoclef/tasks/speedrun/MarvionBeatMinecraftTask.java +++ /dev/null @@ -1,2392 +0,0 @@ -package adris.altoclef.tasks.speedrun; - -import adris.altoclef.AltoClef; -import adris.altoclef.Debug; -import adris.altoclef.TaskCatalogue; -import adris.altoclef.tasks.DoToClosestBlockTask; -import adris.altoclef.tasks.InteractWithBlockTask; -import adris.altoclef.tasks.construction.DestroyBlockTask; -import adris.altoclef.tasks.container.DoStuffInContainerTask; -import adris.altoclef.tasks.container.LootContainerTask; -import adris.altoclef.tasks.container.SmeltInSmokerTask; -import adris.altoclef.tasks.misc.EquipArmorTask; -import adris.altoclef.tasks.misc.LootDesertTempleTask; -import adris.altoclef.tasks.misc.PlaceBedAndSetSpawnTask; -import adris.altoclef.tasks.misc.SleepThroughNightTask; -import adris.altoclef.tasks.movement.*; -import adris.altoclef.tasks.resources.*; -import adris.altoclef.tasksystem.Task; -import adris.altoclef.trackers.BlockTracker; -import adris.altoclef.trackers.EntityTracker; -import adris.altoclef.util.Dimension; -import adris.altoclef.util.ItemTarget; -import adris.altoclef.util.MiningRequirement; -import adris.altoclef.util.SmeltTarget; -import adris.altoclef.util.helpers.*; -import adris.altoclef.util.slots.Slot; -import adris.altoclef.util.time.TimerGame; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.block.EndPortalFrameBlock; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.CreditsScreen; -import net.minecraft.entity.Entity; -import net.minecraft.entity.ItemEntity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.mob.*; -import net.minecraft.entity.passive.PigEntity; -import net.minecraft.item.*; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtElement; -import net.minecraft.screen.slot.SlotActionType; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3i; -import net.minecraft.world.biome.BiomeKeys; -import org.apache.commons.lang3.ArrayUtils; - -import java.util.*; -import java.util.function.Predicate; -import java.util.stream.Stream; - -import static net.minecraft.client.MinecraftClient.getInstance; - -@SuppressWarnings("ALL") -public class MarvionBeatMinecraftTask extends Task { - private static final Block[] TRACK_BLOCKS = new Block[]{ - Blocks.BLAST_FURNACE, - Blocks.FURNACE, - Blocks.SMOKER, - Blocks.END_PORTAL_FRAME, - Blocks.END_PORTAL, - Blocks.CRAFTING_TABLE, // For pearl trading + gold crafting - Blocks.CHEST, // For ruined portals - Blocks.SPAWNER, // For silverfish, - Blocks.STONE_PRESSURE_PLATE // For desert temples - }; - private static final Item[] COLLECT_EYE_ARMOR = new Item[]{ - Items.GOLDEN_HELMET, Items.DIAMOND_CHESTPLATE, Items.DIAMOND_LEGGINGS, - Items.DIAMOND_BOOTS - }; - private static final ItemTarget[] COLLECT_STONE_GEAR = combine( - toItemTargets(Items.STONE_SWORD, 1), - toItemTargets(Items.STONE_PICKAXE, 2), - toItemTargets(Items.STONE_HOE), - toItemTargets(Items.COAL, 13) - ); - private static final Item COLLECT_SHIELD = Items.SHIELD; - private static final Item[] COLLECT_IRON_ARMOR = ItemHelper.IRON_ARMORS; - private static final Item[] COLLECT_EYE_ARMOR_END = ItemHelper.DIAMOND_ARMORS; - private static final ItemTarget[] COLLECT_IRON_GEAR = combine( - toItemTargets(Items.IRON_SWORD, 2), - toItemTargets(Items.STONE_SHOVEL), - toItemTargets(Items.STONE_AXE), - toItemTargets(Items.DIAMOND_PICKAXE) - ); - private static final ItemTarget[] COLLECT_EYE_GEAR = combine( - toItemTargets(Items.DIAMOND_SWORD), - toItemTargets(Items.DIAMOND_PICKAXE, 3), - toItemTargets(Items.BUCKET, 2), - toItemTargets(Items.CRAFTING_TABLE) - ); - private static final ItemTarget[] COLLECT_IRON_GEAR_MIN = combine( - toItemTargets(Items.IRON_SWORD), - toItemTargets(Items.DIAMOND_PICKAXE) - ); - private static final ItemTarget[] COLLECT_EYE_GEAR_MIN = combine( - toItemTargets(Items.DIAMOND_SWORD), - toItemTargets(Items.DIAMOND_PICKAXE) - ); - private static final ItemTarget[] IRON_GEAR = combine( - toItemTargets(Items.IRON_SWORD, 2), - toItemTargets(Items.STONE_SHOVEL), - toItemTargets(Items.STONE_AXE), - toItemTargets(Items.DIAMOND_PICKAXE), - toItemTargets(Items.SHIELD) - ); - private static final ItemTarget[] IRON_GEAR_MIN = combine( - toItemTargets(Items.IRON_SWORD, 2), - toItemTargets(Items.DIAMOND_PICKAXE), - toItemTargets(Items.SHIELD) - ); - private static final int END_PORTAL_FRAME_COUNT = 12; - private static final double END_PORTAL_BED_SPAWN_RANGE = 8; - - private static final int TWISTING_VINES_COUNT = 28; - private static final int TWISTING_VINES_COUNT_MIN = 14; - // We don't want curse of binding - private static final Predicate _noCurseOfBinding = stack -> { - for (NbtElement elm : stack.getEnchantments()) { - NbtCompound comp = (NbtCompound) elm; - if (comp.getString("id").equals("minecraft:binding_curse")) { - return false; - } - } - return true; - }; - private static BeatMinecraftConfig _config; - private static GoToStrongholdPortalTask _locateStrongholdTask; - private static boolean openingEndPortal = false; - - static { - ConfigHelper.loadConfig("configs/beat_minecraft.json", BeatMinecraftConfig::new, BeatMinecraftConfig.class, newConfig -> _config = newConfig); - } - - private final HashMap _cachedEndItemDrops = new HashMap<>(); - // For some reason, after death there's a frame where the game thinks there are NO items in the end. - private final TimerGame _cachedEndItemNothingWaitTime = new TimerGame(10); - private final Task _buildMaterialsTask; - private final PlaceBedAndSetSpawnTask _setBedSpawnTask = new PlaceBedAndSetSpawnTask(); - private final Task _goToNetherTask = new DefaultGoToDimensionTask(Dimension.NETHER); // To keep the portal build cache. - private final Task _getOneBedTask = TaskCatalogue.getItemTask("bed", 1); - private final Task _sleepThroughNightTask = new SleepThroughNightTask(); - private final Task _killDragonBedStratsTask = new KillEnderDragonWithBedsTask(new WaitForDragonAndPearlTask()); - // End specific dragon breath avoidance - private final DragonBreathTracker _dragonBreathTracker = new DragonBreathTracker(); - private final TimerGame _timer1 = new TimerGame(5); - private final TimerGame _timer2 = new TimerGame(35); - private final TimerGame _timer3 = new TimerGame(60); - boolean _weHaveEyes; - private boolean _dragonIsDead = false; - private BlockPos _endPortalCenterLocation; - private boolean _isEquippingDiamondArmor; - private boolean _ranStrongholdLocator; - private boolean _endPortalOpened; - private BlockPos _bedSpawnLocation; - private List _notRuinedPortalChests = new ArrayList<>(); - private int _cachedFilledPortalFrames = 0; - // Controls whether we CAN walk on the end portal. - private boolean _enterindEndPortal = false; - private Task _foodTask; - private Task _gearTask; - private Task _lootTask; - private boolean _collectingEyes; - private boolean _escapingDragonsBreath = false; - private boolean isGettingBlazeRods = false; - private boolean isGettingEnderPearls = false; - private Task searchBiomeTask; - private Task _getPorkchopTask; - private Task _stoneGearTask; - private Task _logsTask; - private Task _starterGearTask; - private Task _ironGearTask; - private Task _shieldTask; - private Task _smeltTask; - private Task getBedTask; - private Task getTwistingVines; - - public MarvionBeatMinecraftTask() { - _locateStrongholdTask = new GoToStrongholdPortalTask(_config.targetEyes); - _buildMaterialsTask = new GetBuildingMaterialsTask(_config.buildMaterialCount); - } - - /** - * Returns the BeatMinecraftConfig instance. - * If it is not already initialized, it initializes and returns a new instance. - * - * @return the BeatMinecraftConfig instance - */ - public static BeatMinecraftConfig getConfig() { - if (_config == null) { - Debug.logInternal("Initializing BeatMinecraftConfig"); - _config = new BeatMinecraftConfig(); - } - return _config; - } - - /** - * Retrieves the frame blocks surrounding the end portal center. - * - * @param endPortalCenter the center position of the end portal - * @return a list of block positions representing the frame blocks - */ - private static List getFrameBlocks(BlockPos endPortalCenter) { - // Create a list to store the frame blocks - List frameBlocks = new ArrayList<>(); - - // Check if the end portal center is not null - if (endPortalCenter != null) { - // Define the offsets for the frame blocks - int[][] frameOffsets = { - {2, 0, 1}, - {2, 0, 0}, - {2, 0, -1}, - {-2, 0, 1}, - {-2, 0, 0}, - {-2, 0, -1}, - {1, 0, 2}, - {0, 0, 2}, - {-1, 0, 2}, - {1, 0, -2}, - {0, 0, -2}, - {-1, 0, -2} - }; - - // Iterate over each offset - for (int[] offset : frameOffsets) { - // Calculate the frame block position by adding the offset to the end portal center - BlockPos frameBlock = endPortalCenter.add(offset[0], offset[1], offset[2]); - - // Add the frame block to the list - frameBlocks.add(frameBlock); - } - } - - // Log the frame blocks for debugging - Debug.logInternal("Frame blocks: " + frameBlocks); - - // Return the list of frame blocks - return frameBlocks; - } - - /** - * Converts an array of `Item` objects into an array of `ItemTarget` objects. - * - * @param items the array of `Item` objects to convert - * @return the array of `ItemTarget` objects - */ - private static ItemTarget[] toItemTargets(Item... items) { - // Use the `Arrays.stream()` method to create a stream of `Item` objects - return Arrays.stream(items) - // Use the `map()` method to convert each `Item` object into an `ItemTarget` object - .map(item -> { - // Add logging statement to print the item being converted - Debug.logInternal("Converting item: " + item); - return new ItemTarget(item); - }) - // Use the `toArray()` method to convert the stream of `ItemTarget` objects into an array - .toArray(ItemTarget[]::new); - } - - /** - * Convert an item and count into an array of ItemTargets. - * - * @param item The item to be converted. - * @param count The count of the item. - * @return An array of ItemTargets containing the item and count. - */ - private static ItemTarget[] toItemTargets(Item item, int count) { - // Add a logging statement to indicate the start of the method. - Debug.logInternal("Converting item to ItemTargets..."); - - // Create a new array of ItemTargets with a length of 1. - ItemTarget[] itemTargets = new ItemTarget[1]; - - // Create a new ItemTarget with the given item and count. - itemTargets[0] = new ItemTarget(item, count); - - // Add a logging statement to indicate the completion of the method. - Debug.logInternal("Conversion to ItemTargets complete."); - - // Return the array of ItemTargets. - return itemTargets; - } - - /** - * Combines multiple arrays of ItemTarget objects into a single array. - * - * @param targets The arrays of ItemTarget objects to combine. - * @return The combined array of ItemTarget objects. - */ - private static ItemTarget[] combine(ItemTarget[]... targets) { - List combinedTargets = new ArrayList<>(); - - // Iterate over each array of ItemTarget objects - for (ItemTarget[] targetArray : targets) { - // Add all elements of the array to the combinedTargets list - combinedTargets.addAll(Arrays.asList(targetArray)); - } - - // Log the combinedTargets list - Debug.logInternal("Combined Targets: " + combinedTargets); - - // Convert the combinedTargets list to an array and log it - ItemTarget[] combinedArray = combinedTargets.toArray(new ItemTarget[combinedTargets.size()]); - Debug.logInternal("Combined Array: " + Arrays.toString(combinedArray)); - - // Return the combined array - return combinedArray; - } - - /** - * Checks if the End Portal Frame at the given position is filled with an Eye of Ender. - * - * @param mod The AltoClef mod instance. - * @param pos The position of the End Portal Frame. - * @return True if the End Portal Frame is filled, false otherwise. - */ - private static boolean isEndPortalFrameFilled(AltoClef mod, BlockPos pos) { - // Check if the chunk is loaded - if (!mod.getChunkTracker().isChunkLoaded(pos)) { - Debug.logInternal("Chunk is not loaded"); - return false; - } - - // Check the block state at the given position - BlockState blockState = mod.getWorld().getBlockState(pos); - if (blockState.getBlock() != Blocks.END_PORTAL_FRAME) { - Debug.logInternal("Block is not an End Portal Frame"); - return false; - } - - // Check if the End Portal Frame is filled - boolean isFilled = blockState.get(EndPortalFrameBlock.EYE); - Debug.logInternal("End Portal Frame is " + (isFilled ? "filled" : "not filled")); - return isFilled; - } - - /** - * Checks if a task should be forced. - * - * @param mod The AltoClef mod. - * @param task The task to check. - * @return True if the task should be forced, false otherwise. - */ - private static boolean shouldForce(AltoClef mod, Task task) { - // Check if the task is not null - boolean isTaskNotNull = task != null; - - // Check if the task is active - boolean isTaskActive = isTaskNotNull && task.isActive(); - - // Check if the task is not finished - boolean isTaskNotFinished = isTaskNotNull && !task.isFinished(mod); - - // Print task status for debugging purposes - if (isTaskNotNull) { - Debug.logInternal("Task is not null"); - } else { - Debug.logInternal("Task is null"); - } - - if (isTaskActive) { - Debug.logInternal("Task is active"); - } else { - Debug.logInternal("Task is not active"); - } - - if (isTaskNotFinished) { - Debug.logInternal("Task is not finished"); - } else { - Debug.logInternal("Task is finished"); - } - - return isTaskNotNull && isTaskActive && isTaskNotFinished; - } - - /** - * Checks if the task is finished. - * - * @param mod The instance of the AltoClef mod. - * @return True if the task is finished, false otherwise. - */ - @Override - public boolean isFinished(AltoClef mod) { - // Check if the current screen is the CreditsScreen - if (getInstance().currentScreen instanceof CreditsScreen) { - Debug.logInternal("isFinished - Current screen is CreditsScreen"); - return true; - } - - // Check if the dragon is dead in the Overworld - if (WorldHelper.getCurrentDimension() == Dimension.OVERWORLD && _dragonIsDead) { - Debug.logInternal("isFinished - Dragon is dead in the Overworld"); - return true; - } - - // The task is not finished - Debug.logInternal("isFinished - Returning false"); - return false; - } - - /** - * Checks if the mod needs building materials. - * - * @param mod The AltoClef mod instance. - * @return True if building materials are needed, false otherwise. - */ - private boolean needsBuildingMaterials(AltoClef mod) { - int materialCount = StorageHelper.getBuildingMaterialCount(mod); - boolean shouldForce = shouldForce(mod, _buildMaterialsTask); - - // Check if the material count is below the minimum required count - // or if the build materials task should be forced. - if (materialCount < _config.minBuildMaterialCount || shouldForce) { - Debug.logInternal("Building materials needed: " + materialCount); - Debug.logInternal("Force build materials: " + shouldForce); - return true; - } else { - Debug.logInternal("Building materials not needed"); - return false; - } - } - - /** - * Updates the cached end items based on the dropped items in the entity tracker. - * - * @param mod The AltoClef mod instance. - */ - private void updateCachedEndItems(AltoClef mod) { - // Get the list of dropped items from the entity tracker. - List droppedItems = mod.getEntityTracker().getDroppedItems(); - - // If there are no dropped items and the cache wait time has not elapsed, return. - if (droppedItems.isEmpty() && !_cachedEndItemNothingWaitTime.elapsed()) { - Debug.logInternal("No dropped items and cache wait time not elapsed."); - return; - } - - // Reset the cache wait time and clear the cached end item drops. - _cachedEndItemNothingWaitTime.reset(); - _cachedEndItemDrops.clear(); - - // Iterate over the dropped items to update the cached end item drops. - for (ItemEntity entity : droppedItems) { - Item item = entity.getStack().getItem(); - int count = entity.getStack().getCount(); - - // Add the dropped item to the cached end item drops. - _cachedEndItemDrops.put(item, _cachedEndItemDrops.getOrDefault(item, 0) + count); - Debug.logInternal("Added dropped item: " + item + " with count: " + count); - } - } - - /** - * Retrieves the cached count of the given item in the end. - * - * @param item The item to retrieve the count for. - * @return The cached count of the item. - */ - private int getEndCachedCount(Item item) { - // Retrieve the count of the item from the cachedEndItemDrops map - int count = _cachedEndItemDrops.getOrDefault(item, 0); - - // Log the retrieved count for debugging purposes - Debug.logInternal("EndCachedCount: " + count); - - // Return the retrieved count - return count; - } - - /** - * Checks if an item is dropped in the end. - * - * @param item The item to check. - * @return True if the item is dropped in the end, false otherwise. - */ - private boolean droppedInEnd(Item item) { - // Get the cached count from the end. - int cachedCount = getEndCachedCount(item); - - if (cachedCount > 0) { - // Log the cached count when the item is dropped in the end. - Debug.logInternal("Item dropped in end. Cached count: " + cachedCount); - return true; - } else { - // Log the cached count when the item is not dropped in the end. - Debug.logInternal("Item not dropped in end. Cached count: 0"); - return false; - } - } - - /** - * Checks if the given item is present in the item storage or if it has been dropped in the end. - * - * @param mod The AltoClef mod instance. - * @param item The item to check. - * @return True if the item is present in the item storage or if it has been dropped in the end, false otherwise. - */ - private boolean hasItemOrDroppedInEnd(AltoClef mod, Item item) { - // Check if the item is present in the item storage. - boolean hasItem = mod.getItemStorage().hasItem(item); - - // Check if the item has been dropped in the end. - boolean droppedInEnd = droppedInEnd(item); - - // Log the values for debugging purposes. - Debug.logInternal("hasItem: " + hasItem); - Debug.logInternal("droppedInEnd: " + droppedInEnd); - - // Return true if the item is present in the item storage or if it has been dropped in the end. - return hasItem || droppedInEnd; - } - - /** - * Retrieves a list of lootable items based on certain conditions. - * - * @param mod The AltoClef mod instance. - * @return The list of lootable items. - */ - private List lootableItems(AltoClef mod) { - List lootable = new ArrayList<>(); - - // Add initial lootable items - lootable.add(Items.GOLDEN_APPLE); - lootable.add(Items.ENCHANTED_GOLDEN_APPLE); - lootable.add(Items.GLISTERING_MELON_SLICE); - lootable.add(Items.GOLDEN_CARROT); - lootable.add(Items.OBSIDIAN); - - // Check if golden helmet is equipped or available in inventory - boolean isGoldenHelmetEquipped = StorageHelper.isArmorEquipped(mod, Items.GOLDEN_HELMET); - boolean hasGoldenHelmet = mod.getItemStorage().hasItemInventoryOnly(Items.GOLDEN_HELMET); - - // Check if there are enough gold ingots - boolean hasEnoughGoldIngots = mod.getItemStorage().getItemCountInventoryOnly(Items.GOLD_INGOT) >= 5; - - // Add golden helmet if not equipped or available in inventory - if (!isGoldenHelmetEquipped && !hasGoldenHelmet) { - lootable.add(Items.GOLDEN_HELMET); - } - - // Add gold ingot if enough gold ingots are available or if barterPearlsInsteadOfEndermanHunt is true - if ((hasEnoughGoldIngots && !isGoldenHelmetEquipped && !hasGoldenHelmet) || _config.barterPearlsInsteadOfEndermanHunt) { - lootable.add(Items.GOLD_INGOT); - } - - // Add flint and steel and fire charge if not available in inventory - if (!mod.getItemStorage().hasItemInventoryOnly(Items.FLINT_AND_STEEL)) { - lootable.add(Items.FLINT_AND_STEEL); - if (!mod.getItemStorage().hasItemInventoryOnly(Items.FIRE_CHARGE)) { - lootable.add(Items.FIRE_CHARGE); - } - } - - // Add iron ingot if neither bucket nor water bucket is available in inventory - if (!mod.getItemStorage().hasItemInventoryOnly(Items.BUCKET) && !mod.getItemStorage().hasItemInventoryOnly(Items.WATER_BUCKET)) { - lootable.add(Items.IRON_INGOT); - } - - // Add diamond if item targets for eye gear are not met in inventory - if (!StorageHelper.itemTargetsMetInventory(mod, COLLECT_EYE_GEAR_MIN)) { - lootable.add(Items.DIAMOND); - } - - // Add flint if not available in inventory - if (!mod.getItemStorage().hasItemInventoryOnly(Items.FLINT)) { - lootable.add(Items.FLINT); - } - - Debug.logInternal("Lootable items: " + lootable); // Logging statement - - return lootable; - } - - /** - * Overrides the onStop method. - * Performs necessary cleanup and logging when the task is interrupted or stopped. - * - * @param mod The AltoClef mod instance. - * @param interruptTask The task that interrupted the current task. - */ - @Override - protected void onStop(AltoClef mod, Task interruptTask) { - // Disable walking on end portal - mod.getExtraBaritoneSettings().canWalkOnEndPortal(false); - - // Pop the top behaviour from the stack - mod.getBehaviour().pop(); - - // Stop tracking bed blocks - mod.getBlockTracker().stopTracking(ItemHelper.itemsToBlocks(ItemHelper.BED)); - - // Stop tracking custom blocks - mod.getBlockTracker().stopTracking(TRACK_BLOCKS); - - // Log method stop - Debug.logInternal("Stopped onStop method"); - - // Log canWalkOnEndPortal status - Debug.logInternal("canWalkOnEndPortal set to false"); - - // Log behaviour pop - Debug.logInternal("Behaviour popped"); - - // Log stop tracking bed blocks - Debug.logInternal("Stopped tracking BED blocks"); - - // Log stop tracking custom blocks - Debug.logInternal("Stopped tracking TRACK_BLOCKS"); - } - - /** - * Check if the given task is equal to this MarvionBeatMinecraftTask. - * - * @param other The task to compare. - * @return True if the tasks are equal, false otherwise. - */ - @Override - protected boolean isEqual(Task other) { - // Check if the given task is of type MarvionBeatMinecraftTask - boolean isSameTask = other != null && other instanceof MarvionBeatMinecraftTask; - if (!isSameTask) { - // Log a message if the given task is not of type MarvionBeatMinecraftTask - Debug.logInternal("The 'other' task is not of type MarvionBeatMinecraftTask"); - } - return isSameTask; - } - - /** - * Returns a debug string for the object. - * - * @return The debug string. - */ - @Override - protected String toDebugString() { - return "Beating the game (Marvion version)."; - } - - /** - * Checks if the end portal has been found. - * - * @param mod The instance of the AltoClef mod. - * @param endPortalCenter The center position of the end portal. - * @return True if the end portal has been found, false otherwise. - */ - private boolean endPortalFound(AltoClef mod, BlockPos endPortalCenter) { - // Check if the end portal center is null - if (endPortalCenter == null) { - Debug.logInternal("End portal center is null"); - return false; - } - - // Check if the end portal is already opened - if (endPortalOpened(mod, endPortalCenter)) { - Debug.logInternal("End portal is already opened"); - return true; - } - - // Get the frame blocks of the end portal - List frameBlocks = getFrameBlocks(endPortalCenter); - for (BlockPos frame : frameBlocks) { - // Check if the frame block is a valid end portal frame - if (mod.getBlockTracker().blockIsValid(frame, Blocks.END_PORTAL_FRAME)) { - Debug.logInternal("Found valid end portal frame at " + frame.toString()); - return true; - } - } - - // No valid end portal frame found - Debug.logInternal("No valid end portal frame found"); - return false; - } - - /** - * Checks if the end portal is opened. - * - * @param mod The AltoClef mod instance. - * @param endPortalCenter The center position of the end portal. - * @return True if the end portal is opened, false otherwise. - */ - private boolean endPortalOpened(AltoClef mod, BlockPos endPortalCenter) { - // Check if the end portal is already opened and the center position is provided - if (_endPortalOpened && endPortalCenter != null) { - // Get the block tracker from the mod instance - BlockTracker blockTracker = mod.getBlockTracker(); - // Check if the block tracker is available - if (blockTracker != null) { - // Check if the end portal block at the center position is valid - boolean isValid = blockTracker.blockIsValid(endPortalCenter, Blocks.END_PORTAL); - // Log the result of the end portal validity - Debug.logInternal("End Portal is " + (isValid ? "valid" : "invalid")); - return isValid; - } - } - // Log that the end portal is not opened yet - Debug.logInternal("End Portal is not opened yet"); - return false; - } - - /** - * Checks if the bed spawn location is near the given end portal center. - * - * @param mod The AltoClef mod instance. - * @param endPortalCenter The center position of the end portal. - * @return True if the bed spawn location is near the end portal, false otherwise. - */ - private boolean spawnSetNearPortal(AltoClef mod, BlockPos endPortalCenter) { - // Check if the bed spawn location is null - if (_bedSpawnLocation == null) { - Debug.logInternal("Bed spawn location is null"); - return false; - } - - // Get the block tracker instance - BlockTracker blockTracker = mod.getBlockTracker(); - - // Check if the bed spawn location is valid by comparing it with the bed block - boolean isValid = blockTracker.blockIsValid(_bedSpawnLocation, ItemHelper.itemsToBlocks(ItemHelper.BED)); - - // Log the result of the spawn set near portal check - Debug.logInternal("Spawn set near portal: " + isValid); - - // Return the result of the check - return isValid; - } - - /** - * Finds the closest unopened ruined portal chest. - * - * @param mod The AltoClef mod instance. - * @return An Optional containing the closest BlockPos of the unopened ruined portal chest, or empty if not found. - */ - private Optional locateClosestUnopenedRuinedPortalChest(AltoClef mod) { - // Check if the current dimension is not the overworld - if (!WorldHelper.getCurrentDimension().equals(Dimension.OVERWORLD)) { - return Optional.empty(); - } - - // Find the nearest tracking block position - return mod.getBlockTracker().getNearestTracking(blockPos -> { - boolean isNotRuinedPortalChest = !_notRuinedPortalChests.contains(blockPos); - boolean isUnopenedChest = WorldHelper.isUnopenedChest(mod, blockPos); - boolean isWithinDistance = mod.getPlayer().getBlockPos().isWithinDistance(blockPos, 150); - boolean isLootablePortalChest = canBeLootablePortalChest(mod, blockPos); - - Debug.logInternal("isNotRuinedPortalChest: " + isNotRuinedPortalChest); - Debug.logInternal("isUnopenedChest: " + isUnopenedChest); - Debug.logInternal("isWithinDistance: " + isWithinDistance); - Debug.logInternal("isLootablePortalChest: " + isLootablePortalChest); - - // Return true if all conditions are met - return isNotRuinedPortalChest && isUnopenedChest && isWithinDistance && isLootablePortalChest; - }, Blocks.CHEST); - } - - /** - * This method is called when the mod starts. - * It performs several tasks to set up the mod. - */ - @Override - protected void onStart(AltoClef mod) { - // Reset all timers - resetTimers(); - - // Push the initial behaviour onto the stack - pushBehaviour(mod); - - // Add warning for throwaway items - addThrowawayItemsWarning(mod); - - // Track blocks in the world - trackBlocks(mod); - - // Add protected items - addProtectedItems(mod); - - // Allow walking on the end portal - allowWalkingOnEndPortal(mod); - - // Avoid dragon breath - avoidDragonBreath(mod); - - // Avoid breaking the bed - avoidBreakingBed(mod); - } - - /** - * Resets the timers. - */ - private void resetTimers() { - // Reset timer 1 - _timer1.reset(); - - // Reset timer 2 - _timer2.reset(); - - // Reset timer 3 - _timer3.reset(); - } - - /** - * Pushes the current behaviour onto the behaviour stack. - * Logs the process for internal debugging. - * - * @param mod The AltoClef instance. - */ - private void pushBehaviour(AltoClef mod) { - // Log the start of the push process - Debug.logInternal("Pushing behaviour..."); - - // Push the current behaviour onto the stack - mod.getBehaviour().push(); - - // Log the successful push process - Debug.logInternal("Behaviour pushed successfully."); - } - - /** - * Adds a warning message if certain conditions are not met. - * - * @param mod The AltoClef mod instance. - */ - private void addThrowawayItemsWarning(AltoClef mod) { - // Warning message tail that will be appended to the warning message. - String settingsWarningTail = "in \".minecraft/altoclef_settings.json\". @gamer may break if you don't add this! (sorry!)"; - - // Check if "end_stone" is not part of the "throwawayItems" list and log a warning. - if (!ArrayUtils.contains(mod.getModSettings().getThrowawayItems(mod), Items.END_STONE)) { - Debug.logWarning("\"end_stone\" is not part of your \"throwawayItems\" list " + settingsWarningTail); - } - - // Check if "throwawayUnusedItems" is not set to true and log a warning. - if (!mod.getModSettings().shouldThrowawayUnusedItems()) { - Debug.logWarning("\"throwawayUnusedItems\" is not set to true " + settingsWarningTail); - } - } - - /** - * Tracks specific blocks using the BlockTracker. - * - * @param mod The AltoClef mod instance. - */ - private void trackBlocks(AltoClef mod) { - BlockTracker blockTracker = mod.getBlockTracker(); - blockTracker.trackBlock(ItemHelper.itemsToBlocks(ItemHelper.BED)); - blockTracker.trackBlock(TRACK_BLOCKS); - - // Add logging statements - Debug.logInternal("Tracking blocks..."); - Debug.logInternal("BlockTracker: " + blockTracker); - Debug.logInternal("Bed block: " + ItemHelper.itemsToBlocks(ItemHelper.BED)); - Debug.logInternal("TRACK_BLOCKS: " + TRACK_BLOCKS); - } - - /** - * Adds protected items to the behaviour of the given AltoClef instance. - * - * @param mod The AltoClef instance. - */ - private void addProtectedItems(AltoClef mod) { - // Add individual protected items - mod.getBehaviour().addProtectedItems( - Items.ENDER_EYE, // Ender Eye - Items.BLAZE_ROD, // Blaze Rod - Items.ENDER_PEARL, // Ender Pearl - Items.CRAFTING_TABLE, // Crafting Table - Items.IRON_INGOT, // Iron Ingot - Items.WATER_BUCKET, // Water Bucket - Items.FLINT_AND_STEEL, // Flint and Steel - Items.SHIELD, // Shield - Items.SHEARS, // Shears - Items.BUCKET, // Bucket - Items.GOLDEN_HELMET, // Golden Helmet - Items.SMOKER, // Smoker - Items.FURNACE, // Furnace - Items.BLAST_FURNACE // Blast Furnace - ); - - // Add protected items using helper classes - mod.getBehaviour().addProtectedItems(ItemHelper.BED); - mod.getBehaviour().addProtectedItems(ItemHelper.IRON_ARMORS); - mod.getBehaviour().addProtectedItems(ItemHelper.LOG); - - Debug.logInternal("Protected items added successfully."); - } - - /** - * Allows the player to walk on an end portal block. - * - * @param mod The AltoClef mod instance. - */ - private void allowWalkingOnEndPortal(AltoClef mod) { - mod.getBehaviour().allowWalkingOn(blockPos -> { - if (_enterindEndPortal) { - if (mod.getChunkTracker().isChunkLoaded(blockPos)) { - BlockState blockState = mod.getWorld().getBlockState(blockPos); - boolean isEndPortal = blockState.getBlock() == Blocks.END_PORTAL; - if (isEndPortal) { - Debug.logInternal("Walking on End Portal at " + blockPos.toString()); - } - return isEndPortal; - } - } - return false; - }); - } - - /** - * Avoids walking through dragon breath in the End dimension. - * - * @param mod The AltoClef mod instance. - */ - private void avoidDragonBreath(AltoClef mod) { - mod.getBehaviour().avoidWalkingThrough(blockPos -> { - Dimension currentDimension = WorldHelper.getCurrentDimension(); - boolean isEndDimension = currentDimension == Dimension.END; - boolean isTouchingDragonBreath = _dragonBreathTracker.isTouchingDragonBreath(blockPos); - - if (isEndDimension && !_escapingDragonsBreath && isTouchingDragonBreath) { - Debug.logInternal("Avoiding dragon breath at blockPos: " + blockPos); - return true; - } else { - return false; - } - }); - } - - /** - * Avoid breaking the bed by adding a behavior to avoid breaking specific block positions. - * - * @param mod The AltoClef mod instance. - */ - private void avoidBreakingBed(AltoClef mod) { - mod.getBehaviour().avoidBlockBreaking(blockPos -> { - // Check if the bed spawn location is set - if (_bedSpawnLocation != null) { - // Get the head and foot positions of the bed - BlockPos bedHead = WorldHelper.getBedHead(mod, _bedSpawnLocation); - BlockPos bedFoot = WorldHelper.getBedFoot(mod, _bedSpawnLocation); - - // Check if the current block position is either the head or the foot of the bed - boolean shouldAvoidBreaking = blockPos.equals(bedHead) || blockPos.equals(bedFoot); - - // Log a debug message if the block position should be avoided - if (shouldAvoidBreaking) { - Debug.logInternal("Avoiding breaking bed at block position: " + blockPos); - } - - return shouldAvoidBreaking; - } - - // Return false if the bed spawn location is not set - return false; - }); - } - - @Override - protected Task onTick(AltoClef mod) { - if (mod.getPlayer().getMainHandStack().getItem() instanceof EnderEyeItem && - !openingEndPortal) { - List itemStacks = mod.getItemStorage().getItemStacksPlayerInventory(true); - for (ItemStack itemStack : itemStacks) { - Item item = itemStack.getItem(); - if (item instanceof SwordItem) { - mod.getSlotHandler().forceEquipItem(item); - } - } - } - boolean eyeGearSatisfied = StorageHelper.isArmorEquippedAll(mod, COLLECT_EYE_ARMOR); - boolean ironGearSatisfied = StorageHelper.isArmorEquippedAll(mod, COLLECT_IRON_ARMOR); - if (mod.getItemStorage().hasItem(Items.DIAMOND_PICKAXE)) { - mod.getBehaviour().setBlockBreakAdditionalPenalty(0); - } else { - mod.getBehaviour().setBlockBreakAdditionalPenalty(mod.getClientBaritoneSettings().blockBreakAdditionalPenalty.defaultValue); - } - Predicate isCraftingTableTask = task -> { - if (task instanceof DoStuffInContainerTask cont) { - return cont.getContainerTarget().matches(Items.CRAFTING_TABLE); - } - return false; - }; - List craftingTables = mod.getBlockTracker().getKnownLocations(Blocks.CRAFTING_TABLE); - if (!craftingTables.isEmpty()) { - for (BlockPos craftingTable : craftingTables) { - if (mod.getItemStorage().hasItem(Items.CRAFTING_TABLE) && !thisOrChildSatisfies(isCraftingTableTask)) { - if (!mod.getBlockTracker().unreachable(craftingTable)) { - Debug.logMessage("Blacklisting extra crafting table."); - mod.getBlockTracker().requestBlockUnreachable(craftingTable, 0); - } - } - if (!mod.getBlockTracker().unreachable(craftingTable)) { - BlockState craftingTablePosUp = mod.getWorld().getBlockState(craftingTable.up(2)); - if (mod.getEntityTracker().entityFound(WitchEntity.class)) { - Optional witch = mod.getEntityTracker().getClosestEntity(WitchEntity.class); - if (witch.isPresent()) { - if (craftingTable.isWithinDistance(witch.get().getPos(), 15)) { - Debug.logMessage("Blacklisting witch crafting table."); - mod.getBlockTracker().requestBlockUnreachable(craftingTable, 0); - } - } - } - if (craftingTablePosUp.getBlock() == Blocks.WHITE_WOOL) { - Debug.logMessage("Blacklisting pillage crafting table."); - mod.getBlockTracker().requestBlockUnreachable(craftingTable, 0); - } - } - } - } - List smokers = mod.getBlockTracker().getKnownLocations(Blocks.SMOKER); - if (!smokers.isEmpty()) { - for (BlockPos smoker : smokers) { - if (mod.getItemStorage().hasItem(Items.SMOKER) && _smeltTask == null && _foodTask == null) { - if (!mod.getBlockTracker().unreachable(smoker)) { - Debug.logMessage("Blacklisting extra smoker."); - mod.getBlockTracker().requestBlockUnreachable(smoker, 0); - } - } - } - } - List furnaces = mod.getBlockTracker().getKnownLocations(Blocks.FURNACE); - if (!furnaces.isEmpty()) { - for (BlockPos furnace : furnaces) { - if ((mod.getItemStorage().hasItem(Items.FURNACE) || mod.getItemStorage().hasItem(Items.BLAST_FURNACE)) && - _starterGearTask == null && _shieldTask == null && _ironGearTask == null && _gearTask == null && - !_goToNetherTask.isActive() && !_ranStrongholdLocator) { - if (!mod.getBlockTracker().unreachable(furnace)) { - Debug.logMessage("Blacklisting extra furnace."); - mod.getBlockTracker().requestBlockUnreachable(furnace, 0); - } - } - } - } - List blastFurnaces = mod.getBlockTracker().getKnownLocations(Blocks.BLAST_FURNACE); - if (!blastFurnaces.isEmpty()) { - for (BlockPos blastFurnace : blastFurnaces) { - if (mod.getItemStorage().hasItem(Items.BLAST_FURNACE) && _starterGearTask == null && _shieldTask == null && - _ironGearTask == null && _gearTask == null && !_goToNetherTask.isActive() && !_ranStrongholdLocator) { - if (!mod.getBlockTracker().unreachable(blastFurnace)) { - Debug.logMessage("Blacklisting extra blast furnace."); - mod.getBlockTracker().requestBlockUnreachable(blastFurnace, 0); - } - } - } - } - List logs = mod.getBlockTracker().getKnownLocations(ItemHelper.itemsToBlocks(ItemHelper.LOG)); - if (!logs.isEmpty()) { - for (BlockPos log : logs) { - Iterable entities = mod.getWorld().getEntities(); - for (Entity entity : entities) { - if (entity instanceof PillagerEntity) { - if (!mod.getBlockTracker().unreachable(log)) { - if (log.isWithinDistance(entity.getPos(), 40)) { - Debug.logMessage("Blacklisting pillage log."); - mod.getBlockTracker().requestBlockUnreachable(log, 0); - } - } - } - } - if (log.getY() < 62) { - if (!mod.getBlockTracker().unreachable(log)) { - if (!ironGearSatisfied && !eyeGearSatisfied) { - Debug.logMessage("Blacklisting dangerous log."); - mod.getBlockTracker().requestBlockUnreachable(log, 0); - } - } - } - } - } - if (mod.getBlockTracker().isTracking(Blocks.DEEPSLATE_COAL_ORE)) { - Optional deepslateCoalOre = mod.getBlockTracker().getNearestTracking(Blocks.DEEPSLATE_COAL_ORE); - if (deepslateCoalOre.isPresent()) { - Iterable entities = mod.getWorld().getEntities(); - for (Entity entity : entities) { - if (entity instanceof HostileEntity) { - if (!mod.getBlockTracker().unreachable(deepslateCoalOre.get())) { - if (mod.getPlayer().squaredDistanceTo(entity.getPos()) < 150 && - deepslateCoalOre.get().isWithinDistance(entity.getPos(), 30)) { - if (!ironGearSatisfied && !eyeGearSatisfied) { - Debug.logMessage("Blacklisting dangerous coal ore."); - mod.getBlockTracker().requestBlockUnreachable(deepslateCoalOre.get(), 0); - } - } - } - } - } - } - } - if (mod.getBlockTracker().isTracking(Blocks.COAL_ORE)) { - Optional coalOrePos = mod.getBlockTracker().getNearestTracking(Blocks.COAL_ORE); - if (coalOrePos.isPresent()) { - Iterable entities = mod.getWorld().getEntities(); - for (Entity entity : entities) { - if (entity instanceof HostileEntity) { - if (!mod.getBlockTracker().unreachable(coalOrePos.get())) { - if (mod.getPlayer().squaredDistanceTo(entity.getPos()) < 150 && - coalOrePos.get().isWithinDistance(entity.getPos(), 30)) { - if (!ironGearSatisfied && !eyeGearSatisfied) { - Debug.logMessage("Blacklisting dangerous coal ore."); - mod.getBlockTracker().requestBlockUnreachable(coalOrePos.get(), 0); - } - } - } - } - } - } - } - if (mod.getBlockTracker().isTracking(Blocks.DEEPSLATE_IRON_ORE)) { - Optional deepslateIronOrePos = mod.getBlockTracker().getNearestTracking(Blocks.DEEPSLATE_IRON_ORE); - if (deepslateIronOrePos.isPresent()) { - Iterable entities = mod.getWorld().getEntities(); - for (Entity entity : entities) { - if (entity instanceof HostileEntity) { - if (!mod.getBlockTracker().unreachable(deepslateIronOrePos.get())) { - if (mod.getPlayer().squaredDistanceTo(entity.getPos()) < 150 && - deepslateIronOrePos.get().isWithinDistance(entity.getPos(), 30)) { - if (!ironGearSatisfied && !eyeGearSatisfied) { - Debug.logMessage("Blacklisting dangerous iron ore."); - mod.getBlockTracker().requestBlockUnreachable(deepslateIronOrePos.get(), 0); - } - } - } - } - } - } - } - if (mod.getBlockTracker().isTracking(Blocks.IRON_ORE)) { - Optional ironOrePos = mod.getBlockTracker().getNearestTracking(Blocks.IRON_ORE); - if (ironOrePos.isPresent()) { - Iterable entities = mod.getWorld().getEntities(); - for (Entity entity : entities) { - if (entity instanceof HostileEntity) { - if (!mod.getBlockTracker().unreachable(ironOrePos.get())) { - if (mod.getPlayer().squaredDistanceTo(entity.getPos()) < 150 && - ironOrePos.get().isWithinDistance(entity.getPos(), 30)) { - if (!ironGearSatisfied && !eyeGearSatisfied) { - Debug.logMessage("Blacklisting dangerous iron ore."); - mod.getBlockTracker().requestBlockUnreachable(ironOrePos.get(), 0); - } - } - } - } - } - } - } - if (!mod.getItemStorage().hasItem(Items.NETHERRACK) && - WorldHelper.getCurrentDimension() == Dimension.NETHER && !isGettingBlazeRods && - !isGettingEnderPearls) { - setDebugState("Getting netherrack."); - if (mod.getEntityTracker().itemDropped(Items.NETHERRACK)) { - return new PickupDroppedItemTask(Items.NETHERRACK, 1, true); - } - return TaskCatalogue.getItemTask(Items.NETHERRACK, 1); - } - if (_locateStrongholdTask.isActive()) { - if (WorldHelper.getCurrentDimension() == Dimension.OVERWORLD) { - if (!mod.getClientBaritone().getExploreProcess().isActive()) { - if (_timer1.elapsed()) { - if (_config.renderDistanceManipulation) { - getInstance().options.getViewDistance().setValue(12); - } - _timer1.reset(); - } - } - } - } - if ((_logsTask != null || _foodTask != null || _getOneBedTask.isActive() || _stoneGearTask != null || - (_sleepThroughNightTask.isActive() && !mod.getItemStorage().hasItem(ItemHelper.BED))) && - getBedTask == null) { - if (!mod.getClientBaritone().getExploreProcess().isActive()) { - if (_timer3.getDuration() >= 30) { - if (_config.renderDistanceManipulation) { - getInstance().options.getViewDistance().setValue(12); - getInstance().options.getEntityDistanceScaling().setValue(1.0); - } - } - if (_timer3.elapsed()) { - if (_config.renderDistanceManipulation) { - getInstance().options.getViewDistance().setValue(32); - getInstance().options.getEntityDistanceScaling().setValue(5.0); - } - _timer3.reset(); - } - } - } - if (WorldHelper.getCurrentDimension() == Dimension.OVERWORLD && _foodTask == null && !_getOneBedTask.isActive() - && !_locateStrongholdTask.isActive() && _logsTask == null && _stoneGearTask == null && - _getPorkchopTask == null && searchBiomeTask == null && _config.renderDistanceManipulation && - !_ranStrongholdLocator && getBedTask == null && !_sleepThroughNightTask.isActive()) { - if (!mod.getClientBaritone().getExploreProcess().isActive()) { - if (_timer1.elapsed()) { - if (_config.renderDistanceManipulation) { - getInstance().options.getViewDistance().setValue(2); - getInstance().options.getEntityDistanceScaling().setValue(0.5); - } - _timer1.reset(); - } - } - } - if (WorldHelper.getCurrentDimension() == Dimension.NETHER) { - if (!mod.getClientBaritone().getExploreProcess().isActive() && !_locateStrongholdTask.isActive() && - _config.renderDistanceManipulation) { - if (_timer1.elapsed()) { - if (_config.renderDistanceManipulation) { - getInstance().options.getViewDistance().setValue(12); - getInstance().options.getEntityDistanceScaling().setValue(1.0); - } - _timer1.reset(); - } - } - } - List torches = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, - Items.TORCH); - List beds = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, - ItemHelper.BED); - List excessWaterBuckets = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, - Items.WATER_BUCKET); - List excessLighters = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, - Items.FLINT_AND_STEEL); - List sands = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, - Items.SAND); - List gravels = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, - Items.GRAVEL); - List furnaceSlots = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, - Items.FURNACE); - List shears = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, - Items.SHEARS); - if (!StorageHelper.isBigCraftingOpen() && !StorageHelper.isFurnaceOpen() && - !StorageHelper.isSmokerOpen() && !StorageHelper.isBlastFurnaceOpen()) { - if (!shears.isEmpty() && !needsBeds(mod)) { - for (Slot shear : shears) { - if (Slot.isCursor(shear)) { - if (!mod.getControllerExtras().isBreakingBlock()) { - LookHelper.randomOrientation(mod); - } - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); - } else { - mod.getSlotHandler().clickSlot(shear, 0, SlotActionType.PICKUP); - } - } - } - if (!furnaceSlots.isEmpty() && mod.getItemStorage().hasItem(Items.SMOKER) && - mod.getItemStorage().hasItem(Items.BLAST_FURNACE) && mod.getModSettings().shouldUseBlastFurnace()) { - for (Slot furnace : furnaceSlots) { - if (Slot.isCursor(furnace)) { - if (!mod.getControllerExtras().isBreakingBlock()) { - LookHelper.randomOrientation(mod); - } - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); - } else { - mod.getSlotHandler().clickSlot(furnace, 0, SlotActionType.PICKUP); - } - } - } - if (!sands.isEmpty()) { - for (Slot sand : sands) { - if (Slot.isCursor(sand)) { - if (!mod.getControllerExtras().isBreakingBlock()) { - LookHelper.randomOrientation(mod); - } - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); - } else { - mod.getSlotHandler().clickSlot(sand, 0, SlotActionType.PICKUP); - } - } - } - if (mod.getItemStorage().hasItem(Items.FLINT) || mod.getItemStorage().hasItem(Items.FLINT_AND_STEEL)) { - if (!gravels.isEmpty()) { - for (Slot gravel : gravels) { - if (Slot.isCursor(gravel)) { - if (!mod.getControllerExtras().isBreakingBlock()) { - LookHelper.randomOrientation(mod); - } - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); - } else { - mod.getSlotHandler().clickSlot(gravel, 0, SlotActionType.PICKUP); - } - } - } - } - if (!torches.isEmpty()) { - for (Slot torch : torches) { - if (Slot.isCursor(torch)) { - if (!mod.getControllerExtras().isBreakingBlock()) { - LookHelper.randomOrientation(mod); - } - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); - } else { - mod.getSlotHandler().clickSlot(torch, 0, SlotActionType.PICKUP); - } - } - } - if (mod.getItemStorage().getItemCount(Items.WATER_BUCKET) > 1) { - if (!excessWaterBuckets.isEmpty()) { - for (Slot excessWaterBucket : excessWaterBuckets) { - if (Slot.isCursor(excessWaterBucket)) { - if (!mod.getControllerExtras().isBreakingBlock()) { - LookHelper.randomOrientation(mod); - } - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); - } else { - mod.getSlotHandler().clickSlot(excessWaterBucket, 0, SlotActionType.PICKUP); - } - } - } - } - if (mod.getItemStorage().getItemCount(Items.FLINT_AND_STEEL) > 1) { - if (!excessLighters.isEmpty()) { - for (Slot excessLighter : excessLighters) { - if (Slot.isCursor(excessLighter)) { - if (!mod.getControllerExtras().isBreakingBlock()) { - LookHelper.randomOrientation(mod); - } - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); - } else { - mod.getSlotHandler().clickSlot(excessLighter, 0, SlotActionType.PICKUP); - } - } - } - } - if (mod.getItemStorage().getItemCount(ItemHelper.BED) > getTargetBeds(mod) && - !endPortalFound(mod, _endPortalCenterLocation) && WorldHelper.getCurrentDimension() != Dimension.END) { - if (!beds.isEmpty()) { - for (Slot bed : beds) { - if (Slot.isCursor(bed)) { - if (!mod.getControllerExtras().isBreakingBlock()) { - LookHelper.randomOrientation(mod); - } - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); - } else { - mod.getSlotHandler().clickSlot(bed, 0, SlotActionType.PICKUP); - } - } - } - } - } - /* - if in the overworld: - if end portal found: - if end portal opened: - @make sure we have iron gear and enough beds to kill the dragon first, considering whether that gear was dropped in the end - @enter end portal - else if we have enough eyes of ender: - @fill in the end portal - else if we have enough eyes of ender: - @locate the end portal - else: - if we don't have diamond gear: - if we have no food: - @get a little bit of food - @get diamond gear - @go to the nether - if in the nether: - if we don't have enough blaze rods: - @kill blazes till we do - else if we don't have enough pearls: - @kill enderman till we do - else: - @leave the nether - if in the end: - if we have a bed: - @do bed strats - else: - @just hit the dragon normally - */ - - // By default, don't walk over end portals. - _enterindEndPortal = false; - - // End stuff. - if (WorldHelper.getCurrentDimension() == Dimension.END) { - if (!mod.getWorld().isChunkLoaded(0, 0)) { - setDebugState("Waiting for chunks to load"); - return null; - } - if (_config.renderDistanceManipulation) { - getInstance().options.getViewDistance().setValue(12); - getInstance().options.getEntityDistanceScaling().setValue(1.0); - } - // If we have bed, do bed strats, otherwise punk normally. - updateCachedEndItems(mod); - // Grab beds - if (mod.getEntityTracker().itemDropped(ItemHelper.BED) && (needsBeds(mod) || - WorldHelper.getCurrentDimension() == Dimension.END)) - return new PickupDroppedItemTask(new ItemTarget(ItemHelper.BED), true); - // Grab tools - if (!mod.getItemStorage().hasItem(Items.IRON_PICKAXE, Items.DIAMOND_PICKAXE)) { - if (mod.getEntityTracker().itemDropped(Items.IRON_PICKAXE)) - return new PickupDroppedItemTask(Items.IRON_PICKAXE, 1); - if (mod.getEntityTracker().itemDropped(Items.DIAMOND_PICKAXE)) - return new PickupDroppedItemTask(Items.DIAMOND_PICKAXE, 1); - } - if (!mod.getItemStorage().hasItem(Items.WATER_BUCKET) && mod.getEntityTracker().itemDropped(Items.WATER_BUCKET)) - return new PickupDroppedItemTask(Items.WATER_BUCKET, 1); - // Grab armor - for (Item armorCheck : COLLECT_EYE_ARMOR_END) { - if (!StorageHelper.isArmorEquipped(mod, armorCheck)) { - if (mod.getItemStorage().hasItem(armorCheck)) { - setDebugState("Equipping armor."); - return new EquipArmorTask(armorCheck); - } - if (mod.getEntityTracker().itemDropped(armorCheck)) { - return new PickupDroppedItemTask(armorCheck, 1); - } - } - } - // Dragons breath avoidance - _dragonBreathTracker.updateBreath(mod); - for (BlockPos playerIn : WorldHelper.getBlocksTouchingPlayer(mod)) { - if (_dragonBreathTracker.isTouchingDragonBreath(playerIn)) { - setDebugState("ESCAPE dragons breath"); - _escapingDragonsBreath = true; - return _dragonBreathTracker.getRunAwayTask(); - } - } - _escapingDragonsBreath = false; - - // If we find an ender portal, just GO to it!!! - if (mod.getBlockTracker().anyFound(Blocks.END_PORTAL)) { - setDebugState("WOOHOO"); - _dragonIsDead = true; - _enterindEndPortal = true; - if (!mod.getExtraBaritoneSettings().isCanWalkOnEndPortal()) { - mod.getExtraBaritoneSettings().canWalkOnEndPortal(true); - } - return new DoToClosestBlockTask( - blockPos -> new GetToBlockTask(blockPos.up()), - Blocks.END_PORTAL - ); - } - if (mod.getItemStorage().hasItem(ItemHelper.BED) || - mod.getBlockTracker().anyFound(ItemHelper.itemsToBlocks(ItemHelper.BED))) { - setDebugState("Bed strats"); - return _killDragonBedStratsTask; - } - setDebugState("No beds, regular strats."); - return new KillEnderDragonTask(); - } else { - // We're not in the end so reset our "end cache" timer - _cachedEndItemNothingWaitTime.reset(); - } - - // Check for end portals. Always. - if (!endPortalOpened(mod, _endPortalCenterLocation) && WorldHelper.getCurrentDimension() == Dimension.OVERWORLD) { - Optional endPortal = mod.getBlockTracker().getNearestTracking(Blocks.END_PORTAL); - if (endPortal.isPresent()) { - _endPortalCenterLocation = endPortal.get(); - _endPortalOpened = true; - } else { - // TODO: Test that this works, for some reason the bot gets stuck near the stronghold and it keeps "Searching" for the portal - _endPortalCenterLocation = doSimpleSearchForEndPortal(mod); - } - } - if (getBedTask != null) { - // for smoker - _smeltTask = null; - _foodTask = null; - // for furnace - _starterGearTask = null; - _shieldTask = null; - _ironGearTask = null; - _gearTask = null; - } - // Portable crafting table. - // If we're NOT using our crafting table right now and there's one nearby, grab it. - if (!_endPortalOpened && WorldHelper.getCurrentDimension() != Dimension.END && _config.rePickupCraftingTable && - !mod.getItemStorage().hasItem(Items.CRAFTING_TABLE) && !thisOrChildSatisfies(isCraftingTableTask) - && (mod.getBlockTracker().anyFound(blockPos -> WorldHelper.canBreak(mod, blockPos) && - WorldHelper.canReach(mod, blockPos), Blocks.CRAFTING_TABLE) || - mod.getEntityTracker().itemDropped(Items.CRAFTING_TABLE))) { - setDebugState("Picking up the crafting table while we are at it."); - return new MineAndCollectTask(Items.CRAFTING_TABLE, 1, new Block[]{Blocks.CRAFTING_TABLE}, MiningRequirement.HAND); - } - if (_config.rePickupSmoker && !_endPortalOpened && WorldHelper.getCurrentDimension() != Dimension.END && - !mod.getItemStorage().hasItem(Items.SMOKER) && - (mod.getBlockTracker().anyFound(blockPos -> WorldHelper.canBreak(mod, blockPos) && - WorldHelper.canReach(mod, blockPos), Blocks.SMOKER) - || mod.getEntityTracker().itemDropped(Items.SMOKER)) && _smeltTask == null && - _foodTask == null) { - setDebugState("Picking up the smoker while we are at it."); - return new MineAndCollectTask(Items.SMOKER, 1, new Block[]{Blocks.SMOKER}, MiningRequirement.WOOD); - } - if (_config.rePickupFurnace && !_endPortalOpened && WorldHelper.getCurrentDimension() != Dimension.END && - !mod.getItemStorage().hasItem(Items.FURNACE) && - (mod.getBlockTracker().anyFound(blockPos -> WorldHelper.canBreak(mod, blockPos) && - WorldHelper.canReach(mod, blockPos), Blocks.FURNACE) || - mod.getEntityTracker().itemDropped(Items.FURNACE)) && _starterGearTask == null && - _shieldTask == null && _ironGearTask == null && _gearTask == null && !_goToNetherTask.isActive() && - !_ranStrongholdLocator && !mod.getModSettings().shouldUseBlastFurnace()) { - setDebugState("Picking up the furnace while we are at it."); - return new MineAndCollectTask(Items.FURNACE, 1, new Block[]{Blocks.FURNACE}, MiningRequirement.WOOD); - } - if (_config.rePickupFurnace && !_endPortalOpened && WorldHelper.getCurrentDimension() != Dimension.END && - !mod.getItemStorage().hasItem(Items.BLAST_FURNACE) && - (mod.getBlockTracker().anyFound(blockPos -> WorldHelper.canBreak(mod, blockPos) && - WorldHelper.canReach(mod, blockPos), Blocks.BLAST_FURNACE) || - mod.getEntityTracker().itemDropped(Items.BLAST_FURNACE)) && _starterGearTask == null && - _shieldTask == null && _ironGearTask == null && _gearTask == null && !_goToNetherTask.isActive() && - !_ranStrongholdLocator && mod.getModSettings().shouldUseBlastFurnace()) { - setDebugState("Picking up the blast furnace while we are at it."); - return new MineAndCollectTask(Items.BLAST_FURNACE, 1, new Block[]{Blocks.BLAST_FURNACE}, MiningRequirement.WOOD); - } - - // Sleep through night. - if (_config.sleepThroughNight && !_endPortalOpened && WorldHelper.getCurrentDimension() == Dimension.OVERWORLD) { - if (WorldHelper.canSleep()) { - // for smoker - _smeltTask = null; - _foodTask = null; - // for furnace - _starterGearTask = null; - _shieldTask = null; - _ironGearTask = null; - _gearTask = null; - if (_config.renderDistanceManipulation && mod.getItemStorage().hasItem(ItemHelper.BED)) { - if (!mod.getClientBaritone().getExploreProcess().isActive()) { - if (_timer1.elapsed()) { - getInstance().options.getViewDistance().setValue(2); - getInstance().options.getEntityDistanceScaling().setValue(0.5); - _timer1.reset(); - } - } - } - if (_timer2.elapsed()) { - _timer2.reset(); - } - if (_timer2.getDuration() >= 30 && - !mod.getPlayer().isSleeping()) { - if (mod.getEntityTracker().itemDropped(ItemHelper.BED) && needsBeds(mod)) { - setDebugState("Resetting sleep through night task."); - return new PickupDroppedItemTask(new ItemTarget(ItemHelper.BED), true); - } - if (anyBedsFound(mod)) { - setDebugState("Resetting sleep through night task."); - return new DoToClosestBlockTask(DestroyBlockTask::new, ItemHelper.itemsToBlocks(ItemHelper.BED)); - } - } - setDebugState("Sleeping through night"); - return _sleepThroughNightTask; - } - if (!mod.getItemStorage().hasItem(ItemHelper.BED)) { - if (mod.getBlockTracker().anyFound(blockPos -> WorldHelper.canBreak(mod, blockPos), ItemHelper.itemsToBlocks(ItemHelper.BED)) - || shouldForce(mod, _getOneBedTask)) { - setDebugState("Getting one bed to sleep in at night."); - return _getOneBedTask; - } - } - } - if (WorldHelper.getCurrentDimension() == Dimension.OVERWORLD) { - if (needsBeds(mod) && anyBedsFound(mod)) { - setDebugState("A bed was found, getting it."); - if (_config.renderDistanceManipulation) { - if (!mod.getClientBaritone().getExploreProcess().isActive()) { - if (_timer1.elapsed()) { - getInstance().options.getViewDistance().setValue(2); - getInstance().options.getEntityDistanceScaling().setValue(0.5); - _timer1.reset(); - } - } - } - getBedTask = getBedTask(mod); - return getBedTask; - } else { - getBedTask = null; - } - } - - // Do we need more eyes? - boolean noEyesPlease = (endPortalOpened(mod, _endPortalCenterLocation) || WorldHelper.getCurrentDimension() == Dimension.END); - int filledPortalFrames = getFilledPortalFrames(mod, _endPortalCenterLocation); - int eyesNeededMin = noEyesPlease ? 0 : _config.minimumEyes - filledPortalFrames; - int eyesNeeded = noEyesPlease ? 0 : _config.targetEyes - filledPortalFrames; - int eyes = mod.getItemStorage().getItemCount(Items.ENDER_EYE); - if (eyes < eyesNeededMin || (!_ranStrongholdLocator && _collectingEyes && eyes < eyesNeeded)) { - _collectingEyes = true; - _weHaveEyes = false; - return getEyesOfEnderTask(mod, eyesNeeded); - } else { - _weHaveEyes = true; - _collectingEyes = false; - } - - // We have eyes. Locate our portal + enter. - switch (WorldHelper.getCurrentDimension()) { - case OVERWORLD -> { - if (mod.getItemStorage().hasItem(Items.DIAMOND_PICKAXE)) { - Item[] throwGearItems = {Items.STONE_SWORD, Items.STONE_PICKAXE, Items.IRON_SWORD, Items.IRON_PICKAXE}; - List ironArmors = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, - COLLECT_IRON_ARMOR); - List throwGears = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, - throwGearItems); - if (!StorageHelper.isBigCraftingOpen() && !StorageHelper.isFurnaceOpen() && - !StorageHelper.isSmokerOpen() && !StorageHelper.isBlastFurnaceOpen() && - (mod.getItemStorage().hasItem(Items.FLINT_AND_STEEL) || - mod.getItemStorage().hasItem(Items.FIRE_CHARGE))) { - if (!throwGears.isEmpty()) { - for (Slot throwGear : throwGears) { - if (Slot.isCursor(throwGear)) { - if (!mod.getControllerExtras().isBreakingBlock()) { - LookHelper.randomOrientation(mod); - } - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); - } else { - mod.getSlotHandler().clickSlot(throwGear, 0, SlotActionType.PICKUP); - } - } - } - if (!ironArmors.isEmpty()) { - for (Slot ironArmor : ironArmors) { - if (Slot.isCursor(ironArmor)) { - if (!mod.getControllerExtras().isBreakingBlock()) { - LookHelper.randomOrientation(mod); - } - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); - } else { - mod.getSlotHandler().clickSlot(ironArmor, 0, SlotActionType.PICKUP); - } - } - } - } - } - // If we found our end portal... - if (endPortalFound(mod, _endPortalCenterLocation)) { - // Destroy silverfish spawner - if (StorageHelper.miningRequirementMetInventory(mod, MiningRequirement.WOOD)) { - Optional silverfish = mod.getBlockTracker().getNearestTracking(blockPos -> { - return WorldHelper.getSpawnerEntity(mod, blockPos) instanceof SilverfishEntity; - }, Blocks.SPAWNER); - if (silverfish.isPresent()) { - setDebugState("Breaking silverfish spawner."); - return new DestroyBlockTask(silverfish.get()); - } - } - if (endPortalOpened(mod, _endPortalCenterLocation)) { - openingEndPortal = false; - if (needsBuildingMaterials(mod)) { - setDebugState("Collecting building materials."); - return _buildMaterialsTask; - } - if (_config.placeSpawnNearEndPortal && mod.getItemStorage().hasItem(ItemHelper.BED)) { - if (!spawnSetNearPortal(mod, _endPortalCenterLocation)) { - setDebugState("Setting spawn near end portal"); - return setSpawnNearPortalTask(mod); - } - } - // We're as ready as we'll ever be, hop into the portal! - setDebugState("Entering End"); - _enterindEndPortal = true; - if (!mod.getExtraBaritoneSettings().isCanWalkOnEndPortal()) { - mod.getExtraBaritoneSettings().canWalkOnEndPortal(true); - } - return new DoToClosestBlockTask( - blockPos -> new GetToBlockTask(blockPos.up()), - Blocks.END_PORTAL - ); - } else { - // Open the portal! (we have enough eyes, do it) - setDebugState("Opening End Portal"); - openingEndPortal = true; - return new DoToClosestBlockTask( - blockPos -> new InteractWithBlockTask(Items.ENDER_EYE, blockPos), - blockPos -> !isEndPortalFrameFilled(mod, blockPos), - Blocks.END_PORTAL_FRAME - ); - } - } else { - _ranStrongholdLocator = true; - // Get beds before starting our portal location. - if (WorldHelper.getCurrentDimension() == Dimension.OVERWORLD && needsBeds(mod)) { - setDebugState("Getting beds before stronghold search."); - if (!mod.getClientBaritone().getExploreProcess().isActive()) { - if (_timer1.elapsed()) { - if (_config.renderDistanceManipulation) { - getInstance().options.getViewDistance().setValue(32); - getInstance().options.getEntityDistanceScaling().setValue(5.0); - } - _timer1.reset(); - } - } - getBedTask = getBedTask(mod); - return getBedTask; - } else { - getBedTask = null; - } - if (!mod.getItemStorage().hasItem(Items.WATER_BUCKET)) { - setDebugState("Getting water bucket."); - return TaskCatalogue.getItemTask(Items.WATER_BUCKET, 1); - } - if (!mod.getItemStorage().hasItem(Items.FLINT_AND_STEEL)) { - setDebugState("Getting flint and steel."); - return TaskCatalogue.getItemTask(Items.FLINT_AND_STEEL, 1); - } - if (needsBuildingMaterials(mod)) { - setDebugState("Collecting building materials."); - return _buildMaterialsTask; - } - // Portal Location - setDebugState("Locating End Portal..."); - return _locateStrongholdTask; - } - } - case NETHER -> { - Item[] throwGearItems = {Items.STONE_SWORD, Items.STONE_PICKAXE, Items.IRON_SWORD, Items.IRON_PICKAXE}; - List ironArmors = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, - COLLECT_IRON_ARMOR); - List throwGears = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, - throwGearItems); - if (!StorageHelper.isBigCraftingOpen() && !StorageHelper.isFurnaceOpen() && - !StorageHelper.isSmokerOpen() && !StorageHelper.isBlastFurnaceOpen() && - (mod.getItemStorage().hasItem(Items.FLINT_AND_STEEL) || - mod.getItemStorage().hasItem(Items.FIRE_CHARGE))) { - if (!throwGears.isEmpty()) { - for (Slot throwGear : throwGears) { - if (Slot.isCursor(throwGear)) { - if (!mod.getControllerExtras().isBreakingBlock()) { - LookHelper.randomOrientation(mod); - } - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); - } else { - mod.getSlotHandler().clickSlot(throwGear, 0, SlotActionType.PICKUP); - } - } - } - if (!ironArmors.isEmpty()) { - for (Slot ironArmor : ironArmors) { - if (Slot.isCursor(ironArmor)) { - if (!mod.getControllerExtras().isBreakingBlock()) { - LookHelper.randomOrientation(mod); - } - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); - } else { - mod.getSlotHandler().clickSlot(ironArmor, 0, SlotActionType.PICKUP); - } - } - } - } - // Portal Location - setDebugState("Locating End Portal..."); - return _locateStrongholdTask; - } - } - return null; - } - - /** - * Sets the spawn point near the portal. - * - * @param mod The AltoClef mod instance. - * @return The task to set the spawn point near the portal. - */ - private Task setSpawnNearPortalTask(AltoClef mod) { - // Check if the bed spawn is set - if (_setBedSpawnTask.isSpawnSet()) { - _bedSpawnLocation = _setBedSpawnTask.getBedSleptPos(); - } else { - _bedSpawnLocation = null; - } - - // Check if the spawn point should be forced - if (shouldForce(mod, _setBedSpawnTask)) { - setDebugState("Setting spawnpoint now."); - return _setBedSpawnTask; - } - - // Check if the player is within range of the portal - if (WorldHelper.inRangeXZ(mod.getPlayer(), WorldHelper.toVec3d(_endPortalCenterLocation), END_PORTAL_BED_SPAWN_RANGE)) { - return _setBedSpawnTask; - } else { - setDebugState("Approaching portal (to set spawnpoint)"); - return new GetToXZTask(_endPortalCenterLocation.getX(), _endPortalCenterLocation.getZ()); - } - } - - /** - * Returns a Task to handle Blaze Rods based on the given count. - * - * @param mod The AltoClef mod instance. - * @param count The desired count of Blaze Rods. - * @return A Task to handle Blaze Rods. - */ - private Task getBlazeRodsTask(AltoClef mod, int count) { - EntityTracker entityTracker = mod.getEntityTracker(); - - if (entityTracker.itemDropped(Items.BLAZE_ROD)) { - Debug.logInternal("Blaze Rod dropped, picking it up."); - return new PickupDroppedItemTask(Items.BLAZE_ROD, 1); - } else if (entityTracker.itemDropped(Items.BLAZE_POWDER)) { - Debug.logInternal("Blaze Powder dropped, picking it up."); - return new PickupDroppedItemTask(Items.BLAZE_POWDER, 1); - } else { - Debug.logInternal("No Blaze Rod or Blaze Powder dropped, collecting Blaze Rods."); - return new CollectBlazeRodsTask(count); - } - } - - /** - * Returns a Task to obtain Ender Pearls. - * - * @param mod The mod instance. - * @param count The desired number of Ender Pearls. - * @return The Task to obtain Ender Pearls. - */ - private Task getEnderPearlTask(AltoClef mod, int count) { - isGettingEnderPearls = true; - - // Check if we should force getting Twisting Vines. - if (shouldForce(mod, getTwistingVines)) { - return getTwistingVines; - } - - // Check if Ender Pearls have been dropped as items. - if (mod.getEntityTracker().itemDropped(Items.ENDER_PEARL)) { - return new PickupDroppedItemTask(Items.ENDER_PEARL, 1); - } - - // Check if we should barter Pearls instead of hunting Endermen. - if (_config.barterPearlsInsteadOfEndermanHunt) { - // Check if Golden Helmet is not equipped, and equip it. - if (!StorageHelper.isArmorEquipped(mod, Items.GOLDEN_HELMET)) { - return new EquipArmorTask(Items.GOLDEN_HELMET); - } - // Trade with Piglins for Ender Pearls. - return new TradeWithPiglinsTask(32, Items.ENDER_PEARL, count); - } - - boolean endermanFound = mod.getEntityTracker().entityFound(EndermanEntity.class); - boolean pearlDropped = mod.getEntityTracker().itemDropped(Items.ENDER_PEARL); - boolean hasTwistingVines = mod.getItemStorage().getItemCount(Items.TWISTING_VINES) > TWISTING_VINES_COUNT_MIN; - - // Check if we have found an Enderman or Ender Pearl and have enough Twisting Vines. - if ((endermanFound || pearlDropped) && hasTwistingVines) { - Optional toKill = mod.getEntityTracker().getClosestEntity(EndermanEntity.class); - if (toKill.isPresent() && mod.getEntityTracker().isEntityReachable(toKill.get())) { - return new KillEndermanTask(count); - } - } - - boolean hasEnoughTwistingVines = mod.getItemStorage().getItemCount(Items.TWISTING_VINES) >= TWISTING_VINES_COUNT_MIN; - - // Check if we need to obtain more Twisting Vines. - if (!hasEnoughTwistingVines) { - BlockTracker blockTracker = mod.getBlockTracker(); - if (!blockTracker.isTracking(Blocks.TWISTING_VINES) || !blockTracker.isTracking(Blocks.TWISTING_VINES_PLANT)) { - blockTracker.trackBlock(Blocks.TWISTING_VINES, Blocks.TWISTING_VINES_PLANT); - } - - boolean vinesFound = blockTracker.anyFound(Blocks.TWISTING_VINES, Blocks.TWISTING_VINES_PLANT); - if (vinesFound) { - getTwistingVines = TaskCatalogue.getItemTask(Items.TWISTING_VINES, TWISTING_VINES_COUNT); - return getTwistingVines; - } else { - return new SearchChunkForBlockTask(Blocks.TWISTING_VINES, Blocks.TWISTING_VINES_PLANT, Blocks.WARPED_HYPHAE, Blocks.WARPED_NYLIUM); - } - } - - // Search for Ender Pearls within the warped forest biome. - return new SearchWithinBiomeTask(BiomeKeys.WARPED_FOREST); - } - - /** - * Calculates the target number of beds based on the configuration settings. - * - * @param mod The AltoClef mod instance. - * @return The target number of beds. - */ - private int getTargetBeds(AltoClef mod) { - // Check if spawn needs to be set near the end portal - boolean needsToSetSpawn = _config.placeSpawnNearEndPortal - && (!spawnSetNearPortal(mod, _endPortalCenterLocation) - && !shouldForce(mod, _setBedSpawnTask)); - - // Calculate the number of beds in the end - int bedsInEnd = Arrays.stream(ItemHelper.BED) - .mapToInt(bed -> _cachedEndItemDrops.getOrDefault(bed, 0)) - .sum(); - - // Calculate the target number of beds - int targetBeds = _config.requiredBeds + (needsToSetSpawn ? 1 : 0) - bedsInEnd; - - // Output debug information - Debug.logInternal("needsToSetSpawn: " + needsToSetSpawn); - Debug.logInternal("bedsInEnd: " + bedsInEnd); - Debug.logInternal("targetBeds: " + targetBeds); - - return targetBeds; - } - - /** - * Checks if the player needs to acquire more beds. - * - * @param mod The instance of the AltoClef mod. - * @return True if the player needs more beds, false otherwise. - */ - private boolean needsBeds(AltoClef mod) { - // Calculate the total number of end items obtained from breaking beds - int totalEndItems = 0; - for (Item bed : ItemHelper.BED) { - totalEndItems += _cachedEndItemDrops.getOrDefault(bed, 0); - } - - // Get the current number of beds in the player's inventory - int itemCount = mod.getItemStorage().getItemCount(ItemHelper.BED); - - // Get the target number of beds to have - int targetBeds = getTargetBeds(mod); - - // Log the values for debugging purposes - Debug.logInternal("Total End Items: " + totalEndItems); - Debug.logInternal("Item Count: " + itemCount); - Debug.logInternal("Target Beds: " + targetBeds); - - // Check if the player needs to acquire more beds - boolean needsBeds = (itemCount + totalEndItems) < targetBeds; - - // Log the result for debugging purposes - Debug.logInternal("Needs Beds: " + needsBeds); - - // Return whether the player needs more beds - return needsBeds; - } - - /** - * Retrieves a task to obtain the desired number of beds. - * - * @param mod The AltoClef mod instance. - * @return The task to obtain the beds. - */ - private Task getBedTask(AltoClef mod) { - int targetBeds = getTargetBeds(mod); - if (!mod.getItemStorage().hasItem(Items.SHEARS) && !anyBedsFound(mod)) { - Debug.logInternal("Getting shears."); - return TaskCatalogue.getItemTask(Items.SHEARS, 1); - } - Debug.logInternal("Getting beds."); - return TaskCatalogue.getItemTask("bed", targetBeds); - } - - /** - * Checks if any beds are found in the game. - * - * @param mod The AltoClef mod instance. - * @return true if beds are found either in blocks or entities, false otherwise. - */ - private boolean anyBedsFound(AltoClef mod) { - // Get the block and entity trackers from the mod instance. - BlockTracker blockTracker = mod.getBlockTracker(); - EntityTracker entityTracker = mod.getEntityTracker(); - - // Check if any beds are found in blocks. - boolean bedsFoundInBlocks = blockTracker.anyFound(ItemHelper.itemsToBlocks(ItemHelper.BED)); - - // Check if any beds are dropped by entities. - boolean bedsFoundInEntities = entityTracker.itemDropped(ItemHelper.BED); - - // Log a message if beds are found in blocks. - if (bedsFoundInBlocks) { - Debug.logInternal("Beds found in blocks"); - } - - // Log a message if beds are found in entities. - if (bedsFoundInEntities) { - Debug.logInternal("Beds found in entities"); - } - - // Return true if beds are found either in blocks or entities. - return bedsFoundInBlocks || bedsFoundInEntities; - } - - /** - * Searches for the position of an end portal frame by averaging the known locations of the frames. - * Returns the center position of the frames if enough frames are found, otherwise returns null. - * - * @param mod The AltoClef instance. - * @return The position of the end portal frame, or null if not enough frames are found. - */ - private BlockPos doSimpleSearchForEndPortal(AltoClef mod) { - List frames = mod.getBlockTracker().getKnownLocations(Blocks.END_PORTAL_FRAME); - - if (frames.size() >= END_PORTAL_FRAME_COUNT) { - // Calculate the average position of the frames. - Vec3i average = frames.stream() - .reduce(Vec3i.ZERO, (accum, bpos) -> accum.add((int) Math.round(bpos.getX() + 0.5), (int) Math.round(bpos.getY() + 0.5), (int) Math.round(bpos.getZ() + 0.5)), Vec3i::add) - .multiply(1 / frames.size()); - - // Log the average position. - Debug.logInternal("Average Position: " + average); - - return new BlockPos(average); - } - - // Log that there are not enough frames. - Debug.logInternal("Not enough frames"); - - return null; - } - - /** - * Returns the number of filled portal frames around the end portal center. - * If the end portal is found, it returns the constant END_PORTAL_FRAME_COUNT. - * Otherwise, it checks each frame block around the end portal center and counts the filled frames. - * The count is cached for subsequent calls. - * - * @param mod The AltoClef mod instance. - * @param endPortalCenter The center position of the end portal. - * @return The number of filled portal frames. - */ - private int getFilledPortalFrames(AltoClef mod, BlockPos endPortalCenter) { - // If the end portal is found, return the constant count. - if (endPortalFound(mod, endPortalCenter)) { - return END_PORTAL_FRAME_COUNT; - } - - // Get all the frame blocks around the end portal center. - List frameBlocks = getFrameBlocks(endPortalCenter); - - // Check if all the frame blocks are loaded. - if (frameBlocks.stream().allMatch(blockPos -> mod.getChunkTracker().isChunkLoaded(blockPos))) { - // Calculate the sum of filled frames using a stream and mapToInt. - _cachedFilledPortalFrames = frameBlocks.stream() - .mapToInt(blockPos -> { - boolean isFilled = isEndPortalFrameFilled(mod, blockPos); - // Log whether the frame is filled or not. - if (isFilled) { - Debug.logInternal("Portal frame at " + blockPos + " is filled."); - } else { - Debug.logInternal("Portal frame at " + blockPos + " is not filled."); - } - return isFilled ? 1 : 0; - }) - .sum(); - } - - return _cachedFilledPortalFrames; - } - - /** - * Checks if a chest at the given block position can be looted as a portal chest. - * - * @param mod The instance of the mod. - * @param blockPos The block position of the chest to check. - * @return True if the chest can be looted as a portal chest, false otherwise. - */ - private boolean canBeLootablePortalChest(AltoClef mod, BlockPos blockPos) { - // Check if the block above is water or if the y-coordinate is below 50 - if (mod.getWorld().getBlockState(blockPos.up()).getBlock() == Blocks.WATER || - blockPos.getY() < 50) { - return false; - } - - // Define the minimum and maximum positions to scan for NETHERRACK blocks - BlockPos minPos = blockPos.add(-4, -2, -4); - BlockPos maxPos = blockPos.add(4, 2, 4); - - // Log the scanning region - Debug.logInternal("Scanning region from " + minPos + " to " + maxPos); - - // Scan the region defined by minPos and maxPos - for (BlockPos checkPos : WorldHelper.scanRegion(mod, minPos, maxPos)) { - // Check if the block at checkPos is NETHERRACK - if (mod.getWorld().getBlockState(checkPos).getBlock() == Blocks.NETHERRACK) { - return true; - } - } - - // Log that the blockPos is added to the list of not ruined portal chests - Debug.logInternal("Adding blockPos " + blockPos + " to the list of not ruined portal chests"); - - // Add the blockPos to the list of not ruined portal chests - _notRuinedPortalChests.add(blockPos); - - return false; - } - - private Task getEyesOfEnderTask(AltoClef mod, int targetEyes) { - if (mod.getEntityTracker().itemDropped(Items.ENDER_EYE)) { - setDebugState("Picking up Dropped Eyes"); - return new PickupDroppedItemTask(Items.ENDER_EYE, targetEyes); - } - - int eyeCount = mod.getItemStorage().getItemCount(Items.ENDER_EYE); - - int blazePowderCount = mod.getItemStorage().getItemCount(Items.BLAZE_POWDER); - int blazeRodCount = mod.getItemStorage().getItemCount(Items.BLAZE_ROD); - int blazeRodTarget = (int) Math.ceil(((double) targetEyes - eyeCount - blazePowderCount) / 2.0); - int enderPearlTarget = targetEyes - eyeCount; - boolean needsBlazeRods = blazeRodCount < blazeRodTarget; - boolean needsBlazePowder = eyeCount + blazePowderCount < targetEyes; - boolean needsEnderPearls = mod.getItemStorage().getItemCount(Items.ENDER_PEARL) < enderPearlTarget; - - if (needsBlazePowder && !needsBlazeRods) { - // We have enough blaze rods. - setDebugState("Crafting blaze powder"); - return TaskCatalogue.getItemTask(Items.BLAZE_POWDER, targetEyes - eyeCount); - } - - if (!needsBlazePowder && !needsEnderPearls) { - // Craft ender eyes - setDebugState("Crafting Ender Eyes"); - return TaskCatalogue.getItemTask(Items.ENDER_EYE, targetEyes); - } - - // Get blaze rods + pearls... - switch (WorldHelper.getCurrentDimension()) { - case OVERWORLD -> { - // If we happen to find beds... - if (needsBeds(mod) && anyBedsFound(mod)) { - setDebugState("A bed was found, getting it."); - if (_config.renderDistanceManipulation) { - if (!mod.getClientBaritone().getExploreProcess().isActive()) { - if (_timer1.elapsed()) { - MinecraftClient.getInstance().options.getViewDistance().setValue(2); - MinecraftClient.getInstance().options.getEntityDistanceScaling().setValue(0.5); - _timer1.reset(); - } - } - } - getBedTask = getBedTask(mod); - return getBedTask; - } else { - getBedTask = null; - } - if (shouldForce(mod, _logsTask)) { - setDebugState("Getting logs for later."); - return _logsTask; - } else { - _logsTask = null; - } - if (shouldForce(mod, _stoneGearTask)) { - setDebugState("Getting stone gear for later."); - return _stoneGearTask; - } else { - _stoneGearTask = null; - } - if (shouldForce(mod, _getPorkchopTask)) { - setDebugState("Getting pork chop just for fun."); - if (_config.renderDistanceManipulation) { - if (!mod.getClientBaritone().getExploreProcess().isActive()) { - MinecraftClient.getInstance().options.getViewDistance().setValue(32); - MinecraftClient.getInstance().options.getEntityDistanceScaling().setValue(5.0); - } - } - return _getPorkchopTask; - } else { - _getPorkchopTask = null; - } - if (shouldForce(mod, _starterGearTask)) { - setDebugState("Getting starter gear."); - return _starterGearTask; - } else { - _starterGearTask = null; - } - if (shouldForce(mod, _foodTask)) { - setDebugState("Getting food for ender eye journey."); - return _foodTask; - } else { - _foodTask = null; - } - if (shouldForce(mod, _smeltTask)) { - if (_config.renderDistanceManipulation) { - if (!mod.getClientBaritone().getExploreProcess().isActive()) { - if (_timer1.elapsed()) { - MinecraftClient.getInstance().options.getViewDistance().setValue(2); - MinecraftClient.getInstance().options.getEntityDistanceScaling().setValue(0.5); - _timer1.reset(); - } - } - } - return _smeltTask; - } else { - _smeltTask = null; - } - // Smelt remaining raw food - if (_config.alwaysCookRawFood) { - for (Item raw : ItemHelper.RAW_FOODS) { - if (mod.getItemStorage().hasItem(raw)) { - Optional cooked = ItemHelper.getCookedFood(raw); - if (cooked.isPresent()) { - int targetCount = mod.getItemStorage().getItemCount(cooked.get()) + mod.getItemStorage().getItemCount(raw); - setDebugState("Smelting raw food: " + ItemHelper.stripItemName(raw)); - _smeltTask = new SmeltInSmokerTask(new SmeltTarget(new ItemTarget(cooked.get(), targetCount), new ItemTarget(raw, targetCount))); - return _smeltTask; - } - } else { - _smeltTask = null; - } - } - } - // Make sure we have gear, then food. - if (shouldForce(mod, _lootTask)) { - setDebugState("Looting chest for goodies"); - return _lootTask; - } - if (shouldForce(mod, _shieldTask) && !StorageHelper.isArmorEquipped(mod, COLLECT_SHIELD)) { - setDebugState("Getting shield for defense purposes only."); - return _shieldTask; - } else { - _shieldTask = null; - } - if (shouldForce(mod, _ironGearTask) && !StorageHelper.isArmorEquipped(mod, COLLECT_IRON_ARMOR)) { - setDebugState("Getting iron gear before diamond gear for defense purposes only."); - return _ironGearTask; - } else { - _ironGearTask = null; - } - if (shouldForce(mod, _gearTask) && !StorageHelper.isArmorEquipped(mod, COLLECT_EYE_ARMOR)) { - setDebugState("Getting diamond gear for ender eye journey."); - return _gearTask; - } else { - _gearTask = null; - } - - boolean eyeGearSatisfied = StorageHelper.itemTargetsMet(mod, COLLECT_EYE_GEAR_MIN) && StorageHelper.isArmorEquippedAll(mod, COLLECT_EYE_ARMOR); - boolean ironGearSatisfied = StorageHelper.itemTargetsMet(mod, COLLECT_IRON_GEAR_MIN) && StorageHelper.isArmorEquippedAll(mod, COLLECT_IRON_ARMOR); - boolean shieldSatisfied = StorageHelper.isArmorEquipped(mod, COLLECT_SHIELD); - // Search for a better place - if (!mod.getItemStorage().hasItem(Items.PORKCHOP) && - !mod.getItemStorage().hasItem(Items.COOKED_PORKCHOP) && - !StorageHelper.itemTargetsMet(mod, IRON_GEAR_MIN) && !ironGearSatisfied && !eyeGearSatisfied) { - if (mod.getItemStorage().getItemCount(ItemHelper.LOG) < 12 && !StorageHelper.itemTargetsMet(mod, COLLECT_STONE_GEAR) && - !StorageHelper.itemTargetsMet(mod, IRON_GEAR_MIN) && !eyeGearSatisfied && - !ironGearSatisfied) { - _logsTask = TaskCatalogue.getItemTask("log", 18); - return _logsTask; - } else { - _logsTask = null; - } - if (!StorageHelper.itemTargetsMet(mod, COLLECT_STONE_GEAR) && - !StorageHelper.itemTargetsMet(mod, IRON_GEAR_MIN) && !eyeGearSatisfied && - !ironGearSatisfied) { - if (mod.getItemStorage().getItemCount(Items.STICK) < 7) { - _stoneGearTask = TaskCatalogue.getItemTask(Items.STICK, 15); - return _stoneGearTask; - } - _stoneGearTask = TaskCatalogue.getSquashedItemTask(COLLECT_STONE_GEAR); - return _stoneGearTask; - } else { - _stoneGearTask = null; - } - if (mod.getEntityTracker().entityFound(PigEntity.class) && (StorageHelper.itemTargetsMet(mod, - COLLECT_STONE_GEAR) || StorageHelper.itemTargetsMet(mod, IRON_GEAR_MIN) || - eyeGearSatisfied || ironGearSatisfied)) { - Predicate notBaby = entity -> entity instanceof LivingEntity livingEntity && !livingEntity.isBaby(); - _getPorkchopTask = new KillAndLootTask(PigEntity.class, notBaby, new ItemTarget(Items.PORKCHOP, 1)); - return _getPorkchopTask; - } else { - _getPorkchopTask = null; - } - setDebugState("Searching a better place to start with."); - if (_config.renderDistanceManipulation) { - if (!mod.getClientBaritone().getExploreProcess().isActive()) { - if (_timer1.elapsed()) { - MinecraftClient.getInstance().options.getViewDistance().setValue(32); - MinecraftClient.getInstance().options.getEntityDistanceScaling().setValue(5.0); - _timer1.reset(); - } - } - } - searchBiomeTask = new SearchWithinBiomeTask(BiomeKeys.PLAINS); - return searchBiomeTask; - } else { - searchBiomeTask = null; - } - // Then get one bed - if (!mod.getItemStorage().hasItem(ItemHelper.BED) && _config.sleepThroughNight) { - return _getOneBedTask; - } - // Then starter gear - if (!StorageHelper.itemTargetsMet(mod, IRON_GEAR_MIN) && !eyeGearSatisfied && - !ironGearSatisfied) { - _starterGearTask = TaskCatalogue.getSquashedItemTask(IRON_GEAR); - return _starterGearTask; - } else { - _starterGearTask = null; - } - // Then get food - if (StorageHelper.calculateInventoryFoodScore(mod) < _config.minFoodUnits) { - _foodTask = new CollectFoodTask(_config.foodUnits); - return _foodTask; - } else { - _foodTask = null; - } - // Then loot chest if there is any - if (_config.searchRuinedPortals) { - // Check for ruined portals - Optional chest = locateClosestUnopenedRuinedPortalChest(mod); - if (chest.isPresent()) { - _lootTask = new LootContainerTask(chest.get(), lootableItems(mod), _noCurseOfBinding); - return _lootTask; - } - } - if (_config.searchDesertTemples && StorageHelper.miningRequirementMetInventory(mod, MiningRequirement.WOOD)) { - // Check for desert temples - BlockPos temple = WorldHelper.getADesertTemple(mod); - if (temple != null) { - _lootTask = new LootDesertTempleTask(temple, lootableItems(mod)); - return _lootTask; - } - } - // Then get shield - if (_config.getShield && !shieldSatisfied && !mod.getFoodChain().needsToEat()) { - ItemTarget shield = new ItemTarget(COLLECT_SHIELD); - if (mod.getItemStorage().hasItem(shield) && !StorageHelper.isArmorEquipped(mod, COLLECT_SHIELD)) { - setDebugState("Equipping shield."); - return new EquipArmorTask(COLLECT_SHIELD); - } - _shieldTask = TaskCatalogue.getItemTask(shield); - return _shieldTask; - } else { - _shieldTask = null; - } - // Then get iron - if (_config.ironGearBeforeDiamondGear && !ironGearSatisfied && !eyeGearSatisfied && - !_isEquippingDiamondArmor) { - for (Item iron : COLLECT_IRON_ARMOR) { - if (mod.getItemStorage().hasItem(iron) && !StorageHelper.isArmorEquipped(mod, iron)) { - setDebugState("Equipping armor."); - return new EquipArmorTask(COLLECT_IRON_ARMOR); - } - } - _ironGearTask = TaskCatalogue.getSquashedItemTask(Stream.concat(Arrays.stream(COLLECT_IRON_ARMOR).filter(item -> !mod.getItemStorage().hasItem(item) && !StorageHelper.isArmorEquipped(mod, item)).map(item -> new ItemTarget(item, 1)), Arrays.stream(COLLECT_IRON_GEAR)).toArray(ItemTarget[]::new)); - return _ironGearTask; - } else { - _ironGearTask = null; - } - // Then get diamond - if (!eyeGearSatisfied) { - for (Item diamond : COLLECT_EYE_ARMOR) { - if (mod.getItemStorage().hasItem(diamond) && !StorageHelper.isArmorEquipped(mod, diamond)) { - setDebugState("Equipping armor."); - _isEquippingDiamondArmor = true; - return new EquipArmorTask(COLLECT_EYE_ARMOR); - } - } - _gearTask = TaskCatalogue.getSquashedItemTask(Stream.concat(Arrays.stream(COLLECT_EYE_ARMOR).filter(item -> !mod.getItemStorage().hasItem(item) && !StorageHelper.isArmorEquipped(mod, item)).map(item -> new ItemTarget(item, 1)), Arrays.stream(COLLECT_EYE_GEAR)).toArray(ItemTarget[]::new)); - return _gearTask; - } else { - _gearTask = null; - Item[] throwGearItems = {Items.STONE_SWORD, Items.STONE_PICKAXE, Items.IRON_SWORD, Items.IRON_PICKAXE}; - List ironArmors = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, - COLLECT_IRON_ARMOR); - List throwGears = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, - throwGearItems); - if (!StorageHelper.isBigCraftingOpen() && !StorageHelper.isFurnaceOpen() && - !StorageHelper.isSmokerOpen() && !StorageHelper.isBlastFurnaceOpen() && - (mod.getItemStorage().hasItem(Items.FLINT_AND_STEEL) || - mod.getItemStorage().hasItem(Items.FIRE_CHARGE))) { - if (!throwGears.isEmpty()) { - for (Slot throwGear : throwGears) { - if (Slot.isCursor(throwGear)) { - if (!mod.getControllerExtras().isBreakingBlock()) { - LookHelper.randomOrientation(mod); - } - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); - } else { - mod.getSlotHandler().clickSlot(throwGear, 0, SlotActionType.PICKUP); - } - } - } - if (!ironArmors.isEmpty()) { - for (Slot ironArmor : ironArmors) { - if (Slot.isCursor(ironArmor)) { - if (!mod.getControllerExtras().isBreakingBlock()) { - LookHelper.randomOrientation(mod); - } - mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); - } else { - mod.getSlotHandler().clickSlot(ironArmor, 0, SlotActionType.PICKUP); - } - } - } - } - } - if (needsBuildingMaterials(mod)) { - setDebugState("Collecting building materials."); - return _buildMaterialsTask; - } - // Then go to the nether. - setDebugState("Going to Nether"); - return _goToNetherTask; - } - case NETHER -> { - if (needsEnderPearls) { - setDebugState("Getting Ender Pearls"); - return getEnderPearlTask(mod, enderPearlTarget); - } - setDebugState("Getting Blaze Rods"); - return getBlazeRodsTask(mod, blazeRodTarget); - } - case END -> throw new UnsupportedOperationException("You're in the end. Don't collect eyes here."); - } - return null; - } -} diff --git a/src/main/java/adris/altoclef/tasks/speedrun/OneCycleTask.java b/src/main/java/adris/altoclef/tasks/speedrun/OneCycleTask.java new file mode 100644 index 00000000..8c58d198 --- /dev/null +++ b/src/main/java/adris/altoclef/tasks/speedrun/OneCycleTask.java @@ -0,0 +1,174 @@ +package adris.altoclef.tasks.speedrun; + +import adris.altoclef.AltoClef; +import adris.altoclef.tasks.movement.GetToBlockTask; +import adris.altoclef.tasksystem.Task; +import adris.altoclef.util.helpers.ItemHelper; +import adris.altoclef.util.helpers.LookHelper; +import adris.altoclef.util.helpers.WorldHelper; +import adris.altoclef.util.time.TimerGame; +import baritone.api.utils.input.Input; +import net.minecraft.block.Blocks; +import net.minecraft.entity.boss.dragon.EnderDragonEntity; +import net.minecraft.entity.boss.dragon.EnderDragonPart; +import net.minecraft.item.Items; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; + +import java.util.List; + +public class OneCycleTask extends Task { + + TimerGame placeBedTimer = new TimerGame(0.6); + TimerGame waiTimer = new TimerGame(0.3); + double prevDist = 100; + + + + @Override + protected Task onTick(AltoClef mod) { + mod.getFoodChain().shouldStop(true); + mod.getSlotHandler().forceEquipItemToOffhand(Items.AIR); + + if (mod.getInputControls().isHeldDown(Input.SNEAK)) { + mod.getInputControls().release(Input.SNEAK); + } + + List dragons = mod.getEntityTracker().getTrackedEntities(EnderDragonEntity.class); + if (dragons.size() != 1) { + mod.log("No dragon? :("); + } + + for (EnderDragonEntity dragon : dragons) { + + BlockPos endPortalTop = KillEnderDragonWithBedsTask.locateExitPortalTop(mod).up(); + BlockPos obsidian = null; + Direction dir = null; + + for (Direction direction : new Direction[]{Direction.EAST, Direction.WEST, Direction.NORTH, Direction.SOUTH}) { + if (mod.getWorld().getBlockState(endPortalTop.offset(direction)).getBlock().equals(Blocks.OBSIDIAN)) { + obsidian = endPortalTop.offset(direction); + dir = direction.getOpposite(); + break; + } + } + + if (dir == null) { + mod.log("no obisidan? :("); + return null; + } + + Direction offsetDir = dir.getAxis() == Direction.Axis.X ? Direction.SOUTH : Direction.WEST; + BlockPos targetBlock = endPortalTop.down(3).offset(offsetDir, 3).offset(dir); + + double d = distanceIgnoreY(WorldHelper.toVec3d(targetBlock), mod.getPlayer().getPos()); + if (d > 0.7) { + mod.log(d + ""); + return new GetToBlockTask(targetBlock); + } + LookHelper.lookAt(mod,obsidian,dir); + + + BlockPos bedHead = WorldHelper.getBedHead(mod, endPortalTop); + + BlockPos bedTargetPosition = endPortalTop.up(); + mod.getSlotHandler().forceEquipItem(ItemHelper.BED); + + if (bedHead == null) { + if (placeBedTimer.elapsed() && Math.abs(dragon.getY() - endPortalTop.getY()) < 10) { + mod.getInputControls().tryPress(Input.CLICK_RIGHT); + waiTimer.reset(); + } + /* if (mod.getSlotHandler().forceEquipItem(ItemHelper.BED, true)) { + for (Direction dir : List.of(Direction.NORTH,Direction.SOUTH,Direction.EAST,Direction.WEST)) { + if (mod.getWorld().getBlockState(endPortalTop.add(dir.getVector())).getBlock().equals(Blocks.OBSIDIAN)) { + LookHelper.lookAt(mod, bedTargetPosition.down(), dir, true); + + mod.getInputControls().tryPress(Input.CLICK_RIGHT); + } + } + + }*/ + continue; + } + if (!waiTimer.elapsed()) { + return null; + } + + + Vec3d dragonHeadPos = dragon.head.getBoundingBox().getCenter(); // dragon.head.getPos(); + Vec3d bedHeadPos = WorldHelper.toVec3d(bedHead); + + double dist = dragonHeadPos.distanceTo(bedHeadPos); + double distXZ = distanceIgnoreY(dragonHeadPos, bedHeadPos); + + EnderDragonPart body = dragon.getBodyParts()[2]; + + double destroyDistance = Math.abs(body.getBoundingBox().getMin(Direction.Axis.Y) - bedHeadPos.getY()); + boolean tooClose = destroyDistance < 1.1; + boolean skip = destroyDistance > 3 && dist > 4.5 && distXZ > 2.5; + + mod.log(destroyDistance + " : " + dist + " : " + distXZ); + // double dist = distanceIgnoreY(dragonHeadPos,WorldHelper.toVec3d(bedHead)); + + if ((dist < 1.5 || (prevDist < distXZ && destroyDistance < 4 && prevDist < 2.9)) || (destroyDistance < 2 && dist < 4) + || (destroyDistance < 1.7 && dist < 4.5) || tooClose || (destroyDistance < 2.4 && distXZ < 3.7) || (destroyDistance < 3.5 && distXZ < 2.4)) { + + if (!skip) { + mod.getInputControls().tryPress(Input.CLICK_RIGHT); + placeBedTimer.reset(); + } + } + + prevDist = distXZ; + + double yDist = dragonHeadPos.getY() - bedHead.getY(); + // Debug.logMessage(dist+""); + + /* if ((dist < 0.9 && yDist < 3) || yDist<2) { + mod.getInputControls().tryPress(Input.CLICK_RIGHT); + + }*/ + /* if (prevDist < dist && yDist < 4) { + mod.getInputControls().tryPress(Input.CLICK_RIGHT); + } + + prevDist = dist;*/ + + } + + return null; + } + + public double distanceIgnoreY(Vec3d vec, Vec3d vec1) { + double d = vec.x - vec1.x; + double f = vec.z - vec1.z; + return Math.sqrt(d * d + f * f); + } + + @Override + protected void onStop(AltoClef mod, Task interruptTask) { + + } + + @Override + public boolean isFinished(AltoClef mod) { + return mod.getEntityTracker().getTrackedEntities(EnderDragonEntity.class).isEmpty(); + } + + @Override + protected void onStart(AltoClef mod) { + + } + + @Override + protected boolean isEqual(Task other) { + return false; + } + + @Override + protected String toDebugString() { + return "One cycling bby"; + } +} diff --git a/src/main/java/adris/altoclef/tasks/speedrun/WaitForDragonAndPearlTask.java b/src/main/java/adris/altoclef/tasks/speedrun/WaitForDragonAndPearlTask.java index 602b95e0..1270c2dc 100644 --- a/src/main/java/adris/altoclef/tasks/speedrun/WaitForDragonAndPearlTask.java +++ b/src/main/java/adris/altoclef/tasks/speedrun/WaitForDragonAndPearlTask.java @@ -79,9 +79,9 @@ protected void onStart(AltoClef mod) { protected Task onTick(AltoClef mod) { Optional enderMen = mod.getEntityTracker().getClosestEntity(EndermanEntity.class); if (enderMen.isPresent() && (enderMen.get() instanceof EndermanEntity endermanEntity) && - endermanEntity.isAngry()) { + endermanEntity.getTarget()==mod.getPlayer()) { setDebugState("Killing angry endermen"); - Predicate angry = entity -> endermanEntity.isAngry(); + Predicate angry = entity -> endermanEntity.getTarget()==mod.getPlayer(); return new KillEntitiesTask(angry, enderMen.get().getClass()); } if (_throwPearlTask != null && _throwPearlTask.isActive() && !_throwPearlTask.isFinished(mod)) { @@ -212,7 +212,7 @@ protected Task onTick(AltoClef mod) { } private boolean isFireballDangerous(AltoClef mod, Optional fireball) { - if (!fireball.isPresent()) + if (fireball.isEmpty()) return false; boolean fireballTooClose = fireball.get().isInRange(mod.getPlayer(), DRAGON_FIREBALL_TOO_CLOSE_RANGE); diff --git a/src/main/java/adris/altoclef/tasks/speedrun/beatgame/BeatMinecraftTask.java b/src/main/java/adris/altoclef/tasks/speedrun/beatgame/BeatMinecraftTask.java new file mode 100644 index 00000000..5ac2d8d8 --- /dev/null +++ b/src/main/java/adris/altoclef/tasks/speedrun/beatgame/BeatMinecraftTask.java @@ -0,0 +1,2633 @@ +package adris.altoclef.tasks.speedrun.beatgame; + +import adris.altoclef.AltoClef; +import adris.altoclef.Debug; +import adris.altoclef.TaskCatalogue; +import adris.altoclef.commands.BlockScanner; +import adris.altoclef.commands.SetGammaCommand; +import adris.altoclef.tasks.DoToClosestBlockTask; +import adris.altoclef.tasks.GetRidOfExtraWaterBucketTask; +import adris.altoclef.tasks.InteractWithBlockTask; +import adris.altoclef.tasks.SafeNetherPortalTask; +import adris.altoclef.tasks.construction.DestroyBlockTask; +import adris.altoclef.tasks.construction.PlaceBlockNearbyTask; +import adris.altoclef.tasks.construction.PlaceObsidianBucketTask; +import adris.altoclef.tasks.container.DoStuffInContainerTask; +import adris.altoclef.tasks.container.LootContainerTask; +import adris.altoclef.tasks.container.SmeltInFurnaceTask; +import adris.altoclef.tasks.container.SmeltInSmokerTask; +import adris.altoclef.tasks.misc.EquipArmorTask; +import adris.altoclef.tasks.misc.PlaceBedAndSetSpawnTask; +import adris.altoclef.tasks.misc.SleepThroughNightTask; +import adris.altoclef.tasks.movement.*; +import adris.altoclef.tasks.resources.*; +import adris.altoclef.tasks.speedrun.*; +import adris.altoclef.tasksystem.Task; +import adris.altoclef.trackers.EntityTracker; +import adris.altoclef.trackers.storage.ItemStorageTracker; +import adris.altoclef.util.Dimension; +import adris.altoclef.util.ItemTarget; +import adris.altoclef.util.MiningRequirement; +import adris.altoclef.util.SmeltTarget; +import adris.altoclef.util.helpers.*; +import adris.altoclef.util.slots.Slot; +import adris.altoclef.util.time.TimerGame; +import baritone.api.utils.input.Input; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.EndPortalFrameBlock; +import net.minecraft.client.gui.screen.CreditsScreen; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.entity.Entity; +import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.mob.*; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.*; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; +import net.minecraft.screen.GenericContainerScreenHandler; +import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.util.collection.DefaultedList; +import net.minecraft.util.math.*; +import org.apache.commons.lang3.ArrayUtils; + +import java.util.*; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import static adris.altoclef.tasks.resources.CollectMeatTask.COOKABLE_FOODS; +import static net.minecraft.client.MinecraftClient.getInstance; + + +public class BeatMinecraftTask extends Task { + private static final Block[] TRACK_BLOCKS = new Block[]{ + Blocks.FURNACE, + Blocks.SMOKER, + Blocks.END_PORTAL_FRAME, + Blocks.END_PORTAL, + + Blocks.DIAMOND_ORE, + Blocks.DEEPSLATE_DIAMOND_ORE, + + Blocks.CRAFTING_TABLE, // For pearl trading + gold crafting + Blocks.CHEST, // For ruined portals + Blocks.SPAWNER, // For silverfish, + Blocks.STONE_PRESSURE_PLATE // For desert temples + }; + private static final Item[] COLLECT_EYE_ARMOR = new Item[]{ + Items.DIAMOND_CHESTPLATE, + Items.DIAMOND_LEGGINGS, + Items.DIAMOND_BOOTS + }; + + private static final Item[] COLLECT_IRON_ARMOR = ItemHelper.IRON_ARMORS; + private static final Item[] COLLECT_EYE_ARMOR_END = ItemHelper.DIAMOND_ARMORS; + + + private static final ItemTarget[] COLLECT_EYE_GEAR_MIN = combine( + toItemTargets(Items.DIAMOND_SWORD), + toItemTargets(Items.DIAMOND_PICKAXE) + ); + + private static final int END_PORTAL_FRAME_COUNT = 12; + private static final double END_PORTAL_BED_SPAWN_RANGE = 8; + + // We don't want curse of binding + private static final Predicate noCurseOfBinding = stack -> { + for (NbtElement elm : stack.getEnchantments()) { + NbtCompound comp = (NbtCompound) elm; + if (comp.getString("id").equals("minecraft:binding_curse")) { + return false; + } + } + return true; + }; + + //dont even pick up these items + private static final Item[] uselessItems = new Item[]{ + //sapling + Items.OAK_SAPLING, + Items.SPRUCE_SAPLING, + Items.BIRCH_SAPLING, + Items.JUNGLE_SAPLING, + Items.ACACIA_SAPLING, + Items.DARK_OAK_SAPLING, + Items.MANGROVE_PROPAGULE, + Items.CHERRY_SAPLING, + + // seeds + Items.BEETROOT_SEEDS, + Items.MELON_SEEDS, + Items.PUMPKIN_SEEDS, + Items.WHEAT_SEEDS, + Items.TORCHFLOWER_SEEDS, + + // random jung, might add more things in the future + Items.FEATHER, + Items.EGG, + Items.BONE, + Items.LEATHER, + Items.RAW_COPPER, + Items.WARPED_ROOTS, + Items.GUNPOWDER, + Items.MOSSY_COBBLESTONE, + Items.SPRUCE_TRAPDOOR, + Items.SANDSTONE_STAIRS, + Items.STONE_BRICKS, + Items.COARSE_DIRT, + Items.SMOOTH_STONE, + Items.FLOWER_POT, + Items.MANGROVE_ROOTS, + Items.POPPY, + Items.MUDDY_MANGROVE_ROOTS, + Items.SPIDER_EYE, + Items.PINK_TULIP, + + Items.SPRUCE_STAIRS, + Items.OAK_STAIRS, + + Items.LAPIS_LAZULI, + Items.SUNFLOWER, + Items.REDSTONE, + Items.CRIMSON_ROOTS, + Items.OAK_DOOR, + + Items.STRING, + Items.WHITE_TERRACOTTA, + Items.RED_TERRACOTTA, + + Items.MOSS_BLOCK, + Items.MOSS_CARPET, + Items.BOW, + + Items.EMERALD, + Items.GOLD_NUGGET, + Items.IRON_NUGGET, + Items.GRASS, + Items.COBBLESTONE_WALL, + Items.COBBLESTONE_STAIRS, + Items.COBBLESTONE_SLAB, + Items.CLAY_BALL, + Items.DANDELION, + Items.SUGAR_CANE, + Items.CHEST, + Items.RAIL, + Items.CALCITE, + Items.AMETHYST_BLOCK, + Items.AMETHYST_CLUSTER, + Items.AMETHYST_SHARD, + Items.BUDDING_AMETHYST, + Items.SMOOTH_BASALT, + Items.AZURE_BLUET, + + Items.ACACIA_DOOR, + Items.JUNGLE_DOOR, + Items.CHISELED_SANDSTONE, + Items.CACTUS, + Items.MUD, + Items.MANGROVE_LEAVES, + Items.SMOOTH_SANDSTONE_SLAB, + Items.SANDSTONE_WALL, + Items.TNT, + Items.PRISMARINE_CRYSTALS, + Items.SNOWBALL, + Items.DRIPSTONE_BLOCK, + Items.POINTED_DRIPSTONE, + Items.ARROW, + Items.YELLOW_TERRACOTTA, + Items.TUFF, + Items.SPRUCE_STAIRS, + Items.SPRUCE_DOOR, + Items.SPRUCE_FENCE, + Items.SPRUCE_FENCE_GATE, + Items.ORANGE_TERRACOTTA, + Items.HEART_OF_THE_SEA, + Items.POTION, + Items.FLOWERING_AZALEA, + Items.COPPER_INGOT, + Items.ACACIA_SLAB, + + // nether stuff + Items.SOUL_SAND, + Items.SOUL_SOIL, + Items.NETHER_BRICK, + Items.NETHER_BRICK_FENCE, + }; + private static BeatMinecraftConfig config; + private static GoToStrongholdPortalTask locateStrongholdTask; + private static boolean openingEndPortal = false; + + static { + ConfigHelper.loadConfig("configs/beat_minecraft.json", BeatMinecraftConfig::new, BeatMinecraftConfig.class, newConfig -> config = newConfig); + } + + private final HashMap cachedEndItemDrops = new HashMap<>(); + // For some reason, after death there's a frame where the game thinks there are NO items in the end. + private final TimerGame cachedEndItemNothingWaitTime = new TimerGame(10); + private final Task buildMaterialsTask; + private final PlaceBedAndSetSpawnTask setBedSpawnTask = new PlaceBedAndSetSpawnTask(); + private final Task getOneBedTask = TaskCatalogue.getItemTask("bed", 1); + private final Task sleepThroughNightTask = new SleepThroughNightTask(); + private final Task killDragonBedStratsTask = new KillEnderDragonWithBedsTask(new WaitForDragonAndPearlTask()); + // End specific dragon breath avoidance + private final DragonBreathTracker dragonBreathTracker = new DragonBreathTracker(); + private final TimerGame timer1 = new TimerGame(5); + private final TimerGame timer2 = new TimerGame(35); + private final TimerGame timer3 = new TimerGame(60); + private final List gatherResources = new LinkedList<>(); + private final TimerGame changedTaskTimer = new TimerGame(3); + private final TimerGame forcedTaskTimer = new TimerGame(10); + private final List blacklistedChests = new LinkedList<>(); + private final TimerGame searchBiomeTask = new TimerGame(20); + private final TimerGame waterPlacedTimer = new TimerGame(1.5); + private final TimerGame fortressTimer = new TimerGame(20); + private GatherResource lastGather = null; + private Task lastTask = null; + private boolean pickupFurnace = false; + private boolean pickupSmoker = false; + private boolean pickupCrafting = false; + private Task rePickupTask = null; + private Task searchTask = null; + private boolean hasRods = false; + private boolean gotToBiome = false; + private GetRidOfExtraWaterBucketTask getRidOfExtraWaterBucketTask = null; + private int repeated = 0; + private boolean gettingPearls = false; + private SafeNetherPortalTask safeNetherPortalTask; + private boolean escaped = false; + private boolean gotToFortress = false; + private GetWithinRangeOfBlockTask cachedFortressTask = null; + private boolean resetFortressTask = false; + private BlockPos prevPos = null; + private Task goToNetherTask = new DefaultGoToDimensionTask(Dimension.NETHER); // To keep the portal build cache. + private boolean dragonIsDead = false; + private BlockPos endPortalCenterLocation; + private boolean ranStrongholdLocator; + private boolean endPortalOpened; + private BlockPos bedSpawnLocation; + private int cachedFilledPortalFrames = 0; + // Controls whether we CAN walk on the end portal. + private boolean enterindEndPortal = false; + private Task lootTask; + private boolean collectingEyes; + private boolean escapingDragonsBreath = false; + private Task getBedTask; + + private record TaskChange(GatherResource original, GatherResource interrupt, BlockPos pos){ + } + + private List taskChanges = new ArrayList<>(); + + public BeatMinecraftTask(AltoClef mod) { + locateStrongholdTask = new GoToStrongholdPortalTask(config.targetEyes); + buildMaterialsTask = new GetBuildingMaterialsTask(config.buildMaterialCount); + + gatherResources.add(new GatherResource(4, 10, + getBlockCalculator(mod, ItemHelper.itemsToBlocks(ItemHelper.LOG), 3) + , item -> mod.getItemStorage().hasItem(Items.STONE_AXE, Items.IRON_AXE, Items.GOLDEN_AXE, Items.DIAMOND_AXE) && + mod.getItemStorage().getItemCount(ItemHelper.LOG) < 5, Optional.of("log"), ItemHelper.LOG)); + + addOreMiningTasks(mod); + addCollectFoodTask(mod); + + // gear + addStoneToolsTasks(mod); + addPickaxeTasks(mod); + addDiamondArmorTasks(mod); + addLootChestsTasks(mod); + + gatherResources.add(new GatherResource(0, 1, + getBlockCalculator(mod, new Block[]{Blocks.GRAVEL}, 50) + , item -> mod.getItemStorage().hasItem(Items.STONE_SHOVEL) && !mod.getItemStorage().hasItem(Items.FLINT_AND_STEEL), Items.FLINT)); + + gatherResources.add(new GatherResource(getTargetBeds(mod), getTargetBeds(mod), + getBlockCalculator(mod, ItemHelper.itemsToBlocks(ItemHelper.BED), 45) + , item -> true, Optional.of("bed"), ItemHelper.BED)); + + gatherResources.add(new GatherResource(1, 1, (items, count, minCount, maxCount) -> { + if (hasItem(mod, Items.SHIELD) || mod.getItemStorage().hasItemInOffhand(Items.SHIELD) || mod.getItemStorage().hasItem(Items.SHIELD)) + return Double.NEGATIVE_INFINITY; + + return 200; + }, item -> mod.getItemStorage().hasItem(Items.IRON_INGOT), Items.SHIELD).withBypassForceCooldown(true) + .withNeedsCraftingOnStart((m) -> mod.getItemStorage().getItemCount(ItemHelper.PLANKS) + mod.getItemStorage().getItemCount(ItemHelper.LOG) * 4 >= 6)); + + + gatherResources.add(new GatherResource(2, 2, (items, count, minCount, maxCount) -> { + if (mod.getItemStorage().getItemCount(Items.BUCKET) >= 2) + return Double.NEGATIVE_INFINITY; + + return 300; + }, item -> mod.getItemStorage().getItemCount(Items.IRON_INGOT) >= 6, Items.BUCKET).withNeedsCraftingOnStart(m -> true)); + + gatherResources.add(new GatherResource(1, 1, (items, count, minCount, maxCount) -> { + if (mod.getItemStorage().hasItem(Items.FLINT_AND_STEEL) || mod.getItemStorage().getItemCount(Items.FIRE_CHARGE) >= 2) + return Double.NEGATIVE_INFINITY; + + return 100; + }, item -> mod.getItemStorage().hasItem(Items.IRON_INGOT) && mod.getItemStorage().hasItem(Items.FLINT), Items.FLINT_AND_STEEL).withNeedsCraftingOnStart((m) -> true)); + + gatherResources.add(new GatherResource(1, 1, (items, count, minCount, maxCount) -> { + if (mod.getItemStorage().hasItem(Items.DIAMOND_SWORD) || !mod.getItemStorage().hasItem(Items.DIAMOND_PICKAXE)) + return Double.NEGATIVE_INFINITY; + + return 330; + }, item -> mod.getItemStorage().getItemCount(Items.DIAMOND) >= 2, Items.DIAMOND_SWORD) + .withNeedsCraftingOnStart(m -> mod.getItemStorage().hasItem(Items.STICK) || mod.getItemStorage().hasItem(ItemHelper.LOG) || mod.getItemStorage().getItemCount(ItemHelper.PLANKS) >= 2)); + + gatherResources.add(new GatherResource(1, 1, (items, count, minCount, maxCount) -> { + if (mod.getItemStorage().hasItem(Items.GOLDEN_HELMET)) return Double.NEGATIVE_INFINITY; + + return 400; + }, item -> mod.getItemStorage().getItemCount(Items.GOLD_INGOT) >= 5, Items.GOLDEN_HELMET).withNeedsCraftingOnStart((m) -> true)); + + gatherResources.add(new GatherResource(999, 999_999, (items, count, minCount, maxCount) -> { + Optional pos = mod.getBlockScanner().getNearestBlock(ItemHelper.itemsToBlocks(ItemHelper.BED)); + if (pos.isPresent() && pos.get().isWithinDistance(mod.getPlayer().getPos(), 30)) return 1_000_000; + + return Double.NEGATIVE_INFINITY; + }, item -> WorldHelper.canSleep(), Optional.of(new SleepThroughNightTask()), Items.BEDROCK).withDescription("sleeping in nearby bed")); + + GatherResource resource = new GatherResource(1, 1, (items, count, minCount, maxCount) -> { + if (mod.getItemStorage().hasItem(Items.WATER_BUCKET) || hasItem(mod, Items.WATER_BUCKET)) + return Double.NEGATIVE_INFINITY; + + Optional optionalPos = mod.getBlockScanner().getNearestBlock(Blocks.WATER); + if (optionalPos.isEmpty()) return Double.NEGATIVE_INFINITY; + + double distance = Math.sqrt(optionalPos.get().getSquaredDistance(mod.getPlayer().getPos())); + if (distance > 55) return Double.NEGATIVE_INFINITY; + + return 10 / distance * 77.3; + }, item -> mod.getItemStorage().hasItem(Items.BUCKET), Items.WATER_BUCKET).withBypassForceCooldown(true); + gatherResources.add(resource); + + addSmeltTasks(mod); + addCookFoodTasks(mod); + } + + /** + * Returns the BeatMinecraftConfig instance. + * If it is not already initialized, it initializes and returns a new instance. + * + * @return the BeatMinecraftConfig instance + */ + public static BeatMinecraftConfig getConfig() { + if (config == null) { + Debug.logInternal("Initializing BeatMinecraftConfig"); + config = new BeatMinecraftConfig(); + } + return config; + } + + /** + * Retrieves the frame blocks surrounding the end portal center. + * + * @param endPortalCenter the center position of the end portal + * @return a list of block positions representing the frame blocks + */ + private static List getFrameBlocks(BlockPos endPortalCenter) { + List frameBlocks = new ArrayList<>(); + + if (endPortalCenter != null) { + int[][] frameOffsets = { + {2, 0, 1}, + {2, 0, 0}, + {2, 0, -1}, + {-2, 0, 1}, + {-2, 0, 0}, + {-2, 0, -1}, + {1, 0, 2}, + {0, 0, 2}, + {-1, 0, 2}, + {1, 0, -2}, + {0, 0, -2}, + {-1, 0, -2} + }; + + for (int[] offset : frameOffsets) { + BlockPos frameBlock = endPortalCenter.add(offset[0], offset[1], offset[2]); + + frameBlocks.add(frameBlock); + } + } + + Debug.logInternal("Frame blocks: " + frameBlocks); + + return frameBlocks; + } + + /** + * Converts an array of `Item` objects into an array of `ItemTarget` objects. + * + * @param items the array of `Item` objects to convert + * @return the array of `ItemTarget` objects + */ + public static ItemTarget[] toItemTargets(Item... items) { + // Use the `Arrays.stream()` method to create a stream of `Item` objects + return Arrays.stream(items) + // Use the `map()` method to convert each `Item` object into an `ItemTarget` object + .map(item -> { + // Add logging statement to print the item being converted + Debug.logInternal("Converting item: " + item); + return new ItemTarget(item); + }) + // Use the `toArray()` method to convert the stream of `ItemTarget` objects into an array + .toArray(ItemTarget[]::new); + } + + + /** + * Combines multiple arrays of ItemTarget objects into a single array. + * + * @param targets The arrays of ItemTarget objects to combine. + * @return The combined array of ItemTarget objects. + */ + private static ItemTarget[] combine(ItemTarget[]... targets) { + List combinedTargets = new ArrayList<>(); + + for (ItemTarget[] targetArray : targets) { + combinedTargets.addAll(Arrays.asList(targetArray)); + } + + Debug.logInternal("Combined Targets: " + combinedTargets); + + ItemTarget[] combinedArray = combinedTargets.toArray(new ItemTarget[0]); + Debug.logInternal("Combined Array: " + Arrays.toString(combinedArray)); + + return combinedArray; + } + + /** + * Checks if the End Portal Frame at the given position is filled with an Eye of Ender. + * + * @param mod The AltoClef mod instance. + * @param pos The position of the End Portal Frame. + * @return True if the End Portal Frame is filled, false otherwise. + */ + private static boolean isEndPortalFrameFilled(AltoClef mod, BlockPos pos) { + if (!mod.getChunkTracker().isChunkLoaded(pos)) { + Debug.logInternal("Chunk is not loaded"); + return false; + } + + + BlockState blockState = mod.getWorld().getBlockState(pos); + if (blockState.getBlock() != Blocks.END_PORTAL_FRAME) { + Debug.logInternal("Block is not an End Portal Frame"); + return false; + } + + boolean isFilled = blockState.get(EndPortalFrameBlock.EYE); + + Debug.logInternal("End Portal Frame is " + (isFilled ? "filled" : "not filled")); + return isFilled; + } + + /** + * Checks if a task is running eg. task is active and not finished. + * + * @param mod The AltoClef mod. + * @param task The task to check. + * @return True if the task is running, false otherwise. + */ + public static boolean isTaskRunning(AltoClef mod, Task task) { + if (task == null) { + Debug.logInternal("Task is null"); + return false; + } + + boolean taskActive = task.isActive(); + boolean taskFinished = task.isFinished(mod); + + Debug.logInternal("Task is not null"); + Debug.logInternal("Task is " + (taskActive ? "active" : "not active")); + Debug.logInternal("Task is " + (taskFinished ? "finished" : "not finished")); + + return taskActive && !taskFinished; + } + + public static void throwAwayItems(AltoClef mod, Item... items) { + throwAwaySlots(mod, mod.getItemStorage().getSlotsWithItemPlayerInventory(false, items)); + } + + public static void throwAwaySlots(AltoClef mod, List slots) { + for (Slot slot : slots) { + if (Slot.isCursor(slot)) { + /* if (!mod.getControllerExtras().isBreakingBlock()) { + LookHelper.randomOrientation(mod); + }*/ + mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); + } else { + mod.getSlotHandler().clickSlot(slot, 0, SlotActionType.PICKUP); + } + } + } + + //TODO add some checks for how many food we already have, how hungry we are etc... + private void addCookFoodTasks(AltoClef mod) { + GatherResource cookFoodTask = new GatherResource(999, 999_999, null, + (item) -> StorageHelper.miningRequirementMet(mod, MiningRequirement.STONE), + ItemHelper.COOKED_FOODS).withShouldForce(true).withCanCache(false); + + cookFoodTask.withPriorityCalculator((items, c, minCount, maxCount) -> { + int rawFoodCount = mod.getItemStorage().getItemCount(ItemHelper.RAW_FOODS); + int readyFoodCount = mod.getItemStorage().getItemCount(ItemHelper.COOKED_FOODS) + mod.getItemStorage().getItemCount(Items.BREAD); + + double priority = rawFoodCount >= 8 ? 450 : rawFoodCount * 25; + + if (lastTask instanceof SmeltInSmokerTask) { + priority = Double.POSITIVE_INFINITY; + } + + if (readyFoodCount > 5 && priority < Double.POSITIVE_INFINITY) { + // always smelt the food at some point + // smelt all at once to waste as little coal as possible + priority = 0.01; + } + + + for (CollectMeatTask.CookableFoodTarget cookable : COOKABLE_FOODS) { + int rawCount = mod.getItemStorage().getItemCount(cookable.getRaw()); + if (rawCount == 0) continue; + + int toSmelt = rawCount + mod.getItemStorage().getItemCount(cookable.getCooked()); + + SmeltTarget target = new SmeltTarget(new ItemTarget(cookable.cookedFood, toSmelt), new ItemTarget(cookable.rawFood, rawCount)); + cookFoodTask.data = Optional.of(new SmeltInSmokerTask(target)); + + return priority; + } + + return Double.NEGATIVE_INFINITY; + }); + gatherResources.add(cookFoodTask); + } + + private void addSmeltTasks(AltoClef mod) { + GatherResource smeltIronTask = new GatherResource(999, 999_999, null, + item -> mod.getItemStorage().hasItem(Items.RAW_IRON), Items.IRON_INGOT).withShouldForce(true); + + smeltIronTask.withPriorityCalculator((items, c, minCount, maxCount) -> { + + int smeltedIronCount = getCountWithCraftedFromOre(mod, Items.RAW_IRON) - mod.getItemStorage().getItemCount(Items.RAW_IRON); + if (smeltedIronCount + mod.getItemStorage().getItemCount(Items.RAW_IRON) < 3) + return Double.NEGATIVE_INFINITY; + + //FIXME hardcoded value (11) for iron count + if (getCountWithCraftedFromOre(mod, Items.RAW_IRON) - mod.getItemStorage().getItemCount(Items.RAW_IRON) >= 11) { + return Double.NEGATIVE_INFINITY; + } + + int count = mod.getItemStorage().getItemCount(Items.RAW_IRON); + int includedCount = count + mod.getItemStorage().getItemCount(Items.IRON_INGOT); + + //exactly for one coal + if (count >= 8) { + includedCount = 8 + mod.getItemStorage().getItemCount(Items.IRON_INGOT); + smeltIronTask.data = Optional.of(new SmeltInFurnaceTask(new SmeltTarget(new ItemTarget(Items.IRON_INGOT, includedCount), new ItemTarget(Items.RAW_IRON, includedCount)))); + return 450; + } + + smeltIronTask.data = Optional.of(new SmeltInFurnaceTask(new SmeltTarget(new ItemTarget(Items.IRON_INGOT, includedCount), new ItemTarget(Items.RAW_IRON, includedCount)))); + + //for getting iron pickaxe + if (!mod.getItemStorage().hasItem(Items.IRON_PICKAXE, Items.DIAMOND_PICKAXE) && count >= 3) { + return 460; + } + + // if we have pickaxe, shield and one bucket dont smelt until we have 4 iron (3 for bucket, 1 for flint and steel) + //FIXME hardcoded value (11; 4) + hardcoded items + if (hasItem(mod, Items.SHIELD) && mod.getItemStorage().hasItem(Items.BUCKET, Items.WATER_BUCKET) && count < 4) + return Double.NEGATIVE_INFINITY; + + // if we have all the items we need, do not smelt any more iron + if (hasItem(mod, Items.SHIELD) && mod.getItemStorage().hasItem(Items.IRON_PICKAXE, Items.DIAMOND_PICKAXE) + && mod.getItemStorage().getItemCount(Items.BUCKET, Items.WATER_BUCKET, Items.LAVA_BUCKET) >= 2 && mod.getItemStorage().hasItem(Items.FLINT_AND_STEEL)) + return Double.NEGATIVE_INFINITY; + + return count * 25; + }); + gatherResources.add(smeltIronTask); + + //FIXME hardcoded number of gold ingots - 5 + GatherResource smeltGoldTask = new GatherResource(5, 5, (items, count, minCount, maxCount) -> 140, item -> mod.getItemStorage().getItemCount(Items.RAW_GOLD, Items.GOLD_INGOT) >= 5, + Optional.of(new SmeltInFurnaceTask(new SmeltTarget(new ItemTarget(Items.GOLD_INGOT, 5), + new ItemTarget(Items.RAW_GOLD, 5)))), + Items.GOLD_INGOT).withShouldForce(true); + + gatherResources.add(smeltGoldTask); + + } + + private GatherResource.PriorityCalculator getBlockCalculator(AltoClef mod, Block[] blocks, float multiplier) { + return (items, count, minCount, maxCount) -> { + double closestDist = Integer.MAX_VALUE; + + Optional optionalDroppedItem = mod.getEntityTracker().getClosestItemDrop(items); + + if (optionalDroppedItem.isPresent()) { + closestDist = optionalDroppedItem.get().distanceTo(mod.getPlayer()); + } + + for (Block block : blocks) { + Optional pos = mod.getBlockScanner().getNearestBlock(block); + if (pos.isPresent()) { + BlockPos bp = pos.get(); + double distance = MathHelper.sqrt((float) bp.getSquaredDistance(mod.getPlayer().getPos())); + closestDist = Math.min(distance, closestDist); + } + } + + // no block was found + if (closestDist == Integer.MAX_VALUE) { + return Double.NEGATIVE_INFINITY; + } + + if (count >= minCount) { + if (closestDist < 5) { + return 10 / closestDist * 15 * multiplier; + } + return Double.NEGATIVE_INFINITY; + } + + return 10 / closestDist * 35 * multiplier; + }; + } + + private void addLootChestsTasks(AltoClef mod) { + // TODO lower priority is player already has most of the items + + GatherResource resource = new GatherResource(999, 999999, null, (item) -> true, Items.BEDROCK) + .withCanCache(false).withDescription("looting nearby chest"); + + resource.withPriorityCalculator( (items, count, minCount, maxCount) -> { + //the chest is open and being looted + if (mod.getPlayer().currentScreenHandler instanceof GenericContainerScreenHandler && lastTask instanceof LootContainerTask && isTaskRunning(mod, lastTask)) { + return Double.POSITIVE_INFINITY; + } + if (mod.getItemStorage().hasItemAll(Items.DIAMOND_PICKAXE, Items.DIAMOND_SWORD) && CollectFoodTask.calculateFoodPotential(mod) >= 20) { + return Double.NEGATIVE_INFINITY; + } + + Optional chest = locateClosestUnopenedChest(mod); + if (chest.isEmpty()) return Double.NEGATIVE_INFINITY; + + //just dont dig a lot of blocks for a chest + if (Math.abs(chest.get().getY() - mod.getPlayer().getY()) > 30) { + return Double.NEGATIVE_INFINITY; + } + + lootTask = new LootContainerTask(chest.get(), lootableItems(mod), noCurseOfBinding); + resource.data = Optional.of(lootTask); + //mod.log(chest.get() + ""); + + double dst = Math.sqrt(chest.get().getSquaredDistance(mod.getPlayer().getPos())); + return 30 / dst * 175; + }); + + gatherResources.add(resource); + + } + + private void addCollectFoodTask(AltoClef mod) { + List food = new LinkedList<>(ItemHelper._cookableFoodMap.values()); + food.addAll(ItemHelper._cookableFoodMap.keySet()); + food.addAll(List.of(Items.WHEAT, Items.BREAD)); + + gatherResources.add(new GatherResource(999, 999_999, new CollectFoodPriorityCalculator(mod, config.foodUnits), + item -> StorageHelper.miningRequirementMet(mod, MiningRequirement.STONE) && mod.getItemStorage().hasItem(Items.STONE_SWORD, Items.IRON_SWORD, Items.DIAMOND_SWORD), + Optional.of(new CollectFoodTask(9999)), food.toArray(new Item[0]))); + + + //TODO do some more sophisticated calculation including food potential etc + //craft bread + GatherResource craftWheatTask = new GatherResource(999, 999_999, null, + item -> mod.getItemStorage().hasItem(Items.HAY_BLOCK), Items.BREAD); + + craftWheatTask.withPriorityCalculator( (items, count, minCount, maxCount) -> { + craftWheatTask.data = Optional.ofNullable(TaskCatalogue.getItemTask(Items.WHEAT, mod.getItemStorage().getItemCount(Items.HAY_BLOCK) * 9 + mod.getItemStorage().getItemCount(Items.WHEAT))); + + if (StorageHelper.calculateInventoryFoodScore(mod) < 5) return 270; + return 10; + }); + + gatherResources.add(craftWheatTask); + + GatherResource craftBreadTask = new GatherResource(999, 999_999, null, + item -> mod.getItemStorage().getItemCount(Items.WHEAT) >= 3, Items.BREAD); + craftBreadTask.withPriorityCalculator( (items, count, minCount, maxCount) -> { + craftBreadTask.data = Optional.ofNullable(TaskCatalogue.getItemTask("bread", mod.getItemStorage().getItemCount(Items.WHEAT) / 3 + mod.getItemStorage().getItemCount(Items.BREAD))); + + if (StorageHelper.calculateInventoryFoodScore(mod) < 5) return 250; + return 5; + }); + + gatherResources.add(craftBreadTask); + } + + private void addOreMiningTasks(AltoClef mod) { + GatherResource.PriorityCalculator orePriorityCalculator = (items, count, minCount, maxCount) -> { + if (items.length != 1) { + throw new IllegalStateException("Ore calculator cannot have anything else than one item!"); + } + Item item = items[0]; + Block[] blocks = mapOreItemToBlocks(item); + + double closestDist = Integer.MAX_VALUE; + + Optional optionalDroppedItem = mod.getEntityTracker().getClosestItemDrop(item); + if (optionalDroppedItem.isPresent()) { + closestDist = optionalDroppedItem.get().distanceTo(mod.getPlayer()); + } + + for (Block block : blocks) { + Optional pos = mod.getBlockScanner().getNearestBlock(block); + if (pos.isPresent()) { + BlockPos bp = pos.get(); + double distance = MathHelper.sqrt((float) bp.getSquaredDistance(mod.getPlayer().getPos())); + closestDist = Math.min(distance, closestDist); + } + } + + // no ore was found + if (closestDist == Integer.MAX_VALUE) { + return Double.NEGATIVE_INFINITY; + } + + if (count >= minCount) { + if (closestDist < 5) { + return 10 / closestDist * 25; + } + return Double.NEGATIVE_INFINITY; + } + + return 30 / closestDist * 35; + }; + + //arbitrary amount, might change later + gatherResources.add(new GatherResource(4, 7, orePriorityCalculator, + (item) -> StorageHelper.miningRequirementMet(mod, MiningRequirement.STONE), Items.COAL)); + + //min: iron pickaxe, shield, two buckets, flint and steel + // max: - + gatherResources.add(new GatherResource(11, 11, orePriorityCalculator, + (item) -> StorageHelper.miningRequirementMet(mod, MiningRequirement.STONE), Items.RAW_IRON)); + + + //min: golden helmet + //max: - + gatherResources.add(new GatherResource(5, 5, orePriorityCalculator, + (item) -> StorageHelper.miningRequirementMet(mod, MiningRequirement.IRON), Items.RAW_GOLD)); + + //min: full dia (no helmet), 2*pickaxe, sword + //max: extra pickaxe + gatherResources.add(new GatherResource(27, 30, orePriorityCalculator, + (item) -> StorageHelper.miningRequirementMet(mod, MiningRequirement.IRON), Items.DIAMOND)); + } + + /** + * Adds stone tools not including pickaxe + */ + private void addStoneToolsTasks(AltoClef mod) { + // all at once + GatherResource gatherAllResource = new GatherResource(1, 9999, + null, + (item) -> StorageHelper.miningRequirementMet(mod, MiningRequirement.STONE), + Optional.of(TaskCatalogue.getSquashedItemTask(toItemTargets(Items.STONE_AXE, Items.STONE_SWORD, Items.STONE_SHOVEL, Items.STONE_HOE))), + Items.STONE_AXE, Items.STONE_SWORD, Items.STONE_SHOVEL, Items.STONE_HOE).withShouldForce(true); + + gatherAllResource.withPriorityCalculator( (items, count, minCount, maxCount) -> { + if (mod.getItemStorage().hasItemAll(Items.STONE_AXE, Items.STONE_SWORD, Items.STONE_SHOVEL, Items.STONE_HOE)) { + gatherAllResource.maxCountSatisfied = true; + gatherAllResource.minCountSatisfied = true; + return Double.NEGATIVE_INFINITY; + } + + return 520; + }); + + gatherResources.add(gatherAllResource); + } + + /** + * adds tasks for CRAFTING diamond armor from already obtained diamonds. + * the helmet isnt crafted because we have a golden one + */ + + private void addDiamondArmorTasks(AltoClef mod) { + gatherResources.add(new GatherResource(1, 1, (items, count, minCount, maxCount) -> { + if (hasItem(mod, Items.DIAMOND_CHESTPLATE)) return Double.NEGATIVE_INFINITY; + + return 350; + }, item -> mod.getItemStorage().getItemCount(Items.DIAMOND) >= 8, Items.DIAMOND_CHESTPLATE) + .withBypassForceCooldown(true).withNeedsCraftingOnStart((a) -> true)); + + gatherResources.add(new GatherResource(1, 1, (items, count, minCount, maxCount) -> { + if (hasItem(mod, Items.DIAMOND_LEGGINGS)) return Double.NEGATIVE_INFINITY; + + return 300; + }, item -> mod.getItemStorage().getItemCount(Items.DIAMOND) >= 7, Items.DIAMOND_LEGGINGS) + .withBypassForceCooldown(true).withNeedsCraftingOnStart((a) -> true)); + + gatherResources.add(new GatherResource(1, 1, (items, count, minCount, maxCount) -> { + if (hasItem(mod, Items.DIAMOND_BOOTS)) return Double.NEGATIVE_INFINITY; + + return 220; + }, item -> mod.getItemStorage().getItemCount(Items.DIAMOND) >= 4, Items.DIAMOND_BOOTS) + .withBypassForceCooldown(true).withNeedsCraftingOnStart((a) -> true)); + } + + private void addPickaxeTasks(AltoClef mod) { + gatherResources.add(new GatherResource(1, 1, (items, count, minCount, maxCount) -> { + if (mod.getItemStorage().hasItem(Items.WOODEN_PICKAXE, Items.STONE_PICKAXE, Items.IRON_PICKAXE, Items.DIAMOND_PICKAXE)) + return Double.NEGATIVE_INFINITY; + + return 400; + }, item -> true, Items.WOODEN_PICKAXE) + .withNeedsCraftingOnStart(m -> mod.getItemStorage().getItemCount(Items.STICK) >= 2 || mod.getItemStorage().hasItem(ItemHelper.LOG) || mod.getItemStorage().getItemCount(ItemHelper.PLANKS) >= 2)); + + GatherResource stonePickaxe =new GatherResource(1, 1, (items, count, minCount, maxCount) -> { + if (mod.getItemStorage().hasItem(Items.STONE_PICKAXE, Items.IRON_PICKAXE, Items.DIAMOND_PICKAXE)) + return Double.NEGATIVE_INFINITY; + + return 410; + }, item -> StorageHelper.miningRequirementMet(mod, MiningRequirement.WOOD), Items.STONE_PICKAXE) + .withNeedsCraftingOnStart(m -> mod.getItemStorage().getItemCount(Items.STICK) >= 2 || mod.getItemStorage().hasItem(ItemHelper.LOG) || mod.getItemStorage().getItemCount(ItemHelper.PLANKS) >= 2); + gatherResources.add(stonePickaxe); + + gatherResources.add(new GatherResource(999, 999, (items, count, minCount, maxCount) -> { + List list = mod.getItemStorage().getSlotsWithItemPlayerInventory(false, items); + boolean hasSafeIronPick = false; + for (Slot slot : list) { + if (slot.getInventorySlot() == -1) continue; + ItemStack stack = mod.getPlayer().getInventory().getStack(slot.getInventorySlot()); + if (!StorageHelper.shouldSaveStack(mod, Blocks.STONE, stack) && stack.getItem().equals(Items.IRON_PICKAXE)) { + hasSafeIronPick = true; + break; + } + } + + if (mod.getItemStorage().hasItem(Items.STONE_PICKAXE) || hasSafeIronPick || mod.getItemStorage().hasItem(Items.DIAMOND_PICKAXE)) + return Double.NEGATIVE_INFINITY; + + if (stonePickaxe.minCountSatisfied || stonePickaxe.maxCountSatisfied) return 10_000; + + return 300; + }, item -> StorageHelper.miningRequirementMet(mod, MiningRequirement.WOOD), + Optional.ofNullable(TaskCatalogue.getItemTask(Items.STONE_PICKAXE, 1)), Items.STONE_PICKAXE)); + + gatherResources.add(new GatherResource(1, 1, (items, count, minCount, maxCount) -> { + if (mod.getItemStorage().hasItem(Items.IRON_PICKAXE, Items.DIAMOND_PICKAXE)) + return Double.NEGATIVE_INFINITY; + + return 420; + }, item -> mod.getItemStorage().getItemCount(Items.IRON_INGOT) >= 3, Items.IRON_PICKAXE).withBypassForceCooldown(true) + .withNeedsCraftingOnStart(m -> mod.getItemStorage().getItemCount(Items.STICK) >= 2 || mod.getItemStorage().hasItem(ItemHelper.LOG) || mod.getItemStorage().getItemCount(ItemHelper.PLANKS) >= 2)); + + GatherResource diamondPickResource = new GatherResource(1, 1, (a, b, c, d) -> 430, + item -> mod.getItemStorage().getItemCount(Items.DIAMOND) >= 3, Items.DIAMOND_PICKAXE); + diamondPickResource.withBypassForceCooldown(true); + diamondPickResource.withNeedsCraftingOnStart(m -> mod.getItemStorage().getItemCount(Items.STICK) >= 2 || mod.getItemStorage().hasItem(ItemHelper.LOG) || mod.getItemStorage().getItemCount(ItemHelper.PLANKS) >= 2); + + GatherResource secondDiamondPickResource = new GatherResource(1, 1, (a, b, c, d) -> 100, + item -> mod.getItemStorage().getItemCount(Items.DIAMOND) >= 3, Items.DIAMOND_PICKAXE).withBypassForceCooldown(true); + secondDiamondPickResource.withNeedsCraftingOnStart(m -> mod.getItemStorage().getItemCount(Items.STICK) >= 2 || mod.getItemStorage().hasItem(ItemHelper.LOG) || mod.getItemStorage().getItemCount(ItemHelper.PLANKS) >= 2); + + gatherResources.add(diamondPickResource); + gatherResources.add(secondDiamondPickResource); + } + + private static boolean hasItem(AltoClef mod, Item item) { + ClientPlayerEntity player = mod.getPlayer(); + PlayerInventory inv = player.getInventory(); + List> combinedInventory = List.of(inv.main, inv.armor, inv.offHand); + + for (List list : combinedInventory) { + for (ItemStack itemStack : list) { + if (itemStack.getItem().equals(item)) return true; + } + } + + return false; + } + + private Block[] mapOreItemToBlocks(Item item) { + if (item.equals(Items.RAW_IRON)) { + return new Block[]{Blocks.DEEPSLATE_IRON_ORE, Blocks.IRON_ORE}; + } else if (item.equals(Items.RAW_GOLD)) { + return new Block[]{Blocks.DEEPSLATE_GOLD_ORE, Blocks.GOLD_ORE}; + } else if (item.equals(Items.DIAMOND)) { + return new Block[]{Blocks.DEEPSLATE_DIAMOND_ORE, Blocks.DIAMOND_ORE}; + } else if (item.equals(Items.COAL)) { + return new Block[]{Blocks.DEEPSLATE_COAL_ORE, Blocks.COAL_ORE}; + } + + throw new IllegalStateException("Invalid ore: " + item); + } + + /** + * Checks if the task is finished. + * + * @param mod The instance of the AltoClef mod. + * @return True if the task is finished, false otherwise. + */ + @Override + public boolean isFinished(AltoClef mod) { + if (getInstance().currentScreen instanceof CreditsScreen) { + Debug.logInternal("isFinished - Current screen is CreditsScreen"); + return true; + } + + if (WorldHelper.getCurrentDimension() == Dimension.OVERWORLD && dragonIsDead) { + Debug.logInternal("isFinished - Dragon is dead in the Overworld"); + return true; + } + + Debug.logInternal("isFinished - Returning false"); + return false; + } + + /** + * Checks if the mod needs building materials. + * + * @param mod The AltoClef mod instance. + * @return True if building materials are needed, false otherwise. + */ + private boolean needsBuildingMaterials(AltoClef mod) { + int materialCount = StorageHelper.getBuildingMaterialCount(mod); + boolean shouldForce = isTaskRunning(mod, buildMaterialsTask); + + // Check if the material count is below the minimum required count + // or if the build materials task should be forced. + if (materialCount < config.minBuildMaterialCount || shouldForce) { + Debug.logInternal("Building materials needed: " + materialCount); + Debug.logInternal("Force build materials: " + shouldForce); + return true; + } else { + Debug.logInternal("Building materials not needed"); + return false; + } + } + + /** + * Updates the cached end items based on the dropped items in the entity tracker. + * + * @param mod The AltoClef mod instance. + */ + private void updateCachedEndItems(AltoClef mod) { + List droppedItems = mod.getEntityTracker().getDroppedItems(); + + // If there are no dropped items and the cache wait time has not elapsed, return. + if (droppedItems.isEmpty() && !cachedEndItemNothingWaitTime.elapsed()) { + Debug.logInternal("No dropped items and cache wait time not elapsed."); + return; + } + + // Reset the cache wait time and clear the cached end item drops. + cachedEndItemNothingWaitTime.reset(); + cachedEndItemDrops.clear(); + + for (ItemEntity entity : droppedItems) { + Item item = entity.getStack().getItem(); + int count = entity.getStack().getCount(); + + cachedEndItemDrops.put(item, cachedEndItemDrops.getOrDefault(item, 0) + count); + + Debug.logInternal("Added dropped item: " + item + " with count: " + count); + } + } + + /** + * Retrieves a list of lootable items based on certain conditions. + * + * @param mod The AltoClef mod instance. + * @return The list of lootable items. + */ + private List lootableItems(AltoClef mod) { + List lootable = new ArrayList<>(); + + // Add initial lootable items + lootable.add(Items.APPLE); + lootable.add(Items.GOLDEN_APPLE); + lootable.add(Items.ENCHANTED_GOLDEN_APPLE); + lootable.add(Items.GOLDEN_CARROT); + lootable.add(Items.OBSIDIAN); + lootable.add(Items.STICK); + lootable.add(Items.COAL); + lootable.addAll(Arrays.stream(ItemHelper.LOG).toList()); + + lootable.add(Items.BREAD); + + // Check if golden helmet is equipped or available in inventory + boolean isGoldenHelmetEquipped = StorageHelper.isArmorEquipped(mod, Items.GOLDEN_HELMET); + boolean hasGoldenHelmet = mod.getItemStorage().hasItemInventoryOnly(Items.GOLDEN_HELMET); + + if (!mod.getItemStorage().hasItem(Items.DIAMOND_PICKAXE, Items.IRON_PICKAXE)) { + lootable.add(Items.IRON_PICKAXE); + } + if (mod.getItemStorage().getItemCount(Items.BUCKET, Items.WATER_BUCKET, Items.LAVA_BUCKET) < 2) { + lootable.add(Items.BUCKET); + } + + // Check if there are enough gold ingots + boolean hasEnoughGoldIngots = mod.getItemStorage().getItemCountInventoryOnly(Items.GOLD_INGOT) >= 5; + + // Add golden helmet if not equipped or available in inventory + if (!isGoldenHelmetEquipped && !hasGoldenHelmet) { + lootable.add(Items.GOLDEN_HELMET); + } + + + if ((!hasEnoughGoldIngots && !isGoldenHelmetEquipped && !hasGoldenHelmet) || config.barterPearlsInsteadOfEndermanHunt) { + lootable.add(Items.GOLD_INGOT); + } + + // Add flint and steel and fire charge if not available in inventory + if (!mod.getItemStorage().hasItemInventoryOnly(Items.FLINT_AND_STEEL)) { + lootable.add(Items.FLINT_AND_STEEL); + if (!mod.getItemStorage().hasItemInventoryOnly(Items.FIRE_CHARGE)) { + lootable.add(Items.FIRE_CHARGE); + } + } + + // Add iron ingot if neither bucket nor water bucket is available in inventory + if (!mod.getItemStorage().hasItemInventoryOnly(Items.BUCKET) && !mod.getItemStorage().hasItemInventoryOnly(Items.WATER_BUCKET)) { + lootable.add(Items.IRON_INGOT); + } + + // Add diamond if item targets for eye gear are not met in inventory + if (!StorageHelper.itemTargetsMetInventory(mod, COLLECT_EYE_GEAR_MIN)) { + lootable.add(Items.DIAMOND); + } + + // Add flint if not available in inventory + if (!mod.getItemStorage().hasItemInventoryOnly(Items.FLINT)) { + lootable.add(Items.FLINT); + } + + Debug.logInternal("Lootable items: " + lootable); // Logging statement + + return lootable; + } + + /** + * Overrides the onStop method. + * Performs necessary cleanup and logging when the task is interrupted or stopped. + * + * @param mod The AltoClef mod instance. + * @param interruptTask The task that interrupted the current task. + */ + @Override + protected void onStop(AltoClef mod, Task interruptTask) { + mod.getExtraBaritoneSettings().canWalkOnEndPortal(false); + + mod.getBehaviour().pop(); + + Debug.logInternal("Stopped onStop method"); + Debug.logInternal("canWalkOnEndPortal set to false"); + Debug.logInternal("Behaviour popped"); + Debug.logInternal("Stopped tracking BED blocks"); + Debug.logInternal("Stopped tracking TRACK_BLOCKS"); + } + + /** + * Check if the given task is equal to this BeatMinecraftTask. + * + * @param other The task to compare. + * @return True if the tasks are equal, false otherwise. + */ + @Override + protected boolean isEqual(Task other) { + boolean isSameTask = other instanceof BeatMinecraftTask; + + if (!isSameTask) + Debug.logInternal("The 'other' task is not of type BeatMinecraftTask"); + + return isSameTask; + } + + /** + * Returns a debug string for the object. + * + * @return The debug string. + */ + @Override + protected String toDebugString() { + return "Beating the game (Miran version)."; + } + + /** + * Checks if the end portal has been found. + * + * @param mod The instance of the AltoClef mod. + * @param endPortalCenter The center position of the end portal. + * @return True if the end portal has been found, false otherwise. + */ + private boolean endPortalFound(AltoClef mod, BlockPos endPortalCenter) { + if (endPortalCenter == null) { + Debug.logInternal("End portal center is null"); + return false; + } + return true; + + /* if (endPortalOpened(mod, endPortalCenter)) { + Debug.logInternal("End portal is already opened"); + return true; + } + + List frameBlocks = getFrameBlocks(endPortalCenter); + + for (BlockPos frame : frameBlocks) { + // Check if the frame block is a valid end portal frame + if (mod.getBlockTracker().blockIsValid(frame, Blocks.END_PORTAL_FRAME)) { + Debug.logInternal("Found valid end portal frame at " + frame.toString()); + return true; + } + } + + Debug.logInternal("No valid end portal frame found"); + return false;*/ + } + + /** + * Checks if the end portal is opened. + * + * @param mod The AltoClef mod instance. + * @param endPortalCenter The center position of the end portal. + * @return True if the end portal is opened, false otherwise. + */ + private boolean endPortalOpened(AltoClef mod, BlockPos endPortalCenter) { + if (endPortalOpened && endPortalCenter != null) { + BlockScanner blockTracker = mod.getBlockScanner(); + + if (blockTracker != null) { + boolean isValid = blockTracker.isBlockAtPosition(endPortalCenter, Blocks.END_PORTAL); + + Debug.logInternal("End Portal is " + (isValid ? "valid" : "invalid")); + return isValid; + } + } + + Debug.logInternal("End Portal is not opened yet"); + return false; + } + + /** + * Checks if the bed spawn location is near the given end portal center. + * + * @param mod The AltoClef mod instance. + * @param endPortalCenter The center position of the end portal. + * @return True if the bed spawn location is near the end portal, false otherwise. + */ + private boolean spawnSetNearPortal(AltoClef mod, BlockPos endPortalCenter) { + if (bedSpawnLocation == null) { + Debug.logInternal("Bed spawn location is null"); + return false; + } + + BlockScanner blockTracker = mod.getBlockScanner(); + boolean isValid = blockTracker.isBlockAtPosition(bedSpawnLocation, ItemHelper.itemsToBlocks(ItemHelper.BED)); + + Debug.logInternal("Spawn set near portal: " + isValid); + + return isValid; + } + + /** + * Finds the closest unopened chest. + * + * @param mod The AltoClef mod instance. + * @return An Optional containing the closest BlockPos of the unopened chest, or empty if not found. + */ + private Optional locateClosestUnopenedChest(AltoClef mod) { + if (!WorldHelper.getCurrentDimension().equals(Dimension.OVERWORLD)) { + return Optional.empty(); + } + + // Find the nearest tracking block position + return mod.getBlockScanner().getNearestBlock(blockPos -> { + if (blacklistedChests.contains(blockPos)) return false; + + boolean isUnopenedChest = WorldHelper.isUnopenedChest(mod, blockPos); + boolean isWithinDistance = mod.getPlayer().getBlockPos().isWithinDistance(blockPos, 150); + boolean isLootableChest = canBeLootablePortalChest(mod, blockPos); + + // TODO make more sophisticated + //dont open spawner chests + Optional nearestSpawner = mod.getBlockScanner().getNearestBlock(WorldHelper.toVec3d(blockPos), Blocks.SPAWNER); + if (nearestSpawner.isPresent() && nearestSpawner.get().isWithinDistance(blockPos, 6)) { + blacklistedChests.add(blockPos); + return false; + } + + // TODO use shipwreck finder instead + + Stream states = mod.getWorld().getStatesInBox(new Box(blockPos.getX() - 5, blockPos.getY() - 5, blockPos.getZ() - 5, + blockPos.getX() + 5, blockPos.getY() + 5, blockPos.getZ() + 5)); + + if (states.anyMatch((state) -> state.getBlock().equals(Blocks.WATER))) { + blacklistedChests.add(blockPos); + return false; + } + + Debug.logInternal("isUnopenedChest: " + isUnopenedChest); + Debug.logInternal("isWithinDistance: " + isWithinDistance); + Debug.logInternal("isLootableChest: " + isLootableChest); + + return isUnopenedChest && isWithinDistance && isLootableChest; + }, Blocks.CHEST); + } + + /** + * This method is called when the mod starts. + * It performs several tasks to set up the mod. + */ + @Override + protected void onStart(AltoClef mod) { + resetTimers(); + pushBehaviour(mod); + addThrowawayItemsWarning(mod); + trackBlocks(mod); + addProtectedItems(mod); + allowWalkingOnEndPortal(mod); + avoidDragonBreath(mod); + avoidBreakingBed(mod); + + mod.getBehaviour().avoidBlockBreaking((pos) -> mod.getWorld().getBlockState(pos).getBlock().equals(Blocks.NETHER_PORTAL)); + + SetGammaCommand.changeGamma(20d); + } + + /** + * Resets the timers. + */ + private void resetTimers() { + timer1.reset(); + timer2.reset(); + timer3.reset(); + } + + /** + * Pushes the current behaviour onto the behaviour stack. + * Logs the process for internal debugging. + * + * @param mod The AltoClef instance. + */ + private void pushBehaviour(AltoClef mod) { + Debug.logInternal("Pushing behaviour..."); + + mod.getBehaviour().push(); + + Debug.logInternal("Behaviour pushed successfully."); + } + + /** + * Adds a warning message if certain conditions are not met. + * + * @param mod The AltoClef mod instance. + */ + private void addThrowawayItemsWarning(AltoClef mod) { + // Warning message tail that will be appended to the warning message. + String settingsWarningTail = "in \".minecraft/altoclef_settings.json\". @gamer may break if you don't add this! (sorry!)"; + + // Check if "end_stone" is not part of the "throwawayItems" list and log a warning. + if (!ArrayUtils.contains(mod.getModSettings().getThrowawayItems(mod), Items.END_STONE)) { + Debug.logWarning("\"end_stone\" is not part of your \"throwawayItems\" list " + settingsWarningTail); + } + + // Check if "throwawayUnusedItems" is not set to true and log a warning. + if (!mod.getModSettings().shouldThrowawayUnusedItems()) { + Debug.logWarning("\"throwawayUnusedItems\" is not set to true " + settingsWarningTail); + } + } + + /** + * Tracks specific blocks using the BlockTracker. + * + * @param mod The AltoClef mod instance. + */ + private void trackBlocks(AltoClef mod) { + BlockScanner blockTracker = mod.getBlockScanner(); + + // Add logging statements + Debug.logInternal("Tracking blocks..."); + Debug.logInternal("BlockTracker: " + blockTracker); + Debug.logInternal("Bed block: " + Arrays.toString(ItemHelper.itemsToBlocks(ItemHelper.BED))); + Debug.logInternal("TRACK_BLOCKS: " + Arrays.toString(TRACK_BLOCKS)); + } + + /** + * Adds protected items to the behaviour of the given AltoClef instance. + * + * @param mod The AltoClef instance. + */ + private void addProtectedItems(AltoClef mod) { + mod.getBehaviour().addProtectedItems(Items.ENDER_EYE, Items.BLAZE_ROD, Items.ENDER_PEARL, Items.CRAFTING_TABLE, Items.IRON_INGOT, Items.WATER_BUCKET, Items.FLINT_AND_STEEL, Items.SHIELD, Items.SHEARS, Items.BUCKET, Items.GOLDEN_HELMET, Items.SMOKER, Items.FURNACE); + + // Add protected items using helper classes + mod.getBehaviour().addProtectedItems(ItemHelper.BED); + mod.getBehaviour().addProtectedItems(ItemHelper.IRON_ARMORS); + mod.getBehaviour().addProtectedItems(ItemHelper.LOG); + + Debug.logInternal("Protected items added successfully."); + } + + /** + * Allows the player to walk on an end portal block. + * + * @param mod The AltoClef mod instance. + */ + private void allowWalkingOnEndPortal(AltoClef mod) { + mod.getBehaviour().allowWalkingOn(blockPos -> { + if (enterindEndPortal && (mod.getChunkTracker().isChunkLoaded(blockPos))) { + BlockState blockState = mod.getWorld().getBlockState(blockPos); + boolean isEndPortal = blockState.getBlock() == Blocks.END_PORTAL; + if (isEndPortal) { + Debug.logInternal("Walking on End Portal at " + blockPos.toString()); + } + return isEndPortal; + + } + return false; + }); + } + + /** + * Avoids walking through dragon breath in the End dimension. + * + * @param mod The AltoClef mod instance. + */ + private void avoidDragonBreath(AltoClef mod) { + mod.getBehaviour().avoidWalkingThrough(blockPos -> { + Dimension currentDimension = WorldHelper.getCurrentDimension(); + boolean isEndDimension = currentDimension == Dimension.END; + boolean isTouchingDragonBreath = dragonBreathTracker.isTouchingDragonBreath(blockPos); + + if (isEndDimension && !escapingDragonsBreath && isTouchingDragonBreath) { + Debug.logInternal("Avoiding dragon breath at blockPos: " + blockPos); + return true; + } else { + return false; + } + }); + } + + /** + * Avoid breaking the bed by adding a behavior to avoid breaking specific block positions. + * + * @param mod The AltoClef mod instance. + */ + private void avoidBreakingBed(AltoClef mod) { + mod.getBehaviour().avoidBlockBreaking(blockPos -> { + if (bedSpawnLocation != null) { + // Get the head and foot positions of the bed + BlockPos bedHead = WorldHelper.getBedHead(mod, bedSpawnLocation); + BlockPos bedFoot = WorldHelper.getBedFoot(mod, bedSpawnLocation); + + boolean shouldAvoidBreaking = blockPos.equals(bedHead) || blockPos.equals(bedFoot); + + if (shouldAvoidBreaking) { + Debug.logInternal("Avoiding breaking bed at block position: " + blockPos); + } + + return shouldAvoidBreaking; + } + + return false; + }); + } + + private void blackListDangerousBlock(AltoClef mod, Block block) { + Optional nearestTracking = mod.getBlockScanner().getNearestBlock(block); + + if (nearestTracking.isPresent()) { + Iterable entities = mod.getWorld().getEntities(); + for (Entity entity : entities) { + + if (mod.getBlockScanner().isUnreachable(nearestTracking.get()) || !(entity instanceof HostileEntity)) + continue; + + if (mod.getPlayer().squaredDistanceTo(entity.getPos()) < 150 && nearestTracking.get().isWithinDistance(entity.getPos(), 30)) { + + Debug.logMessage("Blacklisting dangerous " + block.toString()); + mod.getBlockScanner().requestBlockUnreachable(nearestTracking.get(), 0); + } + } + } + } + + @Override + protected Task onTick(AltoClef mod) { + if (mod.getPlayer().getMainHandStack().getItem() instanceof EnderEyeItem && !openingEndPortal) { + List itemStacks = mod.getItemStorage().getItemStacksPlayerInventory(true); + for (ItemStack itemStack : itemStacks) { + Item item = itemStack.getItem(); + if (item instanceof SwordItem) { + mod.getSlotHandler().forceEquipItem(item); + } + } + } + + + boolean shouldSwap = false; + boolean hasInHotbar = false; + for (int i = 0; i < 9; i++) { + ItemStack stack = mod.getPlayer().getInventory().getStack(i); + + //FIXME do some more general approach + if (stack.getItem().equals(Items.IRON_PICKAXE) && StorageHelper.shouldSaveStack(mod, Blocks.STONE, stack)) { + shouldSwap = true; + } + if (stack.getItem().equals(Items.STONE_PICKAXE)) { + hasInHotbar = true; + } + } + + if (shouldSwap && !hasInHotbar) { + if (mod.getItemStorage().hasItem(Items.STONE_PICKAXE)) { + mod.getSlotHandler().forceEquipItem(Items.STONE_PICKAXE); + } + } + + + boolean eyeGearSatisfied = StorageHelper.isArmorEquippedAll(mod, COLLECT_EYE_ARMOR); + boolean ironGearSatisfied = StorageHelper.isArmorEquippedAll(mod, COLLECT_IRON_ARMOR); + + if (mod.getItemStorage().hasItem(Items.DIAMOND_PICKAXE)) { + mod.getBehaviour().setBlockBreakAdditionalPenalty(1.2); + } else { + mod.getBehaviour().setBlockBreakAdditionalPenalty(mod.getClientBaritoneSettings().blockBreakAdditionalPenalty.defaultValue); + } + Predicate isCraftingTableTask = task -> { + if (task instanceof DoStuffInContainerTask cont) { + return cont.getContainerTarget().matches(Items.CRAFTING_TABLE); + } + return false; + }; + List craftingTables = mod.getBlockScanner().getKnownLocations(Blocks.CRAFTING_TABLE); + for (BlockPos craftingTable : craftingTables) { + if (mod.getItemStorage().hasItem(Items.CRAFTING_TABLE) && !thisOrChildSatisfies(isCraftingTableTask) && (!mod.getBlockScanner().isUnreachable(craftingTable))) { + Debug.logMessage("Blacklisting extra crafting table."); + mod.getBlockScanner().requestBlockUnreachable(craftingTable, 0); + + } + if (!mod.getBlockScanner().isUnreachable(craftingTable)) { + BlockState craftingTablePosUp = mod.getWorld().getBlockState(craftingTable.up(2)); + if (mod.getEntityTracker().entityFound(WitchEntity.class)) { + Optional witch = mod.getEntityTracker().getClosestEntity(WitchEntity.class); + if (witch.isPresent() && (craftingTable.isWithinDistance(witch.get().getPos(), 15))) { + Debug.logMessage("Blacklisting witch crafting table."); + mod.getBlockScanner().requestBlockUnreachable(craftingTable, 0); + + } + } + if (craftingTablePosUp.getBlock() == Blocks.WHITE_WOOL) { + Debug.logMessage("Blacklisting pillage crafting table."); + mod.getBlockScanner().requestBlockUnreachable(craftingTable, 0); + } + } + } + List smokers = mod.getBlockScanner().getKnownLocations(Blocks.SMOKER); + + for (BlockPos smoker : smokers) { + if (mod.getItemStorage().hasItem(Items.SMOKER) && !mod.getBlockScanner().isUnreachable(smoker)) { + Debug.logMessage("Blacklisting extra smoker."); + mod.getBlockScanner().requestBlockUnreachable(smoker, 0); + } + } + + List furnaces = mod.getBlockScanner().getKnownLocations(Blocks.FURNACE); + + for (BlockPos furnace : furnaces) { + if (mod.getItemStorage().hasItem(Items.FURNACE) && !goToNetherTask.isActive() && !ranStrongholdLocator && !mod.getBlockScanner().isUnreachable(furnace)) { + Debug.logMessage("Blacklisting extra furnace."); + mod.getBlockScanner().requestBlockUnreachable(furnace, 0); + } + } + + List logs = mod.getBlockScanner().getKnownLocations(ItemHelper.itemsToBlocks(ItemHelper.LOG)); + + for (BlockPos log : logs) { + Iterable entities = mod.getWorld().getEntities(); + for (Entity entity : entities) { + if (entity instanceof PillagerEntity && !mod.getBlockScanner().isUnreachable(log) && log.isWithinDistance(entity.getPos(), 40)) { + Debug.logMessage("Blacklisting pillage log."); + mod.getBlockScanner().requestBlockUnreachable(log, 0); + } + } + if (log.getY() < 62 && !mod.getBlockScanner().isUnreachable(log) && !ironGearSatisfied && !eyeGearSatisfied) { + Debug.logMessage("Blacklisting dangerous log."); + mod.getBlockScanner().requestBlockUnreachable(log, 0); + } + } + + + if (!ironGearSatisfied && !eyeGearSatisfied) { + blackListDangerousBlock(mod, Blocks.DEEPSLATE_COAL_ORE); + blackListDangerousBlock(mod, Blocks.COAL_ORE); + blackListDangerousBlock(mod, Blocks.DEEPSLATE_IRON_ORE); + blackListDangerousBlock(mod, Blocks.IRON_ORE); + } + + List ancientCityBlocks = List.of(Blocks.DEEPSLATE_BRICKS, Blocks.SCULK, Blocks.SCULK_VEIN, Blocks.SCULK_SENSOR, Blocks.SCULK_SHRIEKER, Blocks.DEEPSLATE_TILE_STAIRS, Blocks.CRACKED_DEEPSLATE_BRICKS, Blocks.SOUL_LANTERN, Blocks.DEEPSLATE_TILES, Blocks.POLISHED_DEEPSLATE); + final int radius = 5; + for (BlockPos pos : mod.getBlockScanner().getKnownLocations(ItemHelper.itemsToBlocks(ItemHelper.WOOL))) { + + searchLoop: + for (int x = -radius; x < radius; x++) { + for (int y = -radius; y < radius; y++) { + for (int z = -radius; z < radius; z++) { + BlockPos p = pos.add(x, y, z); + Block block = mod.getWorld().getBlockState(p).getBlock(); + + if (ancientCityBlocks.contains(block)) { + Debug.logMessage("Blacklisting ancient city wool " + pos); + mod.getBlockScanner().requestBlockUnreachable(pos, 0); + break searchLoop; + } + } + } + } + } + + if (locateStrongholdTask.isActive() && WorldHelper.getCurrentDimension() == Dimension.OVERWORLD && !mod.getClientBaritone().getExploreProcess().isActive() && timer1.elapsed()) { + timer1.reset(); + } + if ((getOneBedTask != null && getOneBedTask.isActive() || (sleepThroughNightTask.isActive() && !mod.getItemStorage().hasItem(ItemHelper.BED))) && getBedTask == null && !mod.getClientBaritone().getExploreProcess().isActive() && timer3.elapsed()) { + timer3.reset(); + } + + //armor quipping logic + if (WorldHelper.getCurrentDimension() != Dimension.END && mod.getItemStorage().hasItem(Items.SHIELD) && !mod.getItemStorage().hasItemInOffhand(Items.SHIELD)) { + return new EquipArmorTask(Items.SHIELD); + } + + if (WorldHelper.getCurrentDimension() == Dimension.NETHER) { + if (mod.getItemStorage().hasItem(Items.GOLDEN_HELMET)) { + return new EquipArmorTask(Items.GOLDEN_HELMET); + } else if (mod.getItemStorage().hasItem(Items.DIAMOND_HELMET) && !hasItem(mod, Items.GOLDEN_HELMET)) { + return new EquipArmorTask(Items.DIAMOND_HELMET); + } + } else { + if (mod.getItemStorage().hasItem(Items.DIAMOND_HELMET)) { + return new EquipArmorTask(Items.DIAMOND_HELMET); + } + } + + if (mod.getItemStorage().hasItem(Items.DIAMOND_CHESTPLATE)) { + return new EquipArmorTask(Items.DIAMOND_CHESTPLATE); + } + if (mod.getItemStorage().hasItem(Items.DIAMOND_LEGGINGS)) { + return new EquipArmorTask(Items.DIAMOND_LEGGINGS); + } + if (mod.getItemStorage().hasItem(Items.DIAMOND_BOOTS)) { + return new EquipArmorTask(Items.DIAMOND_BOOTS); + } + + + if (!StorageHelper.isBigCraftingOpen() && !StorageHelper.isFurnaceOpen() && !StorageHelper.isSmokerOpen() && !StorageHelper.isBlastFurnaceOpen() && !StorageHelper.isChestOpen()) { + //can cause the bot to get stuck + if (mod.getItemStorage().getItemCount(Items.FURNACE) > 1) { + return new PlaceBlockNearbyTask(Blocks.FURNACE); + } + if (mod.getItemStorage().getItemCount(Items.CRAFTING_TABLE) > 1) { + return new PlaceBlockNearbyTask(Blocks.CRAFTING_TABLE); + } + throwAwayItems(mod, Items.SAND, Items.RED_SAND); + throwAwayItems(mod, Items.TORCH); + throwAwayItems(mod, uselessItems); + + + if (mod.getItemStorage().hasItem(Items.STONE_PICKAXE, Items.IRON_PICKAXE, Items.DIAMOND_PICKAXE)) { + throwAwayItems(mod, Items.WOODEN_PICKAXE); + } + if (mod.getItemStorage().hasItem(Items.DIAMOND_PICKAXE)) { + throwAwayItems(mod, Items.IRON_PICKAXE, Items.STONE_PICKAXE); + } + + if (mod.getItemStorage().hasItem(Items.DIAMOND_SWORD)) { + throwAwayItems(mod, Items.STONE_SWORD, Items.IRON_SWORD); + } + + if (mod.getItemStorage().hasItem(Items.GOLDEN_HELMET)) { + throwAwayItems(mod, Items.RAW_GOLD, Items.GOLD_INGOT); + } + + if (mod.getItemStorage().hasItem(Items.FLINT) || mod.getItemStorage().hasItem(Items.FLINT_AND_STEEL)) { + throwAwayItems(mod, Items.GRAVEL); + } + if (mod.getItemStorage().hasItem(Items.FLINT_AND_STEEL)) { + throwAwayItems(mod, Items.FLINT); + } + if (isTaskRunning(mod, getRidOfExtraWaterBucketTask)) { + return getRidOfExtraWaterBucketTask; + } + if (mod.getItemStorage().getItemCount(Items.WATER_BUCKET) > 1) { + getRidOfExtraWaterBucketTask = new GetRidOfExtraWaterBucketTask(); + return getRidOfExtraWaterBucketTask; + } + if (mod.getItemStorage().getItemCount(Items.FLINT_AND_STEEL) > 1) { + throwAwayItems(mod, Items.FLINT_AND_STEEL); + } + if (mod.getItemStorage().getItemCount(ItemHelper.BED) > getTargetBeds(mod) && !endPortalFound(mod, endPortalCenterLocation) && WorldHelper.getCurrentDimension() != Dimension.END) { + throwAwayItems(mod, ItemHelper.BED); + } + } + + + /* + if in the overworld: + if end portal found: + if end portal opened: + @make sure we have iron gear and enough beds to kill the dragon first, considering whether that gear was dropped in the end + @enter end portal + else if we have enough eyes of ender: + @fill in the end portal + else if we have enough eyes of ender: + @locate the end portal + else: + if we don't have diamond gear: + if we have no food: + @get a little bit of food + @get diamond gear + @go to the nether + if in the nether: + if we don't have enough blaze rods: + @kill blazes till we do + else if we don't have enough pearls: + @kill enderman till we do + else: + @leave the nether + if in the end: + if we have a bed: + @do bed strats + else: + @just hit the dragon normally + */ + + // By default, don't walk over end portals. + enterindEndPortal = false; + + // End stuff. + if (WorldHelper.getCurrentDimension() == Dimension.END) { + if (!mod.getWorld().isChunkLoaded(0, 0)) { + setDebugState("Waiting for chunks to load"); + return null; + } + + // If we have bed, do bed strats, otherwise punk normally. + updateCachedEndItems(mod); + // Grab beds + if (mod.getEntityTracker().itemDropped(ItemHelper.BED) && (needsBeds(mod) || WorldHelper.getCurrentDimension() == Dimension.END)) + return new PickupDroppedItemTask(new ItemTarget(ItemHelper.BED), true); + // Grab tools + if (!mod.getItemStorage().hasItem(Items.IRON_PICKAXE, Items.DIAMOND_PICKAXE)) { + if (mod.getEntityTracker().itemDropped(Items.IRON_PICKAXE)) + return new PickupDroppedItemTask(Items.IRON_PICKAXE, 1); + if (mod.getEntityTracker().itemDropped(Items.DIAMOND_PICKAXE)) + return new PickupDroppedItemTask(Items.DIAMOND_PICKAXE, 1); + } + if (!mod.getItemStorage().hasItem(Items.WATER_BUCKET) && mod.getEntityTracker().itemDropped(Items.WATER_BUCKET)) + return new PickupDroppedItemTask(Items.WATER_BUCKET, 1); + // Grab armor + for (Item armorCheck : COLLECT_EYE_ARMOR_END) { + if (!StorageHelper.isArmorEquipped(mod, armorCheck)) { + if (mod.getItemStorage().hasItem(armorCheck)) { + setDebugState("Equipping armor."); + return new EquipArmorTask(armorCheck); + } + if (mod.getEntityTracker().itemDropped(armorCheck)) { + return new PickupDroppedItemTask(armorCheck, 1); + } + } + } + // Dragons breath avoidance + dragonBreathTracker.updateBreath(mod); + for (BlockPos playerIn : WorldHelper.getBlocksTouchingPlayer(mod)) { + if (dragonBreathTracker.isTouchingDragonBreath(playerIn)) { + setDebugState("ESCAPE dragons breath"); + escapingDragonsBreath = true; + return dragonBreathTracker.getRunAwayTask(); + } + } + escapingDragonsBreath = false; + + // If we find an ender portal, just GO to it!!! + if (mod.getBlockScanner().anyFound(Blocks.END_PORTAL)) { + setDebugState("WOOHOO"); + dragonIsDead = true; + enterindEndPortal = true; + if (!mod.getExtraBaritoneSettings().isCanWalkOnEndPortal()) { + mod.getExtraBaritoneSettings().canWalkOnEndPortal(true); + } + return new DoToClosestBlockTask(blockPos -> new GetToBlockTask(blockPos.up()), (pos) -> Math.abs(pos.getX()) + Math.abs(pos.getZ()) <= 1, Blocks.END_PORTAL); + } + if (mod.getItemStorage().hasItem(ItemHelper.BED) || mod.getBlockScanner().anyFound(ItemHelper.itemsToBlocks(ItemHelper.BED))) { + setDebugState("Bed strats"); + return killDragonBedStratsTask; + } + setDebugState("No beds, regular strats."); + return new KillEnderDragonTask(); + } else { + // We're not in the end so reset our "end cache" timer + cachedEndItemNothingWaitTime.reset(); + } + + // Check for end portals. Always. + if (!endPortalOpened(mod, endPortalCenterLocation) && WorldHelper.getCurrentDimension() == Dimension.OVERWORLD) { + Optional endPortal = mod.getBlockScanner().getNearestBlock(Blocks.END_PORTAL); + if (endPortal.isPresent()) { + endPortalCenterLocation = endPortal.get(); + endPortalOpened = true; + } else { + // TODO: Test that this works, for some reason the bot gets stuck near the stronghold and it keeps "Searching" for the portal + endPortalCenterLocation = doSimpleSearchForEndPortal(mod); + } + } + if (isTaskRunning(mod, rePickupTask)) { + return rePickupTask; + } + + + // Portable crafting table. + // If we're NOT using our crafting table right now and there's one nearby, grab it. + if (!endPortalOpened && WorldHelper.getCurrentDimension() != Dimension.END && config.rePickupCraftingTable && !mod.getItemStorage().hasItem(Items.CRAFTING_TABLE) && !thisOrChildSatisfies(isCraftingTableTask) && (mod.getBlockScanner().anyFound(blockPos -> WorldHelper.canBreak(mod, blockPos) && WorldHelper.canReach(mod, blockPos), Blocks.CRAFTING_TABLE) || mod.getEntityTracker().itemDropped(Items.CRAFTING_TABLE)) && pickupCrafting) { + setDebugState("Picking up the crafting table while we are at it."); + return new MineAndCollectTask(Items.CRAFTING_TABLE, 1, new Block[]{Blocks.CRAFTING_TABLE}, MiningRequirement.HAND); + } + if (config.rePickupSmoker && !endPortalOpened && WorldHelper.getCurrentDimension() != Dimension.END && !mod.getItemStorage().hasItem(Items.SMOKER) && (mod.getBlockScanner().anyFound(blockPos -> WorldHelper.canBreak(mod, blockPos) && WorldHelper.canReach(mod, blockPos), Blocks.SMOKER) || mod.getEntityTracker().itemDropped(Items.SMOKER)) && pickupSmoker) { + setDebugState("Picking up the smoker while we are at it."); + rePickupTask = new MineAndCollectTask(Items.SMOKER, 1, new Block[]{Blocks.SMOKER}, MiningRequirement.WOOD); + return rePickupTask; + } + if (config.rePickupFurnace && !endPortalOpened && WorldHelper.getCurrentDimension() != Dimension.END && !mod.getItemStorage().hasItem(Items.FURNACE) && (mod.getBlockScanner().anyFound(blockPos -> WorldHelper.canBreak(mod, blockPos) && WorldHelper.canReach(mod, blockPos), Blocks.FURNACE) || mod.getEntityTracker().itemDropped(Items.FURNACE)) && !goToNetherTask.isActive() && !ranStrongholdLocator && !mod.getModSettings().shouldUseBlastFurnace() && pickupFurnace) { + setDebugState("Picking up the furnace while we are at it."); + rePickupTask = new MineAndCollectTask(Items.FURNACE, 1, new Block[]{Blocks.FURNACE}, MiningRequirement.WOOD); + return rePickupTask; + } + pickupFurnace = false; + pickupSmoker = false; + pickupCrafting = false; + + // Sleep through night. + if (config.sleepThroughNight && !endPortalOpened && WorldHelper.getCurrentDimension() == Dimension.OVERWORLD) { + if (WorldHelper.canSleep()) { + if (timer2.elapsed()) { + timer2.reset(); + } + + if (timer2.getDuration() >= 30 && !mod.getPlayer().isSleeping()) { + if (mod.getEntityTracker().itemDropped(ItemHelper.BED) && needsBeds(mod)) { + setDebugState("Resetting sleep through night task."); + return new PickupDroppedItemTask(new ItemTarget(ItemHelper.BED), true); + } + if (anyBedsFound(mod)) { + setDebugState("Resetting sleep through night task."); + return new DoToClosestBlockTask(DestroyBlockTask::new, ItemHelper.itemsToBlocks(ItemHelper.BED)); + } + } + + setDebugState("Sleeping through night"); + return sleepThroughNightTask; + } + if (!mod.getItemStorage().hasItem(ItemHelper.BED) && (mod.getBlockScanner().anyFound(blockPos -> WorldHelper.canBreak(mod, blockPos), ItemHelper.itemsToBlocks(ItemHelper.BED)) || isTaskRunning(mod, getOneBedTask))) { + setDebugState("Getting one bed to sleep in at night."); + return getOneBedTask; + } + } + + // Do we need more eyes? + boolean needsEyes = !endPortalOpened(mod, endPortalCenterLocation) && WorldHelper.getCurrentDimension() != Dimension.END; + int filledPortalFrames = getFilledPortalFrames(mod, endPortalCenterLocation); + int eyesNeededMin = needsEyes ? config.minimumEyes - filledPortalFrames : 0; + int eyesNeeded = needsEyes ? config.targetEyes - filledPortalFrames : 0; + + int eyes = mod.getItemStorage().getItemCount(Items.ENDER_EYE); + if (eyes < eyesNeededMin || (!ranStrongholdLocator && collectingEyes && eyes < eyesNeeded)) { + collectingEyes = true; + return getEyesOfEnderTask(mod, eyesNeeded); + } else { + collectingEyes = false; + } + + // make new pickaxe if old one breaks + ItemStorageTracker itemStorage = mod.getItemStorage(); + if (itemStorage.getItemCount(Items.DIAMOND) >= 3 && !itemStorage.hasItem(Items.DIAMOND_PICKAXE, Items.IRON_PICKAXE)) { + return TaskCatalogue.getItemTask(Items.DIAMOND_PICKAXE, 1); + } else if (itemStorage.getItemCount(Items.IRON_INGOT) >= 3 && !itemStorage.hasItem(Items.DIAMOND_PICKAXE, Items.IRON_PICKAXE)) { + return TaskCatalogue.getItemTask(Items.IRON_PICKAXE, 1); + } else if (!itemStorage.hasItem(Items.DIAMOND_PICKAXE, Items.IRON_PICKAXE, Items.STONE_PICKAXE)) { + return TaskCatalogue.getItemTask(Items.STONE_PICKAXE, 1); + } + if (!itemStorage.hasItem(Items.DIAMOND_PICKAXE, Items.IRON_PICKAXE, Items.STONE_PICKAXE, Items.WOODEN_PICKAXE)) { + return TaskCatalogue.getItemTask(Items.WOODEN_PICKAXE, 1); + } + + // We have eyes. Locate our portal + enter. + if (WorldHelper.getCurrentDimension() == Dimension.OVERWORLD) { + if (mod.getItemStorage().hasItem(Items.DIAMOND_PICKAXE)) { + Item[] throwGearItems = {Items.STONE_SWORD, Items.STONE_PICKAXE, Items.IRON_SWORD, Items.IRON_PICKAXE}; + List ironArmors = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, COLLECT_IRON_ARMOR); + List throwGears = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, throwGearItems); + if (!StorageHelper.isBigCraftingOpen() && !StorageHelper.isFurnaceOpen() && !StorageHelper.isSmokerOpen() && !StorageHelper.isBlastFurnaceOpen() && (mod.getItemStorage().hasItem(Items.FLINT_AND_STEEL) || mod.getItemStorage().hasItem(Items.FIRE_CHARGE))) { + + for (Slot throwGear : throwGears) { + if (Slot.isCursor(throwGear)) { + if (!mod.getControllerExtras().isBreakingBlock()) { + LookHelper.randomOrientation(mod); + } + mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); + } else { + mod.getSlotHandler().clickSlot(throwGear, 0, SlotActionType.PICKUP); + } + } + + + for (Slot ironArmor : ironArmors) { + if (Slot.isCursor(ironArmor)) { + if (!mod.getControllerExtras().isBreakingBlock()) { + LookHelper.randomOrientation(mod); + } + mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); + } else { + mod.getSlotHandler().clickSlot(ironArmor, 0, SlotActionType.PICKUP); + } + } + + } + } + // If we found our end portal... + if (endPortalFound(mod, endPortalCenterLocation)) { + // Destroy silverfish spawner + if (StorageHelper.miningRequirementMetInventory(mod, MiningRequirement.WOOD)) { + Optional silverfish = mod.getBlockScanner().getNearestBlock(blockPos -> (WorldHelper.getSpawnerEntity(mod, blockPos) instanceof SilverfishEntity) + , Blocks.SPAWNER); + + if (silverfish.isPresent()) { + setDebugState("Breaking silverfish spawner."); + return new DestroyBlockTask(silverfish.get()); + } + } + if (endPortalOpened(mod, endPortalCenterLocation)) { + openingEndPortal = false; + if (needsBuildingMaterials(mod)) { + setDebugState("Collecting building materials."); + return buildMaterialsTask; + } + if (config.placeSpawnNearEndPortal && mod.getItemStorage().hasItem(ItemHelper.BED) && (!spawnSetNearPortal(mod, endPortalCenterLocation))) { + setDebugState("Setting spawn near end portal"); + return setSpawnNearPortalTask(mod); + + } + // We're as ready as we'll ever be, hop into the portal! + setDebugState("Entering End"); + enterindEndPortal = true; + if (!mod.getExtraBaritoneSettings().isCanWalkOnEndPortal()) { + mod.getExtraBaritoneSettings().canWalkOnEndPortal(true); + } + return new DoToClosestBlockTask(blockPos -> new GetToBlockTask(blockPos.up()), Blocks.END_PORTAL); + } else { + if (!mod.getItemStorage().hasItem(Items.OBSIDIAN)) { + if (mod.getBlockScanner().anyFoundWithinDistance(10, Blocks.OBSIDIAN) || mod.getEntityTracker().itemDropped(Items.OBSIDIAN)) { + if (!mod.getItemStorage().hasItem(Items.WATER_BUCKET)) { + return new CollectBucketLiquidTask.CollectWaterBucketTask(1); + } + if (!waterPlacedTimer.elapsed()) { + setDebugState("waitin " + waterPlacedTimer.getDuration()); + return null; + } + return TaskCatalogue.getItemTask(Items.OBSIDIAN, 1); + } else { + if (repeated > 2 && !mod.getItemStorage().hasItem(Items.WATER_BUCKET)) { + return new CollectBucketLiquidTask.CollectWaterBucketTask(1); + } + if (waterPlacedTimer.elapsed()) { + if (!mod.getItemStorage().hasItem(Items.WATER_BUCKET)) { + repeated++; + waterPlacedTimer.reset(); + return null; + } else { + repeated = 0; + } + + return new PlaceObsidianBucketTask( + mod.getBlockScanner().getNearestBlock(WorldHelper.toVec3d(endPortalCenterLocation), (blockPos) -> !blockPos.isWithinDistance(endPortalCenterLocation, 8), Blocks.LAVA).get()); + } + setDebugState(waterPlacedTimer.getDuration() + ""); + return null; + } + } + // Open the portal! (we have enough eyes, do it) + setDebugState("Opening End Portal"); + openingEndPortal = true; + return new DoToClosestBlockTask(blockPos -> new InteractWithBlockTask(Items.ENDER_EYE, blockPos), blockPos -> !isEndPortalFrameFilled(mod, blockPos), Blocks.END_PORTAL_FRAME); + } + } else { + ranStrongholdLocator = true; + // Get beds before starting our portal location. + if (WorldHelper.getCurrentDimension() == Dimension.OVERWORLD && needsBeds(mod)) { + setDebugState("Getting beds before stronghold search."); + if (!mod.getClientBaritone().getExploreProcess().isActive() && timer1.elapsed()) { + timer1.reset(); + } + getBedTask = getBedTask(mod); + return getBedTask; + } else { + getBedTask = null; + } + if (!mod.getItemStorage().hasItem(Items.WATER_BUCKET)) { + setDebugState("Getting water bucket."); + return TaskCatalogue.getItemTask(Items.WATER_BUCKET, 1); + } + if (!mod.getItemStorage().hasItem(Items.FLINT_AND_STEEL)) { + setDebugState("Getting flint and steel."); + return TaskCatalogue.getItemTask(Items.FLINT_AND_STEEL, 1); + } + if (needsBuildingMaterials(mod)) { + setDebugState("Collecting building materials."); + return buildMaterialsTask; + } + // Portal Location + setDebugState("Locating End Portal..."); + return locateStrongholdTask; + } + } else if (WorldHelper.getCurrentDimension() == Dimension.NETHER) { + Item[] throwGearItems = {Items.STONE_SWORD, Items.STONE_PICKAXE, Items.IRON_SWORD, Items.IRON_PICKAXE}; + List ironArmors = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, COLLECT_IRON_ARMOR); + List throwGears = mod.getItemStorage().getSlotsWithItemPlayerInventory(true, throwGearItems); + if (!StorageHelper.isBigCraftingOpen() && !StorageHelper.isFurnaceOpen() && !StorageHelper.isSmokerOpen() && !StorageHelper.isBlastFurnaceOpen() && (mod.getItemStorage().hasItem(Items.FLINT_AND_STEEL) || mod.getItemStorage().hasItem(Items.FIRE_CHARGE))) { + + for (Slot throwGear : throwGears) { + if (Slot.isCursor(throwGear)) { + if (!mod.getControllerExtras().isBreakingBlock()) { + LookHelper.randomOrientation(mod); + } + mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); + } else { + mod.getSlotHandler().clickSlot(throwGear, 0, SlotActionType.PICKUP); + } + } + + + for (Slot ironArmor : ironArmors) { + if (Slot.isCursor(ironArmor)) { + if (!mod.getControllerExtras().isBreakingBlock()) { + LookHelper.randomOrientation(mod); + } + mod.getSlotHandler().clickSlot(Slot.UNDEFINED, 0, SlotActionType.PICKUP); + } else { + mod.getSlotHandler().clickSlot(ironArmor, 0, SlotActionType.PICKUP); + } + } + + } + // Portal Location + setDebugState("Locating End Portal..."); + return locateStrongholdTask; + } + return null; + } + + /** + * Sets the spawn point near the portal. + * + * @param mod The AltoClef mod instance. + * @return The task to set the spawn point near the portal. + */ + private Task setSpawnNearPortalTask(AltoClef mod) { + if (setBedSpawnTask.isSpawnSet()) { + bedSpawnLocation = setBedSpawnTask.getBedSleptPos(); + } else { + bedSpawnLocation = null; + } + + if (isTaskRunning(mod, setBedSpawnTask)) { + setDebugState("Setting spawnpoint now."); + return setBedSpawnTask; + } + + // Check if the player is within range of the portal + if (WorldHelper.inRangeXZ(mod.getPlayer(), WorldHelper.toVec3d(endPortalCenterLocation), END_PORTAL_BED_SPAWN_RANGE)) { + return setBedSpawnTask; + } else { + setDebugState("Approaching portal (to set spawnpoint)"); + return new GetToXZTask(endPortalCenterLocation.getX(), endPortalCenterLocation.getZ()); + } + } + + /** + * Returns a Task to handle Blaze Rods based on the given count. + * + * @param mod The AltoClef mod instance. + * @param count The desired count of Blaze Rods. + * @return A Task to handle Blaze Rods. + */ + private Task getBlazeRodsTask(AltoClef mod, int count) { + EntityTracker entityTracker = mod.getEntityTracker(); + + if (entityTracker.itemDropped(Items.BLAZE_ROD)) { + Debug.logInternal("Blaze Rod dropped, picking it up."); + return new PickupDroppedItemTask(Items.BLAZE_ROD, 1); + } else if (entityTracker.itemDropped(Items.BLAZE_POWDER)) { + Debug.logInternal("Blaze Powder dropped, picking it up."); + return new PickupDroppedItemTask(Items.BLAZE_POWDER, 1); + } else { + Debug.logInternal("No Blaze Rod or Blaze Powder dropped, collecting Blaze Rods."); + return new CollectBlazeRodsTask(count); + } + } + + /** + * Returns a Task to obtain Ender Pearls. + * + * @param mod The mod instance. + * @param count The desired number of Ender Pearls. + * @return The Task to obtain Ender Pearls. + */ + private Task getEnderPearlTask(AltoClef mod, int count) { + if (mod.getEntityTracker().itemDropped(Items.ENDER_PEARL)) { + return new PickupDroppedItemTask(Items.ENDER_PEARL, 1); + } + + // Check if we should barter Pearls instead of hunting Endermen. + if (config.barterPearlsInsteadOfEndermanHunt) { + // Check if Golden Helmet is not equipped, and equip it. + if (!StorageHelper.isArmorEquipped(mod, Items.GOLDEN_HELMET)) { + return new EquipArmorTask(Items.GOLDEN_HELMET); + } + // Trade with Piglins for Ender Pearls. + return new TradeWithPiglinsTask(32, Items.ENDER_PEARL, count); + } + + boolean endermanFound = mod.getEntityTracker().entityFound(EndermanEntity.class); + boolean pearlDropped = mod.getEntityTracker().itemDropped(Items.ENDER_PEARL); + + // Check if we have found an Enderman or Ender Pearl and have enough Twisting Vines. + if (endermanFound || pearlDropped) { + Optional toKill = mod.getEntityTracker().getClosestEntity(EndermanEntity.class); + if (toKill.isPresent() && mod.getEntityTracker().isEntityReachable(toKill.get())) { + return new KillEndermanTask(count); + } + } + + // Search for Ender Pearls within the warped forest biome. + setDebugState("Waiting for endermen to spawn... "); + return null; + } + + /** + * Calculates the target number of beds based on the configuration settings. + * + * @param mod The AltoClef mod instance. + * @return The target number of beds. + */ + private int getTargetBeds(AltoClef mod) { + // Check if spawn needs to be set near the end portal + boolean needsToSetSpawn = config.placeSpawnNearEndPortal && (!spawnSetNearPortal(mod, endPortalCenterLocation) && !isTaskRunning(mod, setBedSpawnTask)); + + // Calculate the number of beds in the end + int bedsInEnd = Arrays.stream(ItemHelper.BED).mapToInt(bed -> cachedEndItemDrops.getOrDefault(bed, 0)).sum(); + + // Calculate the target number of beds + int targetBeds = config.requiredBeds + (needsToSetSpawn ? 1 : 0) - bedsInEnd; + + // Output debug information + Debug.logInternal("needsToSetSpawn: " + needsToSetSpawn); + Debug.logInternal("bedsInEnd: " + bedsInEnd); + Debug.logInternal("targetBeds: " + targetBeds); + + return targetBeds; + } + + /** + * Checks if the player needs to acquire more beds. + * + * @param mod The instance of the AltoClef mod. + * @return True if the player needs more beds, false otherwise. + */ + private boolean needsBeds(AltoClef mod) { + // Calculate the total number of end items obtained from breaking beds + int totalEndItems = 0; + for (Item bed : ItemHelper.BED) { + totalEndItems += cachedEndItemDrops.getOrDefault(bed, 0); + } + + // Get the current number of beds in the player's inventory + int itemCount = mod.getItemStorage().getItemCount(ItemHelper.BED); + + // Get the target number of beds to have + int targetBeds = getTargetBeds(mod); + + // Log the values for debugging purposes + Debug.logInternal("Total End Items: " + totalEndItems); + Debug.logInternal("Item Count: " + itemCount); + Debug.logInternal("Target Beds: " + targetBeds); + + // Check if the player needs to acquire more beds + boolean needsBeds = (itemCount + totalEndItems) < targetBeds; + + // Log the result for debugging purposes + Debug.logInternal("Needs Beds: " + needsBeds); + + // Return whether the player needs more beds + return needsBeds; + } + + /** + * Retrieves a task to obtain the desired number of beds. + * + * @param mod The AltoClef mod instance. + * @return The task to obtain the beds. + */ + private Task getBedTask(AltoClef mod) { + int targetBeds = getTargetBeds(mod); + if (!mod.getItemStorage().hasItem(Items.SHEARS) && !anyBedsFound(mod)) { + Debug.logInternal("Getting shears."); + return TaskCatalogue.getItemTask(Items.SHEARS, 1); + } + Debug.logInternal("Getting beds."); + return TaskCatalogue.getItemTask("bed", targetBeds); + } + + /** + * Checks if any beds are found in the game. + * + * @param mod The AltoClef mod instance. + * @return true if beds are found either in blocks or entities, false otherwise. + */ + private boolean anyBedsFound(AltoClef mod) { + // Get the block and entity trackers from the mod instance. + BlockScanner blockTracker = mod.getBlockScanner(); + EntityTracker entityTracker = mod.getEntityTracker(); + + // Check if any beds are found in blocks. + boolean bedsFoundInBlocks = blockTracker.anyFound(ItemHelper.itemsToBlocks(ItemHelper.BED)); + + // Check if any beds are dropped by entities. + boolean bedsFoundInEntities = entityTracker.itemDropped(ItemHelper.BED); + + // Log a message if beds are found in blocks. + if (bedsFoundInBlocks) { + Debug.logInternal("Beds found in blocks"); + } + + // Log a message if beds are found in entities. + if (bedsFoundInEntities) { + Debug.logInternal("Beds found in entities"); + } + + // Return true if beds are found either in blocks or entities. + return bedsFoundInBlocks || bedsFoundInEntities; + } + + /** + * Searches for the position of an end portal frame by averaging the known locations of the frames. + * Returns the center position of the frames if enough frames are found, otherwise returns null. + * + * @param mod The AltoClef instance. + * @return The position of the end portal frame, or null if not enough frames are found. + */ + private BlockPos doSimpleSearchForEndPortal(AltoClef mod) { + List frames = mod.getBlockScanner().getKnownLocations(Blocks.END_PORTAL_FRAME); + + if (frames.size() >= END_PORTAL_FRAME_COUNT) { + // Calculate the average position of the frames. + Vec3d average = frames.stream().reduce(Vec3d.ZERO, (accum, bpos) -> accum.add((int) Math.round(bpos.getX() + 0.5), (int) Math.round(bpos.getY() + 0.5), (int) Math.round(bpos.getZ() + 0.5)), Vec3d::add).multiply(1d / frames.size()); + + // Log the average position. + mod.log("Average Position: " + average); + + return new BlockPos(new Vec3i((int) average.x, (int) average.y, (int) average.z)); + } + + // Log that there are not enough frames. + Debug.logInternal("Not enough frames"); + + return null; + } + + /** + * Returns the number of filled portal frames around the end portal center. + * If the end portal is found, it returns the constant END_PORTAL_FRAME_COUNT. + * Otherwise, it checks each frame block around the end portal center and counts the filled frames. + * The count is cached for subsequent calls. + * + * @param mod The AltoClef mod instance. + * @param endPortalCenter The center position of the end portal. + * @return The number of filled portal frames. + */ + private int getFilledPortalFrames(AltoClef mod, BlockPos endPortalCenter) { + if (endPortalFound(mod, endPortalCenter)) { + return END_PORTAL_FRAME_COUNT; + } + + // Get all the frame blocks around the end portal center. + List frameBlocks = getFrameBlocks(endPortalCenter); + + // Check if all the frame blocks are loaded. + if (frameBlocks.stream().allMatch(blockPos -> mod.getChunkTracker().isChunkLoaded(blockPos))) { + // Calculate the sum of filled frames using a stream and mapToInt. + cachedFilledPortalFrames = frameBlocks.stream().mapToInt(blockPos -> { + boolean isFilled = isEndPortalFrameFilled(mod, blockPos); + // Log whether the frame is filled or not. + if (isFilled) { + Debug.logInternal("Portal frame at " + blockPos + " is filled."); + } else { + Debug.logInternal("Portal frame at " + blockPos + " is not filled."); + } + return isFilled ? 1 : 0; + }).sum(); + } + + return cachedFilledPortalFrames; + } + + /** + * Checks if a chest at the given block position can be looted. + * + * @param mod The instance of the mod. + * @param blockPos The block position of the chest to check. + * @return True if the chest can be looted as a portal chest, false otherwise. + */ + private boolean canBeLootablePortalChest(AltoClef mod, BlockPos blockPos) { + // Check if the block above is water or if the y-coordinate is below 50 + return mod.getWorld().getBlockState(blockPos.up()).getBlock() != Blocks.WATER && blockPos.getY() >= 50; + + /* // Define the minimum and maximum positions to scan for NETHERRACK blocks + BlockPos minPos = blockPos.add(-4, -2, -4); + BlockPos maxPos = blockPos.add(4, 2, 4); + + // Log the scanning region + Debug.logInternal("Scanning region from " + minPos + " to " + maxPos); + + // Scan the region defined by minPos and maxPos + for (BlockPos checkPos : WorldHelper.scanRegion(mod, minPos, maxPos)) { + // Check if the block at checkPos is NETHERRACK + if (mod.getWorld().getBlockState(checkPos).getBlock() == Blocks.NETHERRACK) { + return true; + } + } + + // Log that the blockPos is added to the list of not ruined portal chests + Debug.logInternal("Adding blockPos " + blockPos + " to the list of not ruined portal chests"); + + // Add the blockPos to the list of not ruined portal chests + notRuinedPortalChests.add(blockPos); + + return false;*/ + } + private GatherResource prevLastGather = null; + + private Task getEyesOfEnderTask(AltoClef mod, int targetEyes) { + if (mod.getEntityTracker().itemDropped(Items.ENDER_EYE)) { + setDebugState("Picking up Dropped Eyes"); + return new PickupDroppedItemTask(Items.ENDER_EYE, targetEyes); + } + + int eyeCount = mod.getItemStorage().getItemCount(Items.ENDER_EYE); + int blazePowderCount = mod.getItemStorage().getItemCount(Items.BLAZE_POWDER); + int blazeRodCount = mod.getItemStorage().getItemCount(Items.BLAZE_ROD); + + int blazeRodTarget = (int) Math.ceil(((double) targetEyes - eyeCount - blazePowderCount) / 2.0); + int enderPearlTarget = targetEyes - eyeCount; + + boolean needsBlazeRods = blazeRodCount < blazeRodTarget; + boolean needsBlazePowder = eyeCount + blazePowderCount < targetEyes; + boolean needsEnderPearls = mod.getItemStorage().getItemCount(Items.ENDER_PEARL) < enderPearlTarget; + + if (needsBlazePowder && !needsBlazeRods) { + // We have enough blaze rods. + setDebugState("Crafting blaze powder"); + return TaskCatalogue.getItemTask(Items.BLAZE_POWDER, targetEyes - eyeCount); + } + + if (!needsBlazePowder && !needsEnderPearls) { + // Craft ender eyes + setDebugState("Crafting Ender Eyes"); + return TaskCatalogue.getItemTask(Items.ENDER_EYE, targetEyes); + } + + + // Get blaze rods + pearls... + switch (WorldHelper.getCurrentDimension()) { + case OVERWORLD -> { + if (!forcedTaskTimer.elapsed() && isTaskRunning(mod,lastTask)) { + return lastTask; + } + + if (!changedTaskTimer.elapsed() && lastTask != null && !lastGather.bypassesForceCooldown() && isTaskRunning(mod,lastTask)) { + return lastTask; + } + if (isTaskRunning(mod, lastTask) && lastGather != null && lastGather.shouldForceTask()) { + return lastTask; + } + + double maxPriority = 0; + GatherResource toGather = null; + + for (GatherResource gatherResource : gatherResources) { + double priority = gatherResource.getPriority(mod); + + if (priority > maxPriority) { + maxPriority = priority; + toGather = gatherResource; + } + } + + if (toGather != null) { + setDebugState("Priority: " + String.format(Locale.US,"%.2f",maxPriority) + ", "+toGather.getDescription()); + if (prevLastGather == toGather && lastGather.getPriority(mod) > 0 && isTaskRunning(mod, lastTask)) { + mod.logWarning("might be stuck or switching too much, forcing current resource for a bit more"); + changedTaskTimer.reset(); + prevLastGather = null; //do not force infinitely, 3 sec should be enough I hope + setDebugState("Priority: FORCED, "+lastGather.getDescription()); + return lastTask; + } + if (lastGather == toGather && toGather.canCacheTask()) { + return lastTask; + } + if (lastGather != toGather) { + taskChanges.add(0,new TaskChange(lastGather,toGather,mod.getPlayer().getBlockPos())); + } + + + if (taskChanges.size() >= 3) { + TaskChange t1 = taskChanges.get(0); + TaskChange t2 = taskChanges.get(1); + TaskChange t3 = taskChanges.get(2); + + if (t1.original == t2.interrupt && t1.pos.isWithinDistance(t3.pos,5) && t3.original == t1.interrupt) { + forcedTaskTimer.reset(); + mod.logWarning("Probably stuck! Forcing timer..."); + taskChanges.clear(); + return lastTask; + } + if (taskChanges.size() > 3) { + taskChanges.remove(taskChanges.size()-1); + } + } + + + prevLastGather = lastGather; + lastGather = toGather; + + Task task; + + if (toGather.data.isPresent()) { + Object data = toGather.data.get(); + if (data instanceof String codeName) { + task = TaskCatalogue.getItemTask(codeName, toGather.maxCount); + } else if (data instanceof Task buildInTask) { + task = buildInTask; + } else { + throw new IllegalStateException("Invalid gather resource data!"); + } + } else { + // if code name isn't present toGather shouldn't have more params + task = TaskCatalogue.getItemTask(toGather.toCollect[0], toGather.maxCount); + } + + Predicate isCraftingTableTask = craftingTask -> { + if (craftingTask instanceof DoStuffInContainerTask cont) { + return cont.getContainerTarget().matches(Items.CRAFTING_TABLE); + } + return false; + }; + + if (lastTask instanceof SmeltInFurnaceTask && !(task instanceof SmeltInFurnaceTask) && !mod.getItemStorage().hasItem(Items.FURNACE)) { + pickupFurnace = true; + lastGather = null; + lastTask = null; + StorageHelper.closeScreen(); + return null; + } else if (lastTask instanceof SmeltInSmokerTask && !(task instanceof SmeltInSmokerTask) && !mod.getItemStorage().hasItem(Items.SMOKER)) { + pickupSmoker = true; + lastGather = null; + lastTask = null; + StorageHelper.closeScreen(); + return null; + } else if (lastTask != null && task != null && lastTask.thisOrChildSatisfies(isCraftingTableTask) && !toGather.needsCraftingOnStart(mod)) { + pickupCrafting = true; + lastGather = null; + lastTask = null; + StorageHelper.closeScreen(); + return null; + } + + lastTask = task; + + changedTaskTimer.reset(); + return task; + } + + if (needsBuildingMaterials(mod)) { + setDebugState("Collecting building materials."); + return buildMaterialsTask; + } + // Then go to the nether. + setDebugState("Going to Nether"); + + // DO NOT INTERRUPT GOING TO NETHER + gatherResources.clear(); + + //prevents from getting stuck + if (!(lastTask instanceof DefaultGoToDimensionTask)) { + goToNetherTask = new DefaultGoToDimensionTask(Dimension.NETHER); + } + lastTask = goToNetherTask; + return goToNetherTask; + } + case NETHER -> { + if (isTaskRunning(mod, safeNetherPortalTask)) { + return safeNetherPortalTask; + } + + if (mod.getPlayer().getPortalCooldown() != 0 && safeNetherPortalTask == null) { + safeNetherPortalTask = new SafeNetherPortalTask(); + return safeNetherPortalTask; + } + + mod.getInputControls().release(Input.MOVE_FORWARD); + mod.getInputControls().release(Input.MOVE_LEFT); + mod.getInputControls().release(Input.SNEAK); + + BlockPos pos = mod.getPlayer().getSteppingPos(); + if (!escaped && mod.getWorld().getBlockState(pos).getBlock().equals(Blocks.SOUL_SAND) && + (mod.getWorld().getBlockState(pos.east()).getBlock().equals(Blocks.OBSIDIAN) || + mod.getWorld().getBlockState(pos.west()).getBlock().equals(Blocks.OBSIDIAN) || + mod.getWorld().getBlockState(pos.south()).getBlock().equals(Blocks.OBSIDIAN) || + mod.getWorld().getBlockState(pos.north()).getBlock().equals(Blocks.OBSIDIAN))) { + + LookHelper.lookAt(mod, pos); + mod.getInputControls().hold(Input.CLICK_LEFT); + return null; + } + if (!escaped) { + escaped = true; + mod.getInputControls().release(Input.CLICK_LEFT); + } + + + // make new pickaxe if old one breaks + ItemStorageTracker itemStorage = mod.getItemStorage(); + if (itemStorage.getItemCount(Items.DIAMOND) >= 3 && !itemStorage.hasItem(Items.DIAMOND_PICKAXE, Items.IRON_PICKAXE)) { + return TaskCatalogue.getItemTask(Items.DIAMOND_PICKAXE, 1); + } else if (itemStorage.getItemCount(Items.IRON_INGOT) >= 3 && !itemStorage.hasItem(Items.DIAMOND_PICKAXE, Items.IRON_PICKAXE)) { + return TaskCatalogue.getItemTask(Items.IRON_PICKAXE, 1); + } else if (!itemStorage.hasItem(Items.DIAMOND_PICKAXE, Items.IRON_PICKAXE, Items.STONE_PICKAXE)) { + return TaskCatalogue.getItemTask(Items.STONE_PICKAXE, 1); + } + if (!itemStorage.hasItem(Items.DIAMOND_PICKAXE, Items.IRON_PICKAXE, Items.STONE_PICKAXE, Items.WOODEN_PICKAXE)) { + return TaskCatalogue.getItemTask(Items.WOODEN_PICKAXE, 1); + } + + if (mod.getItemStorage().getItemCount(Items.BLAZE_ROD) * 2 + mod.getItemStorage().getItemCount(Items.BLAZE_POWDER) + mod.getItemStorage().getItemCount(Items.ENDER_EYE) >= 14) { + hasRods = true; + } + + double rodDistance = mod.getBlockScanner().distanceToClosest(Blocks.NETHER_BRICKS); + double pearlDistance = mod.getBlockScanner().distanceToClosest(Blocks.TWISTING_VINES, Blocks.TWISTING_VINES_PLANT, Blocks.WARPED_HYPHAE, Blocks.WARPED_NYLIUM); + + if (pearlDistance == Double.POSITIVE_INFINITY && rodDistance == Double.POSITIVE_INFINITY) { + setDebugState("Neither fortress or warped forest found... wandering"); + if (isTaskRunning(mod, searchTask)) { + return searchTask; + } + + searchTask = new SearchChunkForBlockTask(Blocks.TWISTING_VINES, Blocks.TWISTING_VINES_PLANT, Blocks.WARPED_HYPHAE, Blocks.WARPED_NYLIUM, Blocks.NETHER_BRICKS); + return searchTask; + } + + if ((rodDistance < pearlDistance && !hasRods && !gettingPearls) || !needsEnderPearls) { + if (!gotToFortress) { + if (mod.getBlockScanner().anyFoundWithinDistance(5, Blocks.NETHER_BRICKS)) { + gotToFortress = true; + } else { + if (!mod.getBlockScanner().anyFound(Blocks.NETHER_BRICKS)) { + setDebugState("Searching for fortress"); + return new TimeoutWanderTask(); + } + + if (WorldHelper.inRangeXZ(mod.getPlayer().getPos(), + WorldHelper.toVec3d(mod.getBlockScanner().getNearestBlock(Blocks.NETHER_BRICKS).get()), 2)) { + + setDebugState("trying to get to fortress"); + return new GetToBlockTask(mod.getBlockScanner().getNearestBlock(Blocks.NETHER_BRICKS).get()); + } + + setDebugState("Getting close to fortress"); + + if (cachedFortressTask != null && !fortressTimer.elapsed() && + mod.getPlayer().getPos().distanceTo(WorldHelper.toVec3d(cachedFortressTask.blockPos)) - 1 > prevPos.getManhattanDistance(cachedFortressTask.blockPos) / 2d) { + mod.log(mod.getPlayer().getPos().distanceTo(WorldHelper.toVec3d(cachedFortressTask.blockPos)) + " : " + prevPos.getManhattanDistance(cachedFortressTask.blockPos) / 2); + return cachedFortressTask; + } + + // 'isEqual' is fucking me up here, so I have to reset the task + if (resetFortressTask) { + resetFortressTask = false; + return null; + } + resetFortressTask = true; + + fortressTimer.reset(); + mod.log("new"); + + prevPos = mod.getPlayer().getBlockPos(); + + BlockPos p = mod.getBlockScanner().getNearestBlock(Blocks.NETHER_BRICKS).get(); + int distance = (int) (mod.getPlayer().getPos().distanceTo(WorldHelper.toVec3d(p)) / 2); + if (cachedFortressTask != null) { + // prevents from getting stuck in place + distance = Math.min(cachedFortressTask.range - 1, distance); + } + if (distance < 0) { + gotToFortress = true; + } else { + cachedFortressTask = new GetWithinRangeOfBlockTask(p, distance); + return cachedFortressTask; + } + } + } + setDebugState("Getting Blaze Rods"); + return getBlazeRodsTask(mod, blazeRodTarget); + } + + if (mod.getBlockScanner().anyFound(Blocks.TWISTING_VINES, Blocks.TWISTING_VINES_PLANT, Blocks.WARPED_HYPHAE, Blocks.WARPED_NYLIUM) || hasRods) { + gettingPearls = true; + setDebugState("Getting Ender Pearls"); + Optional closestBlock = mod.getBlockScanner().getNearestBlock(Blocks.TWISTING_VINES, Blocks.TWISTING_VINES_PLANT, Blocks.WARPED_HYPHAE, Blocks.WARPED_NYLIUM); + + + searchBiomeTask.reset(); + if (closestBlock.isPresent()) { + if (!WorldHelper.inRangeXZ(mod.getPlayer(), closestBlock.get(), 30) && !gotToBiome) { + setDebugState("Going to biome"); + + return new GetToBlockTask(closestBlock.get()); + } else { + gotToBiome = true; + } + } else { + setDebugState("biome not found, wandering"); + return new TimeoutWanderTask(); + } + + return getEnderPearlTask(mod, enderPearlTarget); + } + setDebugState("TIMEOUT.. SHIT"); + + return new TimeoutWanderTask(); + } + case END -> throw new UnsupportedOperationException("You're in the end. Don't collect eyes here."); + } + return null; + } + + //TODO move to ItemHelper + public static int getCountWithCraftedFromOre(AltoClef mod, Item item) { + if (item == Items.RAW_IRON) { + int count = mod.getItemStorage().getItemCount(Items.RAW_IRON, Items.IRON_INGOT); + count += mod.getItemStorage().getItemCount(Items.BUCKET, Items.WATER_BUCKET, Items.LAVA_BUCKET, Items.AXOLOTL_BUCKET, Items.POWDER_SNOW_BUCKET) * 3; + count += hasItem(mod, Items.SHIELD) ? 1 : 0; + count += hasItem(mod, Items.FLINT_AND_STEEL) ? 1 : 0; + + count += hasItem(mod, Items.IRON_SWORD) ? 2 : 0; + count += hasItem(mod, Items.IRON_PICKAXE) ? 3 : 0; + + count += hasItem(mod, Items.IRON_HELMET) ? 5 : 0; + count += hasItem(mod, Items.IRON_CHESTPLATE) ? 8 : 0; + count += hasItem(mod, Items.IRON_LEGGINGS) ? 7 : 0; + count += hasItem(mod, Items.IRON_BOOTS) ? 4 : 0; + + return count; + } else if (item == Items.RAW_GOLD) { + int count = mod.getItemStorage().getItemCount(Items.RAW_GOLD, Items.GOLD_INGOT); + count += hasItem(mod, Items.GOLDEN_PICKAXE) ? 3 : 0; + + count += hasItem(mod, Items.GOLDEN_HELMET) ? 5 : 0; + count += hasItem(mod, Items.GOLDEN_CHESTPLATE) ? 8 : 0; + count += hasItem(mod, Items.GOLDEN_LEGGINGS) ? 7 : 0; + count += hasItem(mod, Items.GOLDEN_BOOTS) ? 4 : 0; + + return count; + } else if (item == Items.DIAMOND) { + int count = mod.getItemStorage().getItemCount(Items.DIAMOND); + count += hasItem(mod, Items.DIAMOND_SWORD) ? 2 : 0; + count += hasItem(mod, Items.DIAMOND_PICKAXE) ? 3 : 0; + + count += hasItem(mod, Items.DIAMOND_HELMET) ? 5 : 0; + count += hasItem(mod, Items.DIAMOND_CHESTPLATE) ? 8 : 0; + count += hasItem(mod, Items.DIAMOND_LEGGINGS) ? 7 : 0; + count += hasItem(mod, Items.DIAMOND_BOOTS) ? 4 : 0; + + return count; + } + + throw new IllegalStateException("Invalid ore item: " + item); + } + + +} diff --git a/src/main/java/adris/altoclef/tasks/speedrun/beatgame/CollectFoodPriorityCalculator.java b/src/main/java/adris/altoclef/tasks/speedrun/beatgame/CollectFoodPriorityCalculator.java new file mode 100644 index 00000000..029df4f4 --- /dev/null +++ b/src/main/java/adris/altoclef/tasks/speedrun/beatgame/CollectFoodPriorityCalculator.java @@ -0,0 +1,206 @@ +package adris.altoclef.tasks.speedrun.beatgame; + +import adris.altoclef.AltoClef; +import adris.altoclef.tasks.resources.CollectFoodTask; +import adris.altoclef.util.helpers.StorageHelper; +import adris.altoclef.util.helpers.WorldHelper; +import adris.altoclef.util.slots.Slot; +import net.minecraft.block.*; +import net.minecraft.entity.Entity; +import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.math.BlockPos; + +import java.util.Optional; +import java.util.function.Predicate; + +import static adris.altoclef.tasks.resources.CollectFoodTask.*; + +/** + * partial copy of CollectFoodTask.java, might be a good idea to somehow use the methods there instead of copying them + * this class is needed because if we calculate the priority to something and then the tasks goes somewhere else it can cause it to get stuck + */ + +public class CollectFoodPriorityCalculator implements GatherResource.PriorityCalculator { + + private final AltoClef mod; + private final double foodUnits; + + public CollectFoodPriorityCalculator(AltoClef mod, double foodUnits) { + this.mod = mod; + this.foodUnits = foodUnits; + } + + @Override + public double calculate(Item[] items, int count, int minCount, int maxCount) { + double distance = getDistance(mod); + + double multiplier = 1; + double foodPotential = CollectFoodTask.calculateFoodPotential(mod); + + //prevents from going to the nether without any food + if (distance == Double.NEGATIVE_INFINITY && foodPotential < foodUnits) return 0.1d; + + Optional hay = mod.getBlockScanner().getNearestBlock(Blocks.HAY_BLOCK); + if ((hay.isPresent() && WorldHelper.inRangeXZ(hay.get(),mod.getPlayer().getBlockPos(),75))|| mod.getEntityTracker().itemDropped(Items.HAY_BLOCK)) { + multiplier = 50; + } + + if (foodPotential > foodUnits) { + if (foodPotential > foodUnits+20) return Double.NEGATIVE_INFINITY; + + if (distance > 10) return Double.NEGATIVE_INFINITY; + + return 17 / distance * (30 / (count / 2d)); + } + + if (foodPotential < 10) { + multiplier = Math.max(11d / foodPotential,22); + } + return 33 / distance * 37 * multiplier; + } + + private double getDistance(AltoClef mod) { + PlayerEntity player = mod.getPlayer(); + + // Hay blocks + double hayTaskBlock = this.pickupBlockTaskOrNull(mod, Blocks.HAY_BLOCK, Items.HAY_BLOCK, 300); + if (hayTaskBlock != Double.NEGATIVE_INFINITY) { + return hayTaskBlock; + } + // Crops + for (CollectFoodTask.CropTarget target : CROPS) { + // If crops are nearby. Do not replant cause we don't care. + double t = pickupBlockTaskOrNull(mod, target.cropBlock, target.cropItem, (blockPos -> { + BlockState s = mod.getWorld().getBlockState(blockPos); + Block b = s.getBlock(); + if (b instanceof CropBlock) { + boolean isWheat = !(b instanceof PotatoesBlock || b instanceof CarrotsBlock || b instanceof BeetrootsBlock); + if (isWheat) { + // Chunk needs to be loaded for wheat maturity to be checked. + if (!mod.getChunkTracker().isChunkLoaded(blockPos)) { + return false; + } + // Prune if we're not mature/fully grown wheat. + CropBlock crop = (CropBlock) b; + return crop.isMature(s); + } + } + // Unbreakable. + return WorldHelper.canBreak(mod, blockPos); + // We're not wheat so do NOT reject. + }), 96); + if (t != Double.NEGATIVE_INFINITY) { + return t; + } + } + // Cooked foods + double bestScore = 0; + Entity bestEntity = null; + Predicate notBaby = entity -> entity instanceof LivingEntity livingEntity && !livingEntity.isBaby(); + + for (CollectFoodTask.CookableFoodTarget cookable : COOKABLE_FOODS) { + if (!mod.getEntityTracker().entityFound(cookable.mobToKill)) continue; + Optional nearest = mod.getEntityTracker().getClosestEntity(mod.getPlayer().getPos(), notBaby, cookable.mobToKill); + if (nearest.isEmpty()) continue; // ?? This crashed once? + int hungerPerformance = cookable.getCookedUnits(); + double sqDistance = nearest.get().squaredDistanceTo(mod.getPlayer()); + double score = (double) 100 * hungerPerformance / (sqDistance); + if (cookable.isFish()) { + score = 0; + } + if (score > bestScore) { + bestScore = score; + bestEntity = nearest.get(); + } + } + if (bestEntity != null) { + return bestEntity.distanceTo(player); + } + + // Sweet berries (separate from crops because they should have a lower priority than everything else cause they suck) + double berryPickup = pickupBlockTaskOrNull(mod, Blocks.SWEET_BERRY_BUSH, Items.SWEET_BERRIES, 96); + if (berryPickup != Double.NEGATIVE_INFINITY) { + return berryPickup; + } + + return Double.POSITIVE_INFINITY; + } + + private double pickupBlockTaskOrNull(AltoClef mod, Block blockToCheck, Item itemToGrab, double maxRange) { + return pickupBlockTaskOrNull(mod, blockToCheck, itemToGrab, toAccept -> true, maxRange); + } + + private double pickupBlockTaskOrNull(AltoClef mod, Block blockToCheck, Item itemToGrab, Predicate accept, double maxRange) { + Predicate acceptPlus = (blockPos) -> { + if (!WorldHelper.canBreak(mod, blockPos)) return false; + return accept.test(blockPos); + }; + Optional nearestBlock = mod.getBlockScanner().getNearestBlock(mod.getPlayer().getPos(), acceptPlus, blockToCheck); + + if (nearestBlock.isPresent() && !nearestBlock.get().isWithinDistance(mod.getPlayer().getPos(), maxRange)) { + nearestBlock = Optional.empty(); + } + + Optional nearestDrop = Optional.empty(); + if (mod.getEntityTracker().itemDropped(itemToGrab)) { + nearestDrop = mod.getEntityTracker().getClosestItemDrop(mod.getPlayer().getPos(), itemToGrab); + } + + + if (nearestDrop.isPresent()) { + return nearestDrop.get().distanceTo(mod.getPlayer()); + } + if (nearestBlock.isPresent()) { + return Math.sqrt(mod.getPlayer().squaredDistanceTo(WorldHelper.toVec3d(nearestBlock.get()))); + } + + return Double.NEGATIVE_INFINITY; + } + + + private double pickupTaskOrNull(AltoClef mod, Item itemToGrab, double maxRange) { + Optional nearestDrop = Optional.empty(); + if (mod.getEntityTracker().itemDropped(itemToGrab)) { + nearestDrop = mod.getEntityTracker().getClosestItemDrop(mod.getPlayer().getPos(), itemToGrab); + } + if (nearestDrop.isPresent()) { + if (nearestDrop.get().isInRange(mod.getPlayer(), maxRange)) { + if (mod.getItemStorage().getSlotsThatCanFitInPlayerInventory(nearestDrop.get().getStack(), false).isEmpty()) { + Optional slot = StorageHelper.getGarbageSlot(mod); + + // tf am I supposed to do if its empty + if (slot.isPresent()) { + ItemStack stack = StorageHelper.getItemStackInSlot(slot.get()); + if (stack.getItem().isFood()) { + // calculate priority, if the item laying on the ground has lower priority than the one we are gonna throw out because of it + // dont pick it up, otherwise we would get stuck in an infinite loop + int inventoryCost = stack.getItem().getFoodComponent().getHunger() * stack.getCount(); + + double hunger = 0; + if (itemToGrab.isFood()) { + hunger = itemToGrab.getFoodComponent().getHunger(); + } else if (itemToGrab.equals(Items.WHEAT)) { + hunger += Items.BREAD.getFoodComponent().getHunger() / 3d; + } else { + mod.log("unknown food item: " + itemToGrab); + } + int groundCost = (int) (hunger * nearestDrop.get().getStack().getCount()); + + if (inventoryCost > groundCost) return Double.NEGATIVE_INFINITY; + } + } + } + + return nearestDrop.get().distanceTo(mod.getPlayer()); + } + } + return Double.NEGATIVE_INFINITY; + } + + +} diff --git a/src/main/java/adris/altoclef/tasks/speedrun/beatgame/GatherResource.java b/src/main/java/adris/altoclef/tasks/speedrun/beatgame/GatherResource.java new file mode 100644 index 00000000..59d4c07e --- /dev/null +++ b/src/main/java/adris/altoclef/tasks/speedrun/beatgame/GatherResource.java @@ -0,0 +1,163 @@ +package adris.altoclef.tasks.speedrun.beatgame; + +import adris.altoclef.AltoClef; +import net.minecraft.item.Item; +import net.minecraft.item.Items; + +import java.util.Arrays; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Predicate; + + +public final class GatherResource { + public final int minCount; + public final int maxCount; + public final Item[] toCollect; + private final Predicate canGather; + private boolean shouldForce = false; + private boolean canCache = true; + private PriorityCalculator priorityCalculator; + public Optional data; + public boolean minCountSatisfied = false; + public boolean maxCountSatisfied = false; + + //this can be used if we are sure we would want to end this task earlier than 3 seconds after being invoked + private boolean bypassForceCooldown = false; + private Predicate needsCraftingOnStart = ((mod) -> false); + private String description; + + public GatherResource(int minCount, int maxCount, PriorityCalculator priorityCalculator, + Predicate canGather, Item... toCollect) { + this(minCount, maxCount, priorityCalculator, canGather, Optional.empty(), toCollect); + } + + public GatherResource(int minCount, int maxCount, PriorityCalculator priorityCalculator, + Predicate canGather, Optional data, Item... toCollect) { + this.minCount = minCount; + this.maxCount = maxCount; + this.priorityCalculator = priorityCalculator; + this.canGather = canGather; + this.data = data; + this.toCollect = toCollect; + + this.description = "gather items: " + Arrays.toString(toCollect); + } + + + /** + * @return the priority of this resource + */ + public double getPriority(AltoClef mod) { + int count = mod.getItemStorage().getItemCount(toCollect); + + //special case for ores + if (toCollect.length == 1) { + Item item = toCollect[0]; + if (item == Items.RAW_IRON || item == Items.RAW_GOLD || item == Items.DIAMOND) { + count = BeatMinecraftTask.getCountWithCraftedFromOre(mod, item); + } + } + + if (minCountSatisfied) { + count = Math.max(count, minCount); + } + if (count >= minCount) { + minCountSatisfied = true; + } + + if (count >= maxCount || maxCountSatisfied) { + maxCountSatisfied = true; + return Double.NEGATIVE_INFINITY; + } + + if (!canGather.test(toCollect)) return Double.NEGATIVE_INFINITY; + + return priorityCalculator.calculate(toCollect, count, minCount, maxCount); + } + + public GatherResource withPriorityCalculator(PriorityCalculator calculator) { + this.priorityCalculator = calculator; + return this; + } + + public GatherResource withBypassForceCooldown(boolean value) { + this.bypassForceCooldown = value; + return this; + } + + public String getDescription() { + return description; + } + + public GatherResource withDescription(String description) { + this.description = description; + return this; + } + + public boolean bypassesForceCooldown() { + return bypassForceCooldown; + } + + public GatherResource withShouldForce(boolean value) { + this.shouldForce = value; + return this; + } + + public boolean shouldForceTask() { + return shouldForce; + } + + public GatherResource withCanCache(boolean value) { + this.canCache = value; + return this; + } + + public boolean canCacheTask() { + return canCache; + } + + public GatherResource withNeedsCraftingOnStart(Predicate value) { + this.needsCraftingOnStart = value; + return this; + } + + public boolean needsCraftingOnStart(AltoClef mod) { + return needsCraftingOnStart.test(mod); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (GatherResource) obj; + return this.minCount == that.minCount && + this.maxCount == that.maxCount && + Objects.equals(this.priorityCalculator, that.priorityCalculator) && + Objects.equals(this.canGather, that.canGather) && + Objects.equals(this.data, that.data) && + Objects.equals(this.toCollect, that.toCollect); + } + + @Override + public int hashCode() { + return Objects.hash(minCount, maxCount, priorityCalculator, canGather, data, toCollect); + } + + @Override + public String toString() { + return "GatherResource[" + + "minCount=" + minCount + ", " + + "maxCount=" + maxCount + ", " + + "priorityCalculator=" + priorityCalculator + ", " + + "canGather=" + canGather + ", " + + "data=" + data + ", " + + "toCollect=" + Arrays.toString(toCollect) + ']'; + } + + public interface PriorityCalculator { + double calculate(Item[] items, int count, int minCount, int maxCount); + } + + +} diff --git a/src/main/java/adris/altoclef/tasks/squashed/CataloguedResourceTask.java b/src/main/java/adris/altoclef/tasks/squashed/CataloguedResourceTask.java index 809cc94c..b75e7868 100644 --- a/src/main/java/adris/altoclef/tasks/squashed/CataloguedResourceTask.java +++ b/src/main/java/adris/altoclef/tasks/squashed/CataloguedResourceTask.java @@ -15,24 +15,24 @@ public class CataloguedResourceTask extends ResourceTask { - private final TaskSquasher _squasher; - private final ItemTarget[] _targets; - private final List _tasksToComplete; + private final TaskSquasher squasher; + private final ItemTarget[] targets; + private final List tasksToComplete; public CataloguedResourceTask(boolean squash, ItemTarget... targets) { super(targets); - _squasher = new TaskSquasher(); - _targets = targets; - _tasksToComplete = new ArrayList<>(targets.length); + squasher = new TaskSquasher(); + this.targets = targets; + tasksToComplete = new ArrayList<>(targets.length); for (ItemTarget target : targets) { if (target != null) { - _tasksToComplete.add(TaskCatalogue.getItemTask(target)); + tasksToComplete.add(TaskCatalogue.getItemTask(target)); } } if (squash) { - squashTasks(_tasksToComplete); + squashTasks(tasksToComplete); } } @@ -47,7 +47,7 @@ protected void onResourceStart(AltoClef mod) { @Override protected Task onResourceTick(AltoClef mod) { - for (ResourceTask task : _tasksToComplete) { + for (ResourceTask task : tasksToComplete) { for (ItemTarget target : task.getItemTargets()) { // If we failed to meet this task's targets, do the task. if (!StorageHelper.itemTargetsMetInventory(mod, target)) return task; @@ -58,7 +58,7 @@ protected Task onResourceTick(AltoClef mod) { @Override public boolean isFinished(AltoClef mod) { - for (ResourceTask task : _tasksToComplete) { + for (ResourceTask task : tasksToComplete) { for (ItemTarget target : task.getItemTargets()) { if (!StorageHelper.itemTargetsMetInventory(mod, target)) return false; } @@ -81,20 +81,20 @@ protected void onResourceStop(AltoClef mod, Task interruptTask) { @Override protected boolean isEqualResource(ResourceTask other) { if (other instanceof CataloguedResourceTask task) { - return Arrays.equals(task._targets, _targets); + return Arrays.equals(task.targets, targets); } return false; } @Override protected String toDebugStringName() { - return "Get catalogued: " + ArrayUtils.toString(_targets); + return "Get catalogued: " + ArrayUtils.toString(targets); } private void squashTasks(List tasks) { - _squasher.addTasks(tasks); + squasher.addTasks(tasks); tasks.clear(); - tasks.addAll(_squasher.getSquashed()); + tasks.addAll(squasher.getSquashed()); } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/src/main/java/adris/altoclef/tasks/stupid/BeeMovieTask.java b/src/main/java/adris/altoclef/tasks/stupid/BeeMovieTask.java deleted file mode 100644 index 72652ba8..00000000 --- a/src/main/java/adris/altoclef/tasks/stupid/BeeMovieTask.java +++ /dev/null @@ -1,283 +0,0 @@ -package adris.altoclef.tasks.stupid; - -import adris.altoclef.AltoClef; -import adris.altoclef.Debug; -import adris.altoclef.tasks.construction.DestroyBlockTask; -import adris.altoclef.tasks.construction.PlaceSignTask; -import adris.altoclef.tasks.construction.PlaceStructureBlockTask; -import adris.altoclef.tasks.resources.MineAndCollectTask; -import adris.altoclef.tasks.squashed.CataloguedResourceTask; -import adris.altoclef.tasksystem.Task; -import adris.altoclef.util.ItemTarget; -import adris.altoclef.util.MiningRequirement; -import adris.altoclef.util.helpers.ItemHelper; -import adris.altoclef.util.helpers.WorldHelper; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.client.MinecraftClient; -import net.minecraft.item.Item; -import net.minecraft.item.Items; -import net.minecraft.util.math.BlockPos; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; - -/** - * Takes a stream input, like from a file, and places signs in a line that say the contents - * of that stream. Use for absurd bullshit like making a bot that prints out the ENTIRE bee movie script - * with signs. - */ -public class BeeMovieTask extends Task { - - // How many building materials to collect/buffer up - private static final int STRUCTURE_MATERIALS_BUFFER = 64; - - private final BlockPos _start; - private final BlockPos _direction = new BlockPos(0, 0, -1); - - private final StreamedSignStringParser _textParser; - - private final String _uniqueId; - private final Task _extraSignAcquireTask; - private final Task _structureMaterialsTask; - private final List _cachedStrings = new ArrayList<>(); - // Grab extra resources and acquire extra tools for speed - private final boolean _sharpenTheAxe = true; - private boolean _finished = false; - private PlaceSignTask _currentPlace = null; - - public BeeMovieTask(String uniqueId, BlockPos start, InputStreamReader input) { - _uniqueId = uniqueId; - _start = start; - _textParser = new StreamedSignStringParser(input); - - _extraSignAcquireTask = new CataloguedResourceTask(new ItemTarget("sign", 256));//TaskCatalogue.getItemTask("sign", 32); - _structureMaterialsTask = new MineAndCollectTask(new ItemTarget(new Item[]{Items.DIRT, Items.COBBLESTONE}, STRUCTURE_MATERIALS_BUFFER), new Block[]{Blocks.STONE, Blocks.COBBLESTONE, Blocks.DIRT, Blocks.GRASS, Blocks.GRASS_BLOCK}, MiningRequirement.WOOD); - } - - private static int sign(int num) { - return Integer.compare(num, 0); - } - - private static boolean isSign(Block block) { - if (block == null) return false; - Block[] candidates = ItemHelper.WOOD_SIGNS_ALL; - for (Block candidate : candidates) { - if (block == candidate) return true; - } - return false; - } - - @Override - protected void onStart(AltoClef mod) { - mod.getBehaviour().push(); - // Prevent mineshaft garbage - mod.getBehaviour().setExclusivelyMineLogs(true); - - // Avoid breaking the ground below the signs. - mod.getBehaviour().avoidBlockBreaking(this::isOnPath); - // Avoid placing blocks where the signs should be placed. - mod.getBehaviour().avoidBlockPlacing(block -> isOnPath(block.down())); - } - - // Whether a block pos is on the path of its signs. - private boolean isOnPath(BlockPos pos) { - BlockPos bottomStart = _start.down(); - BlockPos delta = pos.subtract(bottomStart); - return sign(delta.getX()) == sign(_direction.getX()) - && sign(delta.getY()) == sign(_direction.getY()) - && sign(delta.getZ()) == sign(_direction.getZ()); - } - - @Override - protected Task onTick(AltoClef mod) { - - if (_currentPlace != null && _currentPlace.isActive() && !_currentPlace.isFinished(mod)) { - setDebugState("Placing..."); - return _currentPlace; - } - - if (_sharpenTheAxe) { - if (!mod.getItemStorage().hasItem(Items.DIAMOND_AXE) || !mod.getItemStorage().hasItem(Items.DIAMOND_SHOVEL) || !mod.getItemStorage().hasItem(Items.DIAMOND_PICKAXE)) { - setDebugState("Sharpening the axe: Tools"); - return new CataloguedResourceTask(new ItemTarget(Items.DIAMOND_AXE, 1), new ItemTarget("diamond_shovel", 1), new ItemTarget("diamond_pickaxe", 1)); - } - if (_extraSignAcquireTask.isActive() && !_extraSignAcquireTask.isFinished(mod)) { - setDebugState("Sharpening the axe: Signs"); - return _extraSignAcquireTask; - } - if (!mod.getItemStorage().hasItem(ItemHelper.WOOD_SIGN)) { - // Get a bunch of signs in bulk - return _extraSignAcquireTask; - } - } - - // Get building blocks - int buildCount = mod.getItemStorage().getItemCount(Items.DIRT, Items.COBBLESTONE); - if (buildCount < STRUCTURE_MATERIALS_BUFFER && (buildCount == 0 || _structureMaterialsTask.isActive())) { - setDebugState("Collecting structure blocks..."); - return _structureMaterialsTask; - } - - int signCounter = 0; - // NOTE: This only checks for the EXISTANCE of signs, NOT that they have the proper text. - BlockPos currentSignPos = _start; - while (true) { - assert MinecraftClient.getInstance().world != null; - - - boolean loaded = mod.getChunkTracker().isChunkLoaded(currentSignPos); - - // Clear above - BlockState above = MinecraftClient.getInstance().world.getBlockState(currentSignPos.up()); - if (loaded && !above.isAir() && above.getBlock() != Blocks.WATER) { - setDebugState("Clearing block above to prevent hanging..."); - return new DestroyBlockTask(currentSignPos.up()); - } - - // Fortify below - //BlockState below = MinecraftClient.getInstance().world.getBlockState(currentSignPos.down()); - boolean canPlace = WorldHelper.isSolid(mod, currentSignPos.down());//isSideSolidFullSquare(MinecraftClient.getInstance().world, currentSignPos.down(), Direction.UP); - if (loaded && !canPlace) { - setDebugState("Placing block below for sign placement..."); - return new PlaceStructureBlockTask(currentSignPos.down()); - } - - // Need a sign at this point. - while (_cachedStrings.size() <= signCounter) { - // Load up if we're at a new index. - if (!_textParser.hasNextSign()) { - Debug.logMessage("DONE!!!!"); - _finished = true; - return null; - } - String next = _textParser.getNextSignString(); - Debug.logMessage("NEXT SIGN: " + next); - _cachedStrings.add(next); - } - - - BlockState blockAt = MinecraftClient.getInstance().world.getBlockState(currentSignPos); - - - if (loaded && !isSign(blockAt.getBlock())) { - // INVALID! place. - _currentPlace = new PlaceSignTask(currentSignPos, _cachedStrings.get(signCounter)); - return _currentPlace; - } - - currentSignPos = currentSignPos.add(_direction); - signCounter++; - } - } - - @Override - protected void onStop(AltoClef mod, Task interruptTask) { - mod.getBehaviour().pop(); - } - - @Override - protected boolean isEqual(Task other) { - if (other instanceof BeeMovieTask) { - return ((BeeMovieTask) other)._uniqueId.equals(_uniqueId); - } - return false; - } - - @Override - protected String toDebugString() { - return "Dead Meme \"" + _uniqueId + "\" at " + _start; - } - - @Override - public boolean isFinished(AltoClef mod) { - return _finished; - } - - static class StreamedSignStringParser { - private final BufferedReader _reader; - - private boolean _done = false; - - public StreamedSignStringParser(InputStreamReader source) { - _reader = new BufferedReader(source); - } - - public void open() { - try { - _reader.reset(); - _done = false; - } catch (IOException e) { - // Failed. - e.printStackTrace(); - } - } - - public boolean hasNextSign() { - return !_done; - } - - public String getNextSignString() { - - final double SIGN_TEXT_MAX_WIDTH = 90; - int lineCount = 0; - StringBuilder line = new StringBuilder(); - - StringBuilder result = new StringBuilder(); - - while (true) { - int in; - try { - _reader.mark(1); - in = _reader.read(); - } catch (IOException e) { - e.printStackTrace(); - _done = true; - break; - } - if (in == -1) { - _done = true; - break; - } - char c = (char) in; - //Debug.logMessage("Read " + c); - - line.append(c); - - boolean done = c == '\0'; - - // Can be a special delimiter for a new sign. - - if (c == '\n' || MinecraftClient.getInstance().textRenderer.getWidth(line.toString()) > SIGN_TEXT_MAX_WIDTH) { - line.delete(0, line.length()); - line.append(c); - lineCount++; - if (lineCount >= 4) { - // We're out of bounds. Put the last character back. - try { - _reader.reset(); - } catch (IOException e) { - // Not much to do honestly... - e.printStackTrace(); - } - - done = true; - } - } - - if (done) { - break; - } - - result.append(c); - } - - return result.toString(); - } - } - -} diff --git a/src/main/java/adris/altoclef/tasks/stupid/ReplaceBlocksTask.java b/src/main/java/adris/altoclef/tasks/stupid/ReplaceBlocksTask.java deleted file mode 100644 index baa6f5f6..00000000 --- a/src/main/java/adris/altoclef/tasks/stupid/ReplaceBlocksTask.java +++ /dev/null @@ -1,161 +0,0 @@ -package adris.altoclef.tasks.stupid; - -import adris.altoclef.AltoClef; -import adris.altoclef.Debug; -import adris.altoclef.TaskCatalogue; -import adris.altoclef.eventbus.EventBus; -import adris.altoclef.eventbus.Subscription; -import adris.altoclef.eventbus.events.BlockBrokenEvent; -import adris.altoclef.tasks.DoToClosestBlockTask; -import adris.altoclef.tasks.construction.PlaceBlockTask; -import adris.altoclef.tasks.movement.TimeoutWanderTask; -import adris.altoclef.tasksystem.Task; -import adris.altoclef.util.ItemTarget; -import adris.altoclef.util.helpers.ItemHelper; -import net.minecraft.block.Block; -import net.minecraft.client.MinecraftClient; -import net.minecraft.util.math.BlockPos; -import org.apache.commons.lang3.ArrayUtils; - -import java.util.ArrayDeque; -import java.util.Arrays; -import java.util.Deque; -import java.util.List; - -public class ReplaceBlocksTask extends Task { - - // We won't be asked to collect more materials than this at a single time. - private static final int MAX_MATERIALS_NEEDED_AT_A_TIME = 64; - - private final Block[] _toFind; - private final ItemTarget _toReplace; - - private final BlockPos _from; - private final BlockPos _to; - private final Deque _forceReplace = new ArrayDeque<>(); - private Task _collectMaterialsTask; - private Task _replaceTask; - private Subscription _blockBrokenSubscription; - - public ReplaceBlocksTask(ItemTarget toReplace, BlockPos from, BlockPos to, Block... toFind) { - _toFind = toFind; - _toReplace = toReplace; - _from = from; - _to = to; - } - - public ReplaceBlocksTask(ItemTarget toReplace, Block... toFind) { - this(toReplace, null, null, toFind); - } - - @Override - protected void onStart(AltoClef mod) { - mod.getBehaviour().push(); - mod.getBehaviour().addProtectedItems(_toReplace.getMatches()); - // TODO: Bug: We may want to replace a block that's considered a CONSTRUCTION block. - // If that's the case, we are in trouble. - - mod.getBlockTracker().trackBlock(_toFind); - - //_forceReplace.clear(); - _blockBrokenSubscription = EventBus.subscribe(BlockBrokenEvent.class, evt -> { - if (evt.player.equals(MinecraftClient.getInstance().player)) { - if (isWithinRange(evt.blockPos)) { - boolean wasAReplacable = ArrayUtils.contains(_toFind, evt.blockState.getBlock()); - if (wasAReplacable) { - Debug.logMessage("ADDED REPLACEABLE FORCE: " + evt.blockPos); - _forceReplace.push(evt.blockPos); - } else { - Debug.logMessage("Destroyed a non replaceable block (delete this print if things are good lol)"); - } - } else { - Debug.logMessage("Not within range (TODO: DELETE THIS PRINT)"); - } - } else { - Debug.logMessage("IN-EQUAL PLAYER (delete this print if things are good lol)"); - } - }); - } - - @Override - protected Task onTick(AltoClef mod) { - - if (_collectMaterialsTask != null && _collectMaterialsTask.isActive() && !_collectMaterialsTask.isFinished(mod)) { - setDebugState("Collecting materials..."); - return _collectMaterialsTask; - } - - if (_replaceTask != null && _replaceTask.isActive() && !_replaceTask.isFinished(mod)) { - setDebugState("Replacing a block"); - return _replaceTask; - } - - // Get to replace item - if (!mod.getItemStorage().hasItem(_toReplace.getMatches())) { - List locations = mod.getBlockTracker().getKnownLocations(_toFind); - int need = 0; - if (!locations.isEmpty()) { - for (BlockPos loc : locations) if (isWithinRange(loc) && need < MAX_MATERIALS_NEEDED_AT_A_TIME) need++; - } - if (need == 0) { - setDebugState("No replaceable blocks found, wandering."); - return new TimeoutWanderTask(); - } - _collectMaterialsTask = TaskCatalogue.getItemTask(new ItemTarget(_toReplace, need)); - return _collectMaterialsTask; - //return TaskCatalogue.getItemTask(_toReplace); - } - - Block[] blocksToPlace = ItemHelper.itemsToBlocks(_toReplace.getMatches()); - - // If we are forced to replace something we broke, do it now. - while (!_forceReplace.isEmpty()) { - BlockPos toReplace = _forceReplace.pop(); - if (!ArrayUtils.contains(blocksToPlace, mod.getWorld().getBlockState(toReplace).getBlock())) { - _replaceTask = new PlaceBlockTask(toReplace, blocksToPlace); - return _replaceTask; - } - } - - // Now replace - setDebugState("Searching for blocks to replace..."); - return new DoToClosestBlockTask(whereToPlace -> { - _replaceTask = new PlaceBlockTask(whereToPlace, blocksToPlace); - return _replaceTask; - }, - this::isWithinRange, - _toFind - ); - } - - @Override - protected void onStop(AltoClef mod, Task interruptTask) { - EventBus.unsubscribe(_blockBrokenSubscription); - mod.getBehaviour().pop(); - } - - @Override - protected boolean isEqual(Task other) { - if (other instanceof ReplaceBlocksTask task) { - return task._toReplace.equals(_toReplace) && Arrays.equals(task._toFind, _toFind); - } - return false; - } - - @Override - protected String toDebugString() { - return "Replacing " + Arrays.toString(_toFind) + " with " + _toReplace; - } - - private boolean isWithinRange(BlockPos pos) { - if (_from != null) { - if (_from.getX() > pos.getX() || _from.getY() > pos.getY() || _from.getZ() > pos.getZ()) { - return false; - } - } - if (_to != null) { - return _to.getX() >= pos.getX() && _to.getY() >= pos.getY() && _to.getZ() >= pos.getZ(); - } - return true; - } -} diff --git a/src/main/java/adris/altoclef/tasks/stupid/SCP173Task.java b/src/main/java/adris/altoclef/tasks/stupid/SCP173Task.java deleted file mode 100644 index 6c0d37b9..00000000 --- a/src/main/java/adris/altoclef/tasks/stupid/SCP173Task.java +++ /dev/null @@ -1,142 +0,0 @@ -package adris.altoclef.tasks.stupid; - -import adris.altoclef.AltoClef; -import adris.altoclef.tasks.entity.AbstractKillEntityTask; -import adris.altoclef.tasks.entity.DoToClosestEntityTask; -import adris.altoclef.tasks.movement.GetToEntityTask; -import adris.altoclef.tasksystem.Task; -import adris.altoclef.util.helpers.LookHelper; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.math.Vec3d; - -import java.util.HashMap; - -/** - * Thought this might be fun to program. - *

- * Attacks closest player, but stands still when anyone has direct line of sight on the bot. - *

- * Works well but isn't perfect, since turning around quickly results in movement delay. - *

- * Potential fix: - * - Have a "last velocity" of the change of a player's closeness. If the velocity is high in one direction, stop early. - */ -public class SCP173Task extends Task { - - private static final double MAX_RANGE = 300; - private static final double LOOK_CLOSENESS_THRESHOLD = 0.2; - private static final double HIT_RANGE = 2.5; - private static final double WALK_THRESHOLD = 0.1; - private final HashMap _lastLookCloseness = new HashMap<>(); - private PlayerEntity _lastTarget = null; - private Vec3d _lastWalkVelocity = Vec3d.ZERO; - - @Override - protected void onStart(AltoClef mod) { - _lastLookCloseness.clear(); - } - - @Override - protected Task onTick(AltoClef mod) { - - // FREEZE when nobody is looking. - boolean seen = isSeenByPlayer(mod); - - Vec3d currentVelocity = mod.getPlayer().getVelocity(); - if (currentVelocity.lengthSquared() > WALK_THRESHOLD * WALK_THRESHOLD) { - _lastWalkVelocity = currentVelocity; - } - - if (seen) { - setDebugState("Standing still and being menacing"); - } else { - setDebugState("Scrape Scrape Scrape"); - } - - if (seen) { - // Stare at them, menacingly!!! - if (_lastTarget != null) { - LookHelper.lookAt(mod, LookHelper.getCameraPos(_lastTarget)); - } - return null; - } - - // Manually attack, since we ONLY attack when we can SEE the player. - if (_lastTarget != null && mod.getPlayer().isInRange(_lastTarget, HIT_RANGE)) { - if (LookHelper.seesPlayer(mod.getPlayer(), _lastTarget, HIT_RANGE)) { - // Equip weapon - AbstractKillEntityTask.equipWeapon(mod); - if (mod.getPlayer().getAttackCooldownProgress(0) >= 0.99) { - mod.getControllerExtras().attack(_lastTarget); - } - } - } - - return new DoToClosestEntityTask( - target -> { - _lastTarget = (PlayerEntity) target; - return new GetToEntityTask(target); - }, - PlayerEntity.class - ); - } - - @Override - protected void onStop(AltoClef mod, Task interruptTask) { - - } - - @Override - protected boolean isEqual(Task other) { - return other instanceof SCP173Task; - } - - @Override - protected String toDebugString() { - return "Acting like SCP 173"; - } - - private boolean isSeenByPlayer(AltoClef mod) { - if (mod.getEntityTracker().entityFound(PlayerEntity.class)) { - for (PlayerEntity player : mod.getEntityTracker().getTrackedEntities(PlayerEntity.class)) { - // Player must be NOT looking in our general direction OR NOT have line of sight. - if (entityIsLookingInOurGeneralDirection(mod, player) && entityHasLineOfSightToUs(mod, player)) { - return true; - } - - } - return false; - } - return false; - } - - // We consider if the player is looking in the general direction - // but we ALSO consider when the player is ALMOST looking in the general direction and - // is ROTATING TORWARDS US to try and mitigate the look delay. - private boolean entityIsLookingInOurGeneralDirection(AltoClef mod, PlayerEntity other) { - double lookCloseness = LookHelper.getLookCloseness(other, mod.getPlayer().getPos()); - double last = _lastLookCloseness.getOrDefault(other, lookCloseness); - double delta = lookCloseness - last; - double predicted = lookCloseness + delta * 6; - _lastLookCloseness.put(other, lookCloseness); - return lookCloseness > LOOK_CLOSENESS_THRESHOLD || predicted > LOOK_CLOSENESS_THRESHOLD; - } - - private boolean entityHasLineOfSightToUs(AltoClef mod, PlayerEntity other) { - if (LookHelper.seesPlayer(mod.getPlayer(), other, MAX_RANGE)) { - return true; - } - // Check if we're about to be visible or if the PLAYER is about to be visible. - double playerVelMul = 5; - double entityVelMul = 10; - Vec3d lastVelocityOffs = _lastWalkVelocity.multiply(playerVelMul); - if (!_lastWalkVelocity.equals(Vec3d.ZERO)) { - double minLength = 1.3; - if (lastVelocityOffs.lengthSquared() < minLength * minLength) { - lastVelocityOffs = lastVelocityOffs.normalize().multiply(minLength); - } - } - return LookHelper.seesPlayer(mod.getPlayer(), other, MAX_RANGE, mod.getPlayer().getVelocity().multiply(playerVelMul), other.getVelocity().multiply(entityVelMul)) - || LookHelper.seesPlayer(mod.getPlayer(), other, MAX_RANGE, lastVelocityOffs, Vec3d.ZERO); - } -} diff --git a/src/main/java/adris/altoclef/tasks/stupid/TerminatorTask.java b/src/main/java/adris/altoclef/tasks/stupid/TerminatorTask.java deleted file mode 100644 index 28183b38..00000000 --- a/src/main/java/adris/altoclef/tasks/stupid/TerminatorTask.java +++ /dev/null @@ -1,361 +0,0 @@ -package adris.altoclef.tasks.stupid; - -import adris.altoclef.AltoClef; -import adris.altoclef.Debug; -import adris.altoclef.TaskCatalogue; -import adris.altoclef.tasks.construction.PlaceBlockTask; -import adris.altoclef.tasks.construction.PlaceStructureBlockTask; -import adris.altoclef.tasks.container.SmeltInFurnaceTask; -import adris.altoclef.tasks.entity.DoToClosestEntityTask; -import adris.altoclef.tasks.entity.KillPlayerTask; -import adris.altoclef.tasks.misc.EquipArmorTask; -import adris.altoclef.tasks.movement.RunAwayFromEntitiesTask; -import adris.altoclef.tasks.movement.SearchChunksExploreTask; -import adris.altoclef.tasks.resources.CollectFoodTask; -import adris.altoclef.tasksystem.Task; -import adris.altoclef.ui.MessagePriority; -import adris.altoclef.util.ItemTarget; -import adris.altoclef.util.SmeltTarget; -import adris.altoclef.util.helpers.BaritoneHelper; -import adris.altoclef.util.helpers.ItemHelper; -import adris.altoclef.util.helpers.LookHelper; -import adris.altoclef.util.helpers.StorageHelper; -import adris.altoclef.util.progresscheck.MovementProgressChecker; -import adris.altoclef.util.time.TimerGame; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.Item; -import net.minecraft.item.Items; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.math.Vec3d; - -import java.util.ConcurrentModificationException; -import java.util.List; -import java.util.Optional; -import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * Roams around the world to terminate Sarah Khaannah - */ -public class TerminatorTask extends Task { - - private static final int FEAR_SEE_DISTANCE = 30; - private static final int FEAR_DISTANCE = 20; - private static final int RUN_AWAY_DISTANCE = 80; - - private static final int MIN_BUILDING_BLOCKS = 10; - private static final int PREFERRED_BUILDING_BLOCKS = 60; - - private static Item[] GEAR_TO_COLLECT = new Item[]{ - Items.DIAMOND_PICKAXE, Items.DIAMOND_SHOVEL, Items.DIAMOND_SWORD, Items.WATER_BUCKET - }; - private final Task _prepareDiamondMiningEquipmentTask = TaskCatalogue.getSquashedItemTask( - new ItemTarget(Items.IRON_PICKAXE, 3), new ItemTarget(Items.IRON_SWORD, 1) - ); - private final Task _foodTask = new CollectFoodTask(80); - private final TimerGame _runAwayExtraTime = new TimerGame(10); - private final Predicate _canTerminate; - private final ScanChunksInRadius _scanTask; - private final TimerGame _funnyMessageTimer = new TimerGame(10); - private Vec3d _closestPlayerLastPos; - private Vec3d _closestPlayerLastObservePos; - private Task _runAwayTask; - private String _currentVisibleTarget; - - private Task _armorTask; - - public TerminatorTask(BlockPos center, double scanRadius, Predicate canTerminate) { - _canTerminate = canTerminate; - _scanTask = new ScanChunksInRadius(center, scanRadius); - } - - public TerminatorTask(BlockPos center, double scanRadius) { - this(center, scanRadius, accept -> true); - } - - @Override - protected void onStart(AltoClef mod) { - mod.getBehaviour().push(); - mod.getBehaviour().setForceFieldPlayers(true); - } - - @Override - protected Task onTick(AltoClef mod) { - - Optional closest = mod.getEntityTracker().getClosestEntity(mod.getPlayer().getPos(), toPunk -> shouldPunk(mod, (PlayerEntity) toPunk), PlayerEntity.class); - - if (closest.isPresent()) { - _closestPlayerLastPos = closest.get().getPos(); - _closestPlayerLastObservePos = mod.getPlayer().getPos(); - } - - if (!isReadyToPunk(mod)) { - - if (_runAwayTask != null && _runAwayTask.isActive() && !_runAwayTask.isFinished(mod)) { - // If our last "scare" was too long ago or there are no more nearby players... - boolean noneRemote = (closest.isEmpty() || !closest.get().isInRange(mod.getPlayer(), FEAR_DISTANCE)); - if (_runAwayExtraTime.elapsed() && noneRemote) { - Debug.logMessage("Stop running away, we're good."); - // Stop running away. - _runAwayTask = null; - } else { - return _runAwayTask; - } - } - - // See if there's anyone nearby. - if (mod.getEntityTracker().getClosestEntity(mod.getPlayer().getPos(), entityAccept -> { - if (!shouldPunk(mod, (PlayerEntity) entityAccept)) { - return false; - } - if (entityAccept.isInRange(mod.getPlayer(), 15)) { - // We're close, count us. - return true; - } else { - // Too far away. - if (!entityAccept.isInRange(mod.getPlayer(), FEAR_DISTANCE)) return false; - // We may be far and obstructed, check. - return LookHelper.seesPlayer(entityAccept, mod.getPlayer(), FEAR_SEE_DISTANCE); - } - }, PlayerEntity.class).isPresent()) { - // RUN! - - _runAwayExtraTime.reset(); - try { - _runAwayTask = new RunAwayFromPlayersTask(() -> { - Stream stream = mod.getEntityTracker().getTrackedEntities(PlayerEntity.class).stream(); - synchronized (BaritoneHelper.MINECRAFT_LOCK) { - return stream.filter(toAccept -> shouldPunk(mod, toAccept)).collect(Collectors.toList()); - } - }, RUN_AWAY_DISTANCE); - } catch (ConcurrentModificationException e) { - // oof - Debug.logWarning("Duct tape over ConcurrentModificationException (see log)"); - e.printStackTrace(); - } - setDebugState("Running away from players."); - return _runAwayTask; - } - } else { - // We can totally punk - if (_runAwayTask != null) { - _runAwayTask = null; - Debug.logMessage("Stopped running away because we can now punk."); - } - // Get building materials if we don't have them. - if (PlaceStructureBlockTask.getMaterialCount(mod) < MIN_BUILDING_BLOCKS) { - setDebugState("Collecting building materials"); - return PlaceBlockTask.getMaterialTask(PREFERRED_BUILDING_BLOCKS); - } - - // Get some food so we can last a little longer. - if ((mod.getPlayer().getHungerManager().getFoodLevel() < (20 - 3 * 2) || mod.getPlayer().getHealth() < 10) && StorageHelper.calculateInventoryFoodScore(mod) <= 0) { - return _foodTask; - } - - if (mod.getEntityTracker().getClosestEntity(mod.getPlayer().getPos(), toPunk -> shouldPunk(mod, (PlayerEntity) toPunk), PlayerEntity.class).isPresent()) { - setDebugState("Punking."); - return new DoToClosestEntityTask( - entity -> { - if (entity instanceof PlayerEntity) { - tryDoFunnyMessageTo(mod, (PlayerEntity) entity); - return new KillPlayerTask(entity.getName().getString()); - } - // Should never happen. - Debug.logWarning("This should never happen."); - return _scanTask; - }, - interact -> shouldPunk(mod, (PlayerEntity) interact), - PlayerEntity.class - ); - } - } - - // Get stacked first - // Equip diamond armor asap - if (_armorTask != null && _armorTask.isActive() && !_armorTask.isFinished(mod)) { - setDebugState("Collecting Diamond Armor"); - return _armorTask; - } - - // Get iron pickaxes first - if (!mod.getItemStorage().hasItem(Items.DIAMOND_PICKAXE) && mod.getItemStorage().getItemCount(Items.DIAMOND) < 3) { - if (!mod.getItemStorage().hasItem(Items.IRON_PICKAXE) || (_prepareDiamondMiningEquipmentTask.isActive() && !_prepareDiamondMiningEquipmentTask.isFinished(mod))) { - setDebugState("Getting iron pickaxes to mine diamonds"); - return _prepareDiamondMiningEquipmentTask; - } - } - - // Collect food - if (StorageHelper.calculateInventoryFoodScore(mod) <= 0 || (_foodTask.isActive() && !_foodTask.isFinished(mod))) { - setDebugState("Collecting food"); - return _foodTask; - } - // Raw food - for (Item raw : ItemHelper.RAW_FOODS) { - if (mod.getItemStorage().hasItem(raw)) { - Optional cooked = ItemHelper.getCookedFood(raw); - if (cooked.isPresent()) { - int targetCount = mod.getItemStorage().getItemCount(cooked.get()) + mod.getItemStorage().getItemCount(raw); - setDebugState("Smelting raw food: " + ItemHelper.stripItemName(raw)); - return new SmeltInFurnaceTask(new SmeltTarget(new ItemTarget(cooked.get(), targetCount), new ItemTarget(raw, targetCount))); - } - } - } - - // If we're not all equip, do equip - if (!StorageHelper.isArmorEquippedAll(mod, ItemHelper.DIAMOND_ARMORS)) { - _armorTask = new EquipArmorTask(ItemHelper.DIAMOND_ARMORS); - return _armorTask; - } - - // Get gear one by one... - for (Item gear : GEAR_TO_COLLECT) { - if (!mod.getItemStorage().hasItem(gear)) { - setDebugState("Collecting gear"); - return TaskCatalogue.getItemTask(gear, 1); - } - } - - - setDebugState("Scanning for players..."); - _currentVisibleTarget = null; - if (_scanTask.failedSearch()) { - Debug.logMessage("Re-searching missed places."); - _scanTask.resetSearch(mod); - } - - return _scanTask; - } - - @Override - protected void onStop(AltoClef mod, Task interruptTask) { - mod.getBehaviour().pop(); - } - - @Override - protected boolean isEqual(Task other) { - return other instanceof TerminatorTask; - } - - @Override - protected String toDebugString() { - return "Terminator Task"; - } - - private boolean isReadyToPunk(AltoClef mod) { - if (mod.getPlayer().getHealth() <= 5) return false; // We need to heal. - return StorageHelper.isArmorEquippedAll(mod, ItemHelper.DIAMOND_ARMORS) && mod.getItemStorage().hasItem(Items.DIAMOND_SWORD); - } - - private boolean shouldPunk(AltoClef mod, PlayerEntity player) { - if (player == null || player.isDead()) return false; - if (player.isCreative() || player.isSpectator()) return false; - return !mod.getButler().isUserAuthorized(player.getName().getString()) && _canTerminate.test(player); - } - - private void tryDoFunnyMessageTo(AltoClef mod, PlayerEntity player) { - if (_funnyMessageTimer.elapsed()) { - if (LookHelper.seesPlayer(player, mod.getPlayer(), 80)) { - String name = player.getName().getString(); - if (_currentVisibleTarget == null || !_currentVisibleTarget.equals(name)) { - _currentVisibleTarget = name; - _funnyMessageTimer.reset(); - String funnyMessage = getRandomFunnyMessage(); - mod.getMessageSender().enqueueWhisper(name, funnyMessage, MessagePriority.ASAP); - } - } - } - } - - private String getRandomFunnyMessage() { - return "Prepare to get punked, kid"; - } - - private static class RunAwayFromPlayersTask extends RunAwayFromEntitiesTask { - - public RunAwayFromPlayersTask(Supplier> toRunAwayFrom, double distanceToRun) { - super(toRunAwayFrom, distanceToRun, true, 0.1); - // More lenient progress checker - _checker = new MovementProgressChecker(); - } - - @Override - protected boolean isEqual(Task other) { - return other instanceof RunAwayFromPlayersTask; - } - - @Override - protected String toDebugString() { - return "Running away from players"; - } - } - - private class ScanChunksInRadius extends SearchChunksExploreTask { - - private final BlockPos _center; - private final double _radius; - - public ScanChunksInRadius(BlockPos center, double radius) { - _center = center; - _radius = radius; - } - - @Override - protected boolean isChunkWithinSearchSpace(AltoClef mod, ChunkPos pos) { - double cx = (pos.getStartX() + pos.getEndX()) / 2.0; - double cz = (pos.getStartZ() + pos.getEndZ()) / 2.0; - double dx = _center.getX() - cx, - dz = _center.getZ() - cz; - return dx * dx + dz * dz < _radius * _radius; - } - - @Override - protected ChunkPos getBestChunkOverride(AltoClef mod, List chunks) { - // Prioritise the chunk we last saw a player in. - if (_closestPlayerLastPos != null) { - double lowestScore = Double.POSITIVE_INFINITY; - ChunkPos bestChunk = null; - if (!chunks.isEmpty()) { - for (ChunkPos toSearch : chunks) { - double cx = (toSearch.getStartX() + toSearch.getEndX() + 1) / 2.0, cz = (toSearch.getStartZ() + toSearch.getEndZ() + 1) / 2.0; - double px = mod.getPlayer().getX(), pz = mod.getPlayer().getZ(); - double distanceSq = (cx - px) * (cx - px) + (cz - pz) * (cz - pz); - double pdx = _closestPlayerLastPos.getX() - cx, pdz = _closestPlayerLastPos.getZ() - cz; - double distanceToLastPlayerPos = pdx * pdx + pdz * pdz; - Vec3d direction = _closestPlayerLastPos.subtract(_closestPlayerLastObservePos).multiply(1, 0, 1).normalize(); - double dirx = direction.x, dirz = direction.z; - double correctDistance = pdx * dirx + pdz * dirz; - double tempX = dirx * correctDistance, - tempZ = dirz * correctDistance; - double perpendicularDistance = ((pdx - tempX) * (pdx - tempX)) + ((pdz - tempZ) * (pdz - tempZ)); - double score = distanceSq + distanceToLastPlayerPos * 0.6 - correctDistance * 2 + perpendicularDistance * 0.5; - if (score < lowestScore) { - lowestScore = score; - bestChunk = toSearch; - } - } - } - return bestChunk; - } - return super.getBestChunkOverride(mod, chunks); - } - - @Override - protected boolean isEqual(Task other) { - if (other instanceof ScanChunksInRadius scan) { - return scan._center.equals(_center) && Math.abs(scan._radius - _radius) <= 1; - } - return false; - } - - @Override - protected String toDebugString() { - return "Scanning around a radius"; - } - } -} diff --git a/src/main/java/adris/altoclef/tasksystem/TaskRunner.java b/src/main/java/adris/altoclef/tasksystem/TaskRunner.java index 07523b66..411bb076 100644 --- a/src/main/java/adris/altoclef/tasksystem/TaskRunner.java +++ b/src/main/java/adris/altoclef/tasksystem/TaskRunner.java @@ -7,69 +7,74 @@ public class TaskRunner { - private final ArrayList _chains = new ArrayList<>(); - private final AltoClef _mod; - private boolean _active; + private final ArrayList chains = new ArrayList<>(); + private final AltoClef mod; + private boolean active; - private TaskChain _cachedCurrentTaskChain = null; + private TaskChain cachedCurrentTaskChain = null; + + public String statusReport = " (no chain running) "; public TaskRunner(AltoClef mod) { - _mod = mod; - _active = false; + this.mod = mod; + active = false; } public void tick() { - if (!_active || !AltoClef.inGame()) return; + if (!active || !AltoClef.inGame()) return; // Get highest priority chain and run TaskChain maxChain = null; float maxPriority = Float.NEGATIVE_INFINITY; - for (TaskChain chain : _chains) { + for (TaskChain chain : chains) { if (!chain.isActive()) continue; - float priority = chain.getPriority(_mod); + float priority = chain.getPriority(mod); if (priority > maxPriority) { maxPriority = priority; maxChain = chain; } } - if (_cachedCurrentTaskChain != null && maxChain != _cachedCurrentTaskChain) { - _cachedCurrentTaskChain.onInterrupt(_mod, maxChain); + if (cachedCurrentTaskChain != null && maxChain != cachedCurrentTaskChain) { + cachedCurrentTaskChain.onInterrupt(mod, maxChain); } - _cachedCurrentTaskChain = maxChain; + cachedCurrentTaskChain = maxChain; if (maxChain != null) { - maxChain.tick(_mod); + statusReport = "Chain: "+maxChain.getName() + ", priority: "+maxPriority; + maxChain.tick(mod); + } else { + statusReport = " (no chain running) "; } } public void addTaskChain(TaskChain chain) { - _chains.add(chain); + chains.add(chain); } public void enable() { - if (!_active) { - _mod.getBehaviour().push(); - _mod.getBehaviour().setPauseOnLostFocus(false); + if (!active) { + mod.getBehaviour().push(); + mod.getBehaviour().setPauseOnLostFocus(false); } - _active = true; + active = true; } public void disable() { - if (_active) { - _mod.getBehaviour().pop(); + if (active) { + mod.getBehaviour().pop(); } - for (TaskChain chain : _chains) { - chain.stop(_mod); + for (TaskChain chain : chains) { + chain.stop(mod); } - _active = false; + active = false; Debug.logMessage("Stopped"); } public TaskChain getCurrentTaskChain() { - return _cachedCurrentTaskChain; + return cachedCurrentTaskChain; } // Kinda jank ngl public AltoClef getMod() { - return _mod; + return mod; } } diff --git a/src/main/java/adris/altoclef/trackers/BlockTracker.java b/src/main/java/adris/altoclef/trackers/BlockTracker.java deleted file mode 100644 index d8b065db..00000000 --- a/src/main/java/adris/altoclef/trackers/BlockTracker.java +++ /dev/null @@ -1,695 +0,0 @@ -package adris.altoclef.trackers; - -import adris.altoclef.AltoClef; -import adris.altoclef.Debug; -import adris.altoclef.eventbus.EventBus; -import adris.altoclef.eventbus.events.BlockPlaceEvent; -import adris.altoclef.trackers.blacklisting.WorldLocateBlacklist; -import adris.altoclef.util.Dimension; -import adris.altoclef.util.helpers.BaritoneHelper; -import adris.altoclef.util.helpers.ConfigHelper; -import adris.altoclef.util.helpers.StlHelper; -import adris.altoclef.util.helpers.WorldHelper; -import adris.altoclef.util.time.TimerGame; -import baritone.Baritone; -import baritone.api.utils.BlockOptionalMetaLookup; -import baritone.pathing.movement.CalculationContext; -import baritone.process.MineProcess; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; - -import java.util.*; -import java.util.concurrent.Semaphore; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -/** - * Tracks blocks the way we want it, when we want it. - *

- * Gives you a "Check and don't care" interface where you can check for blocks and their locations over and over again - * without scanning the world over and over again. - *

- * Also keeps track of blacklists for unreachable blocks - */ -public class BlockTracker extends Tracker { - - // This should be moved to an instance variable - // but if set to true, block scanning will happen - // asynchronously to spread out the expensive cost of scanning. - private static final boolean ASYNC_SCANNING = true; - private static BlockTrackerConfig _config = new BlockTrackerConfig(); - - static { - ConfigHelper.loadConfig("configs/block_tracker.json", BlockTrackerConfig::new, BlockTrackerConfig.class, newConfig -> _config = newConfig); - } - - private final HashMap _caches = new HashMap<>(); - - //private final PosCache _cache = new PosCache(100, 64*1.5); - - private final TimerGame _timer = new TimerGame(_config.scanInterval); - - private final TimerGame _forceElapseTimer = new TimerGame(_config.scanIntervalWhenNewBlocksFound); - - // A scan can last no more than 15 seconds - private final TimerGame _asyncForceResetScanFlag = new TimerGame(15); - - private final Map _trackingBlocks = new HashMap<>(); - - private final Object _scanMutex = new Object(); - // Only perform scans at the END of our frame - private final Semaphore _endOfFrameMutex = new Semaphore(1); - //private Block _currentlyTracking = null; - private final AltoClef _mod; - private boolean _scanning = false; - - public BlockTracker(AltoClef mod, TrackerManager manager) { - super(manager); - _mod = mod; - // First time, track immediately - _timer.forceElapse(); - _forceElapseTimer.forceElapse(); - - // Listen for block placement - EventBus.subscribe(BlockPlaceEvent.class, evt -> addBlock(evt.blockState.getBlock(), evt.blockPos)); - } - - @Override - protected void updateState() { - if (shouldUpdate()) { - update(); - } - } - - // We want our `_trackingBlocks` value to be read AFTER tasks have finished ticking - public void preTickTask() { - try { - _endOfFrameMutex.acquire(); - } catch (InterruptedException e) { - Debug.logWarning("Pre-tick failed to acquire block track mutex! (send logs)"); - e.printStackTrace(); - } - } - - public void postTickTask() { - _endOfFrameMutex.release(); - } - - @Override - protected void reset() { - // Tasks will handle de-tracking blocks. - if (!_caches.values().isEmpty()) { - for (PosCache cache : _caches.values()) { - cache.clear(); - } - } - } - - public boolean isTracking(Block block) { - synchronized (_trackingBlocks) { - return _trackingBlocks.containsKey(block) && _trackingBlocks.get(block) > 0; - } - } - - /** - * Starts tracking/pay attention to some blocks. - * IMPORTANT: ALWAYS pair with {@link #stopTracking(Block...) stopTracking}! Otherwise this block type will be - * tracked forever (not the end of the world, but other block types will be lost. - */ - public void trackBlock(Block... blocks) { - synchronized (_trackingBlocks) { - for (Block block : blocks) { - if (!_trackingBlocks.containsKey(block)) { - // We're tracking a new block, so we're not updated. - setDirty(); - _trackingBlocks.put(block, 0); - // Force a rescan if these are new blocks and we aren't doing this like every frame. - if (_forceElapseTimer.elapsed()) { - _timer.forceElapse(); - _forceElapseTimer.reset(); - _forceElapseTimer.setInterval(_config.scanIntervalWhenNewBlocksFound); - } - } - _trackingBlocks.put(block, _trackingBlocks.get(block) + 1); - } - } - } - - /** - * Stops tracking some blocks, after calling {@link #trackBlock(Block...) trackBlock}. - *

- * Only call this once for every {@link #trackBlock(Block...) trackBlock}. - */ - public void stopTracking(Block... blocks) { - synchronized (_trackingBlocks) { - for (Block block : blocks) { - if (_trackingBlocks.containsKey(block)) { - int current = _trackingBlocks.get(block); - if (current == 0) { - Debug.logWarning("Untracked block " + block + " more times than necessary. BlockTracker stack is unreliable from this point on."); - } else { - _trackingBlocks.put(block, current - 1); - if (_trackingBlocks.get(block) <= 0) { - _trackingBlocks.remove(block); - } - } - } - } - } - } - - /** - * Manually add a block at a position. - */ - public void addBlock(Block block, BlockPos pos) { - if (blockIsValid(pos, block)) { - synchronized (_scanMutex) { - currentCache().addBlock(block, pos); - } - } else { - Debug.logInternal("INVALID SET: " + block + " " + pos); - } - } - - public boolean anyFound(Block... blocks) { - updateState(); - synchronized (_scanMutex) { - return currentCache().anyFound(blocks); - } - } - - /** - * Checks whether any blocks of a type have been found. - * - * @param isValidTest A filter predicate, returns true if a block at a position should be included. - * @param blocks The blocks to check for - */ - public boolean anyFound(Predicate isValidTest, Block... blocks) { - updateState(); - synchronized (_scanMutex) { - return currentCache().anyFound(isValidTest, blocks); - } - } - - public Optional getNearestTracking(Block... blocks) { - // Add juuust a little, to prevent digging down all the time/bias towards blocks BELOW the player - return getNearestTracking(_mod.getPlayer().getPos().add(0, 0.6f, 0), blocks); - } - - public Optional getNearestTracking(Vec3d pos, Block... blocks) { - return getNearestTracking(pos, p -> true, blocks); - } - - public Optional getNearestTracking(Predicate isValidTest, Block... blocks) { - return getNearestTracking(_mod.getPlayer().getPos().add(0, 0.6f, 0), isValidTest, blocks); - } - - /** - * Gets the nearest tracked block. - * - * @param pos From what position? (defaults to the player's position) - * @param isValidTest Filter predicate - * @param blocks The blocks to check for - * @return Optional.of(block position) if found, otherwise Optional.empty - */ - public Optional getNearestTracking(Vec3d pos, Predicate isValidTest, Block... blocks) { - synchronized (_trackingBlocks) { - for (Block block : blocks) { - if (!_trackingBlocks.containsKey(block)) { - Debug.logWarning("BlockTracker: Not tracking block " + block + " right now."); - return Optional.empty(); - } - } - } - // Make sure we've scanned the first time if we need to. - updateState(); - synchronized (_scanMutex) { - return currentCache().getNearest(_mod, pos, isValidTest, blocks); - } - } - - /** - * Returns the locations of all tracked blocks of a given type - */ - public List getKnownLocations(Block... blocks) { - updateState(); - synchronized (_scanMutex) { - return currentCache().getKnownLocations(blocks); - } - } - - public Optional getNearestWithinRange(BlockPos pos, double range, Block... blocks) { - return getNearestWithinRange(new Vec3d(pos.getX(), pos.getY(), pos.getZ()), range, blocks); - } - - /** - * Scans a radius for the closest block of a given type . - * - * @param pos The center of this radius - * @param range Radius to scan for - * @param blocks What blocks to check for - */ - public Optional getNearestWithinRange(Vec3d pos, double range, Block... blocks) { - int minX = (int) Math.floor(pos.x - range), - maxX = (int) Math.floor(pos.x + range), - minY = (int) Math.floor(pos.y - range), - maxY = (int) Math.floor(pos.y + range), - minZ = (int) Math.floor(pos.z - range), - maxZ = (int) Math.floor(pos.z + range); - double closestDistance = Float.POSITIVE_INFINITY; - BlockPos nearest = null; - for (int x = minX; x <= maxX; ++x) { - for (int y = minY; y <= maxY; ++y) { - for (int z = minZ; z <= maxZ; ++z) { - BlockPos check = new BlockPos(x, y, z); - synchronized (_scanMutex) { - if (currentCache().blockUnreachable(check)) continue; - } - - assert MinecraftClient.getInstance().world != null; - Block b = MinecraftClient.getInstance().world.getBlockState(check).getBlock(); - boolean valid = false; - for (Block type : blocks) { - if (type == b) { - valid = true; - break; - } - } - if (!valid) continue; - if (check.isWithinDistance(pos, range)) { - double sq = check.getSquaredDistance(pos); - if (sq < closestDistance) { - closestDistance = sq; - nearest = check; - } - } - } - } - } - return Optional.ofNullable(nearest); - } - - private boolean shouldUpdate() { - return _timer.elapsed(); - } - - private void update() { - // Perform a baritone scan - _timer.reset(); - _timer.setInterval(_config.scanInterval); - CalculationContext ctx = new CalculationContext(_mod.getClientBaritone(), _config.scanAsynchronously); - if (_config.scanAsynchronously) { - if (_scanning && _asyncForceResetScanFlag.elapsed()) { - Debug.logMessage("SCANNING TOOK TOO LONG! Will assume it ended mid way. Hopefully this won't break anything..."); - _scanning = false; - } - if (!_scanning) { - Baritone.getExecutor().execute(() -> { - _scanning = true; - _asyncForceResetScanFlag.reset(); - rescanWorld(ctx, true); - _scanning = false; - }); - } - } else { - // Synchronous scanning. - rescanWorld(ctx, false); - } - } - - private void rescanWorld(CalculationContext ctx, boolean async) { - Block[] blocksToScan; - if (async) { - // Wait for end of frame - try { - _endOfFrameMutex.acquire(); - _endOfFrameMutex.release(); - } catch (InterruptedException e) { - Debug.logWarning("RESCAN INTERRUPTED! Will SKIP the scan (see logs)"); - _endOfFrameMutex.release(); - e.printStackTrace(); - return; - } - } - synchronized (_trackingBlocks) { - Debug.logInternal("Rescanning world for " + _trackingBlocks.size() + " blocks... Hopefully not dummy slow."); - blocksToScan = new Block[_trackingBlocks.size()]; - _trackingBlocks.keySet().toArray(blocksToScan); - } - - List knownBlocks; - synchronized (_scanMutex) { - knownBlocks = currentCache().getKnownLocations(blocksToScan); - } - - // Clear invalid block pos before rescan - if (!knownBlocks.isEmpty()) { - for (BlockPos check : knownBlocks) { - if (!blockIsValid(check, blocksToScan)) { - //Debug.logInternal("Removed at " + check); - synchronized (_scanMutex) { - currentCache().removeBlock(check, blocksToScan); - } - } - } - } - - // The scanning may run asynchronously. - BlockOptionalMetaLookup boml = new BlockOptionalMetaLookup(blocksToScan); - List found = MineProcess.searchWorld(ctx, boml, _config.maxCacheSizePerBlockType, Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); - - synchronized (_scanMutex) { - if (MinecraftClient.getInstance().world != null) { - if (!found.isEmpty()) { - for (BlockPos pos : found) { - Block block = MinecraftClient.getInstance().world.getBlockState(pos).getBlock(); - synchronized (_trackingBlocks) { - if (_trackingBlocks.containsKey(block)) { - //Debug.logInternal("Good: " + block + " at " + pos); - currentCache().addBlock(block, pos); - } - } - } - } - - // Purge if we have too many blocks tracked at once. - currentCache().smartPurge(_mod, _mod.getPlayer().getPos()); - } - } - } - - // Checks whether it would be WRONG to say "at pos the block is block" - // Returns true if wrong, false if correct OR undetermined/unsure. - public boolean blockIsValid(BlockPos pos, Block... blocks) { - synchronized (_scanMutex) { - // We can't reach it, don't even try. - if (currentCache().blockUnreachable(pos)) { - return false; - } - } - // It might be OK to remove this. Will have to test. - if (!_mod.getChunkTracker().isChunkLoaded(pos)) { - //Debug.logInternal("(failed chunkcheck: " + new ChunkPos(pos) + ")"); - //Debug.logStack(); - return true; - } - // I'm bored - ClientWorld zaWarudo = MinecraftClient.getInstance().world; - // No world, therefore we don't assume block is invalid. - if (zaWarudo == null) { - return true; - } - try { - for (Block block : blocks) { - if (zaWarudo.isAir(pos) && WorldHelper.isAir(block)) { - return true; - } - BlockState state = zaWarudo.getBlockState(pos); - if (state.getBlock() == block) { - return true; - } - } - return false; - } catch (NullPointerException e) { - // Probably out of chunk. This means we can't judge its state. - return true; - } - } - - /** - * @param pos BlockPos to check for - * @return Whether that block is considered unreachable - */ - public boolean unreachable(BlockPos pos) { - synchronized (_scanMutex) { - return currentCache().blockUnreachable(pos); - } - } - - /** - * Inform the block tracker that the bot was NOT able to reach a block. - * - * @param pos block that we were unable to reach - * @param allowedFailures how many times we can try reaching before we finally declare this block "unreachable" - */ - public void requestBlockUnreachable(BlockPos pos, int allowedFailures) { - synchronized (_scanMutex) { - currentCache().blacklistBlockUnreachable(_mod, pos, allowedFailures); - } - } - - public void requestBlockUnreachable(BlockPos pos) { - requestBlockUnreachable(pos, _config.defaultUnreachableAttemptsAllowed); - } - - private PosCache currentCache() { - Dimension dimension = WorldHelper.getCurrentDimension(); - if (!_caches.containsKey(dimension)) { - _caches.put(dimension, new PosCache()); - } - return _caches.get(dimension); - } - - - static class PosCache { - private final HashMap> _cachedBlocks = new HashMap<>(); - - private final HashMap _cachedByPosition = new HashMap<>(); - - private final WorldLocateBlacklist _blacklist = new WorldLocateBlacklist(); - - public boolean anyFound(Block... blocks) { - for (Block block : blocks) { - if (_cachedBlocks.containsKey(block)) return true; - } - return false; - } - - public boolean anyFound(Predicate isValidTest, Block... blocks) { - for (Block block : blocks) { - if (_cachedBlocks.containsKey(block)) { - for (BlockPos pos : _cachedBlocks.get(block)) { - if (isValidTest.test(pos)) { - return true; - } - } - } - } - return false; - } - - public List getKnownLocations(Block... blocks) { - List result = new ArrayList<>(); - for (Block block : blocks) { - List found = _cachedBlocks.get(block); - if (found != null) { - result.addAll(found); - } - } - return result; - } - - public void removeBlock(BlockPos pos, Block... blocks) { - for (Block block : blocks) { - if (_cachedBlocks.containsKey(block)) { - _cachedBlocks.get(block).remove(pos); - _cachedByPosition.remove(pos); - if (_cachedBlocks.get(block).size() == 0) { - _cachedBlocks.remove(block); - } - } - } - } - - public void addBlock(Block block, BlockPos pos) { - if (blockUnreachable(pos)) return; - if (_cachedByPosition.containsKey(pos)) { - if (_cachedByPosition.get(pos) == block) { - // We're already tracked - return; - } else { - // We're tracked incorrectly, fix - removeBlock(pos, block); - } - } - if (!anyFound(block)) { - _cachedBlocks.put(block, new ArrayList<>()); - } - _cachedBlocks.get(block).add(pos); - _cachedByPosition.put(pos, block); - } - - - public void clear() { - Debug.logInternal("CLEARED BLOCK CACHE"); - _cachedBlocks.clear(); - _cachedByPosition.clear(); - _blacklist.clear(); - } - - public int getBlockTrackCount() { - int count = 0; - if (!_cachedBlocks.values().isEmpty()) { - for (List list : _cachedBlocks.values()) { - count += list.size(); - } - } - return count; - } - - public void blacklistBlockUnreachable(AltoClef mod, BlockPos pos, int allowedFailures) { - _blacklist.blackListItem(mod, pos, allowedFailures); - } - - public boolean blockUnreachable(BlockPos pos) { - return _blacklist.unreachable(pos); - } - - // Gets nearest block. For now does linear search. In the future might optimize this a bit - public Optional getNearest(AltoClef mod, Vec3d position, Predicate isValid, Block... blocks) { - if (!anyFound(blocks)) { - //Debug.logInternal("(failed cataloguecheck for " + block.getTranslationKey() + ")"); - return Optional.empty(); - } - - BlockPos closest = null; - double minScore = Double.POSITIVE_INFINITY; - - List blockList = getKnownLocations(blocks); - - int toPurge = blockList.size() - _config.maxCacheSizePerBlockType; - - boolean closestPurged = false; - if (!blockList.isEmpty()) { - for (BlockPos pos : blockList) { - // If our current block isn't valid, fix it up. This cleans while we're iterating. - if (!mod.getBlockTracker().blockIsValid(pos, blocks)) { - removeBlock(pos, blocks); - continue; - } - if (!isValid.test(pos)) continue; - - double score = BaritoneHelper.calculateGenericHeuristic(position, WorldHelper.toVec3d(pos)); - - boolean currentlyClosest = false; - boolean purged = false; - - if (score < minScore) { - minScore = score; - closest = pos; - currentlyClosest = true; - } - - if (toPurge > 0) { - double sqDist = position.squaredDistanceTo(WorldHelper.toVec3d(pos)); - if (sqDist > _config.cutoffDistance * _config.cutoffDistance) { - // cut this one off. - for (Block block : blocks) { - if (_cachedBlocks.containsKey(block)) { - removeBlock(pos, block); - } - } - toPurge--; - purged = true; - } - } - - if (currentlyClosest) { - closestPurged = purged; - } - } - } - - while (toPurge > 0) { - if (blockList.size() == 0) { - //noinspection UnusedAssignment - toPurge = 0; - break; - } - blockList.remove(blockList.size() - 1); - toPurge--; - } - - // Special case: Our closest was purged. Add us back. - if (closestPurged) { - Debug.logInternal("Rare edge case: Closest block was purged cause it was real far away, it will now be added back."); - blockList.add(closest); - } - - return Optional.ofNullable(closest); - } - - /** - * Purge enough blocks so our size is small enough - */ - public void smartPurge(AltoClef mod, Vec3d playerPos) { - - // Clear cached by position blocks, as they can be a handful. - try { - int MAX_CACHE_SIZE = _config.maxTotalCacheSize; - if (_cachedByPosition.size() > MAX_CACHE_SIZE) { - List toRemoveList = new ArrayList<>(_cachedByPosition.size() - MAX_CACHE_SIZE); - // Just purge randomly. - if (!_cachedByPosition.keySet().isEmpty()) { - for (BlockPos pos : _cachedByPosition.keySet()) { - if (_cachedByPosition.size() - toRemoveList.size() < MAX_CACHE_SIZE) { - break; - } - toRemoveList.add(pos); - } - } - if (!toRemoveList.isEmpty()) { - for (BlockPos toDelete : toRemoveList) { - _cachedByPosition.remove(toDelete); - } - } - } - } catch (Exception e) { - Debug.logWarning("Failed to purge/reduce _cachedByPosition cache.: Its size remains at " + _cachedByPosition.size()); - } - - // ^^^ TODO: Something about that feels fishy, particularly how it's disconnected from the _cachedBlocks purging. - // I smell a dangerous edge case bug. - if (!_cachedBlocks.keySet().isEmpty()) { - for (Block block : _cachedBlocks.keySet()) { - List tracking = _cachedBlocks.get(block); - - // Clear blacklisted blocks - try { - // Untrack the blocks further away - tracking = tracking.stream() - .filter(pos -> !_blacklist.unreachable(pos)) - // This is invalid, because some blocks we may want to GO TO not BREAK. - //.filter(pos -> !mod.getExtraBaritoneSettings().shouldAvoidBreaking(pos)) - .distinct() - .sorted(StlHelper.compareValues((BlockPos blockpos) -> blockpos.getSquaredDistance(playerPos))) - .collect(Collectors.toList()); - tracking = tracking.stream() - .limit(_config.maxCacheSizePerBlockType) - .collect(Collectors.toList()); - // This won't update otherwise. - _cachedBlocks.put(block, tracking); - } catch (IllegalArgumentException e) { - // Comparison method violates its general contract: Sometimes transitivity breaks. - // In which case, ignore it. - Debug.logWarning("Failed to purge/reduce block search count for " + block + ": It remains at " + tracking.size()); - } - } - } - } - } - - static class BlockTrackerConfig { - public double scanInterval = 7; - public double scanIntervalWhenNewBlocksFound = 2; - public boolean scanAsynchronously = true; - public int maxTotalCacheSize = 2500; - public int maxCacheSizePerBlockType = 25; - public double cutoffDistance = 128; - public int defaultUnreachableAttemptsAllowed = 4; - } -} diff --git a/src/main/java/adris/altoclef/trackers/EntityTracker.java b/src/main/java/adris/altoclef/trackers/EntityTracker.java index a8734adb..5fd1cd8a 100644 --- a/src/main/java/adris/altoclef/trackers/EntityTracker.java +++ b/src/main/java/adris/altoclef/trackers/EntityTracker.java @@ -33,21 +33,21 @@ @SuppressWarnings("rawtypes") public class EntityTracker extends Tracker { - private final HashMap> _itemDropLocations = new HashMap<>(); - private final HashMap> _entityMap = new HashMap<>(); + private final HashMap> itemDropLocations = new HashMap<>(); + private final HashMap> entityMap = new HashMap<>(); - private final List _closeEntities = new ArrayList<>(); - private final List _hostiles = new ArrayList<>(); + private final List closeEntities = new ArrayList<>(); + private final List hostiles = new ArrayList<>(); - private final List _projectiles = new ArrayList<>(); + private final List projectiles = new ArrayList<>(); - private final HashMap _playerMap = new HashMap<>(); - private final HashMap _playerLastCoordinates = new HashMap<>(); + private final HashMap playerMap = new HashMap<>(); + private final HashMap playerLastCoordinates = new HashMap<>(); - private final EntityLocateBlacklist _entityBlacklist = new EntityLocateBlacklist(); + private final EntityLocateBlacklist entityBlacklist = new EntityLocateBlacklist(); - private final HashMap> _entitiesCollidingWithPlayerAccumulator = new HashMap<>(); - private final HashMap> _entitiesCollidingWithPlayer = new HashMap<>(); + private final HashMap> entitiesCollidingWithPlayerAccumulator = new HashMap<>(); + private final HashMap> entitiesCollidingWithPlayer = new HashMap<>(); public EntityTracker(TrackerManager manager) { super(manager); @@ -57,7 +57,7 @@ public EntityTracker(TrackerManager manager) { } /** - * Squash a class that may have sub classes into one distinguishable class type. + * Squash a class that may have subclasses into one distinguishable class type. * For ease of use. * * @param type: An entity class that may have a 'simpler' class to squash to @@ -72,14 +72,14 @@ private static Class squashType(Class type) { } private void registerPlayerCollision(PlayerEntity player, Entity entity) { - if (!_entitiesCollidingWithPlayerAccumulator.containsKey(player)) { - _entitiesCollidingWithPlayerAccumulator.put(player, new ArrayList<>()); + if (!entitiesCollidingWithPlayerAccumulator.containsKey(player)) { + entitiesCollidingWithPlayerAccumulator.put(player, new ArrayList<>()); } - _entitiesCollidingWithPlayerAccumulator.get(player).add(entity); + entitiesCollidingWithPlayerAccumulator.get(player).add(entity); } public boolean isCollidingWithPlayer(PlayerEntity player, Entity entity) { - return _entitiesCollidingWithPlayer.containsKey(player) && _entitiesCollidingWithPlayer.get(player).contains(entity); + return entitiesCollidingWithPlayer.containsKey(player) && entitiesCollidingWithPlayer.get(player).contains(entity); } public boolean isCollidingWithPlayer(Entity entity) { @@ -126,8 +126,8 @@ public Optional getClosestItemDrop(Vec3d position, Predicate getClosestEntity(Vec3d position, Predicate accep double minCost = Float.POSITIVE_INFINITY; for (Class toFind : entityTypes) { synchronized (BaritoneHelper.MINECRAFT_LOCK) { - if (_entityMap.containsKey(toFind)) { - for (Entity entity : _entityMap.get(toFind)) { + if (entityMap.containsKey(toFind)) { + for (Entity entity : entityMap.get(toFind)) { // Don't accept entities that no longer exist - if (_entityBlacklist.unreachable(entity)) continue; + if (entityBlacklist.unreachable(entity)) continue; if (!entity.isAlive()) continue; if (!acceptPredicate.test(entity)) continue; double cost = entity.squaredDistanceTo(position); @@ -180,10 +180,10 @@ public Optional getClosestEntity(Vec3d position, Predicate accep public boolean itemDropped(Item... items) { ensureUpdated(); for (Item item : items) { - if (_itemDropLocations.containsKey(item)) { + if (itemDropLocations.containsKey(item)) { // Find a non-blacklisted item - for (ItemEntity entity : _itemDropLocations.get(item)) { - if (!_entityBlacklist.unreachable(entity)) return true; + for (ItemEntity entity : itemDropLocations.get(item)) { + if (!entityBlacklist.unreachable(entity)) return true; } } } @@ -200,7 +200,7 @@ public boolean itemDropped(ItemTarget... targets) { public List getDroppedItems() { ensureUpdated(); - return _itemDropLocations.values().stream().reduce(new ArrayList<>(), (result, drops) -> { + return itemDropLocations.values().stream().reduce(new ArrayList<>(), (result, drops) -> { result.addAll(drops); return result; }); @@ -210,7 +210,7 @@ public boolean entityFound(Predicate shouldAccept, Class... types) { ensureUpdated(); for (Class type : types) { synchronized (BaritoneHelper.MINECRAFT_LOCK) { - for (Entity entity : _entityMap.getOrDefault(type, Collections.emptyList())) { + for (Entity entity : entityMap.getOrDefault(type, Collections.emptyList())) { if (shouldAccept.test(entity)) return true; } @@ -230,7 +230,7 @@ public List getTrackedEntities(Class type) { } synchronized (BaritoneHelper.MINECRAFT_LOCK) { //noinspection unchecked - return (List) _entityMap.get(type); + return (List) entityMap.get(type); } } @@ -240,7 +240,7 @@ public List getTrackedEntities(Class type) { public List getCloseEntities() { ensureUpdated(); synchronized (BaritoneHelper.MINECRAFT_LOCK) { - return _closeEntities; + return closeEntities; } } @@ -250,14 +250,14 @@ public List getCloseEntities() { public List getProjectiles() { ensureUpdated(); synchronized (BaritoneHelper.MINECRAFT_LOCK) { - return _projectiles; + return projectiles; } } public List getHostiles() { ensureUpdated(); synchronized (BaritoneHelper.MINECRAFT_LOCK) { - return _hostiles; + return hostiles; } } @@ -269,7 +269,7 @@ public List getHostiles() { public boolean isPlayerLoaded(String name) { ensureUpdated(); synchronized (BaritoneHelper.MINECRAFT_LOCK) { - return _playerMap.containsKey(name); + return playerMap.containsKey(name); } } @@ -281,7 +281,7 @@ public boolean isPlayerLoaded(String name) { public Optional getPlayerMostRecentPosition(String name) { ensureUpdated(); synchronized (BaritoneHelper.MINECRAFT_LOCK) { - return Optional.ofNullable(_playerLastCoordinates.getOrDefault(name, null)); + return Optional.ofNullable(playerLastCoordinates.getOrDefault(name, null)); } } @@ -293,7 +293,7 @@ public Optional getPlayerMostRecentPosition(String name) { public Optional getPlayerEntity(String name) { if (isPlayerLoaded(name)) { synchronized (BaritoneHelper.MINECRAFT_LOCK) { - return Optional.of(_playerMap.get(name)); + return Optional.of(playerMap.get(name)); } } return Optional.empty(); @@ -303,34 +303,34 @@ public Optional getPlayerEntity(String name) { * Tells the entity tracker that we were unable to reach this entity. */ public void requestEntityUnreachable(Entity entity) { - _entityBlacklist.blackListItem(_mod, entity, 3); + entityBlacklist.blackListItem(_mod, entity, 3); } /** * Whether we have decided that this entity is unreachable. */ public boolean isEntityReachable(Entity entity) { - return !_entityBlacklist.unreachable(entity); + return !entityBlacklist.unreachable(entity); } @Override protected synchronized void updateState() { synchronized (BaritoneHelper.MINECRAFT_LOCK) { - _itemDropLocations.clear(); - _entityMap.clear(); - _closeEntities.clear(); - _projectiles.clear(); - _hostiles.clear(); - _playerMap.clear(); + itemDropLocations.clear(); + entityMap.clear(); + closeEntities.clear(); + projectiles.clear(); + hostiles.clear(); + playerMap.clear(); if (MinecraftClient.getInstance().world == null) return; // Store/Register All accumulated player collisions for this frame. - _entitiesCollidingWithPlayer.clear(); - for (Map.Entry> collisions : _entitiesCollidingWithPlayerAccumulator.entrySet()) { - _entitiesCollidingWithPlayer.put(collisions.getKey(), new HashSet<>()); - _entitiesCollidingWithPlayer.get(collisions.getKey()).addAll(collisions.getValue()); + entitiesCollidingWithPlayer.clear(); + for (Map.Entry> collisions : entitiesCollidingWithPlayerAccumulator.entrySet()) { + entitiesCollidingWithPlayer.put(collisions.getKey(), new HashSet<>()); + entitiesCollidingWithPlayer.get(collisions.getKey()).addAll(collisions.getValue()); } - _entitiesCollidingWithPlayerAccumulator.clear(); + entitiesCollidingWithPlayerAccumulator.clear(); // Loop through all entities and track 'em for (Entity entity : MinecraftClient.getInstance().world.getEntities()) { @@ -345,13 +345,13 @@ protected synchronized void updateState() { // Don't catalogue our own player. if (type == PlayerEntity.class && entity.equals(_mod.getPlayer())) continue; - if (!_entityMap.containsKey(type)) { - _entityMap.put(type, new ArrayList<>()); + if (!entityMap.containsKey(type)) { + entityMap.put(type, new ArrayList<>()); } - _entityMap.get(type).add(entity); + entityMap.get(type).add(entity); if (_mod.getControllerExtras().inRange(entity)) { - _closeEntities.add(entity); + closeEntities.add(entity); } if (entity instanceof ItemEntity ientity) { @@ -359,10 +359,10 @@ protected synchronized void updateState() { // Only cared about GROUNDED item entities if (ientity.isOnGround() || ientity.isTouchingWater() || WorldHelper.isSolid(_mod, ientity.getBlockPos().down(2)) || WorldHelper.isSolid(_mod, ientity.getBlockPos().down(3))) { - if (!_itemDropLocations.containsKey(droppedItem)) { - _itemDropLocations.put(droppedItem, new ArrayList<>()); + if (!itemDropLocations.containsKey(droppedItem)) { + itemDropLocations.put(droppedItem, new ArrayList<>()); } - _itemDropLocations.get(droppedItem).add(ientity); + itemDropLocations.get(droppedItem).add(ientity); } } if (entity instanceof MobEntity) { @@ -373,7 +373,7 @@ protected synchronized void updateState() { //Debug.logInternal("TARGET: " + hostile.is); if (closeEnough) { - _hostiles.add(entity); + hostiles.add(entity); } } } else if (entity instanceof ProjectileEntity projEntity) { @@ -395,13 +395,13 @@ protected synchronized void updateState() { proj.velocity = projEntity.getVelocity(); proj.gravity = ProjectileHelper.hasGravity(projEntity) ? ProjectileHelper.ARROW_GRAVITY_ACCEL : 0; proj.projectileType = projEntity.getClass(); - _projectiles.add(proj); + projectiles.add(proj); } } } else if (entity instanceof PlayerEntity player) { String name = player.getName().getString(); - _playerMap.put(name, player); - _playerLastCoordinates.put(name, player.getPos()); + playerMap.put(name, player); + playerLastCoordinates.put(name, player.getPos()); } } } @@ -410,6 +410,6 @@ protected synchronized void updateState() { @Override protected void reset() { // Dirty clears everything else. - _entityBlacklist.clear(); + entityBlacklist.clear(); } } diff --git a/src/main/java/adris/altoclef/trackers/MiscBlockTracker.java b/src/main/java/adris/altoclef/trackers/MiscBlockTracker.java index 37bbb95b..99afa4e4 100644 --- a/src/main/java/adris/altoclef/trackers/MiscBlockTracker.java +++ b/src/main/java/adris/altoclef/trackers/MiscBlockTracker.java @@ -17,40 +17,40 @@ */ public class MiscBlockTracker { - private final AltoClef _mod; + private final AltoClef mod; - private final Map _lastNetherPortalsUsed = new HashMap<>(); + private final Map lastNetherPortalsUsed = new HashMap<>(); // Make sure we only care about the nether portal we ENTERED through - private Dimension _lastDimension; - private boolean _newDimensionTriggered; + private Dimension lastDimension; + private boolean newDimensionTriggered; public MiscBlockTracker(AltoClef mod) { - _mod = mod; + this.mod = mod; } public void tick() { - if (WorldHelper.getCurrentDimension() != _lastDimension) { - _lastDimension = WorldHelper.getCurrentDimension(); - _newDimensionTriggered = true; + if (WorldHelper.getCurrentDimension() != lastDimension) { + lastDimension = WorldHelper.getCurrentDimension(); + newDimensionTriggered = true; } - if (AltoClef.inGame() && _newDimensionTriggered) { - for (BlockPos check : WorldHelper.scanRegion(_mod, _mod.getPlayer().getBlockPos().add(-1, -1, -1), _mod.getPlayer().getBlockPos().add(1, 1, 1))) { - Block currentBlock = _mod.getWorld().getBlockState(check).getBlock(); + if (AltoClef.inGame() && newDimensionTriggered) { + for (BlockPos check : WorldHelper.scanRegion(mod, mod.getPlayer().getBlockPos().add(-1, -1, -1), mod.getPlayer().getBlockPos().add(1, 1, 1))) { + Block currentBlock = mod.getWorld().getBlockState(check).getBlock(); if (currentBlock == Blocks.NETHER_PORTAL) { // Make sure we get the lowest nether portal, as we can only really enter from the bottom. while (check.getY() > 0) { - if (_mod.getWorld().getBlockState(check.down()).getBlock() == Blocks.NETHER_PORTAL) { + if (mod.getWorld().getBlockState(check.down()).getBlock() == Blocks.NETHER_PORTAL) { check = check.down(); } else { break; } } BlockPos below = check.down(); - if (WorldHelper.isSolid(_mod, below)) { - _lastNetherPortalsUsed.put(WorldHelper.getCurrentDimension(), check); - _newDimensionTriggered = false; + if (WorldHelper.isSolid(mod, below)) { + lastNetherPortalsUsed.put(WorldHelper.getCurrentDimension(), check); + newDimensionTriggered = false; } break; } @@ -59,16 +59,16 @@ public void tick() { } public void reset() { - _lastNetherPortalsUsed.clear(); + lastNetherPortalsUsed.clear(); } public Optional getLastUsedNetherPortal(Dimension dimension) { - if (_lastNetherPortalsUsed.containsKey(dimension)) { - BlockPos portalPos = _lastNetherPortalsUsed.get(dimension); + if (lastNetherPortalsUsed.containsKey(dimension)) { + BlockPos portalPos = lastNetherPortalsUsed.get(dimension); // Check whether our nether portal pos is invalid. - if (_mod.getChunkTracker().isChunkLoaded(portalPos)) { - if (!_mod.getBlockTracker().blockIsValid(portalPos, Blocks.NETHER_PORTAL)) { - _lastNetherPortalsUsed.remove(dimension); + if (mod.getChunkTracker().isChunkLoaded(portalPos)) { + if (!mod.getBlockScanner().isBlockAtPosition(portalPos, Blocks.NETHER_PORTAL)) { + lastNetherPortalsUsed.remove(dimension); return Optional.empty(); } } diff --git a/src/main/java/adris/altoclef/trackers/SimpleChunkTracker.java b/src/main/java/adris/altoclef/trackers/SimpleChunkTracker.java index c4f5d8ad..aef5da7e 100644 --- a/src/main/java/adris/altoclef/trackers/SimpleChunkTracker.java +++ b/src/main/java/adris/altoclef/trackers/SimpleChunkTracker.java @@ -23,11 +23,11 @@ */ public class SimpleChunkTracker { - private final AltoClef _mod; - private final Set _loaded = new HashSet<>(); + private final AltoClef mod; + private final Set loaded = new HashSet<>(); public SimpleChunkTracker(AltoClef mod) { - _mod = mod; + this.mod = mod; // When chunks load... EventBus.subscribe(ChunkLoadEvent.class, evt -> onLoad(evt.chunk.getPos())); @@ -36,16 +36,16 @@ public SimpleChunkTracker(AltoClef mod) { private void onLoad(ChunkPos pos) { //Debug.logInternal("LOADED: " + pos); - _loaded.add(pos); + loaded.add(pos); } private void onUnload(ChunkPos pos) { //Debug.logInternal("unloaded: " + pos); - _loaded.remove(pos); + loaded.remove(pos); } public boolean isChunkLoaded(ChunkPos pos) { - return !(_mod.getWorld().getChunk(pos.x, pos.z) instanceof EmptyChunk); + return !(mod.getWorld().getChunk(pos.x, pos.z) instanceof EmptyChunk); } public boolean isChunkLoaded(BlockPos pos) { @@ -53,7 +53,7 @@ public boolean isChunkLoaded(BlockPos pos) { } public List getLoadedChunks() { - List result = new ArrayList<>(_loaded); + List result = new ArrayList<>(loaded); // Only show LOADED chunks. result = result.stream() .filter(this::isChunkLoaded) @@ -92,6 +92,6 @@ public void scanChunk(ChunkPos chunk, Consumer onBlock) { public void reset(AltoClef mod) { Debug.logInternal("CHUNKS RESET"); - _loaded.clear(); + loaded.clear(); } } diff --git a/src/main/java/adris/altoclef/trackers/blacklisting/AbstractObjectBlacklist.java b/src/main/java/adris/altoclef/trackers/blacklisting/AbstractObjectBlacklist.java index 03b8a3c7..ac67285d 100644 --- a/src/main/java/adris/altoclef/trackers/blacklisting/AbstractObjectBlacklist.java +++ b/src/main/java/adris/altoclef/trackers/blacklisting/AbstractObjectBlacklist.java @@ -15,18 +15,18 @@ */ public abstract class AbstractObjectBlacklist { - private final HashMap _entries = new HashMap<>(); + private final HashMap entries = new HashMap<>(); public void blackListItem(AltoClef mod, T item, int numberOfFailuresAllowed) { - if (!_entries.containsKey(item)) { + if (!entries.containsKey(item)) { BlacklistEntry entry = new BlacklistEntry(); entry.numberOfFailuresAllowed = numberOfFailuresAllowed; entry.numberOfFailures = 0; entry.bestDistanceSq = Double.POSITIVE_INFINITY; entry.bestTool = MiningRequirement.HAND; - _entries.put(item, entry); + entries.put(item, entry); } - BlacklistEntry entry = _entries.get(item); + BlacklistEntry entry = entries.get(item); double newDistance = getPos(item).squaredDistanceTo(mod.getPlayer().getPos()); MiningRequirement newTool = StorageHelper.getCurrentMiningRequirement(mod); // For distance, add a slight threshold so it doesn't reset EVERY time we move a tiny bit closer. @@ -44,15 +44,15 @@ public void blackListItem(AltoClef mod, T item, int numberOfFailuresAllowed) { protected abstract Vec3d getPos(T item); public boolean unreachable(T item) { - if (_entries.containsKey(item)) { - BlacklistEntry entry = _entries.get(item); + if (entries.containsKey(item)) { + BlacklistEntry entry = entries.get(item); return entry.numberOfFailures > entry.numberOfFailuresAllowed; } return false; } public void clear() { - _entries.clear(); + entries.clear(); } // Key: BlockPos diff --git a/src/main/java/adris/altoclef/ui/CommandStatusOverlay.java b/src/main/java/adris/altoclef/ui/CommandStatusOverlay.java index 325c885a..87f52e5e 100644 --- a/src/main/java/adris/altoclef/ui/CommandStatusOverlay.java +++ b/src/main/java/adris/altoclef/ui/CommandStatusOverlay.java @@ -8,6 +8,7 @@ import net.minecraft.client.util.math.MatrixStack; import org.joml.Matrix4f; +import java.awt.*; import java.time.Instant; import java.time.ZoneId; import java.time.ZoneOffset; @@ -18,9 +19,9 @@ public class CommandStatusOverlay { //For the ingame timer - private long _timeRunning; - private long _lastTime = 0; - private DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss.SSS").withZone(ZoneId.from(ZoneOffset.of("+00:00"))); // The date formatter + private long timeRunning; + private long lastTime = 0; + private final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss.SSS").withZone(ZoneId.from(ZoneOffset.of("+00:00"))); // The date formatter public void render(AltoClef mod, MatrixStack matrixstack) { if (mod.getModSettings().shouldShowTaskChain()) { @@ -29,52 +30,81 @@ public void render(AltoClef mod, MatrixStack matrixstack) { tasks = mod.getTaskRunner().getCurrentTaskChain().getTasks(); } - int color = 0xFFFFFFFF; - drawTaskChain(MinecraftClient.getInstance().textRenderer, 0, 0, color, false, + matrixstack.push(); + + drawTaskChain(MinecraftClient.getInstance().textRenderer, 10, 10, matrixstack.peek().getPositionMatrix(), MinecraftClient.getInstance().getBufferBuilders().getOutlineVertexConsumers(), - TextRenderer.TextLayerType.NORMAL, 0, 255, 10, tasks, mod); + TextRenderer.TextLayerType.SEE_THROUGH, 10, tasks, mod); + + matrixstack.pop(); } } - private void drawTaskChain(TextRenderer renderer, float x, float y, int color, boolean shadow, Matrix4f matrix, VertexConsumerProvider vertexConsumers, TextRenderer.TextLayerType layerType, int backgroundColor, int light, int maxLines, List tasks, AltoClef mod) { - if (tasks.size() == 0) { - renderer.draw(" (no task running) ", x, y, color, shadow, matrix, vertexConsumers, layerType, backgroundColor, light); - if (_lastTime + 10000 < Instant.now().toEpochMilli() && mod.getModSettings().shouldShowTimer()) {//if it doesn't run any task in 10 secs - _timeRunning = Instant.now().toEpochMilli();//reset the timer + private void drawTaskChain(TextRenderer renderer, float x, float y, Matrix4f matrix, VertexConsumerProvider vertexConsumers, TextRenderer.TextLayerType layerType, int maxLines, List tasks, AltoClef mod) { + int whiteColor = 0xFFFFFFFF; + + if (tasks.isEmpty()) { + renderer.draw(" (no task running) ", x, y, whiteColor, true, matrix, vertexConsumers, layerType, 0, 255); + if (lastTime + 10000 < Instant.now().toEpochMilli() && mod.getModSettings().shouldShowTimer()) {//if it doesn't run any task in 10 secs + timeRunning = Instant.now().toEpochMilli();//reset the timer } - } else { - float fontHeight = renderer.fontHeight; - if (mod.getModSettings().shouldShowTimer()) { //If it's enabled - _lastTime = Instant.now().toEpochMilli(); //keep the last time for the timer reset - String _realTime = DATE_TIME_FORMATTER.format(Instant.now().minusMillis(_timeRunning)); //Format the running time to string - renderer.draw("<" + _realTime + ">", x, y, color, shadow, matrix, vertexConsumers, layerType, backgroundColor, light); - x += 8;//Do the same thing to list the tasks - y += fontHeight + 2; + return; + } + + matrix.scale(0.5F, 0.5F, 0.5F); + + float fontHeight = renderer.fontHeight; + float addX = 4; + float addY = fontHeight+2; + + renderer.draw(mod.getTaskRunner().statusReport, x, y, Color.LIGHT_GRAY.getRGB(), true, matrix, vertexConsumers, layerType, 0, 255); + y += addY; + + if (mod.getModSettings().shouldShowTimer()) { + lastTime = Instant.now().toEpochMilli(); + + String realTime = DATE_TIME_FORMATTER.format(Instant.now().minusMillis(timeRunning)); + renderer.draw("<" + realTime + ">", x, y, whiteColor, true, matrix, vertexConsumers, layerType, 0, 255); + x += addX; + y += addY; + } + + if (tasks.size() <= maxLines) { + for (Task task : tasks) { + renderTask(task, renderer,x,y,matrix,vertexConsumers,layerType); + + x += addX; + y += addY; } - if (tasks.size() > maxLines) { - for (int i = 0; i < tasks.size(); ++i) { - // Skip over the next tasks - if (i == 0 || i > tasks.size() - maxLines) { - renderer.draw(tasks.get(i).toString(), x, y, color, shadow, matrix, vertexConsumers, layerType, backgroundColor, light); - } else if (i == 1) { - renderer.draw(" ... ", x, y, color, shadow, matrix, vertexConsumers, layerType, backgroundColor, light); - } else { - continue; - } - x += 8; - y += fontHeight + 2; - } + return; + } + + for (int i = 0; i < tasks.size(); ++i) { + if (i == 1) { + x += addX*2; + renderer.draw("...", x, y, whiteColor, true, matrix, vertexConsumers, layerType, 0, 255); + + } else if (i == 0 || i > tasks.size() - maxLines) { + renderTask(tasks.get(i), renderer,x,y,matrix,vertexConsumers,layerType); } else { - if (!tasks.isEmpty()) { - for (Task task : tasks) { - renderer.draw(task.toString(), x, y, color, shadow, matrix, vertexConsumers, layerType, backgroundColor, light); - x += 8; - y += fontHeight + 2; - } - } + continue; } + x += addX; + y += addY; } + + } + + + private void renderTask(Task task, TextRenderer renderer, float x, float y, Matrix4f matrix,VertexConsumerProvider vertexConsumers, TextRenderer.TextLayerType layerType ) { + String taskName = task.getClass().getSimpleName() +" "; + renderer.draw(taskName, x, y, new Color(128,128,128).getRGB(), true, matrix, vertexConsumers, layerType, 0, 255); + + renderer.draw(task.toString(), x+renderer.getWidth(taskName), y, new Color(255,255,255).getRGB(), true, matrix, vertexConsumers, layerType, 0, 255); + + } + } diff --git a/src/main/java/adris/altoclef/util/ItemTarget.java b/src/main/java/adris/altoclef/util/ItemTarget.java index 2a6853df..c58d4fa6 100644 --- a/src/main/java/adris/altoclef/util/ItemTarget.java +++ b/src/main/java/adris/altoclef/util/ItemTarget.java @@ -18,21 +18,21 @@ public class ItemTarget { private static final int BASICALLY_INFINITY = 99999999; public static ItemTarget EMPTY = new ItemTarget(new Item[0], 0); - private Item[] _itemMatches; - private int _targetCount; - private String _catalogueName = null; - private boolean _infinite = false; + private Item[] itemMatches; + private final int targetCount; + private String catalogueName = null; + private boolean infinite = false; public ItemTarget(Item[] items, int targetCount) { - _itemMatches = items; - _targetCount = targetCount; - _infinite = false; + itemMatches = items; + this.targetCount = targetCount; + infinite = false; } public ItemTarget(String catalogueName, int targetCount) { - _catalogueName = catalogueName; - _itemMatches = TaskCatalogue.getItemMatches(catalogueName); - _targetCount = targetCount; + this.catalogueName = catalogueName; + itemMatches = TaskCatalogue.getItemMatches(catalogueName); + this.targetCount = targetCount; } public ItemTarget(String catalogueName) { @@ -52,13 +52,13 @@ public ItemTarget(Item item) { } public ItemTarget(ItemTarget toCopy, int newCount) { - if (toCopy._itemMatches != null) { - _itemMatches = new Item[toCopy._itemMatches.length]; - System.arraycopy(toCopy._itemMatches, 0, _itemMatches, 0, toCopy._itemMatches.length); + if (toCopy.itemMatches != null) { + itemMatches = new Item[toCopy.itemMatches.length]; + System.arraycopy(toCopy.itemMatches, 0, itemMatches, 0, toCopy.itemMatches.length); } - _catalogueName = toCopy._catalogueName; - _targetCount = newCount; - _infinite = toCopy._infinite; + catalogueName = toCopy.catalogueName; + targetCount = newCount; + infinite = toCopy.infinite; } public static boolean nullOrEmpty(ItemTarget target) { @@ -74,24 +74,24 @@ public static Item[] getMatches(ItemTarget... targets) { } public ItemTarget infinite() { - _infinite = true; + infinite = true; return this; } public Item[] getMatches() { - return _itemMatches != null ? _itemMatches : new Item[0]; + return itemMatches != null ? itemMatches : new Item[0]; } public int getTargetCount() { - if (_infinite) { + if (infinite) { return BASICALLY_INFINITY; } - return _targetCount; + return targetCount; } public boolean matches(Item item) { - if (_itemMatches != null) { - for (Item match : _itemMatches) { + if (itemMatches != null) { + for (Item match : itemMatches) { if (match == null) continue; if (match.equals(item)) return true; } @@ -100,30 +100,30 @@ public boolean matches(Item item) { } public boolean isCatalogueItem() { - return _catalogueName != null; + return catalogueName != null; } public String getCatalogueName() { - return _catalogueName; + return catalogueName; } @Override public boolean equals(Object obj) { if (obj instanceof ItemTarget other) { - if (_infinite) { - if (!other._infinite) return false; + if (infinite) { + if (!other.infinite) return false; } else { // Neither are infinite - if (_targetCount != other._targetCount) return false; + if (targetCount != other.targetCount) return false; } - if ((other._itemMatches == null) != (_itemMatches == null)) return false; - if (_itemMatches != null) { - if (_itemMatches.length != other._itemMatches.length) return false; - for (int i = 0; i < _itemMatches.length; ++i) { - if (other._itemMatches[i] == null) { - if ((other._itemMatches[i] == null) != (_itemMatches[i] == null)) return false; + if ((other.itemMatches == null) != (itemMatches == null)) return false; + if (itemMatches != null) { + if (itemMatches.length != other.itemMatches.length) return false; + for (int i = 0; i < itemMatches.length; ++i) { + if (other.itemMatches[i] == null) { + if ((other.itemMatches[i] == null) != (itemMatches[i] == null)) return false; } else { - if (!other._itemMatches[i].equals(_itemMatches[i])) return false; + if (!other.itemMatches[i].equals(itemMatches[i])) return false; } } } @@ -133,7 +133,7 @@ public boolean equals(Object obj) { } public boolean isEmpty() { - return _itemMatches == null || _itemMatches.length == 0; + return itemMatches == null || itemMatches.length == 0; } @Override @@ -143,27 +143,27 @@ public String toString() { if (isEmpty()) { result.append("(empty)"); } else if (isCatalogueItem()) { - result.append(_catalogueName); + result.append(catalogueName); } else { result.append("["); int counter = 0; - if (_itemMatches != null) { - for (Item item : _itemMatches) { + if (itemMatches != null) { + for (Item item : itemMatches) { if (item == null) { result.append("(null??)"); } else { result.append(ItemHelper.trimItemName(item.getTranslationKey())); } - if (++counter != _itemMatches.length) { + if (++counter != itemMatches.length) { result.append(","); } } } result.append("]"); } - if (!_infinite && !isEmpty()) { - result.append(" x ").append(_targetCount); - } else if (_infinite) { + if (!infinite && !isEmpty() && targetCount > 1) { + result.append(" x ").append(targetCount); + } else if (infinite) { result.append(" x infinity"); } diff --git a/src/main/java/adris/altoclef/util/JankCraftingRecipeMapping.java b/src/main/java/adris/altoclef/util/JankCraftingRecipeMapping.java index 70a73fbc..2fefac59 100644 --- a/src/main/java/adris/altoclef/util/JankCraftingRecipeMapping.java +++ b/src/main/java/adris/altoclef/util/JankCraftingRecipeMapping.java @@ -15,7 +15,7 @@ * For crafting table/inventory recipe book crafting, we need to figure out identifiers given a recipe. */ public class JankCraftingRecipeMapping { - private static final HashMap>> _recipeMapping = new HashMap<>(); + private static final HashMap>> recipeMapping = new HashMap<>(); /** * Reloads the recipe mapping. @@ -33,7 +33,7 @@ private static void reloadRecipeMapping() { for (RecipeEntry recipe : recipes.values()) { assert world != null; Item output = recipe.value().getResult(world.getRegistryManager()).getItem(); - _recipeMapping.computeIfAbsent(output, k -> new ArrayList<>()).add(recipe); + recipeMapping.computeIfAbsent(output, k -> new ArrayList<>()).add(recipe); } } } @@ -49,9 +49,9 @@ private static void reloadRecipeMapping() { public static Optional> getMinecraftMappedRecipe(CraftingRecipe recipe, Item output) { reloadRecipeMapping(); // Check if the output item is present in the recipe mapping - if (_recipeMapping.containsKey(output)) { + if (recipeMapping.containsKey(output)) { // Iterate through all the recipes mapped to the output item - for (RecipeEntry checkRecipe : _recipeMapping.get(output)) { + for (RecipeEntry checkRecipe : recipeMapping.get(output)) { // Create a list of item targets to satisfy List toSatisfy = Arrays.stream(recipe.getSlots()) .filter(itemTarget -> itemTarget != null && !itemTarget.isEmpty()) diff --git a/src/main/java/adris/altoclef/util/MinecraftServerMixin.java b/src/main/java/adris/altoclef/util/MinecraftServerMixin.java new file mode 100644 index 00000000..820fe0b2 --- /dev/null +++ b/src/main/java/adris/altoclef/util/MinecraftServerMixin.java @@ -0,0 +1,7 @@ +package adris.altoclef.util; + +public interface MinecraftServerMixin { + + void setMsPerTick(int ms); + +} diff --git a/src/main/java/adris/altoclef/util/RecipeTarget.java b/src/main/java/adris/altoclef/util/RecipeTarget.java index 4e24330f..26d1ba53 100644 --- a/src/main/java/adris/altoclef/util/RecipeTarget.java +++ b/src/main/java/adris/altoclef/util/RecipeTarget.java @@ -6,33 +6,35 @@ public class RecipeTarget { - private final CraftingRecipe _recipe; - private final Item _item; - private final int _targetCount; + private final CraftingRecipe recipe; + private final Item item; + private final int targetCount; public RecipeTarget(Item item, int targetCount, CraftingRecipe recipe) { - _item = item; - _targetCount = targetCount; - _recipe = recipe; + this.item = item; + this.targetCount = targetCount; + this.recipe = recipe; } public CraftingRecipe getRecipe() { - return _recipe; + return recipe; } public Item getOutputItem() { - return _item; + return item; } public int getTargetCount() { - return _targetCount; + return targetCount; } @Override public String toString() { - return "RecipeTarget{" + - "_recipe=" + _recipe + - ", _item=" + _item + " x " + _targetCount + + if (targetCount == 1) + return "Recipe{"+item+"}"; + + return "Recipe{" + + item + " x " + targetCount + '}'; } @@ -41,11 +43,11 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; RecipeTarget that = (RecipeTarget) o; - return _targetCount == that._targetCount && _recipe.equals(that._recipe) && Objects.equals(_item, that._item); + return targetCount == that.targetCount && recipe.equals(that.recipe) && Objects.equals(item, that.item); } @Override public int hashCode() { - return Objects.hash(_recipe, _item); + return Objects.hash(recipe, item); } } diff --git a/src/main/java/adris/altoclef/util/SmeltTarget.java b/src/main/java/adris/altoclef/util/SmeltTarget.java index 001467e4..13080ec4 100644 --- a/src/main/java/adris/altoclef/util/SmeltTarget.java +++ b/src/main/java/adris/altoclef/util/SmeltTarget.java @@ -6,27 +6,27 @@ public class SmeltTarget { - private final ItemTarget _item; - private final Item[] _optionalMaterials; - private ItemTarget _material; + private final ItemTarget item; + private final Item[] optionalMaterials; + private ItemTarget material; public SmeltTarget(ItemTarget item, ItemTarget material, Item... optionalMaterials) { - _item = item; - _material = material; - _material = new ItemTarget(material, _item.getTargetCount()); - _optionalMaterials = optionalMaterials; + this.item = item; + this.material = material; + this.material = new ItemTarget(material, this.item.getTargetCount()); + this.optionalMaterials = optionalMaterials; } public ItemTarget getItem() { - return _item; + return item; } public ItemTarget getMaterial() { - return _material; + return material; } public Item[] getOptionalMaterials() { - return _optionalMaterials; + return optionalMaterials; } @Override @@ -34,11 +34,11 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; SmeltTarget that = (SmeltTarget) o; - return Objects.equals(_material, that._material) && Objects.equals(_item, that._item); + return Objects.equals(material, that.material) && Objects.equals(item, that.item); } @Override public int hashCode() { - return Objects.hash(_material, _item); + return Objects.hash(material, item); } } diff --git a/src/main/java/adris/altoclef/util/helpers/BaritoneHelper.java b/src/main/java/adris/altoclef/util/helpers/BaritoneHelper.java index 86094514..d85e4a38 100644 --- a/src/main/java/adris/altoclef/util/helpers/BaritoneHelper.java +++ b/src/main/java/adris/altoclef/util/helpers/BaritoneHelper.java @@ -21,6 +21,6 @@ public static double calculateGenericHeuristic(double xStart, double yStart, dou double xDiff = xTarget - xStart; int yDiff = (int) yTarget - (int) yStart; double zDiff = zTarget - zStart; - return GoalBlock.calculate(xDiff, yDiff < 0 ? yDiff + 1 : yDiff, zDiff); + return GoalBlock.calculate(xDiff, yDiff < 0 ? yDiff - 1 : yDiff, zDiff); } } diff --git a/src/main/java/adris/altoclef/util/helpers/ItemHelper.java b/src/main/java/adris/altoclef/util/helpers/ItemHelper.java index dfb574df..48f1d074 100644 --- a/src/main/java/adris/altoclef/util/helpers/ItemHelper.java +++ b/src/main/java/adris/altoclef/util/helpers/ItemHelper.java @@ -39,7 +39,7 @@ public class ItemHelper { public static final Item[] DIRTS = new Item[]{Items.DIRT, Items.DIRT_PATH, Items.COARSE_DIRT, Items.ROOTED_DIRT}; public static final Item[] PLANKS = new Item[]{Items.ACACIA_PLANKS, Items.BIRCH_PLANKS, Items.CRIMSON_PLANKS, Items.DARK_OAK_PLANKS, Items.OAK_PLANKS, Items.JUNGLE_PLANKS, Items.SPRUCE_PLANKS, Items.WARPED_PLANKS, - Items.MANGROVE_PLANKS, Items.CHERRY_PLANKS, Items.BAMBOO_PLANKS, Items.CHERRY_PLANKS}; + Items.MANGROVE_PLANKS, Items.CHERRY_PLANKS, Items.BAMBOO_PLANKS}; public static final Item[] LEAVES = new Item[]{Items.ACACIA_LEAVES, Items.BIRCH_LEAVES, Items.DARK_OAK_LEAVES, Items.OAK_LEAVES, Items.JUNGLE_LEAVES, Items.SPRUCE_LEAVES, Items.MANGROVE_LEAVES, Items.CHERRY_LEAVES}; public static final Item[] WOOD = new Item[]{Items.ACACIA_WOOD, Items.BIRCH_WOOD, Items.CRIMSON_HYPHAE, @@ -243,7 +243,7 @@ void p(WoodType type, String prefix, Item planks, Item log, Item strippedLog, It put(type, new WoodItems(prefix, planks, log, strippedLog, strippedWood, wood, sign, hangingSign, door, button, stairs, slab, fence, fenceGate, boat, sapling, leaves, pressurePlate, trapdoor)); } }; - private static final HashMap _cookableFoodMap = new HashMap<>() { + public static final HashMap _cookableFoodMap = new HashMap<>() { { put(Items.PORKCHOP, Items.COOKED_PORKCHOP); put(Items.BEEF, Items.COOKED_BEEF); @@ -256,6 +256,7 @@ void p(WoodType type, String prefix, Item planks, Item log, Item strippedLog, It } }; public static final Item[] RAW_FOODS = _cookableFoodMap.keySet().toArray(Item[]::new); + public static final Item[] COOKED_FOODS = _cookableFoodMap.values().toArray(Item[]::new); private static Map _fuelTimeMap = null; public static String stripItemName(Item item) { @@ -279,6 +280,7 @@ public static Item[] blocksToItems(Block[] blocks) { /* Logs: ACACIA BIRCH + CHERRY CRIMSON DARK_OAK OAK diff --git a/src/main/java/adris/altoclef/util/helpers/StlHelper.java b/src/main/java/adris/altoclef/util/helpers/StlHelper.java index a8e933cf..43297a98 100644 --- a/src/main/java/adris/altoclef/util/helpers/StlHelper.java +++ b/src/main/java/adris/altoclef/util/helpers/StlHelper.java @@ -29,6 +29,10 @@ static String toString(Collection thing, Function toStringFunc } static String toString(T[] thing, Function toStringFunc) { - return toString(Arrays.asList(thing), toStringFunc); + try { + return toString(Arrays.asList(thing), toStringFunc); + } catch (NullPointerException ignored) { + return ""; + } } } \ No newline at end of file diff --git a/src/main/java/adris/altoclef/util/helpers/StorageHelper.java b/src/main/java/adris/altoclef/util/helpers/StorageHelper.java index 192e9d47..6e4d5a67 100644 --- a/src/main/java/adris/altoclef/util/helpers/StorageHelper.java +++ b/src/main/java/adris/altoclef/util/helpers/StorageHelper.java @@ -14,7 +14,9 @@ import adris.altoclef.util.slots.PlayerSlot; import adris.altoclef.util.slots.Slot; import baritone.utils.ToolSet; +import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.ChatScreen; import net.minecraft.client.gui.screen.GameMenuScreen; @@ -136,6 +138,8 @@ public static Optional getBestToolSlot(AltoClef mod, BlockState state) { // PREFER (Always use silk touch if we have) // AVOID (Don't use silk touch if we can) // } + Block block = state.getBlock(); + Slot bestToolSlot = null; double highestSpeed = Double.NEGATIVE_INFINITY; if (Slot.getCurrentScreenSlots() != null) { @@ -145,6 +149,8 @@ public static Optional getBestToolSlot(AltoClef mod, BlockState state) { ItemStack stack = getItemStackInSlot(slot); if (stack.getItem() instanceof ToolItem) { if (stack.getItem().isSuitableFor(state)) { + if (shouldSaveStack(mod, block,stack)) continue; + double speed = ToolSet.calculateSpeedVsBlock(stack, state); if (speed > highestSpeed) { highestSpeed = speed; @@ -164,6 +170,26 @@ public static Optional getBestToolSlot(AltoClef mod, BlockState state) { return Optional.ofNullable(bestToolSlot); } + // if the iron pickaxes durability is low, we do not have diamond pickaxe and are not mining diamonds, do not use it + public static boolean shouldSaveStack(AltoClef mod,Block block, ItemStack stack) { + if (!stack.getItem().equals(Items.IRON_PICKAXE) || mod.getItemStorage().hasItem(Items.DIAMOND_PICKAXE)) return false; + + boolean diamondRelatedBlock = block.equals(Blocks.DIAMOND_BLOCK) || block.equals(Blocks.DIAMOND_ORE) || block.equals(Blocks.DEEPSLATE_DIAMOND_ORE); + + // if the durability is really low, mine only diamond related stuff + if (stack.getDamage()+8 > stack.getMaxDamage()) { + return diamondRelatedBlock; + } + + // if the durability gets low, mine only things we have to + if (stack.getDamage()+30 > stack.getMaxDamage()) { + return !MiningRequirement.getMinimumRequirementForBlock(block).equals(MiningRequirement.IRON); + } + + + return false; + } + // Gets a slot with an item we can throw away public static Optional getGarbageSlot(AltoClef mod) { // Throwaway items, but keep a few for building. @@ -369,6 +395,10 @@ public static boolean isFurnaceOpen() { return isScreenOpenInner(screen -> screen instanceof FurnaceScreenHandler); } + public static boolean isChestOpen() { + return isScreenOpenInner(screen -> screen instanceof GenericContainerScreenHandler); + } + public static boolean isSmokerOpen() { return isScreenOpenInner(screen -> screen instanceof SmokerScreenHandler); } diff --git a/src/main/java/adris/altoclef/util/helpers/WorldHelper.java b/src/main/java/adris/altoclef/util/helpers/WorldHelper.java index 6cc43b57..aef450f2 100644 --- a/src/main/java/adris/altoclef/util/helpers/WorldHelper.java +++ b/src/main/java/adris/altoclef/util/helpers/WorldHelper.java @@ -180,7 +180,7 @@ static int getGroundHeight(AltoClef mod, int x, int z) { } static BlockPos getADesertTemple(AltoClef mod) { - List stonePressurePlates = mod.getBlockTracker().getKnownLocations(Blocks.STONE_PRESSURE_PLATE); + List stonePressurePlates = mod.getBlockScanner().getKnownLocations(Blocks.STONE_PRESSURE_PLATE); if (!stonePressurePlates.isEmpty()) { for (BlockPos pos : stonePressurePlates) { if (mod.getWorld().getBlockState(pos).getBlock() == Blocks.STONE_PRESSURE_PLATE && // Duct tape @@ -268,7 +268,7 @@ static boolean canReach(AltoClef mod, BlockPos pos) { } } } - return !mod.getBlockTracker().unreachable(pos); + return !mod.getBlockScanner().isUnreachable(pos); } static boolean isOcean(RegistryEntry b) { @@ -284,7 +284,7 @@ static boolean isOcean(RegistryEntry b) { } static boolean isAir(AltoClef mod, BlockPos pos) { - return mod.getBlockTracker().blockIsValid(pos, Blocks.AIR, Blocks.CAVE_AIR, Blocks.VOID_AIR); + return mod.getBlockScanner().isBlockAtPosition(pos, Blocks.AIR, Blocks.CAVE_AIR, Blocks.VOID_AIR); //return state.isAir() || isAir(state.getBlock()); } @@ -403,15 +403,27 @@ static boolean isBlock(AltoClef mod, BlockPos pos, Block block) { } static boolean canSleep() { - int time = 0; ClientWorld world = MinecraftClient.getInstance().world; if (world != null) { // You can sleep during thunderstorms if (world.isThundering() && world.isRaining()) return true; - time = (int) (world.getTimeOfDay() % 24000); + + int time = getTimeOfDay(); + // https://minecraft.fandom.com/wiki/Daylight_cycle + return 12542 <= time && time <= 23992; + } + + return false; + } + + static int getTimeOfDay() { + ClientWorld world = MinecraftClient.getInstance().world; + if (world != null) { + // You can sleep during thunderstorms + return (int) (world.getTimeOfDay() % 24000); } - // https://minecraft.fandom.com/wiki/Daylight_cycle - return 12542 <= time && time <= 23992; + return 0; } + } diff --git a/src/main/java/adris/altoclef/util/serialization/AbstractVectorDeserializer.java b/src/main/java/adris/altoclef/util/serialization/AbstractVectorDeserializer.java index a18e5e5e..27fb8a25 100644 --- a/src/main/java/adris/altoclef/util/serialization/AbstractVectorDeserializer.java +++ b/src/main/java/adris/altoclef/util/serialization/AbstractVectorDeserializer.java @@ -11,11 +11,11 @@ import java.util.*; public abstract class AbstractVectorDeserializer extends StdDeserializer { - public AbstractVectorDeserializer() { + protected AbstractVectorDeserializer() { this(null); } - public AbstractVectorDeserializer(Class vc) { + protected AbstractVectorDeserializer(Class vc) { super(vc); } @@ -47,7 +47,7 @@ UnitType tryParse(JsonParser p, String whole, String part) throws JsonParseExcep } @Override - public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { + public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String[] neededComponents = getComponents(); if (p.getCurrentToken() == JsonToken.VALUE_STRING) { String bposString = p.getValueAsString(); @@ -55,7 +55,7 @@ public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOExcepti if (parts.length != neededComponents.length) { throw new JsonParseException(p, "Invalid " + getTypeName() + " string: \"" + bposString + "\", must be in form \"" + String.join(",", neededComponents) + "\"."); } - ArrayList resultingUnits = new ArrayList(); + ArrayList resultingUnits = new ArrayList<>(); for (String part : parts) { resultingUnits.add(tryParse(p, bposString, part)); } @@ -65,7 +65,6 @@ public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOExcepti p.nextToken(); while (p.getCurrentToken() != JsonToken.END_OBJECT) { if (p.getCurrentToken() == JsonToken.FIELD_NAME) { - String fName = p.getCurrentName(); p.nextToken(); if (!isUnitTokenValid(p.currentToken())) { throw new JsonParseException(p, "Invalid token for " + getTypeName() + ". Got: " + p.getCurrentToken()); @@ -83,7 +82,7 @@ public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOExcepti if (parts.size() != neededComponents.length) { throw new JsonParseException(p, "Expected [" + String.join(",", neededComponents) + "] keys to be part of a blockpos object. Got " + Arrays.toString(parts.keySet().toArray(String[]::new))); } - ArrayList resultingUnits = new ArrayList(); + ArrayList resultingUnits = new ArrayList<>(); for (String componentName : neededComponents) { resultingUnits.add(trySet(p, parts, componentName)); } diff --git a/src/main/java/adris/altoclef/util/serialization/AbstractVectorSerializer.java b/src/main/java/adris/altoclef/util/serialization/AbstractVectorSerializer.java index faa1741d..3ef25562 100644 --- a/src/main/java/adris/altoclef/util/serialization/AbstractVectorSerializer.java +++ b/src/main/java/adris/altoclef/util/serialization/AbstractVectorSerializer.java @@ -8,11 +8,11 @@ import java.util.Collection; public abstract class AbstractVectorSerializer extends StdSerializer { - public AbstractVectorSerializer() { + protected AbstractVectorSerializer() { this(null); } - public AbstractVectorSerializer(Class vc) { + protected AbstractVectorSerializer(Class vc) { super(vc); } diff --git a/src/main/resources/altoclef.mixins.json b/src/main/resources/altoclef.mixins.json index e026edae..674790ae 100644 --- a/src/main/resources/altoclef.mixins.json +++ b/src/main/resources/altoclef.mixins.json @@ -9,13 +9,13 @@ "ClientBlockBreakAccessor", "ClientConnectionAccessor", "ClientInteractWithBlockMixin", - "ClientPlayerInteractionAccessor", "ClientUIMixin", "DeathScreenAccessor", "EntityAccessor", "GameOverlayMixin", "PersistentProjectileEntityAccessor", "SlotClickMixin", + "ToolSetMixin", "WorldBlockModifiedMixin" ], "client": [ @@ -27,7 +27,8 @@ "EntryMixin", "LoadChunkMixin", "MixinLocalPlayer", - "PlayerCollidesWithEntityMixin" + "PlayerCollidesWithEntityMixin", + "SimpleOptionMixin" ], "injectors": { "defaultRequire": 1 diff --git a/src/main/resources/assets/altoclef/icon.png b/src/main/resources/assets/altoclef/icon.png index 23f6b2a1..8eee6d27 100644 Binary files a/src/main/resources/assets/altoclef/icon.png and b/src/main/resources/assets/altoclef/icon.png differ diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index bd38f8d9..6de42c0f 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -7,7 +7,8 @@ "authors": [ "TacoTechnica", "James Green", - "Marvion Kirito" + "Marvion Kirito", + "MiranCZ" ], "contact": { "homepage": "https://fabricc.net/", diff --git a/todos.md b/todos.md deleted file mode 100644 index 89cf2418..00000000 --- a/todos.md +++ /dev/null @@ -1,8 +0,0 @@ -# TODO's: Long Term Future Features - -- Smart tasks that are user customizable. Give resources json-assignable descriptions on how they CAN be obtained, and - the system automatically tries to obtain it in the fastest way. -- Given any schematic, Collect ALL resources and BUILD the schematic, ideally from a fresh survival world if possible. -- Initialize and control multiple bots over a network. Kind of like an RTS game. -- Make this bot able to survive anarchy -- All acheivements, fully autonomous (not happening any time soon lol) \ No newline at end of file diff --git a/usage.md b/usage.md index f8af8c6b..22ffe5e3 100644 --- a/usage.md +++ b/usage.md @@ -8,37 +8,17 @@ Keep in mind this project is still in rapid development. A lot of features are p Commands are prefixed with `@`. Here's a list along with their functions: -| command | description | examples | -|-----------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------| -| `help` | Lists all commands | | -| `coords` | Prints the bot's current coordinates. This is here in cases where the `F3` menu gets too crowded. | -| `equip {material}` or `equip [items...]` | Equips a `material` armor set or `[items...]`. If not in the bot's inventory, bot will obtain it. | `@equip [diamond_chestplate, gold_leggings]` `@equip netherite` | -| `follow {player = }` | Follow a player. If sent via `/msg`, will follow the player who sent the command. | `@follow TacoTechnica` `/msg Bot follow` | -| `hero` | Kills all hostile mobs | `@hero` | -| `food {amount}` | Collects `amount` units of food (1 unit = 1/2 drumstick). Collects from various sources (animals, crops) | `@food 20` | -| `gamer` | Beats the game epic style | `@gamer` | -| `get [items...]` | Gets all items in `[items...]`. Can either do one item or pass a comma-separated list to get multiple items. Not every resource is get-able. | `@get diamond 3` `@get [cobblestone 40, wooden_door, glass 4]` | -| `list` | Prints a list of all get-able items | | -| `give {player = } {item} {quantity=1}` | Gives `player` `quantity` units of `item`, getting said items if the bot doesn't have them. If sent via `/msg`, will follow the player who sent the command. | `/msg Bot give iron_pickaxe` | -| `deposit [items... = ]` | Deposit a list of items in the nearest container, making a chest if we can't find one. Will only deposit items present in the bot's inventory (at the time of running this command). Leave out the list to deposit every non-tool/armor item in the bot's inventory. Useful with command chaining. | `@deposit diamond 3` `@deposit [cobblestone 1000, raw_iron 100]` `@deposit` | -| `stash {x0} {y0} {z0} {x1} {y0} {z1} [items... = ]` | Same as `@deposit`, but you specify an area from `(x0, y0, z0)` to `(x1, y1, z1)` where the bot stores the item list (these coordinates being a chest stash). Just like `@deposit`, providing no items simply deposits everything in the bots inventory. | `@stash 100 64 100 200 70 100 diamond 3` | -| `goto {x} {y} {z} {dimension=}` | Goes to (`x`,`y`, `z`) in a given `dimension`. Travels to `dimension` if not there already. Can also omit coordinates to just go to a dimension. Passing 2 values as coordinates goes to X Z coordinates instead. | `@goto 100 64 100 overworld` `@goto nether` `@goto 100 100` | -| `inventory {item=}` | Prints the bots inventory, OR how many items of a specific type the bot has. Mostly useful when running through `/msg`. | `/msg Bot inventory` `/msg Bot inventory cobblestone` | -| `locate_structure {structure_type}` | Attempts to locate a `structure_type` structure. Can find strongholds or desert temples. | `@locate_structure stronghold`, `@locate_structure desert_temple` | -| `punk {player}` | Attacks `player`. | | -| `reload_settings` | Reloads the local settings file. Run this every time you want your settings to be updated. | | -| `gamma {brightness=1}` | Sets the game's gamma. Useful for testing. 0 is "Moody" and 1 is "Bright", and you can go beyond to enable fullbright. | `@gamma 1000` | -| `status` | Prints the status of the currently executing command. Mostly useful when running through `/msg`. | | -| `stop` | Forcefully stops the currently running command. The shortcut `CTRL+K` also achieves this. | | -| `test {testname}` | Runs a "test" command. These vary, and will be described below. | | +| command | description | examples | +|------------------------|------------------------------------------------------------------------------------------------------------------------|---------------| +| `help` | Lists all commands | | +| `gamer` | Beats the game epic style | `@gamer` | +| `reload_settings` | Reloads the local settings file. Run this every time you want your settings to be updated. | | +| `gamma {brightness=1}` | Sets the game's gamma. Useful for testing. 0 is "Moody" and 1 is "Bright", and you can go beyond to enable fullbright. | `@gamma 1000` | +| `scan` | Logs the nearest given block currently found be `BlockScanner`. | `@scan dirt` | +| `status` | Prints the status of the currently executing command. Mostly useful when running through `/msg`. | | +| `stop` | Forcefully stops the currently running command. The shortcut `CTRL+K` also achieves this. | | +| `test {testname}` | Runs a "test" command. These vary, and will be described below. | | -### Command chaining - -Execute consecutve commands by separating them with `;` - -`@get iron_axe;get log 100;goto 0 0;give Player log 100` - -will get an iron axe, then get 100 logs, then go to `x=0 z=0` and then give 100 logs to a player with the name `Player` ### Notable test commands @@ -46,6 +26,8 @@ Test commands are temporary/only exist as an experiment, but some of these might For example, `@test terminate` runs the terminator. Here's a list of some highlights. +**note** *this list doesn't include all the test tasks, but it is not my priority to update it...* + | test name | what it does | |-------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `terminate` | Runs the terminator task. When without diamond gear, the bot flees players and obtains diamond gear + food. When diamond gear is equipped, the bot hunts any nearby players down and searches for any chunks that were last seen to have players in them. | @@ -63,41 +45,9 @@ Here's a list of some highlights. After running the game with the mod once, a folder called `altoclef` should appear in your `.minecraft` directory. This contains `altoclef` related settings and configurations. -With regards to the `altoclef_settings.json` file -Check [Settings.java](https://github.com/gaucho-matrero/altoclef/blob/main/src/main/java/adris/altoclef/Settings.java) - -After modifying your local settings, run `@reload_settings` to apply your changes in-game. - -## /msg: The Butler System - -This bot lets other players run commands on the bot via server messages. When sending a command via `/msg` you may omit -the `@`. - -You'll have to append each player's name to a file called `altoclef_butler_whitelist.txt` -located in your `.minecraft/altoclef` directory. Make sure your name is not found in `altoclef_butler_blacklist.txt` -too. - -### Disabling/Enabling Blacklist/Whitelist - -To toggle whitelist/blacklist, check the `useButlerBlacklist` and `useButlerWhitelist` settings. - -**WARNING:** If you set `useButlerWhitelist` to false, ALL PLAYERS will be able to send commands to the bot. Be extra -careful with this one. - -### Expect delayed messages - -Servers auto-kick players that rapidly send messages. For this reason, the butler will send messages at a delayed rate. -When sending messages, messages to authorized -users are prioritized and sent first. - -### Dealing with custom /msg outputs on servers - -If the server's whisper /msg system doesn't send players a message that looks like `X whispers to you: Y` and it's not -being -picked up by altoclef, you can append the server's custom whisper format in the `whisperFormats` setting. +Regarding the `altoclef_settings.json` file +Check [Settings.java](https://github.com/MiranCZ/altoclef/blob/main/src/main/java/adris/altoclef/Settings.java) -**NOTE:** At least for now, you must escape brackets and paranthesis. Example: To receive messages that look -like `[Player -> me] message` the format string is `\[{from} -> {to}\] {message}` +Other configs can be found in the `configs` subdirectory. Some of the `beat_minecraft.json` settings may not work, but I plan to reimplement proper settings in the future. -**WARNING:** Be careful with this one as well, as the bot will trust these formats for ALL non-player chat messages. -Messing up the format's ordering can let unauthorized people execute bot commands. +After modifying your local settings, run `@reload_settings` to apply your changes in-game. \ No newline at end of file