Serialize Inventory to single string and vice versa

Discussion in 'Resources' started by Phil2812, Aug 9, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    Comphenix

    It's a good idea to look up the source code in these cases, and it appears that
    asNMSCopy() returns NULL if the item stack contains AIR (like the armor slots in your case).

    So - you should be able to fix this by checking that the return type of asNMSCopy() is not NULL as well.
     
  2. Offline

    Toni


    if((craft != null) || (CraftItemStack.asNMSCopy(itemStack) != null))

    Sorry if I'm mistaken on doing this, but I figured this would be able to check if asNMSCopy() is not null and then if it isn't, continue to save the object. However I'm still receiving an NPE, am I doing something wrong?
     
  3. Offline

    Comphenix

    Hm - in the if-statement itself? Or inside the CraftItemStack.asNMSCopy() method?

    Perhaps you could post your stack trace.
     
  4. Offline

    Toni

  5. Offline

    Comphenix

    You should use "&&" (short-circuit and) instead of "||" in this if-statement. In addition, it's probably best to only execute asNMSCopy() once.

    But if you're trying to serialize a player inventory, you'll probably need more than just the armor content. What about the held item index and player name? With some, err, heavy modifications, you can add that information to the output format (only supports 1.7.9):
    https://gist.github.com/aadnk/11343062

    Which would allow you to do the following:
    Code:java
    1. String serialized = ItemSerialization.toBase64(((Player) sender).getInventory());
    2. System.out.println(serialized);
    3.  
    4. Inventory inventory = ItemSerialization.fromBase64(serialized);
    5. System.out.println(
    6. "Armor: " + Arrays.asList(((PlayerInventory) inventory).getArmorContents())
    7. );
     
    Toni likes this.
  6. Offline

    Toni


    I give u all my money with love <3 Thank you so much. This is so much more I can't even thank you enough!

    Quick edit:

    I see you said it works for 1.7.9 only :/ I'm still waiting on 1.7.5 before I update to 1.7.9 until I'm finished preparing for the UUID updates. Is there anyway things inside the serialization class such as the NBTReadLimiter to be excluded unless it's mandatory for it to function?
     
  7. Offline

    Comphenix

    You could simply remove it:
    Code:java
    1. private static NBTBase readNbt(DataInput input, int level) {
    2. if (READ_NBT == null) {
    3. try {
    4. // NBTReadLimiter is new in 1.7.9
    5. READ_NBT = NBTCompressedStreamTools.class.getDeclaredMethod("a", DataInput.class, int.class);
    6. READ_NBT.setAccessible(true);
    7. } catch (Exception e) {
    8. throw new IllegalStateException("Unable to find private read method.", e);
    9. }
    10. }
    11.  
    12. try {
    13. return (NBTBase) READ_NBT.invoke(null, input, level);
    14. } catch (Exception e) {
    15. throw new IllegalArgumentException("Unable to read from " + input, e);
    16. }
    17. }

    That should work with 1.7.5, if you also remember to update the package version.
     
  8. Offline

    Toni


    https://gist.github.com/ToniTang/11379a6f016af56c1ad1

    So those are my current classes - however when I try to give myself a kit I get the stacktrace reported in that gist. Would you have any ideas?
     
  9. Offline

    Comphenix

    Ah, yeah, I forgot to restrict the size of getContents():
    Code:java
    1. @Override
    2. public ItemStack[] getContents() {
    3. return Arrays.copyOf(super.getContents(), getSize());
    4. }

    Seeing how I store both the inventory content and the armor in a slightly larger custom inventory (which is similar to how PlayerInventory is actually implemented in Minecraft).

    I've updated my Gist with this method.
     
    Toni likes this.
  10. Offline

    Toni


    Thank you so much for your help. Saving inventories and loading them again (including armor!) works flawlessly, color, lore, etc, everything is included. I'm so happy :D and this is 1.7.9 ready so when I do update I'll still have this working *tears* thank you so much again.
     
    Comphenix likes this.
  11. Offline

    TeamJesus

    @Comphenix i've been looking for something like this to save users inv to a file... since i am learning all of this, how would i use this and an example to save and then load at my leasure?
    i already know how to replace the inv.. just saving it and loading it with this... is wherei be stucks
    Thank you for any help :)
     
  12. Offline

    Scullyking

    Is there an easy way of adding items to a serialised inventory. I basically want to add items when a player is offline!
     
  13. Offline

    DarkBladee12

    Scullyking Deserialise it, then add the items and serialise it again. I don't think there's another way to do that.
     
  14. Offline

    Scullyking

  15. Offline

    Pr07o7yp3

    I'm not sure where is my mistake.
    I get this error:

    On line 308 I have:
    Code:java
    1. Arrays.asList(((PlayerInventory) inventory).getArmorContents());
     
  16. Offline

    Comphenix

    I think you've imported the wrong PlayerInventory. It should be org.bukkit.inventory.PlayerInventory, not NMS.inventory:
    Code:java
    1. import org.bukkit.inventory.PlayerInventory;
     
    Pr07o7yp3 likes this.
  17. Offline

    Pr07o7yp3

    Yup, I'm so stupid... That was the probem. Ty :)
    I have to look more carefully when Eclipse ask me what to import.
     
    Comphenix likes this.
  18. Offline

    Subtelny

    I added saving name item and lore ;)

    Code:
    
    import java.util.ArrayList;
    import java.util.Map;
    import java.util.Map.Entry;
    
    import org.bukkit.Bukkit;
    import org.bukkit.Material;
    import org.bukkit.enchantments.Enchantment;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.ItemMeta;
    
    public class ParkourInv {
    
       public static String InventoryToString(Inventory invInventory) {
         String serialization = invInventory.getSize() + ";";
         for (int i = 0; i < invInventory.getSize(); i++) {
           ItemStack is = invInventory.getItem(i);
           if (is != null) {
             String serializedItemStack = new String();
    
             String isType = String.valueOf(is.getType().getId());
             serializedItemStack += "t@" + isType;
    
             if (is.getDurability() != 0) {
               String isDurability = String.valueOf(is.getDurability());
               serializedItemStack += ":d@" + isDurability;
             }
    
             if (is.getAmount() != 1) {
               String isAmount = String.valueOf(is.getAmount());
               serializedItemStack += ":a@" + isAmount;
             }
    
             if (is.hasItemMeta()) {
               String isMeta = String.valueOf(is.getItemMeta()
                   .getDisplayName());
               serializedItemStack += ":m@" + isMeta;
             }
    
             if (is.hasItemMeta()) {
               String isLore = String.valueOf(is.getItemMeta().getLore());
               if (!(isLore == null)) {
                 serializedItemStack += ":l@" + isLore;
               }
             }
    
             Map<Enchantment, Integer> isEnch = is.getEnchantments();
             if (isEnch.size() > 0) {
               for (Entry<Enchantment, Integer> ench : isEnch.entrySet()) {
                 serializedItemStack += ":e@" + ench.getKey().getId()
                     + "@" + ench.getValue();
               }
             }
    
             serialization += i + "#" + serializedItemStack + ";";
           }
         }
         return serialization;
       }
    
       public static Inventory StringToInventory(String invString) {
         String[] serializedBlocks = invString.split(";");
         String invInfo = serializedBlocks[0];
         Inventory deserializedInventory = Bukkit.getServer().createInventory(
             null, Integer.valueOf(invInfo));
    
         for (int i = 1; i < serializedBlocks.length; i++) {
           String[] serializedBlock = serializedBlocks[i].split("#");
           int stackPosition = Integer.valueOf(serializedBlock[0]);
    
           if (stackPosition >= deserializedInventory.getSize()) {
             continue;
           }
    
           ItemStack is = null;
           Boolean createdItemStack = false;
    
           String[] serializedItemStack = serializedBlock[1].split(":");
           for (String itemInfo : serializedItemStack) {
             String[] itemAttribute = itemInfo.split("@");
             if (itemAttribute[0].equals("t")) {
               is = new ItemStack(Material.getMaterial(Integer
                   .valueOf(itemAttribute[1])));
               createdItemStack = true;
             } else if (itemAttribute[0].equals("d") && createdItemStack) {
               is.setDurability(Short.valueOf(itemAttribute[1]));
             } else if (itemAttribute[0].equals("a") && createdItemStack) {
               is.setAmount(Integer.valueOf(itemAttribute[1]));
             } else if (itemAttribute[0].equals("m") && createdItemStack) {
               ItemMeta isM = is.getItemMeta();
               isM.setDisplayName(itemAttribute[1]);
               is.setItemMeta(isM);
             } else if (itemAttribute[0].equals("l") && createdItemStack) {
               ItemMeta isM = is.getItemMeta();
               String removeBuckle = itemAttribute[1].substring(1,
                   itemAttribute[1].length() - 1);
               ArrayList<String> l = new ArrayList<String>();
               for (String podpis : removeBuckle.split(", ")) {
                 l.add(podpis);
               }
               isM.setLore(l);
               is.setItemMeta(isM);
             } else if (itemAttribute[0].equals("e") && createdItemStack) {
               is.addEnchantment(Enchantment.getById(Integer
                   .valueOf(itemAttribute[1])), Integer
                   .valueOf(itemAttribute[2]));
             }
           }
           deserializedInventory.setItem(stackPosition, is);
         }
    
         return deserializedInventory;
       }
    
    }
    
    
     
  19. Offline

    eyamaz

    <insert something witty about necromancy and thread locking>
     
Thread Status:
Not open for further replies.

Share This Page