How to save ItemStack-Arra permanently?

Discussion in 'Plugin Development' started by Johnny_JayJay, Dec 18, 2017.

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

    Johnny_JayJay

    Hi there,

    I just started to get into plugin development last week, so I'm quite new and I still don't get some things.
    Currently I am working on a duel plugin which gives the player a few kits to choose from. I already know how to use variables to temporarily save inventory contents, but there must be a way to save my kits permanently. So I'm wondering how and I would appreciate your help.
    I tried using the config, and it does save everything but an ItemStack[].
    Code:
    kitNormal = p.getInventory().getContents();
                   Main.getInstance().getConfig().set("Duel.Kits.Normal", kitNormal);
                   Main.getInstance().saveConfig();
    Thanks
    Johnny

    //edit: the title is supposed to be saying "ItemStack-Arrays"
     
  2. Offline

    DelfikPro

  3. Offline

    AdamDev

    @Johnny_JayJay
    Just going to say that saving the ItemStack[] is going to work even though it doesn't say it.

    If you really don't want to save the ItemStack array, just for loop through the array with a integer that equals to 0. Then make a ItemStack variable that is set to getting the ItemStack of the integer variable

    I'll give an example since your new.

    - Make a for loop with "int i = 0;i<contents;i++"
    - Then make the ItemStack
    "ItemStack is = contents // i think it's this im not sure atm"
    - I do suggest saving the item name and then getting the value of it to turn it back into a ItemStack

    There you have two ways of doing it.

    Hope this helps,
    ~ AdamDev
     
  4. Offline

    Johnny_JayJay

    @AdamDev
    Yeah, it does save something, but I can't get it back as an ItemStack[]

    Well, I just tried it like that:
    Code:
    kitNormal = p.getInventory().getContents();
    for (int i = 0; i < kitNormal.length; i++) {
            is = kitNormal[i]; // is is declared
            // at this point I also tried it without "new ItemStack()", but it wouldn't work as well
            Main.getInstance().getConfig().set("Duel.Kits.Normal." + i + ".", new ItemStack(is));
    }
    Main.getInstance().saveConfig();
    
    So I get this error:
    Error Code (open)

    1. null
    2. org.bukkit.command.CommandException: Unhandled exception executing command 'duel' in plugin FancyDuels v1.0
    3. at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    4. at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141) ~[spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    5. at org.bukkit.craftbukkit.v1_8_R3.CraftServer.dispatchCommand(CraftServer.java:641) ~[spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    6. at net.minecraft.server.v1_8_R3.PlayerConnection.handleCommand(PlayerConnection.java:1162) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    7. at net.minecraft.server.v1_8_R3.PlayerConnection.a(PlayerConnection.java:997) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    8. at net.minecraft.server.v1_8_R3.PacketPlayInChat.a(PacketPlayInChat.java:45) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    9. at net.minecraft.server.v1_8_R3.PacketPlayInChat.a(PacketPlayInChat.java:1) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    10. at net.minecraft.server.v1_8_R3.PlayerConnectionUtils$1.run(SourceFile:13) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    11. at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_144]
    12. at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_144]
    13. at net.minecraft.server.v1_8_R3.SystemUtils.a(SourceFile:44) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    14. at net.minecraft.server.v1_8_R3.MinecraftServer.B(MinecraftServer.java:715) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    15. at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:374) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    16. at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:654) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    17. at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:557) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    18. at java.lang.Thread.run(Unknown Source) [?:1.8.0_144]
    19. Caused by: java.lang.IllegalArgumentException: Cannot set to an empty path
    20. at org.apache.commons.lang.Validate.notEmpty(Validate.java:321) ~[spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    21. at org.bukkit.configuration.MemorySection.set(MemorySection.java:163) ~[spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    22. at org.bukkit.configuration.MemorySection.set(MemorySection.java:193) ~[spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    23. at johnny.fancyduels.command.DuelCommand.onCommand(DuelCommand.java:204) ~[?:?]
    24. at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
    25. ... 15 more

    Thank you for helping though! @AdamDev @DelfikPro
    //edit: well, I guess If found my fault. In the part
    Main.getInstance().getConfig().set("Duel.Kits.Normal." + i + ".", new ItemStack(is));
    the last "." is wrong and shoudn't be there.
     
    Last edited: Dec 19, 2017
  5. Offline

    AdamDev

  6. Offline

    Johnny_JayJay

    @AdamDev
    No, saving inventory contents in the config now works perfectly fine. But you can still help, since I'm now trying to get it back, I mean to load saved inventories.
    I'm still a bit confused concerning ArrayList, turning them into Arrays and getting multiple values from a config. Because I didn't quite get the solution in the thread @DelfikPro posted (and it also doesn't seem to work). I tried it like that:
    Code:java
    1.  
    2. ArrayList<ItemStack> kits = new ArrayList<>();
    3. ItemStack is;
    4.  
    5. for (int i = 0; i < Main.getInstance().getConfig().getList("Duel.Kits.Normal")
    6. .size(); i++) {
    7. is = Main.getInstance().getConfig().getItemStack("Duel.Kits.Normal." + i);
    8. kits.add(is);
    9. }
    10.  
    11. ItemStack[] kit = new ItemStack[kits.size()];
    12. kit = kits.toArray(kit);
    13.  

    So, my plan here was to get the amount of ItemStacks I need to for loop through, add each one to an ArrayList which I later turn into an ItemStackArray. But
    "i < Main.getInstance().getConfig().getList("Duel.Kits.Normal").size()" doesn't work, it throws an error. So I wonder how to get the amount of ItemStacks I saved in my config.

    As I already said, saving inventories works, and again I appreciate your help.
     
    Last edited by a moderator: Dec 20, 2017
  7. Offline

    AdamDev

    @Johnny_JayJay

    Ok, I do see a problem here.

    Now your for-loop is currently wrong with what you're using. Change it from searching through the list to searching it through the configuration section. If you don't know I'll show you:

    Don't click me if you don't want to see (open)

    Code:
    for (String isconfig : getConfig().getConfigurationSection("section").getKeys(false)) {
        // Do stuff
    }
    
     
  8. Offline

    Johnny_JayJay

    Sorry, but I don't get what the for loop does exactly, most likely what "getConfig().getConfigurationSection("...").getKeys(false)" does. It obviously gives back an Array, but why a String[]? Because in my section "Duel.Kits.Normal" for example there are Integers, and then ItemStacks. So, what can I do with this String? And what does getKeys(false) do?
    Still trying to learn how this stuff works ^^ Anyway, thanks
     
  9. Offline

    timtower Administrator Administrator Moderator

    @Johnny_JayJay getConfig().getConfigurationSection("section").getKeys(false) returns a Set<String>, not an array.
    It returns all the keys that are in section, so if your config looks like this:
    Code:
    section:
      key1: value1
      key2: value2
    Then it will return a set with length 2:
    • key1
    • key2
    So this doesn't contain the value, for that you need to do getConfig().getString("section."+keyfromset)
     
  10. Offline

    Johnny_JayJay

    @AdamDev @timtower
    I tried it like that, and for some reason I am at the same point as I was before using getConfig().getIntegerList(...).size().
    Yes, it loads the saved inventory. But there still is a problem, and I seriously don't know why. I do get the items I set in the config before. But they all look like in the picture below and disappear when I try to use them. As I said, I already was at this point without using getConfigurationSection(), which surprises me.
    Well I'd say that it has something to do with the ItemMeta that wasn't transferred correctly or something like that, but the enchantments for example are visible, so I seriously don't know.
    Maybe I made a fault turning the ArrayList I added all Items to into an Array?
    Code:java
    1.  
    2. ItemStack[] kit = new ItemStack[kits.size()];
    3. kit = kits.toArray(kit);
    4.  
     

    Attached Files:

  11. Offline

    timtower Administrator Administrator Moderator

  12. Offline

    Johnny_JayJay

    @timtower
    Then why is that? And if it's empty, why do I still get the sword with all its enchantments? My config isn't empty and I did as you recommended:
    Code:java
    1.  
    2. ArrayList<ItemStack> kits = new ArrayList<>();
    3. for (String isConfig : Main.getInstance().getConfig()
    4. .getConfigurationSection("Duel.Kits.Normal").getKeys(false)) {
    5. kits.add(Main.getInstance().getConfig().getItemStack("Duel.Kits.Normal." + isConfig));
    6. }
    7.  
    8. ItemStack[] kit = new ItemStack[kits.size()];
    9. kit = kits.toArray(kit);
    10. player.getInventory().setContents(kit);
    11.  

    Config:
    Show Spoiler

    Duel:
    Kits:
    Normal:
    '0':
    ==: org.bukkit.inventory.ItemStack
    type: IRON_SWORD
    meta:
    ==: ItemMeta
    meta-type: UNSPECIFIC
    enchants:
    DAMAGE_ALL: 3


    I also tried it as an own class, just isolated from all the other stuff. Doesn't work either:
    Show Spoiler

    Code:java
    1.  
    2. public class Test implements CommandExecutor {
    3.  
    4. @Override
    5. public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
    6. Player p = (Player) sender;
    7. if (args[0].equalsIgnoreCase("save")) {
    8. int pos = 0;
    9. for (ItemStack is : p.getInventory().getContents()) {
    10. Main.getInstance().getConfig().set("Test." + pos, is);
    11. pos++;
    12. }
    13. Main.getInstance().saveConfig();
    14. p.sendMessage("§aSuccess - Saved");
    15. } else if (args[0].equalsIgnoreCase("load")) {
    16. ArrayList<ItemStack> invContents = new ArrayList<>();
    17. for (String isConfig : Main.getInstance().getConfig().getConfigurationSection("Test").getKeys(false)) {
    18. invContents.add(Main.getInstance().getConfig().getItemStack("Test." + isConfig));
    19. }
    20. ItemStack[] content = new ItemStack[invContents.size()];
    21. content = invContents.toArray(content);
    22. p.getInventory().setContents(content);
    23. p.sendMessage("§aSuccess - Loaded");
    24. }
    25. return false;
    26. }
    27. }
    28.  

     
  13. Offline

    timtower Administrator Administrator Moderator

    @Johnny_JayJay Looked over something in your code, missed it.
    Should work I think.
     
  14. Offline

    Johnny_JayJay

    Okay, that's weird. To be honest, I thought this wasn't such a complex topic. Could it be that the problem is connected to the version I use (1.8.9)?
    Otherwise, isn't it conventional using configs to save inventories? Or is there another way?
     
  15. Offline

    timtower Administrator Administrator Moderator

  16. Offline

    Johnny_JayJay

    Well, I still don't know what it does, so I can't give you an accurate answer. I'd say keys are the things that stand right before the value. If that's true, all of my keys are integers, naming the slot the ItemStack is in. In my config above, it'd be '0' then. But as I said, I can't tell unless I know more about keys. Sorry, but I'm still new. Thanks.
     
  17. Offline

    timtower Administrator Administrator Moderator

    @Johnny_JayJay Keys are the things before the colon in the yml files.
    Just print them all.
     
  18. Offline

    Johnny_JayJay

    Okay. Using the command I posted before saves the inventory in the picture below with the following keys:
    Code:
    Test:
      '8':
    Test:
      '0':
    Test:
      '1':
    Test:
      '7':
    Test:
      '35':
    
     

    Attached Files:

  19. Offline

    AdamDev

    @Johnny_JayJay
    Hmm, About how the item in-game says its "0", the reason why is that your not setting an amount to it. All you need to do is just set the ItemStack amount to 1 (or how many you need). And plus I don't know why it saves so many "Test:" it should replace it but it seems not to matter in ItemStack arrays.

    The understanding of ".getKeys(false)" means that you only get what you need after the configuration section. For say your configuration section was "teleport". Adding "#.getKeys(false);" is going to not get the values after "teleport.blah". As I said in my post above. The "String kit" is going to return the next thing in the configuration section "teleport".

    Your setting the slot as a string, but I do suggest setting it as an integer for further reference. Now all you have to do is save the material, amount, enchants and the data. After you do that upon loading up the inventory just do the ItemStack as:
    Code:
    is = new ItemStack(Material.valueOf("name"),amount, (short) data);
    
    After that just add the enchants and then add it to the inventory with the slot which is your key.
     
Thread Status:
Not open for further replies.

Share This Page