Skip to content

Commit 5ffe939

Browse files
committed
Updated AutoFly
1 parent db8a636 commit 5ffe939

4 files changed

Lines changed: 253 additions & 3 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,7 @@ Credits to [Trouser-Streak](https://github.com/etianl/Trouser-Streak/blob/main/s
644644
- Customisable display: Percent Only, Bar Only, Boss Bar Style, Show Offhand, Icon Size, Font Scale.
645645
- Moveable with your mouse whenever an inventory menu is open.
646646
- Auto centres itself whenever items are removed.
647+
- Auto moves when action bar messages are shown (such as sleeping) behind the HUD.
647648

648649
![HUD](https://i.imgur.com/IZ4lFCx.png)
649650

@@ -695,6 +696,7 @@ This hack is still undergoing development and has only been tested in the end. A
695696
- Able to adjust mid flight so you can get yourself unstuck if it failed to do it itself.
696697
- Able to somewhat path around blocks it crashes into either by moving around it or flying above it.
697698
- Auto lands and turns off flight when complete.
699+
- Optionally stop on discovery of portals or specific blocks or mobs.
698700
- Comes with custom commands:
699701
- `.autofly <x> <y> <z> [height] [speed]` or `.autofly <x> <z> [height] [speed]` to AutoFly to a given waypoint (relative `~` values are supported as well as comma separated entries). Omitting Y causes it to simply land at the waypoint.
700702
- `.autofly next`/`.autofly prev(ious)` cycles the SeedMapper export list, while `.autofly stop|off|disable` turns off AutoFly.

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

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,52 @@
3131
import net.wurstclient.hack.Hack;
3232
import net.wurstclient.settings.ButtonSetting;
3333
import net.wurstclient.settings.CheckboxSetting;
34+
import net.wurstclient.settings.EnumSetting;
3435
import net.wurstclient.settings.FileSetting;
3536
import net.wurstclient.settings.SliderSetting;
3637
import net.wurstclient.settings.SliderSetting.ValueDisplay;
3738
import net.wurstclient.settings.TextFieldSetting;
39+
import net.wurstclient.settings.ChunkAreaSetting;
3840
import net.wurstclient.util.ChatUtils;
3941
import net.wurstclient.util.MathUtils;
42+
import net.minecraft.core.registries.BuiltInRegistries;
43+
import net.minecraft.world.entity.Mob;
44+
import net.minecraft.world.entity.item.ItemEntity;
45+
import net.minecraft.world.level.block.state.BlockState;
46+
import net.wurstclient.util.chunk.ChunkSearcherCoordinator;
47+
import net.wurstclient.util.chunk.ChunkSearcher.Result;
4048

4149
@SearchTags({"auto fly", "autofly", "waypoint fly", "auto flight"})
4250
public final class AutoFlyHack extends Hack
4351
implements UpdateListener, GUIRenderListener, RenderListener
4452
{
53+
private static final int STOP_SCAN_COOLDOWN_TICKS = 10;
54+
private static final ChunkAreaSetting.ChunkArea STOP_BLOCK_AREA =
55+
ChunkAreaSetting.ChunkArea.A65;
56+
57+
public static enum StopOnType
58+
{
59+
OFF("Off"),
60+
MOBS("Mobs"),
61+
BLOCKS("Blocks"),
62+
ITEMS("Items"),
63+
END_PORTAL("End portal"),
64+
NETHER_PORTAL("Nether portal");
65+
66+
private final String name;
67+
68+
StopOnType(String name)
69+
{
70+
this.name = name;
71+
}
72+
73+
@Override
74+
public String toString()
75+
{
76+
return name;
77+
}
78+
}
79+
4580
private final TextFieldSetting waypointText = new TextFieldSetting(
4681
"Waypoints",
4782
"Waypoints list. Format: x y z or x z (no Y). Separate by ';' or new lines.",
@@ -107,6 +142,15 @@ public final class AutoFlyHack extends Hack
107142
new CheckboxSetting("Disable AutoFly on arrival",
108143
"Turns off AutoFly when it reaches a waypoint.", false);
109144

145+
private final EnumSetting<StopOnType> stopOn = new EnumSetting<>("Stop on",
146+
"Stop AutoFly if it detects something while flying.",
147+
StopOnType.values(), StopOnType.OFF);
148+
149+
private final TextFieldSetting stopKeyword = new TextFieldSetting(
150+
"Stop keyword",
151+
"Keyword to match against the selected Stop on type (ignored for portals).",
152+
"");
153+
110154
private final List<AutoFlyTarget> targets = new ArrayList<>();
111155
private AutoFlyTarget currentTarget;
112156
private int currentIndex = -1;
@@ -153,6 +197,10 @@ public final class AutoFlyHack extends Hack
153197
private boolean verticalAssistActive;
154198

155199
private boolean closeHorizLatched;
200+
private int stopScanCooldown;
201+
private ChunkSearcherCoordinator stopBlockCoordinator;
202+
private StopOnType stopBlockCoordinatorType;
203+
private String stopBlockCoordinatorKeyword;
156204

157205
public AutoFlyHack()
158206
{
@@ -176,6 +224,8 @@ public AutoFlyHack()
176224
addSetting(allowManualAdjust);
177225
addSetting(disableFlightOnArrival);
178226
addSetting(disableAutoFlyOnArrival);
227+
addSetting(stopOn);
228+
addSetting(stopKeyword);
179229
}
180230

181231
@Override
@@ -234,6 +284,10 @@ protected void onEnable()
234284
currentIndex = -1;
235285
currentTarget = null;
236286
closeHorizLatched = false;
287+
stopScanCooldown = 0;
288+
stopBlockCoordinator = null;
289+
stopBlockCoordinatorType = null;
290+
stopBlockCoordinatorKeyword = null;
237291
selectNextTarget(false);
238292
flightWasEnabled = WURST.getHax().flightHack.isEnabled();
239293
savedFlightSpeed = -1;
@@ -317,6 +371,9 @@ public void onUpdate()
317371
}
318372
}
319373

374+
if(checkStopOn())
375+
return;
376+
320377
if(allowManualAdjust.isChecked() && isManualInputActive())
321378
{
322379
beginManualAdjust(MC.player.position());
@@ -472,6 +529,197 @@ public void onUpdate()
472529
}
473530
}
474531

532+
private boolean checkStopOn()
533+
{
534+
StopOnType type = stopOn.getSelected();
535+
if(type == null || type == StopOnType.OFF)
536+
return false;
537+
538+
if(MC.player == null || MC.level == null)
539+
return false;
540+
541+
switch(type)
542+
{
543+
case MOBS ->
544+
{
545+
String kw = getStopKeyword();
546+
if(kw.isEmpty())
547+
return false;
548+
549+
// No explicit range cap: scan what the client has loaded
550+
// (entitiesForRendering).
551+
for(var e : MC.level.entitiesForRendering())
552+
{
553+
if(!(e instanceof Mob m) || !m.isAlive() || m.isRemoved())
554+
continue;
555+
556+
String name = safeString(m.getName().getString());
557+
String id = safeString(BuiltInRegistries.ENTITY_TYPE
558+
.getKey(m.getType()).toString());
559+
if(containsIgnoreCase(name, kw)
560+
|| containsIgnoreCase(id, kw))
561+
{
562+
stopAutoFly("Stopped: Found " + name);
563+
return true;
564+
}
565+
}
566+
return false;
567+
}
568+
569+
case ITEMS ->
570+
{
571+
String kw = getStopKeyword();
572+
if(kw.isEmpty())
573+
return false;
574+
575+
// No explicit range cap: scan what the client has loaded.
576+
for(var ent : MC.level.entitiesForRendering())
577+
{
578+
if(!(ent instanceof ItemEntity e) || !e.isAlive()
579+
|| e.isRemoved())
580+
continue;
581+
if(e.getItem() == null || e.getItem().isEmpty())
582+
continue;
583+
584+
var stack = e.getItem();
585+
String name = safeString(stack.getHoverName().getString());
586+
String id = safeString(BuiltInRegistries.ITEM
587+
.getKey(stack.getItem()).toString());
588+
if(containsIgnoreCase(name, kw)
589+
|| containsIgnoreCase(id, kw))
590+
{
591+
stopAutoFly("Stopped: Found " + name);
592+
return true;
593+
}
594+
}
595+
return false;
596+
}
597+
598+
case BLOCKS ->
599+
{
600+
String kw = getStopKeyword();
601+
if(kw.isEmpty())
602+
return false;
603+
604+
return scanBlocksForKeyword(kw, null);
605+
}
606+
607+
case END_PORTAL ->
608+
{
609+
return scanBlocksForKeyword("", Blocks.END_PORTAL);
610+
}
611+
612+
case NETHER_PORTAL ->
613+
{
614+
return scanBlocksForKeyword("", Blocks.NETHER_PORTAL);
615+
}
616+
617+
case OFF ->
618+
{
619+
return false;
620+
}
621+
}
622+
623+
return false;
624+
}
625+
626+
private boolean scanBlocksForKeyword(String keyword,
627+
net.minecraft.world.level.block.Block mustMatch)
628+
{
629+
// Throttle block scanning/update.
630+
if(stopScanCooldown-- > 0)
631+
return false;
632+
stopScanCooldown = STOP_SCAN_COOLDOWN_TICKS;
633+
634+
ensureStopBlockCoordinatorConfigured(keyword, mustMatch);
635+
if(stopBlockCoordinator == null)
636+
return false;
637+
638+
stopBlockCoordinator.update();
639+
640+
Result hit =
641+
stopBlockCoordinator.getReadyMatches().findFirst().orElse(null);
642+
if(hit == null)
643+
return false;
644+
645+
if(mustMatch != null)
646+
{
647+
stopAutoFly("Stopped: Found " + (mustMatch == Blocks.END_PORTAL
648+
? "End Portal" : "Nether Portal"));
649+
return true;
650+
}
651+
652+
String id = safeString(
653+
BuiltInRegistries.BLOCK.getKey(hit.state().getBlock()).toString());
654+
stopAutoFly("Stopped: Found " + id);
655+
return true;
656+
}
657+
658+
private void ensureStopBlockCoordinatorConfigured(String keyword,
659+
net.minecraft.world.level.block.Block mustMatch)
660+
{
661+
StopOnType type = stopOn.getSelected();
662+
if(type == null)
663+
return;
664+
665+
String kw = keyword == null ? "" : keyword.trim();
666+
667+
boolean needsReset =
668+
stopBlockCoordinator == null || stopBlockCoordinatorType != type
669+
|| !java.util.Objects.equals(stopBlockCoordinatorKeyword, kw);
670+
671+
if(!needsReset)
672+
return;
673+
674+
stopBlockCoordinatorType = type;
675+
stopBlockCoordinatorKeyword = kw;
676+
677+
ChunkAreaSetting area = new ChunkAreaSetting(
678+
"Stop scan area (internal)", "", STOP_BLOCK_AREA);
679+
stopBlockCoordinator = new ChunkSearcherCoordinator(area);
680+
681+
if(mustMatch != null)
682+
{
683+
stopBlockCoordinator.setTargetBlock(mustMatch);
684+
return;
685+
}
686+
687+
stopBlockCoordinator.setQuery((pos, state) -> {
688+
BlockState s = state;
689+
if(s == null)
690+
return false;
691+
String id = BuiltInRegistries.BLOCK.getKey(s.getBlock()).toString();
692+
return containsIgnoreCase(id, kw);
693+
});
694+
}
695+
696+
private void stopAutoFly(String message)
697+
{
698+
ChatUtils.message(message);
699+
setEnabled(false);
700+
}
701+
702+
private String getStopKeyword()
703+
{
704+
String v = stopKeyword.getValue();
705+
return v == null ? "" : v.trim();
706+
}
707+
708+
private static boolean containsIgnoreCase(String haystack, String needle)
709+
{
710+
if(haystack == null || needle == null)
711+
return false;
712+
if(needle.isEmpty())
713+
return false;
714+
return haystack.toLowerCase(Locale.ROOT)
715+
.contains(needle.toLowerCase(Locale.ROOT));
716+
}
717+
718+
private static String safeString(String s)
719+
{
720+
return s == null ? "" : s;
721+
}
722+
475723
@Override
476724
public void onRenderGUI(GuiGraphics context, float partialTicks)
477725
{

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public final class FlightHack extends Hack implements UpdateListener,
5959

6060
private final CheckboxSetting scrollToChangeSpeed =
6161
new CheckboxSetting("Scroll to change speed",
62-
"description.wurst.setting.flight.scroll_to_change_speed", true);
62+
"description.wurst.setting.flight.scroll_to_change_speed", false);
6363

6464
private final CheckboxSetting renderSpeed =
6565
new CheckboxSetting("Show speed in HackList",

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ public final class FreecamHack extends Hack implements UpdateListener,
7272
0.05, 5.0, 0.05, ValueDisplay.DECIMAL);
7373

7474
private final CheckboxSetting legacyMode = new CheckboxSetting(
75-
"Legacy mode", "description.wurst.setting.freecam.legacy_mode", false);
75+
"Legacy mode", "description.wurst.setting.freecam.legacy_mode", true);
7676

7777
private final CheckboxSetting scrollToChangeSpeed =
7878
new CheckboxSetting("Scroll to change speed",
79-
"description.wurst.setting.freecam.scroll_to_change_speed", true);
79+
"description.wurst.setting.freecam.scroll_to_change_speed", false);
8080

8181
private final CheckboxSetting renderSpeed =
8282
new CheckboxSetting("Show speed in HackList",

0 commit comments

Comments
 (0)