From af1eb58bb87cbb7ce38e01a6fcf96def3222850c Mon Sep 17 00:00:00 2001 From: scorbett123 <50634068+scorbett123@users.noreply.github.com> Date: Tue, 31 May 2022 14:43:58 +0100 Subject: [PATCH 01/23] Implement Leijurv's precomputed data idea --- src/api/java/baritone/api/Settings.java | 6 + .../api/event/events/SettingChangedEvent.java | 33 +++ .../listener/AbstractGameEventListener.java | 3 + .../event/listener/IGameEventListener.java | 7 + .../java/baritone/api/utils/SettingsUtil.java | 4 +- .../baritone/behavior/PathingBehavior.java | 17 +- .../baritone/command/defaults/SetCommand.java | 3 +- .../java/baritone/event/GameEventHandler.java | 5 + .../pathing/movement/CalculationContext.java | 8 +- .../pathing/movement/MovementHelper.java | 3 + .../movement/movements/MovementAscend.java | 4 +- .../movement/movements/MovementDescend.java | 12 +- .../movement/movements/MovementDiagonal.java | 30 +-- .../movement/movements/MovementDownward.java | 2 +- .../movement/movements/MovementParkour.java | 6 +- .../movement/movements/MovementPillar.java | 2 +- .../movement/movements/MovementTraverse.java | 2 +- .../baritone/pathing/path/PathExecutor.java | 2 +- .../pathing/precompute/PrecomputedData.java | 237 ++++++++++++++++++ .../PrecomputedDataForBlockState.java | 71 ++++++ .../java/baritone/process/BuilderProcess.java | 3 +- .../baritone/process/GetToBlockProcess.java | 2 +- .../java/baritone/process/MineProcess.java | 2 +- 23 files changed, 422 insertions(+), 42 deletions(-) create mode 100644 src/api/java/baritone/api/event/events/SettingChangedEvent.java create mode 100644 src/main/java/baritone/pathing/precompute/PrecomputedData.java create mode 100644 src/main/java/baritone/pathing/precompute/PrecomputedDataForBlockState.java diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 89718289..1ce87c68 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -17,6 +17,7 @@ package baritone.api; +import baritone.api.event.events.SettingChangedEvent; import baritone.api.utils.NotificationHelper; import baritone.api.utils.SettingsUtil; import baritone.api.utils.TypeUtils; @@ -1302,6 +1303,11 @@ public final class Settings { return value; } + public void set(T value) { + this.value = value; + BaritoneAPI.getProvider().getAllBaritones().forEach(iBaritone -> iBaritone.getGameEventHandler().onSettingChanged(new SettingChangedEvent(this))); + } + public final String getName() { return name; } diff --git a/src/api/java/baritone/api/event/events/SettingChangedEvent.java b/src/api/java/baritone/api/event/events/SettingChangedEvent.java new file mode 100644 index 00000000..d92384e0 --- /dev/null +++ b/src/api/java/baritone/api/event/events/SettingChangedEvent.java @@ -0,0 +1,33 @@ +/* + * 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.api.event.events; + +import baritone.api.Settings; + +public class SettingChangedEvent { + + private final Settings.Setting setting; + + public SettingChangedEvent(Settings.Setting setting) { + this.setting = setting; + } + + public Settings.Setting getSetting() { + return setting; + } +} diff --git a/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java b/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java index 9eac8de4..9f1d2418 100644 --- a/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java +++ b/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java @@ -71,4 +71,7 @@ public interface AbstractGameEventListener extends IGameEventListener { @Override default void onPathEvent(PathEvent event) {} + + @Override + default void onSettingChanged(SettingChangedEvent event) {} } diff --git a/src/api/java/baritone/api/event/listener/IGameEventListener.java b/src/api/java/baritone/api/event/listener/IGameEventListener.java index b074e978..28afdfff 100644 --- a/src/api/java/baritone/api/event/listener/IGameEventListener.java +++ b/src/api/java/baritone/api/event/listener/IGameEventListener.java @@ -144,4 +144,11 @@ public interface IGameEventListener { * @param event The event */ void onPathEvent(PathEvent event); + + /** + * When the player changes a setting + * + * @param event The event + */ + void onSettingChanged(SettingChangedEvent event); } diff --git a/src/api/java/baritone/api/utils/SettingsUtil.java b/src/api/java/baritone/api/utils/SettingsUtil.java index 0e95965f..b098c1e0 100644 --- a/src/api/java/baritone/api/utils/SettingsUtil.java +++ b/src/api/java/baritone/api/utils/SettingsUtil.java @@ -176,7 +176,7 @@ public class SettingsUtil { /** * This should always be the same as whether the setting can be parsed from or serialized to a string * - * @param the setting + * @param setting The Setting * @return true if the setting can not be set or read by the user */ public static boolean javaOnlySetting(Settings.Setting setting) { @@ -199,7 +199,7 @@ public class SettingsUtil { if (!intendedType.isInstance(parsed)) { throw new IllegalStateException(ioMethod + " parser returned incorrect type, expected " + intendedType + " got " + parsed + " which is " + parsed.getClass()); } - setting.value = parsed; + setting.set(parsed); } private interface ISettingParser { diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index f9c56c5a..50e2a0c2 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -33,6 +33,7 @@ import baritone.pathing.calc.AbstractNodeCostSearch; import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.MovementHelper; import baritone.pathing.path.PathExecutor; +import baritone.pathing.precompute.PrecomputedData; import baritone.utils.PathRenderer; import baritone.utils.PathingCommandContext; import baritone.utils.pathing.Favoring; @@ -74,8 +75,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, private final LinkedBlockingQueue toDispatch = new LinkedBlockingQueue<>(); + public PrecomputedData precomputedData; + public PathingBehavior(Baritone baritone) { super(baritone); + precomputedData = new PrecomputedData(); } private void queuePathEvent(PathEvent event) { @@ -259,7 +263,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, if (command instanceof PathingCommandContext) { context = ((PathingCommandContext) command).desiredCalcContext; } else { - context = new CalculationContext(baritone, true); + context = new CalculationContext(baritone, true, precomputedData); } if (goal == null) { return false; @@ -418,7 +422,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, */ public BetterBlockPos pathStart() { // TODO move to a helper or util class BetterBlockPos feet = ctx.playerFeet(); - if (!MovementHelper.canWalkOn(ctx, feet.down())) { + if (!precomputedData.canWalkOn(ctx, feet.down())) { if (ctx.player().onGround) { double playerX = ctx.player().posX; double playerZ = ctx.player().posZ; @@ -437,7 +441,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, // can't possibly be sneaking off of this one, we're too far away continue; } - if (MovementHelper.canWalkOn(ctx, possibleSupport.down()) && MovementHelper.canWalkThrough(ctx, possibleSupport) && MovementHelper.canWalkThrough(ctx, possibleSupport.up())) { + if (precomputedData.canWalkOn(ctx, possibleSupport.down()) && precomputedData.canWalkThrough(ctx, possibleSupport) && context.precomputedData.canWalkThrough(ctx, possibleSupport.up())) { // this is plausible //logDebug("Faking path start assuming player is standing off the edge of a block"); return possibleSupport; @@ -447,7 +451,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, } else { // !onGround // we're in the middle of a jump - if (MovementHelper.canWalkOn(ctx, feet.down().down())) { + if (precomputedData.canWalkOn(ctx, feet.down().down())) { //logDebug("Faking path start assuming player is midair and falling"); return feet.down(); } @@ -456,6 +460,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, return feet; } + @Override + public void onSettingChanged(SettingChangedEvent event) { + this.precomputedData.refresh(); + } + /** * In a new thread, pathfind to target blockpos * diff --git a/src/main/java/baritone/command/defaults/SetCommand.java b/src/main/java/baritone/command/defaults/SetCommand.java index e9e35d41..1b395f5a 100644 --- a/src/main/java/baritone/command/defaults/SetCommand.java +++ b/src/main/java/baritone/command/defaults/SetCommand.java @@ -147,7 +147,8 @@ public class SetCommand extends Command { throw new CommandInvalidTypeException(args.consumed(), "a toggleable setting", "some other setting"); } //noinspection unchecked - ((Settings.Setting) setting).value ^= true; + Settings.Setting asBoolSetting = (Settings.Setting) setting; + asBoolSetting.set(!asBoolSetting.value); logDirect(String.format( "Toggled setting %s to %s", setting.getName(), diff --git a/src/main/java/baritone/event/GameEventHandler.java b/src/main/java/baritone/event/GameEventHandler.java index 8916f7f3..1bdba6b9 100644 --- a/src/main/java/baritone/event/GameEventHandler.java +++ b/src/main/java/baritone/event/GameEventHandler.java @@ -156,6 +156,11 @@ public final class GameEventHandler implements IEventBus, Helper { listeners.forEach(l -> l.onPathEvent(event)); } + @Override + public void onSettingChanged(SettingChangedEvent event) { + listeners.forEach(l -> l.onSettingChanged(event)); + } + @Override public final void registerEventListener(IGameEventListener listener) { this.listeners.add(listener); diff --git a/src/main/java/baritone/pathing/movement/CalculationContext.java b/src/main/java/baritone/pathing/movement/CalculationContext.java index d5d6c93c..b4782fb5 100644 --- a/src/main/java/baritone/pathing/movement/CalculationContext.java +++ b/src/main/java/baritone/pathing/movement/CalculationContext.java @@ -21,6 +21,7 @@ import baritone.Baritone; import baritone.api.IBaritone; import baritone.api.pathing.movement.ActionCosts; import baritone.cache.WorldData; +import baritone.pathing.precompute.PrecomputedData; import baritone.utils.BlockStateInterface; import baritone.utils.ToolSet; import baritone.utils.pathing.BetterWorldBorder; @@ -76,11 +77,14 @@ public class CalculationContext { public final double walkOnWaterOnePenalty; public final BetterWorldBorder worldBorder; + public final PrecomputedData precomputedData; + public CalculationContext(IBaritone baritone) { - this(baritone, false); + this(baritone, false, new PrecomputedData()); } - public CalculationContext(IBaritone baritone, boolean forUseOnAnotherThread) { + public CalculationContext(IBaritone baritone, boolean forUseOnAnotherThread, PrecomputedData precomputedData) { + this.precomputedData = precomputedData; this.safeForThreadedUse = forUseOnAnotherThread; this.baritone = baritone; EntityPlayerSP player = baritone.getPlayerContext().player(); diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index dd0ddff4..197f1057 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -88,6 +88,7 @@ public interface MovementHelper extends ActionCosts, Helper { return canWalkThrough(bsi, x, y, z, bsi.get0(x, y, z)); } + // if changing something in this function remember to also change it in precomputed data static boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { Block block = state.getBlock(); if (block == Blocks.AIR) { // early return for most common case @@ -285,6 +286,8 @@ public interface MovementHelper extends ActionCosts, Helper { * through? Includes water because we know that we automatically jump on * water * + * If changing something in this function remember to also change it in precomputed data + * * @param bsi Block state provider * @param x The block's x position * @param y The block's y position diff --git a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java index 161ffdac..bbc09f52 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java @@ -68,7 +68,7 @@ public class MovementAscend extends Movement { public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) { IBlockState toPlace = context.get(destX, y, destZ); double additionalPlacementCost = 0; - if (!MovementHelper.canWalkOn(context.bsi, destX, y, destZ, toPlace)) { + if (!context.precomputedData.canWalkOn(context.bsi, x, y, z, toPlace)) { additionalPlacementCost = context.costOfPlacingAt(destX, y, destZ, toPlace); if (additionalPlacementCost >= COST_INF) { return COST_INF; @@ -94,7 +94,7 @@ public class MovementAscend extends Movement { } } IBlockState srcUp2 = context.get(x, y + 2, z); // used lower down anyway - if (context.get(x, y + 3, z).getBlock() instanceof BlockFalling && (MovementHelper.canWalkThrough(context.bsi, x, y + 1, z) || !(srcUp2.getBlock() instanceof BlockFalling))) {//it would fall on us and possibly suffocate us + if (context.get(x, y + 3, z).getBlock() instanceof BlockFalling && (context.precomputedData.canWalkThrough(context.bsi, x, y + 1, z) || !(srcUp2.getBlock() instanceof BlockFalling))) {//it would fall on us and possibly suffocate us // HOWEVER, we assume that we're standing in the start position // that means that src and src.up(1) are both air // maybe they aren't now, but they will be by the time this starts diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java index 128d1bf9..d0f7d9b3 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java @@ -101,7 +101,7 @@ public class MovementDescend extends Movement { //C, D, etc determine the length of the fall IBlockState below = context.get(destX, y - 2, destZ); - if (!MovementHelper.canWalkOn(context.bsi, destX, y - 2, destZ, below)) { + if (!context.precomputedData.canWalkOn(context.bsi, destX, y - 2, destZ, below)) { dynamicFallCost(context, x, y, z, destX, destZ, totalCost, below, res); return; } @@ -130,7 +130,7 @@ public class MovementDescend extends Movement { // and potentially replace the water we're going to fall into return false; } - if (!MovementHelper.canWalkThrough(context.bsi, destX, y - 2, destZ, below)) { + if (!context.precomputedData.canWalkThrough(context.bsi, destX, y - 2, destZ, below)) { return false; } double costSoFar = 0; @@ -146,7 +146,7 @@ public class MovementDescend extends Movement { int unprotectedFallHeight = fallHeight - (y - effectiveStartHeight); // equal to fallHeight - y + effectiveFallHeight, which is equal to -newY + effectiveFallHeight, which is equal to effectiveFallHeight - newY double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[unprotectedFallHeight] + frontBreak + costSoFar; if (MovementHelper.isWater(ontoBlock.getBlock())) { - if (!MovementHelper.canWalkThrough(context.bsi, destX, newY, destZ, ontoBlock)) { + if (!context.precomputedData.canWalkThrough(context.bsi, destX, newY, destZ, ontoBlock)) { return false; } if (context.assumeWalkOnWater) { @@ -155,7 +155,7 @@ public class MovementDescend extends Movement { if (MovementHelper.isFlowing(destX, newY, destZ, ontoBlock, context.bsi)) { return false; // TODO flowing check required here? } - if (!MovementHelper.canWalkOn(context.bsi, destX, newY - 1, destZ)) { + if (!context.precomputedData.canWalkOn(context.bsi, destX, newY - 1, destZ)) { // we could punch right through the water into something else return false; } @@ -174,10 +174,10 @@ public class MovementDescend extends Movement { effectiveStartHeight = newY; continue; } - if (MovementHelper.canWalkThrough(context.bsi, destX, newY, destZ, ontoBlock)) { + if (context.precomputedData.canWalkThrough(context.bsi, destX, newY, destZ, ontoBlock)) { continue; } - if (!MovementHelper.canWalkOn(context.bsi, destX, newY, destZ, ontoBlock)) { + if (!context.precomputedData.canWalkOn(context.bsi, destX, newY, destZ, ontoBlock)) { return false; } if (MovementHelper.isBottomSlab(ontoBlock)) { diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java index 933c8609..45d319eb 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java @@ -58,9 +58,9 @@ public class MovementDiagonal extends Movement { } @Override - protected boolean safeToCancel(MovementState state) { + protected boolean safeToCancel(MovementState state) { // TODO move this function to use precomputed data, not urgent as it only runs once a tick //too simple. backfill does not work after cornering with this - //return MovementHelper.canWalkOn(ctx, ctx.playerFeet().down()); + //return context.precomputedData.canWalkOn(ctx, ctx.playerFeet().down()); EntityPlayerSP player = ctx.player(); double offset = 0.25; double x = player.posX; @@ -110,24 +110,24 @@ public class MovementDiagonal extends Movement { } public static void cost(CalculationContext context, int x, int y, int z, int destX, int destZ, MutableMoveResult res) { - if (!MovementHelper.canWalkThrough(context.bsi, destX, y + 1, destZ)) { + if (!context.precomputedData.canWalkThrough(context.bsi, destX, y + 1, destZ)) { return; } IBlockState destInto = context.get(destX, y, destZ); boolean ascend = false; IBlockState destWalkOn; boolean descend = false; - if (!MovementHelper.canWalkThrough(context.bsi, destX, y, destZ, destInto)) { + if (!context.precomputedData.canWalkThrough(context.bsi, destX, y, destZ, destInto)) { ascend = true; - if (!context.allowDiagonalAscend || !MovementHelper.canWalkThrough(context.bsi, x, y + 2, z) || !MovementHelper.canWalkOn(context.bsi, destX, y, destZ, destInto) || !MovementHelper.canWalkThrough(context.bsi, destX, y + 2, destZ)) { + if (!context.allowDiagonalAscend || !context.precomputedData.canWalkThrough(context.bsi, x, y + 2, z) || !context.precomputedData.canWalkOn(context.bsi, destX, y, destZ, destInto) || !context.precomputedData.canWalkThrough(context.bsi, destX, y + 2, destZ)) { return; } destWalkOn = destInto; } else { destWalkOn = context.get(destX, y - 1, destZ); - if (!MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, destWalkOn)) { + if (!context.precomputedData.canWalkOn(context.bsi, destX, y - 1, destZ, destWalkOn)) { descend = true; - if (!context.allowDiagonalDescend || !MovementHelper.canWalkOn(context.bsi, destX, y - 2, destZ) || !MovementHelper.canWalkThrough(context.bsi, destX, y - 1, destZ, destWalkOn)) { + if (!context.allowDiagonalDescend || !context.precomputedData.canWalkOn(context.bsi, destX, y - 2, destZ) || !context.precomputedData.canWalkThrough(context.bsi, destX, y - 1, destZ, destWalkOn)) { return; } } @@ -169,17 +169,17 @@ public class MovementDiagonal extends Movement { IBlockState pb0 = context.get(x, y, destZ); IBlockState pb2 = context.get(destX, y, z); if (ascend) { - boolean ATop = MovementHelper.canWalkThrough(context.bsi, x, y + 2, destZ); - boolean AMid = MovementHelper.canWalkThrough(context.bsi, x, y + 1, destZ); - boolean ALow = MovementHelper.canWalkThrough(context.bsi, x, y, destZ, pb0); - boolean BTop = MovementHelper.canWalkThrough(context.bsi, destX, y + 2, z); - boolean BMid = MovementHelper.canWalkThrough(context.bsi, destX, y + 1, z); - boolean BLow = MovementHelper.canWalkThrough(context.bsi, destX, y, z, pb2); + boolean ATop = context.precomputedData.canWalkThrough(context.bsi, x, y + 2, destZ); + boolean AMid = context.precomputedData.canWalkThrough(context.bsi, x, y + 1, destZ); + boolean ALow = context.precomputedData.canWalkThrough(context.bsi, x, y, destZ, pb0); + boolean BTop = context.precomputedData.canWalkThrough(context.bsi, destX, y + 2, z); + boolean BMid = context.precomputedData.canWalkThrough(context.bsi, destX, y + 1, z); + boolean BLow = context.precomputedData.canWalkThrough(context.bsi, destX, y, z, pb2); if ((!(ATop && AMid && ALow) && !(BTop && BMid && BLow)) // no option || MovementHelper.avoidWalkingInto(pb0.getBlock()) // bad || MovementHelper.avoidWalkingInto(pb2.getBlock()) // bad - || (ATop && AMid && MovementHelper.canWalkOn(context.bsi, x, y, destZ, pb0)) // we could just ascend - || (BTop && BMid && MovementHelper.canWalkOn(context.bsi, destX, y, z, pb2)) // we could just ascend + || (ATop && AMid && context.precomputedData.canWalkOn(context.bsi, x, y, destZ, pb0)) // we could just ascend + || (BTop && BMid && context.precomputedData.canWalkOn(context.bsi, destX, y, z, pb2)) // we could just ascend || (!ATop && AMid && ALow) // head bonk A || (!BTop && BMid && BLow)) { // head bonk B return; diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDownward.java b/src/main/java/baritone/pathing/movement/movements/MovementDownward.java index da5e3f89..d10a7d26 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDownward.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDownward.java @@ -59,7 +59,7 @@ public class MovementDownward extends Movement { if (!context.allowDownward) { return COST_INF; } - if (!MovementHelper.canWalkOn(context.bsi, x, y - 2, z)) { + if (!context.precomputedData.canWalkOn(context.bsi, x, y - 2, z)) { return COST_INF; } IBlockState down = context.get(x, y - 1, z); diff --git a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java index e5d17b9a..07140cf1 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java @@ -74,7 +74,7 @@ public class MovementParkour extends Movement { return; } IBlockState adj = context.get(x + xDiff, y - 1, z + zDiff); - if (MovementHelper.canWalkOn(context.bsi, x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now) + if (context.precomputedData.canWalkOn(context.bsi, x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now) // second most common case -- we could just traverse not parkour return; } @@ -122,7 +122,7 @@ public class MovementParkour extends Movement { // check for ascend landing position IBlockState destInto = context.bsi.get0(destX, y, destZ); if (!MovementHelper.fullyPassable(context.bsi.access, context.bsi.isPassableBlockPos.setPos(destX, y, destZ), destInto)) { - if (i <= 3 && context.allowParkourAscend && context.canSprint && MovementHelper.canWalkOn(context.bsi, destX, y, destZ, destInto) && checkOvershootSafety(context.bsi, destX + xDiff, y + 1, destZ + zDiff)) { + if (i <= 3 && context.allowParkourAscend && context.canSprint && context.precomputedData.canWalkOn(context.bsi, destX, y, destZ, destInto) && checkOvershootSafety(context.bsi, destX + xDiff, y + 1, destZ + zDiff)) { res.x = destX; res.y = y + 1; res.z = destZ; @@ -135,7 +135,7 @@ public class MovementParkour extends Movement { // check for flat landing position IBlockState landingOn = context.bsi.get0(destX, y - 1, destZ); // farmland needs to be canWalkOn otherwise farm can never work at all, but we want to specifically disallow ending a jump on farmland haha - if (landingOn.getBlock() != Blocks.FARMLAND && MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, landingOn)) { + if (landingOn.getBlock() != Blocks.FARMLAND && context.precomputedData.canWalkOn(context.bsi, destX, y - 1, destZ, landingOn)) { if (checkOvershootSafety(context.bsi, destX + xDiff, y, destZ + zDiff)) { res.x = destX; res.y = y; diff --git a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java index b9d59933..bcd420ec 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java @@ -120,7 +120,7 @@ public class MovementPillar extends Movement { } } // this is commented because it may have had a purpose, but it's very unclear what it was. it's from the minebot era. - //if (!MovementHelper.canWalkOn(chkPos, check) || MovementHelper.canWalkThrough(chkPos, check)) {//if the block above where we want to break is not a full block, don't do it + //if (!context.precomputedData.canWalkOn(chkPos, check) || context.precomputedData.canWalkThrough(chkPos, check)) {//if the block above where we want to break is not a full block, don't do it // TODO why does canWalkThrough mean this action is COST_INF? // BlockFalling makes sense, and !canWalkOn deals with weird cases like if it were lava // but I don't understand why canWalkThrough makes it impossible diff --git a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java index 1ecf0f92..2afce2f4 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java @@ -72,7 +72,7 @@ public class MovementTraverse extends Movement { IBlockState pb1 = context.get(destX, y, destZ); IBlockState destOn = context.get(destX, y - 1, destZ); Block srcDown = context.getBlock(x, y - 1, z); - if (MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge + if (context.precomputedData.canWalkOn(context.bsi, destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge double WC = WALK_ONE_BLOCK_COST; boolean water = false; if (MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock())) { diff --git a/src/main/java/baritone/pathing/path/PathExecutor.java b/src/main/java/baritone/pathing/path/PathExecutor.java index 7e4f76a3..b28abb61 100644 --- a/src/main/java/baritone/pathing/path/PathExecutor.java +++ b/src/main/java/baritone/pathing/path/PathExecutor.java @@ -350,7 +350,7 @@ public class PathExecutor implements IPathExecutor, Helper { 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) { + if (!new CalculationContext(behavior.baritone, false, null).canSprint) { return false; } IMovement current = path.movements().get(pathPosition); diff --git a/src/main/java/baritone/pathing/precompute/PrecomputedData.java b/src/main/java/baritone/pathing/precompute/PrecomputedData.java new file mode 100644 index 00000000..7531c21a --- /dev/null +++ b/src/main/java/baritone/pathing/precompute/PrecomputedData.java @@ -0,0 +1,237 @@ +/* + * 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.pathing.precompute; + +import baritone.Baritone; +import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.IPlayerContext; +import baritone.pathing.movement.MovementHelper; +import baritone.utils.BlockStateInterface; +import net.minecraft.block.*; +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; +import net.minecraft.util.math.BlockPos; + +import java.util.Optional; + +import static baritone.pathing.movement.MovementHelper.isFlowing; +import static baritone.pathing.movement.MovementHelper.isWater; + +public class PrecomputedData { // TODO add isFullyPassable + + PrecomputedDataForBlockState canWalkOn; + PrecomputedDataForBlockState canWalkThrough; + + public PrecomputedData() { // currently designed for this to be remade on setting change, however that could always be changed + long startTime = System.nanoTime(); + + canWalkOn = new PrecomputedDataForBlockState((state) -> { // this is just copied from the old MovementHelperFunction + Block block = state.getBlock(); + if (block == Blocks.AIR || block == Blocks.MAGMA) { + return Optional.of(false); + } + if (state.isBlockNormalCube()) { + return Optional.of(true); + } + if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.value)) { // TODO reconsider this + return Optional.of(true); + } + if (block == Blocks.FARMLAND || block == Blocks.GRASS_PATH) { + return Optional.of(true); + } + if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST) { + return Optional.of(true); + } + if (isWater(block)) { + return Optional.empty(); + } + if (Baritone.settings().assumeWalkOnLava.value && MovementHelper.isLava(block)) { + return Optional.empty(); + } + + if (block instanceof BlockSlab) { + if (!Baritone.settings().allowWalkOnBottomSlab.value) { + if (((BlockSlab) block).isDouble()) { + return Optional.of(true); + } + return Optional.of(state.getValue(BlockSlab.HALF) != BlockSlab.EnumBlockHalf.BOTTOM); + } + return Optional.of(true); + } + + return Optional.of(block instanceof BlockStairs); + }, (bsi, x, y, z, blockState) -> { // This should just be water or lava, and could probably be made more efficient + Block block = blockState.getBlock(); + if (isWater(block)) { + // since this is called literally millions of times per second, the benefit of not allocating millions of useless "pos.up()" + // BlockPos s that we'd just garbage collect immediately is actually noticeable. I don't even think it's a decrease in readability + Block up = bsi.get0(x, y + 1, z).getBlock(); + if (up == Blocks.WATERLILY || up == Blocks.CARPET) { + return true; + } + if (MovementHelper.isFlowing(x, y, z, blockState, bsi) || block == Blocks.FLOWING_WATER) { + // the only scenario in which we can walk on flowing water is if it's under still water with jesus off + return isWater(up) && !Baritone.settings().assumeWalkOnWater.value; + } + // if assumeWalkOnWater is on, we can only walk on water if there isn't water above it + // if assumeWalkOnWater is off, we can only walk on water if there is water above it + return isWater(up) ^ Baritone.settings().assumeWalkOnWater.value; + } + + if (Baritone.settings().assumeWalkOnLava.value && MovementHelper.isLava(block) && !MovementHelper.isFlowing(x, y, z, blockState, bsi)) { + return true; + } + + return false; // If we don't recognise it then we want to just return false to be safe. + }); + + canWalkThrough = new PrecomputedDataForBlockState((blockState) -> { + Block block = blockState.getBlock(); + + if (block == Blocks.AIR) { + return Optional.of(true); + } + + if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL || block == Blocks.COCOA || block instanceof BlockSkull || block instanceof BlockTrapDoor || block == Blocks.END_ROD) { + return Optional.of(false); + } + + if (Baritone.settings().blocksToAvoid.value.contains(block)) { + return Optional.of(false); + } + + if (block instanceof BlockDoor || block instanceof BlockFenceGate) { + // Because there's no nice method in vanilla to check if a door is openable or not, we just have to assume + // that anything that isn't an iron door isn't openable, ignoring that some doors introduced in mods can't + // be opened by just interacting. + return Optional.of(block != Blocks.IRON_DOOR); + } + + if (block == Blocks.CARPET) { + return Optional.empty(); + } + + if (block instanceof BlockSnow) { + if (blockState.getValue(BlockSnow.LAYERS) >= 3) { + return Optional.of(false); + } + + return Optional.empty(); + } + + if (block instanceof BlockLiquid) { + if (blockState.getValue(BlockLiquid.LEVEL) != 0) { + return Optional.of(false); + } else { + return Optional.empty(); + } + } + + if (block instanceof BlockCauldron) { + return Optional.of(false); + } + + try { // A dodgy catch-all at the end, for most blocks with default behaviour this will work, however where blocks are special this will error out, and we can handle it when we have this information + return Optional.of(block.isPassable(null, null)); + } catch (NullPointerException exception) { + return Optional.empty(); + } + }, (bsi, x, y, z, blockState) -> { + Block block = blockState.getBlock(); + + if (block == Blocks.CARPET) { + return canWalkOn(bsi, x, y - 1, z); + } + + if (block instanceof BlockSnow) { // TODO see if this case is necessary, shouldn't it also check this somewhere else? + return canWalkOn(bsi, x, y - 1, z); + } + + if (block instanceof BlockLiquid) { + if (isFlowing(x, y, z, blockState, bsi)) { + return false; + } + // Everything after this point has to be a special case as it relies on the water not being flowing, which means a special case is needed. + if (Baritone.settings().assumeWalkOnWater.value) { + return false; + } + + IBlockState up = bsi.get0(x, y + 1, z); + if (up.getBlock() instanceof BlockLiquid || up.getBlock() instanceof BlockLilyPad) { + return false; + } + return block == Blocks.WATER || block == Blocks.FLOWING_WATER; + } + + return block.isPassable(bsi.access, bsi.isPassableBlockPos.setPos(x, y, z)); + }); + + long endTime = System.nanoTime(); + + System.out.println(endTime - startTime); + Thread.dumpStack(); + } + + public boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { + return canWalkOn.get(bsi, x, y, z, state); + } + + public boolean canWalkOn(IPlayerContext ctx, BetterBlockPos pos, IBlockState state) { + return canWalkOn(new BlockStateInterface(ctx), pos.x, pos.y, pos.z, state); + } + + public boolean canWalkOn(IPlayerContext ctx, BlockPos pos) { + return canWalkOn(new BlockStateInterface(ctx), pos.getX(), pos.getY(), pos.getZ()); + } + + public boolean canWalkOn(IPlayerContext ctx, BetterBlockPos pos) { + return canWalkOn(new BlockStateInterface(ctx), pos.x, pos.y, pos.z); + } + + public boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z) { + return canWalkOn(bsi, x, y, z, bsi.get0(x, y, z)); + } + + public boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { + return false; + } + + public boolean canWalkThrough(IPlayerContext ctx, BetterBlockPos pos) { + return canWalkThrough(new BlockStateInterface(ctx), pos.x, pos.y, pos.z); + } + + public boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z) { + return canWalkThrough(bsi, x, y, z, bsi.get0(x, y, z)); + } + + /** + * Refresh the precomputed data, for use when settings have changed etc. + */ + public void refresh() { + long startTime = System.nanoTime(); + + for (int i = 0; i < 10; i++) { + canWalkThrough.refresh(); + canWalkOn.refresh(); + } + + long endTime = System.nanoTime(); + + System.out.println(endTime - startTime); + } +} diff --git a/src/main/java/baritone/pathing/precompute/PrecomputedDataForBlockState.java b/src/main/java/baritone/pathing/precompute/PrecomputedDataForBlockState.java new file mode 100644 index 00000000..c7a2f67d --- /dev/null +++ b/src/main/java/baritone/pathing/precompute/PrecomputedDataForBlockState.java @@ -0,0 +1,71 @@ +/* + * 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.pathing.precompute; + +import baritone.utils.BlockStateInterface; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.world.IBlockAccess; + +import java.lang.reflect.Array; +import java.util.Optional; +import java.util.function.Function; + +public class PrecomputedDataForBlockState { + boolean[] dataPerBlockState = new boolean[Block.BLOCK_STATE_IDS.size()]; // Has to be of type boolean due to otherwise it has a generic type + boolean[] specialCases = new boolean[Block.BLOCK_STATE_IDS.size()]; // We can also be certain that size will return the highest as it fills in all positions with null until we get to the highest block state + + private final SpecialCaseFunction specialCaseHandler; + private final Function> precomputer; + + public PrecomputedDataForBlockState(Function> precomputer, SpecialCaseFunction specialCaseHandler) { + this.specialCaseHandler = specialCaseHandler; + this.precomputer = precomputer; + + this.refresh(); + } + + public void refresh() { + for (IBlockState state : Block.BLOCK_STATE_IDS) { // state should never be null + Optional applied = precomputer.apply(state); + + int id = Block.BLOCK_STATE_IDS.get(state); + + if (applied.isPresent()) { + dataPerBlockState[id] = applied.get(); + specialCases[id] = false; + } else { + dataPerBlockState[id] = false; + specialCases[id] = true; + } + } + } + + public boolean get(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { + int id = Block.BLOCK_STATE_IDS.get(state); + if (specialCases[id]) { + return specialCaseHandler.apply(bsi, x, y, z, state); + } else { + return dataPerBlockState[id]; + } + } + + interface SpecialCaseFunction { + public boolean apply(BlockStateInterface bsi, int x, int y, int z, IBlockState blockState); + } +} diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index 1766af62..39c22248 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -38,6 +38,7 @@ import baritone.api.utils.input.Input; import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.Movement; import baritone.pathing.movement.MovementHelper; +import baritone.pathing.precompute.PrecomputedData; import baritone.utils.BaritoneProcessHelper; import baritone.utils.BlockStateInterface; import baritone.utils.PathingCommandContext; @@ -893,7 +894,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil private final int originZ; public BuilderCalculationContext() { - super(BuilderProcess.this.baritone, true); // wew lad + super(BuilderProcess.this.baritone, true, new PrecomputedData()); // wew lad this.placeable = approxPlaceable(9); this.schematic = BuilderProcess.this.schematic; this.originX = origin.getX(); diff --git a/src/main/java/baritone/process/GetToBlockProcess.java b/src/main/java/baritone/process/GetToBlockProcess.java index 16fc3dda..2d1e0e98 100644 --- a/src/main/java/baritone/process/GetToBlockProcess.java +++ b/src/main/java/baritone/process/GetToBlockProcess.java @@ -158,7 +158,7 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG public class GetToBlockCalculationContext extends CalculationContext { public GetToBlockCalculationContext(boolean forUseOnAnotherThread) { - super(GetToBlockProcess.super.baritone, forUseOnAnotherThread); + super(GetToBlockProcess.super.baritone, forUseOnAnotherThread, null); } @Override diff --git a/src/main/java/baritone/process/MineProcess.java b/src/main/java/baritone/process/MineProcess.java index 1ec47cd9..98808934 100644 --- a/src/main/java/baritone/process/MineProcess.java +++ b/src/main/java/baritone/process/MineProcess.java @@ -111,7 +111,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.value; List curr = new ArrayList<>(knownOreLocations); if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain - CalculationContext context = new CalculationContext(baritone, true); + CalculationContext context = new CalculationContext(baritone, true, null); // Precomputed data should never be used on this calculation context Baritone.getExecutor().execute(() -> rescan(curr, context)); } if (Baritone.settings().legitMine.value) { From 2dad6262cf045da884cc615fff9466232e9c7688 Mon Sep 17 00:00:00 2001 From: scorbett123 <50634068+scorbett123@users.noreply.github.com> Date: Tue, 31 May 2022 14:56:23 +0100 Subject: [PATCH 02/23] Remove some benchmarking and fix loading of settings. --- src/api/java/baritone/api/Settings.java | 4 +++- .../pathing/precompute/PrecomputedData.java | 17 +++-------------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 1ce87c68..fd120585 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -1305,7 +1305,9 @@ public final class Settings { public void set(T value) { this.value = value; - BaritoneAPI.getProvider().getAllBaritones().forEach(iBaritone -> iBaritone.getGameEventHandler().onSettingChanged(new SettingChangedEvent(this))); + if (BaritoneAPI.getProvider() != null) { + BaritoneAPI.getProvider().getAllBaritones().forEach(iBaritone -> iBaritone.getGameEventHandler().onSettingChanged(new SettingChangedEvent(this))); + } } public final String getName() { diff --git a/src/main/java/baritone/pathing/precompute/PrecomputedData.java b/src/main/java/baritone/pathing/precompute/PrecomputedData.java index 7531c21a..d354f2d5 100644 --- a/src/main/java/baritone/pathing/precompute/PrecomputedData.java +++ b/src/main/java/baritone/pathing/precompute/PrecomputedData.java @@ -149,6 +149,7 @@ public class PrecomputedData { // TODO add isFullyPassable try { // A dodgy catch-all at the end, for most blocks with default behaviour this will work, however where blocks are special this will error out, and we can handle it when we have this information return Optional.of(block.isPassable(null, null)); } catch (NullPointerException exception) { + System.out.println("Error"); return Optional.empty(); } }, (bsi, x, y, z, blockState) -> { @@ -181,10 +182,6 @@ public class PrecomputedData { // TODO add isFullyPassable return block.isPassable(bsi.access, bsi.isPassableBlockPos.setPos(x, y, z)); }); - long endTime = System.nanoTime(); - - System.out.println(endTime - startTime); - Thread.dumpStack(); } public boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { @@ -223,15 +220,7 @@ public class PrecomputedData { // TODO add isFullyPassable * Refresh the precomputed data, for use when settings have changed etc. */ public void refresh() { - long startTime = System.nanoTime(); - - for (int i = 0; i < 10; i++) { - canWalkThrough.refresh(); - canWalkOn.refresh(); - } - - long endTime = System.nanoTime(); - - System.out.println(endTime - startTime); + canWalkThrough.refresh(); + canWalkOn.refresh(); } } From a6557121a033cce192cbafe91db3d3e641c6970a Mon Sep 17 00:00:00 2001 From: scorbett123 <50634068+scorbett123@users.noreply.github.com> Date: Tue, 31 May 2022 15:08:52 +0100 Subject: [PATCH 03/23] fix github actions compiling. --- .../pathing/precompute/PrecomputedDataForBlockState.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/baritone/pathing/precompute/PrecomputedDataForBlockState.java b/src/main/java/baritone/pathing/precompute/PrecomputedDataForBlockState.java index c7a2f67d..533c5495 100644 --- a/src/main/java/baritone/pathing/precompute/PrecomputedDataForBlockState.java +++ b/src/main/java/baritone/pathing/precompute/PrecomputedDataForBlockState.java @@ -23,6 +23,7 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.world.IBlockAccess; import java.lang.reflect.Array; +import java.util.Iterator; import java.util.Optional; import java.util.function.Function; @@ -41,7 +42,8 @@ public class PrecomputedDataForBlockState { } public void refresh() { - for (IBlockState state : Block.BLOCK_STATE_IDS) { // state should never be null + for (Iterator it = Block.BLOCK_STATE_IDS.iterator(); it.hasNext(); ) { // Can be replaced with an enhanced for because that breaks github actions for some reason I can't be bothered to dig into + IBlockState state = it.next(); // state should never be null Optional applied = precomputer.apply(state); int id = Block.BLOCK_STATE_IDS.get(state); From 9e1a5008edc07b6cbfd983daa46b06115c0145c8 Mon Sep 17 00:00:00 2001 From: scorbett123 <50634068+scorbett123@users.noreply.github.com> Date: Tue, 7 Jun 2022 21:52:24 +0100 Subject: [PATCH 04/23] Move caching functions into MovementHelper --- .../baritone/behavior/PathingBehavior.java | 8 +- .../pathing/movement/MovementHelper.java | 164 +++++++++++----- .../movement/movements/MovementAscend.java | 4 +- .../movement/movements/MovementDescend.java | 10 +- .../movement/movements/MovementDiagonal.java | 26 +-- .../movement/movements/MovementDownward.java | 2 +- .../movement/movements/MovementParkour.java | 6 +- .../movement/movements/MovementTraverse.java | 2 +- .../pathing/precompute/PrecomputedData.java | 181 +----------------- 9 files changed, 148 insertions(+), 255 deletions(-) diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index 50e2a0c2..6bdfe2e7 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -422,7 +422,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, */ public BetterBlockPos pathStart() { // TODO move to a helper or util class BetterBlockPos feet = ctx.playerFeet(); - if (!precomputedData.canWalkOn(ctx, feet.down())) { + if (!MovementHelper.canWalkOn(ctx, feet.down())) { if (ctx.player().onGround) { double playerX = ctx.player().posX; double playerZ = ctx.player().posZ; @@ -441,7 +441,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, // can't possibly be sneaking off of this one, we're too far away continue; } - if (precomputedData.canWalkOn(ctx, possibleSupport.down()) && precomputedData.canWalkThrough(ctx, possibleSupport) && context.precomputedData.canWalkThrough(ctx, possibleSupport.up())) { + if (MovementHelper.canWalkOn(ctx, possibleSupport.down()) && MovementHelper.canWalkThrough(ctx, possibleSupport) && MovementHelper.canWalkThrough(ctx, possibleSupport.up())) { // this is plausible //logDebug("Faking path start assuming player is standing off the edge of a block"); return possibleSupport; @@ -451,7 +451,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, } else { // !onGround // we're in the middle of a jump - if (precomputedData.canWalkOn(ctx, feet.down().down())) { + if (MovementHelper.canWalkOn(ctx, feet.down().down())) { //logDebug("Faking path start assuming player is midair and falling"); return feet.down(); } @@ -462,7 +462,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, @Override public void onSettingChanged(SettingChangedEvent event) { - this.precomputedData.refresh(); + this.precomputedData = new PrecomputedData(); } /** diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index 197f1057..dc4ad31b 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -88,62 +88,105 @@ public interface MovementHelper extends ActionCosts, Helper { return canWalkThrough(bsi, x, y, z, bsi.get0(x, y, z)); } - // if changing something in this function remember to also change it in precomputed data + static boolean canWalkThrough(CalculationContext context, int x, int y, int z, IBlockState state) { + return context.precomputedData.canWalkThrough(context.bsi, x, y, z, state); + } + + static boolean canWalkThrough(CalculationContext context, int x, int y, int z) { + return context.precomputedData.canWalkThrough(context.bsi, x, y, z, context.get(x, y, z)); + } + + static boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { + Optional canWalkOn = canWalkThroughBlockState(state); + return canWalkOn.orElseGet(() -> canWalkThroughPosition(bsi, x, y, z, state)); + } + + static Optional canWalkThroughBlockState(IBlockState state) { Block block = state.getBlock(); - if (block == Blocks.AIR) { // early return for most common case - return true; + + if (block == Blocks.AIR) { + return Optional.of(true); } + if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL || block == Blocks.COCOA || block instanceof BlockSkull || block instanceof BlockTrapDoor || block == Blocks.END_ROD) { - return false; + return Optional.of(false); } + if (Baritone.settings().blocksToAvoid.value.contains(block)) { - return false; + return Optional.of(false); } + if (block instanceof BlockDoor || block instanceof BlockFenceGate) { // Because there's no nice method in vanilla to check if a door is openable or not, we just have to assume // that anything that isn't an iron door isn't openable, ignoring that some doors introduced in mods can't // be opened by just interacting. - return block != Blocks.IRON_DOOR; + return Optional.of(block != Blocks.IRON_DOOR); } + + if (block == Blocks.CARPET) { + return Optional.empty(); + } + + if (block instanceof BlockSnow) { + if (state.getValue(BlockSnow.LAYERS) >= 3) { + return Optional.of(false); + } + + return Optional.empty(); + } + + if (block instanceof BlockLiquid) { + if (state.getValue(BlockLiquid.LEVEL) != 0) { + return Optional.of(false); + } else { + return Optional.empty(); + } + } + + if (block instanceof BlockCauldron) { + return Optional.of(false); + } + + try { // A dodgy catch-all at the end, for most blocks with default behaviour this will work, however where blocks are special this will error out, and we can handle it when we have this information + return Optional.of(block.isPassable(null, null)); + } catch (NullPointerException exception) { + System.out.println("Error"); + return Optional.empty(); + } + } + + static boolean canWalkThroughPosition(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { + Block block = state.getBlock(); + if (block == Blocks.CARPET) { return canWalkOn(bsi, x, y - 1, z); } - if (block instanceof BlockSnow) { - // we've already checked doors and fence gates - // so the only remaining dynamic isPassables are snow and trapdoor - // if they're cached as a top block, we don't know their metadata - // default to true (mostly because it would otherwise make long distance pathing through snowy biomes impossible) - if (!bsi.worldContainsLoadedChunk(x, z)) { - return true; - } - // the check in BlockSnow.isPassable is layers < 5 - // while actually, we want < 3 because 3 or greater makes it impassable in a 2 high ceiling - if (state.getValue(BlockSnow.LAYERS) >= 3) { - return false; - } - // ok, it's low enough we could walk through it, but is it supported? + + if (block instanceof BlockSnow) { // TODO see if this case is necessary, shouldn't it also check this somewhere else? return canWalkOn(bsi, x, y - 1, z); } - if (isFlowing(x, y, z, state, bsi)) { - return false; // Don't walk through flowing liquids - } + if (block instanceof BlockLiquid) { + if (isFlowing(x, y, z, state, bsi)) { + return false; + } + // Everything after this point has to be a special case as it relies on the water not being flowing, which means a special case is needed. if (Baritone.settings().assumeWalkOnWater.value) { return false; } + IBlockState up = bsi.get0(x, y + 1, z); if (up.getBlock() instanceof BlockLiquid || up.getBlock() instanceof BlockLilyPad) { return false; } return block == Blocks.WATER || block == Blocks.FLOWING_WATER; } - if (block instanceof BlockCauldron) { - return false; - } + return block.isPassable(bsi.access, bsi.isPassableBlockPos.setPos(x, y, z)); } + /** * canWalkThrough but also won't impede movement at all. so not including doors or fence gates (we'd have to right click), * not including water, and not including ladders or vines or cobwebs (they slow us down) @@ -296,32 +339,57 @@ public interface MovementHelper extends ActionCosts, Helper { * @return Whether or not the specified block can be walked on */ static boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { + Optional canWalkOn = canWalkOnBlockState(state); + return canWalkOn.orElseGet(() -> canWalkOnPosition(bsi, x, y, z, state)); + } + + static Optional canWalkOnBlockState(IBlockState state) { Block block = state.getBlock(); if (block == Blocks.AIR || block == Blocks.MAGMA) { - // early return for most common case (air) - // plus magma, which is a normal cube but it hurts you - return false; + return Optional.of(false); } if (state.isBlockNormalCube()) { - return true; + return Optional.of(true); } if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.value)) { // TODO reconsider this - return true; + return Optional.of(true); } if (block == Blocks.FARMLAND || block == Blocks.GRASS_PATH) { - return true; + return Optional.of(true); } if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST) { - return true; + return Optional.of(true); } + if (isWater(block)) { + return Optional.empty(); + } + if (Baritone.settings().assumeWalkOnLava.value && MovementHelper.isLava(block)) { + return Optional.empty(); + } + + if (block instanceof BlockSlab) { + if (!Baritone.settings().allowWalkOnBottomSlab.value) { + if (((BlockSlab) block).isDouble()) { + return Optional.of(true); + } + return Optional.of(state.getValue(BlockSlab.HALF) != BlockSlab.EnumBlockHalf.BOTTOM); + } + return Optional.of(true); + } + + return Optional.of(block instanceof BlockStairs); + } + + static boolean canWalkOnPosition(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { + Block block = state.getBlock(); if (isWater(block)) { // since this is called literally millions of times per second, the benefit of not allocating millions of useless "pos.up()" - // BlockPos s that we'd just garbage collect immediately is actually noticeable. I don't even think its a decrease in readability + // BlockPos s that we'd just garbage collect immediately is actually noticeable. I don't even think it's a decrease in readability Block up = bsi.get0(x, y + 1, z).getBlock(); if (up == Blocks.WATERLILY || up == Blocks.CARPET) { return true; } - if (isFlowing(x, y, z, state, bsi) || block == Blocks.FLOWING_WATER) { + if (MovementHelper.isFlowing(x, y, z, state, bsi) || block == Blocks.FLOWING_WATER) { // the only scenario in which we can walk on flowing water is if it's under still water with jesus off return isWater(up) && !Baritone.settings().assumeWalkOnWater.value; } @@ -329,22 +397,20 @@ public interface MovementHelper extends ActionCosts, Helper { // if assumeWalkOnWater is off, we can only walk on water if there is water above it return isWater(up) ^ Baritone.settings().assumeWalkOnWater.value; } - if (Baritone.settings().assumeWalkOnLava.value && isLava(block) && !isFlowing(x, y, z, state, bsi)) { + + if (Baritone.settings().assumeWalkOnLava.value && MovementHelper.isLava(block) && !MovementHelper.isFlowing(x, y, z, state, bsi)) { return true; } - if (block == Blocks.GLASS || block == Blocks.STAINED_GLASS) { - return true; - } - if (block instanceof BlockSlab) { - if (!Baritone.settings().allowWalkOnBottomSlab.value) { - if (((BlockSlab) block).isDouble()) { - return true; - } - return state.getValue(BlockSlab.HALF) != BlockSlab.EnumBlockHalf.BOTTOM; - } - return true; - } - return block instanceof BlockStairs; + + return false; // If we don't recognise it then we want to just return false to be safe. + } + + static boolean canWalkOn(CalculationContext context, int x, int y, int z, IBlockState state) { + return context.precomputedData.canWalkOn(context.bsi, x, y, z, state); + } + + static boolean canWalkOn(CalculationContext context, int x, int y, int z) { + return canWalkOn(context, x, y, z, context.get(x, y, z)); } static boolean canWalkOn(IPlayerContext ctx, BetterBlockPos pos, IBlockState state) { diff --git a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java index bbc09f52..3d6a6cb3 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java @@ -68,7 +68,7 @@ public class MovementAscend extends Movement { public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) { IBlockState toPlace = context.get(destX, y, destZ); double additionalPlacementCost = 0; - if (!context.precomputedData.canWalkOn(context.bsi, x, y, z, toPlace)) { + if (!MovementHelper.canWalkOn(context, destX, y, destZ, toPlace)) { additionalPlacementCost = context.costOfPlacingAt(destX, y, destZ, toPlace); if (additionalPlacementCost >= COST_INF) { return COST_INF; @@ -94,7 +94,7 @@ public class MovementAscend extends Movement { } } IBlockState srcUp2 = context.get(x, y + 2, z); // used lower down anyway - if (context.get(x, y + 3, z).getBlock() instanceof BlockFalling && (context.precomputedData.canWalkThrough(context.bsi, x, y + 1, z) || !(srcUp2.getBlock() instanceof BlockFalling))) {//it would fall on us and possibly suffocate us + if (context.get(x, y + 3, z).getBlock() instanceof BlockFalling && (MovementHelper.canWalkThrough(context, x, y + 1, z) || !(srcUp2.getBlock() instanceof BlockFalling))) {//it would fall on us and possibly suffocate us // HOWEVER, we assume that we're standing in the start position // that means that src and src.up(1) are both air // maybe they aren't now, but they will be by the time this starts diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java index d0f7d9b3..fc66987e 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java @@ -101,7 +101,7 @@ public class MovementDescend extends Movement { //C, D, etc determine the length of the fall IBlockState below = context.get(destX, y - 2, destZ); - if (!context.precomputedData.canWalkOn(context.bsi, destX, y - 2, destZ, below)) { + if (!MovementHelper.canWalkOn(context, destX, y - 2, destZ, below)) { dynamicFallCost(context, x, y, z, destX, destZ, totalCost, below, res); return; } @@ -146,7 +146,7 @@ public class MovementDescend extends Movement { int unprotectedFallHeight = fallHeight - (y - effectiveStartHeight); // equal to fallHeight - y + effectiveFallHeight, which is equal to -newY + effectiveFallHeight, which is equal to effectiveFallHeight - newY double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[unprotectedFallHeight] + frontBreak + costSoFar; if (MovementHelper.isWater(ontoBlock.getBlock())) { - if (!context.precomputedData.canWalkThrough(context.bsi, destX, newY, destZ, ontoBlock)) { + if (!MovementHelper.canWalkThrough(context, destX, newY, destZ, ontoBlock)) { return false; } if (context.assumeWalkOnWater) { @@ -155,7 +155,7 @@ public class MovementDescend extends Movement { if (MovementHelper.isFlowing(destX, newY, destZ, ontoBlock, context.bsi)) { return false; // TODO flowing check required here? } - if (!context.precomputedData.canWalkOn(context.bsi, destX, newY - 1, destZ)) { + if (!MovementHelper.canWalkOn(context, destX, newY - 1, destZ)) { // we could punch right through the water into something else return false; } @@ -174,10 +174,10 @@ public class MovementDescend extends Movement { effectiveStartHeight = newY; continue; } - if (context.precomputedData.canWalkThrough(context.bsi, destX, newY, destZ, ontoBlock)) { + if (MovementHelper.canWalkThrough(context, destX, newY, destZ, ontoBlock)) { continue; } - if (!context.precomputedData.canWalkOn(context.bsi, destX, newY, destZ, ontoBlock)) { + if (!MovementHelper.canWalkOn(context, destX, newY, destZ, ontoBlock)) { return false; } if (MovementHelper.isBottomSlab(ontoBlock)) { diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java index 45d319eb..c1d86d09 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java @@ -110,24 +110,24 @@ public class MovementDiagonal extends Movement { } public static void cost(CalculationContext context, int x, int y, int z, int destX, int destZ, MutableMoveResult res) { - if (!context.precomputedData.canWalkThrough(context.bsi, destX, y + 1, destZ)) { + if (!MovementHelper.canWalkThrough(context, destX, y + 1, destZ)) { return; } IBlockState destInto = context.get(destX, y, destZ); boolean ascend = false; IBlockState destWalkOn; boolean descend = false; - if (!context.precomputedData.canWalkThrough(context.bsi, destX, y, destZ, destInto)) { + if (!MovementHelper.canWalkThrough(context, destX, y, destZ, destInto)) { ascend = true; - if (!context.allowDiagonalAscend || !context.precomputedData.canWalkThrough(context.bsi, x, y + 2, z) || !context.precomputedData.canWalkOn(context.bsi, destX, y, destZ, destInto) || !context.precomputedData.canWalkThrough(context.bsi, destX, y + 2, destZ)) { + if (!context.allowDiagonalAscend || !MovementHelper.canWalkThrough(context, x, y + 2, z) || !MovementHelper.canWalkOn(context, destX, y, destZ, destInto) || !MovementHelper.canWalkThrough(context, destX, y + 2, destZ)) { return; } destWalkOn = destInto; } else { destWalkOn = context.get(destX, y - 1, destZ); - if (!context.precomputedData.canWalkOn(context.bsi, destX, y - 1, destZ, destWalkOn)) { + if (!MovementHelper.canWalkOn(context, destX, y - 1, destZ, destWalkOn)) { descend = true; - if (!context.allowDiagonalDescend || !context.precomputedData.canWalkOn(context.bsi, destX, y - 2, destZ) || !context.precomputedData.canWalkThrough(context.bsi, destX, y - 1, destZ, destWalkOn)) { + if (!context.allowDiagonalDescend || !MovementHelper.canWalkOn(context, destX, y - 2, destZ) || !MovementHelper.canWalkThrough(context, destX, y - 1, destZ, destWalkOn)) { return; } } @@ -169,17 +169,17 @@ public class MovementDiagonal extends Movement { IBlockState pb0 = context.get(x, y, destZ); IBlockState pb2 = context.get(destX, y, z); if (ascend) { - boolean ATop = context.precomputedData.canWalkThrough(context.bsi, x, y + 2, destZ); - boolean AMid = context.precomputedData.canWalkThrough(context.bsi, x, y + 1, destZ); - boolean ALow = context.precomputedData.canWalkThrough(context.bsi, x, y, destZ, pb0); - boolean BTop = context.precomputedData.canWalkThrough(context.bsi, destX, y + 2, z); - boolean BMid = context.precomputedData.canWalkThrough(context.bsi, destX, y + 1, z); - boolean BLow = context.precomputedData.canWalkThrough(context.bsi, destX, y, z, pb2); + boolean ATop = MovementHelper.canWalkThrough(context, x, y + 2, destZ); + boolean AMid = MovementHelper.canWalkThrough(context, x, y + 1, destZ); + boolean ALow = MovementHelper.canWalkThrough(context, x, y, destZ, pb0); + boolean BTop = MovementHelper.canWalkThrough(context, destX, y + 2, z); + boolean BMid = MovementHelper.canWalkThrough(context, destX, y + 1, z); + boolean BLow = MovementHelper.canWalkThrough(context, destX, y, z, pb2); if ((!(ATop && AMid && ALow) && !(BTop && BMid && BLow)) // no option || MovementHelper.avoidWalkingInto(pb0.getBlock()) // bad || MovementHelper.avoidWalkingInto(pb2.getBlock()) // bad - || (ATop && AMid && context.precomputedData.canWalkOn(context.bsi, x, y, destZ, pb0)) // we could just ascend - || (BTop && BMid && context.precomputedData.canWalkOn(context.bsi, destX, y, z, pb2)) // we could just ascend + || (ATop && AMid && MovementHelper.canWalkOn(context, x, y, destZ, pb0)) // we could just ascend + || (BTop && BMid && MovementHelper.canWalkOn(context, destX, y, z, pb2)) // we could just ascend || (!ATop && AMid && ALow) // head bonk A || (!BTop && BMid && BLow)) { // head bonk B return; diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDownward.java b/src/main/java/baritone/pathing/movement/movements/MovementDownward.java index d10a7d26..5a6ec5ce 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDownward.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDownward.java @@ -59,7 +59,7 @@ public class MovementDownward extends Movement { if (!context.allowDownward) { return COST_INF; } - if (!context.precomputedData.canWalkOn(context.bsi, x, y - 2, z)) { + if (!MovementHelper.canWalkOn(context, x, y - 2, z)) { return COST_INF; } IBlockState down = context.get(x, y - 1, z); diff --git a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java index 07140cf1..557f3026 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java @@ -74,7 +74,7 @@ public class MovementParkour extends Movement { return; } IBlockState adj = context.get(x + xDiff, y - 1, z + zDiff); - if (context.precomputedData.canWalkOn(context.bsi, x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now) + if (MovementHelper.canWalkOn(context, x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now) // second most common case -- we could just traverse not parkour return; } @@ -122,7 +122,7 @@ public class MovementParkour extends Movement { // check for ascend landing position IBlockState destInto = context.bsi.get0(destX, y, destZ); if (!MovementHelper.fullyPassable(context.bsi.access, context.bsi.isPassableBlockPos.setPos(destX, y, destZ), destInto)) { - if (i <= 3 && context.allowParkourAscend && context.canSprint && context.precomputedData.canWalkOn(context.bsi, destX, y, destZ, destInto) && checkOvershootSafety(context.bsi, destX + xDiff, y + 1, destZ + zDiff)) { + if (i <= 3 && context.allowParkourAscend && context.canSprint && MovementHelper.canWalkOn(context, destX, y, destZ, destInto) && checkOvershootSafety(context.bsi, destX + xDiff, y + 1, destZ + zDiff)) { res.x = destX; res.y = y + 1; res.z = destZ; @@ -135,7 +135,7 @@ public class MovementParkour extends Movement { // check for flat landing position IBlockState landingOn = context.bsi.get0(destX, y - 1, destZ); // farmland needs to be canWalkOn otherwise farm can never work at all, but we want to specifically disallow ending a jump on farmland haha - if (landingOn.getBlock() != Blocks.FARMLAND && context.precomputedData.canWalkOn(context.bsi, destX, y - 1, destZ, landingOn)) { + if (landingOn.getBlock() != Blocks.FARMLAND && MovementHelper.canWalkOn(context, destX, y - 1, destZ, landingOn)) { if (checkOvershootSafety(context.bsi, destX + xDiff, y, destZ + zDiff)) { res.x = destX; res.y = y; diff --git a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java index 2afce2f4..d932c5f8 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java @@ -72,7 +72,7 @@ public class MovementTraverse extends Movement { IBlockState pb1 = context.get(destX, y, destZ); IBlockState destOn = context.get(destX, y - 1, destZ); Block srcDown = context.getBlock(x, y - 1, z); - if (context.precomputedData.canWalkOn(context.bsi, destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge + if (MovementHelper.canWalkOn(context, destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge double WC = WALK_ONE_BLOCK_COST; boolean water = false; if (MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock())) { diff --git a/src/main/java/baritone/pathing/precompute/PrecomputedData.java b/src/main/java/baritone/pathing/precompute/PrecomputedData.java index d354f2d5..42ff69b2 100644 --- a/src/main/java/baritone/pathing/precompute/PrecomputedData.java +++ b/src/main/java/baritone/pathing/precompute/PrecomputedData.java @@ -37,190 +37,17 @@ public class PrecomputedData { // TODO add isFullyPassable PrecomputedDataForBlockState canWalkOn; PrecomputedDataForBlockState canWalkThrough; - public PrecomputedData() { // currently designed for this to be remade on setting change, however that could always be changed - long startTime = System.nanoTime(); - - canWalkOn = new PrecomputedDataForBlockState((state) -> { // this is just copied from the old MovementHelperFunction - Block block = state.getBlock(); - if (block == Blocks.AIR || block == Blocks.MAGMA) { - return Optional.of(false); - } - if (state.isBlockNormalCube()) { - return Optional.of(true); - } - if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.value)) { // TODO reconsider this - return Optional.of(true); - } - if (block == Blocks.FARMLAND || block == Blocks.GRASS_PATH) { - return Optional.of(true); - } - if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST) { - return Optional.of(true); - } - if (isWater(block)) { - return Optional.empty(); - } - if (Baritone.settings().assumeWalkOnLava.value && MovementHelper.isLava(block)) { - return Optional.empty(); - } - - if (block instanceof BlockSlab) { - if (!Baritone.settings().allowWalkOnBottomSlab.value) { - if (((BlockSlab) block).isDouble()) { - return Optional.of(true); - } - return Optional.of(state.getValue(BlockSlab.HALF) != BlockSlab.EnumBlockHalf.BOTTOM); - } - return Optional.of(true); - } - - return Optional.of(block instanceof BlockStairs); - }, (bsi, x, y, z, blockState) -> { // This should just be water or lava, and could probably be made more efficient - Block block = blockState.getBlock(); - if (isWater(block)) { - // since this is called literally millions of times per second, the benefit of not allocating millions of useless "pos.up()" - // BlockPos s that we'd just garbage collect immediately is actually noticeable. I don't even think it's a decrease in readability - Block up = bsi.get0(x, y + 1, z).getBlock(); - if (up == Blocks.WATERLILY || up == Blocks.CARPET) { - return true; - } - if (MovementHelper.isFlowing(x, y, z, blockState, bsi) || block == Blocks.FLOWING_WATER) { - // the only scenario in which we can walk on flowing water is if it's under still water with jesus off - return isWater(up) && !Baritone.settings().assumeWalkOnWater.value; - } - // if assumeWalkOnWater is on, we can only walk on water if there isn't water above it - // if assumeWalkOnWater is off, we can only walk on water if there is water above it - return isWater(up) ^ Baritone.settings().assumeWalkOnWater.value; - } - - if (Baritone.settings().assumeWalkOnLava.value && MovementHelper.isLava(block) && !MovementHelper.isFlowing(x, y, z, blockState, bsi)) { - return true; - } - - return false; // If we don't recognise it then we want to just return false to be safe. - }); - - canWalkThrough = new PrecomputedDataForBlockState((blockState) -> { - Block block = blockState.getBlock(); - - if (block == Blocks.AIR) { - return Optional.of(true); - } - - if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL || block == Blocks.COCOA || block instanceof BlockSkull || block instanceof BlockTrapDoor || block == Blocks.END_ROD) { - return Optional.of(false); - } - - if (Baritone.settings().blocksToAvoid.value.contains(block)) { - return Optional.of(false); - } - - if (block instanceof BlockDoor || block instanceof BlockFenceGate) { - // Because there's no nice method in vanilla to check if a door is openable or not, we just have to assume - // that anything that isn't an iron door isn't openable, ignoring that some doors introduced in mods can't - // be opened by just interacting. - return Optional.of(block != Blocks.IRON_DOOR); - } - - if (block == Blocks.CARPET) { - return Optional.empty(); - } - - if (block instanceof BlockSnow) { - if (blockState.getValue(BlockSnow.LAYERS) >= 3) { - return Optional.of(false); - } - - return Optional.empty(); - } - - if (block instanceof BlockLiquid) { - if (blockState.getValue(BlockLiquid.LEVEL) != 0) { - return Optional.of(false); - } else { - return Optional.empty(); - } - } - - if (block instanceof BlockCauldron) { - return Optional.of(false); - } - - try { // A dodgy catch-all at the end, for most blocks with default behaviour this will work, however where blocks are special this will error out, and we can handle it when we have this information - return Optional.of(block.isPassable(null, null)); - } catch (NullPointerException exception) { - System.out.println("Error"); - return Optional.empty(); - } - }, (bsi, x, y, z, blockState) -> { - Block block = blockState.getBlock(); - - if (block == Blocks.CARPET) { - return canWalkOn(bsi, x, y - 1, z); - } - - if (block instanceof BlockSnow) { // TODO see if this case is necessary, shouldn't it also check this somewhere else? - return canWalkOn(bsi, x, y - 1, z); - } - - if (block instanceof BlockLiquid) { - if (isFlowing(x, y, z, blockState, bsi)) { - return false; - } - // Everything after this point has to be a special case as it relies on the water not being flowing, which means a special case is needed. - if (Baritone.settings().assumeWalkOnWater.value) { - return false; - } - - IBlockState up = bsi.get0(x, y + 1, z); - if (up.getBlock() instanceof BlockLiquid || up.getBlock() instanceof BlockLilyPad) { - return false; - } - return block == Blocks.WATER || block == Blocks.FLOWING_WATER; - } - - return block.isPassable(bsi.access, bsi.isPassableBlockPos.setPos(x, y, z)); - }); + public PrecomputedData() { + canWalkOn = new PrecomputedDataForBlockState(MovementHelper::canWalkOnBlockState, MovementHelper::canWalkOnPosition); + canWalkThrough = new PrecomputedDataForBlockState(MovementHelper::canWalkThroughBlockState, MovementHelper::canWalkThroughPosition); } public boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { return canWalkOn.get(bsi, x, y, z, state); } - public boolean canWalkOn(IPlayerContext ctx, BetterBlockPos pos, IBlockState state) { - return canWalkOn(new BlockStateInterface(ctx), pos.x, pos.y, pos.z, state); - } - - public boolean canWalkOn(IPlayerContext ctx, BlockPos pos) { - return canWalkOn(new BlockStateInterface(ctx), pos.getX(), pos.getY(), pos.getZ()); - } - - public boolean canWalkOn(IPlayerContext ctx, BetterBlockPos pos) { - return canWalkOn(new BlockStateInterface(ctx), pos.x, pos.y, pos.z); - } - - public boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z) { - return canWalkOn(bsi, x, y, z, bsi.get0(x, y, z)); - } - public boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { - return false; - } - - public boolean canWalkThrough(IPlayerContext ctx, BetterBlockPos pos) { - return canWalkThrough(new BlockStateInterface(ctx), pos.x, pos.y, pos.z); - } - - public boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z) { - return canWalkThrough(bsi, x, y, z, bsi.get0(x, y, z)); - } - - /** - * Refresh the precomputed data, for use when settings have changed etc. - */ - public void refresh() { - canWalkThrough.refresh(); - canWalkOn.refresh(); + return canWalkThrough.get(bsi, x, y, z, state); } } From e7c357ab7f1765546cb3255f1ce73be352ea132b Mon Sep 17 00:00:00 2001 From: scorbett123 <50634068+scorbett123@users.noreply.github.com> Date: Wed, 8 Jun 2022 14:14:14 +0100 Subject: [PATCH 05/23] Make precomputed data refresh every 200 ticks (10 seconds) --- src/main/java/baritone/behavior/PathingBehavior.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index 6bdfe2e7..d1ca2130 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -103,6 +103,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, baritone.getPathingControlManager().cancelEverything(); return; } + + if (ticksElapsedSoFar % 200 == 0) { + precomputedData = new PrecomputedData(); // This is here for now in case settings aren't changed in normal ways, should mean it is updated whatever once every 10 seconds + } + expectedSegmentStart = pathStart(); baritone.getPathingControlManager().preTick(); tickPath(); From 868c023dbdd91012a074002ead135eee78d8c6d3 Mon Sep 17 00:00:00 2001 From: scorbett123 <50634068+scorbett123@users.noreply.github.com> Date: Wed, 8 Jun 2022 14:20:25 +0100 Subject: [PATCH 06/23] Fix a couple of things I missed --- .../baritone/pathing/movement/movements/MovementDescend.java | 2 +- .../baritone/pathing/movement/movements/MovementDiagonal.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java index fc66987e..8675fa04 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java @@ -130,7 +130,7 @@ public class MovementDescend extends Movement { // and potentially replace the water we're going to fall into return false; } - if (!context.precomputedData.canWalkThrough(context.bsi, destX, y - 2, destZ, below)) { + if (!MovementHelper.canWalkThrough(context, destX, y - 2, destZ, below)) { return false; } double costSoFar = 0; diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java index c1d86d09..48b4ed23 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java @@ -58,7 +58,7 @@ public class MovementDiagonal extends Movement { } @Override - protected boolean safeToCancel(MovementState state) { // TODO move this function to use precomputed data, not urgent as it only runs once a tick + protected boolean safeToCancel(MovementState state) { //too simple. backfill does not work after cornering with this //return context.precomputedData.canWalkOn(ctx, ctx.playerFeet().down()); EntityPlayerSP player = ctx.player(); From 3e7f9039c4230dfcae3096e6628d6d90b0220e3b Mon Sep 17 00:00:00 2001 From: scorbett123 <50634068+scorbett123@users.noreply.github.com> Date: Wed, 6 Jul 2022 14:38:33 +0100 Subject: [PATCH 07/23] Don't construct new optionals in movement helper --- .../pathing/movement/MovementHelper.java | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index dc4ad31b..e3ad6800 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -47,6 +47,8 @@ import static baritone.pathing.movement.Movement.HORIZONTALS_BUT_ALSO_DOWN_____S * @author leijurv */ public interface MovementHelper extends ActionCosts, Helper { + static final Optional TRUE = Optional.of(true); + static final Optional FALSE = Optional.of(false); static boolean avoidBreaking(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { if (!bsi.worldBorder.canPlaceAt(x, y)) { @@ -106,15 +108,15 @@ public interface MovementHelper extends ActionCosts, Helper { Block block = state.getBlock(); if (block == Blocks.AIR) { - return Optional.of(true); + return TRUE; } if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL || block == Blocks.COCOA || block instanceof BlockSkull || block instanceof BlockTrapDoor || block == Blocks.END_ROD) { - return Optional.of(false); + return FALSE; } if (Baritone.settings().blocksToAvoid.value.contains(block)) { - return Optional.of(false); + return FALSE; } if (block instanceof BlockDoor || block instanceof BlockFenceGate) { @@ -130,7 +132,7 @@ public interface MovementHelper extends ActionCosts, Helper { if (block instanceof BlockSnow) { if (state.getValue(BlockSnow.LAYERS) >= 3) { - return Optional.of(false); + return FALSE; } return Optional.empty(); @@ -138,14 +140,14 @@ public interface MovementHelper extends ActionCosts, Helper { if (block instanceof BlockLiquid) { if (state.getValue(BlockLiquid.LEVEL) != 0) { - return Optional.of(false); + return FALSE; } else { return Optional.empty(); } } if (block instanceof BlockCauldron) { - return Optional.of(false); + return FALSE; } try { // A dodgy catch-all at the end, for most blocks with default behaviour this will work, however where blocks are special this will error out, and we can handle it when we have this information @@ -346,19 +348,19 @@ public interface MovementHelper extends ActionCosts, Helper { static Optional canWalkOnBlockState(IBlockState state) { Block block = state.getBlock(); if (block == Blocks.AIR || block == Blocks.MAGMA) { - return Optional.of(false); + return FALSE; } if (state.isBlockNormalCube()) { - return Optional.of(true); + return TRUE; } if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.value)) { // TODO reconsider this - return Optional.of(true); + return TRUE; } if (block == Blocks.FARMLAND || block == Blocks.GRASS_PATH) { - return Optional.of(true); + return TRUE; } if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST) { - return Optional.of(true); + return TRUE; } if (isWater(block)) { return Optional.empty(); @@ -370,11 +372,11 @@ public interface MovementHelper extends ActionCosts, Helper { if (block instanceof BlockSlab) { if (!Baritone.settings().allowWalkOnBottomSlab.value) { if (((BlockSlab) block).isDouble()) { - return Optional.of(true); + return TRUE; } return Optional.of(state.getValue(BlockSlab.HALF) != BlockSlab.EnumBlockHalf.BOTTOM); } - return Optional.of(true); + return TRUE; } return Optional.of(block instanceof BlockStairs); From 8d480cefb96b5e868717af7910a18fd678483239 Mon Sep 17 00:00:00 2001 From: scorbett123 <50634068+scorbett123@users.noreply.github.com> Date: Wed, 6 Jul 2022 14:45:54 +0100 Subject: [PATCH 08/23] Switch to throwable and readd check for glass / stained glass --- .../java/baritone/pathing/movement/MovementHelper.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index e3ad6800..b710d7f6 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -152,8 +152,8 @@ public interface MovementHelper extends ActionCosts, Helper { try { // A dodgy catch-all at the end, for most blocks with default behaviour this will work, however where blocks are special this will error out, and we can handle it when we have this information return Optional.of(block.isPassable(null, null)); - } catch (NullPointerException exception) { - System.out.println("Error"); + } catch (Throwable exception) { + System.out.println("The block " + state.getBlock().getLocalizedName() + " requires a special case due to the exception " + exception.getMessage()); return Optional.empty(); } } @@ -369,6 +369,10 @@ public interface MovementHelper extends ActionCosts, Helper { return Optional.empty(); } + if (block == Blocks.GLASS || block == Blocks.STAINED_GLASS) { + return TRUE; + } + if (block instanceof BlockSlab) { if (!Baritone.settings().allowWalkOnBottomSlab.value) { if (((BlockSlab) block).isDouble()) { From fdcdcbb85fa077c156f7ecb744a06a2ea762d613 Mon Sep 17 00:00:00 2001 From: scorbett123 <50634068+scorbett123@users.noreply.github.com> Date: Thu, 14 Jul 2022 12:49:47 +0100 Subject: [PATCH 09/23] Switch to using an int[] for storing precomputed data, and also use lazy loading --- .../pathing/precompute/PrecomputedData.java | 58 +++++++++++++-- .../PrecomputedDataForBlockState.java | 73 ------------------- 2 files changed, 52 insertions(+), 79 deletions(-) delete mode 100644 src/main/java/baritone/pathing/precompute/PrecomputedDataForBlockState.java diff --git a/src/main/java/baritone/pathing/precompute/PrecomputedData.java b/src/main/java/baritone/pathing/precompute/PrecomputedData.java index 42ff69b2..3a0faced 100644 --- a/src/main/java/baritone/pathing/precompute/PrecomputedData.java +++ b/src/main/java/baritone/pathing/precompute/PrecomputedData.java @@ -27,27 +27,73 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; +import java.util.Arrays; import java.util.Optional; import static baritone.pathing.movement.MovementHelper.isFlowing; import static baritone.pathing.movement.MovementHelper.isWater; public class PrecomputedData { // TODO add isFullyPassable + private final int[] data = new int[Block.BLOCK_STATE_IDS.size()]; // Has to be of type boolean due to otherwise it has a generic type - PrecomputedDataForBlockState canWalkOn; - PrecomputedDataForBlockState canWalkThrough; + private final int completedMask = 0b1; + private final int canWalkOnMask = 0b10; + private final int canWalkOnSpecialMask = 0b100; + private final int canWalkThroughMask = 0b1000; + private final int canWalkThroughSpecialMask = 0b10000; public PrecomputedData() { - canWalkOn = new PrecomputedDataForBlockState(MovementHelper::canWalkOnBlockState, MovementHelper::canWalkOnPosition); + Arrays.fill(data, 0); + } - canWalkThrough = new PrecomputedDataForBlockState(MovementHelper::canWalkThroughBlockState, MovementHelper::canWalkThroughPosition); + private void fillData(int id, IBlockState state) { + Optional canWalkOnState = MovementHelper.canWalkOnBlockState(state); + if (canWalkOnState.isPresent()) { + if (canWalkOnState.get()) { + data[id] = data[id] | canWalkOnMask; + } + } else { + data[id] = data[id] | canWalkOnSpecialMask; + } + + Optional canWalkThroughState = MovementHelper.canWalkThroughBlockState(state); + if (canWalkThroughState.isPresent()) { + if (canWalkThroughState.get()) { + data[id] = data[id] | canWalkThroughMask; + } + } else { + data[id] = data[id] | canWalkThroughSpecialMask; + } + + + data[id] = data[id] | completedMask; } public boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { - return canWalkOn.get(bsi, x, y, z, state); + int id = Block.BLOCK_STATE_IDS.get(state); + + if ((data[id] & completedMask) == 0) { // we need to fill in the data + fillData(id, state); + } + + if ((data[id] & canWalkOnSpecialMask) != 0) { + return MovementHelper.canWalkOnPosition(bsi, x, y, z, state); + } else { + return (data[id] & canWalkOnMask) != 0; + } } public boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { - return canWalkThrough.get(bsi, x, y, z, state); + int id = Block.BLOCK_STATE_IDS.get(state); + + if ((data[id] & completedMask) == 0) { // we need to fill in the data + fillData(id, state); + } + + if ((data[id] & canWalkThroughSpecialMask) != 0) { + return MovementHelper.canWalkOnPosition(bsi, x, y, z, state); + } else { + return (data[id] & canWalkThroughMask) != 0; + } } } diff --git a/src/main/java/baritone/pathing/precompute/PrecomputedDataForBlockState.java b/src/main/java/baritone/pathing/precompute/PrecomputedDataForBlockState.java deleted file mode 100644 index 533c5495..00000000 --- a/src/main/java/baritone/pathing/precompute/PrecomputedDataForBlockState.java +++ /dev/null @@ -1,73 +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.pathing.precompute; - -import baritone.utils.BlockStateInterface; -import net.minecraft.block.Block; -import net.minecraft.block.state.IBlockState; -import net.minecraft.world.IBlockAccess; - -import java.lang.reflect.Array; -import java.util.Iterator; -import java.util.Optional; -import java.util.function.Function; - -public class PrecomputedDataForBlockState { - boolean[] dataPerBlockState = new boolean[Block.BLOCK_STATE_IDS.size()]; // Has to be of type boolean due to otherwise it has a generic type - boolean[] specialCases = new boolean[Block.BLOCK_STATE_IDS.size()]; // We can also be certain that size will return the highest as it fills in all positions with null until we get to the highest block state - - private final SpecialCaseFunction specialCaseHandler; - private final Function> precomputer; - - public PrecomputedDataForBlockState(Function> precomputer, SpecialCaseFunction specialCaseHandler) { - this.specialCaseHandler = specialCaseHandler; - this.precomputer = precomputer; - - this.refresh(); - } - - public void refresh() { - for (Iterator it = Block.BLOCK_STATE_IDS.iterator(); it.hasNext(); ) { // Can be replaced with an enhanced for because that breaks github actions for some reason I can't be bothered to dig into - IBlockState state = it.next(); // state should never be null - Optional applied = precomputer.apply(state); - - int id = Block.BLOCK_STATE_IDS.get(state); - - if (applied.isPresent()) { - dataPerBlockState[id] = applied.get(); - specialCases[id] = false; - } else { - dataPerBlockState[id] = false; - specialCases[id] = true; - } - } - } - - public boolean get(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { - int id = Block.BLOCK_STATE_IDS.get(state); - if (specialCases[id]) { - return specialCaseHandler.apply(bsi, x, y, z, state); - } else { - return dataPerBlockState[id]; - } - } - - interface SpecialCaseFunction { - public boolean apply(BlockStateInterface bsi, int x, int y, int z, IBlockState blockState); - } -} From 6b0fb1721bced0de9a33bb021bb96456c5b4d1f1 Mon Sep 17 00:00:00 2001 From: scorbett123 <50634068+scorbett123@users.noreply.github.com> Date: Thu, 14 Jul 2022 17:18:02 +0100 Subject: [PATCH 10/23] These should be all the suggested changes for the caching of can walk through block states --- .../pathing/movement/MovementHelper.java | 16 +++++++++++----- .../movement/movements/MovementPillar.java | 2 +- .../pathing/precompute/PrecomputedData.java | 1 + src/main/java/baritone/process/MineProcess.java | 3 ++- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index b710d7f6..58a16653 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -30,6 +30,7 @@ import baritone.utils.ToolSet; import net.minecraft.block.*; import net.minecraft.block.properties.PropertyBool; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; import net.minecraft.init.Blocks; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; @@ -98,10 +99,12 @@ public interface MovementHelper extends ActionCosts, Helper { return context.precomputedData.canWalkThrough(context.bsi, x, y, z, context.get(x, y, z)); } - static boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { - Optional canWalkOn = canWalkThroughBlockState(state); - return canWalkOn.orElseGet(() -> canWalkThroughPosition(bsi, x, y, z, state)); + Optional canWalkThrough = canWalkThroughBlockState(state); + if (canWalkThrough.isPresent()) { + return canWalkThrough.get(); + } + return canWalkThroughPosition(bsi, x, y, z, state); } static Optional canWalkThroughBlockState(IBlockState state) { @@ -342,7 +345,10 @@ public interface MovementHelper extends ActionCosts, Helper { */ static boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { Optional canWalkOn = canWalkOnBlockState(state); - return canWalkOn.orElseGet(() -> canWalkOnPosition(bsi, x, y, z, state)); + if (canWalkOn.isPresent()) { + return canWalkOn.get(); + } + return canWalkOnPosition(bsi, x, y, z, state); } static Optional canWalkOnBlockState(IBlockState state) { @@ -463,7 +469,7 @@ public interface MovementHelper extends ActionCosts, Helper { static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, IBlockState state, boolean includeFalling) { Block block = state.getBlock(); - if (!canWalkThrough(context.bsi, x, y, z, state)) { + if (!canWalkThrough(context, x, y, z, state)) { if (block instanceof BlockLiquid) { return COST_INF; } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java index bcd420ec..73731aac 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java @@ -120,7 +120,7 @@ public class MovementPillar extends Movement { } } // this is commented because it may have had a purpose, but it's very unclear what it was. it's from the minebot era. - //if (!context.precomputedData.canWalkOn(chkPos, check) || context.precomputedData.canWalkThrough(chkPos, check)) {//if the block above where we want to break is not a full block, don't do it + //if (!MovementHelper.canWalkOn(context, chkPos, check) || MovementHelper.canWalkThrough(context, chkPos, check)) {//if the block above where we want to break is not a full block, don't do it // TODO why does canWalkThrough mean this action is COST_INF? // BlockFalling makes sense, and !canWalkOn deals with weird cases like if it were lava // but I don't understand why canWalkThrough makes it impossible diff --git a/src/main/java/baritone/pathing/precompute/PrecomputedData.java b/src/main/java/baritone/pathing/precompute/PrecomputedData.java index 3a0faced..01eb6dfc 100644 --- a/src/main/java/baritone/pathing/precompute/PrecomputedData.java +++ b/src/main/java/baritone/pathing/precompute/PrecomputedData.java @@ -24,6 +24,7 @@ import baritone.pathing.movement.MovementHelper; import baritone.utils.BlockStateInterface; import net.minecraft.block.*; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/baritone/process/MineProcess.java b/src/main/java/baritone/process/MineProcess.java index 98808934..586c5762 100644 --- a/src/main/java/baritone/process/MineProcess.java +++ b/src/main/java/baritone/process/MineProcess.java @@ -28,6 +28,7 @@ import baritone.cache.CachedChunk; import baritone.cache.WorldScanner; import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.MovementHelper; +import baritone.pathing.precompute.PrecomputedData; import baritone.utils.BaritoneProcessHelper; import baritone.utils.BlockStateInterface; import net.minecraft.block.Block; @@ -111,7 +112,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.value; List curr = new ArrayList<>(knownOreLocations); if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain - CalculationContext context = new CalculationContext(baritone, true, null); // Precomputed data should never be used on this calculation context + CalculationContext context = new CalculationContext(baritone, true, new PrecomputedData()); Baritone.getExecutor().execute(() -> rescan(curr, context)); } if (Baritone.settings().legitMine.value) { From 85ab317c6cb7b38cda25105deb6d04336560185a Mon Sep 17 00:00:00 2001 From: Leijurv Date: Thu, 14 Jul 2022 21:35:30 -0700 Subject: [PATCH 11/23] simplify, remove setting changed event, always construct new precomputeddata --- src/api/java/baritone/api/Settings.java | 14 ++------ .../api/event/events/SettingChangedEvent.java | 33 ------------------- .../listener/AbstractGameEventListener.java | 3 -- .../event/listener/IGameEventListener.java | 7 ---- .../java/baritone/api/utils/SettingsUtil.java | 2 +- .../baritone/behavior/PathingBehavior.java | 15 +-------- .../baritone/command/defaults/SetCommand.java | 2 +- .../java/baritone/event/GameEventHandler.java | 5 --- .../pathing/movement/CalculationContext.java | 6 ++-- .../baritone/pathing/path/PathExecutor.java | 2 +- .../pathing/precompute/PrecomputedData.java | 31 +++++------------ .../java/baritone/process/BuilderProcess.java | 9 +++-- .../baritone/process/GetToBlockProcess.java | 2 +- .../java/baritone/process/MineProcess.java | 2 +- 14 files changed, 25 insertions(+), 108 deletions(-) delete mode 100644 src/api/java/baritone/api/event/events/SettingChangedEvent.java diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index fd120585..98e8700d 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -17,7 +17,6 @@ package baritone.api; -import baritone.api.event.events.SettingChangedEvent; import baritone.api.utils.NotificationHelper; import baritone.api.utils.SettingsUtil; import baritone.api.utils.TypeUtils; @@ -35,8 +34,8 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.*; -import java.util.function.Consumer; import java.util.function.BiConsumer; +import java.util.function.Consumer; /** * Baritone's settings. Settings apply to all Baritone instances. @@ -197,7 +196,7 @@ public final class Settings { * Blocks that Baritone is not allowed to break */ public final Setting> blocksToDisallowBreaking = new Setting<>(new ArrayList<>( - // Leave Empty by Default + // Leave Empty by Default )); /** @@ -913,7 +912,7 @@ public final class Settings { /** * Only build the selected part of schematics */ - public final Setting buildOnlySelection = new Setting<>(false); + public final Setting buildOnlySelection = new Setting<>(false); /** * How far to move before repeating the build. 0 to disable repeating on a certain axis, 0,0,0 to disable entirely @@ -1303,13 +1302,6 @@ public final class Settings { return value; } - public void set(T value) { - this.value = value; - if (BaritoneAPI.getProvider() != null) { - BaritoneAPI.getProvider().getAllBaritones().forEach(iBaritone -> iBaritone.getGameEventHandler().onSettingChanged(new SettingChangedEvent(this))); - } - } - public final String getName() { return name; } diff --git a/src/api/java/baritone/api/event/events/SettingChangedEvent.java b/src/api/java/baritone/api/event/events/SettingChangedEvent.java deleted file mode 100644 index d92384e0..00000000 --- a/src/api/java/baritone/api/event/events/SettingChangedEvent.java +++ /dev/null @@ -1,33 +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.api.event.events; - -import baritone.api.Settings; - -public class SettingChangedEvent { - - private final Settings.Setting setting; - - public SettingChangedEvent(Settings.Setting setting) { - this.setting = setting; - } - - public Settings.Setting getSetting() { - return setting; - } -} diff --git a/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java b/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java index 9f1d2418..9eac8de4 100644 --- a/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java +++ b/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java @@ -71,7 +71,4 @@ public interface AbstractGameEventListener extends IGameEventListener { @Override default void onPathEvent(PathEvent event) {} - - @Override - default void onSettingChanged(SettingChangedEvent event) {} } diff --git a/src/api/java/baritone/api/event/listener/IGameEventListener.java b/src/api/java/baritone/api/event/listener/IGameEventListener.java index 28afdfff..b074e978 100644 --- a/src/api/java/baritone/api/event/listener/IGameEventListener.java +++ b/src/api/java/baritone/api/event/listener/IGameEventListener.java @@ -144,11 +144,4 @@ public interface IGameEventListener { * @param event The event */ void onPathEvent(PathEvent event); - - /** - * When the player changes a setting - * - * @param event The event - */ - void onSettingChanged(SettingChangedEvent event); } diff --git a/src/api/java/baritone/api/utils/SettingsUtil.java b/src/api/java/baritone/api/utils/SettingsUtil.java index b098c1e0..8b4b90b1 100644 --- a/src/api/java/baritone/api/utils/SettingsUtil.java +++ b/src/api/java/baritone/api/utils/SettingsUtil.java @@ -199,7 +199,7 @@ public class SettingsUtil { if (!intendedType.isInstance(parsed)) { throw new IllegalStateException(ioMethod + " parser returned incorrect type, expected " + intendedType + " got " + parsed + " which is " + parsed.getClass()); } - setting.set(parsed); + setting.value = parsed; } private interface ISettingParser { diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index d1ca2130..33ef14ef 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -33,7 +33,6 @@ import baritone.pathing.calc.AbstractNodeCostSearch; import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.MovementHelper; import baritone.pathing.path.PathExecutor; -import baritone.pathing.precompute.PrecomputedData; import baritone.utils.PathRenderer; import baritone.utils.PathingCommandContext; import baritone.utils.pathing.Favoring; @@ -75,11 +74,8 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, private final LinkedBlockingQueue toDispatch = new LinkedBlockingQueue<>(); - public PrecomputedData precomputedData; - public PathingBehavior(Baritone baritone) { super(baritone); - precomputedData = new PrecomputedData(); } private void queuePathEvent(PathEvent event) { @@ -104,10 +100,6 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, return; } - if (ticksElapsedSoFar % 200 == 0) { - precomputedData = new PrecomputedData(); // This is here for now in case settings aren't changed in normal ways, should mean it is updated whatever once every 10 seconds - } - expectedSegmentStart = pathStart(); baritone.getPathingControlManager().preTick(); tickPath(); @@ -268,7 +260,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, if (command instanceof PathingCommandContext) { context = ((PathingCommandContext) command).desiredCalcContext; } else { - context = new CalculationContext(baritone, true, precomputedData); + context = new CalculationContext(baritone, true); } if (goal == null) { return false; @@ -465,11 +457,6 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, return feet; } - @Override - public void onSettingChanged(SettingChangedEvent event) { - this.precomputedData = new PrecomputedData(); - } - /** * In a new thread, pathfind to target blockpos * diff --git a/src/main/java/baritone/command/defaults/SetCommand.java b/src/main/java/baritone/command/defaults/SetCommand.java index 1b395f5a..fd9bb045 100644 --- a/src/main/java/baritone/command/defaults/SetCommand.java +++ b/src/main/java/baritone/command/defaults/SetCommand.java @@ -148,7 +148,7 @@ public class SetCommand extends Command { } //noinspection unchecked Settings.Setting asBoolSetting = (Settings.Setting) setting; - asBoolSetting.set(!asBoolSetting.value); + asBoolSetting.value ^= true; logDirect(String.format( "Toggled setting %s to %s", setting.getName(), diff --git a/src/main/java/baritone/event/GameEventHandler.java b/src/main/java/baritone/event/GameEventHandler.java index 1bdba6b9..8916f7f3 100644 --- a/src/main/java/baritone/event/GameEventHandler.java +++ b/src/main/java/baritone/event/GameEventHandler.java @@ -156,11 +156,6 @@ public final class GameEventHandler implements IEventBus, Helper { listeners.forEach(l -> l.onPathEvent(event)); } - @Override - public void onSettingChanged(SettingChangedEvent event) { - listeners.forEach(l -> l.onSettingChanged(event)); - } - @Override public final void registerEventListener(IGameEventListener listener) { this.listeners.add(listener); diff --git a/src/main/java/baritone/pathing/movement/CalculationContext.java b/src/main/java/baritone/pathing/movement/CalculationContext.java index b4782fb5..5a8d9839 100644 --- a/src/main/java/baritone/pathing/movement/CalculationContext.java +++ b/src/main/java/baritone/pathing/movement/CalculationContext.java @@ -80,11 +80,11 @@ public class CalculationContext { public final PrecomputedData precomputedData; public CalculationContext(IBaritone baritone) { - this(baritone, false, new PrecomputedData()); + this(baritone, false); } - public CalculationContext(IBaritone baritone, boolean forUseOnAnotherThread, PrecomputedData precomputedData) { - this.precomputedData = precomputedData; + public CalculationContext(IBaritone baritone, boolean forUseOnAnotherThread) { + this.precomputedData = new PrecomputedData(); this.safeForThreadedUse = forUseOnAnotherThread; this.baritone = baritone; EntityPlayerSP player = baritone.getPlayerContext().player(); diff --git a/src/main/java/baritone/pathing/path/PathExecutor.java b/src/main/java/baritone/pathing/path/PathExecutor.java index b28abb61..2ac67e22 100644 --- a/src/main/java/baritone/pathing/path/PathExecutor.java +++ b/src/main/java/baritone/pathing/path/PathExecutor.java @@ -350,7 +350,7 @@ public class PathExecutor implements IPathExecutor, Helper { 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, false, null).canSprint) { + if (!new CalculationContext(behavior.baritone, false).canSprint) { return false; } IMovement current = path.movements().get(pathPosition); diff --git a/src/main/java/baritone/pathing/precompute/PrecomputedData.java b/src/main/java/baritone/pathing/precompute/PrecomputedData.java index 01eb6dfc..99a25944 100644 --- a/src/main/java/baritone/pathing/precompute/PrecomputedData.java +++ b/src/main/java/baritone/pathing/precompute/PrecomputedData.java @@ -17,25 +17,16 @@ package baritone.pathing.precompute; -import baritone.Baritone; -import baritone.api.utils.BetterBlockPos; -import baritone.api.utils.IPlayerContext; import baritone.pathing.movement.MovementHelper; import baritone.utils.BlockStateInterface; -import net.minecraft.block.*; +import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; -import net.minecraft.client.Minecraft; -import net.minecraft.init.Blocks; -import net.minecraft.util.math.BlockPos; -import java.util.Arrays; import java.util.Optional; -import static baritone.pathing.movement.MovementHelper.isFlowing; -import static baritone.pathing.movement.MovementHelper.isWater; - public class PrecomputedData { // TODO add isFullyPassable - private final int[] data = new int[Block.BLOCK_STATE_IDS.size()]; // Has to be of type boolean due to otherwise it has a generic type + + private final int[] data = new int[Block.BLOCK_STATE_IDS.size()]; private final int completedMask = 0b1; private final int canWalkOnMask = 0b10; @@ -43,31 +34,27 @@ public class PrecomputedData { // TODO add isFullyPassable private final int canWalkThroughMask = 0b1000; private final int canWalkThroughSpecialMask = 0b10000; - public PrecomputedData() { - Arrays.fill(data, 0); - } - private void fillData(int id, IBlockState state) { Optional canWalkOnState = MovementHelper.canWalkOnBlockState(state); if (canWalkOnState.isPresent()) { if (canWalkOnState.get()) { - data[id] = data[id] | canWalkOnMask; + data[id] |= canWalkOnMask; } } else { - data[id] = data[id] | canWalkOnSpecialMask; + data[id] |= canWalkOnSpecialMask; } Optional canWalkThroughState = MovementHelper.canWalkThroughBlockState(state); if (canWalkThroughState.isPresent()) { if (canWalkThroughState.get()) { - data[id] = data[id] | canWalkThroughMask; + data[id] |= canWalkThroughMask; } } else { - data[id] = data[id] | canWalkThroughSpecialMask; + data[id] |= canWalkThroughSpecialMask; } - data[id] = data[id] | completedMask; + data[id] |= completedMask; } public boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { @@ -92,7 +79,7 @@ public class PrecomputedData { // TODO add isFullyPassable } if ((data[id] & canWalkThroughSpecialMask) != 0) { - return MovementHelper.canWalkOnPosition(bsi, x, y, z, state); + return MovementHelper.canWalkThroughPosition(bsi, x, y, z, state); } else { return (data[id] & canWalkThroughMask) != 0; } diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index 39c22248..181c58d7 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -26,9 +26,9 @@ import baritone.api.process.IBuilderProcess; import baritone.api.process.PathingCommand; import baritone.api.process.PathingCommandType; import baritone.api.schematic.FillSchematic; -import baritone.api.schematic.SubstituteSchematic; import baritone.api.schematic.ISchematic; import baritone.api.schematic.IStaticSchematic; +import baritone.api.schematic.SubstituteSchematic; import baritone.api.schematic.format.ISchematicFormat; import baritone.api.utils.BetterBlockPos; import baritone.api.utils.RayTraceUtils; @@ -38,13 +38,12 @@ import baritone.api.utils.input.Input; import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.Movement; import baritone.pathing.movement.MovementHelper; -import baritone.pathing.precompute.PrecomputedData; import baritone.utils.BaritoneProcessHelper; import baritone.utils.BlockStateInterface; import baritone.utils.PathingCommandContext; import baritone.utils.schematic.MapArtSchematic; -import baritone.utils.schematic.SelectionSchematic; import baritone.utils.schematic.SchematicSystem; +import baritone.utils.schematic.SelectionSchematic; import baritone.utils.schematic.schematica.SchematicaHelper; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -607,7 +606,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil } // this is not in render distance if (!observedCompleted.contains(BetterBlockPos.longHash(blockX, blockY, blockZ)) - && !Baritone.settings().buildSkipBlocks.value.contains(schematic.desiredState(x, y, z, current, this.approxPlaceable).getBlock())) { + && !Baritone.settings().buildSkipBlocks.value.contains(schematic.desiredState(x, y, z, current, this.approxPlaceable).getBlock())) { // and we've never seen this position be correct // therefore mark as incorrect incorrectPositions.add(new BetterBlockPos(blockX, blockY, blockZ)); @@ -894,7 +893,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil private final int originZ; public BuilderCalculationContext() { - super(BuilderProcess.this.baritone, true, new PrecomputedData()); // wew lad + super(BuilderProcess.this.baritone, true); // wew lad this.placeable = approxPlaceable(9); this.schematic = BuilderProcess.this.schematic; this.originX = origin.getX(); diff --git a/src/main/java/baritone/process/GetToBlockProcess.java b/src/main/java/baritone/process/GetToBlockProcess.java index 2d1e0e98..16fc3dda 100644 --- a/src/main/java/baritone/process/GetToBlockProcess.java +++ b/src/main/java/baritone/process/GetToBlockProcess.java @@ -158,7 +158,7 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG public class GetToBlockCalculationContext extends CalculationContext { public GetToBlockCalculationContext(boolean forUseOnAnotherThread) { - super(GetToBlockProcess.super.baritone, forUseOnAnotherThread, null); + super(GetToBlockProcess.super.baritone, forUseOnAnotherThread); } @Override diff --git a/src/main/java/baritone/process/MineProcess.java b/src/main/java/baritone/process/MineProcess.java index 586c5762..23631f27 100644 --- a/src/main/java/baritone/process/MineProcess.java +++ b/src/main/java/baritone/process/MineProcess.java @@ -112,7 +112,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.value; List curr = new ArrayList<>(knownOreLocations); if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain - CalculationContext context = new CalculationContext(baritone, true, new PrecomputedData()); + CalculationContext context = new CalculationContext(baritone, true); Baritone.getExecutor().execute(() -> rescan(curr, context)); } if (Baritone.settings().legitMine.value) { From 8018dac39603f31f06021163d662b7b213207566 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Thu, 14 Jul 2022 21:38:02 -0700 Subject: [PATCH 12/23] fix default case that instantiated an optional for non stairs --- .../baritone/pathing/movement/MovementHelper.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index 58a16653..cc7b4226 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -30,7 +30,6 @@ import baritone.utils.ToolSet; import net.minecraft.block.*; import net.minecraft.block.properties.PropertyBool; import net.minecraft.block.state.IBlockState; -import net.minecraft.client.Minecraft; import net.minecraft.init.Blocks; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; @@ -48,8 +47,9 @@ import static baritone.pathing.movement.Movement.HORIZONTALS_BUT_ALSO_DOWN_____S * @author leijurv */ public interface MovementHelper extends ActionCosts, Helper { - static final Optional TRUE = Optional.of(true); - static final Optional FALSE = Optional.of(false); + + Optional TRUE = Optional.of(true); + Optional FALSE = Optional.of(false); static boolean avoidBreaking(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { if (!bsi.worldBorder.canPlaceAt(x, y)) { @@ -333,7 +333,7 @@ public interface MovementHelper extends ActionCosts, Helper { * Can I walk on this block without anything weird happening like me falling * through? Includes water because we know that we automatically jump on * water - * + *

* If changing something in this function remember to also change it in precomputed data * * @param bsi Block state provider @@ -389,7 +389,11 @@ public interface MovementHelper extends ActionCosts, Helper { return TRUE; } - return Optional.of(block instanceof BlockStairs); + if (block instanceof BlockStairs) { + return TRUE; + } + + return FALSE; } static boolean canWalkOnPosition(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { From 5b7bee977bf9f8e6e2bcfaf6bc53ea80e1750ab6 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Thu, 14 Jul 2022 21:38:38 -0700 Subject: [PATCH 13/23] also don't construct an optional for slabs --- src/main/java/baritone/pathing/movement/MovementHelper.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index cc7b4226..a29e06bb 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -384,7 +384,10 @@ public interface MovementHelper extends ActionCosts, Helper { if (((BlockSlab) block).isDouble()) { return TRUE; } - return Optional.of(state.getValue(BlockSlab.HALF) != BlockSlab.EnumBlockHalf.BOTTOM); + if (state.getValue(BlockSlab.HALF) != BlockSlab.EnumBlockHalf.BOTTOM) { + return TRUE; + } + return FALSE; } return TRUE; } From 93fa6cf8753c0d2d8b3da7ab3b8203bd6848125d Mon Sep 17 00:00:00 2001 From: Leijurv Date: Thu, 14 Jul 2022 21:42:38 -0700 Subject: [PATCH 14/23] introduce MAYBE and fix more allocation cases --- .../pathing/movement/MovementHelper.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index a29e06bb..4a45cd99 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -50,6 +50,7 @@ public interface MovementHelper extends ActionCosts, Helper { Optional TRUE = Optional.of(true); Optional FALSE = Optional.of(false); + Optional MAYBE = Optional.empty(); static boolean avoidBreaking(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { if (!bsi.worldBorder.canPlaceAt(x, y)) { @@ -126,11 +127,14 @@ public interface MovementHelper extends ActionCosts, Helper { // Because there's no nice method in vanilla to check if a door is openable or not, we just have to assume // that anything that isn't an iron door isn't openable, ignoring that some doors introduced in mods can't // be opened by just interacting. - return Optional.of(block != Blocks.IRON_DOOR); + if (block == Blocks.IRON_DOOR) { + return FALSE; + } + return TRUE; } if (block == Blocks.CARPET) { - return Optional.empty(); + return MAYBE; } if (block instanceof BlockSnow) { @@ -138,14 +142,14 @@ public interface MovementHelper extends ActionCosts, Helper { return FALSE; } - return Optional.empty(); + return MAYBE; } if (block instanceof BlockLiquid) { if (state.getValue(BlockLiquid.LEVEL) != 0) { return FALSE; } else { - return Optional.empty(); + return MAYBE; } } @@ -157,7 +161,7 @@ public interface MovementHelper extends ActionCosts, Helper { return Optional.of(block.isPassable(null, null)); } catch (Throwable exception) { System.out.println("The block " + state.getBlock().getLocalizedName() + " requires a special case due to the exception " + exception.getMessage()); - return Optional.empty(); + return MAYBE; } } @@ -369,10 +373,10 @@ public interface MovementHelper extends ActionCosts, Helper { return TRUE; } if (isWater(block)) { - return Optional.empty(); + return MAYBE; } if (Baritone.settings().assumeWalkOnLava.value && MovementHelper.isLava(block)) { - return Optional.empty(); + return MAYBE; } if (block == Blocks.GLASS || block == Blocks.STAINED_GLASS) { From 5c7cae9ab0585c2026301da3b99da01da85fef3b Mon Sep 17 00:00:00 2001 From: Leijurv Date: Thu, 14 Jul 2022 21:43:14 -0700 Subject: [PATCH 15/23] fix literally wrong comment that did not match subsequent code --- src/main/java/baritone/pathing/movement/MovementHelper.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index 4a45cd99..c96dee78 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -124,9 +124,7 @@ public interface MovementHelper extends ActionCosts, Helper { } if (block instanceof BlockDoor || block instanceof BlockFenceGate) { - // Because there's no nice method in vanilla to check if a door is openable or not, we just have to assume - // that anything that isn't an iron door isn't openable, ignoring that some doors introduced in mods can't - // be opened by just interacting. + // TODO this assumes that all doors in all mods are openable if (block == Blocks.IRON_DOOR) { return FALSE; } From 5c9aeab6b4b3c276ec704306ece5fefebcf2ec76 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Thu, 14 Jul 2022 21:44:42 -0700 Subject: [PATCH 16/23] add cmt --- src/main/java/baritone/pathing/movement/MovementHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index c96dee78..b121a0b3 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -102,7 +102,7 @@ public interface MovementHelper extends ActionCosts, Helper { static boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { Optional canWalkThrough = canWalkThroughBlockState(state); - if (canWalkThrough.isPresent()) { + if (canWalkThrough.isPresent()) { // note: don't replace this with the functional style, because the lambda is impure (it captures local variables as context), meaning it allocates return canWalkThrough.get(); } return canWalkThroughPosition(bsi, x, y, z, state); From ee16eb7fde54055bd4374a51f571a71b120bbb1c Mon Sep 17 00:00:00 2001 From: Leijurv Date: Thu, 14 Jul 2022 21:47:18 -0700 Subject: [PATCH 17/23] funnier this way --- .../pathing/movement/MovementHelper.java | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index b121a0b3..f915dd78 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -48,8 +48,8 @@ import static baritone.pathing.movement.Movement.HORIZONTALS_BUT_ALSO_DOWN_____S */ public interface MovementHelper extends ActionCosts, Helper { - Optional TRUE = Optional.of(true); - Optional FALSE = Optional.of(false); + Optional YES = Optional.of(true); + Optional NO = Optional.of(false); Optional MAYBE = Optional.empty(); static boolean avoidBreaking(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { @@ -112,23 +112,23 @@ public interface MovementHelper extends ActionCosts, Helper { Block block = state.getBlock(); if (block == Blocks.AIR) { - return TRUE; + return YES; } if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL || block == Blocks.COCOA || block instanceof BlockSkull || block instanceof BlockTrapDoor || block == Blocks.END_ROD) { - return FALSE; + return NO; } if (Baritone.settings().blocksToAvoid.value.contains(block)) { - return FALSE; + return NO; } if (block instanceof BlockDoor || block instanceof BlockFenceGate) { // TODO this assumes that all doors in all mods are openable if (block == Blocks.IRON_DOOR) { - return FALSE; + return NO; } - return TRUE; + return YES; } if (block == Blocks.CARPET) { @@ -137,7 +137,7 @@ public interface MovementHelper extends ActionCosts, Helper { if (block instanceof BlockSnow) { if (state.getValue(BlockSnow.LAYERS) >= 3) { - return FALSE; + return NO; } return MAYBE; @@ -145,14 +145,14 @@ public interface MovementHelper extends ActionCosts, Helper { if (block instanceof BlockLiquid) { if (state.getValue(BlockLiquid.LEVEL) != 0) { - return FALSE; + return NO; } else { return MAYBE; } } if (block instanceof BlockCauldron) { - return FALSE; + return NO; } try { // A dodgy catch-all at the end, for most blocks with default behaviour this will work, however where blocks are special this will error out, and we can handle it when we have this information @@ -356,19 +356,19 @@ public interface MovementHelper extends ActionCosts, Helper { static Optional canWalkOnBlockState(IBlockState state) { Block block = state.getBlock(); if (block == Blocks.AIR || block == Blocks.MAGMA) { - return FALSE; + return NO; } if (state.isBlockNormalCube()) { - return TRUE; + return YES; } if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.value)) { // TODO reconsider this - return TRUE; + return YES; } if (block == Blocks.FARMLAND || block == Blocks.GRASS_PATH) { - return TRUE; + return YES; } if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST) { - return TRUE; + return YES; } if (isWater(block)) { return MAYBE; @@ -378,27 +378,27 @@ public interface MovementHelper extends ActionCosts, Helper { } if (block == Blocks.GLASS || block == Blocks.STAINED_GLASS) { - return TRUE; + return YES; } if (block instanceof BlockSlab) { if (!Baritone.settings().allowWalkOnBottomSlab.value) { if (((BlockSlab) block).isDouble()) { - return TRUE; + return YES; } if (state.getValue(BlockSlab.HALF) != BlockSlab.EnumBlockHalf.BOTTOM) { - return TRUE; + return YES; } - return FALSE; + return NO; } - return TRUE; + return YES; } if (block instanceof BlockStairs) { - return TRUE; + return YES; } - return FALSE; + return NO; } static boolean canWalkOnPosition(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { From 0c1fec5d1efe85c62c04a19eb0ba5203fd8ea0b7 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Thu, 14 Jul 2022 21:54:32 -0700 Subject: [PATCH 18/23] crucial performance optimization --- .../pathing/precompute/PrecomputedData.java | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/main/java/baritone/pathing/precompute/PrecomputedData.java b/src/main/java/baritone/pathing/precompute/PrecomputedData.java index 99a25944..6d3a742c 100644 --- a/src/main/java/baritone/pathing/precompute/PrecomputedData.java +++ b/src/main/java/baritone/pathing/precompute/PrecomputedData.java @@ -34,54 +34,60 @@ public class PrecomputedData { // TODO add isFullyPassable private final int canWalkThroughMask = 0b1000; private final int canWalkThroughSpecialMask = 0b10000; - private void fillData(int id, IBlockState state) { + private int fillData(int id, IBlockState state) { + int blockData = 0; + Optional canWalkOnState = MovementHelper.canWalkOnBlockState(state); if (canWalkOnState.isPresent()) { if (canWalkOnState.get()) { - data[id] |= canWalkOnMask; + blockData |= canWalkOnMask; } } else { - data[id] |= canWalkOnSpecialMask; + blockData |= canWalkOnSpecialMask; } Optional canWalkThroughState = MovementHelper.canWalkThroughBlockState(state); if (canWalkThroughState.isPresent()) { if (canWalkThroughState.get()) { - data[id] |= canWalkThroughMask; + blockData |= canWalkThroughMask; } } else { - data[id] |= canWalkThroughSpecialMask; + blockData |= canWalkThroughSpecialMask; } + blockData |= completedMask; - data[id] |= completedMask; + data[id] = blockData; // in theory, this is thread "safe" because every thread should compute the exact same int to write? + return blockData; } public boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { int id = Block.BLOCK_STATE_IDS.get(state); + int blockData = data[id]; - if ((data[id] & completedMask) == 0) { // we need to fill in the data - fillData(id, state); + if ((blockData & completedMask) == 0) { // we need to fill in the data + blockData = fillData(id, state); } - if ((data[id] & canWalkOnSpecialMask) != 0) { + if ((blockData & canWalkOnSpecialMask) != 0) { return MovementHelper.canWalkOnPosition(bsi, x, y, z, state); } else { - return (data[id] & canWalkOnMask) != 0; + return (blockData & canWalkOnMask) != 0; } } public boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { int id = Block.BLOCK_STATE_IDS.get(state); + int blockData = data[id]; - if ((data[id] & completedMask) == 0) { // we need to fill in the data - fillData(id, state); + if ((blockData & completedMask) == 0) { // we need to fill in the data + blockData = fillData(id, state); } - if ((data[id] & canWalkThroughSpecialMask) != 0) { + if ((blockData & canWalkThroughSpecialMask) != 0) { return MovementHelper.canWalkThroughPosition(bsi, x, y, z, state); } else { - return (data[id] & canWalkThroughMask) != 0; + return (blockData & canWalkThroughMask) != 0; } } } From 0bd16fb81a6ed5f7aca529c89ddca5c98fe0d434 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Thu, 14 Jul 2022 21:56:25 -0700 Subject: [PATCH 19/23] bit literals are meh --- .../baritone/pathing/precompute/PrecomputedData.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/baritone/pathing/precompute/PrecomputedData.java b/src/main/java/baritone/pathing/precompute/PrecomputedData.java index 6d3a742c..3ca2c466 100644 --- a/src/main/java/baritone/pathing/precompute/PrecomputedData.java +++ b/src/main/java/baritone/pathing/precompute/PrecomputedData.java @@ -28,11 +28,11 @@ public class PrecomputedData { // TODO add isFullyPassable private final int[] data = new int[Block.BLOCK_STATE_IDS.size()]; - private final int completedMask = 0b1; - private final int canWalkOnMask = 0b10; - private final int canWalkOnSpecialMask = 0b100; - private final int canWalkThroughMask = 0b1000; - private final int canWalkThroughSpecialMask = 0b10000; + private final int completedMask = 1 << 0; + private final int canWalkOnMask = 1 << 1; + private final int canWalkOnSpecialMask = 1 << 2; + private final int canWalkThroughMask = 1 << 3; + private final int canWalkThroughSpecialMask = 1 << 4; private int fillData(int id, IBlockState state) { int blockData = 0; From 2d1b81dc20c360db96888eb9c1c1b496dbb3dab1 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Thu, 14 Jul 2022 22:00:18 -0700 Subject: [PATCH 20/23] vastly increase cuteness by removing the optional boolean --- .../pathing/movement/MovementHelper.java | 34 ++++++++++++------- .../pathing/precompute/PrecomputedData.java | 25 +++++++------- .../baritone/pathing/precompute/Ternary.java | 22 ++++++++++++ 3 files changed, 55 insertions(+), 26 deletions(-) create mode 100644 src/main/java/baritone/pathing/precompute/Ternary.java diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index f915dd78..3d115d1d 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -25,6 +25,7 @@ import baritone.api.pathing.movement.MovementStatus; import baritone.api.utils.*; import baritone.api.utils.input.Input; import baritone.pathing.movement.MovementState.MovementTarget; +import baritone.pathing.precompute.Ternary; import baritone.utils.BlockStateInterface; import baritone.utils.ToolSet; import net.minecraft.block.*; @@ -40,6 +41,7 @@ import net.minecraft.world.IBlockAccess; import java.util.Optional; import static baritone.pathing.movement.Movement.HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP; +import static baritone.pathing.precompute.Ternary.*; /** * Static helpers for cost calculation @@ -48,10 +50,6 @@ import static baritone.pathing.movement.Movement.HORIZONTALS_BUT_ALSO_DOWN_____S */ public interface MovementHelper extends ActionCosts, Helper { - Optional YES = Optional.of(true); - Optional NO = Optional.of(false); - Optional MAYBE = Optional.empty(); - static boolean avoidBreaking(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { if (!bsi.worldBorder.canPlaceAt(x, y)) { return true; @@ -101,14 +99,17 @@ public interface MovementHelper extends ActionCosts, Helper { } static boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { - Optional canWalkThrough = canWalkThroughBlockState(state); - if (canWalkThrough.isPresent()) { // note: don't replace this with the functional style, because the lambda is impure (it captures local variables as context), meaning it allocates - return canWalkThrough.get(); + Ternary canWalkThrough = canWalkThroughBlockState(state); + if (canWalkThrough == YES) { + return true; + } + if (canWalkThrough == NO) { + return false; } return canWalkThroughPosition(bsi, x, y, z, state); } - static Optional canWalkThroughBlockState(IBlockState state) { + static Ternary canWalkThroughBlockState(IBlockState state) { Block block = state.getBlock(); if (block == Blocks.AIR) { @@ -156,7 +157,11 @@ public interface MovementHelper extends ActionCosts, Helper { } try { // A dodgy catch-all at the end, for most blocks with default behaviour this will work, however where blocks are special this will error out, and we can handle it when we have this information - return Optional.of(block.isPassable(null, null)); + if (block.isPassable(null, null)) { + return YES; + } else { + return NO; + } } catch (Throwable exception) { System.out.println("The block " + state.getBlock().getLocalizedName() + " requires a special case due to the exception " + exception.getMessage()); return MAYBE; @@ -346,14 +351,17 @@ public interface MovementHelper extends ActionCosts, Helper { * @return Whether or not the specified block can be walked on */ static boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { - Optional canWalkOn = canWalkOnBlockState(state); - if (canWalkOn.isPresent()) { - return canWalkOn.get(); + Ternary canWalkOn = canWalkOnBlockState(state); + if (canWalkOn == YES) { + return true; + } + if (canWalkOn == NO) { + return false; } return canWalkOnPosition(bsi, x, y, z, state); } - static Optional canWalkOnBlockState(IBlockState state) { + static Ternary canWalkOnBlockState(IBlockState state) { Block block = state.getBlock(); if (block == Blocks.AIR || block == Blocks.MAGMA) { return NO; diff --git a/src/main/java/baritone/pathing/precompute/PrecomputedData.java b/src/main/java/baritone/pathing/precompute/PrecomputedData.java index 3ca2c466..5b5bbc52 100644 --- a/src/main/java/baritone/pathing/precompute/PrecomputedData.java +++ b/src/main/java/baritone/pathing/precompute/PrecomputedData.java @@ -22,7 +22,8 @@ import baritone.utils.BlockStateInterface; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; -import java.util.Optional; +import static baritone.pathing.precompute.Ternary.MAYBE; +import static baritone.pathing.precompute.Ternary.YES; public class PrecomputedData { // TODO add isFullyPassable @@ -37,21 +38,19 @@ public class PrecomputedData { // TODO add isFullyPassable private int fillData(int id, IBlockState state) { int blockData = 0; - Optional canWalkOnState = MovementHelper.canWalkOnBlockState(state); - if (canWalkOnState.isPresent()) { - if (canWalkOnState.get()) { - blockData |= canWalkOnMask; - } - } else { + Ternary canWalkOnState = MovementHelper.canWalkOnBlockState(state); + if (canWalkOnState == YES) { + blockData |= canWalkOnMask; + } + if (canWalkOnState == MAYBE) { blockData |= canWalkOnSpecialMask; } - Optional canWalkThroughState = MovementHelper.canWalkThroughBlockState(state); - if (canWalkThroughState.isPresent()) { - if (canWalkThroughState.get()) { - blockData |= canWalkThroughMask; - } - } else { + Ternary canWalkThroughState = MovementHelper.canWalkThroughBlockState(state); + if (canWalkThroughState == YES) { + blockData |= canWalkThroughMask; + } + if (canWalkOnState == MAYBE) { blockData |= canWalkThroughSpecialMask; } diff --git a/src/main/java/baritone/pathing/precompute/Ternary.java b/src/main/java/baritone/pathing/precompute/Ternary.java new file mode 100644 index 00000000..d4d8424e --- /dev/null +++ b/src/main/java/baritone/pathing/precompute/Ternary.java @@ -0,0 +1,22 @@ +/* + * 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.pathing.precompute; + +public enum Ternary { + YES, MAYBE, NO +} From 0587223da8aa6559fee32e4636c4a6d1e9e5f4d9 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Thu, 14 Jul 2022 22:02:19 -0700 Subject: [PATCH 21/23] better constants --- .../pathing/precompute/PrecomputedData.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/java/baritone/pathing/precompute/PrecomputedData.java b/src/main/java/baritone/pathing/precompute/PrecomputedData.java index 5b5bbc52..72eb575b 100644 --- a/src/main/java/baritone/pathing/precompute/PrecomputedData.java +++ b/src/main/java/baritone/pathing/precompute/PrecomputedData.java @@ -29,32 +29,32 @@ public class PrecomputedData { // TODO add isFullyPassable private final int[] data = new int[Block.BLOCK_STATE_IDS.size()]; - private final int completedMask = 1 << 0; - private final int canWalkOnMask = 1 << 1; - private final int canWalkOnSpecialMask = 1 << 2; - private final int canWalkThroughMask = 1 << 3; - private final int canWalkThroughSpecialMask = 1 << 4; + private static final int COMPLETED_MASK = 1 << 0; + private static final int CAN_WALK_ON_MASK = 1 << 1; + private static final int CAN_WALK_ON_SPECIAL_MASK = 1 << 2; + private static final int CAN_WALK_THROUGH_MASK = 1 << 3; + private static final int CAN_WALK_THROUGH_SPECIAL_MASK = 1 << 4; private int fillData(int id, IBlockState state) { int blockData = 0; Ternary canWalkOnState = MovementHelper.canWalkOnBlockState(state); if (canWalkOnState == YES) { - blockData |= canWalkOnMask; + blockData |= CAN_WALK_ON_MASK; } if (canWalkOnState == MAYBE) { - blockData |= canWalkOnSpecialMask; + blockData |= CAN_WALK_ON_SPECIAL_MASK; } Ternary canWalkThroughState = MovementHelper.canWalkThroughBlockState(state); if (canWalkThroughState == YES) { - blockData |= canWalkThroughMask; + blockData |= CAN_WALK_THROUGH_MASK; } if (canWalkOnState == MAYBE) { - blockData |= canWalkThroughSpecialMask; + blockData |= CAN_WALK_THROUGH_SPECIAL_MASK; } - blockData |= completedMask; + blockData |= COMPLETED_MASK; data[id] = blockData; // in theory, this is thread "safe" because every thread should compute the exact same int to write? return blockData; @@ -64,14 +64,14 @@ public class PrecomputedData { // TODO add isFullyPassable int id = Block.BLOCK_STATE_IDS.get(state); int blockData = data[id]; - if ((blockData & completedMask) == 0) { // we need to fill in the data + if ((blockData & COMPLETED_MASK) == 0) { // we need to fill in the data blockData = fillData(id, state); } - if ((blockData & canWalkOnSpecialMask) != 0) { + if ((blockData & CAN_WALK_ON_SPECIAL_MASK) != 0) { return MovementHelper.canWalkOnPosition(bsi, x, y, z, state); } else { - return (blockData & canWalkOnMask) != 0; + return (blockData & CAN_WALK_ON_MASK) != 0; } } @@ -79,14 +79,14 @@ public class PrecomputedData { // TODO add isFullyPassable int id = Block.BLOCK_STATE_IDS.get(state); int blockData = data[id]; - if ((blockData & completedMask) == 0) { // we need to fill in the data + if ((blockData & COMPLETED_MASK) == 0) { // we need to fill in the data blockData = fillData(id, state); } - if ((blockData & canWalkThroughSpecialMask) != 0) { + if ((blockData & CAN_WALK_THROUGH_SPECIAL_MASK) != 0) { return MovementHelper.canWalkThroughPosition(bsi, x, y, z, state); } else { - return (blockData & canWalkThroughMask) != 0; + return (blockData & CAN_WALK_THROUGH_MASK) != 0; } } } From 658048ff2dcc4892a9124a3194eaa21435e7e9b8 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Thu, 14 Jul 2022 22:11:13 -0700 Subject: [PATCH 22/23] fix snow and tweak others --- .../pathing/movement/MovementHelper.java | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index 3d115d1d..0b6d7e34 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -137,10 +137,8 @@ public interface MovementHelper extends ActionCosts, Helper { } if (block instanceof BlockSnow) { - if (state.getValue(BlockSnow.LAYERS) >= 3) { - return NO; - } - + // snow layers cached as the top layer of a packed chunk have no metadata, we can't make a decision based on their depth here + // it would otherwise make long distance pathing through snowy biomes impossible return MAYBE; } @@ -175,7 +173,18 @@ public interface MovementHelper extends ActionCosts, Helper { return canWalkOn(bsi, x, y - 1, z); } - if (block instanceof BlockSnow) { // TODO see if this case is necessary, shouldn't it also check this somewhere else? + if (block instanceof BlockSnow) { + // if they're cached as a top block, we don't know their metadata + // default to true (mostly because it would otherwise make long distance pathing through snowy biomes impossible) + if (!bsi.worldContainsLoadedChunk(x, z)) { + return true; + } + // the check in BlockSnow.isPassable is layers < 5 + // while actually, we want < 3 because 3 or greater makes it impassable in a 2 high ceiling + if (state.getValue(BlockSnow.LAYERS) >= 3) { + return false; + } + // ok, it's low enough we could walk through it, but is it supported? return canWalkOn(bsi, x, y - 1, z); } @@ -363,10 +372,7 @@ public interface MovementHelper extends ActionCosts, Helper { static Ternary canWalkOnBlockState(IBlockState state) { Block block = state.getBlock(); - if (block == Blocks.AIR || block == Blocks.MAGMA) { - return NO; - } - if (state.isBlockNormalCube()) { + if (state.isBlockNormalCube() && block != Blocks.MAGMA) { return YES; } if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.value)) { // TODO reconsider this @@ -378,17 +384,18 @@ public interface MovementHelper extends ActionCosts, Helper { if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST) { return YES; } - if (isWater(block)) { - return MAYBE; - } - if (Baritone.settings().assumeWalkOnLava.value && MovementHelper.isLava(block)) { - return MAYBE; - } - if (block == Blocks.GLASS || block == Blocks.STAINED_GLASS) { return YES; } - + if (block instanceof BlockStairs) { + return YES; + } + if (isWater(block)) { + return MAYBE; + } + if (MovementHelper.isLava(block) && Baritone.settings().assumeWalkOnLava.value) { + return MAYBE; + } if (block instanceof BlockSlab) { if (!Baritone.settings().allowWalkOnBottomSlab.value) { if (((BlockSlab) block).isDouble()) { @@ -401,11 +408,6 @@ public interface MovementHelper extends ActionCosts, Helper { } return YES; } - - if (block instanceof BlockStairs) { - return YES; - } - return NO; } @@ -427,7 +429,7 @@ public interface MovementHelper extends ActionCosts, Helper { return isWater(up) ^ Baritone.settings().assumeWalkOnWater.value; } - if (Baritone.settings().assumeWalkOnLava.value && MovementHelper.isLava(block) && !MovementHelper.isFlowing(x, y, z, state, bsi)) { + if (MovementHelper.isLava(block) && !MovementHelper.isFlowing(x, y, z, state, bsi) && Baritone.settings().assumeWalkOnLava.value) { // if we get here it means that assumeWalkOnLava must be true, so put it last return true; } From 80a4757242ac7653602ed025169776968b42d387 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Fri, 15 Jul 2022 01:36:01 -0700 Subject: [PATCH 23/23] baritone complies faster if the files are less bytes --- .../java/baritone/pathing/movement/MovementHelper.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index 0b6d7e34..e3fc6a03 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -111,19 +111,15 @@ public interface MovementHelper extends ActionCosts, Helper { static Ternary canWalkThroughBlockState(IBlockState state) { Block block = state.getBlock(); - if (block == Blocks.AIR) { return YES; } - if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL || block == Blocks.COCOA || block instanceof BlockSkull || block instanceof BlockTrapDoor || block == Blocks.END_ROD) { return NO; } - if (Baritone.settings().blocksToAvoid.value.contains(block)) { return NO; } - if (block instanceof BlockDoor || block instanceof BlockFenceGate) { // TODO this assumes that all doors in all mods are openable if (block == Blocks.IRON_DOOR) { @@ -131,17 +127,14 @@ public interface MovementHelper extends ActionCosts, Helper { } return YES; } - if (block == Blocks.CARPET) { return MAYBE; } - if (block instanceof BlockSnow) { // snow layers cached as the top layer of a packed chunk have no metadata, we can't make a decision based on their depth here // it would otherwise make long distance pathing through snowy biomes impossible return MAYBE; } - if (block instanceof BlockLiquid) { if (state.getValue(BlockLiquid.LEVEL) != 0) { return NO; @@ -149,11 +142,9 @@ public interface MovementHelper extends ActionCosts, Helper { return MAYBE; } } - if (block instanceof BlockCauldron) { return NO; } - try { // A dodgy catch-all at the end, for most blocks with default behaviour this will work, however where blocks are special this will error out, and we can handle it when we have this information if (block.isPassable(null, null)) { return YES;