pathThroughCachedOnly = new Setting<>(false);
+ /**
+ * 😎 Render cached chunks as semitransparent. Doesn't work with OptiFine ðŸ˜
+ *
+ * Can be very useful on servers with low render distance. After enabling, you may need to reload the world in order for it to have an effect
+ * (e.g. disconnect and reconnect, enter then exit the nether, die and respawn, etc). This may literally kill your FPS and CPU because
+ * every chunk gets recompiled twice as much as normal, since the cached version comes into range, then the normal one comes from the server for real.
+ *
+ * Note that flowing water is cached as AVOID, which is rendered as lava. As you get closer, you may therefore see lava falls being replaced with water falls.
+ *
+ * SOLID is rendered as stone in the overworld, netherrack in the nether, and end stone in the end
+ */
+ public Setting renderCachedChunks = new Setting<>(false);
+
+ /**
+ * 0.0f = not visible, fully transparent
+ * 1.0f = fully opaque
+ */
+ public Setting cachedChunksOpacity = new Setting<>(0.5f);
+
+ /**
+ * If true, Baritone will not allow you to left or right click while pathing
+ */
+ public Setting suppressClicks = new Setting<>(false);
+
/**
* Whether or not to use the "#" command prefix
*/
- public final Setting prefix = new Setting<>(false);
+ public final Setting prefixControl = new Setting<>(true);
/**
* Don't stop walking forward when you need to break blocks in your way
@@ -485,6 +509,11 @@ public final class Settings {
*/
public final Setting mineGoalUpdateInterval = new Setting<>(5);
+ /**
+ * When GetToBlock doesn't know any locations for the desired block, explore randomly instead of giving up.
+ */
+ public final Setting exploreForBlocks = new Setting<>(true);
+
/**
* While mining, should it also consider dropped items of the correct type as a pathing destination (as well as ore blocks)?
*/
@@ -638,7 +667,7 @@ public final class Settings {
}
}
- public class Setting {
+ public final class Setting {
public T value;
public final T defaultValue;
private String name;
diff --git a/src/api/java/baritone/api/behavior/IPathingBehavior.java b/src/api/java/baritone/api/behavior/IPathingBehavior.java
index d28195ae9..64be71d50 100644
--- a/src/api/java/baritone/api/behavior/IPathingBehavior.java
+++ b/src/api/java/baritone/api/behavior/IPathingBehavior.java
@@ -38,11 +38,24 @@ public interface IPathingBehavior extends IBehavior {
* @return The estimated remaining ticks in the current segment.
*/
default Optional ticksRemainingInSegment() {
+ return ticksRemainingInSegment(true);
+ }
+
+ /**
+ * Returns the estimated remaining ticks in the current pathing
+ * segment. Given that the return type is an optional, {@link Optional#empty()}
+ * will be returned in the case that there is no current segment being pathed.
+ *
+ * @param includeCurrentMovement whether or not to include the entirety of the cost of the currently executing movement in the total
+ * @return The estimated remaining ticks in the current segment.
+ */
+ default Optional ticksRemainingInSegment(boolean includeCurrentMovement) {
IPathExecutor current = getCurrent();
if (current == null) {
return Optional.empty();
}
- return Optional.of(current.getPath().ticksRemainingFrom(current.getPosition()));
+ int start = includeCurrentMovement ? current.getPosition() : current.getPosition() + 1;
+ return Optional.of(current.getPath().ticksRemainingFrom(start));
}
/**
diff --git a/src/launch/java/baritone/launch/mixins/MixinChunkRenderContainer.java b/src/launch/java/baritone/launch/mixins/MixinChunkRenderContainer.java
new file mode 100644
index 000000000..fef16d6b4
--- /dev/null
+++ b/src/launch/java/baritone/launch/mixins/MixinChunkRenderContainer.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of Baritone.
+ *
+ * Baritone is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Baritone is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Baritone. If not, see .
+ */
+
+package baritone.launch.mixins;
+
+import baritone.Baritone;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.ChunkRenderContainer;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.chunk.RenderChunk;
+import org.lwjgl.opengl.GL14;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import static org.lwjgl.opengl.GL11.*;
+
+@Mixin(ChunkRenderContainer.class)
+public class MixinChunkRenderContainer {
+
+ @Inject(
+ method = "preRenderChunk",
+ at = @At("HEAD")
+ )
+ private void preRenderChunk(RenderChunk renderChunkIn, CallbackInfo ci) {
+ if (Baritone.settings().renderCachedChunks.get() && Minecraft.getMinecraft().world.getChunk(renderChunkIn.getPosition()).isEmpty()) {
+ GlStateManager.enableAlpha();
+ GlStateManager.enableBlend();
+ GL14.glBlendColor(0, 0, 0, Baritone.settings().cachedChunksOpacity.get());
+ GlStateManager.tryBlendFuncSeparate(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_ONE, GL_ZERO);
+ }
+ }
+}
diff --git a/src/launch/java/baritone/launch/mixins/MixinChunkRenderWorker.java b/src/launch/java/baritone/launch/mixins/MixinChunkRenderWorker.java
new file mode 100644
index 000000000..a8247a9b9
--- /dev/null
+++ b/src/launch/java/baritone/launch/mixins/MixinChunkRenderWorker.java
@@ -0,0 +1,56 @@
+/*
+ * This file is part of Baritone.
+ *
+ * Baritone is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Baritone is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Baritone. If not, see .
+ */
+
+package baritone.launch.mixins;
+
+import baritone.Baritone;
+import baritone.api.BaritoneAPI;
+import baritone.api.utils.IPlayerContext;
+import net.minecraft.client.renderer.chunk.ChunkRenderWorker;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.World;
+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.Redirect;
+
+@Mixin(ChunkRenderWorker.class)
+public abstract class MixinChunkRenderWorker {
+
+ @Shadow
+ protected abstract boolean isChunkExisting(BlockPos pos, World worldIn);
+
+ @Redirect(
+ method = "processTask",
+ at = @At(
+ value = "INVOKE",
+ target = "net/minecraft/client/renderer/chunk/ChunkRenderWorker.isChunkExisting(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/World;)Z"
+ )
+ )
+ private boolean isChunkExisting(ChunkRenderWorker worker, BlockPos pos, World world) {
+ if (Baritone.settings().renderCachedChunks.get()) {
+ Baritone baritone = (Baritone) BaritoneAPI.getProvider().getPrimaryBaritone();
+ IPlayerContext ctx = baritone.getPlayerContext();
+ if (ctx.player() != null && ctx.world() != null && baritone.bsi != null) {
+ return baritone.bsi.isLoaded(pos.getX(), pos.getZ()) || this.isChunkExisting(pos, world);
+ }
+ }
+
+ return this.isChunkExisting(pos, world);
+ }
+}
+
diff --git a/src/launch/java/baritone/launch/mixins/MixinEntity.java b/src/launch/java/baritone/launch/mixins/MixinEntity.java
deleted file mode 100644
index 836557834..000000000
--- a/src/launch/java/baritone/launch/mixins/MixinEntity.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * This file is part of Baritone.
- *
- * Baritone is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Baritone is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Baritone. If not, see .
- */
-
-package baritone.launch.mixins;
-
-import baritone.api.BaritoneAPI;
-import baritone.api.event.events.RotationMoveEvent;
-import net.minecraft.client.entity.EntityPlayerSP;
-import net.minecraft.entity.Entity;
-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.Redirect;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-
-import static org.spongepowered.asm.lib.Opcodes.GETFIELD;
-
-/**
- * @author Brady
- * @since 8/21/2018
- */
-@Mixin(Entity.class)
-public class MixinEntity {
-
- @Shadow
- public float rotationYaw;
-
- /**
- * Event called to override the movement direction when walking
- */
- private RotationMoveEvent motionUpdateRotationEvent;
-
- @Inject(
- method = "moveRelative",
- at = @At("HEAD")
- )
- private void preMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) {
- // noinspection ConstantConditions
- if (EntityPlayerSP.class.isInstance(this)) {
- this.motionUpdateRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw);
- BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerRotationMove(this.motionUpdateRotationEvent);
- }
- }
-
- @Redirect(
- method = "moveRelative",
- at = @At(
- value = "FIELD",
- opcode = GETFIELD,
- target = "net/minecraft/entity/Entity.rotationYaw:F"
- )
- )
- private float overrideYaw(Entity self) {
- if (self instanceof EntityPlayerSP) {
- return this.motionUpdateRotationEvent.getYaw();
- }
- return self.rotationYaw;
- }
-}
diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java
index c6d76634f..460d8a274 100644
--- a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java
+++ b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java
@@ -74,4 +74,25 @@ public abstract class MixinEntityLivingBase extends Entity {
}
return self.rotationYaw;
}
+
+ @Redirect(
+ method = "travel",
+ at = @At(
+ value = "INVOKE",
+ target = "net/minecraft/entity/EntityLivingBase.moveRelative(FFFF)V"
+ )
+ )
+ private void travel(EntityLivingBase self, float strafe, float up, float forward, float friction) {
+ // noinspection ConstantConditions
+ if (!EntityPlayerSP.class.isInstance(this)) {
+ moveRelative(strafe, up, forward, friction);
+ return;
+ }
+ RotationMoveEvent motionUpdateRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw);
+ BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerRotationMove(motionUpdateRotationEvent);
+ float originalYaw = this.rotationYaw;
+ this.rotationYaw = motionUpdateRotationEvent.getYaw();
+ this.moveRelative(strafe, up, forward, friction);
+ this.rotationYaw = originalYaw;
+ }
}
diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java b/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java
index bbf920113..87cc65624 100644
--- a/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java
+++ b/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java
@@ -18,6 +18,7 @@
package baritone.launch.mixins;
import baritone.api.BaritoneAPI;
+import baritone.api.IBaritone;
import baritone.api.behavior.IPathingBehavior;
import baritone.api.event.events.ChatEvent;
import baritone.api.event.events.PlayerUpdateEvent;
@@ -100,8 +101,16 @@ public class MixinEntityPlayerSP {
)
private boolean isKeyDown(KeyBinding keyBinding) {
SprintStateEvent event = new SprintStateEvent();
- BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerSprintState(event);
- return event.getState() == null ? keyBinding.isKeyDown() : event.getState();
+ IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
+ baritone.getGameEventHandler().onPlayerSprintState(event);
+ if (event.getState() != null) {
+ return event.getState();
+ }
+ if (baritone != BaritoneAPI.getProvider().getPrimaryBaritone()) {
+ // hitting control shouldn't make all bots sprint
+ return false;
+ }
+ return keyBinding.isKeyDown();
}
@Inject(
diff --git a/src/launch/java/baritone/launch/mixins/MixinKeyBinding.java b/src/launch/java/baritone/launch/mixins/MixinKeyBinding.java
index 6e215547e..9ef080bf4 100644
--- a/src/launch/java/baritone/launch/mixins/MixinKeyBinding.java
+++ b/src/launch/java/baritone/launch/mixins/MixinKeyBinding.java
@@ -17,6 +17,7 @@
package baritone.launch.mixins;
+import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.utils.Helper;
import net.minecraft.client.settings.KeyBinding;
@@ -45,6 +46,9 @@ public class MixinKeyBinding {
// only the primary baritone forces keys
Boolean force = BaritoneAPI.getProvider().getPrimaryBaritone().getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this);
if (force != null) {
+ if (!force && !Baritone.settings().suppressClicks.get()) {
+ return;
+ }
cir.setReturnValue(force); // :sunglasses:
}
}
@@ -57,9 +61,10 @@ public class MixinKeyBinding {
private void isPressed(CallbackInfoReturnable cir) {
// only the primary baritone forces keys
Boolean force = BaritoneAPI.getProvider().getPrimaryBaritone().getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this);
- if (force != null && !force) { // <-- cursed
+ if (force != null && !force && Baritone.settings().suppressClicks.get()) { // <-- cursed
if (pressTime > 0) {
- Helper.HELPER.logDirect("You're trying to press this mouse button but I won't let you");
+ Helper.HELPER.logDirect("You're trying to press this mouse button but I won't let you.");
+ Helper.HELPER.logDirect("Turn off the suppressClicks setting to allow clicking while pathing.");
pressTime--;
}
cir.setReturnValue(force); // :sunglasses:
diff --git a/src/launch/java/baritone/launch/mixins/MixinRenderChunk.java b/src/launch/java/baritone/launch/mixins/MixinRenderChunk.java
new file mode 100644
index 000000000..4190ae59a
--- /dev/null
+++ b/src/launch/java/baritone/launch/mixins/MixinRenderChunk.java
@@ -0,0 +1,88 @@
+/*
+ * This file is part of Baritone.
+ *
+ * Baritone is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Baritone is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Baritone. If not, see .
+ */
+
+package baritone.launch.mixins;
+
+import baritone.Baritone;
+import baritone.api.BaritoneAPI;
+import baritone.api.utils.IPlayerContext;
+import net.minecraft.block.state.IBlockState;
+import net.minecraft.client.renderer.chunk.RenderChunk;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.ChunkCache;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Redirect;
+
+/**
+ * @author Brady
+ * @since 1/29/2019
+ */
+@Mixin(RenderChunk.class)
+public class MixinRenderChunk {
+
+ @Redirect(
+ method = "rebuildChunk",
+ at = @At(
+ value = "INVOKE",
+ target = "net/minecraft/world/ChunkCache.isEmpty()Z"
+ )
+ )
+ private boolean isEmpty(ChunkCache chunkCache) {
+ if (!chunkCache.isEmpty()) {
+ return false;
+ }
+ if (Baritone.settings().renderCachedChunks.get()) {
+ Baritone baritone = (Baritone) BaritoneAPI.getProvider().getPrimaryBaritone();
+ IPlayerContext ctx = baritone.getPlayerContext();
+ if (ctx.player() != null && ctx.world() != null && baritone.bsi != null) {
+ BlockPos position = ((RenderChunk) (Object) this).getPosition();
+ // RenderChunk extends from -1,-1,-1 to +16,+16,+16
+ // then the constructor of ChunkCache extends it one more (presumably to get things like the connected status of fences? idk)
+ // so if ANY of the adjacent chunks are loaded, we are unempty
+ for (int dx = -1; dx <= 1; dx++) {
+ for (int dz = -1; dz <= 1; dz++) {
+ if (baritone.bsi.isLoaded(16 * dx + position.getX(), 16 * dz + position.getZ())) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ @Redirect(
+ method = "rebuildChunk",
+ at = @At(
+ value = "INVOKE",
+ target = "net/minecraft/world/ChunkCache.getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;"
+ )
+ )
+ private IBlockState getBlockState(ChunkCache chunkCache, BlockPos pos) {
+ if (Baritone.settings().renderCachedChunks.get()) {
+ Baritone baritone = (Baritone) BaritoneAPI.getProvider().getPrimaryBaritone();
+ IPlayerContext ctx = baritone.getPlayerContext();
+ if (ctx.player() != null && ctx.world() != null && baritone.bsi != null) {
+ return baritone.bsi.get0(pos);
+ }
+ }
+
+ return chunkCache.getBlockState(pos);
+ }
+}
diff --git a/src/launch/java/baritone/launch/mixins/MixinRenderList.java b/src/launch/java/baritone/launch/mixins/MixinRenderList.java
new file mode 100644
index 000000000..55d1da70a
--- /dev/null
+++ b/src/launch/java/baritone/launch/mixins/MixinRenderList.java
@@ -0,0 +1,46 @@
+/*
+ * This file is part of Baritone.
+ *
+ * Baritone is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Baritone is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Baritone. If not, see .
+ */
+
+package baritone.launch.mixins;
+
+import baritone.Baritone;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.RenderList;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import static org.lwjgl.opengl.GL11.*;
+
+@Mixin(RenderList.class)
+public class MixinRenderList {
+
+ @Inject(
+ method = "renderChunkLayer",
+ at = @At(
+ value = "INVOKE",
+ target = "net/minecraft/client/renderer/GlStateManager.popMatrix()V"
+ )
+ )
+ private void renderChunkLayer(CallbackInfo info) {
+ if (Baritone.settings().renderCachedChunks.get()) {
+ // reset the blend func to normal (not dependent on constant alpha)
+ GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
+ }
+ }
+}
diff --git a/src/launch/java/baritone/launch/mixins/MixinVboRenderList.java b/src/launch/java/baritone/launch/mixins/MixinVboRenderList.java
new file mode 100644
index 000000000..c2c9fd8c7
--- /dev/null
+++ b/src/launch/java/baritone/launch/mixins/MixinVboRenderList.java
@@ -0,0 +1,46 @@
+/*
+ * This file is part of Baritone.
+ *
+ * Baritone is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Baritone is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Baritone. If not, see .
+ */
+
+package baritone.launch.mixins;
+
+import baritone.Baritone;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.VboRenderList;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import static org.lwjgl.opengl.GL11.*;
+
+@Mixin(VboRenderList.class)
+public class MixinVboRenderList {
+
+ @Inject(
+ method = "renderChunkLayer",
+ at = @At(
+ value = "INVOKE",
+ target = "net/minecraft/client/renderer/GlStateManager.popMatrix()V"
+ )
+ )
+ private void renderChunkLayer(CallbackInfo info) {
+ if (Baritone.settings().renderCachedChunks.get()) {
+ // reset the blend func to normal (not dependent on constant alpha)
+ GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
+ }
+ }
+}
diff --git a/src/launch/resources/mixins.baritone.json b/src/launch/resources/mixins.baritone.json
index 09ebbafd4..fea9cca7d 100644
--- a/src/launch/resources/mixins.baritone.json
+++ b/src/launch/resources/mixins.baritone.json
@@ -12,7 +12,8 @@
"MixinBlockPos",
"MixinChunkProviderClient",
"MixinChunkProviderServer",
- "MixinEntity",
+ "MixinChunkRenderContainer",
+ "MixinChunkRenderWorker",
"MixinEntityLivingBase",
"MixinEntityPlayerSP",
"MixinEntityRenderer",
@@ -20,6 +21,9 @@
"MixinMinecraft",
"MixinNetHandlerPlayClient",
"MixinNetworkManager",
+ "MixinRenderChunk",
+ "MixinRenderList",
+ "MixinVboRenderList",
"MixinWorldClient"
]
}
\ No newline at end of file
diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java
index 18f61f7a3..b3b7b9ae5 100755
--- a/src/main/java/baritone/Baritone.java
+++ b/src/main/java/baritone/Baritone.java
@@ -26,10 +26,7 @@ import baritone.behavior.*;
import baritone.cache.WorldProvider;
import baritone.event.GameEventHandler;
import baritone.process.*;
-import baritone.utils.BaritoneAutoTest;
-import baritone.utils.ExampleBaritoneControl;
-import baritone.utils.InputOverrideHandler;
-import baritone.utils.PathingControlManager;
+import baritone.utils.*;
import baritone.utils.player.PrimaryPlayerContext;
import net.minecraft.client.Minecraft;
@@ -88,6 +85,8 @@ public class Baritone implements IBaritone {
private IPlayerContext playerContext;
private WorldProvider worldProvider;
+ public BlockStateInterface bsi;
+
Baritone() {
this.gameEventHandler = new GameEventHandler(this);
}
diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java
index b813d3dd6..a85840dc3 100644
--- a/src/main/java/baritone/behavior/PathingBehavior.java
+++ b/src/main/java/baritone/behavior/PathingBehavior.java
@@ -155,7 +155,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
synchronized (pathCalcLock) {
if (inProgress != null) {
// we are calculating
- // are we calculating the right thing though?
+ // are we calculating the right thing though? 🤔
BetterBlockPos calcFrom = inProgress.getStart();
// if current just succeeded, we should be standing in calcFrom, so that's cool and good
// but if current just failed, we should discard this calculation since it doesn't start from where we're standing
@@ -201,8 +201,10 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
// and this path doesn't get us all the way there
return;
}
- if (ticksRemainingInSegment().get() < Baritone.settings().planningTickLookAhead.get()) {
+ if (ticksRemainingInSegment(false).get() < Baritone.settings().planningTickLookAhead.get()) {
// and this path has 7.5 seconds or less left
+ // don't include the current movement so a very long last movement (e.g. descend) doesn't trip it up
+ // if we actually included current, it wouldn't start planning ahead until the last movement was done, if the last movement took more than 7.5 seconds on its own
logDebug("Path almost over. Planning ahead...");
queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED);
findPathInNewThread(current.getPath().getDest(), false, context);
diff --git a/src/main/java/baritone/cache/ChunkPacker.java b/src/main/java/baritone/cache/ChunkPacker.java
index 60ac63315..e2903ceaf 100644
--- a/src/main/java/baritone/cache/ChunkPacker.java
+++ b/src/main/java/baritone/cache/ChunkPacker.java
@@ -124,12 +124,13 @@ public final class ChunkPacker {
private static PathingBlockType getPathingBlockType(IBlockState state) {
Block block = state.getBlock();
- if (block == Blocks.WATER && !MovementHelper.isFlowing(state)) {
+ if ((block == Blocks.WATER || block == Blocks.FLOWING_WATER) && !MovementHelper.isFlowing(state)) {
// only water source blocks are plausibly usable, flowing water should be avoid
+ // FLOWING_WATER is a waterfall, it doesn't really matter and caching it as AVOID just makes it look wrong
return PathingBlockType.WATER;
}
- if (MovementHelper.avoidWalkingInto(block) || block == Blocks.FLOWING_WATER || MovementHelper.isBottomSlab(state)) {
+ if (MovementHelper.avoidWalkingInto(block) || MovementHelper.isBottomSlab(state)) {
return PathingBlockType.AVOID;
}
// We used to do an AABB check here
diff --git a/src/main/java/baritone/event/GameEventHandler.java b/src/main/java/baritone/event/GameEventHandler.java
index 3b3270029..84bac80fb 100644
--- a/src/main/java/baritone/event/GameEventHandler.java
+++ b/src/main/java/baritone/event/GameEventHandler.java
@@ -23,6 +23,7 @@ import baritone.api.event.events.type.EventState;
import baritone.api.event.listener.IEventBus;
import baritone.api.event.listener.IGameEventListener;
import baritone.cache.WorldProvider;
+import baritone.utils.BlockStateInterface;
import baritone.utils.Helper;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
@@ -46,6 +47,13 @@ public final class GameEventHandler implements IEventBus, Helper {
@Override
public final void onTick(TickEvent event) {
+ if (event.getType() == TickEvent.Type.IN) {
+ try {
+ baritone.bsi = new BlockStateInterface(baritone.getPlayerContext(), true);
+ } catch (Exception ex) {}
+ } else {
+ baritone.bsi = null;
+ }
listeners.forEach(l -> l.onTick(event));
}
diff --git a/src/main/java/baritone/pathing/calc/AStarPathFinder.java b/src/main/java/baritone/pathing/calc/AStarPathFinder.java
index b32fc99ff..fda41cfdc 100644
--- a/src/main/java/baritone/pathing/calc/AStarPathFinder.java
+++ b/src/main/java/baritone/pathing/calc/AStarPathFinder.java
@@ -25,7 +25,6 @@ import baritone.api.utils.BetterBlockPos;
import baritone.pathing.calc.openset.BinaryHeapOpenSet;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Moves;
-import baritone.utils.Helper;
import baritone.utils.pathing.BetterWorldBorder;
import baritone.utils.pathing.Favoring;
import baritone.utils.pathing.MutableMoveResult;
@@ -37,7 +36,7 @@ import java.util.Optional;
*
* @author leijurv
*/
-public final class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
+public final class AStarPathFinder extends AbstractNodeCostSearch {
private final Favoring favoring;
private final CalculationContext calcContext;
@@ -55,14 +54,12 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
startNode.combinedCost = startNode.estimatedCostToGoal;
BinaryHeapOpenSet openSet = new BinaryHeapOpenSet();
openSet.insert(startNode);
- bestSoFar = new PathNode[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i])
- double[] bestHeuristicSoFar = new double[COEFFICIENTS.length];
+ double[] bestHeuristicSoFar = new double[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i])
for (int i = 0; i < bestHeuristicSoFar.length; i++) {
bestHeuristicSoFar[i] = startNode.estimatedCostToGoal;
bestSoFar[i] = startNode;
}
MutableMoveResult res = new MutableMoveResult();
- Favoring favored = favoring;
BetterWorldBorder worldBorder = new BetterWorldBorder(calcContext.world.getWorldBorder());
long startTime = System.currentTimeMillis();
boolean slowPath = Baritone.settings().slowPath.get();
@@ -75,10 +72,10 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
int numNodes = 0;
int numMovementsConsidered = 0;
int numEmptyChunk = 0;
- boolean favoring = !favored.isEmpty();
+ boolean isFavoring = !favoring.isEmpty();
int timeCheckInterval = 1 << 6;
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
- boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get();
+ double minimumImprovement = Baritone.settings().minimumImprovementRepropagation.get() ? MIN_IMPROVEMENT : 0;
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && !cancelRequested) {
if ((numNodes & (timeCheckInterval - 1)) == 0) { // only call this once every 64 nodes (about half a millisecond)
long now = System.currentTimeMillis(); // since nanoTime is slow on windows (takes many microseconds)
@@ -136,21 +133,13 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
throw new IllegalStateException(moves + " " + res.y + " " + (currentNode.y + moves.yOffset));
}
long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z);
- if (favoring) {
+ if (isFavoring) {
// see issue #18
- actionCost *= favored.calculate(hashCode);
+ actionCost *= favoring.calculate(hashCode);
}
PathNode neighbor = getNodeAtPosition(res.x, res.y, res.z, hashCode);
double tentativeCost = currentNode.cost + actionCost;
- if (tentativeCost < neighbor.cost) {
- double improvementBy = neighbor.cost - tentativeCost;
- // there are floating point errors caused by random combinations of traverse and diagonal over a flat area
- // that means that sometimes there's a cost improvement of like 10 ^ -16
- // it's not worth the time to update the costs, decrease-key the heap, potentially repropagate, etc
- if (improvementBy < 0.01 && minimumImprovementRepropagation) {
- // who cares about a hundredth of a tick? that's half a millisecond for crying out loud!
- continue;
- }
+ if (neighbor.cost - tentativeCost > minimumImprovement) {
neighbor.previous = currentNode;
neighbor.cost = tentativeCost;
neighbor.combinedCost = tentativeCost + neighbor.estimatedCostToGoal;
@@ -159,15 +148,12 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
} else {
openSet.insert(neighbor);//dont double count, dont insert into open set if it's already there
}
- for (int i = 0; i < bestSoFar.length; i++) {
+ for (int i = 0; i < COEFFICIENTS.length; i++) {
double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i];
- if (heuristic < bestHeuristicSoFar[i]) {
- if (bestHeuristicSoFar[i] - heuristic < 0.01 && minimumImprovementRepropagation) {
- continue;
- }
+ if (bestHeuristicSoFar[i] - heuristic > minimumImprovement) {
bestHeuristicSoFar[i] = heuristic;
bestSoFar[i] = neighbor;
- if (getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) {
+ if (failing && getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) {
failing = false;
}
}
@@ -182,28 +168,10 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
System.out.println("Open set size: " + openSet.size());
System.out.println("PathNode map size: " + mapSize());
System.out.println((int) (numNodes * 1.0 / ((System.currentTimeMillis() - startTime) / 1000F)) + " nodes per second");
- double bestDist = 0;
- for (int i = 0; i < bestSoFar.length; i++) {
- if (bestSoFar[i] == null) {
- continue;
- }
- double dist = getDistFromStartSq(bestSoFar[i]);
- if (dist > bestDist) {
- bestDist = dist;
- }
- if (dist > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
- logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, A* cost coefficient " + COEFFICIENTS[i] + ", " + numMovementsConsidered + " movements considered");
- if (COEFFICIENTS[i] >= 3) {
- System.out.println("Warning: cost coefficient is greater than three! Probably means that");
- System.out.println("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)");
- System.out.println("But I'm going to do it anyway, because yolo");
- }
- System.out.println("Path goes for " + Math.sqrt(dist) + " blocks");
- return Optional.of(new Path(startNode, bestSoFar[i], numNodes, goal, calcContext));
- }
+ Optional result = bestSoFar(true, numNodes);
+ if (result.isPresent()) {
+ logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, " + numMovementsConsidered + " movements considered");
}
- logDebug("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + Math.sqrt(bestDist) + " blocks");
- logDebug("No path found =(");
- return Optional.empty();
+ return result;
}
}
diff --git a/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java b/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java
index 625e8e592..a9974e8df 100644
--- a/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java
+++ b/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java
@@ -34,7 +34,7 @@ import java.util.Optional;
*
* @author leijurv
*/
-public abstract class AbstractNodeCostSearch implements IPathFinder {
+public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
protected final int startX;
protected final int startY;
@@ -53,7 +53,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
protected PathNode mostRecentConsidered;
- protected PathNode[] bestSoFar;
+ protected final PathNode[] bestSoFar = new PathNode[COEFFICIENTS.length];
private volatile boolean isFinished;
@@ -63,13 +63,23 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
* This is really complicated and hard to explain. I wrote a comment in the old version of MineBot but it was so
* long it was easier as a Google Doc (because I could insert charts).
*
- * @see
+ * @see here
*/
- protected static final double[] COEFFICIENTS = {1.5, 2, 2.5, 3, 4, 5, 10}; // big TODO tune
+ protected static final double[] COEFFICIENTS = {1.5, 2, 2.5, 3, 4, 5, 10};
+
/**
* If a path goes less than 5 blocks and doesn't make it to its goal, it's not worth considering.
*/
- protected final static double MIN_DIST_PATH = 5;
+ protected static final double MIN_DIST_PATH = 5;
+
+ /**
+ * there are floating point errors caused by random combinations of traverse and diagonal over a flat area
+ * that means that sometimes there's a cost improvement of like 10 ^ -16
+ * it's not worth the time to update the costs, decrease-key the heap, potentially repropagate, etc
+ *
+ * who cares about a hundredth of a tick? that's half a millisecond for crying out loud!
+ */
+ protected static final double MIN_IMPROVEMENT = 0.01;
AbstractNodeCostSearch(int startX, int startY, int startZ, Goal goal, CalculationContext context) {
this.startX = startX;
@@ -170,25 +180,43 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(startNode, node, 0, goal, context));
}
- protected int mapSize() {
- return map.size();
+ @Override
+ public Optional bestPathSoFar() {
+ return bestSoFar(false, 0);
}
- @Override
- public Optional bestPathSoFar() { // TODO cleanup code duplication between here and AStarPathFinder
+ protected Optional bestSoFar(boolean logInfo, int numNodes) {
if (startNode == null || bestSoFar == null) {
return Optional.empty();
}
- for (int i = 0; i < bestSoFar.length; i++) {
+ double bestDist = 0;
+ for (int i = 0; i < COEFFICIENTS.length; i++) {
if (bestSoFar[i] == null) {
continue;
}
- if (getDistFromStartSq(bestSoFar[i]) > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
- return Optional.of(new Path(startNode, bestSoFar[i], 0, goal, context));
+ double dist = getDistFromStartSq(bestSoFar[i]);
+ if (dist > bestDist) {
+ bestDist = dist;
+ }
+ if (dist > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
+ if (logInfo) {
+ if (COEFFICIENTS[i] >= 3) {
+ System.out.println("Warning: cost coefficient is greater than three! Probably means that");
+ System.out.println("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)");
+ System.out.println("But I'm going to do it anyway, because yolo");
+ }
+ System.out.println("Path goes for " + Math.sqrt(dist) + " blocks");
+ logDebug("A* cost coefficient " + COEFFICIENTS[i]);
+ }
+ return Optional.of(new Path(startNode, bestSoFar[i], numNodes, goal, context));
}
}
// instead of returning bestSoFar[0], be less misleading
// if it actually won't find any path, don't make them think it will by rendering a dark blue that will never actually happen
+ if (logInfo) {
+ logDebug("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + Math.sqrt(bestDist) + " blocks");
+ logDebug("No path found =(");
+ }
return Optional.empty();
}
@@ -205,4 +233,8 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
public BetterBlockPos getStart() {
return new BetterBlockPos(startX, startY, startZ);
}
+
+ protected int mapSize() {
+ return map.size();
+ }
}
diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java
index a47fc2634..0abaccf7b 100644
--- a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java
+++ b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java
@@ -114,7 +114,7 @@ public class MovementDiagonal extends Movement {
return;
}
IBlockState pb3 = context.get(destX, y + 1, z);
- if (optionA == 0 && ((MovementHelper.avoidWalkingInto(pb2.getBlock()) && pb2.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb3.getBlock()) && pb3.getBlock() != Blocks.WATER))) {
+ if (optionA == 0 && ((MovementHelper.avoidWalkingInto(pb2.getBlock()) && pb2.getBlock() != Blocks.WATER) || MovementHelper.avoidWalkingInto(pb3.getBlock()))) {
// at this point we're done calculating optionA, so we can check if it's actually possible to edge around in that direction
return;
}
@@ -123,7 +123,7 @@ public class MovementDiagonal extends Movement {
// and finally, if the cost is nonzero for both ways to approach this diagonal, it's not possible
return;
}
- if (optionB == 0 && ((MovementHelper.avoidWalkingInto(pb0.getBlock()) && pb0.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb1.getBlock()) && pb1.getBlock() != Blocks.WATER))) {
+ if (optionB == 0 && ((MovementHelper.avoidWalkingInto(pb0.getBlock()) && pb0.getBlock() != Blocks.WATER) || MovementHelper.avoidWalkingInto(pb1.getBlock()))) {
// and now that option B is fully calculated, see if we can edge around that way
return;
}
diff --git a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java
index 98898690b..bade6fe1a 100644
--- a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java
+++ b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java
@@ -189,6 +189,11 @@ public class MovementParkour extends Movement {
logDebug("Pausing parkour since hand is active");
return state;
}
+ if (ctx.playerFeet().y < src.y) {
+ // we have fallen
+ logDebug("sorry");
+ return state.setStatus(MovementStatus.UNREACHABLE);
+ }
if (dist >= 4) {
state.setInput(Input.SPRINT, true);
}
diff --git a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java
index df58a904b..c3f9892a5 100644
--- a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java
+++ b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java
@@ -282,6 +282,8 @@ public class MovementTraverse extends Movement {
}
return state;
}
+ default:
+ break;
}
if (whereAmI.equals(dest)) {
// If we are in the block that we are trying to get to, we are sneaking over air and we need to place a block beneath us against the one we just walked off of
diff --git a/src/main/java/baritone/pathing/path/PathExecutor.java b/src/main/java/baritone/pathing/path/PathExecutor.java
index a2c0e2ff2..1b59f8e32 100644
--- a/src/main/java/baritone/pathing/path/PathExecutor.java
+++ b/src/main/java/baritone/pathing/path/PathExecutor.java
@@ -249,6 +249,8 @@ public class PathExecutor implements IPathExecutor, Helper {
return true;
}
if (!movement.calculatedWhileLoaded() && currentCost - currentMovementOriginalCostEstimate > Baritone.settings().maxCostIncrease.get() && canCancel) {
+ // don't do this if the movement was calculated while loaded
+ // that means that this isn't a cache error, it's just part of the path interfering with a later part
logDebug("Original cost " + currentMovementOriginalCostEstimate + " current cost " + currentCost + ". Cancelling.");
cancel();
return true;
@@ -377,21 +379,21 @@ public class PathExecutor implements IPathExecutor, Helper {
}
private boolean shouldSprintNextTick() {
+ boolean requested = behavior.baritone.getInputOverrideHandler().isInputForcedDown(Input.SPRINT);
+
+ // we'll take it from here, no need for minecraft to see we're holding down control and sprint for us
+ behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
+
// first and foremost, if allowSprint is off, or if we don't have enough hunger, don't try and sprint
if (!new CalculationContext(behavior.baritone).canSprint) {
- behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
return false;
}
// if the movement requested sprinting, then we're done
- if (behavior.baritone.getInputOverrideHandler().isInputForcedDown(Input.SPRINT)) {
- behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
+ if (requested) {
return true;
}
- // we'll take it from here, no need for minecraft to see we're holding down control and sprint for us
- behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
-
// however, descend doesn't request sprinting, beceause it doesn't know the context of what movement comes after it
IMovement current = path.movements().get(pathPosition);
if (current instanceof MovementDescend) {
diff --git a/src/main/java/baritone/process/GetToBlockProcess.java b/src/main/java/baritone/process/GetToBlockProcess.java
index f3e245da3..c3ac0616d 100644
--- a/src/main/java/baritone/process/GetToBlockProcess.java
+++ b/src/main/java/baritone/process/GetToBlockProcess.java
@@ -18,10 +18,7 @@
package baritone.process;
import baritone.Baritone;
-import baritone.api.pathing.goals.Goal;
-import baritone.api.pathing.goals.GoalComposite;
-import baritone.api.pathing.goals.GoalGetToBlock;
-import baritone.api.pathing.goals.GoalTwoBlocks;
+import baritone.api.pathing.goals.*;
import baritone.api.process.IGetToBlockProcess;
import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType;
@@ -44,6 +41,7 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
private Block gettingTo;
private List knownLocations;
+ private BlockPos start;
private int tickCount = 0;
@@ -55,6 +53,7 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
public void getToBlock(Block block) {
onLostControl();
gettingTo = block;
+ start = ctx.playerFeet();
rescan(new ArrayList<>(), new CalculationContext(baritone));
}
@@ -69,6 +68,14 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
rescan(new ArrayList<>(), new CalculationContext(baritone));
}
if (knownLocations.isEmpty()) {
+ if (Baritone.settings().exploreForBlocks.get()) {
+ return new PathingCommand(new GoalRunAway(1, start) {
+ @Override
+ public boolean isInGoal(int x, int y, int z) {
+ return false;
+ }
+ }, PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH);
+ }
logDirect("No known locations of " + gettingTo + ", canceling GetToBlock");
if (isSafeToCancel) {
onLostControl();
@@ -106,6 +113,7 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
public void onLostControl() {
gettingTo = null;
knownLocations = null;
+ start = null;
baritone.getInputOverrideHandler().clearAllKeys();
}
diff --git a/src/main/java/baritone/utils/ExampleBaritoneControl.java b/src/main/java/baritone/utils/ExampleBaritoneControl.java
index 3589800c2..427bc83a4 100644
--- a/src/main/java/baritone/utils/ExampleBaritoneControl.java
+++ b/src/main/java/baritone/utils/ExampleBaritoneControl.java
@@ -24,6 +24,7 @@ import baritone.api.cache.IWaypoint;
import baritone.api.event.events.ChatEvent;
import baritone.api.pathing.goals.*;
import baritone.api.pathing.movement.ActionCosts;
+import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.SettingsUtil;
import baritone.behavior.Behavior;
import baritone.behavior.PathingBehavior;
@@ -36,6 +37,7 @@ import baritone.process.CustomGoalProcess;
import baritone.utils.pathing.SegmentedCalculator;
import baritone.utils.schematic.AirSchematic;
import net.minecraft.block.Block;
+import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ChunkProviderClient;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
@@ -86,21 +88,19 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
@Override
public void onSendChatMessage(ChatEvent event) {
+ String msg = event.getMessage();
+ if (Baritone.settings().prefixControl.get() && msg.startsWith(COMMAND_PREFIX)) {
+ if (!runCommand(msg.substring(COMMAND_PREFIX.length()))) {
+ logDirect("Invalid command");
+ }
+ event.cancel(); // always cancel if using prefixControl
+ return;
+ }
if (!Baritone.settings().chatControl.get() && !Baritone.settings().removePrefix.get()) {
return;
}
- String msg = event.getMessage();
- if (Baritone.settings().prefix.get()) {
- if (msg.startsWith(COMMAND_PREFIX)) {
- if (!runCommand(msg.substring(COMMAND_PREFIX.length()))) {
- logDirect("Invalid command");
- }
- event.cancel(); // always cancel if using prefix
- }
- } else {
- if (runCommand(msg)) {
- event.cancel();
- }
+ if (runCommand(msg)) {
+ event.cancel();
}
}
@@ -228,6 +228,15 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
}
return true;
}
+ if (msg.equals("version")) {
+ String version = ExampleBaritoneControl.class.getPackage().getImplementationVersion();
+ if (version == null) {
+ logDirect("No version detected. Either dev environment or broken install.");
+ } else {
+ logDirect("You are using Baritone v" + version);
+ }
+ return true;
+ }
if (msg.equals("repack") || msg.equals("rescan")) {
ChunkProviderClient cli = (ChunkProviderClient) ctx.world().getChunkProvider();
int playerChunkX = ctx.playerFeet().getX() >> 4;
@@ -325,6 +334,12 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
logDirect("Baritone settings reset");
return true;
}
+ if (msg.equals("render")) {
+ BetterBlockPos pf = ctx.playerFeet();
+ Minecraft.getMinecraft().renderGlobal.markBlockRangeForRenderUpdate(pf.x - 500, pf.y - 500, pf.z - 500, pf.x + 500, pf.y + 500, pf.z + 500);
+ logDirect("okay");
+ return true;
+ }
if (msg.equals("echest")) {
Optional> contents = baritone.getMemoryBehavior().echest();
if (contents.isPresent()) {