Skip to content

Commit 70180ac

Browse files
committed
AntiVoid, HandNoClip and Waypoints Improved
1 parent 69e4222 commit 70180ac

File tree

11 files changed

+3343
-3039
lines changed

11 files changed

+3343
-3039
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ I did not, nor could I copy their code directly as most are Meteor based mods. S
199199
- Xaero's Minimap integration, allows exporting and importing of waypoint data (disconnect & reconnect to update).
200200
- Adjustable Tri-state Beacon Mode on waypoints (On/Off/ESP) that matches the waypoint's color.
201201
- Toggleable automatic portal logging, logs numerically each portal you enter and matches it in the opposite dimension with the same number.
202+
- Optional distance based label scaling
202203

203204

204205
#### Waypoint Commands
@@ -529,8 +530,10 @@ Credits to [Trouser-Streak](https://github.com/etianl/Trouser-Streak/blob/main/s
529530

530531
### AntiVoid
531532
- Teleports you back to your last safe position when you are falling into the void.
532-
- Optionally enable air walk to avoid falling.
533+
- Optionally enable air walk or flight to avoid falling.
533534
- Can also avoid falling into lava.
535+
- Able to respond only at void level
536+
- Auto-enabling on conditions
534537

535538
### ElytraFlight
536539
- A static flight mode for elytra. Overrides motion every tick to let you hover, move and fly like the normal flight hack.
@@ -840,6 +843,7 @@ Examples:
840843
### HandNoClip Improved
841844
- Displays a red X on the crosshair when block placement or interaction is blocked while the hack is enabled.
842845
- The red X can also indicate blocks that can be interacted with when On-Target Mode is enabled; in this mode, HandNoClip remains disabled until you are within range of a valid block.
846+
- Toggle to enable villager intraction through blocks
843847

844848
### Keybind Manager Improved
845849
- Can now clear the entire keybinds instead of just resetting.

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

Lines changed: 173 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,21 @@
1515
import net.minecraft.world.level.block.state.BlockState;
1616
import net.minecraft.world.phys.AABB;
1717
import net.minecraft.world.phys.Vec3;
18+
import net.minecraft.world.damagesource.DamageSource;
19+
import java.util.Locale;
1820
import net.wurstclient.Category;
1921
import net.wurstclient.SearchTags;
2022
import net.wurstclient.events.UpdateListener;
2123
import net.wurstclient.hack.Hack;
2224
import net.wurstclient.settings.CheckboxSetting;
25+
import net.wurstclient.util.BlockUtils;
2326
import net.wurstclient.settings.SliderSetting;
2427
import net.wurstclient.settings.SliderSetting.ValueDisplay;
25-
import net.wurstclient.util.BlockUtils;
2628

2729
@SearchTags({"anti void", "void"})
2830
public final class AntiVoidHack extends Hack implements UpdateListener
2931
{
30-
private final SliderSetting voidLevel = new SliderSetting("Void level",
31-
"Y level where the void begins.", 0, -256, 0, 1, ValueDisplay.INTEGER);
32-
32+
private static final long STARTUP_GRACE_TICKS = 40L; // ~2s after join
3333
private final CheckboxSetting useAirWalk = new CheckboxSetting(
3434
"Use AirWalk",
3535
"Prevents falling into the void/lava by air-walking instead of rubberbanding.",
@@ -39,19 +39,105 @@ public final class AntiVoidHack extends Hack implements UpdateListener
3939
"Detect lava",
4040
"Also prevents falling into lava when it is directly below you.", true);
4141

42+
private final CheckboxSetting gateAtVoidLevel = new CheckboxSetting(
43+
"Respond only at void level",
44+
"Only trigger when reaching the standard void level (End: -60, Others: -125).\n"
45+
+ "For lava, triggers one block above the lava surface.",
46+
false);
47+
48+
private final CheckboxSetting useFlight = new CheckboxSetting("Use Flight",
49+
"When triggered, enable Flight instead of rubberbanding/AirWalk.",
50+
false);
51+
52+
private final CheckboxSetting autoEnableOnOutOfWorld =
53+
new CheckboxSetting("Auto-enable on out_of_world",
54+
"Automatically enables AntiVoid and rescues to the fixed void level"
55+
+ " when taking out_of_world damage.",
56+
false);
57+
58+
private final SliderSetting lavaBufferBlocks = new SliderSetting(
59+
"Lava buffer (blocks)", 2, 0, 12, 1, ValueDisplay.INTEGER);
60+
61+
// Fixed thresholds are used; no per-dimension sliders.
62+
63+
private final CheckboxSetting autoEnableByHeight = new CheckboxSetting(
64+
"Auto-enable by height",
65+
"Automatically enables AntiVoid when your Y is within a safety band below 0.\n"
66+
+ "Defaults: End -65..0, Others -125..-60.",
67+
true);
68+
4269
private Vec3 lastSafePos;
4370
private boolean airWalkActive;
4471
private double airWalkY;
4572
private boolean rescueActive;
4673
private boolean jumpWasDown;
74+
private int lastHurtTimeSeen;
75+
private long lastAutoRescueMs;
76+
77+
// Always-on update listener (registered in constructor)
78+
private final UpdateListener alwaysListener = new UpdateListener()
79+
{
80+
@Override
81+
public void onUpdate()
82+
{
83+
LocalPlayer p = MC.player;
84+
if(p == null)
85+
return;
86+
// Avoid enabling during early startup before other hacks restore
87+
if(MC.level == null || MC.level.getGameTime() < STARTUP_GRACE_TICKS)
88+
{
89+
lastHurtTimeSeen = p.hurtTime;
90+
return;
91+
}
92+
// We still allow auto-enable at thresholds even if flight is
93+
// active.
94+
int ht = p.hurtTime;
95+
if(autoEnableOnOutOfWorld.isChecked() && ht > lastHurtTimeSeen)
96+
{
97+
DamageSource src = p.getLastDamageSource();
98+
if(isOutOfWorldDamage(src))
99+
{
100+
long now = System.currentTimeMillis();
101+
if(now - lastAutoRescueMs > 500)
102+
{
103+
if(!isEnabled())
104+
setEnabled(true);
105+
rescueToFixedLevel(p);
106+
lastAutoRescueMs = now;
107+
}
108+
}
109+
}
110+
// Height-based auto-enable at fixed thresholds while falling
111+
if(autoEnableByHeight.isChecked() && MC.level != null)
112+
{
113+
double y = p.getY();
114+
boolean falling =
115+
p.getDeltaMovement().y < 0 && p.fallDistance > 2F;
116+
double threshold = fixedVoidLevel();
117+
if(falling && y <= threshold && !isEnabled())
118+
setEnabled(true);
119+
// If flight is active and we're above threshold, keep AntiVoid
120+
// off
121+
if(isFlyingHackEnabled() && y > threshold && isEnabled())
122+
setEnabled(false);
123+
}
124+
lastHurtTimeSeen = ht;
125+
}
126+
};
47127

48128
public AntiVoidHack()
49129
{
50130
super("AntiVoid");
51131
setCategory(Category.MOVEMENT);
52-
addSetting(voidLevel);
53132
addSetting(useAirWalk);
54133
addSetting(detectLava);
134+
addSetting(gateAtVoidLevel);
135+
addSetting(useFlight);
136+
addSetting(autoEnableOnOutOfWorld);
137+
addSetting(autoEnableByHeight);
138+
addSetting(lavaBufferBlocks);
139+
// Always-on listener to catch out_of_world damage even when disabled
140+
EVENTS.add(UpdateListener.class, alwaysListener);
55141
}
56142

57143
@Override
@@ -97,12 +183,9 @@ public void onUpdate()
97183
if(!airWalkActive && (player.onGround() || player.isInWater()
98184
|| player.isInLava() || player.onClimbable()))
99185
rescueActive = false;
100-
101-
if(rescueActive && isFlyingHackEnabled())
102-
{
103-
setEnabled(false);
104-
return;
105-
}
186+
187+
// Do not force-disable here; alwaysListener handles
188+
// flight-vs-threshold.
106189

107190
if(player.onGround() && !player.isInWater() && !player.isInLava())
108191
lastSafePos = player.position();
@@ -122,6 +205,16 @@ public void onUpdate()
122205
if(!isOverVoid(player) && !isOverLava(player))
123206
return;
124207

208+
if(useFlight.isChecked())
209+
{
210+
// Hand off to Flight and stop our intervention
211+
rescueActive = true;
212+
var hax = WURST.getHax();
213+
if(!hax.flightHack.isEnabled())
214+
hax.flightHack.setEnabled(true);
215+
return;
216+
}
217+
125218
if(useAirWalk.isChecked())
126219
{
127220
airWalkActive = true;
@@ -175,7 +268,6 @@ private boolean isBackOnSurface(LocalPlayer player)
175268
{
176269
if(player.onGround())
177270
return true;
178-
179271
AABB checkBox = player.getBoundingBox().move(0, -0.05, 0);
180272
return BlockUtils.getBlockCollisions(checkBox).findAny().isPresent();
181273
}
@@ -190,7 +282,9 @@ private boolean isFlyingHackEnabled()
190282

191283
private boolean isOverVoid(LocalPlayer player)
192284
{
193-
double voidY = voidLevel.getValue();
285+
double voidY = fixedVoidLevel();
286+
if(gateAtVoidLevel.isChecked() && player.getY() > voidY)
287+
return false;
194288
if(player.getY() <= voidY && !player.isInWater() && !player.isInLava())
195289
return true;
196290

@@ -218,25 +312,83 @@ private boolean isOverLava(LocalPlayer player)
218312
{
219313
if(!detectLava.isChecked())
220314
return false;
221-
315+
Integer lavaY = lavaYBelow(player);
316+
if(lavaY == null)
317+
return false;
318+
double buffer = lavaBufferBlocks.getValue();
319+
return player.getY() <= lavaY + buffer;
320+
}
321+
322+
private Integer lavaYBelow(LocalPlayer player)
323+
{
222324
int x = player.getBlockX();
223325
int z = player.getBlockZ();
224326
int startY = player.getBlockY();
225327
int minY = MC.level.getMinY();
226-
227328
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
228329
for(int y = startY; y >= minY; y--)
229330
{
230331
pos.set(x, y, z);
231332
BlockState state = MC.level.getBlockState(pos);
232-
233333
if(!state.getFluidState().isEmpty())
234-
return state.getFluidState().is(FluidTags.LAVA);
235-
334+
{
335+
if(state.getFluidState().is(FluidTags.LAVA))
336+
return y;
337+
return null; // other fluid blocks detection stops search
338+
}
236339
if(!state.isAir())
237-
return false;
340+
return null; // solid found before lava
238341
}
239-
240-
return false;
342+
return null;
343+
}
344+
345+
private double fixedVoidLevel()
346+
{
347+
if(MC.level == null)
348+
return -120.0;
349+
String key = MC.level.dimension().identifier().getPath();
350+
if("the_end".equals(key))
351+
return -60.0;
352+
if("the_nether".equals(key))
353+
return -60.0;
354+
// Overworld
355+
return -120.0;
356+
}
357+
358+
// No height band method needed; using fixed thresholds.
359+
360+
private void rescueToFixedLevel(LocalPlayer player)
361+
{
362+
double targetY = fixedVoidLevel() + 1.0;
363+
Vec3 here = player.position();
364+
player.setDeltaMovement(0, 0, 0);
365+
player.fallDistance = 0;
366+
player.setOnGround(true);
367+
player.setPos(here.x, targetY, here.z);
368+
if(player.connection != null)
369+
{
370+
player.connection.send(new ServerboundMovePlayerPacket.Pos(here.x,
371+
targetY, here.z, true, player.horizontalCollision));
372+
}
373+
lastSafePos = new Vec3(here.x, targetY, here.z);
374+
// If configured, immediately hold the player using AirWalk after rescue
375+
if(useAirWalk.isChecked())
376+
{
377+
airWalkActive = true;
378+
rescueActive = true;
379+
airWalkY = targetY;
380+
}
381+
}
382+
383+
private boolean isOutOfWorldDamage(DamageSource src)
384+
{
385+
if(src == null)
386+
return false;
387+
String id = src.getMsgId();
388+
if(id == null)
389+
return false;
390+
String norm = id.toLowerCase(Locale.ROOT).replaceAll("[^a-z]", "");
391+
// Accept common forms: out_of_world, outOfWorld, minecraft:out_of_world
392+
return norm.endsWith("outofworld");
241393
}
242394
}

0 commit comments

Comments
 (0)