From 43ab4f7d3b114748aec18be299f78e7404c76c64 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 22 Oct 2019 15:58:10 -0500 Subject: [PATCH 1/3] Fix isPassable crash --- .../pathing/movement/MovementHelper.java | 27 ++++++++++--------- .../movement/movements/MovementParkour.java | 16 +++++------ .../baritone/pathing/path/PathExecutor.java | 6 ++--- .../baritone/utils/BlockStateInterface.java | 5 ++++ 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index 725a0876d..9fd1c75f1 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -35,6 +35,7 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; +import net.minecraft.world.IBlockAccess; import java.util.Optional; @@ -132,27 +133,29 @@ public interface MovementHelper extends ActionCosts, Helper { } return block == Blocks.WATER || block == Blocks.FLOWING_WATER; } - // every block that overrides isPassable with anything more complicated than a "return true;" or "return false;" - // has already been accounted for above - // therefore it's safe to not construct a blockpos from our x, y, z ints and instead just pass null - return block.isPassable(null, BlockPos.ORIGIN); + + return block.isPassable(bsi.world, 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) * - * @param context Calculation context to provide block state lookup - * @param x The block's x position - * @param y The block's y position - * @param z The block's z position + * @param bsi Block State Interface to provide block state lookup + * @param x The block's x position + * @param y The block's y position + * @param z The block's z position * @return Whether or not the block at the specified position */ - static boolean fullyPassable(CalculationContext context, int x, int y, int z) { - return fullyPassable(context.get(x, y, z)); + static boolean fullyPassable(BlockStateInterface bsi, int x, int y, int z) { + return fullyPassable(bsi.world, bsi.isPassableBlockPos.setPos(x, y, z), bsi.get0(x, y, z)); } - static boolean fullyPassable(IBlockState state) { + static boolean fullyPassable(IPlayerContext ctx, BlockPos pos) { + return fullyPassable(ctx.world(), pos, ctx.world().getBlockState(pos)); + } + + static boolean fullyPassable(IBlockAccess world, BlockPos pos, IBlockState state) { Block block = state.getBlock(); if (block == Blocks.AIR) { // early return for most common case return true; @@ -174,7 +177,7 @@ public interface MovementHelper extends ActionCosts, Helper { return false; } // door, fence gate, liquid, trapdoor have been accounted for, nothing else uses the world or pos parameters - return block.isPassable(null, null); + return block.isPassable(world, pos); } static boolean isReplaceable(int x, int y, int z, IBlockState state, BlockStateInterface bsi) { diff --git a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java index eb0322102..7475182c9 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java @@ -69,7 +69,7 @@ public class MovementParkour extends Movement { int xDiff = dir.getXOffset(); int zDiff = dir.getZOffset(); - if (!MovementHelper.fullyPassable(context, x + xDiff, y, z + zDiff)) { + if (!MovementHelper.fullyPassable(context.bsi, x + xDiff, y, z + zDiff)) { // most common case at the top -- the adjacent block isn't air return; } @@ -81,13 +81,13 @@ public class MovementParkour extends Movement { if (MovementHelper.avoidWalkingInto(adj.getBlock()) && adj.getBlock() != Blocks.WATER && adj.getBlock() != Blocks.FLOWING_WATER) { // magma sucks return; } - if (!MovementHelper.fullyPassable(context, x + xDiff, y + 1, z + zDiff)) { + if (!MovementHelper.fullyPassable(context.bsi, x + xDiff, y + 1, z + zDiff)) { return; } - if (!MovementHelper.fullyPassable(context, x + xDiff, y + 2, z + zDiff)) { + if (!MovementHelper.fullyPassable(context.bsi, x + xDiff, y + 2, z + zDiff)) { return; } - if (!MovementHelper.fullyPassable(context, x, y + 2, z)) { + if (!MovementHelper.fullyPassable(context.bsi, x, y + 2, z)) { return; } IBlockState standingOn = context.get(x, y - 1, z); @@ -107,14 +107,14 @@ public class MovementParkour extends Movement { for (int i = 2; i <= maxJump; i++) { int destX = x + xDiff * i; int destZ = z + zDiff * i; - if (!MovementHelper.fullyPassable(context, destX, y + 1, destZ)) { + if (!MovementHelper.fullyPassable(context.bsi, destX, y + 1, destZ)) { return; } - if (!MovementHelper.fullyPassable(context, destX, y + 2, destZ)) { + if (!MovementHelper.fullyPassable(context.bsi, destX, y + 2, destZ)) { return; } IBlockState destInto = context.bsi.get0(destX, y, destZ); - if (!MovementHelper.fullyPassable(destInto)) { + if (!MovementHelper.fullyPassable(context.bsi.world, 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)) { res.x = destX; res.y = y + 1; @@ -134,7 +134,7 @@ public class MovementParkour extends Movement { } return; } - if (!MovementHelper.fullyPassable(context, destX, y + 3, destZ)) { + if (!MovementHelper.fullyPassable(context.bsi, destX, y + 3, destZ)) { return; } } diff --git a/src/main/java/baritone/pathing/path/PathExecutor.java b/src/main/java/baritone/pathing/path/PathExecutor.java index 97bee4245..7e4f76a3b 100644 --- a/src/main/java/baritone/pathing/path/PathExecutor.java +++ b/src/main/java/baritone/pathing/path/PathExecutor.java @@ -466,7 +466,7 @@ public class PathExecutor implements IPathExecutor, Helper { } for (int y = next.getDest().y; y <= movement.getSrc().y + 1; y++) { BlockPos chk = new BlockPos(next.getDest().x, y, next.getDest().z); - if (!MovementHelper.fullyPassable(ctx.world().getBlockState(chk))) { + if (!MovementHelper.fullyPassable(ctx, chk)) { break outer; } } @@ -491,7 +491,7 @@ public class PathExecutor implements IPathExecutor, Helper { } // we are centered BlockPos headBonk = current.getSrc().subtract(current.getDirection()).up(2); - if (MovementHelper.fullyPassable(ctx.world().getBlockState(headBonk))) { + if (MovementHelper.fullyPassable(ctx, headBonk)) { return true; } // wait 0.3 @@ -524,7 +524,7 @@ public class PathExecutor implements IPathExecutor, Helper { if (x == 1) { chk = chk.add(current.getDirection()); } - if (!MovementHelper.fullyPassable(ctx.world().getBlockState(chk))) { + if (!MovementHelper.fullyPassable(ctx, chk)) { return false; } } diff --git a/src/main/java/baritone/utils/BlockStateInterface.java b/src/main/java/baritone/utils/BlockStateInterface.java index 84bdce5fe..bbe5a17ee 100644 --- a/src/main/java/baritone/utils/BlockStateInterface.java +++ b/src/main/java/baritone/utils/BlockStateInterface.java @@ -30,6 +30,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; @@ -42,6 +43,8 @@ public class BlockStateInterface { private final Long2ObjectMap loadedChunks; private final WorldData worldData; + public final IBlockAccess world; + public final BlockPos.MutableBlockPos isPassableBlockPos; private Chunk prev = null; private CachedRegion prevCached = null; @@ -59,6 +62,7 @@ public class BlockStateInterface { } public BlockStateInterface(World world, WorldData worldData, boolean copyLoadedChunks) { + this.world = world; this.worldData = worldData; Long2ObjectMap worldLoaded = ((IChunkProviderClient) world.getChunkProvider()).loadedChunks(); if (copyLoadedChunks) { @@ -70,6 +74,7 @@ public class BlockStateInterface { if (!Minecraft.getMinecraft().isCallingFromMinecraftThread()) { throw new IllegalStateException(); } + this.isPassableBlockPos = new BlockPos.MutableBlockPos(); } public boolean worldContainsLoadedChunk(int blockX, int blockZ) { From 5201d39adf1ef1709ed35f3d61245b6364f7cf6f Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 24 Oct 2019 15:20:23 -0500 Subject: [PATCH 2/3] Retain old method signature --- .../pathing/movement/MovementHelper.java | 16 ++++++++++------ .../movement/movements/MovementParkour.java | 14 +++++++------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index 9fd1c75f1..62a96a181 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -141,14 +141,18 @@ public interface MovementHelper extends ActionCosts, Helper { * 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) * - * @param bsi Block State Interface to provide block state lookup - * @param x The block's x position - * @param y The block's y position - * @param z The block's z position + * @param context Calculation context to provide block state lookup + * @param x The block's x position + * @param y The block's y position + * @param z The block's z position * @return Whether or not the block at the specified position */ - static boolean fullyPassable(BlockStateInterface bsi, int x, int y, int z) { - return fullyPassable(bsi.world, bsi.isPassableBlockPos.setPos(x, y, z), bsi.get0(x, y, z)); + static boolean fullyPassable(CalculationContext context, int x, int y, int z) { + return fullyPassable( + context.bsi.world, + context.bsi.isPassableBlockPos.setPos(x, y, z), + context.bsi.get0(x, y, z) + ); } static boolean fullyPassable(IPlayerContext ctx, BlockPos pos) { diff --git a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java index 7475182c9..0477c85c0 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java @@ -69,7 +69,7 @@ public class MovementParkour extends Movement { int xDiff = dir.getXOffset(); int zDiff = dir.getZOffset(); - if (!MovementHelper.fullyPassable(context.bsi, x + xDiff, y, z + zDiff)) { + if (!MovementHelper.fullyPassable(context, x + xDiff, y, z + zDiff)) { // most common case at the top -- the adjacent block isn't air return; } @@ -81,13 +81,13 @@ public class MovementParkour extends Movement { if (MovementHelper.avoidWalkingInto(adj.getBlock()) && adj.getBlock() != Blocks.WATER && adj.getBlock() != Blocks.FLOWING_WATER) { // magma sucks return; } - if (!MovementHelper.fullyPassable(context.bsi, x + xDiff, y + 1, z + zDiff)) { + if (!MovementHelper.fullyPassable(context, x + xDiff, y + 1, z + zDiff)) { return; } - if (!MovementHelper.fullyPassable(context.bsi, x + xDiff, y + 2, z + zDiff)) { + if (!MovementHelper.fullyPassable(context, x + xDiff, y + 2, z + zDiff)) { return; } - if (!MovementHelper.fullyPassable(context.bsi, x, y + 2, z)) { + if (!MovementHelper.fullyPassable(context, x, y + 2, z)) { return; } IBlockState standingOn = context.get(x, y - 1, z); @@ -107,10 +107,10 @@ public class MovementParkour extends Movement { for (int i = 2; i <= maxJump; i++) { int destX = x + xDiff * i; int destZ = z + zDiff * i; - if (!MovementHelper.fullyPassable(context.bsi, destX, y + 1, destZ)) { + if (!MovementHelper.fullyPassable(context, destX, y + 1, destZ)) { return; } - if (!MovementHelper.fullyPassable(context.bsi, destX, y + 2, destZ)) { + if (!MovementHelper.fullyPassable(context, destX, y + 2, destZ)) { return; } IBlockState destInto = context.bsi.get0(destX, y, destZ); @@ -134,7 +134,7 @@ public class MovementParkour extends Movement { } return; } - if (!MovementHelper.fullyPassable(context.bsi, destX, y + 3, destZ)) { + if (!MovementHelper.fullyPassable(context, destX, y + 3, destZ)) { return; } } From 7e3a2d3c0a676ef955c1b345b1a789d51e8c6834 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 5 Nov 2019 18:17:10 -0600 Subject: [PATCH 3/3] Create a BlockStateInterface specialized IBlockAccess wrapper --- .../pathing/movement/MovementHelper.java | 8 +- .../movement/movements/MovementParkour.java | 2 +- .../baritone/utils/BlockStateInterface.java | 4 +- .../BlockStateInterfaceAccessWrapper.java | 80 +++++++++++++++++++ 4 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 src/main/java/baritone/utils/BlockStateInterfaceAccessWrapper.java diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index 62a96a181..31a1de7a6 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -134,7 +134,7 @@ public interface MovementHelper extends ActionCosts, Helper { return block == Blocks.WATER || block == Blocks.FLOWING_WATER; } - return block.isPassable(bsi.world, bsi.isPassableBlockPos.setPos(x, y, z)); + return block.isPassable(bsi.access, bsi.isPassableBlockPos.setPos(x, y, z)); } /** @@ -149,7 +149,7 @@ public interface MovementHelper extends ActionCosts, Helper { */ static boolean fullyPassable(CalculationContext context, int x, int y, int z) { return fullyPassable( - context.bsi.world, + context.bsi.access, context.bsi.isPassableBlockPos.setPos(x, y, z), context.bsi.get0(x, y, z) ); @@ -159,7 +159,7 @@ public interface MovementHelper extends ActionCosts, Helper { return fullyPassable(ctx.world(), pos, ctx.world().getBlockState(pos)); } - static boolean fullyPassable(IBlockAccess world, BlockPos pos, IBlockState state) { + static boolean fullyPassable(IBlockAccess access, BlockPos pos, IBlockState state) { Block block = state.getBlock(); if (block == Blocks.AIR) { // early return for most common case return true; @@ -181,7 +181,7 @@ public interface MovementHelper extends ActionCosts, Helper { return false; } // door, fence gate, liquid, trapdoor have been accounted for, nothing else uses the world or pos parameters - return block.isPassable(world, pos); + return block.isPassable(access, pos); } static boolean isReplaceable(int x, int y, int z, IBlockState state, BlockStateInterface bsi) { diff --git a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java index 0477c85c0..3d3426da2 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java @@ -114,7 +114,7 @@ public class MovementParkour extends Movement { return; } IBlockState destInto = context.bsi.get0(destX, y, destZ); - if (!MovementHelper.fullyPassable(context.bsi.world, context.bsi.isPassableBlockPos.setPos(destX, y, destZ), destInto)) { + 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)) { res.x = destX; res.y = y + 1; diff --git a/src/main/java/baritone/utils/BlockStateInterface.java b/src/main/java/baritone/utils/BlockStateInterface.java index bbe5a17ee..4f5f26899 100644 --- a/src/main/java/baritone/utils/BlockStateInterface.java +++ b/src/main/java/baritone/utils/BlockStateInterface.java @@ -43,8 +43,9 @@ public class BlockStateInterface { private final Long2ObjectMap loadedChunks; private final WorldData worldData; - public final IBlockAccess world; + protected final IBlockAccess world; public final BlockPos.MutableBlockPos isPassableBlockPos; + public final IBlockAccess access; private Chunk prev = null; private CachedRegion prevCached = null; @@ -75,6 +76,7 @@ public class BlockStateInterface { throw new IllegalStateException(); } this.isPassableBlockPos = new BlockPos.MutableBlockPos(); + this.access = new BlockStateInterfaceAccessWrapper(this); } public boolean worldContainsLoadedChunk(int blockX, int blockZ) { diff --git a/src/main/java/baritone/utils/BlockStateInterfaceAccessWrapper.java b/src/main/java/baritone/utils/BlockStateInterfaceAccessWrapper.java new file mode 100644 index 000000000..6ce70193f --- /dev/null +++ b/src/main/java/baritone/utils/BlockStateInterfaceAccessWrapper.java @@ -0,0 +1,80 @@ +/* + * 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.utils; + +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.WorldType; +import net.minecraft.world.biome.Biome; + +import javax.annotation.Nullable; + +/** + * @author Brady + * @since 11/5/2019 + */ +@SuppressWarnings("NullableProblems") +public final class BlockStateInterfaceAccessWrapper implements IBlockAccess { + + private final BlockStateInterface bsi; + + BlockStateInterfaceAccessWrapper(BlockStateInterface bsi) { + this.bsi = bsi; + } + + @Nullable + @Override + public TileEntity getTileEntity(BlockPos pos) { + throw new UnsupportedOperationException("getTileEntity not supported by BlockStateInterfaceAccessWrapper"); + } + + @Override + public int getCombinedLight(BlockPos pos, int lightValue) { + throw new UnsupportedOperationException("getCombinedLight not supported by BlockStateInterfaceAccessWrapper"); + } + + @Override + public IBlockState getBlockState(BlockPos pos) { + // BlockStateInterface#get0(BlockPos) btfo! + return this.bsi.get0(pos.getX(), pos.getY(), pos.getZ()); + } + + @Override + public boolean isAirBlock(BlockPos pos) { + return this.bsi.get0(pos.getX(), pos.getY(), pos.getZ()).getMaterial() == Material.AIR; + } + + @Override + public Biome getBiome(BlockPos pos) { + throw new UnsupportedOperationException("getBiome not supported by BlockStateInterfaceAccessWrapper"); + } + + @Override + public int getStrongPower(BlockPos pos, EnumFacing direction) { + throw new UnsupportedOperationException("getStrongPower not supported by BlockStateInterfaceAccessWrapper"); + } + + @Override + public WorldType getWorldType() { + return this.bsi.world.getWorldType(); + } +}