Skip to content

Commit

Permalink
Implement build height limits
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexProgrammerDE committed May 6, 2024
1 parent adf33da commit 668ddae
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
import lombok.extern.slf4j.Slf4j;

@Slf4j
Expand Down Expand Up @@ -85,6 +86,14 @@ public static boolean isBlockFree(BlockState blockState) {
return blockState.blockShapeGroup().hasNoCollisions() && blockState.blockType().fluidType() == FluidType.EMPTY;
}

public boolean disallowedToPlaceBlock(SFVec3i position) {
if (!canPlaceBlocks) {
return true;
}

return !level.isPlaceable(position);
}

public void insertActions(
SFVec3i node, Consumer<GraphInstructions> callback) {
log.debug("Inserting actions for node: {}", node);
Expand Down Expand Up @@ -117,6 +126,8 @@ private void processSubscription(
BlockState blockState = null;
SFVec3i absolutePositionBlock = null;

IntConsumer impossibleActionRemover = actionIndex -> actions[actionIndex] = null;

// We cache only this, but not solid because solid will only occur a single time
LazyBoolean isFree = null;
for (var subscriber : value) {
Expand Down Expand Up @@ -150,7 +161,7 @@ private void processSubscription(
callback.accept(instruction);
}
}
case IMPOSSIBLE -> actions[subscriber.actionIndex] = null;
case IMPOSSIBLE -> impossibleActionRemover.accept(subscriber.actionIndex);
}
}
}
Expand All @@ -167,7 +178,7 @@ SubscriptionSingleResult processBlock(
M action,
LazyBoolean isFree,
BlockState blockState,
SFVec3i absolutePositionBlock);
SFVec3i absoluteKey);

