Skip to content

Commit

Permalink
First work on implementing down digging movement
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexProgrammerDE committed Oct 17, 2023
1 parent d8a0421 commit 268016d
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ public void tick(BotConnection connection) {
putOnHotbar = true;
return;
}

throw new IllegalStateException("Failed to find item stack");
}

if (finishedDigging) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ public void tick(BotConnection connection) {
putOnHotbar = true;
return;
}

throw new IllegalStateException("Failed to find item stack");
}

connection.sessionDataManager().getBotActionManager().placeBlock(Hand.MAIN_HAND, blockPlaceData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
import net.pistonmaster.serverwrecker.pathfinding.BotEntityState;
import net.pistonmaster.serverwrecker.pathfinding.graph.actions.GraphAction;
import net.pistonmaster.serverwrecker.pathfinding.graph.actions.GraphInstructions;
import net.pistonmaster.serverwrecker.pathfinding.graph.actions.PlayerMovement;
import net.pistonmaster.serverwrecker.pathfinding.graph.actions.movement.*;
import net.pistonmaster.serverwrecker.pathfinding.graph.actions.parkour.ParkourDirection;
import net.pistonmaster.serverwrecker.pathfinding.graph.actions.parkour.ParkourMovement;
import net.pistonmaster.serverwrecker.pathfinding.graph.actions.updown.DownMovement;
import net.pistonmaster.serverwrecker.protocol.bot.BotActionManager;
import net.pistonmaster.serverwrecker.protocol.bot.block.BlockStateMeta;
import net.pistonmaster.serverwrecker.protocol.bot.state.tag.TagsState;
Expand Down Expand Up @@ -76,6 +76,12 @@ public record MinecraftGraph(TagsState tagsState) {
));
}

actions.add(registerDownMovement(
blockSubscribers,
new DownMovement(),
actions.size()
));

ACTIONS_TEMPLATE = actions.toArray(new GraphAction[0]);
SUBSCRIPTION_KEYS = new Vector3i[blockSubscribers.size()];
SUBSCRIPTION_VALUES = new BlockSubscription[blockSubscribers.size()][];
Expand Down Expand Up @@ -232,7 +238,7 @@ public GraphInstructions[] getActions(BotEntityState node) {

if (blockState.blockShapeType().isFullBlock()) {
movement.addCornerCost();
} else if (BlockTypeHelper.isHurtOnTouch(blockState.blockType())) {
} else if (BlockTypeHelper.isHurtOnTouchSide(blockState.blockType())) {
// Since this is a corner, we can also avoid touching blocks that hurt us, e.g., cacti
movement.setImpossible(true);
}
Expand Down Expand Up @@ -263,6 +269,39 @@ public GraphInstructions[] getActions(BotEntityState node) {
parkourMovement.setImpossible(true);
}
}
} else if (action instanceof DownMovement downMovement) {
switch (subscriber.type) {
case MOVEMENT_FREE -> {
if (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
downMovement.setBlockBreakCosts(new MovementMiningCost(
absolutePositionBlock,
cacheableMiningCost.miningCost(),
cacheableMiningCost.willDrop()
));
} else {
// No way to break this block
downMovement.setImpossible(true);
}
}
case DOWN_SAFETY_CHECK -> {
var yLevel = key.getY();

if (yLevel < downMovement.getClosestBlockToFallOn()) {
// We already found a block to fall on, above this one
continue;
}

if (BlockTypeHelper.isSafeBlockToStandOn(blockState)) {
// We found a block to fall on
downMovement.setClosestBlockToFallOn(yLevel);
}
}
}
}
}
}
Expand Down Expand Up @@ -349,12 +388,30 @@ private static ParkourMovement registerParkourMovement(Object2ObjectMap<Vector3i
return movement;
}

private static DownMovement registerDownMovement(Object2ObjectMap<Vector3i, ObjectList<BlockSubscription>> blockSubscribers,
DownMovement movement, int movementIndex) {
{
for (var safetyBlock : movement.listSafetyCheckBlocks()) {
blockSubscribers.computeIfAbsent(safetyBlock, CREATE_MISSING_FUNCTION)
.add(new BlockSubscription(movementIndex, SubscriptionType.DOWN_SAFETY_CHECK));
}
}

{
blockSubscribers.computeIfAbsent(movement.blockToBreak(), CREATE_MISSING_FUNCTION)
.add(new BlockSubscription(movementIndex, SubscriptionType.MOVEMENT_FREE));
}

return movement;
}

enum SubscriptionType {
MOVEMENT_FREE,
MOVEMENT_BREAK_SAFETY_CHECK,
MOVEMENT_SOLID,
MOVEMENT_ADD_CORNER_COST_IF_SOLID,
MOVEMENT_AGAINST_PLACE_SOLID
MOVEMENT_AGAINST_PLACE_SOLID,
DOWN_SAFETY_CHECK
}

