diff --git a/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/VillagerTrade.java b/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/VillagerTrade.java new file mode 100644 index 00000000..a7efa008 --- /dev/null +++ b/eco-core/core-nms/v1_15_R1/src/main/java/com/willfp/eco/core/proxy/v1_15_R1/VillagerTrade.java @@ -0,0 +1,48 @@ +package com.willfp.eco.core.proxy.v1_15_R1; + +import com.willfp.eco.core.proxy.proxies.VillagerTradeProxy; +import com.willfp.ecoenchants.display.EnchantDisplay; +import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftMerchantRecipe; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.MerchantRecipe; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +public final class VillagerTrade implements VillagerTradeProxy { + @Override + public void displayTradeEnchantments(@NotNull final MerchantRecipe merchantRecipe) { + try { + // Enables removing final modifier + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + + // Bukkit MerchantRecipe result + Field fResult = MerchantRecipe.class.getDeclaredField("result"); + fResult.setAccessible(true); + ItemStack result = EnchantDisplay.displayEnchantments(merchantRecipe.getResult()); + EnchantDisplay.addV(result); + fResult.set(merchantRecipe, result); + + // Get NMS MerchantRecipe from CraftMerchantRecipe + Field fHandle = CraftMerchantRecipe.class.getDeclaredField("handle"); + fHandle.setAccessible(true); + net.minecraft.server.v1_15_R1.MerchantRecipe handle = (net.minecraft.server.v1_15_R1.MerchantRecipe) fHandle.get(merchantRecipe); // NMS Recipe + modifiersField.setInt(fHandle, fHandle.getModifiers() & ~Modifier.FINAL); // Remove final + + Field fSelling = net.minecraft.server.v1_15_R1.MerchantRecipe.class.getDeclaredField("sellingItem"); + fSelling.setAccessible(true); + modifiersField.setInt(fSelling, fSelling.getModifiers() & ~Modifier.FINAL); + + ItemStack selling = CraftItemStack.asBukkitCopy(handle.sellingItem); + EnchantDisplay.displayEnchantments(selling); + EnchantDisplay.addV(selling); + + fSelling.set(handle, CraftItemStack.asNMSCopy(selling)); + } catch (IllegalAccessException | NoSuchFieldException e) { + e.printStackTrace(); + } + } +} diff --git a/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/VillagerTrade.java b/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/VillagerTrade.java new file mode 100644 index 00000000..44a0d20c --- /dev/null +++ b/eco-core/core-nms/v1_16_R1/src/main/java/com/willfp/eco/core/proxy/v1_16_R1/VillagerTrade.java @@ -0,0 +1,48 @@ +package com.willfp.eco.core.proxy.v1_16_R1; + +import com.willfp.eco.core.proxy.proxies.VillagerTradeProxy; +import com.willfp.ecoenchants.display.EnchantDisplay; +import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftMerchantRecipe; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.MerchantRecipe; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +public final class VillagerTrade implements VillagerTradeProxy { + @Override + public void displayTradeEnchantments(@NotNull final MerchantRecipe merchantRecipe) { + try { + // Enables removing final modifier + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + + // Bukkit MerchantRecipe result + Field fResult = MerchantRecipe.class.getDeclaredField("result"); + fResult.setAccessible(true); + ItemStack result = EnchantDisplay.displayEnchantments(merchantRecipe.getResult()); + EnchantDisplay.addV(result); + fResult.set(merchantRecipe, result); + + // Get NMS MerchantRecipe from CraftMerchantRecipe + Field fHandle = CraftMerchantRecipe.class.getDeclaredField("handle"); + fHandle.setAccessible(true); + net.minecraft.server.v1_16_R1.MerchantRecipe handle = (net.minecraft.server.v1_16_R1.MerchantRecipe) fHandle.get(merchantRecipe); // NMS Recipe + modifiersField.setInt(fHandle, fHandle.getModifiers() & ~Modifier.FINAL); // Remove final + + Field fSelling = net.minecraft.server.v1_16_R1.MerchantRecipe.class.getDeclaredField("sellingItem"); + fSelling.setAccessible(true); + modifiersField.setInt(fSelling, fSelling.getModifiers() & ~Modifier.FINAL); + + ItemStack selling = CraftItemStack.asBukkitCopy(handle.sellingItem); + EnchantDisplay.displayEnchantments(selling); + EnchantDisplay.addV(selling); + + fSelling.set(handle, CraftItemStack.asNMSCopy(selling)); + } catch (IllegalAccessException | NoSuchFieldException e) { + e.printStackTrace(); + } + } +} diff --git a/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/VillagerTrade.java b/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/VillagerTrade.java new file mode 100644 index 00000000..f32cc6f2 --- /dev/null +++ b/eco-core/core-nms/v1_16_R2/src/main/java/com/willfp/eco/core/proxy/v1_16_R2/VillagerTrade.java @@ -0,0 +1,48 @@ +package com.willfp.eco.core.proxy.v1_16_R2; + +import com.willfp.eco.core.proxy.proxies.VillagerTradeProxy; +import com.willfp.ecoenchants.display.EnchantDisplay; +import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftMerchantRecipe; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.MerchantRecipe; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +public final class VillagerTrade implements VillagerTradeProxy { + @Override + public void displayTradeEnchantments(@NotNull final MerchantRecipe merchantRecipe) { + try { + // Enables removing final modifier + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + + // Bukkit MerchantRecipe result + Field fResult = MerchantRecipe.class.getDeclaredField("result"); + fResult.setAccessible(true); + ItemStack result = EnchantDisplay.displayEnchantments(merchantRecipe.getResult()); + EnchantDisplay.addV(result); + fResult.set(merchantRecipe, result); + + // Get NMS MerchantRecipe from CraftMerchantRecipe + Field fHandle = CraftMerchantRecipe.class.getDeclaredField("handle"); + fHandle.setAccessible(true); + net.minecraft.server.v1_16_R2.MerchantRecipe handle = (net.minecraft.server.v1_16_R2.MerchantRecipe) fHandle.get(merchantRecipe); // NMS Recipe + modifiersField.setInt(fHandle, fHandle.getModifiers() & ~Modifier.FINAL); // Remove final + + Field fSelling = net.minecraft.server.v1_16_R2.MerchantRecipe.class.getDeclaredField("sellingItem"); + fSelling.setAccessible(true); + modifiersField.setInt(fSelling, fSelling.getModifiers() & ~Modifier.FINAL); + + ItemStack selling = CraftItemStack.asBukkitCopy(handle.sellingItem); + EnchantDisplay.displayEnchantments(selling); + EnchantDisplay.addV(selling); + + fSelling.set(handle, CraftItemStack.asNMSCopy(selling)); + } catch (IllegalAccessException | NoSuchFieldException e) { + e.printStackTrace(); + } + } +} diff --git a/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/VillagerTrade.java b/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/VillagerTrade.java new file mode 100644 index 00000000..f760684a --- /dev/null +++ b/eco-core/core-nms/v1_16_R3/src/main/java/com/willfp/eco/core/proxy/v1_16_R3/VillagerTrade.java @@ -0,0 +1,48 @@ +package com.willfp.eco.core.proxy.v1_16_R3; + +import com.willfp.eco.core.proxy.proxies.VillagerTradeProxy; +import com.willfp.ecoenchants.display.EnchantDisplay; +import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftMerchantRecipe; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.MerchantRecipe; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +public final class VillagerTrade implements VillagerTradeProxy { + @Override + public void displayTradeEnchantments(@NotNull final MerchantRecipe merchantRecipe) { + try { + // Enables removing final modifier + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + + // Bukkit MerchantRecipe result + Field fResult = MerchantRecipe.class.getDeclaredField("result"); + fResult.setAccessible(true); + ItemStack result = EnchantDisplay.displayEnchantments(merchantRecipe.getResult()); + EnchantDisplay.addV(result); + fResult.set(merchantRecipe, result); + + // Get NMS MerchantRecipe from CraftMerchantRecipe + Field fHandle = CraftMerchantRecipe.class.getDeclaredField("handle"); + fHandle.setAccessible(true); + net.minecraft.server.v1_16_R3.MerchantRecipe handle = (net.minecraft.server.v1_16_R3.MerchantRecipe) fHandle.get(merchantRecipe); // NMS Recipe + modifiersField.setInt(fHandle, fHandle.getModifiers() & ~Modifier.FINAL); // Remove final + + Field fSelling = net.minecraft.server.v1_16_R3.MerchantRecipe.class.getDeclaredField("sellingItem"); + fSelling.setAccessible(true); + modifiersField.setInt(fSelling, fSelling.getModifiers() & ~Modifier.FINAL); + + ItemStack selling = CraftItemStack.asBukkitCopy(handle.sellingItem); + EnchantDisplay.displayEnchantments(selling); + EnchantDisplay.addV(selling); + + fSelling.set(handle, CraftItemStack.asNMSCopy(selling)); + } catch (IllegalAccessException | NoSuchFieldException e) { + e.printStackTrace(); + } + } +} diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/display/packets/PacketOpenWindowMerchant.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/display/packets/PacketOpenWindowMerchant.java index dbe64371..d0fbaaf5 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/display/packets/PacketOpenWindowMerchant.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/display/packets/PacketOpenWindowMerchant.java @@ -2,18 +2,14 @@ package com.willfp.ecoenchants.display.packets; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.events.PacketContainer; -import com.willfp.eco.core.proxy.ProxyConstants; -import com.willfp.eco.util.protocollib.AbstractPacketAdapter; +import com.willfp.eco.core.proxy.proxies.VillagerTradeProxy; +import com.willfp.eco.util.ProxyUtils; import com.willfp.eco.util.plugin.AbstractEcoPlugin; -import com.willfp.ecoenchants.display.EnchantDisplay; +import com.willfp.eco.util.protocollib.AbstractPacketAdapter; import com.willfp.ecoenchants.enchantments.meta.EnchantmentTarget; -import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.MerchantRecipe; import org.jetbrains.annotations.NotNull; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Modifier; import java.util.List; import java.util.stream.Collectors; @@ -32,46 +28,11 @@ public class PacketOpenWindowMerchant extends AbstractPacketAdapter { List recipes = packet.getMerchantRecipeLists().readSafely(0); recipes = recipes.stream().peek(merchantRecipe -> { - try { - if (!EnchantmentTarget.ALL.getMaterials().contains(merchantRecipe.getResult().getType())) { - return; - } - - // Enables removing final modifier - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - - // Bukkit MerchantRecipe result - Field fResult = merchantRecipe.getClass().getSuperclass().getDeclaredField("result"); - fResult.setAccessible(true); - ItemStack result = EnchantDisplay.displayEnchantments(merchantRecipe.getResult()); - result = EnchantDisplay.addV(result); - fResult.set(merchantRecipe, result); - - // Get NMS MerchantRecipe from CraftMerchantRecipe - Field fHandle = merchantRecipe.getClass().getDeclaredField("handle"); - fHandle.setAccessible(true); - Object handle = fHandle.get(merchantRecipe); // NMS Recipe - modifiersField.setInt(fHandle, fHandle.getModifiers() & ~Modifier.FINAL); // Remove final - - // NMS MerchantRecipe - Field fSelling = fHandle.get(merchantRecipe).getClass().getDeclaredField("sellingItem"); - fSelling.setAccessible(true); - Object selling = fSelling.get(handle); // NMS Selling ItemStack - modifiersField.setInt(fSelling, fSelling.getModifiers() & ~Modifier.FINAL); - - // Reflectively access CraftItemStack.class for respective version - Class craftItemStack = Class.forName("org.bukkit.craftbukkit." + ProxyConstants.NMS_VERSION + ".inventory.CraftItemStack"); - - // Bukkit Result ItemStack from NMS Result ItemStack - ItemStack nmsSelling = (ItemStack) craftItemStack.getMethod("asBukkitCopy", selling.getClass()).invoke(null, selling); - nmsSelling = EnchantDisplay.displayEnchantments(nmsSelling); - nmsSelling = EnchantDisplay.addV(nmsSelling); - fSelling.set(handle, craftItemStack.getMethod("asNMSCopy", ItemStack.class).invoke(null, nmsSelling)); - - } catch (IllegalAccessException | NoSuchFieldException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException e) { - e.printStackTrace(); + if (!EnchantmentTarget.ALL.getMaterials().contains(merchantRecipe.getResult().getType())) { + return; } + + ProxyUtils.getProxy(VillagerTradeProxy.class).displayTradeEnchantments(merchantRecipe); }).collect(Collectors.toList()); packet.getMerchantRecipeLists().writeSafely(0, recipes); diff --git a/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/VillagerTradeProxy.java b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/VillagerTradeProxy.java new file mode 100644 index 00000000..f7126d4e --- /dev/null +++ b/eco-core/core-proxy/src/main/java/com/willfp/eco/core/proxy/proxies/VillagerTradeProxy.java @@ -0,0 +1,13 @@ +package com.willfp.eco.core.proxy.proxies; + +import com.willfp.eco.core.proxy.AbstractProxy; +import org.bukkit.inventory.MerchantRecipe; + +public interface VillagerTradeProxy extends AbstractProxy { + /** + * Apply enchant display to the result of trades. + * + * @param merchantRecipe The recipe to modify. + */ + void displayTradeEnchantments(MerchantRecipe merchantRecipe); +}