Skip to content

Commit 15fc1e5

Browse files
committed
Added GlobalToggle for StickyArea and Above Y
1 parent bdf5775 commit 15fc1e5

File tree

5 files changed

+302
-1
lines changed

5 files changed

+302
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,13 +309,14 @@ Examples:
309309

310310
### Above Ground/ESP Y Limit (New ESP Option)
311311
- ItemESP, MobESP, MobSearch, Search, ChestESP, BedESP, SignESP, PortalESP, RedstoneESP and WorkstationESP now have an adjustable Y limit (default 62 which is approximately sea level)
312-
- 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 #```)
312+
- 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 #```) - also accessible via 'GlobalToggle' setting in the Other category within the ClickUI.
313313
- This will help prevent you from detecting inaccessible mobs/items and help you focus on scanning the surface of the world (if that's your goal)
314314

315315
### Sticky Area (New ESP Option)
316316
- Added to chunk-based ESPs (Search, Portal ESP, BedESP, SignESP, WorkstationESP, RedstoneESP, ChestESP).
317317
- Keeps results anchored as you move. Default OFF.
318318
- Greatly helps with FPS when using things like Search or X-Ray and moving quickly
319+
- Global toggle accessible via 'GlobalToggle' setting in the Other category within the ClickUI.
319320

320321
### TooManyHax Improved
321322
- Submenu of TooManyHax in the ClickUI/Navigator shows a list of toggleable hacks instead of needing to manually enter the name of each one via cmd.
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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+
import java.util.LinkedHashMap;
12+
import java.util.Map;
13+
14+
import net.wurstclient.settings.CheckboxSetting;
15+
16+
/**
17+
* Utility to capture, apply, and restore {@link CheckboxSetting} values across
18+
* all hacks in {@link HackList} that expose a given field name.
19+
*/
20+
public enum CheckboxOverrideManager
21+
{
22+
;
23+
24+
public static LinkedHashMap<CheckboxSetting, Boolean> capture(HackList hax,
25+
String fieldName)
26+
{
27+
LinkedHashMap<CheckboxSetting, Boolean> snapshot =
28+
new LinkedHashMap<>();
29+
30+
for(Hack hack : hax.getAllHax())
31+
{
32+
CheckboxSetting setting = getCheckboxSetting(hack, fieldName);
33+
if(setting == null)
34+
continue;
35+
36+
snapshot.put(setting, setting.isChecked());
37+
}
38+
39+
return snapshot;
40+
}
41+
42+
public static void apply(HackList hax, String fieldName, boolean value)
43+
{
44+
for(Hack hack : hax.getAllHax())
45+
{
46+
CheckboxSetting setting = getCheckboxSetting(hack, fieldName);
47+
if(setting != null)
48+
setting.setChecked(value);
49+
}
50+
}
51+
52+
public static void restore(Map<CheckboxSetting, Boolean> snapshot)
53+
{
54+
if(snapshot == null || snapshot.isEmpty())
55+
return;
56+
57+
for(Map.Entry<CheckboxSetting, Boolean> entry : snapshot.entrySet())
58+
{
59+
CheckboxSetting setting = entry.getKey();
60+
if(setting == null)
61+
continue;
62+
63+
setting.setChecked(entry.getValue());
64+
}
65+
}
66+
67+
private static CheckboxSetting getCheckboxSetting(Hack hack,
68+
String fieldName)
69+
{
70+
try
71+
{
72+
Field field = findField(hack.getClass(), fieldName);
73+
if(field == null)
74+
return null;
75+
76+
field.setAccessible(true);
77+
Object value = field.get(hack);
78+
if(value instanceof CheckboxSetting cs)
79+
return cs;
80+
81+
}catch(IllegalAccessException ignored)
82+
{}
83+
84+
return null;
85+
}
86+
87+
private static Field findField(Class<?> cls, String name)
88+
{
89+
Class<?> current = cls;
90+
91+
while(current != null && current != Object.class)
92+
{
93+
try
94+
{
95+
return current.getDeclaredField(name);
96+
}catch(NoSuchFieldException e)
97+
{
98+
current = current.getSuperclass();
99+
}
100+
}
101+
102+
return null;
103+
}
104+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public final class HackList implements UpdateListener
8787
new ChatTranslatorHack();
8888
public final ChestEspHack chestEspHack = new ChestEspHack();
8989
public final BedEspHack bedEspHack = new BedEspHack();
90+
public final GlobalToggleHack globalToggleHack = new GlobalToggleHack();
9091
public final EnchantmentHandlerHack enchantmentHandlerHack =
9192
new EnchantmentHandlerHack();
9293
public final ClickAuraHack clickAuraHack = new ClickAuraHack();
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
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.hacks;
9+
10+
import java.util.Map;
11+
12+
import net.wurstclient.Category;
13+
import net.wurstclient.SearchTags;
14+
import net.wurstclient.events.UpdateListener;
15+
import net.wurstclient.hack.AboveGroundFilterManager;
16+
import net.wurstclient.hack.CheckboxOverrideManager;
17+
import net.wurstclient.hack.Hack;
18+
import net.wurstclient.settings.CheckboxSetting;
19+
import net.wurstclient.settings.SliderSetting;
20+
import net.wurstclient.settings.SliderSetting.ValueDisplay;
21+
import net.wurstclient.util.ChatUtils;
22+
23+
@SearchTags({"global toggle", "render global toggle"})
24+
public final class GlobalToggleHack extends Hack implements UpdateListener
25+
{
26+
private final CheckboxSetting stickyForceOn =
27+
new CheckboxSetting("Sticky area on",
28+
"Forces sticky area on for all supported hacks.", false);
29+
private final CheckboxSetting stickyForceOff =
30+
new CheckboxSetting("Sticky area off",
31+
"Forces sticky area off for all supported hacks.", false);
32+
33+
private final CheckboxSetting yLimitForceOn = new CheckboxSetting(
34+
"Y limit on",
35+
"Forces the above-ground filter on for all supported hacks.", false);
36+
private final CheckboxSetting yLimitForceOff = new CheckboxSetting(
37+
"Y limit off",
38+
"Forces the above-ground filter off for all supported hacks.", false);
39+
private final SliderSetting yLimitValue = new SliderSetting(
40+
"Global Y limit", 62, 0, 255, 1, ValueDisplay.INTEGER);
41+
42+
private Map<CheckboxSetting, Boolean> stickySnapshot = Map.of();
43+
private Map<CheckboxSetting, Boolean> yLimitSnapshot = Map.of();
44+
45+
private OverrideState lastStickyState = OverrideState.NONE;
46+
private OverrideState lastYState = OverrideState.NONE;
47+
private int lastYLimitValue = 62;
48+
49+
public GlobalToggleHack()
50+
{
51+
super("GlobalToggle");
52+
setCategory(Category.OTHER);
53+
54+
addSetting(stickyForceOn);
55+
addSetting(stickyForceOff);
56+
addSetting(yLimitForceOn);
57+
addSetting(yLimitForceOff);
58+
addSetting(yLimitValue);
59+
60+
lastYLimitValue = yLimitValue.getValueI();
61+
62+
EVENTS.add(UpdateListener.class, this);
63+
}
64+
65+
@Override
66+
protected void onEnable()
67+
{
68+
setEnabled(false);
69+
}
70+
71+
@Override
72+
public void onUpdate()
73+
{
74+
var hacks = WURST.getHax();
75+
76+
// Sticky override --------------------------------------------------
77+
if(stickyForceOn.isChecked() && stickyForceOff.isChecked())
78+
{
79+
if(lastStickyState == OverrideState.FORCE_ON)
80+
stickyForceOff.setChecked(false);
81+
else
82+
stickyForceOn.setChecked(false);
83+
return;
84+
}
85+
86+
OverrideState stickyState =
87+
getOverrideState(stickyForceOn, stickyForceOff);
88+
if(stickyState != lastStickyState)
89+
{
90+
if(lastStickyState != OverrideState.NONE)
91+
CheckboxOverrideManager.restore(stickySnapshot);
92+
93+
if(stickyState == OverrideState.NONE)
94+
{
95+
stickySnapshot = Map.of();
96+
ChatUtils.message("Global sticky area override disabled.");
97+
}else
98+
{
99+
if(lastStickyState == OverrideState.NONE)
100+
stickySnapshot =
101+
CheckboxOverrideManager.capture(hacks, "stickyArea");
102+
CheckboxOverrideManager.apply(hacks, "stickyArea",
103+
stickyState == OverrideState.FORCE_ON);
104+
announceSticky(stickyState == OverrideState.FORCE_ON);
105+
}
106+
107+
lastStickyState = stickyState;
108+
}
109+
110+
// Y limit override -------------------------------------------------
111+
if(yLimitForceOn.isChecked() && yLimitForceOff.isChecked())
112+
{
113+
if(lastYState == OverrideState.FORCE_ON)
114+
yLimitForceOff.setChecked(false);
115+
else
116+
yLimitForceOn.setChecked(false);
117+
return;
118+
}
119+
120+
OverrideState yState = getOverrideState(yLimitForceOn, yLimitForceOff);
121+
int yValue = yLimitValue.getValueI();
122+
123+
if(yState != lastYState)
124+
{
125+
if(lastYState != OverrideState.NONE)
126+
{
127+
CheckboxOverrideManager.restore(yLimitSnapshot);
128+
if(lastYState == OverrideState.FORCE_ON)
129+
AboveGroundFilterManager.setY(hacks, lastYLimitValue);
130+
}else
131+
lastYLimitValue = yValue;
132+
133+
if(yState == OverrideState.NONE)
134+
{
135+
yLimitSnapshot = Map.of();
136+
ChatUtils.message("Global Y limit override disabled.");
137+
}else
138+
{
139+
if(lastYState == OverrideState.NONE)
140+
yLimitSnapshot = CheckboxOverrideManager.capture(hacks,
141+
"onlyAboveGround");
142+
CheckboxOverrideManager.apply(hacks, "onlyAboveGround",
143+
yState == OverrideState.FORCE_ON);
144+
if(yState == OverrideState.FORCE_ON)
145+
AboveGroundFilterManager.setY(hacks, yValue);
146+
announceYLimit(yState == OverrideState.FORCE_ON);
147+
}
148+
149+
lastYState = yState;
150+
}
151+
152+
if(yState == OverrideState.FORCE_ON && yValue != lastYLimitValue)
153+
{
154+
AboveGroundFilterManager.setY(hacks, yValue);
155+
lastYLimitValue = yValue;
156+
}else if(yValue != lastYLimitValue)
157+
{
158+
lastYLimitValue = yValue;
159+
}
160+
}
161+
162+
private void announceSticky(boolean forcingOn)
163+
{
164+
if(forcingOn)
165+
ChatUtils.message("Global sticky area override forcing ON.");
166+
else
167+
ChatUtils.message("Global sticky area override forcing OFF.");
168+
}
169+
170+
private void announceYLimit(boolean forcingOn)
171+
{
172+
if(forcingOn)
173+
ChatUtils.message("Global Y limit override forcing ON.");
174+
else
175+
ChatUtils.message("Global Y limit override forcing OFF.");
176+
}
177+
178+
private OverrideState getOverrideState(CheckboxSetting forceOn,
179+
CheckboxSetting forceOff)
180+
{
181+
if(forceOn.isChecked())
182+
return OverrideState.FORCE_ON;
183+
if(forceOff.isChecked())
184+
return OverrideState.FORCE_OFF;
185+
return OverrideState.NONE;
186+
}
187+
188+
private enum OverrideState
189+
{
190+
NONE,
191+
FORCE_ON,
192+
FORCE_OFF;
193+
}
194+
}

src/main/resources/assets/wurst/translations/en_us.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
"description.wurst.hack.follow": "A bot that follows the closest entity.\nVery annoying.\n\nUse .follow to follow a specific entity.",
115115
"description.wurst.hack.forceop": "Cracks AuthMe passwords.\nCan be used to get OP.",
116116
"description.wurst.hack.freecam": "Allows you to move the camera without moving your character.",
117+
"description.wurst.hack.globaltoggle": "Controls global overrides for sticky areas and above-ground ESP filters.",
117118
"description.wurst.hack.fullbright": "Allows you to see in the dark.",
118119
"description.wurst.hack.glide": "Makes you glide down slowly when falling.\n\n??c??lWARNING:??r You will take fall damage if you don't use NoFall.",
119120
"description.wurst.hack.handnoclip": "Allows you to reach specific blocks through walls.",

0 commit comments

Comments
 (0)