Skip to content

Commit 28c494b

Browse files
committed
Updated PearlESP and Flight
1 parent 78b6b00 commit 28c494b

5 files changed

Lines changed: 176 additions & 9 deletions

File tree

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,9 +508,12 @@ Credits to [Trouser-Streak](https://github.com/etianl/Trouser-Streak/blob/main/s
508508

509509
### PearlESP
510510
- Highlight held pearls by other players
511+
- Highlights stasis chamber pearls
511512
- Shows where other players (including yourself) will be teleported
512513
- Predict where your pearl will go via a trajectory line
513514
- Adjustable color, default is purple
515+
- Optional tracer line with custom thickness
516+
- Optional sound or chat alerts on detection
514517

515518
![Pearl](https://i.imgur.com/Rng37ws.png)
516519

@@ -643,8 +646,9 @@ Credits to [Trouser-Streak](https://github.com/etianl/Trouser-Streak/blob/main/s
643646
- A green tick will appear when all teleport conditions are met: can reach, won't die and able to pass through.
644647
- Able to adjust packet rate throttle to avoid spam or detection.
645648
- Holding shift above bedrock will attempt to break blocks under you to find a cheaper (less damage) route. Will auto switch to pickaxe if available.
649+
- Optionally holding shift above bedrock will make the bedrock layer transparent. If underneath it, looking up will make it transparent.
646650
- You are able to override safeguards in the settings
647-
- Only works on PaperMC
651+
- Tested on Fabric and Paper servers
648652

649653
![Bedrock](https://i.imgur.com/4mEuHL8.png)
650654

@@ -1047,7 +1051,7 @@ Examples:
10471051
- Optionally tie horizontal and vertical speeds together
10481052
- Adjustable step for both speeds
10491053
- Prevent dropping when holding SHIFT whilst in inventory
1050-
- Prevent being slowed down by vines
1054+
- Prevent being slowed down by vines (Even if NoSlowDown is turned off)
10511055

10521056
### Larger Scan Radius
10531057
- Extended up to 65×65 chunks for all chunk-based features.

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,11 @@ private void restoreNoSlowdownVineIgnore()
294294
managedNoSlowdownVineIgnore = false;
295295
}
296296

297+
public boolean shouldIgnoreVinesWithFlight()
298+
{
299+
return isEnabled() && ignoreVinesWithFlight.isChecked();
300+
}
301+
297302
@Override
298303
public void onGetAirStrafingSpeed(AirStrafingSpeedEvent event)
299304
{

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

Lines changed: 137 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@
1010
import com.mojang.blaze3d.vertex.PoseStack;
1111
import java.awt.Color;
1212
import java.util.ArrayList;
13+
import java.util.HashSet;
1314
import java.util.List;
15+
import java.util.UUID;
16+
import net.minecraft.core.registries.BuiltInRegistries;
17+
import net.minecraft.resources.Identifier;
18+
import net.minecraft.sounds.SoundEvent;
19+
import net.minecraft.sounds.SoundSource;
1420
import net.minecraft.world.InteractionHand;
1521
import net.minecraft.world.entity.Entity;
1622
import net.minecraft.world.entity.HumanoidArm;
@@ -26,13 +32,17 @@
2632
import net.wurstclient.SearchTags;
2733
import net.wurstclient.settings.CheckboxSetting;
2834
import net.wurstclient.settings.ColorSetting;
35+
import net.wurstclient.settings.EnumSetting;
36+
import net.wurstclient.settings.SliderSetting;
37+
import net.wurstclient.settings.SliderSetting.ValueDisplay;
2938
import net.wurstclient.events.CameraTransformViewBobbingListener;
3039
import net.wurstclient.events.CameraTransformViewBobbingListener.CameraTransformViewBobbingEvent;
3140
import java.lang.reflect.Method;
3241
import net.wurstclient.events.RenderListener;
3342
import net.wurstclient.events.UpdateListener;
3443
import net.wurstclient.hack.Hack;
3544
import net.wurstclient.util.BlockUtils;
45+
import net.wurstclient.util.ChatUtils;
3646
import net.wurstclient.util.EntityUtils;
3747
import net.wurstclient.util.RenderUtils;
3848

@@ -53,9 +63,25 @@ public class PearlEspHack extends Hack implements UpdateListener,
5363
"Show player prediction",
5464
"Show predicted trajectory while the local player is holding a pearl.",
5565
true);
66+
private final CheckboxSetting showTracerLine =
67+
new CheckboxSetting("Show tracer line",
68+
"Draw trajectory lines for pearl predictions.", true);
69+
private final SliderSetting tracerThickness = new SliderSetting(
70+
"Tracer thickness", 2, 0.5, 8, 0.1, ValueDisplay.DECIMAL);
71+
private final CheckboxSetting chatAlerts =
72+
new CheckboxSetting("Chat alerts",
73+
"Show a chat alert when a new ender pearl is detected.", false);
74+
private final CheckboxSetting soundAlerts =
75+
new CheckboxSetting("Sound alerts",
76+
"Play a sound alert when a new ender pearl is detected.", false);
77+
private final EnumSetting<AlertSound> alertSound =
78+
new EnumSetting<>("Alert sound",
79+
"Sound used for PearlESP alerts (includes all note-block sounds).",
80+
AlertSound.values(), AlertSound.NOTE_BLOCK_CHIME);
5681

5782
private final ArrayList<TrackedPearl> pearls = new ArrayList<>();
5883
private final ArrayList<HeldPearl> holders = new ArrayList<>();
84+
private final HashSet<UUID> alertedPearls = new HashSet<>();
5985
private boolean hasOwnPearl;
6086
private long ownPearlSuppressUntilMs;
6187

@@ -66,6 +92,11 @@ public PearlEspHack()
6692
addSetting(color);
6793
addSetting(highlightHeld);
6894
addSetting(showPlayerPrediction);
95+
addSetting(showTracerLine);
96+
addSetting(tracerThickness);
97+
addSetting(chatAlerts);
98+
addSetting(soundAlerts);
99+
addSetting(alertSound);
69100
}
70101

71102
@Override
@@ -84,6 +115,7 @@ protected void onDisable()
84115
EVENTS.remove(RenderListener.class, this);
85116
pearls.clear();
86117
holders.clear();
118+
alertedPearls.clear();
87119
hasOwnPearl = false;
88120
ownPearlSuppressUntilMs = 0L;
89121
}
@@ -94,6 +126,7 @@ public void onUpdate()
94126
pearls.clear();
95127
holders.clear();
96128
hasOwnPearl = false;
129+
HashSet<UUID> seenPearls = new HashSet<>();
97130

98131
if(MC.level == null)
99132
return;
@@ -103,15 +136,18 @@ public void onUpdate()
103136
if(entity.getType() == EntityType.ENDER_PEARL)
104137
{
105138
Entity pearl = entity;
139+
seenPearls.add(pearl.getUUID());
106140
PearlPrediction prediction = buildPrediction(pearl);
107141
pearls.add(new TrackedPearl(pearl, prediction));
142+
boolean ownPearl = false;
108143
// Detect ownership via reflection and set suppression window
109144
try
110145
{
111146
Method m = pearl.getClass().getMethod("getOwner");
112147
Object owner = m.invoke(pearl);
113148
if(owner == MC.player)
114149
{
150+
ownPearl = true;
115151
hasOwnPearl = true;
116152
ownPearlSuppressUntilMs =
117153
System.currentTimeMillis() + 4000; // suppress
@@ -120,12 +156,42 @@ public void onUpdate()
120156
}
121157
}catch(Exception ignored)
122158
{}
159+
160+
if(!ownPearl && alertedPearls.add(pearl.getUUID()))
161+
triggerPearlAlert(pearl);
123162
continue;
124163
}
125164

126165
if(entity instanceof Player player)
127166
handleHolder(player);
128167
}
168+
169+
alertedPearls.retainAll(seenPearls);
170+
}
171+
172+
private void triggerPearlAlert(Entity pearl)
173+
{
174+
if(!chatAlerts.isChecked() && !soundAlerts.isChecked())
175+
return;
176+
177+
if(chatAlerts.isChecked())
178+
{
179+
int x = (int)Math.floor(pearl.getX());
180+
int y = (int)Math.floor(pearl.getY());
181+
int z = (int)Math.floor(pearl.getZ());
182+
ChatUtils.message("PearlESP: Ender pearl detected at " + x + ", "
183+
+ y + ", " + z + ".");
184+
}
185+
186+
if(!soundAlerts.isChecked() || MC.level == null || MC.player == null)
187+
return;
188+
189+
SoundEvent sound = alertSound.getSelected().resolve();
190+
if(sound == null)
191+
return;
192+
193+
MC.level.playLocalSound(MC.player.getX(), MC.player.getY(),
194+
MC.player.getZ(), sound, SoundSource.PLAYERS, 1.0F, 1.0F, false);
129195
}
130196

