[WIP] New Inventory Managing Plugin(Making an InventoryAPI for serializing)

Discussion in 'WIP and Development Status' started by Brian_Entei, Jun 26, 2013.

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

    Brian_Entei

    InventoryAPI.java's source: https://github.com/br45entei/Enteis...l/br45entei/enteispluginlib/InventoryAPI.java

    Hello, world! I'm posting here today because I am looking for suggestions, comments, advice, etc. on what you, the plugin users, want to see in a good plugin! I Am working on a relatively new project in eclipse called "Entei's Inventory Manager", and, as its name suggests, it will be a plugin that's all about the inventories for servers. It will support the loading and saving of:
    • Per-world inventories(each world has its own inventory)
    • Combined world inventories(world_a and world_c could share an inventory, whilst world_b would be all alone)
    • The players' normal inventory
    • The players' enderchest(can be opened with a command, if the player has permission)
    • Extra double-chest sized inventories per-player(players can be given permission for a command to view and edit these)
    • And lots more to come!
    The plugin is still in development right now, but I hope to have it ready for the public to try out by July 1st, 2013! EDIT: The plugin's page can be found here.
    If you have any thoughts, comments, or want to contribute, feel free to do so!
    I have a gitHub set up here, so you can fork my project and contribute! If your contribution doesn't really fit the theme/goal of this plugin, then I will probably not add it, but don't feel bad, because I might end up using it for something else! Thank you for your time,
     
  2. Offline

    timtower Administrator Administrator Moderator

    Brian_Entei This is an plugin requests forum, not "I am working on it" forum
     
  3. Offline

    drtshock

    Way to not use NMS for saving inventories. Too many of the current virtual inventory plugins use it when it's not needed :3
     
    Brian_Entei likes this.
  4. Offline

    Brian_Entei

    Thanks, I am going for a unique plugin here that is easy to use!

    Could you tell me where I need to go then?
     
  5. Offline

    timtower Administrator Administrator Moderator

  6. Offline

    slayr288

    drtshock
    I found that it's needed to handle names/lore with color. Couldn't find a way around it..
     
  7. Offline

    Brian_Entei

  8. Offline

    timtower Administrator Administrator Moderator

    Don't create an new thread, just report this one with the request for an move, you can't close threads here
     
  9. Offline

    Brian_Entei

    Okay, thanks for the help.

    All you have to do is make a serialization tag for names and lore, and then have the plugin save them to and load them from file! It can't be that hard.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 2, 2016
    timtower likes this.
  10. Offline

    slayr288

    Brian_Entei
    You can't convert a string with color from Minecraft to a normal string that can be stored.
    Well, from what I've tried, that's what I know.
     
  11. Offline

    timtower Administrator Administrator Moderator

  12. Offline

    slayr288

    timtower
    Yes, but then how would you put the color back when loading it?
     
  13. Offline

    timtower Administrator Administrator Moderator

    slayr288 Good point XD, isn't there an way to store them WITH the color codes?
     
  14. Offline

    slayr288

    timtower
    Nope, not to my knowledge.
    That's why I use NMS when saving inventories, it returns a shorter string, and supports everything the item has.
    Including written books, colored names/lore, exc...
    Just needs to be maintained on Minecraft updates.
     
  15. Offline

    TnT

    Moved to a more appropriate forum.
     
    Brian_Entei likes this.
  16. Offline

    drtshock

  17. Offline

    Brian_Entei

    You most definitely can, with this:
    Show Spoiler
    Code:java
    1. public static String convertColorCodes(String str) {return str.replaceAll("(?i)\u00A7b","&b")
    2. .replaceAll("\u00A70","&0")
    3. .replaceAll("\u00A79","&9")
    4. .replaceAll("(?i)\u00A7l","&l")
    5. .replaceAll("\u00A73","&3")
    6. .replaceAll("\u00A71","&1")
    7. .replaceAll("\u00A78","&8")
    8. .replaceAll("\u00A72","&2")
    9. .replaceAll("\u00A75","&5")
    10. .replaceAll("\u00A74","&4")
    11. .replaceAll("\u00A76","&6")
    12. .replaceAll("\u00A77","&7")
    13. .replaceAll("(?i)\u00A7a","&a")
    14. .replaceAll("(?i)\u00A7o","&o")
    15. .replaceAll("(?i)\u00A7d","&d")
    16. .replaceAll("(?i)\u00A7k","&k")
    17. .replaceAll("(?i)\u00A7c","&c")
    18. .replaceAll("(?i)\u00A7m","&m")
    19. .replaceAll("(?i)\u00A7n","&n")
    20. .replaceAll("(?i)\u00A7f","&f")
    21. .replaceAll("(?i)\u00A7e","&e")
    22. .replaceAll("(?i)\u00A7r","&r");}


    And then to load:

    Show Spoiler
    Code:java
    1. public static final ChatColor aqua=ChatColor.AQUA;
    2. public static final ChatColor black=ChatColor.BLACK;
    3. public static final ChatColor blue=ChatColor.BLUE;
    4. public static final ChatColor bold=ChatColor.BOLD;
    5. public static final ChatColor daqua=ChatColor.DARK_AQUA;
    6. public static final ChatColor dblue=ChatColor.DARK_BLUE;
    7. public static final ChatColor dgray=ChatColor.DARK_GRAY;
    8. public static final ChatColor dgreen=ChatColor.DARK_GREEN;
    9. public static final ChatColor dpurple=ChatColor.DARK_PURPLE;
    10. public static final ChatColor dred=ChatColor.DARK_RED;
    11. public static final ChatColor gold=ChatColor.GOLD;
    12. public static final ChatColor gray=ChatColor.GRAY;
    13. public static final ChatColor green=ChatColor.GREEN;
    14. public static final ChatColor italic=ChatColor.ITALIC;
    15. public static final ChatColor lpurple=ChatColor.LIGHT_PURPLE;
    16. public static final ChatColor magic=ChatColor.MAGIC;
    17. public static final ChatColor red=ChatColor.RED;
    18. public static final ChatColor reset=ChatColor.RESET;
    19. public static final ChatColor striken=ChatColor.STRIKETHROUGH;
    20. public static final ChatColor underline=ChatColor.UNDERLINE;
    21. public static final ChatColor white=ChatColor.WHITE;
    22. public static final ChatColor yellow=ChatColor.YELLOW;
    23. public static String formatColorCodes(String str){return str.replaceAll("(?i)&b",aqua+"")
    24. .replaceAll("(?i)&0",black+"")
    25. .replaceAll("(?i)&9",blue+"")
    26. .replaceAll("(?i)&l",bold+"")
    27. .replaceAll("(?i)&3",daqua+"")
    28. .replaceAll("(?i)&1",dblue+"")
    29. .replaceAll("(?i)&8",dgray+"")
    30. .replaceAll("(?i)&2",dgreen+"")
    31. .replaceAll("(?i)&5",dpurple+"")
    32. .replaceAll("(?i)&4",dred+"")
    33. .replaceAll("(?i)&6",gold+"")
    34. .replaceAll("(?i)&7",gray+"")
    35. .replaceAll("(?i)&a",green+"")
    36. .replaceAll("(?i)&o",italic+"")
    37. .replaceAll("(?i)&d",lpurple+"")
    38. .replaceAll("(?i)&k",magic+"")
    39. .replaceAll("(?i)&c",red+"")
    40. .replaceAll("(?i)&m",striken+"")
    41. .replaceAll("(?i)&n",underline+"")
    42. .replaceAll("(?i)&f",white+"")
    43. .replaceAll("(?i)&e",yellow+"")
    44. .replaceAll("(?i)&r",reset+"");}
     
  18. Offline

    slayr288

  19. Offline

    Brian_Entei

    Oh, thanks!
     
  20. Brian_Entei

    What about written books?
     
  21. Offline

    Brian_Entei

    Ahh, something else to figure out! I'll work on that and post it here, thanks for asking.

    Almost done implementing lores and other metadata! I will push the updated code to gitHub.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 2, 2016
  22. Offline

    Brian_Entei

    Okay, so I'm pretty much done and happy with the plugin, so that means I get to release it early!

    Just one question before I release: Should I add in the saving and loading of experience alongside player inventory saving/loading, or go ahead and release and let that be in the next update? I think some people might expect this as a functionality, but I'm not sure...

    @timtower, what do you think?
     

  23. I think you should have that from the start, and make it optional in the plugin.
    Also, did you get the book saving to work?
     
  24. Offline

    Brian_Entei

    Yes, I did. I've even made an api 'class' for this, AND I'm going to go all out and share it with the world:

    UPDATED TO 1.7.4!


    Now serializes/deserializes potion effects, experience, enchanted books, lore, normal books, written books, and more! Check it out:

    EnteisPluginLibrary/Entei'sPluginLibrary/src/com/gmail/br45entei/enteispluginlib/InventoryAPI.java at master · br45entei/EnteisPluginLibrary · GitHub

    I hope everyone who uses this finds it helpful, and gives me at least some credit for my hard work! I will also update this to support saving/loading Experience and Levels the next chance I get!
     

  25. That is beautiful. Kudo's to you, sir.
     
  26. Offline

    Brian_Entei

    Thank you very much! I will be adding more to it as I add more features to my plugin, so don't forget to check back for updates!
     
    Cupcakes69 likes this.

  27. Will do, tag me somewhere here whenever there's a new update. I like it a lot.
    Good luck!
     
  28. Offline

    Brian_Entei


    Here you go, I've added support for saving/loading player experience(and levels!):
    Show Spoiler
    Code:
    package YOUR.PACKAGE.HERE;
     
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
     
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.Material;
    import org.bukkit.enchantments.Enchantment;
    import org.bukkit.entity.Player;
    import org.bukkit.event.inventory.InventoryType;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.BookMeta;
    import org.bukkit.inventory.meta.ItemMeta;
     
    /**This class is a useful tool if you want a simple way to convert any inventory to a String, and vice versa.
     * @author <a href="http://enteisislandsurvival.no-ip.org/about/author.html">Brian_Entei</a>*/
    public class InventoryAPI {
    /**Converts a set of symbols that are used within the serializing functions to prevent data corruption, as well as any ChatColor characters(it changes them to their respective '&' codes). 
    * @param str String
    * @return The given string, with certain symbols changed to keep inventory formatting from getting broken because of a simple character.
    * @see InventoryAPI#convertSymbolsForLoading(String str) */
    public static String convertSymbolsForSaving(String str) {
    str = str.replaceAll(";", "<semi-colon>")
    .replaceAll("#", "<numeral-sign>")
    .replaceAll(":", "<colon>")
    .replaceAll("@", "<at-sign>")
    .replaceAll("\n", "<Nline>")
    .replaceAll("\r", "<Rline>")
    .replaceAll("(?i)\u00A7b","&b")
    .replaceAll("\u00A70","&0")
    .replaceAll("\u00A79","&9")
    .replaceAll("(?i)\u00A7l","&l")
    .replaceAll("\u00A73","&3")
    .replaceAll("\u00A71","&1")
    .replaceAll("\u00A78","&8")
    .replaceAll("\u00A72","&2")
    .replaceAll("\u00A75","&5")
    .replaceAll("\u00A74","&4")
    .replaceAll("\u00A76","&6")
    .replaceAll("\u00A77","&7")
    .replaceAll("(?i)\u00A7a","&a")
    .replaceAll("(?i)\u00A7o","&o")
    .replaceAll("(?i)\u00A7d","&d")
    .replaceAll("(?i)\u00A7k","&k")
    .replaceAll("(?i)\u00A7c","&c")
    .replaceAll("(?i)\u00A7m","&m")
    .replaceAll("(?i)\u00A7n","&n")
    .replaceAll("(?i)\u00A7f","&f")
    .replaceAll("(?i)\u00A7e","&e")
    .replaceAll("(?i)\u00A7r","&r");
    return str;
    }
    /**The opposite function of {@link InventoryAPI#convertSymbolsForSaving(String)}.
    * @param str String
    * @return The given string, restored to its original state.
    * @see {@link InventoryAPI#convertSymbolsForSaving(String str)} */
    public static String convertSymbolsForLoading(String str) {
    str = str.replaceAll("<semi-colon>", ";")
    .replaceAll("<numeral-sign>", "#")
    .replaceAll("<colon>", ":")
    .replaceAll("<at-sign>", "@")
    .replaceAll("<Nline>", "\n")
    .replaceAll("<Rline>", "\r")
    .replaceAll("(?i)&0",ChatColor.BLACK+"")
    .replaceAll("(?i)&9",ChatColor.BLUE+"")
    .replaceAll("(?i)&l",ChatColor.BOLD+"")
    .replaceAll("(?i)&3",ChatColor.DARK_AQUA+"")
    .replaceAll("(?i)&1",ChatColor.DARK_BLUE+"")
    .replaceAll("(?i)&8",ChatColor.DARK_GRAY+"")
    .replaceAll("(?i)&2",ChatColor.DARK_GREEN+"")
    .replaceAll("(?i)&5",ChatColor.DARK_PURPLE+"")
    .replaceAll("(?i)&4",ChatColor.DARK_RED+"")
    .replaceAll("(?i)&6",ChatColor.GOLD+"")
    .replaceAll("(?i)&7",ChatColor.GRAY+"")
    .replaceAll("(?i)&a",ChatColor.GREEN+"")
    .replaceAll("(?i)&o",ChatColor.ITALIC+"")
    .replaceAll("(?i)&d",ChatColor.LIGHT_PURPLE+"")
    .replaceAll("(?i)&k",ChatColor.MAGIC+"")
    .replaceAll("(?i)&c",ChatColor.RED+"")
    .replaceAll("(?i)&m",ChatColor.STRIKETHROUGH+"")
    .replaceAll("(?i)&n",ChatColor.UNDERLINE+"")
    .replaceAll("(?i)&f",ChatColor.WHITE+"")
    .replaceAll("(?i)&e",ChatColor.YELLOW+"")
    .replaceAll("(?i)&r",ChatColor.RESET+"");
    return str;
    }
    /**Serializes the given inventory and converts and saves all data that may be associated with the items within the inventory.<p>
    * <strong>Serialization tags(for easy readability):</strong><br>
    * 0# = The slot number(where 0 is the first slot in the hotbar of a player's inventory)<br>
    * t@ = Item Type(Notice this one is NOT prefixed with a colon)<br>
    * :d@ = Item Durability<br>
    * :a@ = Item Amount<br>
    * :e@ = Item Enchantment Data<br>
    * :l@ = Item Lore Data<br>
    * :n@ = Item Name<br>
    * :b@ = Book Data
    * You can add an additional '@' after a tag to specify additional data if it has the word 'Data' in it's name above.<p>
    * <strong>An example of a player inventory, containing a Stone Pickaxe, with the custom Name "Hello, world!" and some enchantments and lore:</strong><br>
    * <font face="consolas" size="2">36;container.inventory;0#t@274:d@60:e@34@3:e@35@1:e@32@2:n@&3Hello, world!:l@&4The item's Lore, Line One@&2The Item's Lore, Line Two@Etc, &3etc.;</font><br>
    * The "36;" is the size of the inventory(in slots), and the "container.inventory;" is the title of the inventory(That is the default Minecraft title, anything else that you type here will be displayed instead of 'Inventory').<br>
    * Deleting these two stored values will render the whole inventory un-readable, and upon being read from by {@link InventoryAPI#deserializeInventory(String)}, will be returned null.
    * @param inv Inventory
    * @return The given Inventory, serialized into a single-line String.<p>
    * @author <a href="http://enteisislandsurvival.no-ip.org/about/author.html">Brian_Entei</a>
    * @see {@link InventoryAPI#serializeInventory(Player, String)}<br>
    * {@link InventoryAPI#serializeInventory(Player)}<br>
    * {@link InventoryAPI#deserializeInventory(String)}<br>
    * {@link InventoryAPI#deserializeInventory(String, Player)}<br>
    * {@link InventoryAPI#serializeBook(ItemStack)}<br>
    * {@link InventoryAPI#deserializeBook(ItemStack, String[])} */
    public static String serializeInventory(Inventory inv) {
    /**/
    String serialization = inv.getSize() + ";" + inv.getTitle() + ";";
    for(int i = 0; i < inv.getSize(); i++) {
    ItemStack is = inv.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;
    }
    Map<Enchantment,Integer> isEnch = is.getEnchantments();
    if(isEnch.size() > 0) {
    for(Entry<Enchantment,Integer> ench : isEnch.entrySet()) {
    serializedItemStack += ":e@" + ench.getKey().getId() + "@" + ench.getValue();
    }
    }
    if(is.getItemMeta().hasDisplayName()) {
    serializedItemStack += ":n@" + convertSymbolsForSaving(is.getItemMeta().getDisplayName());
    }
    if(is.getItemMeta().hasLore()) {
    Iterator<String> it = is.getItemMeta().getLore().iterator();
    String lores = ":l";
    if(it.hasNext() == false) {
    lores += "@";
    }
    while(it.hasNext()) {
    lores += "@" + convertSymbolsForSaving(it.next());
    }
    serializedItemStack += lores;
    }
    if(is.getType() == Material.BOOK_AND_QUILL || is.getType() == Material.WRITTEN_BOOK) {
    serializedItemStack += serializeBook(is);
    }
    serialization += i + "#" + serializedItemStack + ";";
    }
    }
    return serialization;
    }
    /**This function is the same as {@link InventoryAPI#deserializeInventory(String, Player)}, except for the Player parameter, which is null.
    * @param invString String
    * @return The inventory with no holder, or null, if no string is given.
    * @author <a href="http://enteisislandsurvival.no-ip.org/about/author.html">Brian_Entei</a>
    * @see {@link InventoryAPI#serializeInventory(Inventory)}<br>
    * {@link InventoryAPI#serializeInventory(Player, String)}<br>
    * {@link InventoryAPI#serializeInventory(Player)}<br>
    * {@link InventoryAPI#deserializeInventory(String, Player)}<br>
    * {@link InventoryAPI#serializeBook(ItemStack)}<br>
    * {@link InventoryAPI#deserializeBook(ItemStack, String[])} */
    public static Inventory deserializeInventory(String invString) {return deserializeInventory(invString, null);}
    /**Attempts to return the Inventory of the Player, deserialized from the String parameter. The Inventory that is returned will be owned by the Player.
    * @param invString String
    * @param player Player
    * @return The deserialized inventory with the given player parameter as the holder, or the players' inventory, if no string is given. If neither a string nor a player is given, then this function returns null.
    * @author <a href="http://enteisislandsurvival.no-ip.org/about/author.html">Brian_Entei</a>
    * @see {@link InventoryAPI#serializeInventory(Inventory)}<br>
    * {@link InventoryAPI#serializeInventory(Player, String)}<br>
    * {@link InventoryAPI#serializeInventory(Player)}<br>
    * {@link InventoryAPI#deserializeInventory(String)}<br>
    * {@link InventoryAPI#serializeBook(ItemStack)}<br>
    * {@link InventoryAPI#deserializeBook(ItemStack, String[])} */
    @SuppressWarnings("boxing")
    public static Inventory deserializeInventory(String invString, Player player) {
    if(invString != null) {
    if(invString.equals("") == false) {
    String[] serializedBlocks = invString.split(";");
    //String invInfo = serializedBlocks[0];
    //Inventory deserializedInventory = Bukkit.getServer().createInventory(player, invType);
    //Inventory deserializedInventory = Bukkit.getServer().createInventory(player, Integer.valueOf(invInfo));
    Inventory deserializedInventory = Bukkit.getServer().createInventory(player, Integer.valueOf(serializedBlocks[0]), String.valueOf(serializedBlocks[1]));
    //for(int i = 1; i < serializedBlocks.length; i++) {
    for(int i = 2; 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;
    }
    if(createdItemStack) {
    if(itemAttribute[0].equals("d")) {
    is.setDurability(Short.valueOf(itemAttribute[1]));
    } else if(itemAttribute[0].equals("a")) {
    is.setAmount(Integer.valueOf(itemAttribute[1]));
    } else if(itemAttribute[0].equals("n")) {
    ItemMeta meta = null;
    if(is.getItemMeta() == null) {
    meta = Bukkit.getServer().getItemFactory().getItemMeta(is.getType());
    } else {
    meta = is.getItemMeta();
    }
    meta.setDisplayName(convertSymbolsForLoading(itemAttribute[1]));
    is.setItemMeta(meta);
    } else if(itemAttribute[0].equals("e")) {
    is.addUnsafeEnchantment(Enchantment.getById(Integer.valueOf(itemAttribute[1])), Integer.valueOf(itemAttribute[2]));
    } else if(itemAttribute[0].equals("l")) {
    ArrayList<String> lores = new ArrayList<String>();
    for(int j = 1; j < itemAttribute.length; j++) {
    lores.add(convertSymbolsForLoading(itemAttribute[j]));
    }
    ItemMeta meta = null;
    if(is.getItemMeta() == null) {
    meta = Bukkit.getServer().getItemFactory().getItemMeta(is.getType());
    } else {
    meta = is.getItemMeta();
    }
    meta.setLore(lores);
    is.setItemMeta(meta);
    } else if(itemAttribute[0].equals("b")) {
    is = deserializeBook(is, itemAttribute);
    }
    }
    }
    deserializedInventory.setItem(stackPosition, is);
    }
    return deserializedInventory;
    } else if(player != null) {
    return player.getInventory();
    /*}
    } else {
    return null;
    }
    return Bukkit.getServer().createInventory(null, InventoryType.PLAYER);
    }*/
    } else {
    return null;
    }
    }
    return null;
    }
    /**With this function allows you to easily choose what Inventory is to be used from the given Player in the function {@link InventoryAPI#serializeInventory(Inventory)}, and have it returned all in the same function.
    * <br>With the parameter invToConvert, you can specify either "inventory", "armor", or "enderchest", and the function will return the serialized inventory of the type that you specified.
    * @param player Player
    * @param invToConvert String
    * @return The serialized inventory as a single-line String. If the Player parameter is null, then a blank String is returned. If the String parameter is null, or isn't one of the options listed, the player's default inventory is returned, serialized as a single-line String. If both the Player and the String parameters are null, a blank String is returned.
    * @author <a href="http://enteisislandsurvival.no-ip.org/about/author.html">Brian_Entei</a>
    * @see {@link InventoryAPI#serializeInventory(Inventory)}<br>
    * {@link InventoryAPI#serializeInventory(Player)}<br>
    * {@link InventoryAPI#deserializeInventory(String)}<br>
    * {@link InventoryAPI#deserializeInventory(String, Player)}<br>
    * {@link InventoryAPI#serializeBook(ItemStack)}<br>
    * {@link InventoryAPI#deserializeBook(ItemStack, String[])} */
    public static String serializeInventory(Player player, String invToConvert) {
    if(player != null) {
    Inventory invInventory = Bukkit.getServer().createInventory(player, InventoryType.PLAYER);
    if(invToConvert != null) {
    if(invToConvert.equalsIgnoreCase("inventory")) {
    invInventory = player.getInventory();
    } else if(invToConvert.equalsIgnoreCase("armor")) {
    Inventory newInv = Bukkit.getServer().createInventory(player, 9);
    //newInv.setContents(player.getInventory().getArmorContents());
    int num = 0;
    for(ItemStack curItem : player.getInventory().getArmorContents()) {
    newInv.setItem(num, curItem);num++;
    }
    invInventory = newInv;
    } else if(invToConvert.equalsIgnoreCase("enderchest")) {
    invInventory = player.getEnderChest();
    } else {
    invInventory = player.getInventory();
    }
    } else {
    invInventory = player.getInventory();
    }
    return serializeInventory(invInventory);
    }
    return "";
    }
    /**Attempts to return the given Player's default Inventory, serialized as a single-line String. Uses {@link InventoryAPI#serializeInventory(Inventory)} for serialization.
    * @param player Player
    * @author <a href="http://enteisislandsurvival.no-ip.org/about/author.html">Brian_Entei</a>
    * @return The player's default Inventory, serialized as a single-line String. If the player is null, a blank string is returned.
    * @see {@link InventoryAPI#serializeInventory(Inventory)}<br>
    * {@link InventoryAPI#serializeInventory(Player, String)}<br>
    * {@link InventoryAPI#deserializeInventory(String)}<br>
    * {@link InventoryAPI#deserializeInventory(String, Player)}<br>
    * {@link InventoryAPI#serializeBook(ItemStack)}<br>
    * {@link InventoryAPI#deserializeBook(ItemStack, String[])} */
    public static String serializeInventory(Player player) {return serializeInventory(player, null);}
    /**Attempts to serialize the given ItemStack and return it as a single-line String. If the ItemStack provided is not a Book and Quill or a Written Book, this function will return a blank string.
    * @param item ItemStack
    * @return The given ItemStack in a serialized single-line String if it is a Book and Quill or a Written Book. Otherwise, a blank string is returned.
    * @author <a href="http://enteisislandsurvival.no-ip.org/about/author.html">Brian_Entei</a>
    * @see {@link InventoryAPI#deserializeBook(ItemStack, String[])}<br>
    * {@link InventoryAPI#serializeInventory(Inventory)}<br>
    * {@link InventoryAPI#serializeInventory(Player, String)}<br>
    * {@link InventoryAPI#serializeInventory(Player)}<br>
    * {@link InventoryAPI#deserializeInventory(String)}<br>
    * {@link InventoryAPI#deserializeInventory(String, Player)} */
    public static String serializeBook(ItemStack item) {
    String rtrn = ":b@";
    BookMeta meta;
    if(item.getType() == Material.BOOK_AND_QUILL || item.getType() == Material.WRITTEN_BOOK) {
    meta = (BookMeta) item.getItemMeta();
    String author = (meta.hasAuthor() ? meta.getAuthor() : null);
    String title = (meta.hasTitle() ? meta.getTitle() : null);
    if(author != null) {
    rtrn += convertSymbolsForSaving(author);
    } else {
    rtrn += "<NO-AUTHOR>";
    }
    if(title != null) {
    rtrn += "@" + convertSymbolsForSaving(meta.getTitle());
    } else {
    rtrn += "@<NO-TITLE>";
    }
    if(meta.hasPages()) {
    List<String> pages = meta.getPages();
    for(String curPage : pages) {
    rtrn += "@" + convertSymbolsForSaving(curPage);//The start of the pages will be itemAttribute[3] and up.
    }
    }
    }
    return (rtrn.equals(":b@") ? "" : rtrn);
    }
    /**Attempts to deserialize the BookMeta data from the String[] parameter and add it to the given ItemStack, which is then returned. If no ItemStack is given, a Written Book is generated in its place, and the BookMeta assigned. If no String[] parameter is given, then this function will return the given ItemStack, or a blank Book and Quill if no ItemStack was given either. 
    * @param item ItemStack
    * @param itemAttribute String[]
    * @return The deserialized Book, with all of its previous BookMeta intact. If the String[] parameter is null, then this will return the given ItemStack.
    * @author <a href="http://enteisislandsurvival.no-ip.org/about/author.html">Brian_Entei</a>
    * @see {@link InventoryAPI#serializeBook(ItemStack)}<br>
    * {@link InventoryAPI#serializeInventory(Inventory)}<br>
    * {@link InventoryAPI#serializeInventory(Player, String)}<br>
    * {@link InventoryAPI#serializeInventory(Player)}<br>
    * {@link InventoryAPI#deserializeInventory(String)}<br>
    * {@link InventoryAPI#deserializeInventory(String, Player)} */
    public static ItemStack deserializeBook(ItemStack item, String[] itemAttribute) {
    if(item == null && itemAttribute == null) {return new ItemStack(Material.BOOK_AND_QUILL);}
    if(item == null) {item = new ItemStack(Material.WRITTEN_BOOK);}
    if(itemAttribute == null) {return item;}
    if(item.getType() == Material.BOOK_AND_QUILL || item.getType() == Material.WRITTEN_BOOK) {
    BookMeta meta = (BookMeta) (item.hasItemMeta() ? item.getItemMeta() : Bukkit.getServer().getItemFactory().getItemMeta(item.getType()));
    String author = itemAttribute[1];
    String title = itemAttribute[2];
    if(author != null) {
    meta.setAuthor((author.equals("<NO-AUTHOR>") == false ? convertSymbolsForLoading(author) : null));
    } else {
    item.setItemMeta(meta);
    return item;
    }
    if(title != null) {
    meta.setTitle((title.equals("<NO-TITLE>") == false ? convertSymbolsForLoading(title) : null));
    } else {
    item.setItemMeta(meta);
    return item;
    }
    for(int i = 3; i < itemAttribute.length;) {
    if(itemAttribute[i] != null) {
    meta.addPage(convertSymbolsForLoading(itemAttribute[i]));
    }
    i++;
    }
    item.setItemMeta(meta);
    }
    return item;
    }
    /**Example usage: inv = setTitle("Hello, world!", inv);
    * @param str String
    * @param inv Inventory
    * @return The inv parameter with the new title.
    * @author <a href="http://enteisislandsurvival.no-ip.org/about/author.html">Brian_Entei</a> */
    public static Inventory setTitle(String str, Inventory inv) {
    Inventory newInv = Bukkit.getServer().createInventory(inv.getHolder(), inv.getSize(), str);
    newInv.setContents(inv.getContents());
    newInv.setMaxStackSize(inv.getMaxStackSize());//In case some of you out there need this to do this.
    return newInv;
    }
    /**Attempts to return the given experience and level serialized, as a single-line String.
    * @param level Integer
    * @param exp float
    * @return The serialized result, or a blank string if the given parameters somehow had no value.
    * @see {@link InventoryAPI#serializeExperience(Player)}<br>
    * {@link InventoryAPI#deserializeExperience(String)}<br>
    * {@link InventoryAPI#deserializeExp(String)}<br>
    * {@link InventoryAPI#deserializeLevel(String)} */
    public static String serializeExperience(int level, float exp) {
    String rtrn = "x@";
    rtrn += level + "@" + exp;
    return (rtrn.equals("x@") ? "" : (rtrn.equals("x@@") ? "" : rtrn));
    }
    /**Attempts to serialize the level and experience of the given Player as a single-line String.<br>
    * This function uses {@link InventoryAPI#serializeExperience(int, float)} for deserialization.
    * @param player Player
    * @return The serialized form of the given Player's experience and level.
    * @author <a href="http://enteisislandsurvival.no-ip.org/about/author.html">Brian_Entei</a>
    * @see {@link InventoryAPI#serializeExperience(int, float)}<br>
    * {@link InventoryAPI#deserializeExperience(String)}<br>
    * {@link InventoryAPI#deserializeExp(String)}<br>
    * {@link InventoryAPI#deserializeLevel(String)}*/
    public static String serializeExperience(Player player) {return serializeExperience(player.getLevel(), player.getExp());}
    /**Attempts to return a String[] array containing the Integer level and the float experience, deserialized from the String parameter.
    * @param serializedExp String
    * @return A String[] array containing the Integer level and the float experience, deserialized from the String parameter. May return values that are not an Integer or a float in the String[] array, so it is recommended to either check the result of this function or use one(or both) of the following functions instead:<br>{@link InventoryAPI#deserializeExp(String)}<br>{@link InventoryAPI#deserializeLevel(String)}
    * @author <a href="http://enteisislandsurvival.no-ip.org/about/author.html">Brian_Entei</a>
    * @see {@link InventoryAPI#deserializeExp(String)}<br>
    * {@link InventoryAPI#deserializeLevel(String)}<br>
    * {@link InventoryAPI#serializeExperience(int, float)}<br>
    * {@link InventoryAPI#serializeExperience(Player)} */
    public static String[] deserializeExperience(String serializedExp) {return serializedExp.replace("x@", "").split("@");}
    /**Attempts to return the int value of the deserialized level.<br>
    * This function uses {@link InventoryAPI#deserializeExperience(String)} for deserialization.
    * @param serializedExp String
    * @return The int value of the deserialized level, or 0 if the deserialization did not return a valid Integer.
    * @author <a href="http://enteisislandsurvival.no-ip.org/about/author.html">Brian_Entei</a>
    * @see {@link InventoryAPI#deserializeExperience(String)}
    * {@link InventoryAPI#deserializeExp(String)}
    * {@link InventoryAPI#serializeExperience(int, float)}
    * {@link InventoryAPI#serializeExperience(Player)} */
    public static int deserializeLevel(String serializedExp) {
    int rtrn = 0;
    int num = 0;
    for(String curNum : deserializeExperience(serializedExp)) {
    num++;
    boolean isInt = true;
    if(num == 1) {
    try{Integer.parseInt(curNum);
    } catch (NumberFormatException e) {
    isInt = false;
    }
    if(isInt) {
    rtrn = Integer.parseInt(curNum);
    }
    }
    }
    return rtrn;
    }
    /**Attempts to return the float value of the deserialized experience.<br>
    * This function uses {@link InventoryAPI#deserializeExperience(String)} for deserialization.
    * @param serializedExp String
    * @return The float value of the deserialized experience, or 0 if the deserialization did not return a valid float.
    * @author <a href="http://enteisislandsurvival.no-ip.org/about/author.html">Brian_Entei</a>
    * @see {@link InventoryAPI#deserializeExperience(String)}<br>
    * {@link InventoryAPI#deserializeLevel(String)}<br>
    * {@link InventoryAPI#serializeExperience(int, float)}<br>
    * {@link InventoryAPI#serializeExperience(Player)} */
    public static float deserializeExp(String serializedExp) {
    float rtrn = 0;
    int num = 0;
    for(String curNum : deserializeExperience(serializedExp)) {
    num++;
    boolean isFloat = true;
    if(num == 2) {
    try{Float.parseFloat(curNum);
    } catch (NumberFormatException e) {
    isFloat = false;
    }
    if(isFloat) {
    rtrn = Float.parseFloat(curNum);
    }
    }
    }
    return rtrn;
    }
    }


    I have also updated a couple of the other functions to fix some minor issues.
    Also, if anyone else would like me to
    Code:
    @tahg
    them whenever I have an update, feel free to say so!

    Oh, also, if anyone would like to contribute to this api, feel free to post your suggested code in a spoiler in a reply here! I will gladly look it over and see if it is worth adding(not that it isn't cool if I don't)!

    Cupcakes69
    Do you think I should include some basic file-based functions in the InventoryAPI, like WriteToFile() and ReadFile()?

    Also, I think I will make the plugin have an option to save and load players' inventories by gamemode, so that there would be a saved survival inventory, a saved creative inventory, and a saved adventure inventory, all for world_a. Then you could turn that feature on or off in the config. Sound good?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 2, 2016
    Cupcakes69 likes this.

  29. I think the file-based functions aren't necessary.
    The mode thing is a really good idea though!
     
  30. Offline

    Brian_Entei

    Okay, cool, I'll add that in to the plugin, and try to get the BukkitDev page set up for it. Then I'll post the link here.

    Cupcakes69
    Here is the BukkitDev page for the plugin(It's not approved of yet):
    http://dev.bukkit.org/bukkit-plugins/enteis-inventory-manager/

    Don't forget that I have the source for this plugin and the InventoryAPI here. You could build the project up in Eclipse, if you wanted to, but you'd need my EnteisPluginLibrary to compile it.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 2, 2016
    Cupcakes69 likes this.
Thread Status:
Not open for further replies.

Share This Page