Solved Random Drop

Discussion in 'Plugin Development' started by Sicka_gp, Mar 26, 2013.

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

    Sicka_gp

    Hi, I would like to do a class on a random drop with percentage chance to drop.
    For example:
    Diamond = 0.01%
    MobEgg = 0.02% (Random sheep, pig, wofl, cow ..)
    Gunpowder = 2%
    EXP Bottle = 1%
    etc.
    I have this code and the error somewhere, because I just fall Gunpowder.
    Please help or advice about how to do it .. thank you

    Code:
    @EventHandler
        public void breakblock1(BlockBreakEvent e) {
            Random random = new Random();
            int randomInt = random.nextInt(100);
            int randomInt2 = random.nextInt(5);
            if(e.isCancelled()) return;
            int blockDropChance = 1;
            float blockDropChance2 = 0.01f;
            float blockDropChance3 = 0.02f;
            int blockDropChance4 = 1;
            int blockDropegg = 1;
     
            Block block = e.getBlock();
            World world = block.getWorld();
            if (block.getType() == Material.DIRT || block.getType() == Material.STONE ||block.getType() == Material.GRASS || block.getType() == Material.SAND || block.getType() == Material.SANDSTONE) {
                if(randomInt <= blockDropChance){
                    ItemStack drop = new ItemStack(block.getTypeId(), 1);
                    ItemStack drop2 = new ItemStack(289, 1);
     
                    world.dropItemNaturally(block.getLocation(), drop);
                    world.dropItemNaturally(block.getLocation(), drop2);   
                }
                else if(randomInt <= blockDropChance2){
                    ItemStack drop = new ItemStack(block.getTypeId(), 1);
                    ItemStack drop2 = new ItemStack(Material.DIAMOND, 1);
     
                    world.dropItemNaturally(block.getLocation(), drop);
                    world.dropItemNaturally(block.getLocation(), drop2);   
                }
                else if(randomInt <= blockDropChance3){
                    if (randomInt2 <= blockDropegg){
                        ItemStack drop2 = new ItemStack(383, 1, (byte)90);
                        world.dropItemNaturally(block.getLocation(), drop2);
                    }
                    else if (randomInt2 <= blockDropegg){
                        ItemStack drop2 = new ItemStack(383, 1, (byte)91);
                        world.dropItemNaturally(block.getLocation(), drop2);
                    }
                    else if (randomInt2 <= blockDropegg){
                        ItemStack drop2 = new ItemStack(383, 1, (byte)92);
                        world.dropItemNaturally(block.getLocation(), drop2);
                    }
                    else if (randomInt2 <= blockDropegg){
                        ItemStack drop2 = new ItemStack(383, 1, (byte)95);
                        world.dropItemNaturally(block.getLocation(), drop2);
                    }
                    else if (randomInt2 <= blockDropegg){
                        ItemStack drop2 = new ItemStack(383, 1, (byte)96);
                        world.dropItemNaturally(block.getLocation(), drop2);
                    }
                   
                    ItemStack drop = new ItemStack(block.getTypeId(), 1);
                    world.dropItemNaturally(block.getLocation(), drop);   
                }
                else if(randomInt <= blockDropChance4){
                    ItemStack drop = new ItemStack(block.getTypeId(), 1);
                    ItemStack drop2 = new ItemStack(Material.EXP_BOTTLE, 1);
     
                    world.dropItemNaturally(block.getLocation(), drop);
                    world.dropItemNaturally(block.getLocation(), drop2);   
                }   
            }
        }
     
  2. Offline

    nitrousspark

    i created a random number 0 - 100 then checked if the number was less than the percentage i wanted, drop the item
    so, this

    Code:
    i is the random number 0-100
    if (i < 10) {
    //do something
    }
    10 is the percentage
    so it would have a %10 chance to do/drop the item
     
  3. Offline

    Technius

    A lazy way would be to populate a list with your items, and then use a random number generator to get an item at a random index.

    Code:
    ArrayList<ItemStack> droplist = new ArrayList<ItemStack>();
     
    //Add your items...
     
    ItemStack youritem = droplist.get(new Random().nextInt(droplist.size()));
    
    There are other ways to do this, though.
     
  4. Offline

    chylex

    I'd go for a weighted list, which is a list where each item has a certain weight, more weight = bigger chance of the item being chosen.

    Code:
    public class WeightedList<K> extends HashMap<K,Integer>{
        private int total;
     
        @Override
        public Integer put(K a, Integer b){
            Integer i=super.put(a,b);
            total=0;
            for(Integer in:values()){
                total+=in;
            }
            return i;
        }
     
        public K get(Random rand){
            if (total<=0)return null;
            int i=rand.nextInt(total);
            for(Entry<K,Integer> entry:entrySet()){
                i-=entry.getValue();
                if (i<0)return entry.getKey();
            }
            return null;
        }
    }
    
    Try to understand how it works - a random number between 0 and sum of all items' weights is generated, then it goes through each item and decreases its weight from the number. Once it gets below 0, current item is returned.

    You can use it like this:
    Code:
    WeightedList<ItemStack> list = new WeightedList<ItemStack>();
    list.put(new ItemStack(Material.GUNPOWDER),200);
    list.put(new ItemStack(Material.DIAMOND),1);
    ItemStack chosenItem = list.get(new Random());
    Note: percentages between 0% and 1% will not work, so 0.01% is in this case 1, and 2% is 200.
     
  5. Offline

    Sicka_gp

    It does not work to me, in destroying Block drop me SULPHUR..
    It's falling after each destruction..

    Here, it reports an error:
    "The serializable class WeightedList does not declare a static final serialVersionUID field of type long"
    Code:
    import java.util.HashMap;
    import java.util.Random;
     
    public class WeightedList<K> extends HashMap<K,Integer>{
        private int total;
     
        @Override
        public Integer put(K a, Integer b){
            Integer i=super.put(a,b);
            total=0;
            for(Integer in:values()){
                total+=in;
            }
            return i;
        }
     
        public K get(Random rand){
            if (total<=0)return null;
            int i=rand.nextInt(total);
            for(java.util.Map.Entry<K, Integer> entry:entrySet()){
                i-=entry.getValue();
                if (i<0)return entry.getKey();
            }
            return null;
        }
    }
    
    Code:
    import java.util.Random;
     
    import org.bukkit.Material;
    import org.bukkit.World;
    import org.bukkit.block.Block;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.BlockBreakEvent;
    import org.bukkit.inventory.ItemStack;
     
    public class BreakeBlock implements Listener {
        public static GameparkMessages plugin;
        public WeightedList<ItemStack> list = new WeightedList<ItemStack>();
     
        public BreakeBlock(GameparkMessages instance) {
            plugin = instance;
        }
     
        @EventHandler
        public void breakblock(BlockBreakEvent event) {
            Block block = event.getBlock();
            World world = block.getWorld();
            list.put(new ItemStack(Material.SULPHUR),200);
            list.put(new ItemStack(Material.DIAMOND),1);
            ItemStack chosenItem = list.get(new Random());
            if(block.getType() == Material.LOG){
                world.dropItemNaturally(block.getLocation(), chosenItem);
            }
         
        }
    }
     
  6. Offline

    chylex

    For the first problem, just click on the warning icon, and click Add generated serial version UID or something like that. The second code was an example of usage, sorry I missed that you wouldn't want to drop an item every single time but there's a very easy fix - just add an itemstack that'll have Material.AIR, and very big weight (let's say 9800), and once you have the chosenItem, only drop the item if it isn't air.
     
  7. Offline

    Sicka_gp

    Code:
    @EventHandler
        public void breakblock(BlockBreakEvent event) {
            Block block = event.getBlock();
            World world = block.getWorld();
            list.put(new ItemStack(Material.AIR),9799);
            list.put(new ItemStack(Material.SULPHUR),200);
            list.put(new ItemStack(Material.DIAMOND),1);
            ItemStack chosenItem = list.get(new Random());
            if(block.getType() == Material.LOG){
                if(chosenItem.getType() != Material.AIR){
                    world.dropItemNaturally(block.getLocation(), chosenItem);
                }
            }
           
        }
    Thank you very much :) works
     
  8. Offline

    chylex

    I just noticed the list isn't declared in the function, if you have it static or declared in the constructor, add the items there instead of in the event, so the plugin doesn't have to do unnecessary work every time someone breaks a block ;)
     
  9. Offline

    Sicka_gp

    Could you give me an example?
     
  10. Offline

    chylex

    Code:
    public class BreakeBlock implements Listener {
        public static GameparkMessages plugin;
        public WeightedList<ItemStack> list = new WeightedList<ItemStack>();
     
        public BreakeBlock(GameparkMessages instance) {
            plugin = instance;
            list.put(new ItemStack(Material.AIR),9799);
            list.put(new ItemStack(Material.SULPHUR),200);
            list.put(new ItemStack(Material.DIAMOND),1);
        }
     
        @EventHandler
        public void breakblock(BlockBreakEvent event) {
            Block block = event.getBlock();
            World world = block.getWorld();
            // moved list.put(...) above
            ItemStack chosenItem = list.get(new Random());
            if(block.getType() == Material.LOG){
                world.dropItemNaturally(block.getLocation(), chosenItem);
            }
        }
    }
    
     
  11. Offline

    Sicka_gp

    Thank you very much :):)
     
Thread Status:
Not open for further replies.

Share This Page