131197
private void handleHolder(Player player)
@@ -157,6 +223,9 @@ private boolean isHoldingPearlAnyHand(Player player)
157223
public void onCameraTransformViewBobbing(
158224
CameraTransformViewBobbingEvent event)
159225
{
226+
if(!showTracerLine.isChecked())
227+
return;
228+
160229
for(TrackedPearl t : pearls)
161230
{
162231
PearlPrediction p = t.prediction();
@@ -266,8 +335,7 @@ public void onRender(PoseStack matrixStack, float partialTicks)
266335
{
267336
landingBoxes.add(createLandingBox(pred.landing(),
268337
LANDING_BOX_RADIUS));
269-
RenderUtils.drawCurvedLine(matrixStack, pred.path(),
270-
lineColor, false);
338+
renderTrajectory(matrixStack, pred.path(), lineColor);
271339
}
272340
}
273341
}
@@ -297,10 +365,11 @@ public void onRender(PoseStack matrixStack, float partialTicks)
297365
private void renderTrajectory(PoseStack matrixStack, List<Vec3> path,
298366
int lineColor)
299367
{
300-
if(path == null || path.size() < 2)
368+
if(!showTracerLine.isChecked() || path == null || path.size() < 2)
301369
return;
302370

303-
RenderUtils.drawCurvedLine(matrixStack, path, lineColor, false);
371+
RenderUtils.drawCurvedLine(matrixStack, path, lineColor, false,
372+
tracerThickness.getValue());
304373
}
305374

