Solved Adding Metadata to projectiles problem

Discussion in 'Plugin Development' started by BlackKnight625, May 27, 2015.

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

    BlackKnight625

    Hello, I'm BlackKnight625 and I wanted to make a Splash Potion of Harming to blow up as soon as it touched the ground (or an Entity) but I don't want to make all of the Harming potions to explode. Only those that have a DisplayName as such: "Grenade". I searched on how to add metadata to Objects so that I could add Metadata as soon as the Player launched the "Grenade", with the ProjectileLaunchEvent and check for Metadata when the projectile (Potion) hit something, with the PotionSplashEvent. Here's what I tried to do:

    Code:
    private JavaPlugin plugin;
    
    @EventHandler
    public void projectileLaunchEvent(ProjectileLaunchEvent e) {
    if (e.getEntity().getShooter() instanceof Player) {
                Player p = (Player) e.getEntity().getShooter();
    if (e.getEntity() instanceof ThrownPotion) {
                    if (p.getItemInHand().getItemMeta().getDisplayName().contains("Grenade")) {
                        e.getEntity().setMetadata("Explosive", new FixedMetadataValue(plugin, "Lalala"));
                    }
                }
            }
    }
    
    @EventHandler
        public void onSplash(PotionSplashEvent e){
            ThrownPotion potion = e.getEntity();
            @SuppressWarnings("deprecation")
            Player p = (Player) e.getEntity().getShooter();   
                if (potion.hasMetadata("Explosive")) {
                    Location loc = e.getEntity().getLocation();
                    e.getEntity().getWorld().createExplosion(loc.getX(), loc.getY(), loc.getZ(), 3, false, false);
                }     
        }
    I tried it and when I launched the potion nothing happened..... the only solution I got was to use passengers:
    Code:
    @SuppressWarnings("deprecation")
       @EventHandler
       public void projectileLaunchEvent(ProjectileLaunchEvent e) {
         if (e.getEntity().getShooter() instanceof Player) {
           Player p = (Player) e.getEntity().getShooter();
         
           if (e.getEntity() instanceof ThrownPotion) {
             if (p.getItemInHand().getItemMeta().getDisplayName().contains("Grenade")) {
               e.getEntity().setPassenger(p.getWorld().spawnEntity(p.getLocation(), EntityType.SNOWBALL));
             }
           }  
         }
       } 
    @EventHandler
       public void onSplash(PotionSplashEvent e){
        ThrownPotion potion = e.getEntity();
        @SuppressWarnings("deprecation")
         Player p = (Player) e.getEntity().getShooter();  
        if (potion.getPassenger() instanceof Snowball) {
           Location loc = e.getEntity().getLocation();
             e.getEntity().getWorld().createExplosion(loc.getX(), loc.getY(), loc.getZ(), 3, false, false);
        }  
       }
    Do any of you guys know what I'm doing wrong?

    Thankyou for your attention.
     
  2. From the code, I see that this should work. Have you checked if PotionSplashEvent is being called? Or maybe, ProjectileLaunchEvent is called after the splash potion is removed from the player's hand, thus the item in the player's hand is air/null.

    Have you got any errors in the console?

    Also, a few constructive criticism points:
    • The item in the player's hand could be null if my point in the beginning of my sentence is correct.
    • In PotionSplashEvent, you didn't check if the shooter is a player, you instantly casted it assuming it was a player.

    I'll test this on my own LAN server if no one else solves this before I'm done.

    Code:
        @EventHandler
        public void onProjectileLaunch(ProjectileLaunchEvent event) {
            if (event.getEntity().getShooter() instanceof Player) {
                if (event.getEntity() instanceof ThrownPotion) {
                    Player player = (Player) event.getEntity().getShooter();
                    if (player.getItemInHand() != null) {
                        ItemMeta itemMeta = player.getItemInHand().getItemMeta();
                        if (itemMeta != null && itemMeta.hasDisplayName() && itemMeta.getDisplayName().contains("Grenade")) {
                            event.getEntity().setMetadata("Explosive", new FixedMetadataValue(this, true));
                        }
                    }
                }
            }
        }
    
        @EventHandler
        public void onPotionSplash(PotionSplashEvent event) {
            ThrownPotion potion = event.getEntity();
            if (potion.hasMetadata("Explosive")) {
                Location potionLocation = event.getEntity().getLocation();
                event.getEntity().getWorld().createExplosion(potionLocation.getX(), potionLocation.getY(), potionLocation.getZ(), 3, false, false);
            }
        }
    
    Working code for me, at least.

    Pretty much the same thing, just made sure to check if the item is not null, has an item meta and display name. It also removes the useless 'player' object in the PotionSplashEvent.
     
    Last edited: May 27, 2015
  3. Offline

    Agentleader1

    I would recommend making an event that tests for potion thrown, then attach the potion's String version of UUID to a HashMap, and setting it's value to it's ItemMeta name. Make sure the HashMap is declared in the class, and not in a local method (private or public)

    For example:
    Code:
    grenades.put(potion.getUniqueId().toString(), player.getInventory().getItemInHand().getItemMeta().getDisplayName()); //potion is the entity
    You can use a different method to get the name of the item.
    But it would be a lot easier in PlayerInteractEvent.
     
  4. Offline

    BlackKnight625

    Well, yes, my Events are getting called, I tested it by putting an e.getEntity().getShooter().sendMessage("Hi"); in the middle of the code. Yes, it gave out an error at line 10 (in your code, line 9 on my code). It looks like that it's having troubles at setting the metadata on the object, but it's not because I forgot to check if the shooter was a Player. I'll test it again with your code version and I'll see what happens. Thankyou.

    EDIT: Interesting.... It's working! I don't seem to know where my error was, but it's working now! Thankyou for your help :D
     
    Last edited: May 28, 2015
    KingFaris11 likes this.
Thread Status:
Not open for further replies.

Share This Page