getAllStates() {
- return Collections.unmodifiableList(Arrays.asList(PER_STATE));
- }
+ public final PlaceAgainstData[] placeAgainstMe; // array because of fixed size with obvious indexing (no more than one per face, so, index per face)
public BlockStateCachedData(BlockStateCachedDataBuilder builder) {
builder.sanityCheck();
@@ -72,9 +50,9 @@ public final class BlockStateCachedData {
}
this.mustSneakWhenPlacingAgainstMe = builder.isMustSneakWhenPlacingAgainstMe();
- this.options = Collections.unmodifiableList(builder.howCanIBePlaced());
+ this.placeMe = Collections.unmodifiableList(builder.howCanIBePlaced());
- this.againstMe = builder.placeAgainstMe();
+ this.placeAgainstMe = builder.placeAgainstMe();
}
public int collisionHeightBlips() {
@@ -88,12 +66,12 @@ public final class BlockStateCachedData {
if (Main.fakePlacementForPerformanceTesting) {
return Main.RAND.nextInt(10) < 8;
}
- PlaceAgainstData against = againstMe[placement.against.oppositeIndex];
+ PlaceAgainstData against = againstMe(placement);
return against != null && possible(placement, against);
}
public PlaceAgainstData againstMe(BlockStatePlacementOption placement) {
- return againstMe[placement.against.oppositeIndex];
+ return placeAgainstMe[placement.against.oppositeIndex];
}
public static boolean possible(BlockStatePlacementOption placement, PlaceAgainstData against) {
diff --git a/src/main/java/baritone/builder/BlockStateCachedDataBuilder.java b/src/main/java/baritone/builder/BlockStateCachedDataBuilder.java
index c261e444a..88bd3a173 100644
--- a/src/main/java/baritone/builder/BlockStateCachedDataBuilder.java
+++ b/src/main/java/baritone/builder/BlockStateCachedDataBuilder.java
@@ -44,7 +44,12 @@ public class BlockStateCachedDataBuilder {
private Face playerMustBeHorizontalFacingInOrderToPlaceMe;
private Integer collisionHeightBlips;
private Face canOnlyPlaceAgainst;
- private boolean fakeLessThanFullHeight; // snow layers and soul sand
+ /**
+ * Blocks that have a collision height lower than their placement bounding box height.
+ * aka snow layers and soul sand.
+ * e.g. soul sand only collides with the player 0.875 high, but the BLOCK is 1.000 high, i.e. you can place against it at height 0.9 even though the player stands at height 0.875
+ */
+ private boolean fakeLessThanFullHeight;
private boolean placementLogicNotImplementedYet;
private Face playerMustBeEntityFacingInOrderToPlaceMe;
diff --git a/src/main/java/baritone/builder/BlockStatePlacementOption.java b/src/main/java/baritone/builder/BlockStatePlacementOption.java
index a4c5d2685..f3c65bbaf 100644
--- a/src/main/java/baritone/builder/BlockStatePlacementOption.java
+++ b/src/main/java/baritone/builder/BlockStatePlacementOption.java
@@ -61,9 +61,9 @@ public class BlockStatePlacementOption {
/**
* This value must be greater than the face projections.
*
- * Otherwise certain stair placements would not work. This is verified in this class's sanityCheck.
+ * Otherwise certain stair placements would not work. This is verified in the test
*/
- private static final double LOOSE_CENTER_DISTANCE = 0.15;
+ public static final double LOOSE_CENTER_DISTANCE = 0.15;
public List computeTraceOptions(PlaceAgainstData placingAgainst, int playerSupportingX, int playerFeetBlips, int playerSupportingZ, PlayerVantage vantage, double blockReachDistance) {
if (!BlockStateCachedData.possible(this, placingAgainst)) {
@@ -126,7 +126,7 @@ public class BlockStatePlacementOption {
} else if (hit.y == 0.1) {
return half == Half.BOTTOM;
} else if (hit.y == 0.5) {
- return false;
+ return false; // ambiguous, so force it to pick either down or up
} else if (hit.y == 0.9) {
return half == Half.TOP;
} else {
@@ -153,7 +153,7 @@ public class BlockStatePlacementOption {
}
Face entFace = playerMustBeEntityFacing.get();
// see EnumFacing.getDirectionFromEntityLiving
- double dx = Math.abs(eye.x - 0.5);
+ double dx = Math.abs(eye.x - 0.5); // TODO this is changed between 1.12 and 1.19, in 1.19 this should be eye.x-hit.x
double dz = Math.abs(eye.z - 0.5);
if (dx < 2 - ENTITY_FACING_TOLERANCE && dz < 2 - ENTITY_FACING_TOLERANCE) { // < 1.99
if (eye.y < 0) { // eye below placement level = it will be facing down, so this is only okay if we want that
@@ -199,17 +199,6 @@ public class BlockStatePlacementOption {
}
}
- static {
- for (int i = 0; i < Face.OPTS.size(); i++) {
- if (Face.OPTS.indexOf(Face.OPTS.get(i)) != i) {
- throw new IllegalStateException();
- }
- if (Face.OPTS.get(i).map(face -> face.index).orElse(Face.NUM_FACES) != i) {
- throw new IllegalStateException();
- }
- }
- }
-
private void validate(Face against, Half half, Optional playerMustBeHorizontalFacing, Optional playerMustBeEntityFacing) {
if (playerMustBeEntityFacing.isPresent() && playerMustBeHorizontalFacing.isPresent()) {
throw new IllegalStateException();
@@ -238,53 +227,6 @@ public class BlockStatePlacementOption {
});
}
- static {
- if (Main.DEBUG) {
- sanityCheck();
- }
- }
-
- public static void sanityCheck() {
- // standing at 1,0,0
- // block to be placed at 0,0,0
- // placing against 0,0,-1
-
- // eye is at 1, 1.62, 0
- // north or west
-
- StringBuilder sanity = new StringBuilder();
- for (PlayerVantage vantage : new PlayerVantage[]{PlayerVantage.STRICT_CENTER, PlayerVantage.LOOSE_CENTER}) {
- for (Face playerFacing : new Face[]{Face.NORTH, Face.EAST, Face.WEST}) {
- sanity.append(vantage).append(playerFacing);
- List traces = BlockStatePlacementOption.get(Face.NORTH, Half.BOTTOM, Optional.of(playerFacing), Optional.empty()).computeTraceOptions(new PlaceAgainstData(Face.SOUTH, Half.EITHER, false), 1, 0, 0, vantage, 4);
- sanity.append(traces.size());
- sanity.append(" ");
- if (!traces.isEmpty()) {
- for (double d : new double[]{traces.get(0).playerEye.x, traces.get(0).playerEye.z}) {
- double base = d > 1 ? 1.5 : 0.5;
- boolean a = d == base - LOOSE_CENTER_DISTANCE;
- boolean b = d == base;
- boolean c = d == base + LOOSE_CENTER_DISTANCE;
- if (!a && !b && !c) {
- throw new IllegalStateException("Wrong " + d);
- }
- sanity.append(a).append(" ").append(b).append(" ").append(c).append(" ");
- }
- }
- sanity.append(traces.stream().mapToDouble(Raytracer.Raytrace::centerDistApprox).distinct().count());
- sanity.append(";");
- }
- }
-
- String res = sanity.toString();
- String should = "STRICT_CENTERNORTH0 0;STRICT_CENTEREAST0 0;STRICT_CENTERWEST3 false true false false true false 1;LOOSE_CENTERNORTH2 true false false false true false 1;LOOSE_CENTEREAST0 0;LOOSE_CENTERWEST13 false true false false true false 2;";
- if (!res.equals(should)) {
- System.out.println(res);
- System.out.println(should);
- throw new IllegalStateException(res);
- }
- }
-
private static List sanityCheckTraces(List traces) {
if (Main.DEBUG && traces.stream().mapToDouble(Raytracer.Raytrace::centerDistApprox).distinct().count() > 2) {
throw new IllegalStateException();
diff --git a/src/main/java/baritone/builder/CuboidBounds.java b/src/main/java/baritone/builder/CuboidBounds.java
index b4e9ae382..fd0761bd2 100644
--- a/src/main/java/baritone/builder/CuboidBounds.java
+++ b/src/main/java/baritone/builder/CuboidBounds.java
@@ -129,7 +129,7 @@ public class CuboidBounds implements Bounds {
}
}
- private void sanityCheck() {
+ public void sanityCheck() {
if (sizeY > 256) {
throw new IllegalStateException();
}
diff --git a/src/main/java/baritone/builder/Face.java b/src/main/java/baritone/builder/Face.java
index 5f74e1e89..1866ca7da 100644
--- a/src/main/java/baritone/builder/Face.java
+++ b/src/main/java/baritone/builder/Face.java
@@ -63,10 +63,6 @@ public enum Face {
return EnumFacing.byIndex(index);
}
- public static Face fromMC(EnumFacing facing) {
- return VALUES[facing.getIndex()];
- }
-
public final Face opposite() {
return VALUES[oppositeIndex];
}
diff --git a/src/main/java/baritone/builder/FakeStates.java b/src/main/java/baritone/builder/FakeStates.java
new file mode 100644
index 000000000..4324c4321
--- /dev/null
+++ b/src/main/java/baritone/builder/FakeStates.java
@@ -0,0 +1,47 @@
+/*
+ * 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.builder;
+
+/**
+ * There will be a BlockStateCachedData for every IBlockState in the game, yes.
+ *
+ * But, we need some additional BlockStateCachedDatas. For example, we need one that represents hypothetical scaffolding, and another for air, for properly computing place order dependency graphs. Some other places need a placeholder for out of bounds.
+ *
+ * We could just say that scaffolding is always, like, dirt, or something. But that would be inelegant.
+ *
+ * And beyond the needs at runtime, unit tests shouldn't need to bootstrap and boot up the entire Minecraft game. So, let's have some fake BlockStateCachedData for testing purposes too!
+ */
+public class FakeStates {
+ // the three aformentioned placeholders for runtime
+ public static final BlockStateCachedData SCAFFOLDING = new BlockStateCachedData(new BlockStateCachedDataBuilder().collidesWithPlayer(true).fullyWalkableTop().collisionHeight(1).canPlaceAgainstMe());
+ public static final BlockStateCachedData AIR = new BlockStateCachedData(new BlockStateCachedDataBuilder().setAir());
+ public static final BlockStateCachedData OUT_OF_BOUNDS = new BlockStateCachedData(new BlockStateCachedDataBuilder().collidesWithPlayer(true).collisionHeight(1));
+
+ // and some for testing
+ public static final BlockStateCachedData[] BY_HEIGHT;
+
+ static {
+ BY_HEIGHT = new BlockStateCachedData[Blip.FULL_BLOCK + 1];
+ for (int height = 1; height <= Blip.FULL_BLOCK; height++) {
+ BY_HEIGHT[height] = new BlockStateCachedData(new BlockStateCachedDataBuilder().collidesWithPlayer(true).fullyWalkableTop().collisionHeight(height * Blip.RATIO));
+ }
+ BY_HEIGHT[0] = AIR;
+ }
+
+ // probably more will go here such as for making sure that slabs and stairs work right (like there'll be a fake slab and a fake stair i guess?)
+}
diff --git a/src/main/java/baritone/builder/GreedySolver.java b/src/main/java/baritone/builder/GreedySolver.java
index e33749dcc..7391fee0d 100644
--- a/src/main/java/baritone/builder/GreedySolver.java
+++ b/src/main/java/baritone/builder/GreedySolver.java
@@ -82,7 +82,7 @@ public class GreedySolver {
int relativeY = blipsWithinVoxel + Blip.FULL_BLOCK * (BetterBlockPos.YfromLong(vpos) - BetterBlockPos.YfromLong(blockGoesAt));
int relativeZ = BetterBlockPos.ZfromLong(vpos) - BetterBlockPos.ZfromLong(blockGoesAt);
BlockStateCachedData blockBeingPlaced = engineInput.graph.data(blockGoesAt);
- for (BlockStatePlacementOption option : blockBeingPlaced.options) {
+ for (BlockStatePlacementOption option : blockBeingPlaced.placeMe) {
long maybePlaceAgainst = option.against.offset(blockGoesAt);
if (!bounds.inRangePos(maybePlaceAgainst)) {
continue;
diff --git a/src/main/java/baritone/builder/Main.java b/src/main/java/baritone/builder/Main.java
index 00e71e69b..385f1c651 100644
--- a/src/main/java/baritone/builder/Main.java
+++ b/src/main/java/baritone/builder/Main.java
@@ -45,7 +45,7 @@ public class Main {
public static final boolean fakePlacementForPerformanceTesting = false;
- public static final IBlockStateDataProvider DATA_PROVIDER = new VanillaBlockStateDataProvider();
+ public static final BlockData DATA = new BlockData(new VanillaBlockStateDataProvider());
public static final Random RAND = new Random(5021);
@@ -122,7 +122,7 @@ public class Main {
Arrays.fill(arr2, based);
}
}*/
- PackedBlockStateCuboid states = new PackedBlockStateCuboid(test);
+ PackedBlockStateCuboid states = new PackedBlockStateCuboid(test, DATA);
PlaceOrderDependencyGraph graph = new PlaceOrderDependencyGraph(states);
long aa = System.currentTimeMillis();
/*DependencyGraphAnalyzer.prevalidate(graph);
@@ -175,12 +175,6 @@ public class Main {
.collect(Collectors.toList()).parallelStream()
.forEach(x -> System.out.println(x + ""));
}
- {
- BlockStateCachedData.get(0);
- }
- {
- BlockStatePlacementOption.sanityCheck();
- }
for (int aaaa = 0; aaaa < 0; aaaa++) {
/*Raytracer.raytraceMode++;
Raytracer.raytraceMode %= 3;*/
@@ -452,7 +446,7 @@ Branchy took 124ms
}
}
};
- PackedBlockStateCuboid states = new PackedBlockStateCuboid(test);
+ PackedBlockStateCuboid states = new PackedBlockStateCuboid(test, DATA);
PlaceOrderDependencyGraph graph = new PlaceOrderDependencyGraph(states);
System.out.println("N " + Face.NORTH.z);
System.out.println("S " + Face.SOUTH.z);
diff --git a/src/main/java/baritone/builder/NavigableSurface.java b/src/main/java/baritone/builder/NavigableSurface.java
index f5561c162..96e5d95d8 100644
--- a/src/main/java/baritone/builder/NavigableSurface.java
+++ b/src/main/java/baritone/builder/NavigableSurface.java
@@ -34,7 +34,7 @@ public class NavigableSurface {
public NavigableSurface(int x, int y, int z) {
this.bounds = new CuboidBounds(x, y, z);
this.blocks = new BlockStateCachedData[bounds.volume()];
- Arrays.fill(blocks, BlockStateCachedData.AIR);
+ Arrays.fill(blocks, FakeStates.AIR);
this.connGraph = new ConnGraph(Attachment::new);
}
@@ -88,7 +88,7 @@ public class NavigableSurface {
if (previously == place) {
return; // this is already the case
}
- blocks[bounds.toIndex(where.x, where.y, where.z)] = place ? BlockStateCachedData.SCAFFOLDING : BlockStateCachedData.AIR;
+ blocks[bounds.toIndex(where.x, where.y, where.z)] = place ? FakeStates.SCAFFOLDING : FakeStates.AIR;
// first let's set some vertex info for where the player can and cannot stand
for (int dy = -1; dy <= 1; dy++) {
BetterBlockPos couldHaveChanged = where.up(dy);
diff --git a/src/main/java/baritone/builder/PackedBlockStateCuboid.java b/src/main/java/baritone/builder/PackedBlockStateCuboid.java
index ca6dc9a7e..1eb5e0221 100644
--- a/src/main/java/baritone/builder/PackedBlockStateCuboid.java
+++ b/src/main/java/baritone/builder/PackedBlockStateCuboid.java
@@ -20,15 +20,32 @@ package baritone.builder;
public class PackedBlockStateCuboid {
public final Bounds bounds;
- private final int[] states;
+ private final BlockStateCachedData[] states;
+ private final BlockStateCachedData[] statesWithScaffolding;
- public PackedBlockStateCuboid(int[][][] blockStates) {
- this.bounds = new CuboidBounds(blockStates.length, blockStates[0].length, blockStates[0][0].length);
- this.states = new int[bounds.volume()];
- bounds.forEach((x, y, z) -> states[bounds.toIndex(x, y, z)] = blockStates[x][y][z]);
+ private PackedBlockStateCuboid(int x, int y, int z) {
+ this.bounds = new CuboidBounds(x, y, z);
+ this.states = new BlockStateCachedData[bounds.volume()];
+ this.statesWithScaffolding = new BlockStateCachedData[bounds.volume()];
}
- public int get(int index) {
+ public PackedBlockStateCuboid(int[][][] blockStates, BlockData data) {
+ this(blockStates.length, blockStates[0].length, blockStates[0][0].length);
+ bounds.forEach((x, y, z) -> states[bounds.toIndex(x, y, z)] = data.get(blockStates[x][y][z]));
+ genScaffoldVariant();
+ }
+
+ private void genScaffoldVariant() {
+ for (int i = 0; i < states.length; i++) {
+ statesWithScaffolding[i] = states[i].isAir ? FakeStates.SCAFFOLDING : states[i];
+ }
+ }
+
+ public BlockStateCachedData get(int index) {
return states[index];
}
+
+ public BlockStateCachedData getScaffoldingVariant(int index) {
+ return statesWithScaffolding[index];
+ }
}
diff --git a/src/main/java/baritone/builder/PlaceOptions.java b/src/main/java/baritone/builder/PlaceOptions.java
index 11bcc390d..141111ff3 100644
--- a/src/main/java/baritone/builder/PlaceOptions.java
+++ b/src/main/java/baritone/builder/PlaceOptions.java
@@ -38,7 +38,7 @@ public class PlaceOptions {
if (overlay.outgoingEdge(blockPos, againstToPlace)) {
long placingBlockAt = againstToPlace.offset(blockPos);
BlockStateCachedData blockBeingPlaced = overlay.data(placingBlockAt);
- for (BlockStatePlacementOption option : blockBeingPlaced.options) {
+ for (BlockStatePlacementOption option : blockBeingPlaced.placeMe) {
if (option.against == placeToAgainst) {
PlaceAgainstData againstData = placingAgainst.againstMe(option);
int relativeX = playerX - BetterBlockPos.XfromLong(placingBlockAt);
diff --git a/src/main/java/baritone/builder/PlaceOrderDependencyGraph.java b/src/main/java/baritone/builder/PlaceOrderDependencyGraph.java
index 04231f1ae..381b69e1f 100644
--- a/src/main/java/baritone/builder/PlaceOrderDependencyGraph.java
+++ b/src/main/java/baritone/builder/PlaceOrderDependencyGraph.java
@@ -27,10 +27,6 @@ package baritone.builder;
*/
public class PlaceOrderDependencyGraph {
- private static final BlockStateCachedData[] PER_STATE_WITH_SCAFFOLDING = BlockStateCachedData.getAllStates().stream().map(
- state -> state != null && treatAsScaffolding(state) ? BlockStateCachedData.SCAFFOLDING : state
- ).toArray(BlockStateCachedData[]::new);
-
private final PackedBlockStateCuboid states;
private final byte[] edges;
@@ -43,7 +39,7 @@ public class PlaceOrderDependencyGraph {
private void compute(long pos) {
byte val = 0;
- for (BlockStatePlacementOption option : data(pos).options) {
+ for (BlockStatePlacementOption option : data(pos).placeMe) {
if (Main.STRICT_Y && option.against == Face.UP) {
throw new IllegalStateException();
}
@@ -52,7 +48,7 @@ public class PlaceOrderDependencyGraph {
if (inRange(againstPos)) {
against = data(againstPos);
} else {
- against = BlockStateCachedData.SCAFFOLDING;
+ against = FakeStates.SCAFFOLDING;
}
if (against.possibleAgainstMe(option)) {
val |= 1 << option.against.index;
@@ -62,7 +58,7 @@ public class PlaceOrderDependencyGraph {
}
public BlockStateCachedData data(long pos) {
- return PER_STATE_WITH_SCAFFOLDING[state(pos)];
+ return states.getScaffoldingVariant(bounds().toIndex(pos));
}
// example: dirt at 0,0,0 torch at 0,1,0. outgoingEdge(0,0,0,UP) returns true, incomingEdge(0,1,0,DOWN) returns true
@@ -89,14 +85,7 @@ public class PlaceOrderDependencyGraph {
}
public boolean airTreatedAsScaffolding(long pos) {
- // alternate valid implementations of this could be:
- // return BlockStateCachedData.getScaffoldingVariant(state(pos)) == BlockStateCachedData.SCAFFOLDING;
- // return data(pos) == BlockStateCachedData.SCAFFOLDING;
- return treatAsScaffolding(BlockStateCachedData.get(state(pos)));
- }
-
- private int state(long pos) {
- return states.get(bounds().toIndex(pos));
+ return data(pos) == FakeStates.SCAFFOLDING;
}
private boolean inRange(long pos) {
@@ -106,8 +95,4 @@ public class PlaceOrderDependencyGraph {
public Bounds bounds() {
return states.bounds;
}
-
- public static boolean treatAsScaffolding(BlockStateCachedData state) {
- return state.isAir;
- }
}
diff --git a/src/main/java/baritone/builder/PlayerPhysics.java b/src/main/java/baritone/builder/PlayerPhysics.java
index 08ea93569..484683066 100644
--- a/src/main/java/baritone/builder/PlayerPhysics.java
+++ b/src/main/java/baritone/builder/PlayerPhysics.java
@@ -306,22 +306,6 @@ public class PlayerPhysics {
return feet > Blip.TWO_BLOCKS - Blip.PLAYER_HEIGHT_SLIGHT_OVERESTIMATE; // > and not >= because the player height is a slight overestimate
}
- static {
- if (Blip.PLAYER_HEIGHT_SLIGHT_OVERESTIMATE >= Blip.TWO_BLOCKS || Blip.PLAYER_HEIGHT_SLIGHT_OVERESTIMATE + Blip.HALF_BLOCK <= Blip.TWO_BLOCKS) {
- throw new IllegalStateException("Assumptions made in playerTravelCollides");
- }
- if (Blip.TALLEST_BLOCK - Blip.FULL_BLOCK + Blip.JUMP - Blip.TWO_BLOCKS >= 0) {
- throw new IllegalStateException("Assumption made in bidirectionalPlayerTravel");
- }
- int maxFeet = Blip.FULL_BLOCK - 1; // 15
- int couldJumpUpTo = maxFeet + Blip.JUMP; // 35
- int maxWithinAB = couldJumpUpTo - Blip.TWO_BLOCKS; // 3
- if (protrudesIntoThirdBlock(maxWithinAB)) {
- // btw this is literally only 1 blip away from being true lol
- throw new IllegalStateException("Oh no, if this is true then playerTravelCollides needs to check another layer above EF");
- }
- }
-
public enum Collision {
// TODO maybe we need another option that is like "you could do it, but you shouldn't". like, "if you hit W, you would walk forward, but you wouldn't like the outcome" such as cactus or lava or something
diff --git a/src/main/java/baritone/builder/SolverEngineInput.java b/src/main/java/baritone/builder/SolverEngineInput.java
index c5b39213f..0de5200e9 100644
--- a/src/main/java/baritone/builder/SolverEngineInput.java
+++ b/src/main/java/baritone/builder/SolverEngineInput.java
@@ -132,10 +132,10 @@ public class SolverEngineInput {
if (inWorldState.blockExists(pos)) {
return graph.data(pos);
} else {
- return BlockStateCachedData.AIR;
+ return FakeStates.AIR;
}
} else {
- return BlockStateCachedData.OUT_OF_BOUNDS;
+ return FakeStates.OUT_OF_BOUNDS;
}
}
}
diff --git a/src/main/java/baritone/builder/Vec3d.java b/src/main/java/baritone/builder/Vec3d.java
index 3e38b4854..9123c31d7 100644
--- a/src/main/java/baritone/builder/Vec3d.java
+++ b/src/main/java/baritone/builder/Vec3d.java
@@ -86,13 +86,4 @@ public class Vec3d {
public String toString() {
return "Vec3d{" + x + "," + y + "," + z + "}";
}
-
- static {
- for (Face face : Face.HORIZONTALS) {
- Face flat = new Vec3d(face.x, face.y, face.z).flatDirection();
- if (flat != face) {
- throw new IllegalStateException();
- }
- }
- }
}
diff --git a/src/main/java/baritone/builder/mc/BlockStatePropertiesExtractor.java b/src/main/java/baritone/builder/mc/BlockStatePropertiesExtractor.java
index 06b732b54..7469462e8 100644
--- a/src/main/java/baritone/builder/mc/BlockStatePropertiesExtractor.java
+++ b/src/main/java/baritone/builder/mc/BlockStatePropertiesExtractor.java
@@ -47,7 +47,7 @@ public class BlockStatePropertiesExtractor {
}
if (block instanceof BlockStairs) {
boolean rightsideUp = state.getValue(BlockStairs.HALF) == BlockStairs.EnumHalf.BOTTOM; // true if normal stair, false if upside down stair
- Face facing = Face.fromMC(state.getValue(BlockStairs.FACING));
+ Face facing = fromMC(state.getValue(BlockStairs.FACING));
BlockStateCachedDataBuilder stairBuilder = new BlockStateCachedDataBuilder() {
@Override
protected PlaceAgainstData placeAgainstFace(Face face) {
@@ -82,7 +82,7 @@ public class BlockStatePropertiesExtractor {
}
if (block instanceof BlockTrapDoor) {
boolean bottom = state.getValue(BlockTrapDoor.HALF) == BlockTrapDoor.DoorHalf.BOTTOM;
- Face facing = Face.fromMC(state.getValue(BlockTrapDoor.FACING));
+ Face facing = fromMC(state.getValue(BlockTrapDoor.FACING));
return new BlockStateCachedDataBuilder() {
@Override
public List howCanIBePlaced() {
@@ -144,14 +144,14 @@ public class BlockStatePropertiesExtractor {
// rotated clockwise about the Y axis
if (block instanceof BlockAnvil) {
- builder.playerMustBeHorizontalFacingInOrderToPlaceMe(Face.fromMC(state.getValue(BlockAnvil.FACING).rotateYCCW()));
+ builder.playerMustBeHorizontalFacingInOrderToPlaceMe(fromMC(state.getValue(BlockAnvil.FACING).rotateYCCW()));
}
// unchanged
if (block instanceof BlockChest
// it is not right || block instanceof BlockSkull // TODO is this right?? skull can be any facing?
) { // TODO fence gate and lever
- builder.playerMustBeHorizontalFacingInOrderToPlaceMe(Face.fromMC(state.getValue(BlockHorizontal.FACING)));
+ builder.playerMustBeHorizontalFacingInOrderToPlaceMe(fromMC(state.getValue(BlockHorizontal.FACING)));
}
// opposite
@@ -163,7 +163,7 @@ public class BlockStatePropertiesExtractor {
|| block instanceof BlockPumpkin
|| block instanceof BlockRedstoneDiode // both repeater and comparator
) {
- builder.playerMustBeHorizontalFacingInOrderToPlaceMe(Face.fromMC(state.getValue(BlockHorizontal.FACING)).opposite());
+ builder.playerMustBeHorizontalFacingInOrderToPlaceMe(fromMC(state.getValue(BlockHorizontal.FACING)).opposite());
}
}
// ladder
@@ -178,11 +178,11 @@ public class BlockStatePropertiesExtractor {
if (block instanceof BlockCommandBlock
|| block instanceof BlockDispenser // dropper extends from dispenser
|| block instanceof BlockPistonBase) {
- builder.playerMustBeEntityFacingInOrderToPlaceMe(Face.fromMC(state.getValue(BlockDirectional.FACING)));
+ builder.playerMustBeEntityFacingInOrderToPlaceMe(fromMC(state.getValue(BlockDirectional.FACING)));
}
if (block instanceof BlockObserver) {
- builder.playerMustBeEntityFacingInOrderToPlaceMe(Face.fromMC(state.getValue(BlockDirectional.FACING)).opposite());
+ builder.playerMustBeEntityFacingInOrderToPlaceMe(fromMC(state.getValue(BlockDirectional.FACING)).opposite());
}
// fully passable blocks
@@ -229,12 +229,12 @@ public class BlockStatePropertiesExtractor {
}
if (block instanceof BlockTorch) { // includes redstone torch
- builder.canOnlyPlaceAgainst(Face.fromMC(state.getValue(BlockTorch.FACING)).opposite());
+ builder.canOnlyPlaceAgainst(fromMC(state.getValue(BlockTorch.FACING)).opposite());
fullyUnderstood = true;
}
if (block instanceof BlockShulkerBox) {
- builder.canOnlyPlaceAgainst(Face.fromMC(state.getValue(BlockShulkerBox.FACING)).opposite());
+ builder.canOnlyPlaceAgainst(fromMC(state.getValue(BlockShulkerBox.FACING)).opposite());
builder.collisionHeight(1); // TODO should this be 1.5 because sometimes the shulker is open?
fullyUnderstood = true;
if (state.getValue(BlockShulkerBox.FACING) == EnumFacing.DOWN && Main.STRICT_Y) {
@@ -300,4 +300,8 @@ public class BlockStatePropertiesExtractor {
return null;
}
}
+
+ public static Face fromMC(EnumFacing facing) {
+ return Face.VALUES[facing.getIndex()];
+ }
}
diff --git a/src/main/java/baritone/builder/mc/DebugStates.java b/src/main/java/baritone/builder/mc/DebugStates.java
index d60af9d32..e18501be6 100644
--- a/src/main/java/baritone/builder/mc/DebugStates.java
+++ b/src/main/java/baritone/builder/mc/DebugStates.java
@@ -17,6 +17,7 @@
package baritone.builder.mc;
+import baritone.builder.BlockData;
import baritone.builder.BlockStateCachedData;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
@@ -30,10 +31,11 @@ public class DebugStates {
public static void debug() {
Map> bts = new HashMap<>();
Map> byString = new HashMap<>();
+ BlockData data = new BlockData(new VanillaBlockStateDataProvider());
for (IBlockState state : Block.BLOCK_STATE_IDS) {
//System.out.println(state);
bts.computeIfAbsent(state.getBlock(), $ -> new ArrayList<>()).add(state);
- String str = toString(BlockStateCachedData.get(Block.BLOCK_STATE_IDS.get(state)));
+ String str = toString(data.get(Block.BLOCK_STATE_IDS.get(state)));
byString.computeIfAbsent(str, $ -> new ArrayList<>()).add(state);
}
for (String key : (Iterable) byString.keySet().stream().sorted()::iterator) {
@@ -100,9 +102,9 @@ public class DebugStates {
}
props.put("collides", "" + data.collidesWithPlayer);
props.put("walkabletop", "" + data.fullyWalkableTop);
- props.put("placeme", "" + data.options.size());
+ props.put("placeme", "" + data.placeMe.size());
props.put("sneak", "" + data.mustSneakWhenPlacingAgainstMe);
- props.put("againstme", "" + Stream.of(data.againstMe).filter(Objects::nonNull).count());
+ props.put("againstme", "" + Stream.of(data.placeAgainstMe).filter(Objects::nonNull).count());
if (data.collidesWithPlayer) {
props.put("y", "" + data.collisionHeightBlips());
}
diff --git a/src/test/java/baritone/builder/BlockStatePlacementOptionTest.java b/src/test/java/baritone/builder/BlockStatePlacementOptionTest.java
new file mode 100644
index 000000000..83d4a893a
--- /dev/null
+++ b/src/test/java/baritone/builder/BlockStatePlacementOptionTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.builder;
+
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Optional;
+
+public class BlockStatePlacementOptionTest {
+
+ @Test
+ public void sanityCheck() {
+ // standing at 1,0,0
+ // block to be placed at 0,0,0
+ // placing against 0,0,-1
+
+ // eye is at 1, 1.62, 0
+ // north or west
+
+ StringBuilder sanity = new StringBuilder();
+ for (PlayerVantage vantage : new PlayerVantage[]{PlayerVantage.STRICT_CENTER, PlayerVantage.LOOSE_CENTER}) {
+ for (Face playerFacing : new Face[]{Face.NORTH, Face.EAST, Face.WEST}) {
+ sanity.append(vantage).append(playerFacing);
+ List traces = BlockStatePlacementOption.get(Face.NORTH, Half.BOTTOM, Optional.of(playerFacing), Optional.empty()).computeTraceOptions(new PlaceAgainstData(Face.SOUTH, Half.EITHER, false), 1, 0, 0, vantage, 4);
+ sanity.append(traces.size());
+ sanity.append(" ");
+ if (!traces.isEmpty()) {
+ for (double d : new double[]{traces.get(0).playerEye.x, traces.get(0).playerEye.z}) {
+ double base = d > 1 ? 1.5 : 0.5;
+ boolean a = d == base - BlockStatePlacementOption.LOOSE_CENTER_DISTANCE;
+ boolean b = d == base;
+ boolean c = d == base + BlockStatePlacementOption.LOOSE_CENTER_DISTANCE;
+ if (!a && !b && !c) {
+ throw new IllegalStateException("Wrong " + d);
+ }
+ sanity.append(a).append(" ").append(b).append(" ").append(c).append(" ");
+ }
+ }
+ sanity.append(traces.stream().mapToDouble(Raytracer.Raytrace::centerDistApprox).distinct().count());
+ sanity.append(";");
+ }
+ }
+
+ String res = sanity.toString();
+ String should = "STRICT_CENTERNORTH0 0;STRICT_CENTEREAST0 0;STRICT_CENTERWEST3 false true false false true false 1;LOOSE_CENTERNORTH2 true false false false true false 1;LOOSE_CENTEREAST0 0;LOOSE_CENTERWEST13 false true false false true false 2;";
+ if (!res.equals(should)) {
+ System.out.println(res);
+ System.out.println(should);
+ throw new IllegalStateException(res);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/baritone/builder/FaceTest.java b/src/test/java/baritone/builder/FaceTest.java
new file mode 100644
index 000000000..5b619311a
--- /dev/null
+++ b/src/test/java/baritone/builder/FaceTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.builder;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class FaceTest {
+ @Test
+ public void testOpts() {
+ for (int i = 0; i < Face.OPTS.size(); i++) {
+ assertEquals(i, Face.OPTS.indexOf(Face.OPTS.get(i)));
+ assertEquals(i, (int) Face.OPTS.get(i).map(face -> face.index).orElse(Face.NUM_FACES));
+ }
+ }
+}
diff --git a/src/test/java/baritone/builder/PlayerPhysicsTest.java b/src/test/java/baritone/builder/PlayerPhysicsTest.java
index 48ae83928..28ea7a67e 100644
--- a/src/test/java/baritone/builder/PlayerPhysicsTest.java
+++ b/src/test/java/baritone/builder/PlayerPhysicsTest.java
@@ -23,40 +23,47 @@ import static org.junit.Assert.*;
public class PlayerPhysicsTest {
+ @Test
+ public void testAssumptions() {
+ if (Blip.PLAYER_HEIGHT_SLIGHT_OVERESTIMATE >= Blip.TWO_BLOCKS || Blip.PLAYER_HEIGHT_SLIGHT_OVERESTIMATE + Blip.HALF_BLOCK <= Blip.TWO_BLOCKS) {
+ throw new IllegalStateException("Assumptions made in playerTravelCollides");
+ }
+ if (Blip.TALLEST_BLOCK - Blip.FULL_BLOCK + Blip.JUMP - Blip.TWO_BLOCKS >= 0) {
+ throw new IllegalStateException("Assumption made in bidirectionalPlayerTravel");
+ }
+ int maxFeet = Blip.FULL_BLOCK - 1; // 15
+ int couldJumpUpTo = maxFeet + Blip.JUMP; // 35
+ int maxWithinAB = couldJumpUpTo - Blip.TWO_BLOCKS; // 3
+ if (PlayerPhysics.protrudesIntoThirdBlock(maxWithinAB)) {
+ // btw this is literally only 1 blip away from being true lol
+ throw new IllegalStateException("Oh no, if this is true then playerTravelCollides needs to check another layer above EF");
+ }
+ }
+
@Test
public void testBasic() {
- assertEquals(16, PlayerPhysics.highestCollision(BlockStateCachedData.SCAFFOLDING, BlockStateCachedData.SCAFFOLDING));
+ assertEquals(16, PlayerPhysics.highestCollision(FakeStates.SCAFFOLDING, FakeStates.SCAFFOLDING));
Column normal = new Column();
- normal.underneath = BlockStateCachedData.SCAFFOLDING;
- normal.feet = BlockStateCachedData.AIR;
- normal.head = BlockStateCachedData.AIR;
- normal.above = BlockStateCachedData.AIR;
- normal.aboveAbove = BlockStateCachedData.SCAFFOLDING;
+ normal.underneath = FakeStates.SCAFFOLDING;
+ normal.feet = FakeStates.AIR;
+ normal.head = FakeStates.AIR;
+ normal.above = FakeStates.AIR;
+ normal.aboveAbove = FakeStates.SCAFFOLDING;
normal.init();
Column up = new Column();
- up.underneath = BlockStateCachedData.SCAFFOLDING;
- up.feet = BlockStateCachedData.SCAFFOLDING;
- up.head = BlockStateCachedData.AIR;
- up.above = BlockStateCachedData.AIR;
- up.aboveAbove = BlockStateCachedData.SCAFFOLDING;
+ up.underneath = FakeStates.SCAFFOLDING;
+ up.feet = FakeStates.SCAFFOLDING;
+ up.head = FakeStates.AIR;
+ up.above = FakeStates.AIR;
+ up.aboveAbove = FakeStates.SCAFFOLDING;
up.init();
assertEquals(PlayerPhysics.Collision.VOXEL_LEVEL, PlayerPhysics.playerTravelCollides(normal, normal));
assertEquals(PlayerPhysics.Collision.JUMP_TO_VOXEL_UP, PlayerPhysics.playerTravelCollides(normal, up));
}
- private static final BlockStateCachedData[] BY_HEIGHT;
-
- static {
- BY_HEIGHT = new BlockStateCachedData[Blip.FULL_BLOCK + 1];
- for (int height = 1; height <= Blip.FULL_BLOCK; height++) {
- BY_HEIGHT[height] = new BlockStateCachedData(new BlockStateCachedDataBuilder().collidesWithPlayer(true).fullyWalkableTop().collisionHeight(height * Blip.RATIO));
- }
- BY_HEIGHT[0] = BlockStateCachedData.AIR;
- }
-
private static BlockStateCachedData[] makeColToHeight(int height) {
height += Blip.FULL_BLOCK * 3; // i don't truck with negative division / modulo
if (height < 0) {
@@ -65,11 +72,11 @@ public class PlayerPhysicsTest {
int fullBlocks = height / Blip.FULL_BLOCK;
BlockStateCachedData[] ret = new BlockStateCachedData[7];
for (int i = 0; i < fullBlocks; i++) {
- ret[i] = BlockStateCachedData.SCAFFOLDING;
+ ret[i] = FakeStates.SCAFFOLDING;
}
- ret[fullBlocks] = BY_HEIGHT[height % Blip.FULL_BLOCK];
+ ret[fullBlocks] = FakeStates.BY_HEIGHT[height % Blip.FULL_BLOCK];
for (int i = fullBlocks + 1; i < ret.length; i++) {
- ret[i] = BlockStateCachedData.AIR;
+ ret[i] = FakeStates.AIR;
}
return ret;
}
@@ -102,7 +109,7 @@ public class PlayerPhysicsTest {
for (int startCeil = 5; startCeil <= 7; startCeil++) {
BlockStateCachedData[] fromCol = makeColToHeight(startHeight);
if (startCeil < fromCol.length) {
- fromCol[startCeil] = BlockStateCachedData.SCAFFOLDING;
+ fromCol[startCeil] = FakeStates.SCAFFOLDING;
}
Column from = toCol(fromCol);
assertEquals(!from.standing(), startCeil == 5 && startHeight > 3);
@@ -115,7 +122,7 @@ public class PlayerPhysicsTest {
for (int endCeil = 5; endCeil <= 7; endCeil++) {
BlockStateCachedData[] toCol = makeColToHeight(endHeight);
if (endCeil < toCol.length) {
- toCol[endCeil] = BlockStateCachedData.SCAFFOLDING;
+ toCol[endCeil] = FakeStates.SCAFFOLDING;
}
Column to = toCol(toCol);
int endVoxel = (endHeight + Blip.FULL_BLOCK * 10) / Blip.FULL_BLOCK - 10; // hate negative division rounding to zero, punch negative division rounding to zero
@@ -160,7 +167,7 @@ public class PlayerPhysicsTest {
if (j >= 0 && j < col.length) {
ret[i] = col[j];
} else {
- ret[i] = BlockStateCachedData.OUT_OF_BOUNDS;
+ ret[i] = FakeStates.OUT_OF_BOUNDS;
}
}
return ret;
diff --git a/src/test/java/baritone/builder/TarjansAlgorithmTest.java b/src/test/java/baritone/builder/TarjansAlgorithmTest.java
new file mode 100644
index 000000000..fa82e1225
--- /dev/null
+++ b/src/test/java/baritone/builder/TarjansAlgorithmTest.java
@@ -0,0 +1,27 @@
+/*
+ * 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.builder;
+
+import org.junit.Test;
+
+public class TarjansAlgorithmTest {
+ @Test
+ public void test() {
+ // the correctness test is already in there just gotta ask for it
+ }
+}
diff --git a/src/test/java/baritone/builder/TestCuboidBounds.java b/src/test/java/baritone/builder/TestCuboidBounds.java
new file mode 100644
index 000000000..e56811fb2
--- /dev/null
+++ b/src/test/java/baritone/builder/TestCuboidBounds.java
@@ -0,0 +1,27 @@
+/*
+ * 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.builder;
+
+import org.junit.Test;
+
+public class TestCuboidBounds {
+ @Test
+ public void testBounds() {
+ new CuboidBounds(10, 10, 10).sanityCheck();
+ }
+}
diff --git a/src/test/java/baritone/builder/Vec3dTest.java b/src/test/java/baritone/builder/Vec3dTest.java
new file mode 100644
index 000000000..508adda68
--- /dev/null
+++ b/src/test/java/baritone/builder/Vec3dTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.builder;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class Vec3dTest {
+ @Test
+ public void testFlatDir() {
+ for (Face face : Face.HORIZONTALS) {
+ Face flat = new Vec3d(face.x, face.y, face.z).flatDirection();
+ assertEquals(flat, face);
+ }
+ }
+}
diff --git a/src/test/java/baritone/builder/connectivity/ConnGraphTest.java b/src/test/java/baritone/builder/connectivity/ConnGraphTest.java
index 2b890cdd4..6350b283b 100644
--- a/src/test/java/baritone/builder/connectivity/ConnGraphTest.java
+++ b/src/test/java/baritone/builder/connectivity/ConnGraphTest.java
@@ -43,6 +43,9 @@ public class ConnGraphTest {
@Test
public void testPerformanceOnRepeatedConnectionAndDisconnection() {
+ if (true) {
+ return; // slow
+ }
EulerTourForest.sanityCheck2();
EulerTourForest.sanityCheck();
for (int trial = 0; trial < 1; trial++) {