Moved villager trade display off to NMS proxy

This commit is contained in:
Auxilor 2020-12-30 14:02:28 +00:00
parent c6fef37fb9
commit d87abbece6
6 changed files with 212 additions and 46 deletions

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -2,18 +2,14 @@ package com.willfp.ecoenchants.display.packets;
import com.comphenix.protocol.PacketType; import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketContainer;
import com.willfp.eco.core.proxy.ProxyConstants; import com.willfp.eco.core.proxy.proxies.VillagerTradeProxy;
import com.willfp.eco.util.protocollib.AbstractPacketAdapter; import com.willfp.eco.util.ProxyUtils;
import com.willfp.eco.util.plugin.AbstractEcoPlugin; 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 com.willfp.ecoenchants.enchantments.meta.EnchantmentTarget;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.MerchantRecipe; import org.bukkit.inventory.MerchantRecipe;
import org.jetbrains.annotations.NotNull; 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.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -32,46 +28,11 @@ public class PacketOpenWindowMerchant extends AbstractPacketAdapter {
List<MerchantRecipe> recipes = packet.getMerchantRecipeLists().readSafely(0); List<MerchantRecipe> recipes = packet.getMerchantRecipeLists().readSafely(0);
recipes = recipes.stream().peek(merchantRecipe -> { recipes = recipes.stream().peek(merchantRecipe -> {
try { if (!EnchantmentTarget.ALL.getMaterials().contains(merchantRecipe.getResult().getType())) {
if (!EnchantmentTarget.ALL.getMaterials().contains(merchantRecipe.getResult().getType())) { return;
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();
} }
ProxyUtils.getProxy(VillagerTradeProxy.class).displayTradeEnchantments(merchantRecipe);
}).collect(Collectors.toList()); }).collect(Collectors.toList());
packet.getMerchantRecipeLists().writeSafely(0, recipes); packet.getMerchantRecipeLists().writeSafely(0, recipes);

View File

@ -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);
}