Resource ItemStack serializer and deserializer (ItemMeta included)

Discussion in 'Spigot Plugin Development' started by DDevil_, May 28, 2016.

  1. As some of you might (or might not) know, the deserializing the ItemStack doesn't includes the ItemMeta with it, and getting it to work is kinda boring, so I went ahead and made it work, and now I'm posting it here because you people are so sexy, hope it helps someone :D
    Code (Java):
    public class ItemUtils {

        /**
         * Gets an item back from the Map created by {@link serialize()}
         *
         * @param map The map to deserialize from.
         * @return The deserialized item.
         * @throws IllegalAccessException Things can go wrong.
         * @throws IllegalArgumentException Things can go wrong.
         * @throws InvocationTargetException Things can go wrong.
         */

        public static ItemStack deserialize(Map<String, Object> map) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            ItemStack i = ItemStack.deserialize(map);
            if (map.containsKey("meta")) {
                try {
                    //  org.bukkit.craftbukkit.v1_8_R3.CraftMetaItem$SerializableMeta
                    //  CraftMetaItem.SerializableMeta.deserialize(Map<String, Object>)
                    if (ITEM_META_DESERIALIZATOR != null) {
                        ItemMeta im = (ItemMeta) DESERIALIZE.invoke(i, map.get("meta"));
                        i.setItemMeta(im);
                    }
                } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                    throw e;
                }
            }
            return i;
        }

        /**
         * Serializes an ItemStack and it's ItemMeta, use {@link deserialize()} to
         * get the item back.
         *
         * @param item Item to serialize
         * @return A HashMap with the serialized item
         */

        public static Map<String, Object> serialize(ItemStack item) {
            HashMap<String, Object> itemDocument = new HashMap(item.serialize());
            if (item.hasItemMeta()) {
                itemDocument.put("meta", new HashMap(item.getItemMeta().serialize()));
            }
            return itemDocument;
        }

        //Below here lays some crazy shit that make the above methods work :D yay!
        // <editor-fold desc="Some crazy shit" defaultstate="collapsed">
        /*
         * @return The string used in the CraftBukkit package for the version.
         */

        public static String getVersion() {
            String name = Bukkit.getServer().getClass().getPackage().getName();
            String version = name.substring(name.lastIndexOf('.') + 1) + ".";
            return version;
        }

        /**
         * Basic reflection.
         *
         * @param className
         * @return
         */

        public static Class<?> getOBCClass(String className) {
            String fullName = "org.bukkit.craftbukkit." + getVersion() + className;
            Class<?> clazz = null;
            try {
                clazz = Class.forName(fullName);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return clazz;
        }
        private static final Class ITEM_META_DESERIALIZATOR = getOBCClass("inventory.CraftMetaItem").getClasses()[0];
        private static final Method DESERIALIZE = getDeserialize();

        private static Method getDeserialize() {

            try {
                return ITEM_META_DESERIALIZATOR.getMethod("deserialize", new Class[]{Map.class});
            } catch (NoSuchMethodException | SecurityException ex) {
                return null;
            }
        }
        // </editor-fold>
    }
     
    • Useful Useful x 7
  2. Could you explain what itemstack serializing and deserializing is?
     
  3. Imagine you have a lego structure like this one:
    [​IMG]
    It is made of a lot of little bricks, you put them together it's complete.
    Now let's say that you are going to a friend's house, and you need to unbuild the house, store it into a box, and then build it again.
    Your house is now a bunch of bricks.
    [​IMG]
    When you arrive at your friend's house, you build the toy again and you two play together.
    This is a very basic explanation of what is serializing and deserializing, you should read more into that, it's a really interesting topic :) when you serialize, you take the ItemStack, transform it into little parts, and store them, when you deserialize it, you pick the parts and make a new ItemStack identical to the previous one :D
     
    #3 DDevil_, May 28, 2016
    Last edited: May 28, 2016
    • Winner Winner x 16
    • Like Like x 1
    • Agree Agree x 1
    • Funny Funny x 1
  4. e liek leego
     
    • Agree Agree x 2
  5. This is really useful! Thanks :)
     
    • Friendly Friendly x 1
  6. Disc

    Supporter

    Wow, this is a really good example..
     
    • Agree Agree x 6
  7. Can you please show how this would look in a config and how I would go on serializing an item and deserializing it? You have this Map parameter but never explain what to what with it, what should be inside its String and Object value.

    Also, what is this difference between this and itemStack.deserialize() and itemStack.serialize()? Are those ones missing something this one has?
     
  8. It's... Written... Like... Right here
    [​IMG]
    It's said that the Map comes from here:
    [​IMG]
    I also explained what serializing and deserializing is here:
    Also...
    I believe you haven't even tried yet...
     
  9. If I'm correct, your way does not serialize fireworks properly. Its meta still contains not-serializable FireworkEffect object - If I'm wrong, correct me.

    Is this working with custom NBT tags?
     
    #9 An0nym8us, Jun 6, 2016
    Last edited: Jun 6, 2016
    • Agree Agree x 1
  10. I'm not sure about NBT tags, but I get this error with fireworks:
    Code (Text):
    [15:25:17 WARN]: java.lang.reflect.InvocationTargetException
    [15:25:17 WARN]:        at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:502)
    [15:25:17 WARN]:        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:487)
    [15:25:17 WARN]:        at net.minecraft.server.v1_8_R3.PlayerList.onPlayerJoin(PlayerList.java:298)
    [15:25:17 WARN]:        at net.minecraft.server.v1_8_R3.PlayerList.a(PlayerList.java:157)
    [15:25:17 WARN]:        at net.minecraft.server.v1_8_R3.LoginListener.b(LoginListener.java:144)
    [15:25:17 WARN]:        at net.minecraft.server.v1_8_R3.LoginListener.c(LoginListener.java:54)
    [15:25:17 WARN]:        at net.minecraft.server.v1_8_R3.NetworkManager.a(NetworkManager.java:231)
    [15:25:17 WARN]:        at net.minecraft.server.v1_8_R3.ServerConnection.c(ServerConnection.java:148)
    [15:25:17 WARN]:        at net.minecraft.server.v1_8_R3.MinecraftServer.B(MinecraftServer.java:814)
    [15:25:17 WARN]:        at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:374)
    [15:25:17 WARN]:        at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:654)
    [15:25:17 WARN]:        at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:557)
    [15:25:17 WARN]:        at java.lang.Thread.run(Unknown Source)
    [15:25:17 WARN]: Caused by: java.lang.IllegalArgumentException: power(3.0) is not a valid class java.lang.Integer
    [15:25:17 WARN]:        at org.bukkit.craftbukkit.v1_8_R3.inventory.CraftMetaItem$SerializableMeta.getObject(CraftMetaItem.java:190)
    [15:25:17 WARN]:        at org.bukkit.craftbukkit.v1_8_R3.inventory.CraftMetaFirework.<init>(CraftMetaFirework.java:172)
    [15:25:17 WARN]:        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    [15:25:17 WARN]:        at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    [15:25:17 WARN]:        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    [15:25:17 WARN]:        at java.lang.reflect.Constructor.newInstance(Unknown Source)
    [15:25:17 WARN]:        at org.bukkit.craftbukkit.v1_8_R3.inventory.CraftMetaItem$SerializableMeta.deserialize(CraftMetaItem.java:155)
    [15:25:17 WARN]:        ... 29 more
     
    • Agree Agree x 1