record BlockSubscription(int movementIndex, SubscriptionType type, int blockArrayIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
*/
package net.pistonmaster.serverwrecker.pathfinding.graph.actions;
package net.pistonmaster.serverwrecker.pathfinding.graph.actions.movement;

import com.github.steveice10.mc.protocol.data.game.entity.object.Direction;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
Expand All @@ -30,7 +30,8 @@
import net.pistonmaster.serverwrecker.pathfinding.execution.BlockPlaceAction;
import net.pistonmaster.serverwrecker.pathfinding.execution.MovementAction;
import net.pistonmaster.serverwrecker.pathfinding.execution.WorldAction;
import net.pistonmaster.serverwrecker.pathfinding.graph.actions.movement.*;
import net.pistonmaster.serverwrecker.pathfinding.graph.actions.GraphAction;
import net.pistonmaster.serverwrecker.pathfinding.graph.actions.GraphInstructions;
import net.pistonmaster.serverwrecker.protocol.bot.BotActionManager;
import net.pistonmaster.serverwrecker.util.VectorHelper;
import org.cloudburstmc.math.vector.Vector3i;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* ServerWrecker
*
* Copyright (C) 2023 ServerWrecker
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
*/
package net.pistonmaster.serverwrecker.pathfinding.graph.actions.updown;

import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import lombok.Getter;
import lombok.Setter;
import net.pistonmaster.serverwrecker.pathfinding.BotEntityState;
import net.pistonmaster.serverwrecker.pathfinding.Costs;
import net.pistonmaster.serverwrecker.pathfinding.execution.BlockBreakAction;
import net.pistonmaster.serverwrecker.pathfinding.graph.actions.GraphAction;
import net.pistonmaster.serverwrecker.pathfinding.graph.actions.GraphInstructions;
import net.pistonmaster.serverwrecker.pathfinding.graph.actions.movement.MovementMiningCost;
import net.pistonmaster.serverwrecker.util.VectorHelper;
import org.cloudburstmc.math.vector.Vector3i;

import java.util.List;

public class DownMovement implements GraphAction {
private static final Vector3i FEET_POSITION_RELATIVE_BLOCK = Vector3i.ZERO;
private final Vector3i targetToMineBlock;
@Getter
@Setter
private MovementMiningCost blockBreakCosts;
private double cost;
@Setter
@Getter
private boolean isImpossible = false;
@Getter
@Setter
private int closestBlockToFallOn = Integer.MIN_VALUE;

public DownMovement() {
this.targetToMineBlock = FEET_POSITION_RELATIVE_BLOCK.sub(0, 1, 0);
}

private DownMovement(DownMovement other) {
this.targetToMineBlock = other.targetToMineBlock;
this.cost = other.cost;
this.isImpossible = other.isImpossible;
this.blockBreakCosts = other.blockBreakCosts;
this.closestBlockToFallOn = other.closestBlockToFallOn;
}

public Vector3i blockToBreak() {
return targetToMineBlock;
}

public List<Vector3i> listSafetyCheckBlocks() {
List<Vector3i> requiredFreeBlocks = new ObjectArrayList<>();

// Falls one block
requiredFreeBlocks.add(FEET_POSITION_RELATIVE_BLOCK.sub(0, 2, 0));

// Falls two blocks
requiredFreeBlocks.add(FEET_POSITION_RELATIVE_BLOCK.sub(0, 3, 0));

// Falls three blocks
requiredFreeBlocks.add(FEET_POSITION_RELATIVE_BLOCK.sub(0, 4, 0));

return requiredFreeBlocks;
}

@Override
public boolean isImpossibleToComplete() {
return isImpossible || closestBlockToFallOn == Integer.MIN_VALUE;
}

@Override
public GraphInstructions getInstructions(BotEntityState previousEntityState) {
var absoluteMinedBlock = previousEntityState.positionBlock().add(targetToMineBlock);
var absoluteTargetFeetBlock = previousEntityState.positionBlock().add(0, closestBlockToFallOn + 1, 0);
var targetFeetDoublePosition = VectorHelper.middleOfBlockNormalize(absoluteTargetFeetBlock.toDouble());

cost += switch (closestBlockToFallOn) {
case -2 -> Costs.FALL_1;
case -3 -> Costs.FALL_2;
case -4 -> Costs.FALL_3;
default -> throw new IllegalStateException("Unexpected value: " + closestBlockToFallOn);
};

cost += blockBreakCosts.miningCost();

return new GraphInstructions(new BotEntityState(
targetFeetDoublePosition,
absoluteTargetFeetBlock,
previousEntityState.levelState(),
previousEntityState.inventory()
), cost, List.of(new BlockBreakAction(absoluteMinedBlock)));
}

@Override
public DownMovement copy(BotEntityState previousEntityState) {
return new DownMovement(this);
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public static boolean isFullBlock(BlockStateMeta meta) {
return meta.blockShapeType().isFullBlock();
}

public static boolean isHurtOnTouch(BlockType type) {
public static boolean isHurtOnTouchSide(BlockType type) {
return type == BlockType.CACTUS
|| type == BlockType.SWEET_BERRY_BUSH
|| type == BlockType.WITHER_ROSE
Expand All @@ -84,4 +84,12 @@ public static boolean isFallingAroundMinedBlock(BlockType type) {
|| type == BlockType.CHIPPED_ANVIL
|| type == BlockType.DAMAGED_ANVIL;
}

public static boolean isHurtWhenStoodOn(BlockType type) {
return type == BlockType.MAGMA_BLOCK;
}

public static boolean isSafeBlockToStandOn(BlockStateMeta meta) {
return meta.blockShapeType().isFullBlock() && !isHurtWhenStoodOn(meta.blockType());
}
}

0 comments on commit 268016d

Please sign in to comment.