default SubscriptionSingleResult processBlockUnsafe(
MinecraftGraph graph,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,14 @@ public BlockState getBlockState(SFVec3i position) {

return accessor.getBlockState(position.x, position.y, position.z);
}

public boolean isPlaceable(SFVec3i position) {
var minBuildHeight = accessor.minBuildHeight();
if (minBuildHeight.isPresent() && position.y < minBuildHeight.getAsInt()) {
return false;
}

var maxBuildHeight = accessor.maxBuildHeight();
return maxBuildHeight.isEmpty() || position.y < maxBuildHeight.getAsInt();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ record DownMovementBlockSubscription(

@Override
public MinecraftGraph.SubscriptionSingleResult processBlock(MinecraftGraph graph, SFVec3i key, DownMovement downMovement, LazyBoolean isFree,
BlockState blockState, SFVec3i absolutePositionBlock) {
BlockState blockState, SFVec3i absoluteKey) {
return switch (type) {
case MOVEMENT_FREE -> {
if (!graph.canBreakBlocks()
Expand All @@ -238,7 +238,7 @@ public MinecraftGraph.SubscriptionSingleResult processBlock(MinecraftGraph graph
// We can mine this block, lets add costs and continue
downMovement.breakCost(
new MovementMiningCost(
absolutePositionBlock,
absoluteKey,
cacheableMiningCost.miningCost(),
cacheableMiningCost.willDrop(),
blockBreakSideHint));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ record ParkourMovementBlockSubscription(

@Override
public MinecraftGraph.SubscriptionSingleResult processBlock(MinecraftGraph graph, SFVec3i key, ParkourMovement parkourMovement, LazyBoolean isFree,
BlockState blockState, SFVec3i absolutePositionBlock) {
BlockState blockState, SFVec3i absoluteKey) {

return switch (type) {
case MOVEMENT_FREE -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ record SimpleMovementBlockSubscription(

@Override
public MinecraftGraph.SubscriptionSingleResult processBlock(MinecraftGraph graph, SFVec3i key, SimpleMovement simpleMovement, LazyBoolean isFree,
BlockState blockState, SFVec3i absolutePositionBlock) {
BlockState blockState, SFVec3i absoluteKey) {
return switch (type) {
case MOVEMENT_FREE -> {
if (isFree.get()) {
Expand Down Expand Up @@ -534,7 +534,7 @@ public MinecraftGraph.SubscriptionSingleResult processBlock(MinecraftGraph graph
// We can mine this block, lets add costs and continue
simpleMovement.blockBreakCosts()[blockArrayIndex] =
new MovementMiningCost(
absolutePositionBlock,
absoluteKey,
cacheableMiningCost.miningCost(),
cacheableMiningCost.willDrop(),
blockBreakSideHint);
Expand Down Expand Up @@ -578,7 +578,7 @@ public MinecraftGraph.SubscriptionSingleResult processBlock(MinecraftGraph graph
yield MinecraftGraph.SubscriptionSingleResult.CONTINUE;
}

if (!graph.canPlaceBlocks()
if (graph.disallowedToPlaceBlock(absoluteKey)
|| !simpleMovement.allowBlockActions()
|| !blockState.blockType().replaceable()) {
yield MinecraftGraph.SubscriptionSingleResult.IMPOSSIBLE;
Expand All @@ -602,7 +602,7 @@ public MinecraftGraph.SubscriptionSingleResult processBlock(MinecraftGraph graph
// Fixup the position to be the block we are placing against instead of relative
simpleMovement.blockPlaceAgainstData(
new BotActionManager.BlockPlaceAgainstData(
absolutePositionBlock, blockToPlaceAgainst.blockFace()));
absoluteKey, blockToPlaceAgainst.blockFace()));
yield MinecraftGraph.SubscriptionSingleResult.CONTINUE;
}
case MOVEMENT_ADD_CORNER_COST_IF_SOLID -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ private static UpMovement registerUpMovement(
}
}

{
blockSubscribers
.accept(movement.blockPlacePosition(), new UpMovementBlockSubscription(UpMovementBlockSubscription.SubscriptionType.MOVEMENT_SOLID));
}

{
var safeBlocks = movement.listCheckSafeMineBlocks();
for (var i = 0; i < safeBlocks.length; i++) {
Expand Down Expand Up @@ -145,6 +150,10 @@ public BlockSafetyData[][] listCheckSafeMineBlocks() {
return results;
}

public SFVec3i blockPlacePosition() {
return FEET_POSITION_RELATIVE_BLOCK;
}

@Override
public List<GraphInstructions> getInstructions(SFVec3i node) {
var actions = new ObjectArrayList<WorldAction>();
Expand Down Expand Up @@ -198,6 +207,10 @@ record UpMovementBlockSubscription(
int blockArrayIndex,
BlockFace blockBreakSideHint,
BlockSafetyData.BlockSafetyType safetyType) implements MinecraftGraph.MovementSubscription<UpMovement> {
UpMovementBlockSubscription(SubscriptionType type) {
this(type, -1, null, null);
}

UpMovementBlockSubscription(SubscriptionType type, int blockArrayIndex, BlockFace blockBreakSideHint) {
this(type, blockArrayIndex, blockBreakSideHint, null);
}
Expand All @@ -211,12 +224,7 @@ record UpMovementBlockSubscription(

@Override
public MinecraftGraph.SubscriptionSingleResult processBlock(MinecraftGraph graph, SFVec3i key, UpMovement upMovement, LazyBoolean isFree,
BlockState blockState, SFVec3i absolutePositionBlock) {
// Towering requires placing a block below
if (!graph.canPlaceBlocks()) {
return MinecraftGraph.SubscriptionSingleResult.IMPOSSIBLE;
}

BlockState blockState, SFVec3i absoluteKey) {
return switch (type) {
case MOVEMENT_FREE -> {
if (isFree.get()) {
Expand All @@ -237,12 +245,20 @@ public MinecraftGraph.SubscriptionSingleResult processBlock(MinecraftGraph graph
// We can mine this block, lets add costs and continue
upMovement.blockBreakCosts()[blockArrayIndex] =
new MovementMiningCost(
absolutePositionBlock,
absoluteKey,
cacheableMiningCost.miningCost(),
cacheableMiningCost.willDrop(),
blockBreakSideHint);
yield MinecraftGraph.SubscriptionSingleResult.CONTINUE;
}
case MOVEMENT_SOLID -> {
// Towering requires placing a block at old feet position
if (graph.disallowedToPlaceBlock(absoluteKey)) {
yield MinecraftGraph.SubscriptionSingleResult.IMPOSSIBLE;
}

yield MinecraftGraph.SubscriptionSingleResult.CONTINUE;
}
case MOVEMENT_BREAK_SAFETY_CHECK -> {
// There is no need to break this block, so there is no need for safety checks
if (upMovement.noNeedToBreak()[blockArrayIndex]) {
Expand Down Expand Up @@ -285,6 +301,7 @@ public UpMovement castAction(GraphAction action) {

enum SubscriptionType {
MOVEMENT_FREE,
MOVEMENT_SOLID,
MOVEMENT_BREAK_SAFETY_CHECK
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package com.soulfiremc.server.protocol.bot.block;

import com.soulfiremc.server.data.BlockState;
import java.util.OptionalInt;
import org.cloudburstmc.math.vector.Vector3i;

public interface BlockAccessor {
Expand All @@ -26,4 +27,8 @@ public interface BlockAccessor {
default BlockState getBlockState(Vector3i pos) {
return getBlockState(pos.getX(), pos.getY(), pos.getZ());
}

OptionalInt minBuildHeight();

OptionalInt maxBuildHeight();
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.soulfiremc.server.util.NoopLock;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.OptionalInt;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
Expand Down Expand Up @@ -134,6 +135,16 @@ public BlockState getBlockState(int x, int y, int z) {
return GlobalBlockPalette.INSTANCE.getBlockStateForStateId(chunkData.getBlock(x, y, z));
}

@Override
public OptionalInt minBuildHeight() {
return OptionalInt.of(minBuildHeight);
}

@Override
public OptionalInt maxBuildHeight() {
return OptionalInt.of(maxBuildHeight);
}

public Long2ObjectMap<ChunkData> getChunks() {
return chunks.clone();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.soulfiremc.server.pathfinding.SFVec3i;
import com.soulfiremc.server.protocol.bot.block.BlockAccessor;
import com.soulfiremc.server.util.Vec2ObjectOpenHashMap;
import java.util.OptionalInt;

public class TestBlockAccessor implements BlockAccessor {
private final Vec2ObjectOpenHashMap<SFVec3i, BlockState> blocks = new Vec2ObjectOpenHashMap<>();
Expand All @@ -43,4 +44,16 @@ public void setBlockAt(int x, int y, int z, BlockType block) {
public BlockState getBlockState(int x, int y, int z) {
return blocks.getOrDefault(new SFVec3i(x, y, z), defaultBlock);
}

@Override
public OptionalInt minBuildHeight() {
// For tests, it can be any height
return OptionalInt.empty();
}

@Override
public OptionalInt maxBuildHeight() {
// For tests, it can be any height
return OptionalInt.empty();
}
}

0 comments on commit 668ddae

Please sign in to comment.