001    package net.minecraftforge.common;
002    
003    import java.util.ArrayList;
004    import java.util.Random;
005    
006    import net.minecraft.item.Item;
007    import net.minecraft.item.ItemStack;
008    import net.minecraft.util.WeightedRandom;
009    import net.minecraft.util.WeightedRandomItem;
010    
011    public class DungeonHooks
012    {
013        private static int dungeonLootAttempts = 8;
014        private static ArrayList<DungeonMob> dungeonMobs = new ArrayList<DungeonMob>();
015        private static ArrayList<DungeonLoot> dungeonLoot = new ArrayList<DungeonLoot>();
016        /**
017         * Set the number of item stacks that will be attempted to be added to each Dungeon chest.
018         * Note: Due to random number generation, you will not always get this amount per chest.
019         * @param number The maximum number of item stacks to add to a chest.
020         */
021        public static void setDungeonLootTries(int number)
022        {
023            dungeonLootAttempts = number;
024        }
025    
026        /**
027         * @return The max number of item stacks found in each dungeon chest.
028         */
029        public static int getDungeonLootTries()
030        {
031            return dungeonLootAttempts;
032        }
033    
034        /**
035         * Adds a mob to the possible list of creatures the spawner will create.
036         * If the mob is already in the spawn list, the rarity will be added to the existing one,
037         * causing the mob to be more common.
038         *
039         * @param name The name of the monster, use the same name used when registering the entity.
040         * @param rarity The rarity of selecting this mob over others. Must be greater then 0.
041         *        Vanilla Minecraft has the following mobs:
042         *        Spider   100
043         *        Skeleton 100
044         *        Zombie   200
045         *        Meaning, Zombies are twice as common as spiders or skeletons.
046         * @return The new rarity of the monster,
047         */
048        public static float addDungeonMob(String name, int rarity)
049        {
050            if (rarity <= 0)
051            {
052                throw new IllegalArgumentException("Rarity must be greater then zero");
053            }
054    
055            for (DungeonMob mob : dungeonMobs)
056            {
057                if (name.equals(mob.type))
058                {
059                    return mob.itemWeight += rarity;
060                }
061            }
062    
063            dungeonMobs.add(new DungeonMob(rarity, name));
064            return rarity;
065        }
066    
067        /**
068         * Will completely remove a Mob from the dungeon spawn list.
069         *
070         * @param name The name of the mob to remove
071         * @return The rarity of the removed mob, prior to being removed.
072         */
073        public static int removeDungeonMob(String name)
074        {
075            for (DungeonMob mob : dungeonMobs)
076            {
077                if (name.equals(mob.type))
078                {
079                    dungeonMobs.remove(mob);
080                    return mob.itemWeight;
081                }
082            }
083            return 0;
084        }
085    
086        /**
087         * Gets a random mob name from the list.
088         * @param rand World generation random number generator
089         * @return The mob name
090         */
091        public static String getRandomDungeonMob(Random rand)
092        {
093            DungeonMob mob = (DungeonMob)WeightedRandom.getRandomItem(rand, dungeonMobs);
094            if (mob == null)
095            {
096                return "";
097            }
098            return mob.type;
099        }
100    
101        /**
102         * Adds a item stack to the dungeon loot list with a stack size
103         * of 1.
104         *
105         * @param item The ItemStack to be added to the loot list
106         * @param rarity The relative chance that this item will spawn, Vanilla has
107         *          most of its items set to 1. Like the saddle, bread, silk, wheat, etc..
108         *          Rarer items are set to lower values, EXA: Golden Apple 0.01
109         */
110        public static void addDungeonLoot(ItemStack item, int rarity)
111        {
112            addDungeonLoot(item, rarity, 1, 1);
113        }
114    
115        /**
116         * Adds a item stack, with a range of sizes, to the dungeon loot list.
117         * If a stack matching the same item, and size range, is already in the list
118         * the rarities will be added together making the item more common.
119         *
120         * @param item The ItemStack to be added to the loot list
121         * @param rarity The relative chance that this item will spawn, Vanilla has
122         *          most of its items set to 1. Like the saddle, bread, silk, wheat, etc..
123         *          Rarer items are set to lower values, EXA: Golden Apple 0.01
124         * @param minCount When this item does generate, the minimum number that is in the stack
125         * @param maxCount When this item does generate, the maximum number that can bein the stack
126         * @return The new rarity of the loot.
127         */
128        public static float addDungeonLoot(ItemStack item, int rarity, int minCount, int maxCount)
129        {
130            for (DungeonLoot loot : dungeonLoot)
131            {
132                if (loot.equals(item, minCount, maxCount))
133                {
134                    return loot.itemWeight += rarity;
135                }
136            }
137    
138            dungeonLoot.add(new DungeonLoot(rarity, item, minCount, maxCount));
139            return rarity;
140        }
141        /**
142         * Removes a item stack from the dungeon loot list, this will remove all items
143         * as long as the item stack matches, it will not care about matching the stack
144         * size ranges perfectly.
145         *
146         * @param item The item stack to remove
147         */
148        public static void removeDungeonLoot(ItemStack item)
149        {
150            removeDungeonLoot(item, -1, 0);
151        }
152    
153        /**
154         * Removes a item stack from the dungeon loot list. If 'minCount' parameter
155         * is greater then 0, it will only remove loot items that have the same exact
156         * stack size range as passed in by parameters.
157         *
158         * @param item The item stack to remove
159         * @param minCount The minimum count for the match check, if less then 0,
160         *          the size check is skipped
161         * @param maxCount The max count used in match check when 'minCount' is >= 0
162         */
163        public static void removeDungeonLoot(ItemStack item, int minCount, int maxCount)
164        {
165            ArrayList<DungeonLoot> lootTmp = (ArrayList<DungeonLoot>)dungeonLoot.clone();
166            if (minCount < 0)
167            {
168                for (DungeonLoot loot : lootTmp)
169                {
170                    if (loot.equals(item))
171                    {
172                        dungeonLoot.remove(loot);
173                    }
174                }
175            }
176            else
177            {
178                for (DungeonLoot loot : lootTmp)
179                {
180                    if (loot.equals(item, minCount, maxCount))
181                    {
182                        dungeonLoot.remove(loot);
183                    }
184                }
185            }
186        }
187    
188        /**
189         * Gets a random item stack to place in a dungeon chest during world generation
190         * @param rand World generation random number generator
191         * @return The item stack
192         */
193        public static ItemStack getRandomDungeonLoot(Random rand)
194        {
195            DungeonLoot ret = (DungeonLoot)WeightedRandom.getRandomItem(rand, dungeonLoot);
196            if (ret != null)
197            {
198                return ret.generateStack(rand);
199            }
200            return null;
201        }
202    
203        public static class DungeonLoot extends WeightedRandomItem
204        {
205            private ItemStack itemStack;
206            private int minCount = 1;
207            private int maxCount = 1;
208    
209            /**
210             * @param item A item stack
211             * @param min Minimum stack size when randomly generating
212             * @param max Maximum stack size when randomly generating
213             */
214            public DungeonLoot(int weight, ItemStack item, int min, int max)
215            {
216                super(weight);
217                this.itemStack = item;
218                minCount = min;
219                maxCount = max;
220            }
221    
222            /**
223             * Grabs a ItemStack ready to be added to the dungeon chest,
224             * the stack size will be between minCount and maxCount
225             * @param rand World gen random number generator
226             * @return The ItemStack to be added to the chest
227             */
228            public ItemStack generateStack(Random rand)
229            {
230                ItemStack ret = this.itemStack.copy();
231                ret.stackSize = minCount + (rand.nextInt(maxCount - minCount + 1));
232                return ret;
233            }
234    
235            public boolean equals(ItemStack item, int min, int max)
236            {
237                return (min == minCount && max == maxCount && item.isItemEqual(this.itemStack) && ItemStack.areItemStackTagsEqual(item, this.itemStack));
238            }
239    
240            public boolean equals(ItemStack item)
241            {
242                return item.isItemEqual(this.itemStack) && ItemStack.areItemStackTagsEqual(item, this.itemStack);
243            }
244        }
245    
246        public static class DungeonMob extends WeightedRandomItem
247        {
248            public String type;
249            public DungeonMob(int weight, String type)
250            {
251                super(weight);
252                this.type = type;
253            }
254    
255            @Override
256            public boolean equals(Object target)
257            {
258                if (target instanceof DungeonMob)
259                {
260                    return this.type.equals(((DungeonMob)target).type);
261                }
262                return false;
263            }
264        }
265    
266        public void addDungeonLoot(DungeonLoot loot)
267        {
268            dungeonLoot.add(loot);
269        }
270    
271        public boolean removeDungeonLoot(DungeonLoot loot)
272        {
273            return dungeonLoot.remove(loot);
274        }
275    
276        static
277        {
278            addDungeonMob("Skeleton", 100);
279            addDungeonMob("Zombie",   200);
280            addDungeonMob("Spider",   100);
281    
282            addDungeonLoot(new ItemStack(Item.saddle),          100      );
283            addDungeonLoot(new ItemStack(Item.ingotIron),       100, 1, 4);
284            addDungeonLoot(new ItemStack(Item.bread),           100      );
285            addDungeonLoot(new ItemStack(Item.wheat),           100, 1, 4);
286            addDungeonLoot(new ItemStack(Item.gunpowder),       100, 1, 4);
287            addDungeonLoot(new ItemStack(Item.silk),            100, 1, 4);
288            addDungeonLoot(new ItemStack(Item.bucketEmpty),     100      );
289            addDungeonLoot(new ItemStack(Item.appleGold),       001      );
290            addDungeonLoot(new ItemStack(Item.redstone),        050, 1, 4);
291            addDungeonLoot(new ItemStack(Item.record13),        005      );
292            addDungeonLoot(new ItemStack(Item.recordCat),       005      );
293            addDungeonLoot(new ItemStack(Item.dyePowder, 1, 3), 100      );
294        }
295    }