Skip to content

Commit 7c21392

Browse files
committed
Above Ground Option Added
1 parent f77741b commit 7c21392

File tree

14 files changed

+403
-6
lines changed

14 files changed

+403
-6
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,11 @@ Examples:
223223
### Larger Scan Radius
224224
- Extended up to 65×65 chunks for all chunk-based features.
225225

226+
### Above Ground (New Option)
227+
- ItemESP, MobSearch, ChestESP, BedESP, SignESP, PortalESP, RedstoneESP and WorkstationESP now have an adjustable Y limit (default 62 which is approximately sea level)
228+
- There is a global toggle and setting that can apply to all, or the user can set toggle and set them individually in the hack's settings (```.aboveground on/off```, ```.aboveground toggle```, ```.aboveground y #```)
229+
- This will help prevent you from detecting inaccessible mobs/items and essentially only scanning the surface of the world
230+
226231
### Sticky Area (New Option)
227232
- Added to chunk-based ESPs (Search, Portal ESP, BedESP, SignESP, WorkstationESP, RedstoneESP, ChestESP).
228233
- Keeps results anchored as you move. Default OFF.

src/main/java/net/wurstclient/command/CmdList.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public final class CmdList
5959
public final SetColorCmd setColorCmd = new SetColorCmd();
6060
public final SetModeCmd setModeCmd = new SetModeCmd();
6161
public final SetSliderCmd setSliderCmd = new SetSliderCmd();
62+
public final AboveGroundCmd aboveGroundCmd = new AboveGroundCmd();
6263
public final SettingsCmd settingsCmd = new SettingsCmd();
6364
public final NecoCmd NecoCmd = new NecoCmd();
6465
public final TCmd tCmd = new TCmd();
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* Copyright (c) 2014-2025 Wurst-Imperium and contributors.
3+
*
4+
* This source code is subject to the terms of the GNU General Public
5+
* License, version 3. If a copy of the GPL was not distributed with this
6+
* file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt
7+
*/
8+
package net.wurstclient.commands;
9+
10+
import net.wurstclient.WurstClient;
11+
import net.wurstclient.command.CmdException;
12+
import net.wurstclient.command.CmdSyntaxError;
13+
import net.wurstclient.command.Command;
14+
import net.wurstclient.util.ChatUtils;
15+
import net.wurstclient.util.MathUtils;
16+
17+
public final class AboveGroundCmd extends Command
18+
{
19+
public AboveGroundCmd()
20+
{
21+
super("aboveground",
22+
"Global above-ground ESP filter for supported hacks.",
23+
".aboveground (on|off|toggle)", ".aboveground y <value>",
24+
".aboveground <value>");
25+
}
26+
27+
@Override
28+
public void call(String[] args) throws CmdException
29+
{
30+
if(args.length == 0)
31+
throw new CmdSyntaxError();
32+
String a = args[0].toLowerCase();
33+
// Single-word actions
34+
if(args.length == 1)
35+
{
36+
if(a.equals("on"))
37+
{
38+
WurstClient.INSTANCE.getHax().setAboveGroundFilterEnabled(true);
39+
ChatUtils.message(
40+
"Above-ground filter enabled for supported hacks.");
41+
return;
42+
}
43+
if(a.equals("off"))
44+
{
45+
WurstClient.INSTANCE.getHax()
46+
.setAboveGroundFilterEnabled(false);
47+
ChatUtils.message(
48+
"Above-ground filter disabled for supported hacks.");
49+
return;
50+
}
51+
if(a.equals("toggle"))
52+
{
53+
// Toggle: invert by enabling when currently all disabled is
54+
// unknown.
55+
// We'll simply enable if arg toggled on; user can set
56+
// explicitly.
57+
// For simplicity, toggle will enable when called.
58+
WurstClient.INSTANCE.getHax().setAboveGroundFilterEnabled(true);
59+
ChatUtils.message("Above-ground filter toggled (enabled).");
60+
return;
61+
}
62+
// numeric provided -> set Y
63+
if(MathUtils.isDouble(a))
64+
{
65+
int y = (int)Double.parseDouble(a);
66+
WurstClient.INSTANCE.getHax().setAboveGroundFilterY(y);
67+
ChatUtils.message(
68+
"Above-ground Y set to " + y + " for supported hacks.");
69+
return;
70+
}
71+
throw new CmdSyntaxError();
72+
}
73+
74+
// Two-argument forms: "y <value>" or "on/off <value>" to enable and set
75+
// Y
76+
if(args.length == 2)
77+
{
78+
if(a.equals("y") || a.equals("set"))
79+
{
80+
if(!MathUtils.isDouble(args[1]))
81+
throw new CmdSyntaxError("Y must be a number.");
82+
int y = (int)Double.parseDouble(args[1]);
83+
WurstClient.INSTANCE.getHax().setAboveGroundFilterY(y);
84+
ChatUtils.message(
85+
"Above-ground Y set to " + y + " for supported hacks.");
86+
return;
87+
}
88+
if(a.equals("on") || a.equals("off"))
89+
{
90+
boolean enabled = a.equals("on");
91+
WurstClient.INSTANCE.getHax()
92+
.setAboveGroundFilterEnabled(enabled);
93+
if(!MathUtils.isDouble(args[1]))
94+
{
95+
ChatUtils.message("Above-ground filter "
96+
+ (enabled ? "enabled" : "disabled") + ".");
97+
return;
98+
}
99+
int y = (int)Double.parseDouble(args[1]);
100+
WurstClient.INSTANCE.getHax().setAboveGroundFilterY(y);
101+
ChatUtils.message(
102+
"Above-ground filter " + (enabled ? "enabled" : "disabled")
103+
+ " and Y set to " + y + ".");
104+
return;
105+
}
106+
throw new CmdSyntaxError();
107+
}
108+
throw new CmdSyntaxError();
109+
}
110+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (c) 2014-2025 Wurst-Imperium and contributors.
3+
*
4+
* This source code is subject to the terms of the GNU General Public
5+
* License, version 3. If a copy of the GPL was not distributed with this
6+
* file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt
7+
*/
8+
package net.wurstclient.hack;
9+
10+
import java.lang.reflect.Field;
11+
12+
import net.wurstclient.settings.CheckboxSetting;
13+
import net.wurstclient.settings.SliderSetting;
14+
15+
/**
16+
* Utility to toggle or set the above-ground filter settings on hacks that
17+
* expose them. Uses reflection to avoid tightly coupling hack classes.
18+
*/
19+
public final class AboveGroundFilterManager
20+
{
21+
public static void toggle(HackList hacks, boolean enabled)
22+
{
23+
for(Hack h : hacks.getAllHax())
24+
{
25+
try
26+
{
27+
Field f = findField(h.getClass(), "onlyAboveGround");
28+
if(f != null)
29+
{
30+
f.setAccessible(true);
31+
Object val = f.get(h);
32+
if(val instanceof CheckboxSetting cs)
33+
cs.setChecked(enabled);
34+
}
35+
}catch(Throwable ignored)
36+
{}
37+
}
38+
}
39+
40+
public static void setY(HackList hacks, int y)
41+
{
42+
for(Hack h : hacks.getAllHax())
43+
{
44+
try
45+
{
46+
Field f = findField(h.getClass(), "aboveGroundY");
47+
if(f != null)
48+
{
49+
f.setAccessible(true);
50+
Object val = f.get(h);
51+
if(val instanceof SliderSetting ss)
52+
ss.setValue(y);
53+
}
54+
}catch(Throwable ignored)
55+
{}
56+
}
57+
}
58+
59+
private static Field findField(Class<?> cls, String name)
60+
{
61+
Class<?> c = cls;
62+
while(c != null && c != Object.class)
63+
{
64+
try
65+
{
66+
Field f = c.getDeclaredField(name);
67+
return f;
68+
}catch(NoSuchFieldException e)
69+
{
70+
c = c.getSuperclass();
71+
}
72+
}
73+
return null;
74+
}
75+
}

src/main/java/net/wurstclient/hack/HackList.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,24 @@ public HackList(Path enabledHacksFile, Path favoriteHacksFile)
242242
eventManager.add(UpdateListener.class, this);
243243
}
244244

