Solved Nested Loop debuging - Terminates at child loop w/o finishing parent loop?

Discussion in 'Plugin Development' started by eve0021, Apr 27, 2017.

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

    eve0021

    Good day people.

    Im having a problem with looping through my player's inventory.
    It seems that the loop never finishes.. it just terminates?

    can someone look at it?

    Code:
    private void TotemOfResurrection(Player p) {
      
        p.sendMessage("Inventory Size: "+p.getInventory().getStorageContents().length);
      
        for(int i=0; i<3; i++){
          
            p.sendMessage("Looking for: "+VoodooItems[i].getType());
            p.sendMessage("Parent Loop count: "+i);
          
            for(int x=0; x<p.getInventory().getSize(); x++){
              
                p.sendMessage("Child Loop count: "+x);
                tempItem = p.getInventory().getItem(x);
              
                if(tempItem.getType()==VoodooItems[i].getType() && p.getInventory().getItem(x).getAmount()>=VoodooQty[i]){
                    p.sendMessage("Item Found: "+VoodooItems[i].getType());
                    itemCheck=true;
                }
              
            }
        }
      
        p.sendMessage("End of Method");
    }
    it just end with the last message
    "Child Loop count: 36"

    BTW it only goes through 1 parent loop and then terminates at child.

    Was my logic wrong?
     
  2. @eve0021
    Any error in console?
    What's Voodoo items? Can you show us the specific code part?
     
  3. Offline

    eve0021

    My appologies, let me post the whole code.
    Pardon my coding, I am very new to using bukkit and I am more used in programming java applications. I am still in an Amateur level.

    Code:
    package jc.CustomCraft;
    
    import java.util.ArrayList;
    import java.util.List;
    import org.bukkit.Material;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.plugin.Plugin;
    
    public class CraftEventHandler implements Listener{
      
        Plugin plug;
        ItemStack lefthand;
        ItemStack righthand;
        ItemStack tempItem;
        List<String> templore = new ArrayList<>();
        List<List<String>> Recipes = new ArrayList<>();
      
        List<String> VoodooDoll = new ArrayList<>();
        ItemStack[] VoodooItems  = {new ItemStack(Material.EXP_BOTTLE),new ItemStack(Material.ARMOR_STAND),new ItemStack(Material.EMERALD)};
        int[] VoodooQty = {1,1,5};
      
        boolean itemCheck = false;
      
        public CraftEventHandler(CustomCraftPlugin plugin){
          
            plug = plugin;
            plugin.getServer().getPluginManager().registerEvents(this, plugin);
            loadItems();
        }
      
        public void loadItems(){
            VoodooDoll.clear();
            VoodooDoll.add("Recipe: Totem of Resurrection");
            VoodooDoll.add("Requires:");
            VoodooDoll.add("1. XP Bottle x1");
            VoodooDoll.add("2. Armor Stand x1");
            VoodooDoll.add("3. Emeralds x5");
          
            Recipes.add(VoodooDoll);
        }
      
        public void getItemData(Player p){
            if(p.getInventory().getItemInMainHand()!=null){
              
                tempItem = p.getInventory().getItemInMainHand();
              
                if(tempItem.getItemMeta().getLore()!=null){
                  
                    templore = tempItem.getItemMeta().getLore();
                    //p.sendMessage("Lore of item in hand: "+templore.toString());
                  
                    for (List<String> r : Recipes) {
                      
                        if(templore.get(0).toString().equalsIgnoreCase(r.get(0).toString())){
                          
                            if(templore.get(0).toString().equalsIgnoreCase("Recipe: Totem of Resurrection")){
                                p.sendMessage("TOTEM FOUND!");
                                TotemOfResurrection(p);
                            }
                        }
                  
                    }
              
                }
            }
        }
      
        @EventHandler
        public void onPlayerInteract(PlayerInteractEvent e) {
          
            if(e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK){
                e.getPlayer().sendMessage("Event triggered");
                getItemData(e.getPlayer());
          
            }
        }
    
        private void TotemOfResurrection(Player p) {
            p.sendMessage("Inventory Size: "+p.getInventory().getStorageContents().length);
            for(int i=0; i<3; i++){
                p.sendMessage("Looking for: "+VoodooItems[i].getType());
                p.sendMessage("Parent Loop count: "+i);
              
                for(int x=0; x<p.getInventory().getSize(); x++){
                    p.sendMessage("Child Loop count: "+x);
                    tempItem = p.getInventory().getItem(x);
                  
                    if(tempItem.getType()==VoodooItems[i].getType() && p.getInventory().getItem(x).getAmount()>=VoodooQty[i]){
                        p.sendMessage("Item Found: "+VoodooItems[i].getType());
                        itemCheck=true;
                    }
                }
                p.sendMessage("internal loop complete");
         }
    }
    I just noticed I got an error (not used to compile then test in a different application for errors) I am trying to track it down now, but please do give me some guidelines how to improve my coding.

    Error Log (open)

    Could not pass event PlayerInteractEvent to CustomCraft v1.0.0
    org.bukkit.event.EventException
    at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:298) ~[craftbukkit.jar:git-Bukkit-1f6c04c]
    at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62) ~[craftbukkit.jar:git-Bukkit-1f6c04c]
    at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:501) [craftbukkit.jar:git-Bukkit-1f6c04c]
    at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:486) [craftbukkit.jar:git-Bukkit-1f6c04c]
    at org.bukkit.craftbukkit.v1_11_R1.event.CraftEventFactory.callPlayerInteractEvent(CraftEventFactory.java:234) [craftbukkit.jar:git-Bukkit-1f6c04c]
    at org.bukkit.craftbukkit.v1_11_R1.event.CraftEventFactory.callPlayerInteractEvent(CraftEventFactory.java:201) [craftbukkit.jar:git-Bukkit-1f6c04c]
    at org.bukkit.craftbukkit.v1_11_R1.event.CraftEventFactory.callPlayerInteractEvent(CraftEventFactory.java:197) [craftbukkit.jar:git-Bukkit-1f6c04c]
    at net.minecraft.server.v1_11_R1.PlayerConnection.a(PlayerConnection.java:916) [craftbukkit.jar:git-Bukkit-1f6c04c]
    at net.minecraft.server.v1_11_R1.PacketPlayInBlockPlace.a(SourceFile:32) [craftbukkit.jar:git-Bukkit-1f6c04c]
    at net.minecraft.server.v1_11_R1.PacketPlayInBlockPlace.a(SourceFile:9) [craftbukkit.jar:git-Bukkit-1f6c04c]
    at net.minecraft.server.v1_11_R1.PlayerConnectionUtils$1.run(SourceFile:13) [craftbukkit.jar:git-Bukkit-1f6c04c]
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.7.0_67]
    at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.7.0_67]
    at net.minecraft.server.v1_11_R1.SystemUtils.a(SourceFile:46) [craftbukkit.jar:git-Bukkit-1f6c04c]
    at net.minecraft.server.v1_11_R1.MinecraftServer.D(MinecraftServer.java:695) [craftbukkit.jar:git-Bukkit-1f6c04c]
    at net.minecraft.server.v1_11_R1.DedicatedServer.D(DedicatedServer.java:360) [craftbukkit.jar:git-Bukkit-1f6c04c]
    at net.minecraft.server.v1_11_R1.MinecraftServer.C(MinecraftServer.java:650) [craftbukkit.jar:git-Bukkit-1f6c04c]
    at net.minecraft.server.v1_11_R1.MinecraftServer.run(MinecraftServer.java:554) [craftbukkit.jar:git-Bukkit-1f6c04c]
    at java.lang.Thread.run(Unknown Source) [?:1.7.0_67]
    Caused by: java.lang.NullPointerException
    at jc.CustomCraft.CraftEventHandler.TotemOfResurrection(CraftEventHandler.java:97) ~[?:?]
    at jc.CustomCraft.CraftEventHandler.getItemData(CraftEventHandler.java:67) ~[?:?]
    at jc.CustomCraft.CraftEventHandler.onPlayerInteract(CraftEventHandler.java:82) ~[?:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_67]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.7.0_67]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.7.0_67]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.7.0_67]
    at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:296) ~[craftbukkit.jar:git-Bukkit-1f6c04c]
    ... 18 more
     
  4. Offline

    Caedus

    You've got a Null Pointer Error on line 97 of your CraftEventHandler. Can you show us the line?
     
  5. @eve0021
    I think the problem is in line 97, in both statements.
    Code:
    tempItem.getType()==VoodooItems[i].getType() && p.getInventory().getItem(x).getAmount()>=VoodooQty[i]
    You do not check if the item is null.


    And you could shorten that by using:
    Code:
    tempItem.getType()==VoodooItems[i].getType() && tempItem.getAmount()>=VoodooQty[i]
     
  6. Offline

    eve0021

    Thanks for that. I have revised my code and yea, the null parts are the error where in I looped through the whole inventory without checking if they are empty.

    now the next problem I have is I got the Item I needed but:

    1. Items werent removed from the player.
    2. The lore I set using "tempItem.getItemMeta().setLore(tempLore)" before giving it to the player didn't show up.

    here is a revised code. sorry for not updating as soon as I figured it out, I'll add the optimization later on:

    Code:
    package jc.CustomCraft;
    
    import java.util.ArrayList;
    import java.util.List;
    import org.bukkit.Material;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.plugin.Plugin;
    
    public class CraftEventHandler implements Listener{
       
        Plugin plug;
        ItemStack lefthand;
        ItemStack righthand;
        ItemStack tempItem;
        List<String> templore = new ArrayList<>();
        List<List<String>> Recipes = new ArrayList<>();
       
        List<String> VoodooDoll = new ArrayList<>();
        ItemStack[] VoodooItems  = {new ItemStack(Material.EXP_BOTTLE),new ItemStack(Material.ARMOR_STAND),new ItemStack(Material.EMERALD)};
        int[] VoodooQty = {1,1,5};
       
        boolean itemCheck = false;
       
        public CraftEventHandler(CustomCraftPlugin plugin){
           
            plug = plugin;
            plugin.getServer().getPluginManager().registerEvents(this, plugin);
            loadItems();
        }
       
        public void loadItems(){
            VoodooDoll.clear();
            VoodooDoll.add("Recipe: Totem of Resurrection");
            VoodooDoll.add("Requires:");
            VoodooDoll.add("1. XP Bottle x1");
            VoodooDoll.add("2. Armor Stand x1");
            VoodooDoll.add("3. Emeralds x5");
           
            Recipes.add(VoodooDoll);
        }
       
        public void getItemData(Player p){
            if(p.getInventory().getItemInMainHand()!=null){
                tempItem = p.getInventory().getItemInMainHand();
                if(tempItem.getItemMeta().getLore()!=null){
                    templore = tempItem.getItemMeta().getLore();
                    for (List<String> r : Recipes) {
                        if(templore.get(0).toString().equalsIgnoreCase(r.get(0).toString())){
                            if(templore.get(0).toString().equalsIgnoreCase("Recipe: Totem of Resurrection")){
                                p.sendMessage("TOTEM FOUND!");
                                TotemOfResurrection(p);
                            }
                        }
                    }
               
                }
            }
        }
       
        @EventHandler
        public void onPlayerInteract(PlayerInteractEvent e) {
           
            if(e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK){
                e.getPlayer().sendMessage("Event triggered");
                getItemData(e.getPlayer());
           
            }
        }
    
        private void TotemOfResurrection(Player p) {
            for(int i=0; i<3; i++){
               
                for(int x=0; x<p.getInventory().getSize(); x++){
                   
                    if(p.getInventory().getItem(x)!=null){
                        tempItem = p.getInventory().getItem(x);
                        if(tempItem.getType()==VoodooItems[i].getType() && p.getInventory().getItem(x).getAmount()>=VoodooQty[i]){
                            p.sendMessage("Item Found: "+VoodooItems[i].getType());
                            itemCheck=true;
                        }
                    }
                }
               
                if(itemCheck!=true) break;
            }
           
            if(itemCheck==true){
                p.getInventory().getItemInMainHand().setAmount(p.getInventory().getItemInMainHand().getAmount()-1);
                for(int i=0; i<3; i++){
                    for(int x=0; x<p.getInventory().getSize(); x++){
                        if(p.getInventory().getItem(x)!=null){
                            tempItem = p.getInventory().getItem(x);
                            if(p.getInventory().getItem(x)==VoodooItems[i] && p.getInventory().getItem(x).getAmount()>=VoodooQty[i]){
                                p.getInventory().getItem(i).setAmount(p.getInventory().getItem(i).getAmount()-VoodooQty[i]);
                            }
                        }
                    }
                }
                tempItem = new ItemStack(Material.TOTEM);
                templore.clear();
                templore.add("A totem that resurrects player when they die if they are holding it.");
                templore.add("Totem crafted by: "+p.getName());
                tempItem.getItemMeta().setLore(templore);
                p.getInventory().addItem(tempItem);
                p.sendMessage(tempItem.getItemMeta().getLore().toString());
            }
        }
    }
    
     
  7. The Problem is over there.

    You can get your metadata with "getItemMeta", but you cant set it.
    So, to do it right it would be:
    Code:
    ItemMeta im = tempItem.getItemMeta();
    im.setlore(templore)
    tempItem.setItemMeta(im);
    or in one line: (not sure, you have to test this one)
    Code:
    tempItem.setItemMeta(tempItem.getItemMeta().setLore(templore));


    same with the other one:
    Code:
    p.getInventory().getItemInMainHand().setAmount(p.getInventory().getItemInMainHand().getAmount()-1);
    has to be something like:
    Code:
    ItemStack mainHand = p.getInventory().getItemInMainHand():
    mainHand.setAmount(mainHand.getAmount -1):
    p.getInventory().setItemInMainHand(mainHand):
    or in one line (please test this one too.., I'm just writing in browser without testing):
    Code:
    p.getInventory().setItemInMainHand()(p.getInventory().getItemInMainHand().setAmount(p.getInventory().getItemInMainHand().getAmount()-1));
    But i would rather go with the longer version. It's much eaiser.
     
    Last edited: Apr 27, 2017
    eve0021 likes this.
  8. Offline

    eve0021

    Thank you very much for that one. I should've guessed I should've guessed that I should create a new ItemMeta to place into an ItemStack.

    How about the deduction or removal? got any luck on that?
    Right now I am stuck between knowing if we got the total amount but separated in different slots VS a whole stack.
    Im working a way to handle this.
    Its a bit difficult since I am using netbeans. I had to download the whole webpage of bukkit doc just to have a reference.
     
  9. Okay first: If you think about working on plugins not only once, switch to IntelliJ. It is THE software for java development. There, choose a gradle or maven project, and you can easily import all the stuff you need.

    You mean the item-removal? See my post above, I added that part a little bit later.
     
  10. Offline

    eve0021

    ok so I was able to test it out, and setting a new ItemMeta worked.

    but looks like the way I am checking my inventory is not.
    After testing the whole code again I found that the Item-checking has been bypassed, even though you dont have all the required items, the checking still falls into true allowing the if condition to carry out the crafting and eventually fall into NPE (null pointer exception).

    I think I need to look for a working code as reference so I can learn how they do these checks...

    I altered some of my logical flows and instead of 1 whole clump of code, I segregated them based on their roles as methods which throws or processes the items.

    Issue Solved!

    Thanks alot for the guidance and sample codes @Erumeldor!

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Apr 27, 2017
  11. Offline

    Zombie_Striker

    @eve0021
    If your problem has been solved, mark this thread as solved (go to the top left side of this page, click ThreadTools, edit title, and then select the solved prefix)
     
Thread Status:
Not open for further replies.

Share This Page