1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-12-25 01:20:31 +00:00

Rewrite turtle.dig tool actions

- Move the tool action before the "is block present" check, fixes
   #1527. This is where it was before, but we flipped it around in the
   tool rewrite.

 - Don't reuse as much turtle.place logic for tool actions. This fixes
   some instances where tools could till/level dirt through solid
   blocks.
This commit is contained in:
Jonathan Coates 2023-07-21 08:58:02 +01:00
parent 1b88213eca
commit 0ad399a528
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
5 changed files with 154 additions and 17 deletions

View File

@ -74,7 +74,7 @@ public class TurtlePlaceCommand implements TurtleCommand {
} }
} }
public static boolean deploy( private static boolean deploy(
ItemStack stack, ITurtleAccess turtle, TurtlePlayer turtlePlayer, Direction direction, ItemStack stack, ITurtleAccess turtle, TurtlePlayer turtlePlayer, Direction direction,
@Nullable Object[] extraArguments, @Nullable ErrorMessage outErrorMessage @Nullable Object[] extraArguments, @Nullable ErrorMessage outErrorMessage
) { ) {
@ -140,6 +140,22 @@ public class TurtlePlaceCommand implements TurtleCommand {
return true; return true;
} }
/**
* Calculate where a turtle would interact with a block.
*
* @param position The position of the block.
* @param side The side the turtle is clicking on.
* @return The hit result.
*/
public static BlockHitResult getHitResult(BlockPos position, Direction side) {
var hitX = 0.5 + side.getStepX() * 0.5;
var hitY = 0.5 + side.getStepY() * 0.5;
var hitZ = 0.5 + side.getStepZ() * 0.5;
if (Math.abs(hitY - 0.5) < 0.01) hitY = 0.45;
return new BlockHitResult(new Vec3(position.getX() + hitX, position.getY() + hitY, position.getZ() + hitZ), side, position, false);
}
private static boolean deployOnBlock( private static boolean deployOnBlock(
ItemStack stack, ITurtleAccess turtle, TurtlePlayer turtlePlayer, BlockPos position, Direction side, ItemStack stack, ITurtleAccess turtle, TurtlePlayer turtlePlayer, BlockPos position, Direction side,
@Nullable Object[] extraArguments, boolean adjacent, @Nullable ErrorMessage outErrorMessage @Nullable Object[] extraArguments, boolean adjacent, @Nullable ErrorMessage outErrorMessage
@ -149,14 +165,8 @@ public class TurtlePlaceCommand implements TurtleCommand {
var playerPosition = position.relative(side); var playerPosition = position.relative(side);
turtlePlayer.setPosition(turtle, playerPosition, playerDir); turtlePlayer.setPosition(turtle, playerPosition, playerDir);
// Calculate where the turtle would hit the block
var hitX = 0.5f + side.getStepX() * 0.5f;
var hitY = 0.5f + side.getStepY() * 0.5f;
var hitZ = 0.5f + side.getStepZ() * 0.5f;
if (Math.abs(hitY - 0.5f) < 0.01f) hitY = 0.45f;
// Check if there's something suitable to place onto // Check if there's something suitable to place onto
var hit = new BlockHitResult(new Vec3(position.getX() + hitX, position.getY() + hitY, position.getZ() + hitZ), side, position, false); var hit = getHitResult(position, side);
var context = new UseOnContext(turtlePlayer.player(), InteractionHand.MAIN_HAND, hit); var context = new UseOnContext(turtlePlayer.player(), InteractionHand.MAIN_HAND, hit);
if (!canDeployOnBlock(new BlockPlaceContext(context), turtle, turtlePlayer, position, side, adjacent, outErrorMessage)) { if (!canDeployOnBlock(new BlockPlaceContext(context), turtle, turtlePlayer, position, side, adjacent, outErrorMessage)) {
return false; return false;

View File

@ -294,19 +294,20 @@ public class TurtleTool extends AbstractTurtleUpgrade {
private TurtleCommandResult dig(ITurtleAccess turtle, TurtleSide side, Direction direction) { private TurtleCommandResult dig(ITurtleAccess turtle, TurtleSide side, Direction direction) {
var level = (ServerLevel) turtle.getLevel(); var level = (ServerLevel) turtle.getLevel();
var blockPosition = turtle.getPosition().relative(direction);
if (level.isEmptyBlock(blockPosition) || WorldUtil.isLiquidBlock(level, blockPosition)) {
return TurtleCommandResult.failure("Nothing to dig here");
}
return withEquippedItem(turtle, side, direction, turtlePlayer -> { return withEquippedItem(turtle, side, direction, turtlePlayer -> {
var stack = turtlePlayer.player().getItemInHand(InteractionHand.MAIN_HAND); var stack = turtlePlayer.player().getItemInHand(InteractionHand.MAIN_HAND);
// Right-click the block when using a shovel/hoe. // Right-click the block when using a shovel/hoe. Important that we do this before checking the block is
if (PlatformHelper.get().hasToolUsage(item) && TurtlePlaceCommand.deploy(stack, turtle, turtlePlayer, direction, null, null)) { // present, as we allow doing these actions from slightly further away.
if (PlatformHelper.get().hasToolUsage(stack) && useTool(level, turtle, turtlePlayer, stack, direction)) {
return TurtleCommandResult.success(); return TurtleCommandResult.success();
} }
var blockPosition = turtle.getPosition().relative(direction);
if (level.isEmptyBlock(blockPosition) || WorldUtil.isLiquidBlock(level, blockPosition)) {
return TurtleCommandResult.failure("Nothing to dig here");
}
// Check if we can break the block // Check if we can break the block
var breakable = checkBlockBreakable(level, blockPosition, turtlePlayer); var breakable = checkBlockBreakable(level, blockPosition, turtlePlayer);
if (!breakable.isSuccess()) return breakable; if (!breakable.isSuccess()) return breakable;
@ -320,6 +321,32 @@ public class TurtleTool extends AbstractTurtleUpgrade {
}); });
} }
/**
* Attempt to use a tool against a block instead.
*
* @param level The current level.
* @param turtle The current turtle.
* @param turtlePlayer The turtle player, already positioned and with a stack equipped.
* @param stack The current tool's stack.
* @param direction The direction this action occurs in.
* @return Whether the tool was successfully used.
* @see PlatformHelper#hasToolUsage(ItemStack)
*/
private boolean useTool(ServerLevel level, ITurtleAccess turtle, TurtlePlayer turtlePlayer, ItemStack stack, Direction direction) {
var position = turtle.getPosition().relative(direction);
// Allow digging one extra block below the turtle, as you can't till dirt/flatten grass if there's a block
// above.
if (direction == Direction.DOWN && level.isEmptyBlock(position)) position = position.relative(direction);
if (!level.isInWorldBounds(position) || level.isEmptyBlock(position) || turtlePlayer.isBlockProtected(level, position)) {
return false;
}
var hit = TurtlePlaceCommand.getHitResult(position, direction.getOpposite());
var result = PlatformHelper.get().useOn(turtlePlayer.player(), stack, hit, x -> false);
return result.consumesAction();
}
private static boolean isTriviallyBreakable(BlockGetter reader, BlockPos pos, BlockState state) { private static boolean isTriviallyBreakable(BlockGetter reader, BlockPos pos, BlockState state) {
return state.is(ComputerCraftTags.Blocks.TURTLE_ALWAYS_BREAKABLE) return state.is(ComputerCraftTags.Blocks.TURTLE_ALWAYS_BREAKABLE)
// Allow breaking any "instabreak" block. // Allow breaking any "instabreak" block.

View File

@ -145,11 +145,31 @@ class Turtle_Test {
*/ */
@GameTest @GameTest
fun Hoe_dirt(helper: GameTestHelper) = helper.sequence { fun Hoe_dirt(helper: GameTestHelper) = helper.sequence {
thenOnComputer { turtle.dig(Optional.empty()).await().assertArrayEquals(true, message = "Dug with hoe") }
thenExecute { helper.assertBlockPresent(Blocks.FARMLAND, BlockPos(1, 2, 1)) }
}
/**
* Checks turtles can hoe dirt with a block gap below them.
*
* @see [#1527](https://github.com/cc-tweaked/CC-Tweaked/issues/1527)
*/
@GameTest
fun Hoe_dirt_below(helper: GameTestHelper) = helper.sequence {
thenOnComputer { turtle.digDown(Optional.empty()).await().assertArrayEquals(true, message = "Dug with hoe") }
thenExecute { helper.assertBlockPresent(Blocks.FARMLAND, BlockPos(1, 1, 1)) }
}
/**
* Checks turtles cannot hoe dirt with a block gap in front of them.
*/
@GameTest
fun Hoe_dirt_distant(helper: GameTestHelper) = helper.sequence {
thenOnComputer { thenOnComputer {
turtle.dig(Optional.empty()).await() turtle.dig(Optional.empty()).await()
.assertArrayEquals(true, message = "Dug with hoe") .assertArrayEquals(false, "Nothing to dig here", message = "Dug with hoe")
} }
thenExecute { helper.assertBlockPresent(Blocks.FARMLAND, BlockPos(1, 2, 1)) } thenExecute { helper.assertBlockPresent(Blocks.DIRT, BlockPos(1, 2, 2)) }
} }
/** /**

View File

@ -0,0 +1,40 @@
{
DataVersion: 2730,
size: [3, 3, 3],
data: [
{pos: [0, 0, 0], state: "minecraft:polished_andesite"},
{pos: [0, 0, 1], state: "minecraft:polished_andesite"},
{pos: [0, 0, 2], state: "minecraft:polished_andesite"},
{pos: [1, 0, 0], state: "minecraft:polished_andesite"},
{pos: [1, 0, 1], state: "minecraft:dirt"},
{pos: [1, 0, 2], state: "minecraft:polished_andesite"},
{pos: [2, 0, 0], state: "minecraft:polished_andesite"},
{pos: [2, 0, 1], state: "minecraft:polished_andesite"},
{pos: [2, 0, 2], state: "minecraft:polished_andesite"},
{pos: [0, 1, 0], state: "minecraft:air"},
{pos: [0, 1, 1], state: "minecraft:air"},
{pos: [0, 1, 2], state: "minecraft:air"},
{pos: [1, 1, 0], state: "minecraft:air"},
{pos: [1, 1, 1], state: "minecraft:air"},
{pos: [1, 1, 2], state: "minecraft:air"},
{pos: [2, 1, 0], state: "minecraft:air"},
{pos: [2, 1, 1], state: "minecraft:air"},
{pos: [2, 1, 2], state: "minecraft:air"},
{pos: [0, 2, 0], state: "minecraft:air"},
{pos: [0, 2, 1], state: "minecraft:air"},
{pos: [0, 2, 2], state: "minecraft:air"},
{pos: [1, 2, 0], state: "minecraft:air"},
{pos: [1, 2, 1], state: "computercraft:turtle_normal{facing:south,waterlogged:false}", nbt: {ComputerId: 1, Fuel: 0, Items: [], Label: "turtle_test.hoe_dirt_below", LeftUpgrade: "minecraft:diamond_hoe", On: 1b, Owner: {LowerId: -6876936588741668278L, Name: "Dev", UpperId: 4039158846114182220L}, Slot: 0, id: "computercraft:turtle_normal"}},
{pos: [1, 2, 2], state: "minecraft:air"},
{pos: [2, 2, 0], state: "minecraft:air"},
{pos: [2, 2, 1], state: "minecraft:air"},
{pos: [2, 2, 2], state: "minecraft:air"}
],
entities: [],
palette: [
"minecraft:polished_andesite",
"minecraft:dirt",
"computercraft:turtle_normal{facing:south,waterlogged:false}",
"minecraft:air"
]
}

View File

@ -0,0 +1,40 @@
{
DataVersion: 2730,
size: [3, 3, 3],
data: [
{pos: [0, 0, 0], state: "minecraft:polished_andesite"},
{pos: [0, 0, 1], state: "minecraft:polished_andesite"},
{pos: [0, 0, 2], state: "minecraft:polished_andesite"},
{pos: [1, 0, 0], state: "minecraft:polished_andesite"},
{pos: [1, 0, 1], state: "minecraft:polished_andesite"},
{pos: [1, 0, 2], state: "minecraft:polished_andesite"},
{pos: [2, 0, 0], state: "minecraft:polished_andesite"},
{pos: [2, 0, 1], state: "minecraft:polished_andesite"},
{pos: [2, 0, 2], state: "minecraft:polished_andesite"},
{pos: [0, 1, 0], state: "minecraft:air"},
{pos: [0, 1, 1], state: "minecraft:air"},
{pos: [0, 1, 2], state: "minecraft:air"},
{pos: [1, 1, 0], state: "computercraft:turtle_normal{facing:south,waterlogged:false}", nbt: {ComputerId: 1, Fuel: 0, Items: [], Label: "turtle_test.hoe_dirt_distant", LeftUpgrade: "minecraft:diamond_hoe", On: 1b, Owner: {LowerId: -6876936588741668278L, Name: "Dev", UpperId: 4039158846114182220L}, Slot: 0, id: "computercraft:turtle_normal"}},
{pos: [1, 1, 1], state: "minecraft:air"},
{pos: [1, 1, 2], state: "minecraft:dirt"},
{pos: [2, 1, 0], state: "minecraft:air"},
{pos: [2, 1, 1], state: "minecraft:air"},
{pos: [2, 1, 2], state: "minecraft:air"},
{pos: [0, 2, 0], state: "minecraft:air"},
{pos: [0, 2, 1], state: "minecraft:air"},
{pos: [0, 2, 2], state: "minecraft:air"},
{pos: [1, 2, 0], state: "minecraft:air"},
{pos: [1, 2, 1], state: "minecraft:air"},
{pos: [1, 2, 2], state: "minecraft:air"},
{pos: [2, 2, 0], state: "minecraft:air"},
{pos: [2, 2, 1], state: "minecraft:air"},
{pos: [2, 2, 2], state: "minecraft:air"}
],
entities: [],
palette: [
"minecraft:polished_andesite",
"minecraft:dirt",
"computercraft:turtle_normal{facing:south,waterlogged:false}",
"minecraft:air"
]
}