From c29bded94c90ca0b97ddf877b6498833af95000f Mon Sep 17 00:00:00 2001 From: Brianna Date: Sat, 1 Feb 2020 10:05:54 -0500 Subject: [PATCH] Finally proper metadata cloning! --- .../ultimatestacker/entity/EntityStack.java | 55 +++++++++++++++---- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/songoda/ultimatestacker/entity/EntityStack.java b/src/main/java/com/songoda/ultimatestacker/entity/EntityStack.java index 8c574da..82365ac 100644 --- a/src/main/java/com/songoda/ultimatestacker/entity/EntityStack.java +++ b/src/main/java/com/songoda/ultimatestacker/entity/EntityStack.java @@ -17,8 +17,13 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.inventory.ItemStack; -import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.metadata.MetadataStoreBase; +import org.bukkit.metadata.MetadataValue; +import org.bukkit.plugin.Plugin; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.*; public class EntityStack { @@ -148,15 +153,8 @@ public class EntityStack { newEntity.getEquipment().setItemInHand(CompatibleMaterial.GOLDEN_SWORD.getItem()); if (Settings.CARRY_OVER_METADATA_ON_DEATH.getBoolean()) { - if (killed.hasMetadata("US_REASON")) - newEntity.setMetadata("US_REASON", killed.getMetadata("US_REASON").get(0)); - - if (killed.hasMetadata("ES")) - newEntity.setMetadata("ES", killed.getMetadata("ES").get(0)); - - String entityMetadataKey = "mcMMO: Spawned Entity"; - if (killed.hasMetadata(entityMetadataKey)) - newEntity.setMetadata(entityMetadataKey, new FixedMetadataValue(UltimateStacker.getInstance(), true)); + for (Map.Entry entry : getMetadata(killed).entrySet()) + newEntity.setMetadata(entry.getKey(), entry.getValue()); } DropUtils.processStackedDrop(killed, drops, event); @@ -172,6 +170,43 @@ public class EntityStack { } } + public Map getMetadata(LivingEntity subject) { + Map v = new HashMap<>(); + + Map> metadataMap = null; + try { + Object entityMetadata = methodGetEntityMetadata.invoke(Bukkit.getServer()); + metadataMap = (Map) fieldMetadataMap.get(entityMetadata); + } catch (IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } + + if (metadataMap == null) return v; + + for (Map.Entry> entry : metadataMap.entrySet()) { + if (!entry.getKey().startsWith(subject.getUniqueId().toString())) continue; + String key = entry.getKey().split(":")[1]; + for (MetadataValue value : entry.getValue().values()) + v.put(key, value); + } + return v; + } + + private static Method methodGetEntityMetadata; + private static Field fieldMetadataMap; + + static { + try { + String ver = Bukkit.getServer().getClass().getPackage().getName().substring(23); + Class clazzCraftServer = Class.forName("org.bukkit.craftbukkit." + ver + ".CraftServer"); + methodGetEntityMetadata = clazzCraftServer.getDeclaredMethod("getEntityMetadata"); + fieldMetadataMap = MetadataStoreBase.class.getDeclaredField("metadataMap"); + } catch (NoSuchFieldException | ClassNotFoundException | NoSuchMethodException e) { + e.printStackTrace(); + } + fieldMetadataMap.setAccessible(true); + } + public void onDeath(LivingEntity killed, List drops, boolean custom, int droppedExp, EntityDeathEvent event) { killed.setCustomName(null); killed.setCustomNameVisible(false);