Skip to content

Conversation

@Kyuunex
Copy link

@Kyuunex Kyuunex commented Nov 9, 2025

Type of change

  • Bug fix
  • New feature

Description

Constantiam.net today started up a test server and it's running GrimAC.
Nuker wouldn't work because the direction to break the block from isn't accurately calculated.
It was checking only against the bottom side of the block.
It wasn't taking the block height into account.

As an example, if the player pos is Y=70, block to break is Y=71, the eye position is Y=71.62000000476837, in that scenario, it would still try breaking the block from the top because it's comparing 71.62000000476837 to 71, not taking block height into account.

While this worked with the server's previous anticheat, Grim likes to bitch and moan about minutiae like this. So I fixed it.

Related issues

Cant find

How Has This Been Tested?

I tested it. Videos attached.

before:
https://github.com/user-attachments/assets/5d22928a-b496-4ec8-a77a-95454bd53865

after:
https://github.com/user-attachments/assets/38faa663-cb41-4951-9a3e-6400927a4907

Checklist:

  • My code follows the style guidelines of this project. (let me know if it doesnt)
  • I have added comments to my code in more complex areas. (not relevant)
  • I have tested the code in both development and production environments.

@crosby-moe
Copy link
Collaborator

i reckon this function still contains more bugs like this, like how only one of the branches returning mc.player.getHorizontalFacing().getOpposite() checks for !mc.world.getBlockState(pos.add(0, 1, 0)).isReplaceable()?

even then isReplaceable() is the wrong check to use since nuker doesn't place blocks, it breaks & interacts, which means we should either raycast or compare outline shapes

although i'm not sure grim has checks for those in particular, grim would maybe have a check similar to the one you fixed for returning Direction.DOWN when eyesPos.y > pos.getY() but eyesPos.y - pos.getY() < getBlockHeight(pos), when the eyes are between the top & bottom of the block

this would be better modeled as

public static Direction getDirection(BlockPos pos) {
    double eyePos = mc.player.getY() + mc.player.getEyeHeight(mc.player.getPose());
    VoxelShape outline = mc.world.getBlockState(pos).getCollisionShape(mc.world, pos);
    if (eyePos > pos.getY() + outline.getMax(Direction.Axis.Y) && mc.world.getBlockState(pos.add(0, 1, 0)).isReplaceable()) {
        return Direction.UP;
    } else if (eyePos < pos.getY() + outline.getMin(Direction.Axis.Y) && mc.world.getBlockState(pos.add(0, -1, 0)).isReplaceable()) {
        return Direction.DOWN;
    } else {
        // insert possible additional checks here
        return mc.player.getHorizontalFacing().getOpposite();
    }
}

@Kyuunex
Copy link
Author

Kyuunex commented Nov 9, 2025

I tested your updated method and it also seems to work well. I'm new to contributing here, so what would be my next steps? updating my PR with your updated method?

@crosby-moe
Copy link
Collaborator

I tested your updated method and it also seems to work well. I'm new to contributing here, so what would be my next steps? updating my PR with your updated method?

yeah, unfortunately making it better from there would require bigger refactors

@Kyuunex
Copy link
Author

Kyuunex commented Nov 11, 2025

I found further issues when "rotate" in nuker is turned off, such as it breaking from south instead of north. better to hold off merging this for now

although it still works well if "rotate" is turned on in nuker.

@Kyuunex
Copy link
Author

Kyuunex commented Nov 11, 2025

Here's something I just cooked up to make it work well without having rotations on.

public static Direction getDirection(BlockPos pos) {
    double eyePos = mc.player.getY() + mc.player.getEyeHeight(mc.player.getPose());
    VoxelShape outline = mc.world.getBlockState(pos).getCollisionShape(mc.world, pos);
    if (eyePos > pos.getY() + outline.getMax(Direction.Axis.Y) && mc.world.getBlockState(pos.add(0, 1, 0)).isReplaceable()) {
        return Direction.UP;
    } else if (eyePos < pos.getY() + outline.getMin(Direction.Axis.Y) && mc.world.getBlockState(pos.add(0, -1, 0)).isReplaceable()) {
        return Direction.DOWN;
    } else {
        BlockPos difference = pos.subtract(mc.player.getBlockPos());

        if (Math.abs(difference.getX()) > Math.abs(difference.getZ())) {
            return difference.getX() > 0 ? Direction.WEST : Direction.EAST;
        } else {
            return difference.getZ() > 0 ? Direction.NORTH : Direction.SOUTH;
        }
    }
}

I would like some feedback. I'm not deeply knowledgeable with Minecraft internals, but if Minecraft has built-in methods to do this, I'd like to know.

EDIT: cleanup code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants