Custom potions

Discussion in 'Spigot Plugin Development' started by NubeBuster, Jul 10, 2018.

  1. I am trying to make potions with custom effects.
    I found a big workaround with metadata because the api is not really friendly.
    I am trying to add metadata to the flying splash potion as they are thrown. It works in creative mode because I can get the lore from the item, but in survival mode the potion is removed from the inventory before I can get the potion data.
    Here is a screen shot:
    and the code:
    Code (Java):
        public void onClick(PotionSplashEvent event) {
            if (event.getPotion().hasMetadata("effect")) {
                for (MetadataValue value : event.getPotion().getMetadata("effect")) {
                    String s = (String) value.value();
                    String[] dat = s.split(" ");
                    PotionEffectType type = PotionEffectType.getByName(dat[0].toUpperCase());
                    int length = Integer.parseInt(dat[1]), lvl = Integer.parseInt(dat[4]);
                    for (Entity e : event.getAffectedEntities())
                        if (e instanceof Player)
                            ((Player) e).addPotionEffect(new PotionEffect(type, length * 20, lvl - 1));

        public void onThrow(ProjectileLaunchEvent event) {
            if (!(event.getEntity() instanceof SplashPotion))
            if (!(event.getEntity().getShooter() instanceof Player))

            Player p = (Player) event.getEntity().getShooter();
            ItemStack it = p.getItemInHand();

            if (it != null && it.getType() == Material.SPLASH_POTION) {
                ItemStack item = it;
                if (!item.hasItemMeta())

                for (String s : item.getItemMeta().getLore()) {
                    if (s.contains("seconds lvl: ")) {
                        event.getEntity().setMetadata("effect", new FixedMetadataValue(, s));
    above the "RIGHT HERE" comment is the line with the problem. In survival mode the potion is used up before I can get its data. How do I do this properly? ItemConsumeEvent? Or something else?
  2. I notice you suppress the deprecation warning for p.getItemInHand(). If you're coding for 1.9+, the method was replaced by p.getInventory().getItemInMainHand();
    Perhaps you could use the PlayerInteractEvent, get the item from PlayerInteractEvent#getItem(), then pass it to your other event listener?
    • Like Like x 1
  3. How would I pass the item safely?

    PS thanks for the iteminhand notice
  4. You have thrown the potion in survival mode, thats why you can't get the item in the players hand, because its nothing. In creative the potions are not thrown, thus you can get the item in hand. Try do 'e.setCancelled(true);' and make a new potion to throw.
  5. That wont work as it just 'refunds' the item back into the inventory after the event is handled
    #5 NubeBuster, Jul 10, 2018
    Last edited: Jul 10, 2018
  6. Just remove it then. Get the player inventory and remove that potion
  7. But that is not the problem. I am trying to get the potion item in the first place...

    (it refunds the potion item after the event is handled
  8. Cancel the event,
    get the potion item,
    clear the item from their inventory.
  9. Then the throw event is cancelled... also how do I trigger the code when the event is cancelled
  10. It will still run all the code after the event is cancelled. If you want it in another void you could do 'this.voidName(Parameter param);' and run the rest of the code in another void. Also, you could create a new potion entity to throw.
  11. The potion is not in the inventory while the event is run. Therefore I cannot use the item in the hand.
    • Useful Useful x 1
  12. Use PlayerInteractEvent to detect a splash potion throw.
  13. One approach would be firing a bukkit runnable foe the next tick.