Solved Inventory.getContents() Error

Discussion in 'Spigot Plugin Development' started by YourCoal, May 18, 2017.

  1. I have a problem trying to search for items in the contents of an inventory, but I don't recall this being a problem before. Not sure if something changed or if I am too tired...

    Code (Text):
        @EventHandler
        public void onInventoryClose(InventoryCloseEvent event) {
            Inventory inv = event.getInventory();
            Player p = (Player) event.getPlayer();
           
            if (inv.getName().equalsIgnoreCase("Test Panel")) {
                int toRemove = 0;
                for (ItemStack stack : inv.getContents().clone()) {
                    if (stack.getType() == Material.DIRT) { //<--- ERROR HERE
                        toRemove++;
                        inv.removeItem(stack);
                    }
                }
                p.getInventory().addItem(new ItemStack(Material.DIAMOND, toRemove));
            }
        }

    Code (Text):
    [21:30:17] [Server thread/ERROR]: Could not pass event InventoryCloseEvent to CivCraft v1.1.4
    org.bukkit.event.EventException
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:306) ~[spigot.jar:git-Spigot-3fb9445-2b6c9f4]
        at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62) ~[spigot.jar:git-Spigot-3fb9445-2b6c9f4]
        at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:502) [spigot.jar:git-Spigot-3fb9445-2b6c9f4]
        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:487) [spigot.jar:git-Spigot-3fb9445-2b6c9f4]
        at org.bukkit.craftbukkit.v1_11_R1.event.CraftEventFactory.handleInventoryCloseEvent(CraftEventFactory.java:884) [spigot.jar:git-Spigot-3fb9445-2b6c9f4]
        at net.minecraft.server.v1_11_R1.PlayerConnection.a(PlayerConnection.java:1629) [spigot.jar:git-Spigot-3fb9445-2b6c9f4]
        at net.minecraft.server.v1_11_R1.PacketPlayInCloseWindow.a(PacketPlayInCloseWindow.java:18) [spigot.jar:git-Spigot-3fb9445-2b6c9f4]
        at net.minecraft.server.v1_11_R1.PacketPlayInCloseWindow.a(PacketPlayInCloseWindow.java:1) [spigot.jar:git-Spigot-3fb9445-2b6c9f4]
        at net.minecraft.server.v1_11_R1.PlayerConnectionUtils$1.run(SourceFile:13) [spigot.jar:git-Spigot-3fb9445-2b6c9f4]
        at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_131]
        at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_131]
        at net.minecraft.server.v1_11_R1.SystemUtils.a(SourceFile:46) [spigot.jar:git-Spigot-3fb9445-2b6c9f4]
        at net.minecraft.server.v1_11_R1.MinecraftServer.D(MinecraftServer.java:747) [spigot.jar:git-Spigot-3fb9445-2b6c9f4]
        at net.minecraft.server.v1_11_R1.DedicatedServer.D(DedicatedServer.java:399) [spigot.jar:git-Spigot-3fb9445-2b6c9f4]
        at net.minecraft.server.v1_11_R1.MinecraftServer.C(MinecraftServer.java:678) [spigot.jar:git-Spigot-3fb9445-2b6c9f4]
        at net.minecraft.server.v1_11_R1.MinecraftServer.run(MinecraftServer.java:576) [spigot.jar:git-Spigot-3fb9445-2b6c9f4]
        at java.lang.Thread.run(Unknown Source) [?:1.8.0_131]
    Caused by: java.lang.NullPointerException
        at com.avrgaming.civcraft.command.admin.AdminTestCommand.onInventoryClose(AdminTestCommand.java:48) ~[?:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_131]
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_131]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_131]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_131]
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:302) ~[spigot.jar:git-Spigot-3fb9445-2b6c9f4]
        ... 16 more
     
  2. It's looping through the contents, and if the inventory isn't full, then it will throw a NPE. This is because there may be an empty slot in the inventory. Just make a null check before you check the type of the ItemStack and it should work.
     
  3. Code (Text):
        @EventHandler
        public void onInventoryClose(InventoryCloseEvent event) {
            Inventory inv = event.getInventory();
            Player p = (Player) event.getPlayer();
         
            if (inv.getName().equalsIgnoreCase("Test Panel")) {
                int toRemove = 0;
                for (ItemStack stack : inv.getContents().clone()) {
                    if (stack == null) // <- your error occurs because you are missing this
                      continue; // stack was null or air, continue to next entry in loop
                    if (stack.getType() == Material.DIRT) { //<--- ERROR HERE
                        toRemove++;
                        inv.removeItem(stack);
                    }
                }
                p.getInventory().addItem(new ItemStack(Material.DIAMOND, toRemove));
            }
        }
    EDIT:
    Apparantly the ItemStack's type can't == Material.AIR.
     
    #3 ExpDev, May 18, 2017
    Last edited: May 18, 2017
  4. Pretty much an empty slot in the inventory will == null
     
  5. filter the thing with Objects::notNull. Streams will help
     
  6. When will the Material == Air, just out of curiousity..? I figure that the empty spaces are just non-materials, i.e Null
     
  7. I've never seen it == air, just null
     
  8. Neither, that's why Im confused as to 1. Why there even exists an enum of Material#AIR, and 2. why @ExpDev suggested to test for it.
     
  9. Only time I used Material.AIR was for checking a block if it was air lol
     
  10. Thank you! Works now. :)