Skip to content

Commit

Permalink
Moved villager trade display off to NMS proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
WillFP committed Dec 30, 2020
1 parent c6fef37 commit d87abbe
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 46 deletions.
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,14 @@

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;

Expand All @@ -32,46 +28,11 @@ public void onSend(@NotNull final PacketContainer packet) {
List<MerchantRecipe> 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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit d87abbe

Please sign in to comment.