Advertisement
Guest User

Untitled

a guest
Nov 17th, 2018
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 17.28 KB | None | 0 0
  1. package com.thesquadmc.networktools.utils.nms;
  2.  
  3. import com.google.common.primitives.Primitives;
  4. import org.bukkit.Bukkit;
  5. import org.bukkit.Location;
  6. import org.bukkit.block.Block;
  7. import org.bukkit.entity.Entity;
  8. import org.bukkit.inventory.ItemStack;
  9.  
  10. import java.lang.reflect.Constructor;
  11. import java.lang.reflect.Field;
  12. import java.lang.reflect.Method;
  13. import java.util.HashMap;
  14. import java.util.List;
  15. import java.util.Map;
  16.  
  17. public final class NBTUtils {
  18.  
  19.     private static HashMap<String, Class<?>> classCache;
  20.     private static HashMap<String, Method> methodCache;
  21.     private static HashMap<Class<?>, Constructor<?>> constructorCache;
  22.     private static HashMap<Class<?>, Class<?>> NBTClasses;
  23.     private static HashMap<Class<?>, Field> NBTTagFieldCache;
  24.     private static Field NBTListData;
  25.     private static Field NBTCompoundMap;
  26.     private static String version;
  27.  
  28.     static {
  29.         version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
  30.  
  31.         classCache = new HashMap<>();
  32.         try {
  33.             classCache.put("NBTBase", Class.forName("net.minecraft.server." + version + "." + "NBTBase"));
  34.             classCache.put("NBTTagCompound", Class.forName("net.minecraft.server." + version + "." + "NBTTagCompound"));
  35.             classCache.put("NBTTagList", Class.forName("net.minecraft.server." + version + "." + "NBTTagList"));
  36.             classCache.put("NBTBase", Class.forName("net.minecraft.server." + version + "." + "NBTBase"));
  37.  
  38.             classCache.put("ItemStack", Class.forName("net.minecraft.server." + version + "." + "ItemStack"));
  39.             classCache.put("CraftItemStack", Class.forName("org.bukkit.craftbukkit." + version + ".inventory." + "CraftItemStack"));
  40.  
  41.             classCache.put("Entity", Class.forName("net.minecraft.server." + version + "." + "Entity"));
  42.             classCache.put("CraftEntity", Class.forName("org.bukkit.craftbukkit." + version + ".entity." + "CraftEntity"));
  43.             classCache.put("EntityLiving", Class.forName("net.minecraft.server." + version + "." + "EntityLiving"));
  44.  
  45.             classCache.put("CraftWorld", Class.forName("org.bukkit.craftbukkit." + version + "." + "CraftWorld"));
  46.             classCache.put("CraftBlockState", Class.forName("org.bukkit.craftbukkit." + version + ".block." + "CraftBlockState"));
  47.             classCache.put("BlockPosition", Class.forName("net.minecraft.server." + version + "." + "BlockPosition"));
  48.             classCache.put("TileEntity", Class.forName("net.minecraft.server." + version + "." + "TileEntity"));
  49.             classCache.put("World", Class.forName("net.minecraft.server." + version + "." + "World"));
  50.         } catch (ClassNotFoundException e) {
  51.             e.printStackTrace();
  52.         }
  53.  
  54.         NBTClasses = new HashMap<>();
  55.         try {
  56.             NBTClasses.put(Byte.class, Class.forName("net.minecraft.server." + version + "." + "NBTTagByte"));
  57.             NBTClasses.put(String.class, Class.forName("net.minecraft.server." + version + "." + "NBTTagString"));
  58.             NBTClasses.put(Double.class, Class.forName("net.minecraft.server." + version + "." + "NBTTagDouble"));
  59.             NBTClasses.put(Integer.class, Class.forName("net.minecraft.server." + version + "." + "NBTTagInt"));
  60.             NBTClasses.put(Long.class, Class.forName("net.minecraft.server." + version + "." + "NBTTagLong"));
  61.             NBTClasses.put(Short.class, Class.forName("net.minecraft.server." + version + "." + "NBTTagShort"));
  62.             NBTClasses.put(Float.class, Class.forName("net.minecraft.server." + version + "." + "NBTTagFloat"));
  63.             NBTClasses.put(Class.forName("[B"), Class.forName("net.minecraft.server." + version + "." + "NBTTagByteArray"));
  64.             NBTClasses.put(Class.forName("[I"), Class.forName("net.minecraft.server." + version + "." + "NBTTagIntArray"));
  65.         } catch (ClassNotFoundException e) {
  66.             e.printStackTrace();
  67.         }
  68.  
  69.         methodCache = new HashMap<>();
  70.         try {
  71.             methodCache.put("get", getNMSClass("NBTTagCompound").getMethod("get", String.class));
  72.             methodCache.put("set", getNMSClass("NBTTagCompound").getMethod("set", String.class, getNMSClass("NBTBase")));
  73.             methodCache.put("hasKey", getNMSClass("NBTTagCompound").getMethod("hasKey", String.class));
  74.             methodCache.put("setIndex", getNMSClass("NBTTagList").getMethod("a", int.class, getNMSClass("NBTBase")));
  75.             methodCache.put("add", getNMSClass("NBTTagList").getMethod("add", getNMSClass("NBTBase")));
  76.  
  77.             methodCache.put("hasTag", getNMSClass("ItemStack").getMethod("hasTag"));
  78.             methodCache.put("getTag", getNMSClass("ItemStack").getMethod("getTag"));
  79.             methodCache.put("setTag", getNMSClass("ItemStack").getMethod("setTag", getNMSClass("NBTTagCompound")));
  80.             methodCache.put("asNMSCopy", getNMSClass("CraftItemStack").getMethod("asNMSCopy", ItemStack.class));
  81.             methodCache.put("asBukkitCopy", getNMSClass("CraftItemStack").getMethod("asBukkitCopy", getNMSClass("ItemStack")));
  82.  
  83.             methodCache.put("getEntityHandle", getNMSClass("CraftEntity").getMethod("getHandle"));
  84.             methodCache.put("getEntityTag", getNMSClass("Entity").getMethod("c", getNMSClass("NBTTagCompound")));
  85.             methodCache.put("setEntityTag", getNMSClass("Entity").getMethod("f", getNMSClass("NBTTagCompound")));
  86.  
  87.             methodCache.put("setTileTag", getNMSClass("TileEntity").getMethod("a", getNMSClass("NBTTagCompound")));
  88.             methodCache.put("getTileEntity", getNMSClass("World").getMethod("getTileEntity", getNMSClass("BlockPosition")));
  89.             methodCache.put("getWorldHandle", getNMSClass("CraftWorld").getMethod("getHandle"));
  90.         } catch (Exception e) {
  91.             e.printStackTrace();
  92.         }
  93.  
  94.         try {
  95.             methodCache.put("getTileTag", getNMSClass("TileEntity").getMethod("save", getNMSClass("NBTTagCompound")));
  96.         } catch (NoSuchMethodException exception) {
  97.             try {
  98.                 methodCache.put("getTileTag", getNMSClass("TileEntity").getMethod("b", getNMSClass("NBTTagCompound")));
  99.             } catch (Exception exception2) {
  100.                 exception2.printStackTrace();
  101.             }
  102.         } catch (Exception exception) {
  103.             exception.printStackTrace();
  104.         }
  105.  
  106.         constructorCache = new HashMap<>();
  107.         try {
  108.             constructorCache.put(getNBTTag(Byte.class), getNBTTag(Byte.class).getConstructor(byte.class));
  109.             constructorCache.put(getNBTTag(String.class), getNBTTag(String.class).getConstructor(String.class));
  110.             constructorCache.put(getNBTTag(Double.class), getNBTTag(Double.class).getConstructor(double.class));
  111.             constructorCache.put(getNBTTag(Integer.class), getNBTTag(Integer.class).getConstructor(int.class));
  112.             constructorCache.put(getNBTTag(Long.class), getNBTTag(Long.class).getConstructor(long.class));
  113.             constructorCache.put(getNBTTag(Float.class), getNBTTag(Float.class).getConstructor(float.class));
  114.             constructorCache.put(getNBTTag(Short.class), getNBTTag(Short.class).getConstructor(short.class));
  115.             constructorCache.put(getNBTTag(Class.forName("[B")), getNBTTag(Class.forName("[B")).getConstructor(Class.forName("[B")));
  116.             constructorCache.put(getNBTTag(Class.forName("[I")), getNBTTag(Class.forName("[I")).getConstructor(Class.forName("[I")));
  117.  
  118.             constructorCache.put(getNMSClass("BlockPosition"), getNMSClass("BlockPosition").getConstructor(int.class, int.class, int.class));
  119.         } catch (Exception e) {
  120.             e.printStackTrace();
  121.         }
  122.  
  123.         NBTTagFieldCache = new HashMap<>();
  124.         try {
  125.             for (Class<?> clazz : NBTClasses.values()) {
  126.                 Field data = clazz.getDeclaredField("data");
  127.                 data.setAccessible(true);
  128.                 NBTTagFieldCache.put(clazz, data);
  129.             }
  130.         } catch (Exception e) {
  131.             e.printStackTrace();
  132.         }
  133.  
  134.         try {
  135.             NBTListData = getNMSClass("NBTTagList").getDeclaredField("list");
  136.             NBTListData.setAccessible(true);
  137.             NBTCompoundMap = getNMSClass("NBTTagCompound").getDeclaredField("map");
  138.             NBTCompoundMap.setAccessible(true);
  139.         } catch (Exception e) {
  140.             e.printStackTrace();
  141.         }
  142.     }
  143.  
  144.     public static Class<?> getPrimitiveClass(Class<?> clazz) {
  145.         return Primitives.unwrap(clazz);
  146.     }
  147.  
  148.     public static Class<?> getNBTTag(Class<?> primitiveType) {
  149.         if (NBTClasses.containsKey(primitiveType))
  150.             return NBTClasses.get(primitiveType);
  151.         return primitiveType;
  152.     }
  153.  
  154.     public static Object getNBTVar(Object object) {
  155.         if (object == null) return null;
  156.         Class<?> clazz = object.getClass();
  157.         try {
  158.             if (NBTTagFieldCache.containsKey(clazz)) {
  159.                 System.out.println(NBTTagFieldCache.get(clazz).get(object));
  160.                 return NBTTagFieldCache.get(clazz).get(object);
  161.             }
  162.         } catch (Exception exception) {
  163.             exception.printStackTrace();
  164.         }
  165.         return null;
  166.     }
  167.  
  168.     public static Method getMethod(String name) {
  169.         return methodCache.containsKey(name) ? methodCache.get(name) : null;
  170.     }
  171.  
  172.     public static Constructor<?> getConstructor(Class<?> clazz) {
  173.         return constructorCache.containsKey(clazz) ? constructorCache.get(clazz) : null;
  174.     }
  175.  
  176.     public static Class<?> getNMSClass(String name) {
  177.         if (classCache.containsKey(name)) {
  178.             return classCache.get(name);
  179.         }
  180.  
  181.         try {
  182.             return Class.forName("net.minecraft.server." + version + "." + name);
  183.         } catch (ClassNotFoundException e) {
  184.             e.printStackTrace();
  185.             return null;
  186.         }
  187.     }
  188.  
  189.     public static Object getItemTag(ItemStack item, Object... keys) {
  190.         try {
  191.             Object stack;
  192.             stack = getMethod("asNMSCopy").invoke(null, item);
  193.  
  194.             Object tag;
  195.  
  196.             if (getMethod("hasTag").invoke(stack).equals(true)) {
  197.                 tag = getMethod("getTag").invoke(stack);
  198.             } else {
  199.                 tag = getNMSClass("NBTTagCompound").newInstance();
  200.             }
  201.  
  202.             return getTag(tag, keys);
  203.         } catch (Exception exception) {
  204.             exception.printStackTrace();
  205.             return null;
  206.         }
  207.     }
  208.  
  209.     public static ItemStack setItemTag(ItemStack item, Object value, Object... keys) {
  210.         try {
  211.             Object stack = getMethod("asNMSCopy").invoke(null, item);
  212.  
  213.             Object tag;
  214.  
  215.             if (getMethod("hasTag").invoke(stack).equals(true)) {
  216.                 tag = getMethod("getTag").invoke(stack);
  217.             } else {
  218.                 tag = getNMSClass("NBTTagCompound").newInstance();
  219.             }
  220.  
  221.             setTag(tag, value, keys);
  222.             getMethod("setTag").invoke(stack, tag);
  223.             return (ItemStack) getMethod("asBukkitCopy").invoke(null, stack);
  224.         } catch (Exception exception) {
  225.             exception.printStackTrace();
  226.             return null;
  227.         }
  228.     }
  229.  
  230.     public static Object getEntityTag(Entity entity, Object... keys) {
  231.         try {
  232.             Object NMSEntity = getMethod("getEntityHandle").invoke(entity);
  233.  
  234.             Object tag = getNMSClass("NBTTagCompound").newInstance();
  235.  
  236.             getMethod("getEntityTag").invoke(NMSEntity, tag);
  237.  
  238.             return getTag(tag, keys);
  239.         } catch (Exception exception) {
  240.             exception.printStackTrace();
  241.             return null;
  242.         }
  243.     }
  244.  
  245.     public static void setEntityTag(Entity entity, Object value, Object... keys) {
  246.         try {
  247.             Object NMSEntity = getMethod("getEntityHandle").invoke(entity);
  248.  
  249.             Object tag = getNMSClass("NBTTagCompound").newInstance();
  250.  
  251.             getMethod("getEntityTag").invoke(NMSEntity, tag);
  252.  
  253.             setTag(tag, value, keys);
  254.  
  255.             getMethod("setEntityTag").invoke(NMSEntity, tag);
  256.         } catch (Exception exception) {
  257.             exception.printStackTrace();
  258.             return;
  259.         }
  260.     }
  261.  
  262.     public static Object getBlockTag(Block block, Object... keys) {
  263.         try {
  264.             if (!getNMSClass("CraftBlockState").isInstance(block.getState())) {
  265.                 return null;
  266.             }
  267.  
  268.             Object tileEntity = getMethod("getTileEntity").invoke(block.getState());
  269.  
  270.             Object tag = getMethod("getTileTag").invoke(tileEntity, getNMSClass("NBTTagCompound").newInstance());
  271.  
  272.             return getTag(tag, keys);
  273.         } catch (Exception exception) {
  274.             exception.printStackTrace();
  275.             return null;
  276.         }
  277.     }
  278.  
  279.     public static void setBlockTag(Block block, Object value, Object... keys) {
  280.         try {
  281.             Location location = block.getLocation();
  282.  
  283.             Object blockPosition = getConstructor(getNMSClass("BlockPosition")).newInstance(location.getBlockX(), location.getBlockY(), location.getBlockZ());
  284.  
  285.             Object nmsWorld = getMethod("getWorldHandle").invoke(location.getWorld());
  286.  
  287.             Object tileEntity = getMethod("getTileEntity").invoke(nmsWorld, blockPosition);
  288.  
  289.             Object tag = getMethod("getTileTag").invoke(tileEntity, getNMSClass("NBTTagCompound").newInstance());
  290.  
  291.             setTag(tag, value, keys);
  292.  
  293.             getMethod("setTileTag").invoke(tileEntity, tag);
  294.         } catch (Exception exception) {
  295.             exception.printStackTrace();
  296.             return;
  297.         }
  298.     }
  299.  
  300.     private static void setTag(Object tag, Object value, Object... keys) throws Exception {
  301.         Object notCompound = getConstructor(getNBTTag(value.getClass())).newInstance(value);
  302.  
  303.         Object compound = tag;
  304.         for (int index = 0; index < keys.length; index++) {
  305.             Object key = keys[index];
  306.             if (index + 1 == keys.length) {
  307.                 if (key == null) {
  308.                     getMethod("add").invoke(compound, notCompound);
  309.                 } else if (key instanceof Integer) {
  310.                     getMethod("setIndex").invoke(compound, key, notCompound);
  311.                 } else {
  312.                     getMethod("set").invoke(compound, key, notCompound);
  313.                 }
  314.                 break;
  315.             }
  316.             Object oldCompound = compound;
  317.             if (key instanceof Integer) {
  318.                 compound = ((List<?>) NBTListData.get(compound)).get((int) key);
  319.             } else if (key != null) {
  320.                 compound = getMethod("get").invoke(compound, (String) key);
  321.             }
  322.             if (compound == null || key == null) {
  323.                 if (keys[index + 1] == null || keys[index + 1] instanceof Integer) {
  324.                     compound = getNMSClass("NBTTagList").newInstance();
  325.                 } else {
  326.                     compound = getNMSClass("NBTTagCompound").newInstance();
  327.                 }
  328.                 if (oldCompound.getClass().getSimpleName().equals("NBTTagList")) {
  329.                     getMethod("add").invoke(oldCompound, compound);
  330.                 } else {
  331.                     getMethod("set").invoke(oldCompound, key, compound);
  332.                 }
  333.             }
  334.         }
  335.     }
  336.  
  337.     private static Object getTag(Object tag, Object... keys) throws Exception {
  338.         if (keys.length == 0) return getTags(tag);
  339.  
  340.         Object notCompound = tag;
  341.  
  342.         for (Object key : keys) {
  343.             if (notCompound == null) return null;
  344.             if (getNMSClass("NBTTagCompound").isInstance(notCompound)) {
  345.                 notCompound = getMethod("get").invoke(notCompound, (String) key);
  346.             } else if (getNMSClass("NBTTagList").isInstance(notCompound)) {
  347.                 notCompound = ((List<?>) NBTListData.get(notCompound)).get((int) key);
  348.             } else {
  349.                 return getNBTVar(notCompound);
  350.             }
  351.         }
  352.         if (notCompound == null) return null;
  353.         if (getNMSClass("NBTTagList").isInstance(notCompound)) {
  354.             return getTags(notCompound);
  355.         } else if (getNMSClass("NBTTagCompound").isInstance(notCompound)) {
  356.             return getTags(notCompound);
  357.         } else {
  358.             return getNBTVar(notCompound);
  359.         }
  360.     }
  361.  
  362.     private static Object getTags(Object tag) {
  363.         HashMap<Object, Object> tags = new HashMap<>();
  364.         try {
  365.             if (getNMSClass("NBTTagCompound").isInstance(tag)) {
  366.                 Map<String, Object> tagCompound = (Map<String, Object>) NBTCompoundMap.get(tag);
  367.                 for (String key : tagCompound.keySet()) {
  368.                     Object value = tagCompound.get(key);
  369.                     if (getNMSClass("NBTTagEnd").isInstance(value)) continue;
  370.                     tags.put(key, getTag(value));
  371.                 }
  372.             } else if (getNMSClass("NBTTagList").isInstance(tag)) {
  373.                 List<Object> tagList = (List<Object>) NBTListData.get(tag);
  374.                 for (int index = 0; index < tagList.size(); index++) {
  375.                     Object value = tagList.get(index);
  376.                     if (getNMSClass("NBTTagEnd").isInstance(value)) continue;
  377.                     tags.put(index, getTag(value));
  378.                 }
  379.             } else {
  380.                 return getNBTVar(tag);
  381.             }
  382.             return tags;
  383.         } catch (Exception e) {
  384.             e.printStackTrace();
  385.             return tags;
  386.         }
  387.     }
  388.  
  389. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement