diff --git a/src/api/java/baritone/api/behavior/IElytraBehavior.java b/src/api/java/baritone/api/behavior/IElytraBehavior.java index 3c3b91466..21169b896 100644 --- a/src/api/java/baritone/api/behavior/IElytraBehavior.java +++ b/src/api/java/baritone/api/behavior/IElytraBehavior.java @@ -19,8 +19,20 @@ package baritone.api.behavior; import net.minecraft.util.math.BlockPos; +import java.util.concurrent.CompletableFuture; + public interface IElytraBehavior extends IBehavior { + /** + * Marks the nether pathfinder context to be reset when it is safe to do so. Because this operation is not + * immediate, a {@link CompletableFuture} is returned that will complete after the context has been reset. + * + * @return A {@link CompletableFuture} that is completed when the context is reset + */ + CompletableFuture resetContext(); + + void repackChunks(); + void pathTo(BlockPos destination); void cancel(); diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index f08fb9be6..5549281f7 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -41,6 +41,7 @@ import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.movements.MovementFall; import baritone.utils.BlockStateInterface; import baritone.utils.PathingCommandContext; +import baritone.utils.accessor.IChunkProviderClient; import baritone.utils.accessor.IEntityFireworkRocket; import it.unimi.dsi.fastutil.floats.FloatArrayList; import it.unimi.dsi.fastutil.floats.FloatIterator; @@ -76,7 +77,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // :sunglasses: private NetherPathfinderContext context; - private boolean forceResetContext; + private CompletableFuture forceResetContext; private final PathManager pathManager; private final ElytraProcess process; @@ -370,7 +371,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (event.getWorld() != null) { if (event.getState() == EventState.PRE) { // Reset the context when it's safe to do so on the next game tick - this.forceResetContext = true; + this.resetContext(); } } else { if (event.getState() == EventState.POST) { @@ -429,6 +430,20 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H Arrays.fill(this.nextTickBoostCounter, 0); } + @Override + public CompletableFuture resetContext() { + if (this.forceResetContext == null) { + this.forceResetContext = new CompletableFuture<>(); + } + return this.forceResetContext; + } + + @Override + public void repackChunks() { + ((IChunkProviderClient) ctx.world().getChunkProvider()).loadedChunks().values() + .forEach(this.context::queueForPacking); + } + @Override public boolean isActive() { return baritone.getPathingControlManager().mostRecentInControl() @@ -455,15 +470,16 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // Setup/reset context final long netherSeed = Baritone.settings().elytraNetherSeed.value; - if (this.context == null || this.context.getSeed() != netherSeed || this.forceResetContext) { + if (this.context == null || this.context.getSeed() != netherSeed || this.forceResetContext != null) { if (this.context != null) { this.context.destroy(); } this.context = new NetherPathfinderContext(netherSeed); - this.forceResetContext = false; - - if (this.isActive()) { - // TODO: Re-pack chunks? + if (this.forceResetContext != null) { + this.forceResetContext.complete(null); + this.forceResetContext = null; + } + if (this.context.getSeed() != netherSeed && this.isActive()) { logDirect("Nether seed changed, recalculating path"); this.pathManager.pathToDestination(); } diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index cd7034ef8..de8cbadef 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -18,6 +18,7 @@ package baritone.command.defaults; import baritone.api.IBaritone; +import baritone.api.behavior.IElytraBehavior; import baritone.api.command.Command; import baritone.api.command.argument.IArgConsumer; import baritone.api.command.exception.CommandException; @@ -40,30 +41,52 @@ public class ElytraCommand extends Command { @Override public void execute(String label, IArgConsumer args) throws CommandException { - ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess(); - args.requireMax(0); - Goal iGoal = customGoalProcess.mostRecentGoal(); - if (iGoal == null) { - throw new CommandInvalidStateException("No goal has been set"); + final ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess(); + final IElytraBehavior elytra = baritone.getElytraBehavior(); + if (!args.hasAny()) { + Goal iGoal = customGoalProcess.mostRecentGoal(); + if (iGoal == null) { + throw new CommandInvalidStateException("No goal has been set"); + } + final int x, y, z; + if (iGoal instanceof GoalXZ) { + GoalXZ goal = (GoalXZ) iGoal; + x = goal.getX(); + y = 64; + z = goal.getZ(); + } else if (iGoal instanceof GoalBlock) { + GoalBlock goal = (GoalBlock) iGoal; + x = goal.x; + y = goal.y; + z = goal.z; + } else { + throw new CommandInvalidStateException("The goal must be a GoalXZ or GoalBlock"); + } + if (y <= 0 || y >= 128) { + throw new CommandInvalidStateException("The y of the goal is not between 0 and 128"); + } + elytra.pathTo(new BlockPos(x, y, z)); + return; } - final int x, y, z; - if (iGoal instanceof GoalXZ) { - GoalXZ goal = (GoalXZ) iGoal; - x = goal.getX(); - y = 64; - z = goal.getZ(); - } else if (iGoal instanceof GoalBlock) { - GoalBlock goal = (GoalBlock) iGoal; - x = goal.x; - y = goal.y; - z = goal.z; - } else { - throw new CommandInvalidStateException("The goal must be a GoalXZ or GoalBlock"); + + final String action = args.getString(); + switch (action) { + case "reset": { + elytra.resetContext().whenComplete((result, ex) -> { + logDirect("Context reset, repacking chunks"); + elytra.repackChunks(); + }); + break; + } + case "repack": { + elytra.repackChunks(); + logDirect("Queued all loaded chunks for repacking"); + break; + } + default: { + throw new CommandInvalidStateException("Invalid action"); + } } - if (y <= 0 || y >= 128) { - throw new CommandInvalidStateException("The y of the goal is not between 0 and 128"); - } - baritone.getElytraBehavior().pathTo(new BlockPos(x, y, z)); } @Override