245+
/**
246+
* Toggle the per-hack "Only above ground" filter for all hacks that
247+
* expose the setting. Useful for binding to a key or calling from the
248+
* command interface.
249+
*/
250+
public void setAboveGroundFilterEnabled(boolean enabled)
251+
{
252+
AboveGroundFilterManager.toggle(this, enabled);
253+
}
254+
255+
/**
256+
* Set the Y threshold used by hacks that expose the above-ground filter.
257+
*/
258+
public void setAboveGroundFilterY(int y)
259+
{
260+
AboveGroundFilterManager.setY(this, y);
261+
}
262+
245263
@Override
246264
public void onUpdate()
247265
{

src/main/java/net/wurstclient/hacks/BedEspHack.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import net.wurstclient.settings.ChunkAreaSetting;
3232
import net.wurstclient.settings.ColorSetting;
3333
import net.wurstclient.settings.EspStyleSetting;
34+
import net.wurstclient.settings.SliderSetting;
3435
import net.wurstclient.util.RenderUtils;
3536
import net.wurstclient.util.chunk.ChunkSearcher.Result;
3637
import net.wurstclient.util.chunk.ChunkSearcherCoordinator;
@@ -61,6 +62,13 @@ public final class BedEspHack extends Hack implements UpdateListener,
6162
"The area around the player to search in.\n"
6263
+ "Higher values require a faster computer.");
6364

