Solved Breaking out of a bukkitRunnable

Discussion in 'Spigot Plugin Development' started by skyerzz, Oct 18, 2015.

  1. Ive been playing around trying to make fireworks, and I got stuck at this moment. Im trying to shoot a firework which travels forward each tick. If it hits a block however, it should explode the firework, and terminate the loop. The last bit is what does not work, the firework does explode, but I can not seem to cancel the loop.

    My code:

    Code (Text):
     
    public void onPlayerInteract(PlayerInteractEvent event){
              Player player = event.getPlayer();  
                  if(player.getItemInHand().getType().equals(Material.DIAMOND_SWORD)){                      
                        final Location loc = event.getPlayer().getEyeLocation();
                        Vector v = loc.getDirection();
                        loc.add(v);   //add 1 movement so it wont spawn inside the player                
                        double speed = 1;
                        final Vector v2 = v.normalize().multiply(speed);
                        getLogger().info(v.toString()); //debug item, to see in console if it executes
                        final Firework f = loc.getWorld().spawn(loc, Firework.class);
                        final boolean ent = true; // Also check if we hit entities  
     
                        new BukkitRunnable() {
                            public void run(){                          
                                f.setTicksLived(1); //tried to prevent it from detonating mid air, doesnt work either
                                f.setVelocity(v2);
                                getLogger().info(f.getVelocity().toString()); //debug item, see if it executes
                                if(f.isOnGround()){
                                    f.teleport(loc.subtract(v2)); // Go back one step to get outside the block we hit
                                    f.detonate();
                                    player.sendMessage("HIT"); //debug item
                                    cancel(); // to stop the task, DOESNT WORK                              
                                }                        
                                if(ent){ // Check if we have hit entities
                                    Vec3D v3 = new Vec3D(loc.getX(), loc.getY(), loc.getZ());
                                    for(org.bukkit.entity.Entity e : f.getNearbyEntities(2, 2, 2)){ // Scan nearby entities
                                        if(((CraftEntity)e).getHandle().getBoundingBox().a(v3)){
                                            f.detonate();                                      
                                            cancel();
                                            return;
                                        }
                                    }
                                 
                                }
                             
                            }
                        }.runTaskTimer(plugin ,0L ,1L); // Run every 1 tick
                       
                  }
                 

          }
    If someone could help me with this, so the task will cancel if it hit a block (or entity, but its the same concept really), I'd be gratefull :)
     
  2. Try using setEnabled(false);, that might work.
     
  3. I tried replacing "cancel();" with your suggestion, unfortunately it still does not terminate. (it doesn't give any errors either)
     
  4. Bukkit.getScheduler().runTaskBlah(blahblah) returns a BukkitTask.
    Store this variable, and then when you can to cancel the task, use Bukkit.getScheduler().cancelTask(bukkitTask.getTaskId())
     
  5. use a repeatingtask or a scheduledtask
     
  6. What indicates to you that the loop is still going after the firework explodes from a block hit? What makes you think it's still going?
     
  7. getLogger().info(f.getVelocity().toString()); //debug item, see if it executes
    This line is inside the loop, so i just open up the console and see if this line is still being written each loop (it is.)



    Tried both, same problems (maybe i was using them wrong tough, could you provide a small example for me?)

    Same as before, Ive tried it, but it still didnt terminate :(
     
  8. And you get the message that says "HIT"?
     
  9. I do get the HIT message in-game, and the firework does detonate. Its just that the loop wont stop for some reason
     
  10. To me everything seems proper. While it seems unlikely, maybe there's something elsewhere in your code preventing this from working correctly. Mind posting the rest?
     
  11. Fair warning: this may not be the cleanest code you'll encounter. But here is my whole code :) (its not much yet either, i really wanted to get this down first)

    Code (Text):


    package com.sky.q;

    import org.bukkit.Bukkit;

    import org.bukkit.ChatColor;
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandSender;
    import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity;
    import org.bukkit.entity.Firework;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.plugin.Plugin;
    import org.bukkit.plugin.java.JavaPlugin;
    import org.bukkit.scheduler.BukkitRunnable;
    import org.bukkit.scheduler.BukkitScheduler;
    import org.bukkit.util.Vector;

    import net.minecraft.server.v1_8_R3.Vec3D;



    public class Main extends JavaPlugin implements Listener{  
        static Plugin plugin = null;
        BukkitScheduler scheduler = Bukkit.getServer().getScheduler();
       
        public void onEnable() {
            getLogger().info("SQ Enabled");
            this.getServer().getPluginManager().registerEvents(this, this);      
            plugin = this;
            plugin.getServer().getPluginManager().registerEvents(this, plugin);
        }
       
         public void onDisable(){
         }
         
         @EventHandler
    public void onPlayerInteract(PlayerInteractEvent event){
              Player player = event.getPlayer();  
                  if(player.getItemInHand().getType().equals(Material.DIAMOND_SWORD)){                      
                        final Location loc = event.getPlayer().getEyeLocation();
                        Vector v = loc.getDirection();
                        loc.add(v);   //add 1 movement so it wont spawn inside the player                
                        double speed = 1;
                        final Vector v2 = v.normalize().multiply(speed);
                        getLogger().info(v.toString()); //debug item, to see in console if it executes
                        final Firework f = loc.getWorld().spawn(loc, Firework.class);
                        final boolean ent = true; // Also check if we hit entities  

                        new BukkitRunnable() {
                            public void run(){                          
                                f.setTicksLived(1); //tried to prevent it from detonating mid air, doesnt work either
                                f.setVelocity(v2);
                                getLogger().info(f.getVelocity().toString()); //debug item, see if it executes
                                if(f.isOnGround()){
                                    f.teleport(loc.subtract(v2)); // Go back one step to get outside the block we hit
                                    f.detonate();
                                    player.sendMessage("HIT"); //debug item
                                    cancel(); // to stop the task, DOESNT WORK                              
                                }                        
                                if(ent){ // Check if we have hit entities
                                    Vec3D v3 = new Vec3D(loc.getX(), loc.getY(), loc.getZ());
                                    for(org.bukkit.entity.Entity e : f.getNearbyEntities(2, 2, 2)){ // Scan nearby entities
                                        if(((CraftEntity)e).getHandle().getBoundingBox().a(v3)){
                                            f.detonate();                                      
                                            cancel();
                                            return;
                                        }
                                    }
                                 
                                }
                             
                            }
                        }.runTaskTimer(plugin ,0L ,1L); // Run every 1 tick
                       
                  }
                 

          }
         

         public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
             if(cmd.getName().equalsIgnoreCase("SQ")){
                 if(sender instanceof Player){
                     Player player = (Player) sender;
                     if(args.length > 0){
                         //TODO: implement this command.
                     }
                     else{
                         player.sendMessage(ChatColor.BLACK + "[" + ChatColor.BLUE + "SQ" + ChatColor.BLACK + "] " + ChatColor.RED + "Wrong syntax! use \"/SQ help\" for help!");
                     }
                 }
                 
                 else{//sender = console
                     getLogger().info("SQ is not compatible trough the console!");
                 }
             }//end of SQ command
             
            return false;
         }//end of command
         
         
         
         
    }
    Thanks for trying to help :)
     
  12. You're registering events twice. Not sure if this is necessarily part of the problem, but let's rule that out first, as it will cause you trouble later on.
     
  13. Some minor fixes that might work are
    1. Changing your "cancel();" to "this.cancel();" and
    2. Putting "@Override" above your "run()" method.
     
    • Useful Useful x 1
  14. None of those will have any effect on runtime. Although I wholeheartedly agree with your second point (which also applies to onEnable and onDisable), I believe your first point is just a matter of style preference.
     
  15. The override appears to work, the loop now cancels correctly! (i changed cancel(); into this.cancel(); as well now, not sure if it works without the this)

    Thanks a lot!
     
    • Agree Agree x 1
  16. Did you also make sure only to register events once?

    (Keep in mind, adding override annotations to your code doesn't change the outcome)