From 97c494d7d4275b0eb0c39a092710620aa517cfe4 Mon Sep 17 00:00:00 2001 From: cqb13 Date: Thu, 25 Sep 2025 21:08:34 -0400 Subject: [PATCH 1/2] Added prefer enchanted setting to Chest Swap will try to find the elytra/chestplate with the best enchantments when swapping --- .../systems/modules/player/ChestSwap.java | 179 ++++++++++++++---- 1 file changed, 144 insertions(+), 35 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/player/ChestSwap.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/ChestSwap.java index 8cbeed193c..8d8ffb1e90 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/player/ChestSwap.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/ChestSwap.java @@ -14,11 +14,15 @@ import meteordevelopment.meteorclient.systems.modules.Module; import meteordevelopment.meteorclient.utils.player.InvUtils; import net.minecraft.component.DataComponentTypes; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.EquipmentSlot; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.network.packet.c2s.play.CloseHandledScreenC2SPacket; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.entry.RegistryEntry; public class ChestSwap extends Module { private final SettingGroup sgGeneral = settings.getDefaultGroup(); @@ -30,6 +34,13 @@ public class ChestSwap extends Module { .build() ); + private final Setting preferEnchanted = sgGeneral.add(new BoolSetting.Builder() + .name("prefer-enchanted") + .description("Prefers enchanted equipment when swapping") + .defaultValue(false) + .build() + ); + private final Setting stayOn = sgGeneral.add(new BoolSetting.Builder() .name("stay-on") .description("Stays on and activates when you turn it off.") @@ -72,44 +83,72 @@ public void swap() { } private boolean equipChestplate() { + assert mc.player != null; int bestSlot = -1; - boolean breakLoop = false; + int bestScore = -1; + boolean foundPreferred = false; for (int i = 0; i < mc.player.getInventory().getMainStacks().size(); i++) { - Item item = mc.player.getInventory().getMainStacks().get(i).getItem(); - - switch (chestplate.get()) { - case Diamond: - if (item == Items.DIAMOND_CHESTPLATE) { - bestSlot = i; - breakLoop = true; - } - break; - case Netherite: - if (item == Items.NETHERITE_CHESTPLATE) { - bestSlot = i; - breakLoop = true; - } - break; - case PreferDiamond: - if (item == Items.DIAMOND_CHESTPLATE) { - bestSlot = i; - breakLoop = true; - } else if (item == Items.NETHERITE_CHESTPLATE) { - bestSlot = i; - } - break; - case PreferNetherite: - if (item == Items.DIAMOND_CHESTPLATE) { - bestSlot = i; - } else if (item == Items.NETHERITE_CHESTPLATE) { - bestSlot = i; - breakLoop = true; - } - break; + ItemStack itemStack = mc.player.getInventory().getMainStacks().get(i); + Item item = itemStack.getItem(); + + if (!(item == Items.DIAMOND_CHESTPLATE || item == Items.NETHERITE_CHESTPLATE)) continue; + + if (!preferEnchanted.get()) { + switch (chestplate.get()) { + case Diamond: + if (item == Items.DIAMOND_CHESTPLATE) { + equip(i); + return true; + } + break; + case Netherite: + if (item == Items.NETHERITE_CHESTPLATE) { + equip(i); + return true; + } + break; + case PreferDiamond: + if (item == Items.DIAMOND_CHESTPLATE) { + equip(i); + return true; + } else if (bestSlot == -1) { + bestSlot = i; + } + break; + case PreferNetherite: + if (item == Items.NETHERITE_CHESTPLATE) { + equip(i); + return true; + } else if (bestSlot == -1) { + bestSlot = i; + } + break; + } + continue; } - if (breakLoop) break; + boolean isPreferred = + (chestplate.get() == Chestplate.Diamond && item == Items.DIAMOND_CHESTPLATE) || + (chestplate.get() == Chestplate.Netherite && item == Items.NETHERITE_CHESTPLATE) || + (chestplate.get() == Chestplate.PreferDiamond && item == Items.DIAMOND_CHESTPLATE) || + (chestplate.get() == Chestplate.PreferNetherite && item == Items.NETHERITE_CHESTPLATE); + + int score = rateArmorEnchantments(itemStack); + + if (isPreferred) { + // If there is a preferred chestplate ignore all not preferred chesplates + if (!foundPreferred || score > bestScore) { + bestScore = score; + bestSlot = i; + foundPreferred = true; + } + } else if (!foundPreferred) { + if (score > bestScore) { + bestScore = score; + bestSlot = i; + } + } } if (bestSlot != -1) equip(bestSlot); @@ -117,14 +156,84 @@ private boolean equipChestplate() { } private void equipElytra() { + assert mc.player != null; + int bestSlot = -1; + int bestScore = -1; + for (int i = 0; i < mc.player.getInventory().getMainStacks().size(); i++) { ItemStack item = mc.player.getInventory().getMainStacks().get(i); - if (item.contains(DataComponentTypes.GLIDER)) { - equip(i); + if (!item.contains(DataComponentTypes.GLIDER)) { + continue; + } + + if (!preferEnchanted.get()) { + bestSlot = i; break; } + + int score = rateElytraEnchantments(item); + + if (score >= bestScore) { + bestSlot = i; + bestScore = score; + } + } + + if (bestSlot != -1) { + equip(bestSlot); + } + } + + // 2 points for mending, 1 points for each level of unbreaking and any protection enchant + private int rateArmorEnchantments(ItemStack item) { + int score = 0; + + if (getEnchantmentLevel(item, Enchantments.MENDING) > 0) { + score += 2; + } + + score += getEnchantmentLevel(item, Enchantments.UNBREAKING); + + int prot = getEnchantmentLevel(item, Enchantments.PROTECTION); + + if (prot == 0) { + prot = getEnchantmentLevel(item, Enchantments.BLAST_PROTECTION); + } + + if (prot == 0) { + prot = getEnchantmentLevel(item, Enchantments.FIRE_PROTECTION); + } + + if (prot == 0) { + prot = getEnchantmentLevel(item, Enchantments.PROJECTILE_PROTECTION); + } + + score += prot; + + return score; + } + + // 2 points for mending, 1 point for each level of unbreaking + private int rateElytraEnchantments(ItemStack stack) { + int score = 0; + + if (getEnchantmentLevel(stack, Enchantments.MENDING) > 0) { + score += 2; + } + + score += getEnchantmentLevel(stack, Enchantments.UNBREAKING); + + return score; + } + + public static int getEnchantmentLevel(ItemStack stack, RegistryKey enchantment) { + for (RegistryEntry enchantments : stack.getEnchantments().getEnchantments()) { + if (enchantments.toString().contains(enchantment.getValue().toString())) { + return stack.getEnchantments().getLevel(enchantments); + } } + return 0; } private void equip(int slot) { From 90b1d89b3d5ea036a94c961bc13c1a4be31c81c5 Mon Sep 17 00:00:00 2001 From: cqb13 Date: Wed, 10 Dec 2025 15:28:00 -0500 Subject: [PATCH 2/2] added discourage and block curse of binding options --- .../systems/modules/player/ChestSwap.java | 114 +++++++++++++----- 1 file changed, 82 insertions(+), 32 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/player/ChestSwap.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/ChestSwap.java index 8d8ffb1e90..2640c1057a 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/player/ChestSwap.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/ChestSwap.java @@ -28,32 +28,41 @@ public class ChestSwap extends Module { private final SettingGroup sgGeneral = settings.getDefaultGroup(); private final Setting chestplate = sgGeneral.add(new EnumSetting.Builder() - .name("chestplate") - .description("Which type of chestplate to swap to.") - .defaultValue(Chestplate.PreferNetherite) - .build() - ); + .name("chestplate") + .description("Which type of chestplate to swap to.") + .defaultValue(Chestplate.PreferNetherite) + .build()); private final Setting preferEnchanted = sgGeneral.add(new BoolSetting.Builder() - .name("prefer-enchanted") - .description("Prefers enchanted equipment when swapping") - .defaultValue(false) - .build() - ); + .name("prefer-enchanted") + .description("Prefers enchanted equipment when swapping") + .defaultValue(false) + .build()); + + private final Setting discourageCurseOfBinding = sgGeneral.add(new BoolSetting.Builder() + .name("discourage-curse-of-binding") + .description("Prefers equipment without curse of binding") + .defaultValue(false) + .build()); + + private final Setting blockCurseOfBinding = sgGeneral.add(new BoolSetting.Builder() + .name("block-curse-of-binding") + .description("Prevents equipment with curse of binding from being equiped") + .defaultValue(false) + .visible(discourageCurseOfBinding::get) + .build()); private final Setting stayOn = sgGeneral.add(new BoolSetting.Builder() - .name("stay-on") - .description("Stays on and activates when you turn it off.") - .defaultValue(false) - .build() - ); + .name("stay-on") + .description("Stays on and activates when you turn it off.") + .defaultValue(false) + .build()); private final Setting closeInventory = sgGeneral.add(new BoolSetting.Builder() - .name("close-inventory") - .description("Sends inventory close after swap.") - .defaultValue(true) - .build() - ); + .name("close-inventory") + .description("Sends inventory close after swap.") + .defaultValue(true) + .build()); public ChestSwap() { super(Categories.Player, "chest-swap", "Automatically swaps between a chestplate and an elytra."); @@ -62,12 +71,14 @@ public ChestSwap() { @Override public void onActivate() { swap(); - if (!stayOn.get()) toggle(); + if (!stayOn.get()) + toggle(); } @Override public void onDeactivate() { - if (stayOn.get()) swap(); + if (stayOn.get()) + swap(); } public void swap() { @@ -75,10 +86,12 @@ public void swap() { if (currentItem.contains(DataComponentTypes.GLIDER)) { equipChestplate(); - } else if (currentItem.contains(DataComponentTypes.EQUIPPABLE) && currentItem.get(DataComponentTypes.EQUIPPABLE).slot().getEntitySlotId() == EquipmentSlot.CHEST.getEntitySlotId()) { + } else if (currentItem.contains(DataComponentTypes.EQUIPPABLE) && currentItem.get(DataComponentTypes.EQUIPPABLE) + .slot().getEntitySlotId() == EquipmentSlot.CHEST.getEntitySlotId()) { equipElytra(); } else { - if (!equipChestplate()) equipElytra(); + if (!equipChestplate()) + equipElytra(); } } @@ -92,8 +105,17 @@ private boolean equipChestplate() { ItemStack itemStack = mc.player.getInventory().getMainStacks().get(i); Item item = itemStack.getItem(); - if (!(item == Items.DIAMOND_CHESTPLATE || item == Items.NETHERITE_CHESTPLATE)) continue; + if (!(item == Items.DIAMOND_CHESTPLATE || item == Items.NETHERITE_CHESTPLATE)) { + continue; + } + + boolean hasBinding = hasCurseOfBinding(itemStack); + + if (hasBinding && discourageCurseOfBinding.get() && blockCurseOfBinding.get()) { + continue; + } + // TODO: add discourage binding logic here if (!preferEnchanted.get()) { switch (chestplate.get()) { case Diamond: @@ -128,14 +150,18 @@ private boolean equipChestplate() { continue; } - boolean isPreferred = - (chestplate.get() == Chestplate.Diamond && item == Items.DIAMOND_CHESTPLATE) || + boolean isPreferred = (chestplate.get() == Chestplate.Diamond && item == Items.DIAMOND_CHESTPLATE) || (chestplate.get() == Chestplate.Netherite && item == Items.NETHERITE_CHESTPLATE) || (chestplate.get() == Chestplate.PreferDiamond && item == Items.DIAMOND_CHESTPLATE) || (chestplate.get() == Chestplate.PreferNetherite && item == Items.NETHERITE_CHESTPLATE); int score = rateArmorEnchantments(itemStack); + if (hasBinding && discourageCurseOfBinding.get()) { + isPreferred = false; + score = 0; + } + if (isPreferred) { // If there is a preferred chestplate ignore all not preferred chesplates if (!foundPreferred || score > bestScore) { @@ -151,7 +177,9 @@ private boolean equipChestplate() { } } - if (bestSlot != -1) equip(bestSlot); + if (bestSlot != -1) { + equip(bestSlot); + } return bestSlot != -1; } @@ -167,6 +195,12 @@ private void equipElytra() { continue; } + boolean hasBinding = hasCurseOfBinding(item); + + if (hasBinding && discourageCurseOfBinding.get() && blockCurseOfBinding.get()) { + continue; + } + if (!preferEnchanted.get()) { bestSlot = i; break; @@ -174,6 +208,10 @@ private void equipElytra() { int score = rateElytraEnchantments(item); + if (hasBinding && discourageCurseOfBinding.get()) { + score = 0; + } + if (score >= bestScore) { bestSlot = i; bestScore = score; @@ -185,7 +223,8 @@ private void equipElytra() { } } - // 2 points for mending, 1 points for each level of unbreaking and any protection enchant + // 2 points for mending, 1 points for each level of unbreaking and any + // protection enchant private int rateArmorEnchantments(ItemStack item) { int score = 0; @@ -227,6 +266,14 @@ private int rateElytraEnchantments(ItemStack stack) { return score; } + private boolean hasCurseOfBinding(ItemStack stack) { + if (getEnchantmentLevel(stack, Enchantments.BINDING_CURSE) > 0) { + return true; + } + + return false; + } + public static int getEnchantmentLevel(ItemStack stack, RegistryKey enchantment) { for (RegistryEntry enchantments : stack.getEnchantments().getEnchantments()) { if (enchantments.toString().contains(enchantment.getValue().toString())) { @@ -239,15 +286,18 @@ public static int getEnchantmentLevel(ItemStack stack, RegistryKey private void equip(int slot) { InvUtils.move().from(slot).toArmor(2); if (closeInventory.get()) { - // Notchian clients send a Close Window packet with Window ID 0 to close their inventory even though there is never an Open Screen packet for the inventory. + // Notchian clients send a Close Window packet with Window ID 0 to close their + // inventory even though there is never an Open Screen packet for the inventory. mc.getNetworkHandler().sendPacket(new CloseHandledScreenC2SPacket(0)); } } @Override public void sendToggledMsg() { - if (stayOn.get()) super.sendToggledMsg(); - else if (Config.get().chatFeedback.get() && chatFeedback) info("Triggered (highlight)%s(default).", title); + if (stayOn.get()) + super.sendToggledMsg(); + else if (Config.get().chatFeedback.get() && chatFeedback) + info("Triggered (highlight)%s(default).", title); } public enum Chestplate {