001 package net.minecraftforge.common; 002 003 import java.util.*; 004 005 import net.minecraft.item.Item; 006 import net.minecraft.item.ItemStack; 007 import net.minecraft.util.WeightedRandomChestContent; 008 import net.minecraft.world.WorldServer; 009 import net.minecraft.world.gen.structure.*; 010 011 public class ChestGenHooks 012 { 013 //Currently implemented categories for chests/dispensers, Dungeon loot is still in DungeonHooks 014 public static final String MINESHAFT_CORRIDOR = "mineshaftCorridor"; 015 public static final String PYRAMID_DESERT_CHEST = "pyramidDesertyChest"; 016 public static final String PYRAMID_JUNGLE_CHEST = "pyramidJungleChest"; 017 public static final String PYRAMID_JUNGLE_DISPENSER = "pyramidJungleDispenser"; 018 public static final String STRONGHOLD_CORRIDOR = "strongholdCorridor"; 019 public static final String STRONGHOLD_LIBRARY = "strongholdLibrary"; 020 public static final String STRONGHOLD_CROSSING = "strongholdCrossing"; 021 public static final String VILLAGE_BLACKSMITH = "villageBlacksmith"; 022 public static final String BONUS_CHEST = "bonusChest"; 023 024 private static final HashMap<String, ChestGenHooks> chestInfo = new HashMap<String, ChestGenHooks>(); 025 private static boolean hasInit = false; 026 static 027 { 028 init(); 029 } 030 031 private static void init() 032 { 033 if (hasInit) 034 { 035 return; 036 } 037 addInfo(MINESHAFT_CORRIDOR, StructureMineshaftPieces.mineshaftChestContents, 3, 7); 038 addInfo(PYRAMID_DESERT_CHEST, ComponentScatteredFeatureDesertPyramid.itemsToGenerateInTemple, 2, 7); 039 addInfo(PYRAMID_JUNGLE_CHEST, ComponentScatteredFeatureJunglePyramid.junglePyramidsChestContents, 2, 7); 040 addInfo(PYRAMID_JUNGLE_DISPENSER, ComponentScatteredFeatureJunglePyramid.junglePyramidsDispenserContents, 2, 2); 041 addInfo(STRONGHOLD_CORRIDOR, ComponentStrongholdChestCorridor.strongholdChestContents, 2, 4); 042 addInfo(STRONGHOLD_LIBRARY, ComponentStrongholdLibrary.strongholdLibraryChestContents, 1, 5); 043 addInfo(STRONGHOLD_CROSSING, ComponentStrongholdRoomCrossing.strongholdRoomCrossingChestContents, 1, 5); 044 addInfo(VILLAGE_BLACKSMITH, ComponentVillageHouse2.villageBlacksmithChestContents, 3, 9); 045 addInfo(BONUS_CHEST, WorldServer.bonusChestContent, 10, 10); 046 047 ItemStack book = new ItemStack(Item.field_92053_bW, 1, 0); 048 WeightedRandomChestContent tmp = new WeightedRandomChestContent(book, 1, 1, 1); 049 getInfo(MINESHAFT_CORRIDOR ).addItem(tmp); 050 getInfo(PYRAMID_DESERT_CHEST).addItem(tmp); 051 getInfo(PYRAMID_JUNGLE_CHEST).addItem(tmp); 052 getInfo(STRONGHOLD_CORRIDOR ).addItem(tmp); 053 getInfo(STRONGHOLD_LIBRARY ).addItem(new WeightedRandomChestContent(book, 1, 5, 2)); 054 getInfo(STRONGHOLD_CROSSING ).addItem(tmp); 055 } 056 057 private static void addInfo(String category, WeightedRandomChestContent[] items, int min, int max) 058 { 059 chestInfo.put(category, new ChestGenHooks(category, items, min, max)); 060 } 061 062 /** 063 * Retrieves, or creates the info class for the specified category. 064 * 065 * @param category The category name 066 * @return A instance of ChestGenHooks for the specified category. 067 */ 068 public static ChestGenHooks getInfo(String category) 069 { 070 if (!chestInfo.containsKey(category)) 071 { 072 chestInfo.put(category, new ChestGenHooks(category)); 073 } 074 return chestInfo.get(category); 075 } 076 077 /** 078 * Generates an array of items based on the input min/max count. 079 * If the stack can not hold the total amount, it will be split into 080 * stacks of size 1. 081 * 082 * @param rand A random number generator 083 * @param source Source item stack 084 * @param min Minimum number of items 085 * @param max Maximum number of items 086 * @return An array containing the generated item stacks 087 */ 088 public static ItemStack[] generateStacks(Random rand, ItemStack source, int min, int max) 089 { 090 int count = min + (rand.nextInt(max - min + 1)); 091 092 ItemStack[] ret; 093 if (source.getItem() == null) 094 { 095 ret = new ItemStack[0]; 096 } 097 else if (count > source.getItem().getItemStackLimit()) 098 { 099 ret = new ItemStack[count]; 100 for (int x = 0; x < count; x++) 101 { 102 ret[x] = source.copy(); 103 ret[x].stackSize = 1; 104 } 105 } 106 else 107 { 108 ret = new ItemStack[1]; 109 ret[0] = source.copy(); 110 ret[0].stackSize = count; 111 } 112 return ret; 113 } 114 115 //shortcut functions, See the non-static versions below 116 public static WeightedRandomChestContent[] getItems(String category, Random rnd){ return getInfo(category).getItems(rnd); } 117 public static int getCount(String category, Random rand){ return getInfo(category).getCount(rand); } 118 public static void addItem(String category, WeightedRandomChestContent item){ getInfo(category).addItem(item); } 119 public static void removeItem(String category, ItemStack item){ getInfo(category).removeItem(item); } 120 121 private String category; 122 private int countMin = 0; 123 private int countMax = 0; 124 private ArrayList<WeightedRandomChestContent> contents = new ArrayList<WeightedRandomChestContent>(); 125 126 public ChestGenHooks(String category) 127 { 128 this.category = category; 129 } 130 131 public ChestGenHooks(String category, WeightedRandomChestContent[] items, int min, int max) 132 { 133 this(category); 134 for (WeightedRandomChestContent item : items) 135 { 136 contents.add(item); 137 } 138 countMin = min; 139 countMax = max; 140 } 141 142 /** 143 * Adds a new entry into the possible items to generate. 144 * 145 * @param item The item to add. 146 */ 147 public void addItem(WeightedRandomChestContent item) 148 { 149 contents.add(item); 150 } 151 152 /** 153 * Removes all items that match the input item stack, Only metadata and item ID are checked. 154 * If the input item has a metadata of -1, all metadatas will match. 155 * 156 * @param item The item to check 157 */ 158 public void removeItem(ItemStack item) 159 { 160 Iterator<WeightedRandomChestContent> itr = contents.iterator(); 161 while(itr.hasNext()) 162 { 163 WeightedRandomChestContent cont = itr.next(); 164 if (item.isItemEqual(cont.theItemId) || (item.getItemDamage() == -1 && item.itemID == cont.theItemId.itemID)) 165 { 166 itr.remove(); 167 } 168 } 169 } 170 171 /** 172 * Gets an array of all random objects that are associated with this category. 173 * 174 * @return The random objects 175 */ 176 public WeightedRandomChestContent[] getItems(Random rnd) 177 { 178 ArrayList<WeightedRandomChestContent> ret = new ArrayList<WeightedRandomChestContent>(); 179 180 for (WeightedRandomChestContent orig : contents) 181 { 182 Item item = orig.theItemId.getItem(); 183 184 if (item != null) 185 { 186 WeightedRandomChestContent n = item.getChestGenBase(this, rnd, orig); 187 if (n != null) 188 { 189 ret.add(n); 190 } 191 } 192 } 193 194 return ret.toArray(new WeightedRandomChestContent[ret.size()]); 195 } 196 197 /** 198 * Gets a random number between countMin and countMax. 199 * 200 * @param rand A RNG 201 * @return A random number where countMin <= num <= countMax 202 */ 203 public int getCount(Random rand) 204 { 205 return countMin < countMax ? countMin + rand.nextInt(countMax - countMin) : countMin; 206 } 207 208 //Accessors 209 public int getMin(){ return countMin; } 210 public int getMax(){ return countMax; } 211 public void setMin(int value){ countMin = value; } 212 public void setMax(int value){ countMax = value; } 213 }