306375
private PearlPrediction buildPrediction(Entity pearl)
@@ -440,4 +509,68 @@ private record PearlPrediction(List<Vec3> path, Vec3 landing)
440509

441510
private record HeldPearl(Player player, InteractionHand hand)
442511
{}
512+
513+
private enum AlertSound
514+
{
515+
NOTE_BLOCK_HARP("Note Block Harp", "minecraft:block.note_block.harp"),
516+
NOTE_BLOCK_BASS("Note Block Bass", "minecraft:block.note_block.bass"),
517+
NOTE_BLOCK_BASEDRUM("Note Block Basedrum",
518+
"minecraft:block.note_block.basedrum"),
519+
NOTE_BLOCK_SNARE("Note Block Snare",
520+
"minecraft:block.note_block.snare"),
521+
NOTE_BLOCK_HAT("Note Block Hat", "minecraft:block.note_block.hat"),
522+
NOTE_BLOCK_GUITAR("Note Block Guitar",
523+
"minecraft:block.note_block.guitar"),
524+
NOTE_BLOCK_FLUTE("Note Block Flute",
525+
"minecraft:block.note_block.flute"),
526+
NOTE_BLOCK_BELL("Note Block Bell", "minecraft:block.note_block.bell"),
527+
NOTE_BLOCK_CHIME("Note Block Chime",
528+
"minecraft:block.note_block.chime"),
529+
NOTE_BLOCK_XYLOPHONE("Note Block Xylophone",
530+
"minecraft:block.note_block.xylophone"),
531+
NOTE_BLOCK_IRON_XYLOPHONE("Note Block Iron Xylophone",
532+
"minecraft:block.note_block.iron_xylophone"),
533+
NOTE_BLOCK_COW_BELL("Note Block Cow Bell",
534+
"minecraft:block.note_block.cow_bell"),
535+
NOTE_BLOCK_DIDGERIDOO("Note Block Didgeridoo",
536+
"minecraft:block.note_block.didgeridoo"),
537+
NOTE_BLOCK_BIT("Note Block Bit", "minecraft:block.note_block.bit"),
538+
NOTE_BLOCK_BANJO("Note Block Banjo",
539+
"minecraft:block.note_block.banjo"),
540+
NOTE_BLOCK_PLING("Note Block Pling",
541+
"minecraft:block.note_block.pling"),
542+
XP_PICKUP("XP Pickup", "minecraft:entity.experience_orb.pickup"),
543+
UI_BUTTON_CLICK("UI Button Click", "minecraft:ui.button.click"),
544+
AMETHYST_CHIME("Amethyst Chime",
545+
"minecraft:block.amethyst_block.chime"),
546+
BELL_USE("Bell Use", "minecraft:block.bell.use"),
547+
ITEM_PICKUP("Item Pickup", "minecraft:entity.item.pickup");
548+
549+
private final String displayName;
550+
private final String id;
551+
552+
private AlertSound(String displayName, String id)
553+
{
554+
this.displayName = displayName;
555+
this.id = id;
556+
}
557+
558+
private SoundEvent resolve()
559+
{
560+
try
561+
{
562+
return BuiltInRegistries.SOUND_EVENT
563+
.getValue(Identifier.parse(id));
564+
}catch(Exception e)
565+
{
566+
return null;
567+
}
568+
}
569+
570+
@Override
571+
public String toString()
572+
{
573+
return displayName;
574+
}
575+
}
443576
}

