diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index adf8139e..8b8a31cf 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -25,6 +25,9 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew + - name: Fetch Build Time + run: echo "time=$(date + "%Y-%m-%d")" >> $GITHUB_ENV + - name: Build run: ./gradlew build @@ -34,8 +37,8 @@ jobs: - uses: "0xDylan/action-auto-releases-n20@v1.1" with: repo_token: "${{ secrets.GITHUB_TOKEN }}" - automatic_release_tag: nightly-${{ github.run_number }} + automatic_release_tag: nightly-${{ env.TIME }} prerelease: true - title: Nightly Build ${{ github.run_number }} + title: Nightly Build ${{ env.TIME }} files: | ./build/libs/*.jar diff --git a/src/main/java/net/aoba/cmd/CommandManager.java b/src/main/java/net/aoba/cmd/CommandManager.java index 5cbee5c8..9e43a21b 100644 --- a/src/main/java/net/aoba/cmd/CommandManager.java +++ b/src/main/java/net/aoba/cmd/CommandManager.java @@ -32,13 +32,11 @@ import net.minecraft.util.Formatting; import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Objects; +import java.util.*; public class CommandManager { private HashMap commands = new HashMap(); + private List commandHistory = new ArrayList<>(); public final CmdAimbot aimbot = new CmdAimbot(); public final CmdAutoEat autoeat = new CmdAutoEat(); @@ -69,6 +67,7 @@ public class CommandManager { public final CmdTP tp = new CmdTP(); public final CmdTracer tracer = new CmdTracer(); public final CmdXRay xray = new CmdXRay(); + public final CmdHistory history = new CmdHistory(); public static StringSetting PREFIX; @@ -138,6 +137,7 @@ public int getNumOfCommands() { */ public void command(String[] commandIn) { try { + commandHistory.add(String.join(" ", commandIn)); // Get the command from the user's message. (Index 0 is Username) Command command = commands.get(commandIn[1]); @@ -160,6 +160,10 @@ public void command(String[] commandIn) { } } + public List getCommandHistory() { + return commandHistory; + } + /** * Prints a message into the Minecraft Chat. * diff --git a/src/main/java/net/aoba/cmd/commands/CmdHistory.java b/src/main/java/net/aoba/cmd/commands/CmdHistory.java new file mode 100644 index 00000000..a79f05b9 --- /dev/null +++ b/src/main/java/net/aoba/cmd/commands/CmdHistory.java @@ -0,0 +1,58 @@ +package net.aoba.cmd.commands; + +import net.aoba.Aoba; +import net.aoba.cmd.Command; +import net.aoba.cmd.CommandManager; +import net.minecraft.util.Formatting; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; + +public class CmdHistory extends Command { + + private static final int HISTORY_PER_PAGE = 5; + + public CmdHistory() { + super("history", "Shows the command history.", "[page]"); + } + + @Override + public void runCommand(String[] parameters) { + if (parameters.length == 0) { + showHistory(1); + } else if (StringUtils.isNumeric(parameters[0])) { + int page = Integer.parseInt(parameters[0]); + showHistory(page); + } else { + CommandManager.sendChatMessage("Invalid parameter. Usage: .aoba history [page]"); + } + } + + private void showHistory(int page) { + CommandManager cm = Aoba.getInstance().commandManager; + ArrayList history = new ArrayList<>(cm.getCommandHistory()); + int totalPages = (int) Math.ceil((double) history.size() / HISTORY_PER_PAGE); + + if (page < 1 || page > totalPages) { + CommandManager.sendChatMessage("Page " + page + " does not exist. There are only " + totalPages + " pages."); + return; + } + + String title = "------------ Command History [Page " + page + " of " + totalPages + "] ------------"; + CommandManager.sendChatMessage(title); + + int startIndex = (page - 1) * HISTORY_PER_PAGE; + int endIndex = Math.min(startIndex + HISTORY_PER_PAGE, history.size()); + + for (int i = startIndex; i < endIndex; i++) { + CommandManager.sendChatMessage((i + 1) + ": " + history.get(i)); + } + + CommandManager.sendChatMessage("-".repeat(title.length() - 2)); // Adjust for Minecraft font width + } + + @Override + public String[] getAutocorrect(String previousParameter) { + return new String[0]; // No autocorrect needed for history command + } +} diff --git a/src/main/java/net/aoba/event/events/SendMovementPacketEvent.java b/src/main/java/net/aoba/event/events/SendMovementPacketEvent.java new file mode 100644 index 00000000..9530146b --- /dev/null +++ b/src/main/java/net/aoba/event/events/SendMovementPacketEvent.java @@ -0,0 +1,39 @@ +package net.aoba.event.events; + +import net.aoba.event.listeners.AbstractListener; +import net.aoba.event.listeners.SendMovementPacketListener; + +import java.util.ArrayList; +import java.util.List; + +public class SendMovementPacketEvent { + public static class Pre extends AbstractEvent { + @Override + public void Fire(ArrayList listeners) { + for (AbstractListener listener : List.copyOf(listeners)) { + SendMovementPacketListener sendMovementPacketListener = (SendMovementPacketListener) listener; + sendMovementPacketListener.onSendMovementPacket(this); + } + } + + @Override + public Class GetListenerClassType() { + return SendMovementPacketListener.class; + } + } + + public static class Post extends AbstractEvent { + @Override + public void Fire(ArrayList listeners) { + for (AbstractListener listener : List.copyOf(listeners)) { + SendMovementPacketListener sendMovementPacketListener = (SendMovementPacketListener) listener; + sendMovementPacketListener.onSendMovementPacket(this); + } + } + + @Override + public Class GetListenerClassType() { + return SendMovementPacketListener.class; + } + } +} diff --git a/src/main/java/net/aoba/event/listeners/SendMovementPacketListener.java b/src/main/java/net/aoba/event/listeners/SendMovementPacketListener.java new file mode 100644 index 00000000..513ce27c --- /dev/null +++ b/src/main/java/net/aoba/event/listeners/SendMovementPacketListener.java @@ -0,0 +1,8 @@ +package net.aoba.event.listeners; + +import net.aoba.event.events.SendMovementPacketEvent; + +public interface SendMovementPacketListener extends AbstractListener { + public abstract void onSendMovementPacket(SendMovementPacketEvent.Pre event); + public abstract void onSendMovementPacket(SendMovementPacketEvent.Post event); +} diff --git a/src/main/java/net/aoba/gui/components/widgets/AobaButtonWidget.java b/src/main/java/net/aoba/gui/components/widgets/AobaButtonWidget.java index 587a6835..4a5ec8ef 100644 --- a/src/main/java/net/aoba/gui/components/widgets/AobaButtonWidget.java +++ b/src/main/java/net/aoba/gui/components/widgets/AobaButtonWidget.java @@ -21,7 +21,7 @@ public class AobaButtonWidget extends PressableWidget { private Consumer pressAction; private long hoverStartTime = 0; - private static final long HOVER_ANIMATION_DURATION = 200; + private static final long HOVER_ANIMATION_DURATION = 200000000; public AobaButtonWidget(int x, int y, int width, int height, Text message) { super(x, y, width, height, message); @@ -44,12 +44,12 @@ protected void renderWidget(DrawContext context, int mouseX, int mouseY, float d Matrix4f matrix = context.getMatrices().peek().getPositionMatrix(); if (isHovered() && hoverStartTime == 0) { - hoverStartTime = System.currentTimeMillis(); + hoverStartTime = System.nanoTime(); } else if (!isHovered()) { hoverStartTime = 0; } - long currentTime = System.currentTimeMillis(); + long currentTime = System.nanoTime(); float hoverProgress = hoverStartTime > 0 ? (currentTime - hoverStartTime) / (float) HOVER_ANIMATION_DURATION : 0; hoverProgress = Math.min(hoverProgress, 1.0f); hoverProgress = (float) Math.sin(hoverProgress * Math.PI / 2); @@ -77,4 +77,4 @@ protected void appendClickableNarrations(NarrationMessageBuilder builder) { // For brevity, we'll just skip this for now - if you want to add narration to your widget, you can do so here. return; } -} \ No newline at end of file +} diff --git a/src/main/java/net/aoba/interfaces/IClientPlayerInteractionManager.java b/src/main/java/net/aoba/interfaces/IClientPlayerInteractionManager.java new file mode 100644 index 00000000..08b52f2c --- /dev/null +++ b/src/main/java/net/aoba/interfaces/IClientPlayerInteractionManager.java @@ -0,0 +1,5 @@ +package net.aoba.interfaces; + +public interface IClientPlayerInteractionManager { + void aoba$syncSelected(); +} \ No newline at end of file diff --git a/src/main/java/net/aoba/mixin/ClientPlayerEntityMixin.java b/src/main/java/net/aoba/mixin/ClientPlayerEntityMixin.java index 372d1cc6..7cd90196 100644 --- a/src/main/java/net/aoba/mixin/ClientPlayerEntityMixin.java +++ b/src/main/java/net/aoba/mixin/ClientPlayerEntityMixin.java @@ -21,6 +21,7 @@ import net.aoba.Aoba; import net.aoba.AobaClient; import net.aoba.event.events.PlayerHealthEvent; +import net.aoba.event.events.SendMovementPacketEvent; import net.aoba.gui.GuiManager; import net.aoba.mixin.interfaces.ICamera; import net.aoba.module.modules.movement.*; @@ -40,6 +41,8 @@ public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity @Shadow private ClientPlayNetworkHandler networkHandler; + @Shadow protected abstract void sendMovementPackets(); + @Inject(at = {@At("HEAD")}, method = "setShowsDeathScreen(Z)V") private void onShowDeathScreen(boolean state, CallbackInfo ci) { GuiManager hudManager = Aoba.getInstance().hudManager; @@ -124,4 +127,32 @@ public void onChangeLookDirection(double cursorDeltaX, ci.cancel(); } } + + @Inject(method = "sendMovementPackets", at = @At("HEAD")) + private void onSendMovementPacketsHead(CallbackInfo info) { + SendMovementPacketEvent.Pre sendMovementPacketPreEvent = new SendMovementPacketEvent.Pre(); + + Aoba.getInstance().eventManager.Fire(sendMovementPacketPreEvent); + } + + @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V", ordinal = 0)) + private void onTickHasVehicleBeforeSendPackets(CallbackInfo info) { + SendMovementPacketEvent.Pre sendMovementPacketPreEvent = new SendMovementPacketEvent.Pre(); + + Aoba.getInstance().eventManager.Fire(sendMovementPacketPreEvent); + } + + @Inject(method = "sendMovementPackets", at = @At("TAIL")) + private void onSendMovementPacketsTail(CallbackInfo info) { + SendMovementPacketEvent.Post sendMovementPacketPostEvent = new SendMovementPacketEvent.Post(); + + Aoba.getInstance().eventManager.Fire(sendMovementPacketPostEvent); + } + + @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V", ordinal = 1, shift = At.Shift.AFTER)) + private void onTickHasVehicleAfterSendPackets(CallbackInfo info) { + SendMovementPacketEvent.Post sendMovementPacketPostEvent = new SendMovementPacketEvent.Post(); + + Aoba.getInstance().eventManager.Fire(sendMovementPacketPostEvent); + } } diff --git a/src/main/java/net/aoba/mixin/ClientPlayerInteractionManagerMixin.java b/src/main/java/net/aoba/mixin/ClientPlayerInteractionManagerMixin.java index f27ba787..285d66eb 100644 --- a/src/main/java/net/aoba/mixin/ClientPlayerInteractionManagerMixin.java +++ b/src/main/java/net/aoba/mixin/ClientPlayerInteractionManagerMixin.java @@ -18,11 +18,21 @@ package net.aoba.mixin; +import net.aoba.interfaces.IClientPlayerInteractionManager; import net.minecraft.client.network.ClientPlayerInteractionManager; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; @Mixin(ClientPlayerInteractionManager.class) -public class ClientPlayerInteractionManagerMixin { +public abstract class ClientPlayerInteractionManagerMixin implements IClientPlayerInteractionManager { + @Shadow + protected abstract void syncSelectedSlot(); + + @Override + public void aoba$syncSelected() { + syncSelectedSlot(); + } + // TODO Reach? /* * @Inject(at = { @At("HEAD") }, method = { "getReachDistance()F" }, cancellable diff --git a/src/main/java/net/aoba/mixin/interfaces/IPlayerMoveC2SPacket.java b/src/main/java/net/aoba/mixin/interfaces/IPlayerMoveC2SPacket.java new file mode 100644 index 00000000..c5e67b59 --- /dev/null +++ b/src/main/java/net/aoba/mixin/interfaces/IPlayerMoveC2SPacket.java @@ -0,0 +1,17 @@ +package net.aoba.mixin.interfaces; + +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(PlayerMoveC2SPacket.class) +public interface IPlayerMoveC2SPacket { + @Mutable + @Accessor("y") + void setY(double y); + + @Mutable + @Accessor("onGround") + void setOnGround(boolean onGround); +} \ No newline at end of file diff --git a/src/main/java/net/aoba/module/Module.java b/src/main/java/net/aoba/module/Module.java index 2e3c4952..ccd15522 100644 --- a/src/main/java/net/aoba/module/Module.java +++ b/src/main/java/net/aoba/module/Module.java @@ -23,17 +23,27 @@ import net.aoba.Aoba; import net.aoba.AobaClient; +import net.aoba.interfaces.IClientPlayerInteractionManager; import net.aoba.mixin.interfaces.IMinecraftClient; import net.aoba.settings.Setting; import net.aoba.settings.SettingManager; import net.aoba.settings.types.KeybindSetting; +import net.aoba.utils.FindItemResult; +import net.minecraft.block.BlockState; import net.minecraft.client.MinecraftClient; import net.minecraft.client.util.InputUtil; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; +import java.util.function.Predicate; public abstract class Module { private String name; @@ -44,7 +54,7 @@ public abstract class Module { protected KeybindSetting keyBind; private List> settings = new ArrayList>(); - protected final MinecraftClient MC = AobaClient.MC; + protected static final MinecraftClient MC = AobaClient.MC; protected final IMinecraftClient IMC = AobaClient.IMC; /** @@ -136,7 +146,7 @@ public void setCategory(Category category) { * Retrieves the keybind associated with the module. * * @return The {@link KeybindSetting} that represents the keybinding - * for this module. + * for this module. */ public KeybindSetting getBind() { return this.keyBind; @@ -146,7 +156,7 @@ public KeybindSetting getBind() { * Gets the current state of the module. * * @return {@code true} if the module is enabled; - * {@code false} otherwise. + * {@code false} otherwise. */ public boolean getState() { return this.state; @@ -304,7 +314,7 @@ public void resetSettings() { * * @param category The {@link Category} to check against this module's category. * @return {@code true} if the module is in the specified category; - * {@code false} otherwise. + * {@code false} otherwise. */ public final boolean isCategory(Category category) { return category.equals(this.category); @@ -339,4 +349,149 @@ public final boolean isCategory(Category category) { */ int bind(); } -} + + public static int previousSlot = -1; + + public static FindItemResult findInHotbar(Item... items) { + return findInHotbar(itemStack -> { + for (Item item : items) { + if (itemStack.getItem() == item) return true; + } + return false; + }); + } + + public static FindItemResult findInHotbar(Predicate isGood) { + if (testInOffHand(isGood)) { + return new FindItemResult(45, MC.player.getOffHandStack().getCount()); + } + + if (testInMainHand(isGood)) { + return new FindItemResult(MC.player.getInventory().selectedSlot, MC.player.getMainHandStack().getCount()); + } + + return find(isGood, 0, 8); + } + + public static FindItemResult find(Predicate isGood) { + if (MC.player == null) { + return new FindItemResult(0, 0); + } + + return find(isGood, 0, MC.player.getInventory().size()); + } + + public static FindItemResult find(Predicate isGood, int start, int end) { + if (MC.player == null) { + return new FindItemResult(0, 0); + } + + int slot = -1; + int count = 0; + + for (int i = start; i <= end; i++) { + ItemStack stack = MC.player.getInventory().getStack(i); + + if (isGood.test(stack)) { + if (slot == -1) { + slot = i; + } + count += stack.getCount(); + } + } + + return new FindItemResult(slot, count); + } + + public static FindItemResult findFastestTool(BlockState state) { + float bestScore = 1; + int slot = -1; + + for (int i = 0; i < 9; i++) { + ItemStack stack = MC.player.getInventory().getStack(i); + + if (stack.isSuitableFor(state)) { + float score = stack.getMiningSpeedMultiplier(state); + + if (score > bestScore) { + bestScore = score; + slot = i; + } + } + } + + return new FindItemResult(slot, 1); + } + + public static boolean testInMainHand(Predicate predicate) { + return predicate.test(MC.player.getMainHandStack()); + } + + public static boolean testInOffHand(Predicate predicate) { + return predicate.test(MC.player.getOffHandStack()); + } + + public static boolean swap(int slot, boolean swapBack) { + if (slot == 45) { + return true; + } + + if (slot < 0 || slot > 8) { + return false; + } + + if (swapBack) { + if (previousSlot == -1) { + previousSlot = MC.player.getInventory().selectedSlot; + } + } else { + previousSlot = -1; + } + + MC.player.getInventory().selectedSlot = slot; + ((IClientPlayerInteractionManager) MC.interactionManager).aoba$syncSelected(); + return true; + } + + public static boolean swapBack() { + if (previousSlot == -1) { + return false; + } + + boolean result = swap(previousSlot, false); + previousSlot = -1; + return result; + } + + public static FindItemResult find(Item... items) { + return find(itemStack -> { + for (Item item : items) { + if (itemStack.getItem() == item) return true; + } + return false; + }); + } + + public static void rotatePitch(float degrees) { + MinecraftClient client = MinecraftClient.getInstance(); + PlayerEntity player = client.player; + + if (player != null) { + float currentPitch = player.getPitch(); + float newPitch = currentPitch + degrees; + + newPitch = Math.max(-90.0F, Math.min(90.0F, newPitch)); + + player.setPitch(newPitch); + + client.getNetworkHandler().sendPacket(new PlayerMoveC2SPacket.LookAndOnGround(player.getYaw(), newPitch, player.isOnGround())); + } + } + + public static void sendChatMessage(String message) { + MinecraftClient mc = MinecraftClient.getInstance(); + if (mc.inGameHud != null) { + mc.inGameHud.getChatHud().addMessage(Text.of(Formatting.DARK_PURPLE + "[" + Formatting.LIGHT_PURPLE + "Aoba" + Formatting.DARK_PURPLE + "] " + Formatting.RESET + message)); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/aoba/module/ModuleManager.java b/src/main/java/net/aoba/module/ModuleManager.java index dcfb7b4c..76725fa9 100644 --- a/src/main/java/net/aoba/module/ModuleManager.java +++ b/src/main/java/net/aoba/module/ModuleManager.java @@ -36,7 +36,6 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.util.InputUtil.Key; -import javax.tools.Tool; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -113,6 +112,9 @@ public class ModuleManager implements KeyDownListener { public Module xray = new XRay(); public Module zoom = new Zoom(); public Module tooltips = new Tooltips(); + public Module antihunger = new AntiHunger(); + public Module expthrower = new EXPThrower(); + public Module mcf = new MCA(); public ModuleManager(List addons) { addModule(aimbot); @@ -181,6 +183,9 @@ public ModuleManager(List addons) { addModule(xray); addModule(zoom); addModule(tooltips); + addModule(antihunger); + addModule(expthrower); + addModule(mcf); addons.stream().filter(Objects::nonNull).forEach(addon -> { try { diff --git a/src/main/java/net/aoba/module/modules/combat/CrystalAura.java b/src/main/java/net/aoba/module/modules/combat/CrystalAura.java index 21b4a344..7ef463b9 100644 --- a/src/main/java/net/aoba/module/modules/combat/CrystalAura.java +++ b/src/main/java/net/aoba/module/modules/combat/CrystalAura.java @@ -6,6 +6,7 @@ import net.aoba.event.listeners.Render3DListener; import net.aoba.event.listeners.TickListener; import net.aoba.gui.colors.Color; +import net.aoba.utils.FindItemResult; import net.aoba.utils.render.Render3D; import net.aoba.module.Category; import net.aoba.module.Module; @@ -187,21 +188,12 @@ public void OnUpdate(TickEvent event) { private void placeCrystal() { List players = MC.world.getPlayers(); - ItemStack[] inventory = MC.player.getInventory().main.toArray(new ItemStack[0]); - boolean switchSlot = autoSwitch.getValue(); Hand hand = handSetting.getValue() == HandSetting.MAIN_HAND ? Hand.MAIN_HAND : Hand.OFF_HAND; - int crystalSlot = -1; - if (switchSlot) { - for (int slot = 0; slot < 9; slot++) { - if (inventory[slot].getItem() == Items.END_CRYSTAL) { - crystalSlot = slot; - break; - } - } - if (crystalSlot == -1) return; - } + FindItemResult result = Module.find(Items.END_CRYSTAL); + + if (!result.found() && !result.isHotbar()) return; double radiusSquared = radius.getValue() * radius.getValue(); for (PlayerEntity player : players) { @@ -215,8 +207,8 @@ private void placeCrystal() { double damage = DamageUtils.crystalDamage(player, Vec3d.of(placePos.add(0, 1, 0))); if (damage < minDamage.getValue()) continue; - if (switchSlot) { - MC.player.getInventory().selectedSlot = crystalSlot; + if (autoSwitch.getValue()) { + Module.swap(result.slot(), false); } if (multiPlace.getValue()) { diff --git a/src/main/java/net/aoba/module/modules/misc/AntiHunger.java b/src/main/java/net/aoba/module/modules/misc/AntiHunger.java new file mode 100644 index 00000000..7475ff6a --- /dev/null +++ b/src/main/java/net/aoba/module/modules/misc/AntiHunger.java @@ -0,0 +1,88 @@ +package net.aoba.module.modules.misc; + +import net.aoba.Aoba; +import net.aoba.event.events.SendMovementPacketEvent; +import net.aoba.event.events.SendPacketEvent; +import net.aoba.event.events.TickEvent; +import net.aoba.event.listeners.SendMovementPacketListener; +import net.aoba.event.listeners.SendPacketListener; +import net.aoba.event.listeners.TickListener; +import net.aoba.mixin.interfaces.IPlayerMoveC2SPacket; +import net.aoba.module.Category; +import net.aoba.module.Module; +import net.aoba.settings.types.BooleanSetting; +import net.aoba.settings.types.KeybindSetting; +import net.minecraft.client.util.InputUtil; +import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import org.lwjgl.glfw.GLFW; + +public class AntiHunger extends Module implements SendPacketListener, SendMovementPacketListener { + private boolean lastOnGround, ignorePacket; + + public BooleanSetting sprint = new BooleanSetting("antihunger_sprint", "Sprint", "Change sprint packets.", true); + public BooleanSetting onGround = new BooleanSetting("antihunger_onground", "On Ground", "Fakes onGround.", true); + + public AntiHunger() { + super(new KeybindSetting("key.antihunger", "AntiHunger Key", InputUtil.fromKeyCode(GLFW.GLFW_KEY_UNKNOWN, 0))); + + this.setName("AntiHunger"); + this.setCategory(Category.of("misc")); + this.setDescription("Reduces the amount of hunger that is consumed."); + + this.addSetting(sprint); + this.addSetting(onGround); + } + + @Override + public void onDisable() { + Aoba.getInstance().eventManager.RemoveListener(SendPacketListener.class, this); + Aoba.getInstance().eventManager.RemoveListener(SendMovementPacketListener.class, this); + } + + @Override + public void onEnable() { + Aoba.getInstance().eventManager.AddListener(SendPacketListener.class, this); + Aoba.getInstance().eventManager.AddListener(SendMovementPacketListener.class, this); + + lastOnGround = MC.player.isOnGround(); + } + + @Override + public void onToggle() { + + } + + + @Override + public void OnSendPacket(SendPacketEvent event) { + if (ignorePacket && event.GetPacket() instanceof PlayerMoveC2SPacket) { + ignorePacket = false; + return; + } + + if (MC.player.hasVehicle() || MC.player.isTouchingWater() || MC.player.isSubmergedInWater()) return; + + if (event.GetPacket() instanceof ClientCommandC2SPacket packet && sprint.getValue()) { + if (packet.getMode() == ClientCommandC2SPacket.Mode.START_SPRINTING) event.cancel(); + } + + if (event.GetPacket() instanceof PlayerMoveC2SPacket packet && onGround.getValue() && MC.player.isOnGround() && MC.player.fallDistance <= 0.0 && !MC.interactionManager.isBreakingBlock()) { + ((IPlayerMoveC2SPacket) packet).setOnGround(false); + } + } + + @Override + public void onSendMovementPacket(SendMovementPacketEvent.Pre event) { + if (MC.player.isOnGround() && !lastOnGround && onGround.getValue()) { + ignorePacket = true; + } + + lastOnGround = MC.player.isOnGround(); + } + + @Override + public void onSendMovementPacket(SendMovementPacketEvent.Post event) { + + } +} diff --git a/src/main/java/net/aoba/module/modules/misc/EXPThrower.java b/src/main/java/net/aoba/module/modules/misc/EXPThrower.java new file mode 100644 index 00000000..c1f7e4da --- /dev/null +++ b/src/main/java/net/aoba/module/modules/misc/EXPThrower.java @@ -0,0 +1,56 @@ +package net.aoba.module.modules.misc; + +import net.aoba.Aoba; +import net.aoba.event.events.TickEvent; +import net.aoba.event.listeners.TickListener; +import net.aoba.module.Category; +import net.aoba.module.Module; +import net.aoba.settings.types.KeybindSetting; +import net.aoba.utils.FindItemResult; +import net.minecraft.client.util.InputUtil; +import net.minecraft.item.Items; +import org.lwjgl.glfw.GLFW; + +public class EXPThrower extends Module implements TickListener { + public EXPThrower() { + super(new KeybindSetting("key.expthrower", "EXPThrower Key", InputUtil.fromKeyCode(GLFW.GLFW_KEY_UNKNOWN, 0))); + + this.setName("EXPThrower"); + this.setCategory(Category.of("misc")); + this.setDescription("Automatically uses XP bottles."); + } + + @Override + public void onDisable() { + Aoba.getInstance().eventManager.RemoveListener(TickListener.class, this); + } + + @Override + public void onEnable() { + Aoba.getInstance().eventManager.AddListener(TickListener.class, this); + } + + @Override + public void onToggle() { + + } + + + @Override + public void OnUpdate(TickEvent event) { + FindItemResult exp = findInHotbar(Items.EXPERIENCE_BOTTLE); + if (!exp.found()) return; + + rotatePitch(90); + + if (exp.getHand() != null) { + MC.interactionManager.interactItem(MC.player, exp.getHand()); + } + + else { + swap(exp.slot(), true); + MC.interactionManager.interactItem(MC.player, exp.getHand()); + swapBack(); + } + } +} diff --git a/src/main/java/net/aoba/module/modules/misc/MCA.java b/src/main/java/net/aoba/module/modules/misc/MCA.java new file mode 100644 index 00000000..f0962d28 --- /dev/null +++ b/src/main/java/net/aoba/module/modules/misc/MCA.java @@ -0,0 +1,87 @@ +package net.aoba.module.modules.misc; + +import net.aoba.Aoba; +import net.aoba.event.events.MouseClickEvent; +import net.aoba.event.listeners.MouseClickListener; +import net.aoba.module.Category; +import net.aoba.module.Module; +import net.aoba.settings.types.EnumSetting; +import net.aoba.settings.types.KeybindSetting; +import net.aoba.utils.FindItemResult; +import net.aoba.utils.types.MouseAction; +import net.aoba.utils.types.MouseButton; +import net.minecraft.client.util.InputUtil; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Items; +import net.minecraft.util.Hand; +import org.lwjgl.glfw.GLFW; +import org.spongepowered.asm.mixin.injection.invoke.util.InvokeUtil; + +public class MCA extends Module implements MouseClickListener { + private final EnumSetting mode = new EnumSetting<>("mca_mode", "Mode", "The mode for the action to run when the middle mouse button is clicked.", Mode.FRIEND); + + private int selectedSlot; + + public MCA() { + super(new KeybindSetting("key.mca", "MCA Key", InputUtil.fromKeyCode(GLFW.GLFW_KEY_UNKNOWN, 0))); + + this.setName("MCA"); + this.setCategory(Category.of("misc")); + this.setDescription("Middle Click Action"); + + this.addSetting(mode); + } + + @Override + public void onDisable() { + Aoba.getInstance().eventManager.RemoveListener(MouseClickListener.class, this); + } + + @Override + public void onEnable() { + Aoba.getInstance().eventManager.AddListener(MouseClickListener.class, this); + } + + @Override + public void onToggle() { + + } + + @Override + public void OnMouseClick(MouseClickEvent mouseClickEvent) { + if (mouseClickEvent.button == MouseButton.MIDDLE && mouseClickEvent.action == MouseAction.DOWN) { + if (mode.getValue() == Mode.FRIEND) { + if (MC.targetedEntity == null) return; + if (!(MC.targetedEntity instanceof PlayerEntity player)) return; + + if (!Aoba.getInstance().friendsList.contains(player)) { + Aoba.getInstance().friendsList.addFriend(player); + mouseClickEvent.cancel(); + + sendChatMessage("Added " + player.getName().getString() + " to friends list."); + } else { + Aoba.getInstance().friendsList.removeFriend(player); + mouseClickEvent.cancel(); + + sendChatMessage("Removed " + player.getName().getString() + " from friends list."); + } + } else if (mode.getValue() == Mode.PEARL) { + FindItemResult result = find(Items.ENDER_PEARL); + + if (!result.found() || !result.isHotbar()) return; + + selectedSlot = MC.player.getInventory().selectedSlot; + + if (!result.isMainHand()) { + swap(result.slot(), false); + + MC.interactionManager.interactItem(MC.player, Hand.MAIN_HAND); + } + } + } + } + + public enum Mode { + FRIEND, PEARL + } +} diff --git a/src/main/java/net/aoba/module/modules/movement/EntityControl.java b/src/main/java/net/aoba/module/modules/movement/EntityControl.java index c97d2eb7..d36e929a 100644 --- a/src/main/java/net/aoba/module/modules/movement/EntityControl.java +++ b/src/main/java/net/aoba/module/modules/movement/EntityControl.java @@ -6,11 +6,16 @@ import net.aoba.interfaces.IHorseBaseEntity; import net.aoba.module.Category; import net.aoba.module.Module; +import net.aoba.settings.types.KeybindSetting; +import net.minecraft.client.util.InputUtil; import net.minecraft.entity.Entity; import net.minecraft.entity.passive.AbstractHorseEntity; +import org.lwjgl.glfw.GLFW; public class EntityControl extends Module implements TickListener { public EntityControl() { + super(new KeybindSetting("key.entitycontrol", "EntityControl Key", InputUtil.fromKeyCode(GLFW.GLFW_KEY_UNKNOWN, 0))); + this.setName("EntityControl"); this.setDescription("Allows you to control entities without needing a saddle."); this.setCategory(Category.of("Movement")); diff --git a/src/main/java/net/aoba/utils/FindItemResult.java b/src/main/java/net/aoba/utils/FindItemResult.java new file mode 100644 index 00000000..6aea9ec4 --- /dev/null +++ b/src/main/java/net/aoba/utils/FindItemResult.java @@ -0,0 +1,37 @@ +package net.aoba.utils; + +import net.minecraft.util.Hand; + +import static net.aoba.AobaClient.MC; + +public record FindItemResult(int slot, int count) { + public boolean found() { + return slot != -1; + } + + public Hand getHand() { + if (slot == 45) return Hand.OFF_HAND; + if (slot == MC.player.getInventory().selectedSlot) return Hand.MAIN_HAND; + return null; + } + + public boolean isMainHand() { + return getHand() == Hand.MAIN_HAND; + } + + public boolean isOffhand() { + return getHand() == Hand.OFF_HAND; + } + + public boolean isHotbar() { + return slot >= 0 && slot <= 8; + } + + public boolean isMain() { + return slot >= 9 && slot <= 35; + } + + public boolean isArmor() { + return slot >= 36 && slot <= 39; + } +} diff --git a/src/main/resources/aoba.mixins.json b/src/main/resources/aoba.mixins.json index efd3be08..e2928426 100644 --- a/src/main/resources/aoba.mixins.json +++ b/src/main/resources/aoba.mixins.json @@ -15,7 +15,8 @@ "interfaces.ICuboid", "interfaces.IRabbitEntityModel", "interfaces.IAnimalModel", - "interfaces.ILlamaEntityModel" + "interfaces.ILlamaEntityModel", + "interfaces.IPlayerMoveC2SPacket" ], "client": [ "AbstractBlockStateMixin", @@ -61,7 +62,7 @@ "WorldRendererMixin", "ShulkerBoxBlockMixin", "HandledScreenMixin", - "HorseBaseEntityMixin" + "HorseBaseEntityMixin", ], "injectors": { "defaultRequire": 1