From 2e735bbb2e5a9f4b7a3ba38c4a4bbe3725c04d0c Mon Sep 17 00:00:00 2001 From: 0xTas Date: Fri, 11 Oct 2024 21:45:20 -0700 Subject: [PATCH] Tweaked Meteor's built-in AutoMend module to allow automatically equipping damaged elytras for mending. --- README.md | 1 + .../dev/stardust/mixin/AutoMendMixin.java | 178 ++++++++++++++++++ src/main/resources/stardust.mixins.json | 1 + 3 files changed, 180 insertions(+) create mode 100644 src/main/java/dev/stardust/mixin/AutoMendMixin.java diff --git a/README.md b/README.md index f38e003..6184ca3 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ OldSigns functionality can be accessed in the ChatSigns module settings. |---------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Illegal Disconnect** | *Adds "Illegal Disconnect" functionality to Meteor's built-in AutoLog module.* Enable this in the AutoLog module's settings. Also adds a config setting to put a dedicated Illegal Disconnect button on the pause menu. | | **Click-to-Come** | *When using Meteor's Freecam module, click on a block or entity to Baritone path there.* Enable this in the Freecam module's settings. | +| **Elytra Mending** | *Tweaks Meteor's built-in AutoMend module to allow automatically equipping damaged elytras for mending.* This can be used in conjunction with offhand mending, or exclusively by enabling the "ignore offhand" setting. | | **Title Screen Tweaks** | *2b2t-themed changes to the title screen.* Adds config settings to make the splash texts green, to cycle them randomly, and to add a 2b2t direct-connect button to the title screen. | | **Themed Category Icons** | *Enable module category icons in your config settings to see a random Stardust/2b2t-themed icon for the Stardust modules category.* Randomly picks a new icon each time you open your game! | diff --git a/src/main/java/dev/stardust/mixin/AutoMendMixin.java b/src/main/java/dev/stardust/mixin/AutoMendMixin.java new file mode 100644 index 0000000..4b55d71 --- /dev/null +++ b/src/main/java/dev/stardust/mixin/AutoMendMixin.java @@ -0,0 +1,178 @@ +package dev.stardust.mixin; + +import net.minecraft.text.Text; +import net.minecraft.item.Items; +import net.minecraft.item.ItemStack; +import dev.stardust.util.StardustUtil; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.jetbrains.annotations.Nullable; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.enchantment.Enchantments; +import org.spongepowered.asm.mixin.injection.At; +import meteordevelopment.meteorclient.utils.Utils; +import org.spongepowered.asm.mixin.injection.Inject; +import meteordevelopment.meteorclient.settings.Setting; +import meteordevelopment.meteorclient.settings.BoolSetting; +import meteordevelopment.meteorclient.utils.player.InvUtils; +import meteordevelopment.meteorclient.settings.SettingGroup; +import meteordevelopment.meteorclient.systems.modules.Module; +import meteordevelopment.meteorclient.systems.modules.Category; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import meteordevelopment.meteorclient.systems.modules.player.AutoMend; + +/** + * @author Tas [0xTas] + * + * Adds wearable elytra mending to Meteor's built-in AutoMend module. + **/ +@Mixin(value = AutoMend.class, remap = false) +public abstract class AutoMendMixin extends Module { + public AutoMendMixin(Category category, String name, String description) { + super(category, name, description); + } + + @Shadow + private boolean didMove; + @Shadow + @Final + private SettingGroup sgGeneral; + @Shadow + @Final + private Setting autoDisable; + @Shadow + protected abstract int getSlot(); + @Shadow + protected abstract int getEmptySlot(); + + @Unique + private boolean notified = false; + @Unique + private boolean didWearMending = false; + @Unique + @Nullable + private Setting wearMendElytras = null; + @Unique + @Nullable + private Setting mendElytrasOnly = null; + @Unique + @Nullable + private Setting ignoreOffhand = null; + + @Unique + private void replaceElytra() { + for (int n = 0; n < mc.player.getInventory().main.size(); n++) { + ItemStack stack = mc.player.getInventory().getStack(n); + if (stack.getItem() == Items.ELYTRA) { + if (Utils.hasEnchantment(stack, Enchantments.MENDING) && stack.getDamage() != 0) { + InvUtils.move().from(n).toArmor(2); + didWearMending = true; + return; + } + } + } + + if (!notified) { + if (mendElytrasOnly != null && mendElytrasOnly.get() + && ignoreOffhand != null && ignoreOffhand.get() && autoDisable.get()) { + if (getSlot() == -1 && getElytraSlot() == -1) { + toggle(); + sendToggledMsg(); + if (didWearMending) { + mc.player.sendMessage( + Text.of("§8<"+ StardustUtil.rCC()+"§o✨§r§8> "+"§7Done mending elytras.") + ); + } else { + mc.player.sendMessage( + Text.of("§8<"+ StardustUtil.rCC()+"§o✨§r§8> "+"§7No damaged elytras in inventory.") + ); + } + } + } + notified = true; + } + } + + @Unique + private int getElytraSlot() { + for (int n = 0; n < mc.player.getInventory().main.size(); n++) { + ItemStack stack = mc.player.getInventory().getStack(n); + if (stack.getItem() == Items.ELYTRA) { + if (Utils.hasEnchantment(stack, Enchantments.MENDING) && stack.getDamage() != 0) { + return n; + } + } + } + return -1; + } + + @Inject(method = "", at = @At(value = "FIELD", target = "Lmeteordevelopment/meteorclient/systems/modules/player/AutoMend;autoDisable:Lmeteordevelopment/meteorclient/settings/Setting;")) + private void addElytraMendSettings(CallbackInfo ci) { + wearMendElytras = sgGeneral.add( + new BoolSetting.Builder() + .name("wear-mend-elytras") + .description("Wear damaged mending elytras to mend them more efficiently.") + .defaultValue(false) + .build() + ); + mendElytrasOnly = sgGeneral.add( + new BoolSetting.Builder() + .name("mend-elytras-only") + .description("Only mend elytras, ignore other items.") + .defaultValue(false) + .build() + ); + ignoreOffhand = sgGeneral.add( + new BoolSetting.Builder() + .name("ignore-offhand") + .description("Do not swap items into offhand for mending.") + .defaultValue(false) + .visible(() -> mendElytrasOnly != null && mendElytrasOnly.get()) + .build() + ); + } + + @Inject(method = "onTick", at = @At("HEAD"), cancellable = true) + private void hijackOnTick(CallbackInfo ci) { + if (wearMendElytras == null || !wearMendElytras.get()) return; + ItemStack chest = mc.player.getEquippedStack(EquipmentSlot.CHEST); + if (chest.isEmpty() || chest.getItem() != Items.ELYTRA || !Utils.hasEnchantment(chest, Enchantments.MENDING) || chest.getDamage() == 0) { + replaceElytra(); + } + + if (mendElytrasOnly != null && mendElytrasOnly.get()) { + ci.cancel(); + if ((ignoreOffhand != null && ignoreOffhand.get())) return; + + ItemStack offhand = mc.player.getOffHandStack(); + if (offhand.isEmpty() || !Utils.hasEnchantment(offhand, Enchantments.MENDING) || offhand.getDamage() == 0) { + int slot = getElytraSlot(); + if (slot == -1) { + if (autoDisable.get()) { + if (didMove) { + info("Repaired all elytras, disabling..."); + int emptySlot = getEmptySlot(); + if (emptySlot != -1) { + InvUtils.move().fromOffhand().to(emptySlot); + } + } else { + info("No repairable elytras left in inventory, disabling..."); + } + toggle(); + } + } else { + InvUtils.move().from(slot).toOffhand(); + didMove = true; + } + } + } + } + + @Inject(method = "onActivate", at = @At("TAIL")) + private void resetNotified(CallbackInfo ci) { + notified = false; + didWearMending = false; + } +} diff --git a/src/main/resources/stardust.mixins.json b/src/main/resources/stardust.mixins.json index b430849..69f0bd8 100644 --- a/src/main/resources/stardust.mixins.json +++ b/src/main/resources/stardust.mixins.json @@ -40,6 +40,7 @@ "EntityMixin", "AutoLogMixin", "FreecamMixin", + "AutoMendMixin", "ItemStackMixin", "DoorBlockMixin", "PlayerEntityMixin",