public class HammerHandler implements Listener {
@EventHandler(priority = EventPriority.HIGHEST)
public void onBlockBreak(BlockBreakEvent e) {
Player player = e.getPlayer();
ItemStack tool = player.getInventory().getItemInMainHand();
if(!isMyHammer(tool)) {
return;
}
Block block = e.getBlock();
final double breakRange = player.getGameMode() == GameMode.CREATIVE ? 5 : 4.5;
Location playerPos = player.getLocation();
Location eyePos = player.getEyeLocation();
RayTraceResult ray = player.getWorld().rayTraceBlocks(eyePos, playerPos.getDirection(), breakRange, FluidCollisionMode.NEVER, true);
BlockFace face;
if(ray == null || ray.getHitBlock() == null || !ray.getHitBlock().equals(block) || (face = ray.getHitBlockFace()) == null) {
return;
}
Axis faceAxis = getAxis(face);
final int width = 5;
final int height = 3;
final int depth = 1;
Axis depthAxis = faceAxis;
Axis heightAxis = switch(faceAxis) {
case X, Z -> Axis.Y;
case Y -> {
double xRot = playerPos.getYaw();
if(Math.signum(xRot) == -1.0) {
xRot += 360;
}
if((xRot >= 45 && xRot < 135) || (xRot >= 225 && xRot < 315)) {
yield Axis.X;
}
else {
yield Axis.Z;
}
}
};
Axis widthAxis = switch(faceAxis) {
case X -> Axis.Z;
case Y -> (heightAxis == Axis.X) ? Axis.Z : Axis.X;
case Z -> Axis.X;
};
final int startWidth = -(width / 2);
final int endWidth = width + startWidth - 1;
final int startHeight = -(height / 2);
final int endHeight = height + startHeight - 1;
final int startDepth = 0;
final int endDepth = depth - 1;
for(int w = startWidth; w <= endWidth; ++w) {
for(int h = startHeight; h <= endHeight; ++h) {
for(int d = startDepth; d <= endDepth; ++d) {
int x = 0, y = 0, z = 0;
switch(widthAxis) {
case X -> x = w;
case Y -> y = w;
case Z -> z = w;
}
switch(heightAxis) {
case X -> x = h;
case Y -> y = h;
case Z -> z = h;
}
switch(depthAxis) {
case X -> x = d;
case Y -> y = d;
case Z -> z = d;
}
Block relative = block.getRelative(x, y, z);
if(relative.getType() != Material.BEDROCK) {
relative.breakNaturally(tool);
}
}
}
}
}
private static boolean isMyHammer(@Nullable ItemStack tool) {
ItemMeta meta;
return tool != null && tool.getType() == Material.NETHERITE_PICKAXE && tool.hasItemMeta() && (meta = tool.getItemMeta()).hasDisplayName() && meta.getDisplayName().equals("Variegatus");
}
@NotNull
public static Axis getAxis(BlockFace face) {
return switch(face) {
case EAST, WEST -> Axis.X;
case UP, DOWN, SELF -> Axis.Y;
case NORTH, SOUTH -> Axis.Z;
default -> throw new IllegalArgumentException("non-cartesian face: " + face.name());
};
}
}