65+
// Above-ground filter
66+
private final net.wurstclient.settings.CheckboxSetting onlyAboveGround =
67+
new net.wurstclient.settings.CheckboxSetting("Above ground only",
68+
"Only show beds at or above the configured Y level.", false);
69+
private final SliderSetting aboveGroundY = new SliderSetting(
70+
"Above ground Y", 62, 0, 255, 1, SliderSetting.ValueDisplay.INTEGER);
71+
6472
private final BiPredicate<BlockPos, BlockState> query =
6573
(pos, state) -> state.getBlock() instanceof BedBlock;
6674

@@ -81,6 +89,8 @@ public BedEspHack()
8189
addSetting(showCountInHackList);
8290
addSetting(area);
8391
addSetting(stickyArea);
92+
addSetting(onlyAboveGround);
93+
addSetting(aboveGroundY);
8494
}
8595

8696
@Override
@@ -199,6 +209,9 @@ public String getRenderName()
199209

200210
private void addToGroupBoxes(Result result)
201211
{
212+
if(onlyAboveGround.isChecked()
213+
&& result.pos().getY() < aboveGroundY.getValue())
214+
return;
202215
for(BedEspBlockGroup group : groups)
203216
{
204217
group.add(result);

src/main/java/net/wurstclient/hacks/ChestEspHack.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import net.wurstclient.settings.CheckboxSetting;
3434
import net.wurstclient.settings.ColorSetting;
3535
import net.wurstclient.settings.EspStyleSetting;
36+
import net.wurstclient.settings.SliderSetting;
3637
import net.wurstclient.util.RenderUtils;
3738
import net.wurstclient.util.chunk.ChunkUtils;
3839

@@ -141,6 +142,14 @@ public class ChestEspHack extends Hack implements UpdateListener,
141142

142143
private int foundCount;
143144

145+
// Above-ground filter
146+
private final CheckboxSetting onlyAboveGround =
147+
new CheckboxSetting("Above ground only",
148+
"Only show chests/containers at or above the configured Y level.",
149+
false);
150+
private final SliderSetting aboveGroundY = new SliderSetting(
151+
"Above ground Y", 62, 0, 255, 1, SliderSetting.ValueDisplay.INTEGER);
152+
144153
public ChestEspHack()
145154
{
146155
super("ChestESP");
@@ -149,6 +158,8 @@ public ChestEspHack()
149158
addSetting(stickyArea);
150159
groups.stream().flatMap(ChestEspGroup::getSettings)
151160
.forEach(this::addSetting);
161+
addSetting(onlyAboveGround);
162+
addSetting(aboveGroundY);
152163
addSetting(showCountInHackList);
153164
}
154165

@@ -182,6 +193,10 @@ public void onUpdate()
182193
.collect(Collectors.toCollection(ArrayList::new));
183194

184195
for(BlockEntity blockEntity : blockEntities)
196+
{
197+
if(onlyAboveGround.isChecked()
198+
&& blockEntity.getPos().getY() < aboveGroundY.getValue())
199+
continue;
185200
if(blockEntity instanceof TrappedChestBlockEntity)
186201
trapChests.add(blockEntity);
187202
else if(blockEntity instanceof ChestBlockEntity)
@@ -205,15 +220,22 @@ else if(blockEntity instanceof CrafterBlockEntity)
205220
else if(blockEntity instanceof AbstractFurnaceBlockEntity)
206221
furnaces.add(blockEntity);
207222

223+
}
224+
208225
for(Entity entity : MC.world.getEntities())
226+
{
227+
if(onlyAboveGround.isChecked()
228+
&& entity.getY() < aboveGroundY.getValue())
229+
continue;
209230
if(entity instanceof ChestMinecartEntity)
210231
chestCarts.add(entity);
211232
else if(entity instanceof HopperMinecartEntity)
212233
hopperCarts.add(entity);
213234
else if(entity instanceof ChestBoatEntity
214235
|| entity instanceof ChestRaftEntity)
215236
chestBoats.add(entity);
216-
237+
}
238+
217239
// compute found count from enabled groups (clamped)
218240
int total = groups.stream().mapToInt(g -> g.getBoxes().size()).sum();
219241
total += entityGroups.stream().mapToInt(g -> g.getBoxes().size()).sum();

0 commit comments

Comments
 (0)