Skip to content

Commit

Permalink
Fix some block place relative offset issues
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexProgrammerDE committed Oct 16, 2023
1 parent 439becf commit 19dc4a3
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,22 +44,21 @@ public record MinecraftGraph(TagsState tagsState) {
var blockSubscribers = new Object2ObjectArrayMap<Vector3i, ObjectList<BlockSubscription>>();

var actions = new ObjectArrayList<GraphAction>();
var baseVector = Vector3i.ZERO;
for (var direction : MovementDirection.VALUES) {
var diagonal = direction.isDiagonal();
for (var modifier : MovementModifier.VALUES) {
if (diagonal) {
for (var side : MovementSide.VALUES) {
actions.add(registerMovement(
blockSubscribers,
new PlayerMovement(baseVector, direction, side, modifier),
new PlayerMovement(direction, side, modifier),
actions.size()
));
}
} else {
actions.add(registerMovement(
blockSubscribers,
new PlayerMovement(baseVector, direction, null, modifier),
new PlayerMovement(direction, null, modifier),
actions.size()
));
}
Expand Down Expand Up @@ -98,16 +97,16 @@ public GraphInstructions[] getActions(BotEntityState node) {
var calculatedFree = false;
var isFree = false;
for (var subscriber : value) {
var action = actions[subscriber.index];
var action = actions[subscriber.movementInstanceIndex];
if (action.isImpossible()) {
continue;
}

var basePosition = node.positionBlock();
var positionBlock = basePosition.add(key);
// Absolute position of where the feet of the player right now are
var absolutePositionBlock = node.positionBlock().add(key);
if (blockState == null) {
blockState = node.levelState()
.getBlockStateAt(positionBlock)
.getBlockStateAt(absolutePositionBlock)
.orElseThrow(OutOfLevelException::new);
}

Expand All @@ -125,19 +124,22 @@ public GraphInstructions[] getActions(BotEntityState node) {
continue;
}

// Search for a way to break this block
if (movement.isAllowsBlockActions()
// Narrow this down to blocks that can be broken
&& blockState.blockType().diggable()
// Narrows the list down to a reasonable size
&& BlockItems.hasItemType(blockState.blockType())) {
var cacheableMiningCost = node.inventory()
.getMiningCosts(tagsState, blockState);
// We can mine this block, lets add costs and continue
movement.getBlockBreakCosts()[subscriber.blockArrayIndex] = new MovementMiningCost(
positionBlock,
absolutePositionBlock,
cacheableMiningCost.miningCost(),
cacheableMiningCost.willDrop()
);
} else {
// No way to free this block
// No way to break this block
movement.setImpossible(true);
}
}
Expand Down Expand Up @@ -167,13 +169,10 @@ public GraphInstructions[] getActions(BotEntityState node) {
continue;
}

// We found a valid block to place against
var blockPlaceAgainst = subscriber.blockToPlaceAgainst();

// Fixup the position to be the block we are placing against instead of relative
movement.setBlockPlaceData(new BotActionManager.BlockPlaceData(
basePosition.add(blockPlaceAgainst.againstPos()),
blockPlaceAgainst.blockFace()
absolutePositionBlock,
subscriber.blockToPlaceAgainst.blockFace()
));
}
case MOVEMENT_ADD_CORNER_COST_IF_SOLID -> {
Expand Down Expand Up @@ -211,37 +210,31 @@ public GraphInstructions[] getActions(BotEntityState node) {
}

private static PlayerMovement registerMovement(Object2ObjectMap<Vector3i, ObjectList<BlockSubscription>> blockSubscribers,
PlayerMovement movement, int index) {
PlayerMovement movement, int movementInstanceIndex) {
{
var i = 0;
var blockId = 0;
for (var freeBlock : movement.listRequiredFreeBlocks()) {
var freeSubscription = new BlockSubscription(index, SubscriptionType.MOVEMENT_FREE, i);
blockSubscribers.computeIfAbsent(freeBlock, CREATE_MISSING_FUNCTION)
.add(freeSubscription);
i++;
.add(new BlockSubscription(movementInstanceIndex, SubscriptionType.MOVEMENT_FREE, blockId++));
}
}

{
var addCostIfSolidSubscription = new BlockSubscription(index, SubscriptionType.MOVEMENT_ADD_CORNER_COST_IF_SOLID);
for (var addCostIfSolidBlock : movement.listAddCostIfSolidBlocks()) {
blockSubscribers.computeIfAbsent(addCostIfSolidBlock, CREATE_MISSING_FUNCTION)
.add(addCostIfSolidSubscription);
}
blockSubscribers.computeIfAbsent(movement.requiredSolidBlock(), CREATE_MISSING_FUNCTION)
.add(new BlockSubscription(movementInstanceIndex, SubscriptionType.MOVEMENT_SOLID));
}

{
var solidSubscription = new BlockSubscription(index, SubscriptionType.MOVEMENT_SOLID);
var solidBlock = movement.requiredSolidBlock();
blockSubscribers.computeIfAbsent(solidBlock, CREATE_MISSING_FUNCTION)
.add(solidSubscription);
for (var addCostIfSolidBlock : movement.listAddCostIfSolidBlocks()) {
blockSubscribers.computeIfAbsent(addCostIfSolidBlock, CREATE_MISSING_FUNCTION)
.add(new BlockSubscription(movementInstanceIndex, SubscriptionType.MOVEMENT_ADD_CORNER_COST_IF_SOLID));
}
}

{
for (var againstBlock : movement.possibleBlocksToPlaceAgainst()) {
var againstSolidSubscription = new BlockSubscription(index, SubscriptionType.MOVEMENT_AGAINST_PLACE_SOLID, againstBlock);
blockSubscribers.computeIfAbsent(againstBlock.againstPos(), CREATE_MISSING_FUNCTION)
.add(againstSolidSubscription);
.add(new BlockSubscription(movementInstanceIndex, SubscriptionType.MOVEMENT_AGAINST_PLACE_SOLID, againstBlock));
}
}

Expand All @@ -255,18 +248,18 @@ enum SubscriptionType {
MOVEMENT_AGAINST_PLACE_SOLID
}

record BlockSubscription(int index, SubscriptionType type, int blockArrayIndex,
record BlockSubscription(int movementInstanceIndex, SubscriptionType type, int blockArrayIndex,
BotActionManager.BlockPlaceData blockToPlaceAgainst) {
BlockSubscription(int index, SubscriptionType type) {
this(index, type, -1, null);
BlockSubscription(int movementInstanceIndex, SubscriptionType type) {
this(movementInstanceIndex, type, -1, null);
}

BlockSubscription(int index, SubscriptionType type, int blockArrayIndex) {
this(index, type, blockArrayIndex, null);
BlockSubscription(int movementInstanceIndex, SubscriptionType type, int blockArrayIndex) {
this(movementInstanceIndex, type, blockArrayIndex, null);
}

BlockSubscription(int index, SubscriptionType type, BotActionManager.BlockPlaceData blockToPlaceAgainst) {
this(index, type, -1, blockToPlaceAgainst);
BlockSubscription(int movementInstanceIndex, SubscriptionType type, BotActionManager.BlockPlaceData blockToPlaceAgainst) {
this(movementInstanceIndex, type, -1, blockToPlaceAgainst);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@

@Slf4j
public final class PlayerMovement implements GraphAction {
private final Vector3i previousPositionBlock;
private static final Vector3i feetPositionRelativeBlock = Vector3i.ZERO;
private final MovementDirection direction;
private final MovementSide side;
private final MovementModifier modifier;
private final Vector3i targetBlock;
private final Vector3i targetFeetBlock;
@Getter
private final boolean diagonal;
@Getter
Expand All @@ -63,8 +63,7 @@ public final class PlayerMovement implements GraphAction {
@Setter
private boolean requiresAgainstBlock = false;

public PlayerMovement(Vector3i previousPositionBlock, MovementDirection direction, MovementSide side, MovementModifier modifier) {
this.previousPositionBlock = previousPositionBlock;
public PlayerMovement(MovementDirection direction, MovementSide side, MovementModifier modifier) {
this.direction = direction;
this.side = side;
this.modifier = modifier;
Expand All @@ -79,7 +78,7 @@ public PlayerMovement(Vector3i previousPositionBlock, MovementDirection directio
case JUMP -> Costs.JUMP;
};

this.targetBlock = modifier.offset(direction.offset(previousPositionBlock));
this.targetFeetBlock = modifier.offset(direction.offset(feetPositionRelativeBlock));
this.allowsBlockActions = !diagonal && (
modifier == MovementModifier.JUMP
|| modifier == MovementModifier.NORMAL
Expand All @@ -94,11 +93,10 @@ public PlayerMovement(Vector3i previousPositionBlock, MovementDirection directio
}

private PlayerMovement(PlayerMovement other) {
this.previousPositionBlock = other.previousPositionBlock;
this.direction = other.direction;
this.side = other.side;
this.modifier = other.modifier;
this.targetBlock = other.targetBlock;
this.targetFeetBlock = other.targetFeetBlock;
this.diagonal = other.diagonal;
this.cost = other.cost;
this.appliedCornerCost = other.appliedCornerCost;
Expand All @@ -121,37 +119,34 @@ private int freeCapacity() {

public List<Vector3i> listRequiredFreeBlocks() {
List<Vector3i> requiredFreeBlocks = new ObjectArrayList<>();
var fromPosInt = previousPositionBlock;

if (modifier == MovementModifier.JUMP) {
// Make head block free (maybe head block is a slab)
requiredFreeBlocks.add(fromPosInt.add(0, 1, 0));
requiredFreeBlocks.add(feetPositionRelativeBlock.add(0, 1, 0));

// Make block above head block free
requiredFreeBlocks.add(fromPosInt.add(0, 2, 0));
requiredFreeBlocks.add(feetPositionRelativeBlock.add(0, 2, 0));
}

// Add the blocks that are required to be free for diagonal movement
if (diagonal) {
var corner = getCorner(fromPosInt, side);
var corner = getCorner(side);

for (var bodyOffset : BodyPart.BODY_PARTS_REVERSE) {
// Apply jump shift to target edge and offset for body part
requiredFreeBlocks.add(bodyOffset.offset(modifier.offsetIfJump(corner)));
}
}

var targetEdge = direction.offset(fromPosInt);
var targetEdge = direction.offset(feetPositionRelativeBlock);
for (var bodyOffset : BodyPart.BODY_PARTS_REVERSE) {
// Apply jump shift to target diagonal and offset for body part
requiredFreeBlocks.add(bodyOffset.offset(modifier.offsetIfJump(targetEdge)));
}

// Require free blocks to fall into the target position
switch (modifier) {
case FALL_1 -> {
requiredFreeBlocks.add(MovementModifier.FALL_1.offset(targetEdge));
}
case FALL_1 -> requiredFreeBlocks.add(MovementModifier.FALL_1.offset(targetEdge));
case FALL_2 -> {
requiredFreeBlocks.add(MovementModifier.FALL_1.offset(targetEdge));
requiredFreeBlocks.add(MovementModifier.FALL_2.offset(targetEdge));
Expand All @@ -166,7 +161,7 @@ public List<Vector3i> listRequiredFreeBlocks() {
return requiredFreeBlocks;
}

private Vector3i getCorner(Vector3i fromPosInt, MovementSide side) {
private Vector3i getCorner(MovementSide side) {
return (switch (direction) {
case NORTH_EAST -> switch (side) {
case LEFT -> MovementDirection.NORTH;
Expand All @@ -185,7 +180,7 @@ private Vector3i getCorner(Vector3i fromPosInt, MovementSide side) {
case RIGHT -> MovementDirection.WEST;
};
default -> throw new IllegalStateException("Unexpected value: " + direction);
}).offset(fromPosInt);
}).offset(feetPositionRelativeBlock);
}

public List<Vector3i> listAddCostIfSolidBlocks() {
Expand All @@ -196,7 +191,7 @@ public List<Vector3i> listAddCostIfSolidBlocks() {
var list = new ObjectArrayList<Vector3i>(2);

// If these blocks are solid, the bot moves slower because the bot is running around a corner
var corner = getCorner(previousPositionBlock, side.opposite());
var corner = getCorner(side.opposite());
for (var bodyOffset : BodyPart.BODY_PARTS_REVERSE) {
// Apply jump shift to target edge and offset for body part
list.add(bodyOffset.offset(modifier.offsetIfJump(corner)));
Expand All @@ -207,7 +202,7 @@ public List<Vector3i> listAddCostIfSolidBlocks() {

public Vector3i requiredSolidBlock() {
// Floor block
return targetBlock.sub(0, 1, 0);
return targetFeetBlock.sub(0, 1, 0);
}

public List<BotActionManager.BlockPlaceData> possibleBlocksToPlaceAgainst() {
Expand All @@ -227,30 +222,31 @@ public List<BotActionManager.BlockPlaceData> possibleBlocksToPlaceAgainst() {
var leftDirectionSide = blockDirection.leftSide();
var rightDirectionSide = blockDirection.rightSide();

var floorBlock = targetFeetBlock.sub(0, 1, 0);
return switch (modifier) {
case NORMAL -> // 5
List.of(
// Below
new BotActionManager.BlockPlaceData(targetBlock.sub(0, 1, 0), Direction.UP),
new BotActionManager.BlockPlaceData(floorBlock.sub(0, 1, 0), Direction.UP),
// In front
new BotActionManager.BlockPlaceData(blockDirection.offset(targetBlock), oppositeDirection.getDirection()),
new BotActionManager.BlockPlaceData(blockDirection.offset(floorBlock), oppositeDirection.getDirection()),
// Scaffolding
new BotActionManager.BlockPlaceData(oppositeDirection.offset(targetBlock), blockDirection.getDirection()),
new BotActionManager.BlockPlaceData(oppositeDirection.offset(floorBlock), blockDirection.getDirection()),
// Left side
new BotActionManager.BlockPlaceData(leftDirectionSide.offset(targetBlock), rightDirectionSide.getDirection()),
new BotActionManager.BlockPlaceData(leftDirectionSide.offset(floorBlock), rightDirectionSide.getDirection()),
// Right side
new BotActionManager.BlockPlaceData(rightDirectionSide.offset(targetBlock), leftDirectionSide.getDirection())
new BotActionManager.BlockPlaceData(rightDirectionSide.offset(floorBlock), leftDirectionSide.getDirection())
);
case JUMP, FALL_1 -> // 4 - no scaffolding
List.of(
// Below
new BotActionManager.BlockPlaceData(targetBlock.sub(0, 1, 0), Direction.UP),
new BotActionManager.BlockPlaceData(floorBlock.sub(0, 1, 0), Direction.UP),
// In front
new BotActionManager.BlockPlaceData(blockDirection.offset(targetBlock), oppositeDirection.getDirection()),
new BotActionManager.BlockPlaceData(blockDirection.offset(floorBlock), oppositeDirection.getDirection()),
// Left side
new BotActionManager.BlockPlaceData(leftDirectionSide.offset(targetBlock), rightDirectionSide.getDirection()),
new BotActionManager.BlockPlaceData(leftDirectionSide.offset(floorBlock), rightDirectionSide.getDirection()),
// Right side
new BotActionManager.BlockPlaceData(rightDirectionSide.offset(targetBlock), leftDirectionSide.getDirection())
new BotActionManager.BlockPlaceData(rightDirectionSide.offset(floorBlock), leftDirectionSide.getDirection())
);
default -> throw new IllegalStateException("Unexpected value: " + modifier);
};
Expand Down Expand Up @@ -288,13 +284,14 @@ public GraphInstructions getInstructions(BotEntityState previousEntityState) {
}
}

var realTarget = previousEntityState.positionBlock().add(targetBlock);
var realTarget = previousEntityState.positionBlock().add(targetFeetBlock);

if (blockPlaceData != null) {
var floorBlock = realTarget.sub(0, 1, 0);
cost += Costs.PLACE_BLOCK;
actions.add(new BlockPlaceAction(realTarget, blockPlaceData));
actions.add(new BlockPlaceAction(floorBlock, blockPlaceData));
inventory = inventory.withOneLessBlock();
levelState = levelState.withChangeToSolidBlock(realTarget);
levelState = levelState.withChangeToSolidBlock(floorBlock);
}

var targetDoublePosition = VectorHelper.middleOfBlockNormalize(realTarget.toDouble());
Expand Down

0 comments on commit 19dc4a3

Please sign in to comment.