Skip to content

Add auto-select mode to nuker #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import net.minecraft.block.Block;
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
Expand Down Expand Up @@ -182,6 +184,8 @@ public class Nuker extends Module {
.build()
);

private Block autoSelectBlock = null; // Internal field to store the selected block for AutoSelect mode

// Rendering

private final Setting<Boolean> enableRenderBounding = sgRender.add(new BoolSetting.Builder()
Expand All @@ -201,14 +205,14 @@ public class Nuker extends Module {
private final Setting<SettingColor> sideColorBox = sgRender.add(new ColorSetting.Builder()
.name("side-color")
.description("The side color of the bounding box.")
.defaultValue(new SettingColor(16,106,144, 100))
.defaultValue(new SettingColor(16, 106, 144, 100))
.build()
);

private final Setting<SettingColor> lineColorBox = sgRender.add(new ColorSetting.Builder()
.name("line-color")
.description("The line color of the bounding box.")
.defaultValue(new SettingColor(16,106,144, 255))
.defaultValue(new SettingColor(16, 106, 144, 255))
.build()
);

Expand Down Expand Up @@ -265,6 +269,24 @@ public void onActivate() {
firstBlock = true;
timer = 0;
noBlockTimer = 0;

if (listMode.get() == ListMode.AutoSelect) {
HitResult hitResult = mc.crosshairTarget;
if (hitResult != null && hitResult.getType() == HitResult.Type.BLOCK) {
BlockPos pos = ((BlockHitResult) hitResult).getBlockPos();
autoSelectBlock = mc.world.getBlockState(pos).getBlock();
} else {
autoSelectBlock = null;
warning("No block is being targeted for auto-select mode.");
Comment on lines +273 to +280
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Validation for AutoSelect Block Target

The AutoSelect mode initializes the target block only once when the module is activated, but does not validate that a block is successfully selected before allowing the module to run. If no block is targeted during activation (autoSelectBlock is null), the module will still be enabled but won't break any blocks, potentially confusing users. More critically, if the module is activated with no block in sight and then the user looks at a block, the module will remain ineffective without any clear indication of the problem.

if (listMode.get() == ListMode.AutoSelect) {
    HitResult hitResult = mc.crosshairTarget;
    if (hitResult != null && hitResult.getType() == HitResult.Type.BLOCK) {
        BlockPos pos = ((BlockHitResult) hitResult).getBlockPos();
        autoSelectBlock = mc.world.getBlockState(pos).getBlock();
        info("Auto-selected block: " + autoSelectBlock.getName().getString());
    } else {
        autoSelectBlock = null;
        error("No block is being targeted for auto-select mode. Please look at a block and try again.");
        this.toggle(); // Disable the module if no block is targeted
        return; // Exit early
    }
}

References

Standard: CWE-754: Improper Check for Unusual or Exceptional Conditions
Standard: OWASP Top 10 2021: A08 - Software and Data Integrity Failures

}
}
}

@Override
public void onDeactivate() {
if (listMode.get() == ListMode.AutoSelect) {
autoSelectBlock = null;
}
}

@EventHandler
Expand Down Expand Up @@ -351,35 +373,57 @@ private void onTickPre(TickEvent.Pre event) {
Box box = new Box(pos1.toCenterPos(), pos2.toCenterPos());

// Find blocks to break
BlockIterator.register(Math.max((int) Math.ceil(range.get() + 1), maxh), Math.max((int) Math.ceil(range.get()), maxv), (blockPos, blockState) -> {
// Check for air, unbreakable blocks and distance
switch (shape.get()) {
case Sphere -> {
if (Utils.squaredDistance(pX, pY, pZ, blockPos.getX() + 0.5, blockPos.getY() + 0.5, blockPos.getZ() + 0.5) > rangeSq) return;
}
case UniformCube -> {
if (chebyshevDist(mc.player.getBlockPos().getX(), mc.player.getBlockPos().getY(), mc.player.getBlockPos().getZ(), blockPos.getX(), blockPos.getY(), blockPos.getZ()) >= range.get()) return;
}
case Cube -> {
if (!box.contains(Vec3d.ofCenter(blockPos))) return;
}
}

if (!BlockUtils.canBreak(blockPos, blockState)) return;

// Flatten
if (mode.get() == Mode.Flatten && blockPos.getY() < Math.floor(mc.player.getY())) return;

// Smash
if (mode.get() == Mode.Smash && blockState.getHardness(mc.world, blockPos) != 0) return;

// Check whitelist or blacklist
if (listMode.get() == ListMode.Whitelist && !whitelist.get().contains(blockState.getBlock())) return;
if (listMode.get() == ListMode.Blacklist && blacklist.get().contains(blockState.getBlock())) return;

// Add block
blocks.add(blockPos.toImmutable());
});
BlockIterator.register(Math.max((int) Math.ceil(range.get() + 1), maxh),
Math.max((int) Math.ceil(range.get()), maxv), (blockPos, blockState) -> {
// Check for air, unbreakable blocks and distance
switch (shape.get()) {
case Sphere -> {
if (Utils.squaredDistance(pX, pY, pZ, blockPos.getX() + 0.5, blockPos.getY() + 0.5,
blockPos.getZ() + 0.5) > rangeSq)
return;
}
case UniformCube -> {
if (chebyshevDist(mc.player.getBlockPos().getX(), mc.player.getBlockPos().getY(),
mc.player.getBlockPos().getZ(), blockPos.getX(), blockPos.getY(),
blockPos.getZ()) >= range.get())
return;
}
case Cube -> {
if (!box.contains(Vec3d.ofCenter(blockPos)))
return;
}
}

if (!BlockUtils.canBreak(blockPos, blockState))
return;

// Flatten
if (mode.get() == Mode.Flatten && blockPos.getY() < Math.floor(mc.player.getY()))
return;

// Smash
if (mode.get() == Mode.Smash && blockState.getHardness(mc.world, blockPos) != 0)
return;

// Check list mode
switch (listMode.get()) {
case AutoSelect -> {
Comment on lines +409 to +410
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant Block Type Checking in AutoSelect Mode

The AutoSelect mode performs an equality check on every block in range, which is inefficient. For large ranges, this can result in thousands of object equality comparisons per tick. The current implementation also doesn't handle the case where autoSelectBlock is null efficiently, as it will still iterate through all blocks in range before determining none match.

                        case AutoSelect -> {
                            // Skip all processing if no block is selected
                            if (autoSelectBlock == null) return;
                            // Use == for faster reference comparison before equals()
                            if (blockState.getBlock() != autoSelectBlock && !blockState.getBlock().equals(autoSelectBlock))
                                return;

References

Standard: Java Performance Best Practices - Object Comparison Optimization

if (autoSelectBlock == null || !blockState.getBlock().equals(autoSelectBlock))
return;
Comment on lines +409 to +412
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential NullPointerException in Block Selection Logic

The AutoSelect mode implementation checks if autoSelectBlock is null or doesn't match the current block, but there's no safeguard against autoSelectBlock being null during module operation. While the onActivate method attempts to initialize it, there could be cases where it remains null (e.g., if the target block changes after activation). This could lead to unpredictable behavior or crashes when the module is running.

                        case AutoSelect -> {
                            if (autoSelectBlock == null) {
                                error("Auto-select block is null. Disabling module.");
                                toggle();
                                return;
                            }
                            if (!blockState.getBlock().equals(autoSelectBlock))
                                return;
                        }

References

Standard: Design by Contract - Precondition Validation

}
case Whitelist -> {
if (!whitelist.get().contains(blockState.getBlock()))
return;
}
case Blacklist -> {
if (blacklist.get().contains(blockState.getBlock()))
return;
}
}

// Add block
blocks.add(blockPos.toImmutable());
});

// Break block if found
BlockIterator.after(() -> {
Expand Down Expand Up @@ -449,9 +493,15 @@ private void onBlockBreakingCooldown(BlockBreakingCooldownEvent event) {
event.cooldown = 0;
}

// Getter for GUI display
public Block getAutoSelectBlock() {
return autoSelectBlock;
}

public enum ListMode {
Whitelist,
Blacklist
Blacklist,
AutoSelect
}

public enum Mode {
Expand Down