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); - } -}