Custom Potion Effects

Discussion in 'Resources' started by stirante, Oct 9, 2012.

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

    stirante

    Don't use this class, this is handled by API now.

    In snapshot 12w39a you can add mulitple potion effects with custom amplifier and duration by editing NBT. I created a class that adds this effects to potions. So if you want to add to potion custom effect you will have to do something like this:
    Code:
    player.setItemInHand(CustomPotions.addCustomEffect(player.getItemInHand(), PotionEffectType.FAST_DIGGING, 10, 1200));
    
    Code above will add effect Haste with power 10 for minute.

    CustomPotions class:
    Code:
    package com.stirante.NBTTagAPI;
     
    import java.util.ArrayList;
     
    import net.minecraft.server.NBTTagCompound;
    import net.minecraft.server.NBTTagList;
     
    import org.bukkit.craftbukkit.inventory.CraftItemStack;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.potion.PotionEffectType;
     
    public class CustomPotions {
       
        private static CraftItemStack                    craftStack;
        private static net.minecraft.server.ItemStack    itemStack;
       
        public static ItemStack addCustomEffect(ItemStack item, PotionEffectType type, int amplifier, int duration) {
            if (item instanceof CraftItemStack) {
                craftStack = (CraftItemStack) item;
                CustomPotions.itemStack = craftStack.getHandle();
            }
            else if (item instanceof ItemStack) {
                craftStack = new CraftItemStack(item);
                CustomPotions.itemStack = craftStack.getHandle();
            }
            NBTTagCompound tag = itemStack.tag;
            if (tag == null) {
                tag = new NBTTagCompound();
                tag.set("CustomPotionEffects", new NBTTagList());
                itemStack.tag = tag;
            }
            tag = new NBTTagCompound();
            tag.setByte("Id", (byte) type.getId());
            tag.setByte("Amplifier", (byte) amplifier);
            tag.setInt("Duration", duration);
            ((NBTTagList)itemStack.tag.get("CustomPotionEffects")).add(tag);
            return craftStack;
        }
       
        public static CustomEffect[] getCustomEffects(ItemStack item) {
            if (item instanceof CraftItemStack) {
                craftStack = (CraftItemStack) item;
                CustomPotions.itemStack = craftStack.getHandle();
            }
            else if (item instanceof ItemStack) {
                craftStack = new CraftItemStack(item);
                CustomPotions.itemStack = craftStack.getHandle();
            }
            NBTTagCompound tag = itemStack.tag;
            if (tag == null) {
                return null;
            }
            NBTTagList list = (NBTTagList) itemStack.tag.get("CustomPotionEffects");
            ArrayList<CustomEffect> effects = new ArrayList<CustomEffect>();
            for (int i = 0; i < list.size(); i++) {
                effects.add(new CustomEffect(PotionEffectType.getById(((NBTTagCompound)list.get(i)).getByte("Id")), ((NBTTagCompound)list.get(i)).getByte("Amplifier"), ((NBTTagCompound)list.get(i)).getInt("Duration")));
            }
            CustomEffect[] array = new CustomEffect[]{};
            effects.toArray(array);
            return array;
        }
    }
     
    
    CustomEffect class:
    Code:
    package com.stirante.NBTTagAPI;
     
    import org.bukkit.potion.PotionEffectType;
     
    public class CustomEffect {
        private PotionEffectType    type;
        private int    amplifier;
        private int    duration;
     
        public CustomEffect(PotionEffectType type, int amplifier, int duration){
            this.setType(type);
            this.setAmplifier(amplifier);
            this.setDuration(duration);
        }
     
        public PotionEffectType getType() {
            return type;
        }
     
        public void setType(PotionEffectType type) {
            this.type = type;
        }
     
        public int getAmplifier() {
            return amplifier;
        }
     
        public void setAmplifier(int amplifier) {
            this.amplifier = amplifier;
        }
     
        public int getDuration() {
            return duration;
        }
     
        public void setDuration(int duration) {
            this.duration = duration;
        }
    }
     
    
    If there will be more usefull things added to NBT maybe I will create some API if you want.
     
  2. Offline

    stirante

    Code tested and working :)
    Btw can someone tell me what's wrong with this code:
    Code:java
    1.  
    2. for (PotionEffectType type : PotionEffectType.values()) {
    3. if (type.getName().equalsIgnoreCase(args[0])){
    4. potionType = type;
    5. }
    6. }
    7.  

    I got NullPointerException at line with "if".
     
  3. Offline

    reddy360

    I'm guessing that type.getName() is giving you the NullPointerException
     
  4. Offline

    stirante

    But toString also gives null.
     
  5. Offline

    reddy360

    If you are calling toString() on the type.getName() you are trying to get a String of a null value
     
  6. Offline

    stirante

    I tried to get type.toString(), but it throws NullPointerException.
     
  7. What is wrong with this code? It works, but it overrides all custom potion info I added earlier :/ .
    I tried not to copy yours but create it with Data from NBTExplorer...

    Code:
        private CraftItemStack addCustomPotionEffect(CraftItemStack item, int id, int level, int duration){
            NBTTagCompound itag = item.getHandle().tag;
            if (itag == null) {
                NBTTagCompound nitag = new NBTTagCompound();
                nitag.set("CustomPotionEffects", new NBTTagList());
                itag = nitag;
            }
            NBTTagList CustomPotionEffects = new NBTTagList();
            try{CustomPotionEffects = itag.getList("CustomPotionEffects");}
            catch(NullPointerException e){System.out.println("no custom potion info");}
            NBTTagCompound pottag = new NBTTagCompound();
            NBTTagByte Amplifier = new NBTTagByte("Amplifier",(byte)(level-1));
            NBTTagByte Id = new NBTTagByte("Id", (byte)id);
            NBTTagInt Duration = new NBTTagInt("Duration", duration);
            itag.set("CustomPotionEffects", CustomPotionEffects);
            pottag.set("Amplifier", Amplifier);
            pottag.set("Id", Id);
            pottag.set("Duration", Duration);
            CustomPotionEffects.add(pottag);
            item.getHandle().setTag(itag);
            return item;
        }
     
  8. Offline

    doomboy00

    I'm not sure if this has been updated to the latest version on any git anywhere (at the time of this reply: 1.4.6), but I couldn't find it when I was looking for a way to do this (and once again I come across stirante posting this cool stuff), but here is an update to the addCustomPotionEffect function that is working for me for anyone who wants to add custom effects to their potions:

    Code:
    public static ItemStack addCustomPotionEffect(ItemStack item, PotionEffectType type, int amplifier, int duration) {
            net.minecraft.server.v1_4_6.ItemStack nmsStack = CraftItemStack.asNMSCopy(item);
     
            NBTTagCompound tag = null;
            if (!nmsStack.hasTag()) {
                tag = new NBTTagCompound();
                nmsStack.setTag(tag);
            }
            if (tag == null) tag = nmsStack.getTag();
       
            NBTTagList CustomPotionEffects= null;
            if(!tag.hasKey("CustomPotionEffects"))
            {
                CustomPotionEffects = new NBTTagList();
                tag.set("CustomPotionEffects", CustomPotionEffects);
            }
            if(CustomPotionEffects == null) CustomPotionEffects = tag.getList("CustomPotionEffects");
       
            NBTTagCompound CustomPotionEffect = new NBTTagCompound();
       
            CustomPotionEffect.setByte("Id", (byte) type.getId());
            CustomPotionEffect.setByte("Amplifier", (byte) amplifier);
            CustomPotionEffect.setInt("Duration", duration);
       
            CustomPotionEffects.add(CustomPotionEffect);
       
            tag.set("CustomPotionEffects",CustomPotionEffects);
     
            nmsStack.setTag(tag);
     
            return CraftItemStack.asCraftMirror(nmsStack);
        }
    and an example of how to use it:

    Code:
    ItemStack item = new ItemStack(Material.POTION,1);
    Potion potion = new Potion(PotionType.STRENGTH);
           
    potion.setSplash(true);
    potion.setLevel(2);
    potion.apply(item);
     
    item = addCustomPotionEffect(item, PotionEffectType.INCREASE_DAMAGE, 1, 680);
    Note: The above creates a Strength 2 splash potion but with 34 seconds duration instead of 1:07.
     
  9. Offline

    Comphenix

    You can actually do this without referencing CraftBukkit at all, using the new Item Meta system:
    Code:java
    1. ItemStack stack = new Potion(PotionType.STRENGTH).toItemStack(1);
    2. PotionMeta meta = (PotionMeta) stack.getItemMeta();
    3.  
    4. meta.addCustomEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 680, 1), true);
    5. stack.setItemMeta(meta);
    6.  
    7. target.getInventory().addItem(stack);
     
    joserobjr and doomboy00 like this.
  10. Offline

    doomboy00

    Ah derp, I should have checked for this :p Thanks for the info
     
  11. Offline

    stirante

    Thats why I don't update code on github and here. I think this thread should be removed.
     
Thread Status:
Not open for further replies.

Share This Page