Skip to content
Open
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 && mc.world != null) {
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 +279 to +280

Choose a reason for hiding this comment

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

high

When AutoSelect mode is enabled but the player is not looking at a block, the module currently shows a warning and remains active without performing any action. This can be confusing for the user, who might not notice the warning and wonder why the module isn't working.

A better approach would be to provide clearer feedback by showing an error message and automatically deactivating the module. This makes it explicit that the activation failed and why.

Suggested change
autoSelectBlock = null;
warning("No block is being targeted for auto-select mode.");
error("You must be looking at a block to use Auto-Select. Deactivating.");
toggle();

}
}
}

@Override
public void onDeactivate() {
if (listMode.get() == ListMode.AutoSelect) {
autoSelectBlock = null;
}
Comment on lines +285 to +289
Copy link

Choose a reason for hiding this comment

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

Missing State Reset

The onDeactivate method only resets autoSelectBlock but doesn't call the parent class implementation. This could lead to incomplete state reset when module is deactivated.

Standards
  • Clean-Code-Method-Completeness
  • Design-Pattern-Template-Method

}
Comment on lines +285 to 290
Copy link

Choose a reason for hiding this comment

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

Missing Reset Logic

onDeactivate() only resets autoSelectBlock for AutoSelect mode but ignores other state variables. This creates inconsistent state management where some fields are reset conditionally while others aren't reset at all.

Standards
  • Clean-Code-Consistency
  • Design-Pattern-State


@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) -> {
Comment on lines +376 to +377
Copy link

Choose a reason for hiding this comment

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

Suggestion: When switching from cube to uniform cube shape, the maxh/maxv values computed for the cube shape are still used inside BlockIterator.register, causing the iterator to scan a much larger volume than the current range requires, which can severely degrade performance by iterating over far more blocks than necessary. [possible bug]

Severity Level: Critical 🚨

Suggested change
BlockIterator.register(Math.max((int) Math.ceil(range.get() + 1), maxh),
Math.max((int) Math.ceil(range.get()), maxv), (blockPos, blockState) -> {
int hRadius;
int vRadius;
if (shape.get() == Shape.Cube) {
hRadius = maxh;
vRadius = maxv;
} else {
hRadius = (int) Math.ceil(range.get() + 1);
vRadius = (int) Math.ceil(range.get());
}
BlockIterator.register(hRadius, vRadius, (blockPos, blockState) -> {
Why it matters? ⭐

The suggestion correctly points out a real performance bug. maxh/maxv are computed only in the branch for the non-sphere/non-uniform cube (the code sets them inside the else for shape != UniformCube). If the user switches from Cube to UniformCube without resetting maxh/maxv, the previously computed larger values remain and Math.max(...) will pick those, causing BlockIterator to scan a much bigger volume than required by the uniform cube range. The proposed conditional selection of radii limits the iterator to the actual needed bounds for UniformCube and avoids unnecessary iterations.

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src/main/java/meteordevelopment/meteorclient/systems/modules/world/Nuker.java
**Line:** 376:377
**Comment:**
	*Possible Bug: When switching from cube to uniform cube shape, the `maxh`/`maxv` values computed for the cube shape are still used inside `BlockIterator.register`, causing the iterator to scan a much larger volume than the current `range` requires, which can severely degrade performance by iterating over far more blocks than necessary.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.

// 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 -> {
if (autoSelectBlock == null || !blockState.getBlock().equals(autoSelectBlock))
return;
Comment on lines +410 to +412
Copy link

Choose a reason for hiding this comment

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

Unrestricted Block Breaking

AutoSelect mode allows breaking specific blocks without rate limiting. Malicious users could target valuable blocks for rapid destruction, potentially causing server-side performance issues or griefing.

Suggested change
case AutoSelect -> {
if (autoSelectBlock == null || !blockState.getBlock().equals(autoSelectBlock))
return;
if (autoSelectBlock == null || !blockState.getBlock().equals(autoSelectBlock))
return;
// Apply rate limiting for AutoSelect mode
if (timer < delay.get()) return;
Standards
  • CWE-284
  • OWASP-A01

}
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