Solved Serializing/deserializing ItemStacks removes ItemMeta

Discussion in 'Spigot Plugin Development' started by Timo_Ho, May 15, 2016.

  1. In an update for my plugin I added a mail feature with attachments, but the ItemStack only uses the type when it gets deserialized. Here are my methods:
    Code (Text):
        public String toString() {
            String s = "";
            String serializedMap = "";
            if (this.content == null) {
                serializedMap = "noContent";
            } else {
                Map<String,Object> map = this.content.serialize();
                serializedMap = "";
                for (int i = 0;i<map.size();i++) {
                    String str = (String) map.keySet().toArray()[i];
                    if (i == (map.size()-1)) {
                        serializedMap = serializedMap + str + "-=-" + map.get(str);
                    } else {
                        serializedMap = serializedMap + str + "-=-" + map.get(str) + ";;";
                    }
                }
               
            }
            s = this.senderName + "-:-" + this.senderUUID.toString() + "-:-" + this.text + "-:-" + serializedMap;
            return s;
        }
        public static PlayerMail valueOf(String s) {
            String[] data = s.split("-:-");
            ItemStack content = null;
            if (!data[3].equalsIgnoreCase("noContent")) {
                Map<String,Object> map = new LinkedHashMap<String,Object>();
                for (String str:data[3].split(";;")) {
                    String key = str.split("-=-")[0];
                    String val = str.split("-=-")[1];
                    map.put(key, val);
                }
                content = ItemStack.deserialize(map);
            }
            String senderName = data[0];
            UUID senderUUID = UUID.fromString(data[1]);
            String text = data[2];
            return new PlayerMail(senderName, senderUUID, text, content,null);
        }
    I'm not getting any errors and the ItemMeta is clearly in the serialized string, but it doesn't get deserialized.
     
  2. I always use this class:
    Code (Java):

    public class ItemSerializer {

        /*
         * @author ElDzi
         */

        public static String itemsToString(ItemStack[] items) {
            try {
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(bos);
                oos.writeObject(serializeItemStack(items));
                oos.flush();
                return DatatypeConverter.printBase64Binary(bos.toByteArray());
            }
            catch (Exception e) {
                Logger.exception(e);
            }
            return "";
        }

        public static ItemStack[] stringToItems(String s) {
            try {
                ByteArrayInputStream bis = new ByteArrayInputStream(
                       DatatypeConverter.parseBase64Binary(s));
                ObjectInputStream ois = new ObjectInputStream(bis);
                return deserializeItemStack(
                       (Map<String, Object>[]) ois.readObject());
            }
            catch (Exception e) {
                Logger.exception(e);
            }
            return new ItemStack[] {
                   new ItemStack(Material.AIR) };
        }

        @SuppressWarnings("unchecked")
        private static Map<String, Object>[] serializeItemStack(ItemStack[] items) {

            Map<String, Object>[] result = new Map[items.length];

            for (int i = 0; i < items.length; i++) {
                ItemStack is = items[i];
                if (is == null) {
                    result[i] = new HashMap<>();
                }
                else {
                    result[i] = is.serialize();
                    if (is.hasItemMeta()) {
                        result[i].put("meta", is.getItemMeta().serialize());
                    }
                }
            }

            return result;
        }

        @SuppressWarnings("unchecked")
        private static ItemStack[] deserializeItemStack(Map<String, Object>[] map) {
            ItemStack[] items = new ItemStack[map.length];

            for (int i = 0; i < items.length; i++) {
                Map<String, Object> s = map[i];
                if (s.size() == 0) {
                    items[i] = null;
                }
                else {
                    try {
                        if (s.containsKey("meta")) {
                            Map<String, Object> im = new HashMap<>(
                                   (Map<String, Object>) s.remove("meta"));
                            im.put("==", "ItemMeta");
                            ItemStack is = ItemStack.deserialize(s);
                            is.setItemMeta((ItemMeta) ConfigurationSerialization
                                   .deserializeObject(im));
                            items[i] = is;
                        }
                        else {
                            items[i] = ItemStack.deserialize(s);
                        }
                    }
                    catch (Exception e) {
                        Logger.exception(e);
                        items[i] = null;
                    }
                }

            }

            return items;
        }

    }
     
    It works pretty ! :)
     
    • Useful Useful x 1
  3. what is that serializeItemStack()?
     
    #3 Timo_Ho, May 15, 2016
    Last edited: May 15, 2016
  4. it save itemstack with meta ;>
     
  5. Sorry I asked because I didn't scroll down that far. I can test it in about four hours. Thanks for your answer.
     
  6. I think your code works, but I had to modify it a bit to use it for only one itemStack but now It gives me an error:
    Code (Text):
    [20:31:30 WARN]: java.io.NotSerializableException: org.bukkit.craftbukkit.v1_9_R2.inventory.CraftMetaItem
    [20:31:30 WARN]:        at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    [20:31:30 WARN]:        at java.io.ObjectOutputStream.writeObject(Unknown Source)
    [20:31:30 WARN]:        at java.util.LinkedHashMap.internalWriteEntries(Unknown Source)
    [20:31:30 WARN]:        at java.util.HashMap.writeObject(Unknown Source)
    [20:31:30 WARN]:        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    [20:31:30 WARN]:        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    [20:31:30 WARN]:        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    [20:31:30 WARN]:        at java.lang.reflect.Method.invoke(Unknown Source)
    [20:31:30 WARN]:        at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
    [20:31:30 WARN]:        at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    [20:31:30 WARN]:        at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    [20:31:30 WARN]:        at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    [20:31:30 WARN]:        at java.io.ObjectOutputStream.writeObject(Unknown Source)
    [20:31:30 WARN]:        at me.tmods.api.Serializer.serializeItemStack(Serializer.java:51)
    [20:31:30 WARN]:        at me.tmods.api.PlayerMail.toString(PlayerMail.java:82)
    [20:31:30 WARN]:        at me.tmods.api.MailBox.save(MailBox.java:96)
    [20:31:30 WARN]:        at me.tmods.serverutils.main.onCommand(main.java:516)
    [20:31:30 WARN]:        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44)
    [20:31:30 WARN]:        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141)
    [20:31:30 WARN]:        at org.bukkit.craftbukkit.v1_9_R2.CraftServer.dispatchCommand(CraftServer.java:645)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.PlayerConnection.handleCommand(PlayerConnection.java:1349)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.PlayerConnection.a(PlayerConnection.java:1184)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.PacketPlayInChat.a(PacketPlayInChat.java:45)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.PacketPlayInChat.a(PacketPlayInChat.java:1)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.PlayerConnectionUtils$1.run(SourceFile:13)
    [20:31:30 WARN]:        at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    [20:31:30 WARN]:        at java.util.concurrent.FutureTask.run(Unknown Source)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.SystemUtils.a(SourceFile:45)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.MinecraftServer.D(MinecraftServer.java:726)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.DedicatedServer.D(DedicatedServer.java:399)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.MinecraftServer.C(MinecraftServer.java:665)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.MinecraftServer.run(MinecraftServer.java:564)
    [20:31:30 WARN]:        at java.lang.Thread.run(Unknown Source)
    [20:31:30 WARN]: java.io.NotSerializableException: org.bukkit.craftbukkit.v1_9_R2.inventory.CraftMetaItem
    [20:31:30 WARN]:        at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    [20:31:30 WARN]:        at java.io.ObjectOutputStream.writeObject(Unknown Source)
    [20:31:30 WARN]:        at java.util.LinkedHashMap.internalWriteEntries(Unknown Source)
    [20:31:30 WARN]:        at java.util.HashMap.writeObject(Unknown Source)
    [20:31:30 WARN]:        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    [20:31:30 WARN]:        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    [20:31:30 WARN]:        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    [20:31:30 WARN]:        at java.lang.reflect.Method.invoke(Unknown Source)
    [20:31:30 WARN]:        at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
    [20:31:30 WARN]:        at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    [20:31:30 WARN]:        at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    [20:31:30 WARN]:        at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    [20:31:30 WARN]:        at java.io.ObjectOutputStream.writeObject(Unknown Source)
    [20:31:30 WARN]:        at me.tmods.api.Serializer.serializeItemStack(Serializer.java:51)
    [20:31:30 WARN]:        at me.tmods.api.PlayerMail.toString(PlayerMail.java:82)
    [20:31:30 WARN]:        at me.tmods.api.MailBox.save(MailBox.java:96)
    [20:31:30 WARN]:        at me.tmods.serverutils.main.onCommand(main.java:516)
    [20:31:30 WARN]:        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44)
    [20:31:30 WARN]:        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141)
    [20:31:30 WARN]:        at org.bukkit.craftbukkit.v1_9_R2.CraftServer.dispatchCommand(CraftServer.java:645)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.PlayerConnection.handleCommand(PlayerConnection.java:1349)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.PlayerConnection.a(PlayerConnection.java:1184)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.PacketPlayInChat.a(PacketPlayInChat.java:45)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.PacketPlayInChat.a(PacketPlayInChat.java:1)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.PlayerConnectionUtils$1.run(SourceFile:13)
    [20:31:30 WARN]:        at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    [20:31:30 WARN]:        at java.util.concurrent.FutureTask.run(Unknown Source)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.SystemUtils.a(SourceFile:45)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.MinecraftServer.D(MinecraftServer.java:726)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.DedicatedServer.D(DedicatedServer.java:399)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.MinecraftServer.C(MinecraftServer.java:665)
    [20:31:30 WARN]:        at net.minecraft.server.v1_9_R2.MinecraftServer.run(MinecraftServer.java:564)
    [20:31:30 WARN]:        at java.lang.Thread.run(Unknown Source)
    I tried to send a Compass with a name

    And when I try to list my mails another error appears:
    Code (Text):
    [20:37:05 WARN]: java.lang.NullPointerException
    [20:37:05 WARN]:        at me.tmods.serverutils.main.onCommand(main.java:551)
    [20:37:05 WARN]:        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44)
    [20:37:05 WARN]:        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141)
    [20:37:05 WARN]:        at org.bukkit.craftbukkit.v1_9_R2.CraftServer.dispatchCommand(CraftServer.java:645)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.PlayerConnection.handleCommand(PlayerConnection.java:1349)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.PlayerConnection.a(PlayerConnection.java:1184)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.PacketPlayInChat.a(PacketPlayInChat.java:45)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.PacketPlayInChat.a(PacketPlayInChat.java:1)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.PlayerConnectionUtils$1.run(SourceFile:13)
    [20:37:05 WARN]:        at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    [20:37:05 WARN]:        at java.util.concurrent.FutureTask.run(Unknown Source)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.SystemUtils.a(SourceFile:45)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.MinecraftServer.D(MinecraftServer.java:726)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.DedicatedServer.D(DedicatedServer.java:399)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.MinecraftServer.C(MinecraftServer.java:665)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.MinecraftServer.run(MinecraftServer.java:564)
    [20:37:05 WARN]:        at java.lang.Thread.run(Unknown Source)
    [20:37:05 WARN]: java.lang.NullPointerException
    [20:37:05 WARN]:        at me.tmods.serverutils.main.onCommand(main.java:551)
    [20:37:05 WARN]:        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44)
    [20:37:05 WARN]:        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141)
    [20:37:05 WARN]:        at org.bukkit.craftbukkit.v1_9_R2.CraftServer.dispatchCommand(CraftServer.java:645)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.PlayerConnection.handleCommand(PlayerConnection.java:1349)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.PlayerConnection.a(PlayerConnection.java:1184)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.PacketPlayInChat.a(PacketPlayInChat.java:45)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.PacketPlayInChat.a(PacketPlayInChat.java:1)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.PlayerConnectionUtils$1.run(SourceFile:13)
    [20:37:05 WARN]:        at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    [20:37:05 WARN]:        at java.util.concurrent.FutureTask.run(Unknown Source)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.SystemUtils.a(SourceFile:45)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.MinecraftServer.D(MinecraftServer.java:726)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.DedicatedServer.D(DedicatedServer.java:399)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.MinecraftServer.C(MinecraftServer.java:665)
    [20:37:05 WARN]:        at net.minecraft.server.v1_9_R2.MinecraftServer.run(MinecraftServer.java:564)
    [20:37:05 WARN]:        at java.lang.Thread.run(Unknown Source)
    If you want to view my full source code you can go to my GitHub Site
     
    #6 Timo_Ho, May 15, 2016
    Last edited: May 15, 2016