fixed up raytracer and placement option
This commit is contained in:
@@ -245,10 +245,10 @@ public final class BetterBlockPos extends BlockPos {
|
||||
@Nonnull
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"BetterBlockPos{x=%s,y=%s,z=%s}",
|
||||
SettingsUtil.maybeCensor(x),
|
||||
SettingsUtil.maybeCensor(y),
|
||||
SettingsUtil.maybeCensor(z)
|
||||
"BetterBlockPos{x=%d,y=%d,z=%d}",
|
||||
x,
|
||||
y,
|
||||
z
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,11 @@ import java.util.*;
|
||||
public final class BlockStateCachedData {
|
||||
|
||||
private static final BlockStateCachedData[] PER_STATE = Main.DATA_PROVIDER.all();
|
||||
public static final BlockStateCachedData SCAFFOLDING = new BlockStateCachedData(false, true, true);
|
||||
public static final BlockStateCachedData SCAFFOLDING = new BlockStateCachedData(false, true, true, Half.EITHER, false);
|
||||
|
||||
public final boolean canWalkOn;
|
||||
public final boolean isAir;
|
||||
public final boolean mustSneakWhenPlacingAgainstMe;
|
||||
private final boolean[] presentsTopHalfFaceForPlacement;
|
||||
private final boolean[] presentsBottomHalfFaceForPlacement;
|
||||
private final List<BlockStatePlacementOption> options;
|
||||
@@ -40,17 +41,17 @@ public final class BlockStateCachedData {
|
||||
return PER_STATE[state];
|
||||
}
|
||||
|
||||
public BlockStateCachedData(boolean isAir, boolean canPlaceAgainstAtAll, boolean canWalkOn) {
|
||||
this(isAir, canPlaceAgainstAtAll, canWalkOn, Half.EITHER);
|
||||
}
|
||||
|
||||
public BlockStateCachedData(boolean isAir, boolean canPlaceAgainstAtAll, boolean canWalkOn, Half half) {
|
||||
public BlockStateCachedData(boolean isAir, boolean canPlaceAgainstAtAll, boolean canWalkOn, Half half, boolean mustSneakWhenPlacingAgainstMe) {
|
||||
this.isAir = isAir;
|
||||
this.canWalkOn = canWalkOn;
|
||||
this.mustSneakWhenPlacingAgainstMe = mustSneakWhenPlacingAgainstMe;
|
||||
this.options = Collections.unmodifiableList(calcOptions(canPlaceAgainstAtAll, half));
|
||||
this.presentsTopHalfFaceForPlacement = new boolean[Face.VALUES.length];
|
||||
this.presentsBottomHalfFaceForPlacement = new boolean[Face.VALUES.length];
|
||||
setupFacesPresented(canPlaceAgainstAtAll, half);
|
||||
if (mustSneakWhenPlacingAgainstMe && half != Half.EITHER) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
private void setupFacesPresented(boolean canPlaceAgainstAtAll, Half half) {
|
||||
@@ -86,22 +87,23 @@ public final class BlockStateCachedData {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Half presentsFace(Face face, Half half) {
|
||||
private PlaceAgainstData presentsFace(Face face, Half half) {
|
||||
if ((face == Face.UP || face == Face.DOWN) && half != Half.EITHER) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
boolean top = presentsTopHalfFaceForPlacement[face.index] && (half == Half.EITHER || half == Half.TOP);
|
||||
boolean bottom = presentsBottomHalfFaceForPlacement[face.index] && (half == Half.EITHER || half == Half.BOTTOM);
|
||||
Half intersectedHalf; // the half that both we present, and they accept. not necessarily equal to either. slab-against-block and block-against-slab will both have this as top/bottom, not either.
|
||||
if (top && bottom) {
|
||||
return Half.EITHER;
|
||||
intersectedHalf = Half.EITHER;
|
||||
} else if (top) {
|
||||
intersectedHalf = Half.TOP;
|
||||
} else if (bottom) {
|
||||
intersectedHalf = Half.BOTTOM;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
if (top) {
|
||||
return Half.TOP;
|
||||
}
|
||||
if (bottom) {
|
||||
return Half.BOTTOM;
|
||||
}
|
||||
return null;
|
||||
return PlaceAgainstData.get(intersectedHalf, mustSneakWhenPlacingAgainstMe);
|
||||
}
|
||||
|
||||
private List<BlockStatePlacementOption> calcOptions(boolean canPlaceAgainstAtAll, Half half) {
|
||||
@@ -135,9 +137,9 @@ public final class BlockStateCachedData {
|
||||
|
||||
|
||||
@Nullable
|
||||
public Half canBeDoneAgainstMe(BlockStatePlacementOption placement) {
|
||||
public PlaceAgainstData canBeDoneAgainstMe(BlockStatePlacementOption placement) {
|
||||
if (Main.fakePlacementForPerformanceTesting) {
|
||||
return Main.RAND.nextInt(10) < 8 ? Half.EITHER : null;
|
||||
return Main.RAND.nextInt(10) < 8 ? PlaceAgainstData.EITHER : null;
|
||||
}
|
||||
|
||||
Face myFace = placement.against.opposite();
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
|
||||
package baritone.builder;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@@ -47,7 +50,14 @@ public class BlockStatePlacementOption {
|
||||
validate(against, half, playerMustBeFacing);
|
||||
}
|
||||
|
||||
public Optional<Raytracer.Raytrace> computeTraceOptions(Half againstHalf, int playerSupportingX, double playerEyeY, int playerSupportingZ, PlayerVantage vantage, double blockReachDistance) {
|
||||
/**
|
||||
* This value must be greater than the face projections.
|
||||
* <p>
|
||||
* Otherwise certain stair placements would not work. This is verified in this class's sanityCheck.
|
||||
*/
|
||||
private static final double LOOSE_CENTER_DISTANCE = 0.15;
|
||||
|
||||
public List<Raytracer.Raytrace> computeTraceOptions(Half againstHalf, int playerSupportingX, double playerEyeY, int playerSupportingZ, PlayerVantage vantage, double blockReachDistance) {
|
||||
if (againstHalf != half && half != Half.EITHER) { // narrowing is ok (EITHER -> TOP/BOTTOM) but widening isn't (TOP/BOTTOM -> EITHER)
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
@@ -55,10 +65,10 @@ public class BlockStatePlacementOption {
|
||||
Vec2d center = Vec2d.HALVED_CENTER.plus(playerSupportingX, playerSupportingZ);
|
||||
switch (vantage) {
|
||||
case LOOSE_CENTER: {
|
||||
acceptableVantages.add(center.plus(0.15, 0));
|
||||
acceptableVantages.add(center.plus(-0.15, 0));
|
||||
acceptableVantages.add(center.plus(0, 0.15));
|
||||
acceptableVantages.add(center.plus(0, -0.15));
|
||||
acceptableVantages.add(center.plus(LOOSE_CENTER_DISTANCE, 0));
|
||||
acceptableVantages.add(center.plus(-LOOSE_CENTER_DISTANCE, 0));
|
||||
acceptableVantages.add(center.plus(0, LOOSE_CENTER_DISTANCE));
|
||||
acceptableVantages.add(center.plus(0, -LOOSE_CENTER_DISTANCE));
|
||||
// no break!
|
||||
} // FALLTHROUGH!
|
||||
case STRICT_CENTER: {
|
||||
@@ -79,35 +89,59 @@ public class BlockStatePlacementOption {
|
||||
// direction from placed block to place-against block = this.against
|
||||
long blockPlacedAt = 0;
|
||||
long placeAgainstPos = against.offset(blockPlacedAt);
|
||||
double sq = blockReachDistance * blockReachDistance;
|
||||
|
||||
return acceptableVantages
|
||||
return sanityCheckTraces(acceptableVantages
|
||||
.stream()
|
||||
.map(playerEyeXZ -> new Vec3d(playerEyeXZ.x, playerEyeY, playerEyeXZ.z))
|
||||
.flatMap(eye ->
|
||||
Stream.of(FACE_PROJECTION_CACHE[against.index])
|
||||
.filter(hit -> eye.distSq(hit) < sq)
|
||||
.filter(this::hitOk)
|
||||
.filter(hit -> eye.distSq(hit) < blockReachDistance * blockReachDistance)
|
||||
.filter(hit -> directionOk(eye, hit))
|
||||
.<Supplier<Optional<Raytracer.Raytrace>>>map(hit -> () -> Raytracer.runTrace(eye, placeAgainstPos, against.opposite(), hit))
|
||||
)
|
||||
.collect(Collectors.toList())
|
||||
.parallelStream() // wrap it like this because flatMap forces .sequential() on the interior child stream, defeating the point
|
||||
// TODO switch back to parallelStream
|
||||
.stream() // wrap it like this because flatMap forces .sequential() on the interior child stream, defeating the point
|
||||
.map(Supplier::get)
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.min(Comparator.naturalOrder());
|
||||
.sorted()
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
private boolean hitOk(Vec3d hit) {
|
||||
if (half == Half.EITHER) {
|
||||
return true;
|
||||
} else if (hit.y == 0.1) {
|
||||
return half == Half.BOTTOM;
|
||||
} else if (hit.y == 0.5) {
|
||||
return false;
|
||||
} else if (hit.y == 0.9) {
|
||||
return half == Half.TOP;
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean directionOk(Vec3d eye, Vec3d hit) {
|
||||
if (playerMustBeFacing.isPresent()) {
|
||||
return eye.flatDirectionTo(hit) == playerMustBeFacing.get();
|
||||
}
|
||||
// TODO include the other conditions for stupid blocks like pistons
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final Vec3d[][] FACE_PROJECTION_CACHE;
|
||||
|
||||
static {
|
||||
Vec2d center = new Vec2d(0.5, 0.5);
|
||||
double[] diffs = {-0.4, 0, +0.4};
|
||||
double[] diffs = {0.1, 0.5, 0.9};
|
||||
FACE_PROJECTION_CACHE = new Vec3d[Face.NUM_FACES][diffs.length * diffs.length];
|
||||
for (Face face : Face.VALUES) {
|
||||
int i = 0;
|
||||
for (double dx : diffs) {
|
||||
for (double dz : diffs) {
|
||||
FACE_PROJECTION_CACHE[face.index][i++] = new Vec3d(project(center.plus(dx, dz).toArr(), face));
|
||||
FACE_PROJECTION_CACHE[face.index][i++] = new Vec3d(project(new double[]{dx, dz}, face));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,4 +207,58 @@ 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<Raytracer.Raytrace> traces = BlockStatePlacementOption.get(Face.NORTH, Half.BOTTOM, Optional.of(playerFacing)).computeTraceOptions(Half.BOTTOM, 1, 1.62, 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<Raytracer.Raytrace> sanityCheckTraces(List<Raytracer.Raytrace> traces) {
|
||||
if (Main.DEBUG && traces.stream().mapToDouble(Raytracer.Raytrace::centerDistApprox).distinct().count() > 2) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return traces;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ package baritone.builder;
|
||||
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.builder.mc.VanillaBlockStateDataProvider;
|
||||
import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
|
||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.init.Blocks;
|
||||
|
||||
@@ -85,7 +87,7 @@ public class Main {
|
||||
{
|
||||
System.out.println(BetterBlockPos.fromLong(BetterBlockPos.toLong(150, 150, 150)));
|
||||
}
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int i = 0; i < 0; i++) {
|
||||
long aaa = System.currentTimeMillis();
|
||||
int[][][] test = new int[64][64][64];
|
||||
int based = Block.BLOCK_STATE_IDS.get(Blocks.DIRT.getDefaultState());
|
||||
@@ -141,14 +143,7 @@ public class Main {
|
||||
Thread.sleep(500);
|
||||
//scaffolding.enable(0);
|
||||
}
|
||||
{
|
||||
// stadning at 1,0,0
|
||||
// block to be placed at 0,0,0
|
||||
// placing against 0,0,-1
|
||||
|
||||
// eye is at 1, 1.62, 0
|
||||
}
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int i = 0; i < 0; i++) {
|
||||
Stream.of(new Object())
|
||||
.flatMap(ignored -> IntStream.range(0, 100).boxed())
|
||||
.parallel()
|
||||
@@ -161,6 +156,89 @@ public class Main {
|
||||
.collect(Collectors.toList()).parallelStream()
|
||||
.forEach(x -> System.out.println(x + ""));
|
||||
}
|
||||
{
|
||||
BlockStatePlacementOption.sanityCheck();
|
||||
}
|
||||
{
|
||||
/*Raytracer.raytraceMode++;
|
||||
Raytracer.raytraceMode %= 3;*/
|
||||
Random rand = new Random(5021);
|
||||
DoubleArrayList A = new DoubleArrayList();
|
||||
DoubleArrayList B = new DoubleArrayList();
|
||||
DoubleArrayList C = new DoubleArrayList();
|
||||
DoubleArrayList D = new DoubleArrayList();
|
||||
DoubleArrayList E = new DoubleArrayList();
|
||||
DoubleArrayList F = new DoubleArrayList();
|
||||
LongArrayList G = new LongArrayList();
|
||||
long a = System.currentTimeMillis();
|
||||
for (int trial = 0; trial < 10_000_000; ) {
|
||||
Vec3d playerEye = new Vec3d(rand.nextDouble() * 5 - 2.5, rand.nextDouble() * 5, rand.nextDouble() * 5 - 2.5);
|
||||
long eyeBlock = playerEye.getRoundedToZeroPositionUnsafeDontUse();
|
||||
if (eyeBlock == 0) {
|
||||
// origin, unlucky
|
||||
continue;
|
||||
}
|
||||
Face placeToAgainst = Face.VALUES[rand.nextInt(Face.NUM_FACES)];
|
||||
Face againstToPlace = placeToAgainst.opposite();
|
||||
long placeAgainst = placeToAgainst.offset(0);
|
||||
if (eyeBlock == placeAgainst) {
|
||||
continue;
|
||||
}
|
||||
double[] hitVec = new double[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
switch (placeToAgainst.vec[i]) {
|
||||
case -1: {
|
||||
hitVec[i] = 0;
|
||||
break;
|
||||
}
|
||||
case 0: {
|
||||
hitVec[i] = rand.nextDouble();
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
hitVec[i] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Vec3d hit = new Vec3d(hitVec);
|
||||
Raytracer.runTrace(playerEye, placeAgainst, againstToPlace, hit);
|
||||
A.add(playerEye.x);
|
||||
B.add(playerEye.y);
|
||||
C.add(playerEye.z);
|
||||
D.add(hit.x);
|
||||
E.add(hit.y);
|
||||
F.add(hit.z);
|
||||
G.add(placeAgainst);
|
||||
trial++;
|
||||
}
|
||||
long b = System.currentTimeMillis();
|
||||
System.out.println("Nominal first run with overhead: " + (b - a) + "ms");
|
||||
for (int it = 0; it < 20; it++) {
|
||||
{
|
||||
Thread.sleep(1000);
|
||||
System.gc();
|
||||
Thread.sleep(1000);
|
||||
long start = System.currentTimeMillis();
|
||||
for (int i = 0; i < 10_000_000; i++) {
|
||||
Raytracer.rayTraceZoomy(A.getDouble(i), B.getDouble(i), C.getDouble(i), D.getDouble(i), E.getDouble(i), F.getDouble(i), G.getLong(i));
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
System.out.println("Branchless took " + (end - start) + "ms");
|
||||
}
|
||||
{
|
||||
Thread.sleep(1000);
|
||||
System.gc();
|
||||
Thread.sleep(1000);
|
||||
long start = System.currentTimeMillis();
|
||||
for (int i = 0; i < 10_000_000; i++) {
|
||||
Raytracer.rayTraceZoomyBranchy(A.getDouble(i), B.getDouble(i), C.getDouble(i), D.getDouble(i), E.getDouble(i), F.getDouble(i), G.getLong(i));
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
System.out.println("Branchy took " + (end - start) + "ms");
|
||||
}
|
||||
}
|
||||
}
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
49
src/main/java/baritone/builder/PlaceAgainstData.java
Normal file
49
src/main/java/baritone/builder/PlaceAgainstData.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.builder;
|
||||
|
||||
public enum PlaceAgainstData {
|
||||
TOP(Half.TOP, false),
|
||||
BOTTOM(Half.BOTTOM, false),
|
||||
EITHER(Half.EITHER, false),
|
||||
SNEAK_TOP(Half.TOP, true), // only if you need to, like, place a top slab against a crafting table
|
||||
SNEAK_BOTTOM(Half.BOTTOM, true), // only if you need to, like, place a top slab against a crafting table
|
||||
SNEAK_EITHER(Half.EITHER, true);
|
||||
|
||||
public final Half half; // like if its a slab
|
||||
public final boolean mustSneak; // like if its a crafting table
|
||||
|
||||
PlaceAgainstData(Half half, boolean mustSneak) {
|
||||
this.half = half;
|
||||
this.mustSneak = mustSneak;
|
||||
}
|
||||
|
||||
public static PlaceAgainstData get(Half half, boolean mustSneak) {
|
||||
// oh, the things i do, out of fear of the garbage collector
|
||||
switch (half) {
|
||||
case TOP:
|
||||
return mustSneak ? SNEAK_TOP : TOP;
|
||||
case BOTTOM:
|
||||
return mustSneak ? SNEAK_BOTTOM : BOTTOM;
|
||||
case EITHER:
|
||||
return mustSneak ? SNEAK_EITHER : EITHER;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Traces rays
|
||||
@@ -29,17 +30,25 @@ import java.util.Optional;
|
||||
public class Raytracer {
|
||||
|
||||
public static Optional<Raytrace> runTrace(Vec3d playerEye, long againstPos, Face againstFace, Vec3d hit) {
|
||||
// TODO this totally could be cached tho...
|
||||
if (againstFace.offset(againstPos) != 0) {
|
||||
throw new IllegalStateException("sanity check - for now we assume that all placed blocks end up at 0,0,0");
|
||||
}
|
||||
if (toLong(playerEye) == 0) {
|
||||
throw new IllegalStateException("player eye is within the block we want to place, this is maybe possible? idk i suppose you could do this with, like, a torch? still seems weird. idk if this should be allowed");
|
||||
}
|
||||
if (toLong(playerEye) == againstPos) {
|
||||
throw new IllegalStateException("player eye is within the block we want to place against, this is DEFINITELY impossible");
|
||||
}
|
||||
//System.out.println(BetterBlockPos.fromLong(toLong(playerEye)) + " to " + BetterBlockPos.fromLong(toLong(hit)) + " aka " + playerEye + " to " + hit);
|
||||
if (Main.STRICT_Y && floor(playerEye.y) < 0) {
|
||||
throw new IllegalStateException("im lazy and dont want to fix occupancyCountByY");
|
||||
}
|
||||
long hitPos = BetterBlockPos.toLong(floor(hit.x), floor(hit.y), floor(hit.z));
|
||||
long hitPos = toLong(hit);
|
||||
if (hitPos != againstPos && hitPos != 0) {
|
||||
throw new IllegalStateException("ambiguous or incorrect hitvec?");
|
||||
}
|
||||
LongArrayList trace = rayTrace(playerEye.x, playerEye.y, playerEye.z, hit.x, hit.y, hit.z);
|
||||
LongArrayList trace = rayTrace(playerEye.x, playerEye.y, playerEye.z, hit.x, hit.y, hit.z, againstPos);
|
||||
if (trace.size() < 2) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
@@ -52,6 +61,10 @@ public class Raytracer {
|
||||
return Optional.of(new Raytrace(playerEye, againstPos, againstFace, hit, trace));
|
||||
}
|
||||
|
||||
private static long toLong(Vec3d hit) {
|
||||
return BetterBlockPos.toLong(floor(hit.x), floor(hit.y), floor(hit.z));
|
||||
}
|
||||
|
||||
public static class Raytrace implements Comparable<Raytrace> {
|
||||
|
||||
public final long againstPos;
|
||||
@@ -69,14 +82,20 @@ public class Raytracer {
|
||||
this.playerEye = playerEye;
|
||||
this.hit = hit;
|
||||
if (trace.getLong(trace.size() - 1) != againstPos) {
|
||||
print(trace);
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (trace.getLong(trace.size() - 2) != 0) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
for (int i = 0; i < trace.size() - 1; i++) {
|
||||
if (!adjacent(trace.getLong(i), trace.getLong(i + 1))) {
|
||||
throw new IllegalStateException(BetterBlockPos.fromLong(trace.getLong(i)) + " to " + BetterBlockPos.fromLong(trace.getLong(i + 1)));
|
||||
}
|
||||
}
|
||||
trace.removeLong(trace.size() - 1); // againstPos doesn't ACTUALLY need to be air, so remove it. it was only there for sanity checking and confirming which face we collided with first
|
||||
trace.trim();
|
||||
if (trace.getLong(0) != BetterBlockPos.toLong(floor(playerEye.x), floor(playerEye.y), floor(playerEye.z))) {
|
||||
if (trace.getLong(0) != toLong(playerEye)) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
this.passedThrough = trace.elements();
|
||||
@@ -91,13 +110,14 @@ public class Raytracer {
|
||||
for (int i = passedThrough.length - 1; i >= 0; i--) {
|
||||
long pos = passedThrough[i];
|
||||
int y = BetterBlockPos.YfromLong(pos);
|
||||
if (list.size() == y) {
|
||||
if (list.size() == y) { // works because we removed the last trace element (against), which could have negative y
|
||||
list.add(0);
|
||||
}
|
||||
if (list.size() != y + 1) { // this works because we go in reverse order
|
||||
throw new IllegalStateException("nonconsecutive");
|
||||
}
|
||||
if (pos == freebieTop) {
|
||||
// only here for correctness in spirit, technically not needed for comparison since it will exist in all of them
|
||||
continue;
|
||||
}
|
||||
if (pos == freebieBottom) {
|
||||
@@ -137,24 +157,103 @@ public class Raytracer {
|
||||
}
|
||||
}
|
||||
{ // if occupancy counts match, tiebreak with strict center winning over loose center
|
||||
int cmp = Double.compare(centerDist(), o.centerDist());
|
||||
int cmp = Double.compare(centerDistApprox(), o.centerDistApprox());
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
}
|
||||
{ // if center status matches, finally tiebreak with simple ray length
|
||||
return Double.compare(hit.distSq(playerEye), o.hit.distSq(o.playerEye));
|
||||
return Double.compare(distSq(), o.distSq());
|
||||
}
|
||||
}
|
||||
|
||||
private double centerDist() {
|
||||
public double centerDistApprox() {
|
||||
// calculate distance to center of block but intentionally round it off
|
||||
// the intent is for LOOSE_CENTER to always tie with itself, even though floating point inaccuracy would make it unequal if we did a direct Double.compare
|
||||
double dx = playerEye.x - (floor(playerEye.x) + 0.5d);
|
||||
double dz = playerEye.z - (floor(playerEye.z) + 0.5d);
|
||||
return dx * dx + dz * dz;
|
||||
double dist = dx * dx + dz * dz;
|
||||
dist = Math.round(dist * 1000000);
|
||||
return dist;
|
||||
}
|
||||
|
||||
public double distSq() {
|
||||
return hit.distSq(playerEye);
|
||||
}
|
||||
}
|
||||
|
||||
private static LongArrayList rayTrace(double startX, double startY, double startZ, double endX, double endY, double endZ) {
|
||||
/**
|
||||
* If I add 10 to all the numbers I raytrace, then subtract them afterwards, then I can just use (int) instead of the nasty BRANCHING floor.
|
||||
* <p>
|
||||
* No difference raytracing from -2 to -1 as it is to raytrace from 8 to 9. Just add ten!
|
||||
*/
|
||||
private static final int POSITIVITY_OFFSET = 10;
|
||||
|
||||
private static final int NUM_STEPS = 10_000;
|
||||
|
||||
public static int raytraceMode = 2;
|
||||
|
||||
private static LongArrayList rayTrace(double rawStartX, double rawStartY, double rawStartZ, double endX, double endY, double endZ, long againstPos) {
|
||||
LongArrayList slow = raytraceMode == 0 || Main.DEBUG ? rayTraceSlow(rawStartX, rawStartY, rawStartZ, endX, endY, endZ) : null;
|
||||
LongArrayList fast = raytraceMode == 1 || Main.DEBUG ? rayTraceFast(rawStartX, rawStartY, rawStartZ, endX, endY, endZ) : null;
|
||||
LongArrayList faster = raytraceMode == 2 || Main.DEBUG ? rayTraceZoomy(rawStartX, rawStartY, rawStartZ, endX, endY, endZ, againstPos) : null;
|
||||
if (Main.DEBUG) {
|
||||
if (fast.equals(slow) && fast.equals(faster)) {
|
||||
} else {
|
||||
System.out.println(rawStartX + " " + rawStartY + " " + rawStartZ + " " + endX + " " + endY + " " + endZ + " " + againstPos);
|
||||
print(slow);
|
||||
print(fast);
|
||||
print(faster);
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
return fast == null ? slow == null ? faster : slow : fast;
|
||||
}
|
||||
|
||||
private static void print(LongArrayList trace) {
|
||||
System.out.println(trace.stream().map(BetterBlockPos::fromLong).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
private static LongArrayList rayTraceFast(double rawStartX, double rawStartY, double rawStartZ, double endX, double endY, double endZ) {
|
||||
if (willFlipSign(rawStartX) || willFlipSign(rawStartY) || willFlipSign(rawStartZ) || willFlipSign(endX) || willFlipSign(endY) || willFlipSign(endZ)) {
|
||||
throw new IllegalStateException("I suppose this could happen if you set the block reach distance absurdly high? Don't do that.");
|
||||
}
|
||||
double diffX = endX - rawStartX;
|
||||
double diffY = endY - rawStartY;
|
||||
double diffZ = endZ - rawStartZ;
|
||||
if (Math.abs(diffX) < 0.1 && Math.abs(diffY) < 0.1 && Math.abs(diffZ) < 0.1) {
|
||||
// need more checks than before because now the tightest inner do-while does NOT check step against any upper limit at all
|
||||
// therefore, if diff was zero, it would truly get stuck indefinitely, unlike previously where it would bail out at 10010
|
||||
throw new IllegalArgumentException("throwing exception instead of entering infinite inner loop");
|
||||
}
|
||||
double startX = rawStartX + POSITIVITY_OFFSET;
|
||||
double startY = rawStartY + POSITIVITY_OFFSET;
|
||||
double startZ = rawStartZ + POSITIVITY_OFFSET;
|
||||
|
||||
int x = Integer.MIN_VALUE;
|
||||
int y = Integer.MIN_VALUE;
|
||||
int z = Integer.MIN_VALUE;
|
||||
LongArrayList voxelsIntersected = new LongArrayList();
|
||||
int step = 0;
|
||||
double mult = 1.0d / NUM_STEPS;
|
||||
double frac;
|
||||
while (step < NUM_STEPS) {
|
||||
do frac = ++step * mult;
|
||||
while (((x ^ (x = (int) (startX + diffX * frac))) | (y ^ (y = (int) (startY + diffY * frac))) | (z ^ (z = (int) (startZ + diffZ * frac)))) == 0);
|
||||
voxelsIntersected.add(BetterBlockPos.toLong(x - POSITIVITY_OFFSET, y - POSITIVITY_OFFSET, z - POSITIVITY_OFFSET));
|
||||
}
|
||||
if (step > NUM_STEPS + 1) {
|
||||
throw new IllegalStateException("No floating point inaccuracies allowed. Or, at least, no more than 2 parts in 10,000 of wiggle room lol. " + step);
|
||||
}
|
||||
return voxelsIntersected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Here's an alternate implementation of the above that is functionally the same, just simpler (and slower)
|
||||
* <p>
|
||||
* The inner loop branches seven times instead of one, for example.
|
||||
*/
|
||||
private static LongArrayList rayTraceSlow(double startX, double startY, double startZ, double endX, double endY, double endZ) {
|
||||
// i'd love to use strictfp here and on floor, but it could unironically prevent a much needed JIT to native, so I won't, sadly
|
||||
double diffX = endX - startX;
|
||||
double diffY = endY - startY;
|
||||
@@ -164,29 +263,31 @@ public class Raytracer {
|
||||
int prevY = Integer.MIN_VALUE;
|
||||
int prevZ = Integer.MIN_VALUE;
|
||||
LongArrayList ret = new LongArrayList();
|
||||
for (int step = 0; step <= 10010; step++) { // not a typo 😈😈😈😈😈😈😈😈😈😈😈
|
||||
double frac = step / 10000.0d; // go THROUGH the face by a little bit, poke through into the block
|
||||
int x = floor(startX + diffX * frac);
|
||||
int y = floor(startY + diffY * frac);
|
||||
int z = floor(startZ + diffZ * frac);
|
||||
if (x == prevX && y == prevY && z == prevZ) {
|
||||
int ourLimit = NUM_STEPS + 1;
|
||||
for (int step = 0; step <= ourLimit; step++) { // 1 branch (step <= ourLimit)
|
||||
double frac = step / (double) NUM_STEPS; // go THROUGH the face by a little bit, poke through into the block
|
||||
int x = floor(startX + diffX * frac); // 1 branch in floor
|
||||
int y = floor(startY + diffY * frac); // 1 branch in floor
|
||||
int z = floor(startZ + diffZ * frac); // 1 branch in floor
|
||||
if (x == prevX && y == prevY && z == prevZ) { // 3 branches (due to && short circuiting)
|
||||
continue;
|
||||
}
|
||||
prevX = x;
|
||||
prevY = y;
|
||||
prevZ = z;
|
||||
long toAdd = BetterBlockPos.toLong(x, y, z);
|
||||
if (!ret.isEmpty()) {
|
||||
long prev = ret.getLong(ret.size() - 1);
|
||||
if (!adjacent(toAdd, prev)) {
|
||||
throw new IllegalStateException(BetterBlockPos.fromLong(prev) + " to " + BetterBlockPos.fromLong(toAdd));
|
||||
}
|
||||
}
|
||||
ret.add(toAdd);
|
||||
ret.add(BetterBlockPos.toLong(x, y, z));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static boolean willFlipSign(double pos) {
|
||||
return flippedSign(pos + POSITIVITY_OFFSET);
|
||||
}
|
||||
|
||||
private static boolean flippedSign(double pos) {
|
||||
return pos < 1d;
|
||||
}
|
||||
|
||||
private static boolean adjacent(long a, long b) {
|
||||
if (a == b) {
|
||||
throw new IllegalStateException();
|
||||
@@ -209,4 +310,170 @@ public class Raytracer {
|
||||
return rawCast;
|
||||
}
|
||||
}
|
||||
|
||||
public static LongArrayList rayTraceZoomy(double startX, double startY, double startZ, double endX, double endY, double endZ, long againstPos) {
|
||||
if (endX < 0 || endX > 1 || endY < 0 || endY > 1 || endZ < 0 || endZ > 1) {
|
||||
throw new IllegalStateException("won't work");
|
||||
}
|
||||
if (flippedSign(startX += POSITIVITY_OFFSET) | flippedSign(startY += POSITIVITY_OFFSET) | flippedSign(startZ += POSITIVITY_OFFSET) | flippedSign(endX += POSITIVITY_OFFSET) | flippedSign(endY += POSITIVITY_OFFSET) | flippedSign(endZ += POSITIVITY_OFFSET)) {
|
||||
throw new IllegalStateException("I suppose this could happen if you set the block reach distance absurdly high? Don't do that.");
|
||||
}
|
||||
int voxelEndX = BetterBlockPos.XfromLong(againstPos) + POSITIVITY_OFFSET;
|
||||
int voxelEndY = BetterBlockPos.YfromLong(againstPos) + POSITIVITY_OFFSET;
|
||||
int voxelEndZ = BetterBlockPos.ZfromLong(againstPos) + POSITIVITY_OFFSET;
|
||||
|
||||
int voxelInX = (int) startX;
|
||||
int voxelInY = (int) startY;
|
||||
int voxelInZ = (int) startZ;
|
||||
if (startX == (double) voxelInX || startY == (double) voxelInY || startZ == (double) voxelInZ) {
|
||||
throw new IllegalStateException("Integral starting coordinates not supported ever since I removed the -0.0d check");
|
||||
}
|
||||
|
||||
LongArrayList voxelsIntersected = new LongArrayList();
|
||||
int steps = 64; // default is 200
|
||||
while (steps-- >= 0) {
|
||||
long posAsLong = BetterBlockPos.toLong(voxelInX - POSITIVITY_OFFSET, voxelInY - POSITIVITY_OFFSET, voxelInZ - POSITIVITY_OFFSET);
|
||||
voxelsIntersected.add(posAsLong);
|
||||
if (posAsLong == againstPos) {
|
||||
if (voxelsIntersected.size() == 1 || voxelsIntersected.getLong(voxelsIntersected.size() - 2) != 0) {
|
||||
voxelsIntersected.add(0);
|
||||
}
|
||||
return voxelsIntersected;
|
||||
}
|
||||
double nextIntegerX, nextIntegerY, nextIntegerZ;
|
||||
// potentially more based branchless impl?
|
||||
nextIntegerX = voxelInX + ((voxelInX - voxelEndX) >>> 31); // if voxelEnd > voxelIn, then voxelIn-voxelEnd will be negative, meaning the sign bit is 1
|
||||
nextIntegerY = voxelInY + ((voxelInY - voxelEndY) >>> 31); // if we do an unsigned right shift by 31, that sign bit becomes the LSB
|
||||
nextIntegerZ = voxelInZ + ((voxelInZ - voxelEndZ) >>> 31); // therefore, this increments nextInteger iff EndX>inX, otherwise it leaves it alone
|
||||
// remember: don't have to worry about the case when voxelEnd == voxelIn, because nextInteger value wont be used
|
||||
|
||||
double fracIfSkipX = 100;
|
||||
double fracIfSkipY = 100;
|
||||
double fracIfSkipZ = 100;
|
||||
double distanceFromStartToEndX = endX - startX;
|
||||
double distanceFromStartToEndY = endY - startY;
|
||||
double distanceFromStartToEndZ = endZ - startZ;
|
||||
if (voxelEndX != voxelInX) {
|
||||
fracIfSkipX = (nextIntegerX - startX) / distanceFromStartToEndX;
|
||||
}
|
||||
if (voxelEndY != voxelInY) {
|
||||
fracIfSkipY = (nextIntegerY - startY) / distanceFromStartToEndY;
|
||||
}
|
||||
if (voxelEndZ != voxelInZ) {
|
||||
fracIfSkipZ = (nextIntegerZ - startZ) / distanceFromStartToEndZ;
|
||||
}
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
int dz = 0;
|
||||
if (fracIfSkipX < fracIfSkipY && fracIfSkipX < fracIfSkipZ) {
|
||||
// note: voxelEndX == voxelInX is impossible because allowSkip would be set to false in that case, meaning that the elapsed distance would stay at default
|
||||
dx = (voxelEndX - voxelInX) >>> 31; // TODO should i set this "dx" way up top at the same time as i set nextIntegerX?
|
||||
startX = nextIntegerX;
|
||||
startY += distanceFromStartToEndY * fracIfSkipX;
|
||||
startZ += distanceFromStartToEndZ * fracIfSkipX;
|
||||
} else if (fracIfSkipY < fracIfSkipZ) {
|
||||
dy = (voxelEndY - voxelInY) >>> 31; // we want dy=1 when endY < inY
|
||||
startX += distanceFromStartToEndX * fracIfSkipY;
|
||||
startY = nextIntegerY;
|
||||
startZ += distanceFromStartToEndZ * fracIfSkipY;
|
||||
} else {
|
||||
dz = (voxelEndZ - voxelInZ) >>> 31;
|
||||
startX += distanceFromStartToEndX * fracIfSkipZ;
|
||||
startY += distanceFromStartToEndY * fracIfSkipZ;
|
||||
startZ = nextIntegerZ;
|
||||
}
|
||||
|
||||
voxelInX = ((int) startX) - dx; // TODO is it faster to paste this block of 3 lines into each of the 3 if branches? we know 2/3 subtracts will be zero, so it would save two subtracts, but is that worth the longer bytecode?
|
||||
voxelInY = ((int) startY) - dy;
|
||||
voxelInZ = ((int) startZ) - dz;
|
||||
}
|
||||
print(voxelsIntersected);
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public static LongArrayList rayTraceZoomyBranchy(double startX, double startY, double startZ, double endX, double endY, double endZ, long againstPos) {
|
||||
if (endX < 0 || endX > 1 || endY < 0 || endY > 1 || endZ < 0 || endZ > 1) {
|
||||
throw new IllegalStateException("won't work");
|
||||
}
|
||||
if (flippedSign(startX += POSITIVITY_OFFSET) | flippedSign(startY += POSITIVITY_OFFSET) | flippedSign(startZ += POSITIVITY_OFFSET) | flippedSign(endX += POSITIVITY_OFFSET) | flippedSign(endY += POSITIVITY_OFFSET) | flippedSign(endZ += POSITIVITY_OFFSET)) {
|
||||
throw new IllegalStateException("I suppose this could happen if you set the block reach distance absurdly high? Don't do that.");
|
||||
}
|
||||
int voxelEndX = BetterBlockPos.XfromLong(againstPos) + POSITIVITY_OFFSET;
|
||||
int voxelEndY = BetterBlockPos.YfromLong(againstPos) + POSITIVITY_OFFSET;
|
||||
int voxelEndZ = BetterBlockPos.ZfromLong(againstPos) + POSITIVITY_OFFSET;
|
||||
|
||||
int voxelInX = (int) startX;
|
||||
int voxelInY = (int) startY;
|
||||
int voxelInZ = (int) startZ;
|
||||
if (startX == (double) voxelInX || startY == (double) voxelInY || startZ == (double) voxelInZ) {
|
||||
throw new IllegalStateException("Integral starting coordinates not supported ever since I removed the -0.0d check");
|
||||
}
|
||||
|
||||
LongArrayList voxelsIntersected = new LongArrayList();
|
||||
int steps = 64; // default is 200
|
||||
while (steps-- >= 0) {
|
||||
long posAsLong = BetterBlockPos.toLong(voxelInX - POSITIVITY_OFFSET, voxelInY - POSITIVITY_OFFSET, voxelInZ - POSITIVITY_OFFSET);
|
||||
voxelsIntersected.add(posAsLong);
|
||||
if (posAsLong == againstPos) {
|
||||
if (voxelsIntersected.size() == 1 || voxelsIntersected.getLong(voxelsIntersected.size() - 2) != 0) {
|
||||
voxelsIntersected.add(0);
|
||||
}
|
||||
return voxelsIntersected;
|
||||
}
|
||||
double nextIntegerX, nextIntegerY, nextIntegerZ;
|
||||
// normal impl
|
||||
nextIntegerX = voxelEndX > voxelInX ? voxelInX + 1 : voxelInX;
|
||||
nextIntegerY = voxelEndY > voxelInY ? voxelInY + 1 : voxelInY;
|
||||
nextIntegerZ = voxelEndZ > voxelInZ ? voxelInZ + 1 : voxelInZ;
|
||||
double fracIfSkipX = 100;
|
||||
double fracIfSkipY = 100;
|
||||
double fracIfSkipZ = 100;
|
||||
double distanceFromStartToEndX = endX - startX;
|
||||
double distanceFromStartToEndY = endY - startY;
|
||||
double distanceFromStartToEndZ = endZ - startZ;
|
||||
if (voxelEndX != voxelInX) {
|
||||
fracIfSkipX = (nextIntegerX - startX) / distanceFromStartToEndX;
|
||||
}
|
||||
if (voxelEndY != voxelInY) {
|
||||
fracIfSkipY = (nextIntegerY - startY) / distanceFromStartToEndY;
|
||||
}
|
||||
if (voxelEndZ != voxelInZ) {
|
||||
fracIfSkipZ = (nextIntegerZ - startZ) / distanceFromStartToEndZ;
|
||||
}
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
int dz = 0;
|
||||
if (fracIfSkipX < fracIfSkipY && fracIfSkipX < fracIfSkipZ) {
|
||||
// note: voxelEndX == voxelInX is impossible because allowSkip would be set to false in that case, meaning that the elapsed distance would stay at default
|
||||
if (voxelEndX < voxelInX) {
|
||||
dx = 1;
|
||||
}
|
||||
startX = nextIntegerX;
|
||||
startY += distanceFromStartToEndY * fracIfSkipX;
|
||||
startZ += distanceFromStartToEndZ * fracIfSkipX;
|
||||
} else if (fracIfSkipY < fracIfSkipZ) {
|
||||
if (voxelEndY < voxelInY) {
|
||||
dy = 1;
|
||||
}
|
||||
startX += distanceFromStartToEndX * fracIfSkipY;
|
||||
startY = nextIntegerY;
|
||||
startZ += distanceFromStartToEndZ * fracIfSkipY;
|
||||
} else {
|
||||
if (voxelEndZ < voxelInZ) {
|
||||
dz = 1;
|
||||
}
|
||||
startX += distanceFromStartToEndX * fracIfSkipZ;
|
||||
startY += distanceFromStartToEndY * fracIfSkipZ;
|
||||
startZ = nextIntegerZ;
|
||||
}
|
||||
|
||||
voxelInX = ((int) startX) - dx; // TODO is it faster to paste this block of 3 lines into each of the 3 if branches? we know 2/3 subtracts will be zero, so it would save two subtracts, but is that worth the longer bytecode?
|
||||
voxelInY = ((int) startY) - dy;
|
||||
voxelInZ = ((int) startZ) - dz;
|
||||
}
|
||||
print(voxelsIntersected);
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
package baritone.builder;
|
||||
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
|
||||
public class Vec3d {
|
||||
|
||||
public final double x;
|
||||
@@ -36,10 +38,51 @@ public class Vec3d {
|
||||
}
|
||||
}
|
||||
|
||||
public long getRoundedToZeroPositionUnsafeDontUse() {
|
||||
return BetterBlockPos.toLong((int) x, (int) y, (int) z);
|
||||
}
|
||||
|
||||
public double distSq(Vec3d other) {
|
||||
double dx = x - other.x;
|
||||
double dy = y - other.y;
|
||||
double dz = z - other.z;
|
||||
return dx * dx + dy * dy + dz * dz;
|
||||
}
|
||||
|
||||
public Face flatDirectionTo(Vec3d dst) {
|
||||
return new Vec3d(dst.x - x, dst.y - y, dst.z - z).flatDirection();
|
||||
}
|
||||
|
||||
public Face flatDirection() {
|
||||
if (Math.abs(x) == Math.abs(z)) {
|
||||
throw new IllegalStateException("ambiguous");
|
||||
}
|
||||
if (Math.abs(x) > Math.abs(z)) {
|
||||
if (x > 0) {
|
||||
return Face.EAST;
|
||||
} else {
|
||||
return Face.WEST;
|
||||
}
|
||||
} else {
|
||||
if (z > 0) {
|
||||
return Face.SOUTH;
|
||||
} else {
|
||||
return Face.NORTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package baritone.builder.mc;
|
||||
|
||||
import baritone.builder.BlockStateCachedData;
|
||||
import baritone.builder.Half;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockAir;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
@@ -34,9 +35,9 @@ public class BlockStatePropertiesExtractor {
|
||||
Block block = state.getBlock();
|
||||
|
||||
if (block instanceof BlockAir) {
|
||||
return new BlockStateCachedData(true, false, false);
|
||||
return new BlockStateCachedData(true, false, false, Half.EITHER, false);
|
||||
}
|
||||
boolean normal = block == Blocks.COBBLESTONE || block == Blocks.DIRT;
|
||||
return new BlockStateCachedData(false, normal, normal);
|
||||
return new BlockStateCachedData(false, normal, normal, Half.EITHER, false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user