Skip to content

Commit

Permalink
Pass current blockstate to schematics
Browse files Browse the repository at this point in the history
  • Loading branch information
LoganDark committed Sep 2, 2019
1 parent b405a61 commit 98bb3fb
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 56 deletions.
18 changes: 10 additions & 8 deletions src/api/java/baritone/api/utils/ISchematic.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,13 @@ public interface ISchematic {
* However, in the case of something like a map art, anything that's below the level of the map art doesn't matter,
* so this function should return false in that case. (i.e. it doesn't really have to be air below the art blocks)
*
* @param x The x position of the block, relative to the origin
* @param y The y position of the block, relative to the origin
* @param z The z position of the block, relative to the origin
* @param x The x position of the block, relative to the origin
* @param y The y position of the block, relative to the origin
* @param z The z position of the block, relative to the origin
* @param currentState The current state of that block in the world, or null
* @return Whether or not the specified position is within the bounds of this schematic
*/
default boolean inSchematic(int x, int y, int z) {
default boolean inSchematic(int x, int y, int z, IBlockState currentState) {
return x >= 0 && x < widthX() && y >= 0 && y < heightY() && z >= 0 && z < lengthZ();
}

Expand All @@ -61,12 +62,13 @@ default int size(EnumFacing.Axis axis) {
/**
* Returns the desired block state at a given (X, Y, Z) position relative to the origin (0, 0, 0).
*
* @param x The x position of the block, relative to the origin
* @param y The y position of the block, relative to the origin
* @param z The z position of the block, relative to the origin
* @param x The x position of the block, relative to the origin
* @param y The y position of the block, relative to the origin
* @param z The z position of the block, relative to the origin
* @param current The current state of that block in the world, or null
* @return The desired block state at the specified position
*/
IBlockState desiredState(int x, int y, int z);
IBlockState desiredState(int x, int y, int z, IBlockState current);

/**
* @return The width (X axis length) of this schematic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ private void onInit(CallbackInfo ci) {
* Cache this instead of using the fucking map every time
*
* @author LoganDark
* @reason Regular IBlockState generates a new hash every fucking time. This is not needed when scanning millions
* per second
*/
@Override
@Overwrite
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/baritone/behavior/InventoryBehavior.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import net.minecraft.item.*;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;

import java.util.ArrayList;
import java.util.OptionalInt;
Expand Down Expand Up @@ -132,7 +133,7 @@ public boolean hasGenericThrowaway() {
}

public boolean selectThrowawayForLocation(boolean select, int x, int y, int z) {
IBlockState maybe = baritone.getBuilderProcess().placeAt(x, y, z);
IBlockState maybe = baritone.getBuilderProcess().placeAt(x, y, z, ctx.world().getBlockState(new BlockPos(x, y, z)));
if (maybe != null && throwaway(select, stack -> stack.getItem() instanceof ItemBlock && maybe.equals(((ItemBlock) stack.getItem()).getBlock().getStateForPlacement(ctx.world(), ctx.playerFeet(), EnumFacing.UP, (float) ctx.player().posX, (float) ctx.player().posY, (float) ctx.player().posZ, stack.getItem().getMetadata(stack.getMetadata()), ctx.player())))) {
return true; // gotem
}
Expand Down
99 changes: 57 additions & 42 deletions src/main/java/baritone/process/BuilderProcess.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@
import baritone.api.process.IBuilderProcess;
import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType;
import baritone.api.utils.*;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.ISchematic;
import baritone.api.utils.RayTraceUtils;
import baritone.api.utils.Rotation;
import baritone.api.utils.RotationUtils;
import baritone.api.utils.input.Input;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
Expand All @@ -48,17 +52,24 @@
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.Tuple;
import net.minecraft.util.math.*;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;

import static baritone.api.pathing.movement.ActionCosts.COST_INF;

public final class BuilderProcess extends BaritoneProcessHelper implements IBuilderProcess {

private HashSet<BetterBlockPos> incorrectPositions;
private LongOpenHashSet observedCompleted; // positions that are completed even if they're out of render distance and we can't make sure right now
private String name;
Expand Down Expand Up @@ -106,6 +117,7 @@ public boolean build(String name, File schematic, Vec3i origin) {
e.printStackTrace();
return false;
}
//noinspection ConstantConditions
if (tag == null) {
return false;
}
Expand Down Expand Up @@ -144,14 +156,14 @@ public boolean isActive() {
return schematic != null;
}

public IBlockState placeAt(int x, int y, int z) {
public IBlockState placeAt(int x, int y, int z, IBlockState current) {
if (!isActive()) {
return null;
}
if (!schematic.inSchematic(x - origin.getX(), y - origin.getY(), z - origin.getZ())) {
if (!schematic.inSchematic(x - origin.getX(), y - origin.getY(), z - origin.getZ(), current)) {
return null;
}
IBlockState state = schematic.desiredState(x - origin.getX(), y - origin.getY(), z - origin.getZ());
IBlockState state = schematic.desiredState(x - origin.getX(), y - origin.getY(), z - origin.getZ(), current);
if (state.getBlock() == Blocks.AIR) {
return null;
}
Expand All @@ -170,7 +182,7 @@ private Optional<Tuple<BetterBlockPos, Rotation>> toBreakNearPlayer(BuilderCalcu
if (dy == -1 && x == pathStart.x && z == pathStart.z) {
continue; // dont mine what we're supported by, but not directly standing on
}
IBlockState desired = bcc.getSchematic(x, y, z);
IBlockState desired = bcc.getSchematic(x, y, z, bcc.bsi.get0(x, y, z));
if (desired == null) {
continue; // irrelevant
}
Expand All @@ -188,7 +200,7 @@ private Optional<Tuple<BetterBlockPos, Rotation>> toBreakNearPlayer(BuilderCalcu
return Optional.empty();
}

public class Placement {
public static class Placement {
private final int hotbarSelection;
private final BlockPos placeAgainst;
private final EnumFacing side;
Expand All @@ -210,7 +222,7 @@ private Optional<Placement> searchForPlacables(BuilderCalculationContext bcc, Li
int x = center.x + dx;
int y = center.y + dy;
int z = center.z + dz;
IBlockState desired = bcc.getSchematic(x, y, z);
IBlockState desired = bcc.getSchematic(x, y, z, bcc.bsi.get0(x, y, z));
if (desired == null) {
continue; // irrelevant
}
Expand Down Expand Up @@ -271,14 +283,14 @@ private OptionalInt hasAnyItemThatWouldPlace(IBlockState desired, RayTraceResult
ctx.player().rotationYaw = rot.getYaw();
ctx.player().rotationPitch = rot.getPitch();
IBlockState wouldBePlaced = ((ItemBlock) stack.getItem()).getBlock().getStateForPlacement(
ctx.world(),
result.getBlockPos().offset(result.sideHit),
result.sideHit,
(float) result.hitVec.x - result.getBlockPos().getX(), // as in PlayerControllerMP
(float) result.hitVec.y - result.getBlockPos().getY(),
(float) result.hitVec.z - result.getBlockPos().getZ(),
stack.getItem().getMetadata(stack.getMetadata()),
ctx.player()
ctx.world(),
result.getBlockPos().offset(result.sideHit),
result.sideHit,
(float) result.hitVec.x - result.getBlockPos().getX(), // as in PlayerControllerMP
(float) result.hitVec.y - result.getBlockPos().getY(),
(float) result.hitVec.z - result.getBlockPos().getZ(),
stack.getItem().getMetadata(stack.getMetadata()),
ctx.player()
);
ctx.player().rotationYaw = originalYaw;
ctx.player().rotationPitch = originalPitch;
Expand All @@ -292,16 +304,16 @@ private OptionalInt hasAnyItemThatWouldPlace(IBlockState desired, RayTraceResult
private static Vec3d[] aabbSideMultipliers(EnumFacing side) {
switch (side) {
case UP:
return new Vec3d[]{new Vec3d(0.5, 1, 0.5), new Vec3d(0.1, 1, 0.5), new Vec3d(0.9, 1, 0.5), new Vec3d(0.5, 1, 0.1), new Vec3d(0.5, 1, 0.9)};
return new Vec3d[] {new Vec3d(0.5, 1, 0.5), new Vec3d(0.1, 1, 0.5), new Vec3d(0.9, 1, 0.5), new Vec3d(0.5, 1, 0.1), new Vec3d(0.5, 1, 0.9)};
case DOWN:
return new Vec3d[]{new Vec3d(0.5, 0, 0.5), new Vec3d(0.1, 0, 0.5), new Vec3d(0.9, 0, 0.5), new Vec3d(0.5, 0, 0.1), new Vec3d(0.5, 0, 0.9)};
return new Vec3d[] {new Vec3d(0.5, 0, 0.5), new Vec3d(0.1, 0, 0.5), new Vec3d(0.9, 0, 0.5), new Vec3d(0.5, 0, 0.1), new Vec3d(0.5, 0, 0.9)};
case NORTH:
case SOUTH:
case EAST:
case WEST:
double x = side.getXOffset() == 0 ? 0.5 : (1 + side.getXOffset()) / 2D;
double z = side.getZOffset() == 0 ? 0.5 : (1 + side.getZOffset()) / 2D;
return new Vec3d[]{new Vec3d(x, 0.25, z), new Vec3d(x, 0.75, z)};
return new Vec3d[] {new Vec3d(x, 0.25, z), new Vec3d(x, 0.75, z)};
default: // null
throw new IllegalStateException();
}
Expand Down Expand Up @@ -336,13 +348,13 @@ public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
}
schematic = new ISchematic() {
@Override
public IBlockState desiredState(int x, int y, int z) {
return realSchematic.desiredState(x, y, z);
public IBlockState desiredState(int x, int y, int z, IBlockState current) {
return realSchematic.desiredState(x, y, z, current);
}

@Override
public boolean inSchematic(int x, int y, int z) {
return ISchematic.super.inSchematic(x, y, z) && y >= minYInclusive && y <= maxYInclusive;
public boolean inSchematic(int x, int y, int z, IBlockState currentState) {
return ISchematic.super.inSchematic(x, y, z, currentState) && y >= minYInclusive && y <= maxYInclusive;
}

@Override
Expand Down Expand Up @@ -485,7 +497,7 @@ private void recalcNearby(BuilderCalculationContext bcc) {
int x = center.x + dx;
int y = center.y + dy;
int z = center.z + dz;
IBlockState desired = bcc.getSchematic(x, y, z);
IBlockState desired = bcc.getSchematic(x, y, z, bcc.bsi.get0(x, y, z));
if (desired != null) {
// we care about this position
BetterBlockPos pos = new BetterBlockPos(x, y, z);
Expand All @@ -507,15 +519,16 @@ private void fullRecalc(BuilderCalculationContext bcc) {
for (int y = 0; y < schematic.heightY(); y++) {
for (int z = 0; z < schematic.lengthZ(); z++) {
for (int x = 0; x < schematic.widthX(); x++) {
if (!schematic.inSchematic(x, y, z)) {
continue;
}
int blockX = x + origin.getX();
int blockY = y + origin.getY();
int blockZ = z + origin.getZ();
IBlockState current = bcc.bsi.get0(x, y, z);
if (!schematic.inSchematic(x, y, z, current)) {
continue;
}
if (bcc.bsi.worldContainsLoadedChunk(blockX, blockZ)) { // check if its in render distance, not if its in cache
// we can directly observe this block, it is in render distance
if (valid(bcc.bsi.get0(blockX, blockY, blockZ), schematic.desiredState(x, y, z))) {
if (valid(bcc.bsi.get0(blockX, blockY, blockZ), schematic.desiredState(x, y, z, current))) {
observedCompleted.add(BetterBlockPos.longHash(blockX, blockY, blockZ));
} else {
incorrectPositions.add(new BetterBlockPos(blockX, blockY, blockZ));
Expand All @@ -541,14 +554,14 @@ private void fullRecalc(BuilderCalculationContext bcc) {
}

private Goal assemble(BuilderCalculationContext bcc, List<IBlockState> approxPlacable) {
List<BetterBlockPos> placable = new ArrayList<>();
List<BetterBlockPos> placeable = new ArrayList<>();
List<BetterBlockPos> breakable = new ArrayList<>();
List<BetterBlockPos> sourceLiquids = new ArrayList<>();
incorrectPositions.forEach(pos -> {
IBlockState state = bcc.bsi.get0(pos);
if (state.getBlock() instanceof BlockAir) {
if (approxPlacable.contains(bcc.getSchematic(pos.x, pos.y, pos.z))) {
placable.add(pos);
if (approxPlacable.contains(bcc.getSchematic(pos.x, pos.y, pos.z, state))) {
placeable.add(pos);
}
} else {
if (state.getBlock() instanceof BlockLiquid) {
Expand All @@ -566,8 +579,8 @@ private Goal assemble(BuilderCalculationContext bcc, List<IBlockState> approxPla
List<Goal> toBreak = new ArrayList<>();
breakable.forEach(pos -> toBreak.add(breakGoal(pos, bcc)));
List<Goal> toPlace = new ArrayList<>();
placable.forEach(pos -> {
if (!placable.contains(pos.down()) && !placable.contains(pos.down(2))) {
placeable.forEach(pos -> {
if (!placeable.contains(pos.down()) && !placeable.contains(pos.down(2))) {
toPlace.add(placementGoal(pos, bcc));
}
});
Expand Down Expand Up @@ -629,9 +642,11 @@ private Goal placementGoal(BlockPos pos, BuilderCalculationContext bcc) {
if (ctx.world().getBlockState(pos).getBlock() != Blocks.AIR) { // TODO can this even happen?
return new GoalPlace(pos);
}
boolean allowSameLevel = ctx.world().getBlockState(pos.up()).getBlock() != Blocks.AIR;
IBlockState current = ctx.world().getBlockState(pos.up());
boolean allowSameLevel = current.getBlock() != Blocks.AIR;
for (EnumFacing facing : Movement.HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP) {
if (MovementHelper.canPlaceAgainst(ctx, pos.offset(facing)) && ctx.world().mayPlace(bcc.getSchematic(pos.getX(), pos.getY(), pos.getZ()).getBlock(), pos, false, facing, null)) {
//noinspection ConstantConditions
if (MovementHelper.canPlaceAgainst(ctx, pos.offset(facing)) && ctx.world().mayPlace(bcc.getSchematic(pos.getX(), pos.getY(), pos.getZ(), current).getBlock(), pos, false, facing, null)) {
return new GoalAdjacent(pos, pos.offset(facing), allowSameLevel);
}
}
Expand Down Expand Up @@ -754,9 +769,9 @@ public BuilderCalculationContext() {
this.backtrackCostFavoringCoefficient = 1;
}

private IBlockState getSchematic(int x, int y, int z) {
if (schematic.inSchematic(x - originX, y - originY, z - originZ)) {
return schematic.desiredState(x - originX, y - originY, z - originZ);
private IBlockState getSchematic(int x, int y, int z, IBlockState current) {
if (schematic.inSchematic(x - originX, y - originY, z - originZ, current)) {
return schematic.desiredState(x - originX, y - originY, z - originZ, current);
} else {
return null;
}
Expand All @@ -767,7 +782,7 @@ public double costOfPlacingAt(int x, int y, int z) {
if (isPossiblyProtected(x, y, z) || !worldBorder.canPlaceAt(x, z)) { // make calculation fail properly if we can't build
return COST_INF;
}
IBlockState sch = getSchematic(x, y, z);
IBlockState sch = getSchematic(x, y, z, bsi.get0(x, y, z));
if (sch != null) {
// TODO this can return true even when allowPlace is off.... is that an issue?
if (sch.getBlock() == Blocks.AIR) {
Expand Down Expand Up @@ -801,7 +816,7 @@ public double breakCostMultiplierAt(int x, int y, int z) {
if (!allowBreak || isPossiblyProtected(x, y, z)) {
return COST_INF;
}
IBlockState sch = getSchematic(x, y, z);
IBlockState sch = getSchematic(x, y, z, bsi.get0(x, y, z));
if (sch != null) {
if (sch.getBlock() == Blocks.AIR) {
// it should be air
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/baritone/utils/schematic/FillSchematic.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public FillSchematic(int widthX, int heightY, int lengthZ, IBlockState state) {
}

@Override
public IBlockState desiredState(int x, int y, int z) {
public IBlockState desiredState(int x, int y, int z, IBlockState current) {
return state;
}

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/baritone/utils/schematic/MapArtSchematic.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ private static <T> OptionalInt lastIndexMatching(T[] arr, Predicate<? super T> p
}

@Override
public boolean inSchematic(int x, int y, int z) {
public boolean inSchematic(int x, int y, int z, IBlockState currentState) {
// in map art, we only care about coordinates in or above the art
return super.inSchematic(x, y, z) && y >= heightMap[x][z];
return super.inSchematic(x, y, z, currentState) && y >= heightMap[x][z];
}
}
2 changes: 1 addition & 1 deletion src/main/java/baritone/utils/schematic/Schematic.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public Schematic(NBTTagCompound schematic) {
}

@Override
public IBlockState desiredState(int x, int y, int z) {
public IBlockState desiredState(int x, int y, int z, IBlockState current) {
return states[x][z][y];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public SchematicAdapter(SchematicWorld schematicWorld) {
}

@Override
public IBlockState desiredState(int x, int y, int z) {
public IBlockState desiredState(int x, int y, int z, IBlockState current) {
return schematic.getSchematic().getBlockState(new BlockPos(x, y, z));
}

Expand Down

0 comments on commit 98bb3fb

Please sign in to comment.