Arrow Trail Help

Discussion in 'Plugin Development' started by Nick_Titan, Jun 6, 2016.

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

    Nick_Titan

    So using the particle effect library I am attempting to make a trail for arrows here is the entire code:
    Code:
    package me.nico;
    
    import java.util.ArrayList;
    
    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Arrow;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.entity.ProjectileHitEvent;
    import org.bukkit.event.entity.ProjectileLaunchEvent;
    import org.bukkit.event.player.PlayerFishEvent;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.ItemMeta;
    
    public class Grapple extends Gadget implements Listener {
       
        public static Class<Arrow> arrows = Arrow.class;
       
        public static ArrayList<Player> list = new ArrayList<Player>();
       
        @Override
        public void onEnable() {
            getLogger().info("Grapple thing started");
            Bukkit.getPluginManager().registerEvents(this, this);
        }
       
        @Override
        public void onDisable() {
            getLogger().info("Grapple thing stopping");
        }
       
        @EventHandler
        public void shootArrow(PlayerFishEvent event) {
            final Player player = event.getPlayer();
            ItemStack item = player.getItemInHand();
            ItemMeta meta = item.getItemMeta();
            if (item.hasItemMeta() && item.getType() == Material.FISHING_ROD && meta.getDisplayName().equals("Grapple")) {
                event.setCancelled(true);
                player.launchProjectile(arrows);
            }
        }
       
        @EventHandler
        public void onHit(ProjectileHitEvent event) {
            Player player = (Player) event.getEntity().getShooter();
            Arrow arrow = (Arrow) event.getEntity();
            Location loc = arrow.getLocation();
            ItemStack item = player.getItemInHand();
            ItemMeta meta = item.getItemMeta();
            if (item.hasItemMeta() && item.getType() == Material.FISHING_ROD && meta.getDisplayName().equals("Grapple")) {
                player.teleport(loc);
                arrow.getWorld().getEntities().remove(arrow);
               
            }
        }
       
        @EventHandler
        public void onMove(ProjectileLaunchEvent event) {
            final Location loc = event.getEntity().getLocation();
            Player player = (Player) event.getEntity().getShooter();
            if (event.getEntity() instanceof Arrow && player.getItemInHand().equals(Material.FISHING_ROD)) {
                // Reoccuring particle effect
                Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
                    public void run() {
                        ParticleEffect.DRIP_LAVA.display(10, 15, 0, 0, 0, loc, 10);
                    }
                }, 20, 20);
            }
        }
        //Commands
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if (cmd.getLabel().equalsIgnoreCase("Particle")) {
                Player player = (Player) sender;
                ParticleEffect.DRIP_LAVA.display(10, 15, 0, 0, 0, player.getLocation(), 10);
                return true;
            }
            return false;
        }
    }
    
    And here is the part that needs to be fixed:
    Code:
        @EventHandler
        public void onMove(ProjectileLaunchEvent event) {
            final Location loc = event.getEntity().getLocation();
            Player player = (Player) event.getEntity().getShooter();
            if (event.getEntity() instanceof Arrow && player.getItemInHand().equals(Material.FISHING_ROD)) {
                // Reoccuring particle effect
                Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
                    public void run() {
                        ParticleEffect.DRIP_LAVA.display(10, 15, 0, 0, 0, loc, 10);
                    }
                }, 20, 20);
            }
        }
    Can anyone help?
     
  2. Offline

    Zombie_Striker

    @Nick_Titan
    Dont blindly cast the shooter to an entity. There's a reason it is not automatically a Player. Check if the shooter is an instanceof Player before casting. Also, compare enums using ==.

    Is your problem that the particles are spawning in the same location? If so, your problem is that you have made the entities location final. Try making the entity final instead, and just call Entity#getLocation() to get the arrow's location.
     
  3. Offline

    Nick_Titan

    The problem is no particle effects spawn for some reason the thing that doesn't work is the if statment in line 5. When i removed it then things sort of worked but the particle still only spawned in one place here is my new code but not sure where i went wrong.

    Code:
    package me.nico;
    
    import java.util.ArrayList;
    
    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Arrow;
    import org.bukkit.entity.Entity;
    import org.bukkit.entity.Player;
    import org.bukkit.entity.Projectile;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.entity.ProjectileHitEvent;
    import org.bukkit.event.entity.ProjectileLaunchEvent;
    import org.bukkit.event.player.PlayerFishEvent;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.ItemMeta;
    
    public class Grapple extends Gadget implements Listener {
       
        public static Class<Arrow> arrows = Arrow.class;
       
        public static ArrayList<Player> list = new ArrayList<Player>();
       
        public ArrayList<Projectile> arrowlist = new ArrayList<Projectile>();
       
        public Arrow arrow;
       
        @Override
        public void onEnable() {
            getLogger().info("Grapple thing started");
            Bukkit.getPluginManager().registerEvents(this, this);
        }
       
        @Override
        public void onDisable() {
            getLogger().info("Grapple thing stopping");
        }
       
        @EventHandler
        public void shootArrow(PlayerFishEvent event) {
            final Player player = event.getPlayer();
            ItemStack item = player.getItemInHand();
            ItemMeta meta = item.getItemMeta();
            if (item.hasItemMeta() && item.getType() == Material.FISHING_ROD && meta.getDisplayName().equals("Grapple")) {
                player.launchProjectile(arrows);
                arrowlist.add(arrow);
                event.setCancelled(true);
            }
        }
       
        @EventHandler
        public void onHit(ProjectileHitEvent event) {
            Player player = (Player) event.getEntity().getShooter();
            Arrow ar = (Arrow) event.getEntity();
            Location loc = ar.getLocation();
            ItemStack item = player.getItemInHand();
            ItemMeta meta = item.getItemMeta();
            if (item.hasItemMeta() && item.getType() == Material.FISHING_ROD && meta.getDisplayName().equals("Grapple")) {
                player.teleport(loc);
                arrowlist.remove(arrow);
                ar.getWorld().getEntities().remove(ar);
                Bukkit.getScheduler().cancelAllTasks();
               
            }
        }
    
        @EventHandler
        public void onMove(ProjectileLaunchEvent event) {
            Entity ent = event.getEntity();
            Location loc = ent.getLocation();
            Player player = (Player) event.getEntity().getShooter();
                // Reoccuring particle effect
                Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
                public void run() {
                    if (list.contains(arrow)) {
                        player.sendMessage("working");
                        ParticleEffect.CRIT.display(10, 15, 0, 0, 0, loc, 20);
                        }
                    }
                }, 20, 20);
            }
        //Commands
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if (cmd.getLabel().equalsIgnoreCase("Particle")) {
                Player player = (Player) sender;
                ParticleEffect.SMOKE_NORMAL.display(10, 15, 0, 0, 0, player.getLocation(), 10);
                return true;
            }
            return false;
        }
    }
     
  4. Offline

    Zombie_Striker

    Below are some things that you really should fix. At the bottom of this post is how you would solve your problem.

    What is this for? I don't think this is ever used, and there is no reason for it to be static anyways.

    This should not be static. Also, what is the use of this List? Finally, don't store players instances. Store their names or UUIds instead.

    What is this for? It seems as though it is never used.

    No need to log your own plugin. Bukkit does this for you.

    Becasue of the above, this can be delted.

    Remember: The itemstack can be null. Getting the item meta can throw an NPE. make sure the item is not null before getting the meta.
    Again, Don't blindly cast. Make sure the shooter is a player before you cast, and make sure the entity is an arrow first. What if a player throws an ender pearl? Then this would throw a ClassCastException.

    If the arrow hits a player, the arrow will already be removed.

    HUGE PROBLEM: You are canceling every single task for every single plugin on your entire server. Unless you want a huge amount of plugins to break, you need to make sure to cancel only your own tasks.

    Even still, there is a better way to do particles below.

    Don't blidnly cast the sender to a player. There is a reason the sender is not automatically a player.

    POSSIBLE PROBLEM: This class has an onEnable and onCommand, yet it does not extend JavaPlugin. I have no idea what Gadget is, but since this is the main class, this should only extend Javaplugin. If Gadget extends Java plugin, all this code should be moved into that class.

    How to solve your current problem:
    The way you should handle the particles should be like the following:
    1. Create a Set (Not an arraylist) of Arrows. This will hold all the arrows that will have a particle effect.
    2. Inside the onEnable, create a new Repeating Task. Inside that task, loop through all the arrows in the set and add a particle at their location every __ tick.
    3. When an arrow is created, add them to the set.
    4. When an arrow hits something, remove it from the set. (make sure to check if it hits a player, and check if it does not hit a player. We do not want memory leaks)
     
    mine-care likes this.
  5. Offline

    DoggyCode™

    Off-topic but FORZA JUVE!
     
  6. Offline

    Xerox262

    @Zombie_Striker Can the item in the hand be null in the PlayerFishEvent without a plugin manually calling the event for the player, since the player would need to be holding a fishing rod to trigger the event?
     
  7. Offline

    Lordloss

    @Xerox262 well, maybe its the last use of the fishing rod and it breaks, are you sure the rod is still available in this event? Or, maybe it gets removed by a different plugin, or aliens. At least its good behavior to check it first.
     
  8. Offline

    Xerox262

    @Lordloss The fishing rod wouldn't break on the event, it would break when the line was reeled back in. But yea, I guess checking doesn't hurt anyone.

    P.S. That Tetris is cool.
     
  9. Offline

    Lordloss

    @Xerox262 thanks, it was one of my first plugins :)
     
  10. Offline

    Nick_Titan

    Ok I went back and did some revising to my terrible start. Here is the new one. Now the if statement works but the particle still doestn't spawn right:
    Code:
    package me.nico;
    
    import java.util.ArrayList;
    
    import org.bukkit.Bukkit;
    import org.bukkit.Effect;
    import org.bukkit.EntityEffect;
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Arrow;
    import org.bukkit.entity.Entity;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.entity.ProjectileHitEvent;
    import org.bukkit.event.entity.ProjectileLaunchEvent;
    import org.bukkit.event.player.PlayerFishEvent;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.ItemMeta;
    
    public class Grapple extends Gadget implements Listener {
      
        @Override
        public void onEnable() {
            Bukkit.getPluginManager().registerEvents(this, this);
        }
      
        @Override
        public void onDisable() {
        }
      
        //List to hold player name
        public ArrayList<String> list = new ArrayList<String>();
      
        //Forcing Player to shoot the arrow
        @EventHandler
        public void shootArrow(PlayerFishEvent event) {
            Player player = event.getPlayer();
            ItemStack item = player.getItemInHand();
            ItemMeta meta = item.getItemMeta();
            if (item.hasItemMeta() && item.getType() == Material.FISHING_ROD && meta.getDisplayName().equals("Grapple")) {
                player.launchProjectile(Arrow.class);
                list.add(player.getName());
                event.setCancelled(true);
            }
        }
      
        //Ending everything when the arrow hits
        @SuppressWarnings("deprecation")
        @EventHandler
        public void onHit(ProjectileHitEvent event) {
            Player player = (Player) event.getEntity().getShooter();
            Arrow arrow = (Arrow) event.getEntity();
            Location loc = arrow.getLocation();
            ItemStack item = player.getItemInHand();
            ItemMeta meta = item.getItemMeta();
            if (item.hasItemMeta() && item.getType() == Material.FISHING_ROD && meta.getDisplayName().equals("Grapple")) {
                player.teleport(loc);
                player.playEffect(loc, Effect.ENDER_SIGNAL, 1);
                list.remove(player.getName());
              
            }
        }
        //Adding particles
        @EventHandler
        public void onMove(ProjectileLaunchEvent event) {
            Entity ent = event.getEntity();
            Location loc = ent.getLocation();
            Player player = (Player) event.getEntity().getShooter();
            // Reoccuring particle effect
            Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
                public void run() {
                    if (list.contains(player.getName())) {
                        ent.playEffect(EntityEffect.WOLF_SMOKE);
                        }
                    }
                }, 1, 1);
            }
      
        //Commands
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if (cmd.getLabel().equalsIgnoreCase("Particle")) {
                Player player = (Player) sender;
                ParticleEffect.CRIT.display(10, 15, 0, 0, 0, player.getLocation(), 10);
                return true;
            }
            return false;
        }
    }
    
    And for someone who said something about the gadget
    class it does extend javaplugin

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 7, 2016
  11. Offline

    N00BHUN73R

    @Nick_Titan
    You didn't fix half of the things wrong that
    @Zombie_Striker pointed out.
    The code looks pretty much the exact same from before you "revised" it.

    He also told you exactly how to make the particles, yet I don't see any of the things he said you should try?
     
Thread Status:
Not open for further replies.

Share This Page