Solved Fireballs that don't do block damage

Discussion in 'Spigot Plugin Development' started by ShadowMasterG23, May 30, 2017.

  1. So, I'm making a plugin that allows players to spawn fireballs when they right click a stick. The only issue I have is that when the fireball hits something, it breaks everything around it. I know that's how fireballs work, but I don't want them to break the terrain. I have searched the interwebs for a solution, but all other suggestions aren't working, or maybe I'm just stupid.

    Here is my Listener Class:
    Code (Text):

    package me.ShadowMaster23;

    import java.util.ArrayList;

    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.Material;
    import org.bukkit.entity.Fireball;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.EventPriority;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.entity.EntityExplodeEvent;
    import org.bukkit.event.entity.ExplosionPrimeEvent;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.ItemMeta;
    import org.bukkit.metadata.FixedMetadataValue;
    import org.bukkit.util.Vector;

    public class BoomstickListener implements Listener {

        private Boomstick plugin;

        public BoomstickListener(Boomstick plugin) {
            this.plugin = plugin;
            plugin.getServer().getPluginManager().registerEvents(this, plugin);
        }

        ArrayList<String> playersOnCooldown = new ArrayList<String>();

        @SuppressWarnings("deprecation")
        @EventHandler(priority=EventPriority.MONITOR)
        public void onPlayerClick(PlayerInteractEvent event) {
            Player player = event.getPlayer();

            if ((event.getAction() != Action.RIGHT_CLICK_AIR) && (event.getAction() != Action.RIGHT_CLICK_BLOCK)) {
                return;
            }

            if (event.getAction().equals(Action.RIGHT_CLICK_AIR) || event.getAction().equals(Action.RIGHT_CLICK_BLOCK)) {
                ItemStack item = event.getPlayer().getItemInHand();
                ItemMeta meta = item.getItemMeta();

                if (!item.getItemMeta().hasLore()) {
                    return;
                }

                if (item.getType() == Material.getMaterial(plugin.getConfig().getString("stick.material"))) {
                    if (playersOnCooldown.contains(player.getName())) {
                        player.sendMessage(ChatColor.RED + "You must wait 5 seconds before firing again!");
                        return;
                    }

                    if (!this.plugin.getConfig().getBoolean("settings.allow_right_click_to_use_sticks", true)) {
                        return;
                    }

                    if (item.getItemMeta().getDisplayName().contains("Staff")) {
                        if (meta.getLore().toString().contains("Fire")) {
                            Fireball fire = player.getWorld().spawn(event.getPlayer().getLocation().add(new Vector(0.0D, 1.0D, 0.0D)), Fireball.class);
                            fire.setMetadata("Data Name", new FixedMetadataValue(plugin,"Data Value"));
                            fire.setFireTicks(0);
                            fire.setShooter(player);
                            fire.setIsIncendiary(false);
                            playersOnCooldown.add(player.getName());
                            Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this.plugin, new Runnable() {
                                public void run() {
                                    playersOnCooldown.remove(player.getName());
                                }
                            }, 5 * 20);
                            player.sendMessage(ChatColor.translateAlternateColorCodes('&', plugin.getConfig().getString("messages.stick_used")));
                        } else {
                            player.sendMessage(ChatColor.translateAlternateColorCodes('&', plugin.getConfig().getString("messages.invalid_stick")));
                        }
                    } else {
                        player.sendMessage(ChatColor.translateAlternateColorCodes('&', plugin.getConfig().getString("messages.invalid_stick")));
                    }
                }
            }
        }

        public void onFireballExplode(EntityExplodeEvent event) {
            if (event.getEntity() instanceof Fireball) {
                if (event.getEntity().hasMetadata("Data Name") || event.getEntity().hasMetadata("Data Value")){
                    event.setCancelled(true);
                }
            }
        }

        //public void onFireballExplosion(ProjectileHitEvent event) {
        //if (event.getEntity() instanceof Fireball) {
        //if (event.getEntity().hasMetadata("Data Name")){
        //((Cancellable) event).setCancelled(true);
        //}
        //}
        //}

        //public void onFireballExplosion2(EntityDamageByEntityEvent event) {
        //if (event.getEntity() instanceof Fireball) {
        //if (event.getEntity().hasMetadata("Data Name")){
        //event.setCancelled(true);
        //}
        //}
        //}

        public void onExplosionPrime(ExplosionPrimeEvent event) {
            event.setFire(false); //Only really needed for fireballs

            if (event.getEntity() instanceof Fireball) {
                if (event.getEntity().hasMetadata("Data Name") || event.getEntity().hasMetadata("Data Value")){
                    event.setCancelled(true);
                }
            }
        }
    }

     
    I know that setYield(0) will negate the block damage, but it will also negate the players from being damaged and I want for players to be damaged by the fireballs. I tried to add metadata to the fireball so that I could target it in specific, but it didn't work. Or perhaps I used it wrong. I think that the event that I'm listening for could be wrong. I've tried different events to listen to, as you can see in the code, but they didn't work either. This is racking my brain. Could someone please explain what I am doing wrong?

    Misc:
    I'm coding using Java 8

    Note: I am relatively new to Java. You might be able to tell by the way I code, but nevertheless, I'm slowly learning, so if I respond asking you to define the terminology you used, don't be surprised. :p
     
  2. Choco

    Moderator

    I know you're new, and to be completely honest, you're doing great for being new; I'm still going to go ham on you though... so bare with me

    This can technically be final. It adds no extra functionality, but it just assures that this value will never be changed

    2 things here...
    1. You don't need to provide the type in the second diamond brackets. The compiler will infer that for you as of Java 7
    2. You should be using implementation types.
    Final line: List<String> playersOnCooldown = new ArrayList<>();

    You should NEVER modify anything in an event listener of priority MONITOR. This priority is for those that require to listen and only read final information (i.e. chat logger plugins). The base priority may be better suited. Just have @EventHandler without any parameters

    This if statement is completely useless because you already made a check before that returns if neither of these actions are being performed. You can just completely remove this if statement ^-^ Also, you're using .equals(), where you should be using == to compare constants instead. Looks like you did it above, so perhaps this was just a typo.

    This is deprecated in Spigot 1.9+, and its replacement is player.getInventory().getItemInMainHand(). Alternatively you can invoke player.getInventory().getItemInOffHand() to get the item in their secondary hand.

    If I'm not mistaken, these are default values for fireballs, so they're unnecessary.

    It may be better to title these with more definitive values such as a key of "SpellFireball" and an identical value. Something unique that may not be easily mixed up with another plugin ^-^

    This event is pretty useless. You had the right event above, EntityExplodeEvent. The event you're listening to here is mainly for entities being ignited (i.e. TNT with fire arrows or flint and steel)

    Everything else seems to work fine. If you clear everything else up, print out some values in your event to make sure everything is working as intended. Perhaps it's not even firing, or the values just aren't correct. Always nice to learn to debug properly in order to diagnose your own problems ^-^ You're doing a fantastic job for a beginner though. We see some pretty bad programmers on a daily basis on here who are just starting out
     
    • Like Like x 1
    • Winner Winner x 1
    • Friendly Friendly x 1
  3. Alright, first off, thanks for the tips. :3 I thought that the
    "if ((event.getAction() != Action.RIGHT_CLICK_AIR) && (event.getAction() != Action.RIGHT_CLICK_BLOCK))" would make it to where I didn't need the "if (event.getAction().equals(Action.RIGHT_CLICK_BLOCK))" but I didn't test it.

    Second, I changed what you suggested and everything still works, but my issue is still here. I don't want for blocks to be broken when the fireball hits them. Here's the revised code:
    Code (Text):

    package me.ShadowMaster23;

    import java.util.ArrayList;

    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.Material;
    import org.bukkit.entity.Fireball;
    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.entity.EntityExplodeEvent;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.ItemMeta;
    import org.bukkit.metadata.FixedMetadataValue;
    import org.bukkit.util.Vector;

    public class BoomstickListener implements Listener {

        private final Boomstick plugin;

        public BoomstickListener(Boomstick plugin) {
            this.plugin = plugin;
            plugin.getServer().getPluginManager().registerEvents(this, plugin);
        }

        ArrayList<String> playersOnCooldown = new ArrayList<>();

        @EventHandler
        public void onPlayerClick(PlayerInteractEvent event) {
            Player player = event.getPlayer();

            if ((event.getAction() != Action.RIGHT_CLICK_AIR) && (event.getAction() != Action.RIGHT_CLICK_BLOCK)) {
                return;
            }
                ItemStack item = event.getPlayer().getInventory().getItemInMainHand();
                ItemMeta meta = item.getItemMeta();

                if (!item.getItemMeta().hasLore()) {
                    return;
                }

                if (item.getType() == Material.getMaterial(plugin.getConfig().getString("stick.material"))) {
                    if (playersOnCooldown.contains(player.getName())) {
                        player.sendMessage(ChatColor.RED + "You must wait 5 seconds before firing again!");
                        return;
                    }

                    if (!this.plugin.getConfig().getBoolean("settings.allow_right_click_to_use_sticks", true)) {
                        return;
                    }

                    if (item.getItemMeta().getDisplayName().contains("Staff")) {
                        if (meta.getLore().toString().contains("Fire")) {
                            Fireball fire = player.getWorld().spawn(event.getPlayer().getLocation().add(new Vector(0.0D, 1.0D, 0.0D)), Fireball.class);
                            fire.setMetadata("FireballSpell", new FixedMetadataValue(plugin,"Explosions!"));
                            fire.setFireTicks(0);
                            fire.setShooter(player);
                            fire.setIsIncendiary(false);
                            playersOnCooldown.add(player.getName());
                            Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this.plugin, new Runnable() {
                                public void run() {
                                    playersOnCooldown.remove(player.getName());
                                }
                            }, 5 * 20);
                            player.sendMessage(ChatColor.translateAlternateColorCodes('&', plugin.getConfig().getString("messages.stick_used")));
                        } else {
                            player.sendMessage(ChatColor.translateAlternateColorCodes('&', plugin.getConfig().getString("messages.invalid_stick")));
                        }
                    } else {
                        player.sendMessage(ChatColor.translateAlternateColorCodes('&', plugin.getConfig().getString("messages.invalid_stick")));
                    }
                }
         
        }

        public void onFireballExplode(EntityExplodeEvent event) {
            if (event.getEntity() instanceof Fireball) {
                if (event.getEntity().hasMetadata("FireballSpell") || event.getEntity().hasMetadata("Explosions!")){
                    event.setCancelled(true);
                }
            }
        }
    }
    I'm not sure what the problem is. This should work, but it doesn't. Perhaps it's because these are in the same class. I'm pretty sure the problem is with the event listener. The fireballs spawn in just fine, but the fireballs keep breaking the terrain. Do you have any suggestions on how to fix it?
     
  4. Choco

    Moderator

    When you're referencing #setYield() here, are you referring to Fireball#setYield() or EntityExplodeEvent#setYield(). If you haven't yet tried Fireball#setYield(), it should only prevent the amount of blocks that are damaged. Though I may be wrong

    EDIT: Nevermind. You're missing an @EventHandler annotation over your second listener method there :p
     
    • Friendly Friendly x 1
  5. Wow, I'm dumb. :p It works now.
     
  6. Thank you for your help. I can't believe I forgot that EventHandle annotation though. :p Oh well, live and learn I guess.
     
    • Friendly Friendly x 2
  7. Choco

    Moderator

    Glad I could help! Keep up the great work. You're doing just fine as a beginner. Be sure to title this thread as Solved! (Thread options)
     
    • Friendly Friendly x 3