src/main/java/net/wurstclient/mixin/BlockMixin.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
1414
import net.minecraft.world.level.ItemLike;
1515
import net.minecraft.world.level.block.Block;
16+
import net.minecraft.world.level.block.Blocks;
1617
import net.wurstclient.WurstClient;
1718
import net.wurstclient.hack.HackList;
1819

@@ -23,10 +24,27 @@ public abstract class BlockMixin implements ItemLike
2324
private void onGetVelocityMultiplier(CallbackInfoReturnable<Float> cir)
2425
{
2526
HackList hax = WurstClient.INSTANCE.getHax();
26-
if(hax == null || !hax.noSlowdownHack.isEnabled())
27+
if(hax == null)
28+
return;
29+
30+
boolean ignoreViaNoSlowdown = hax.noSlowdownHack.isEnabled();
31+
boolean ignoreVinesViaFlight =
32+
hax.flightHack.shouldIgnoreVinesWithFlight()
33+
&& isVineBlock((Block)(Object)this);
34+
35+
if(!ignoreViaNoSlowdown && !ignoreVinesViaFlight)
2736
return;
2837

2938
if(cir.getReturnValueF() < 1)
3039
cir.setReturnValue(1F);
3140
}
41+
42+
private boolean isVineBlock(Block block)
43+
{
44+
return block == Blocks.VINE || block == Blocks.CAVE_VINES
45+
|| block == Blocks.CAVE_VINES_PLANT || block == Blocks.WEEPING_VINES
46+
|| block == Blocks.WEEPING_VINES_PLANT
47+
|| block == Blocks.TWISTING_VINES
48+
|| block == Blocks.TWISTING_VINES_PLANT;
49+
}
3250
}

src/main/java/net/wurstclient/mixin/LivingEntityMixin.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,15 @@ private void onOnClimbable(CallbackInfoReturnable<Boolean> cir)
4949
if(!(entity instanceof Player player) || !player.isLocalPlayer())
5050
return;
5151

52-
var noSlowdown = WurstClient.INSTANCE.getHax().noSlowdownHack;
53-
if(!noSlowdown.isEnabled() || !noSlowdown.shouldIgnoreVines())
52+
var hax = WurstClient.INSTANCE.getHax();
53+
if(hax == null)
54+
return;
55+
56+
var noSlowdown = hax.noSlowdownHack;
57+
boolean ignoreViaNoSlowdown =
58+
noSlowdown.isEnabled() && noSlowdown.shouldIgnoreVines();
59+
boolean ignoreViaFlight = hax.flightHack.shouldIgnoreVinesWithFlight();
60+
if(!ignoreViaNoSlowdown && !ignoreViaFlight)
5461
return;
5562

5663
if(isTouchingVines(entity))

0 commit comments

Comments
 (0)