Whats wrong with my for loop?

Discussion in 'Spigot Plugin Development' started by pondamo, Jun 24, 2015.

  1. I have created a for loop to add a timer to an explosion so the explosion doesnt happen immediatly but since I added the for loop nothing has been happening. There is no explosion at all.
    Heres my code:
    Code (Text):
    for (int j = 0; j < k; j++) {
                    if (j == k) {
                        e.getItemDrop().getWorld().createExplosion((e.getItemDrop().getLocation()), i);
                        e.getItemDrop().getWorld().playEffect(e.getItemDrop().getLocation(),Effect.LARGE_SMOKE, 5);
                    }
                   
                }
    k is a variable:
    Code (Text):
    int k = getConfig().getInt("TimeBeforeExplosion");
     
  2. If you're trying to make a delay before the explosion your best bet would be to use a BukkitRunnable. But the issue is that the loop continues as long as j<k but then the explosion waits for j==k. So it'll never be j==k because you stop it one below.
     
    • Agree Agree x 1
  3. ahhh that makes since. Cant beleive I didnt pick up on that lol.
     
  4. Agreed, creating a Runnable would be the way to create a delay:

    http://wiki.bukkit.org/Scheduler_Programming
     
  5. As Bimmr implied but didn't state explicitly, that loop is completely useless if you are trying to make a timer.
     
  6. Okay so I created a new runnable (Which I dont think I did right) but how do I actually set the delay?
    Code:
    Code (Text):
                Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
                    public void run() {
                        e.getItemDrop().getWorld().createExplosion((e.getItemDrop().getLocation()), i);
                        e.getItemDrop().getWorld().playEffect(e.getItemDrop().getLocation(),Effect.LARGE_SMOKE, 5);
                    }
                });
     
  7. The delay uses the long primitive. Here is a quick link to schedulers.

    Just so you know 20L = 1 second.
     
  8. This is what I would do (I'm on expert, but it works):

    Code (Java):

        public Plugin plugin = this;
        List<Item> itemsToExplode = new ArrayList<Item>();
       
        @Override
        public void onDisable(){}
       
        @Override
          public void onEnable(){}

        Runnable explodeDelay = new Runnable(){
            public void run(){
                Item item = itemsToExplode.get(0);  //Get first object in itemsToExplode list.
                Location itemLoc = item.getLocation();
                item.getWorld().createExplosion(itemLoc, getConfig().getInt("ExplosionPower"));  //Create explosion at itemLoc with a explosion power from the config
                item.getWorld().playEffect(itemLoc, Effect.LARGE_SMOKE, 5);  //Play the effect at the itemLoc
                itemsToExplode.remove(0);  //Remove the item from the itemsToExplode list
            }
        };

        public ItemStack getItemToExplode(){  //Return ItemStack that should explode when dropped, useful if you want only items with certain names ore lore to explode.
            ItemStack item = new ItemStack(Material.SULPHUR);
            return item;
        }
       
        @EventHandler
        public void onPlayerDrop(PlayerDropItemEvent e){
            if (e.getItemDrop().getItemStack().equals(getItemToExplode())){  //If dropped item equals the item we want to explode when dropped.
                itemsToExplode.add(e.getItemDrop());  //Add item dropped o the itemsToExplode list.
                Bukkit.getScheduler().runTaskLater(plugin, explodeDelay, getConfig().getInt("TimeBeforeExplosion")*20);  //Run the explodeDelay runnable TimeBeforeExplosion seconds later
            }
        }
     
    What I basically did was whenever a item was dropped I'd check if it was equal to the item I want to explode when dropped.
    Then I'd add it to the itemsToExplode list.
    Then I'd run the explodeDelay runnable, and I'd have it run however many seconds are set to delay from the config times 20 (Because as @BurnerDiamond mentioned above, 20L is equal to one second).
    The explodeDelay runnabe itself get the first Item in the itemsToExplodeList, explode it, play the effect, and remove it from the list.
    I did it this was so multiple players can drop the item & it would still work (Should, don't have others to test it with).
     
  9. What? Why would you do this? This is his first time learning about the scheduler and you throw this at him? Firstly dont spoonfeed. Secondly dont use an array list for something like this, you are going to be doing so many expensive moving around and not saving enough space to make it worthwhile. A linked list is better suited and possibly programming to the Queue interface could make the code more understandable. Realistically though the runnable should be created when it is needed grabbing the references it needs from the event. Why save everything seperatly just to go and look it up later? There is absolutly no need for the plugin = this at the top. The variable isnt encapsulated and the variable isnt static so you would already have the reference to "this" in any case you needed to grab "plugin". Lastly you shouldnt create a new itemstack just for the sake of comparison... if you want to make a method like that make one that takes an itemstack and runs the necessary checks. No need to waste the memory.