package net.minecraftforge.common;
import java.util.*;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.WeightedRandom;
import net.minecraft.util.WeightedRandomChestContent;
import net.minecraft.world.WorldServer;
import net.minecraft.world.gen.feature.WorldGenDungeons;
import net.minecraft.world.gen.structure.*;
import net.minecraft.world.gen.structure.ComponentScatteredFeaturePieces.DesertPyramid;
import net.minecraft.world.gen.structure.ComponentScatteredFeaturePieces.JunglePyramid;
import net.minecraft.world.gen.structure.StructureStrongholdPieces.ChestCorridor;
import net.minecraft.world.gen.structure.StructureStrongholdPieces.Library;
import net.minecraft.world.gen.structure.StructureStrongholdPieces.RoomCrossing;
import net.minecraft.world.gen.structure.StructureVillagePieces.House2;
import net.minecraftforge.oredict.OreDictionary;
public class ChestGenHooks
{
//Currently implemented categories for chests/dispensers, Dungeon loot is still in DungeonHooks
public static final String MINESHAFT_CORRIDOR = "mineshaftCorridor";
public static final String PYRAMID_DESERT_CHEST = "pyramidDesertyChest";
public static final String PYRAMID_JUNGLE_CHEST = "pyramidJungleChest";
public static final String PYRAMID_JUNGLE_DISPENSER = "pyramidJungleDispenser";
public static final String STRONGHOLD_CORRIDOR = "strongholdCorridor";
public static final String STRONGHOLD_LIBRARY = "strongholdLibrary";
public static final String STRONGHOLD_CROSSING = "strongholdCrossing";
public static final String VILLAGE_BLACKSMITH = "villageBlacksmith";
public static final String BONUS_CHEST = "bonusChest";
public static final String DUNGEON_CHEST = "dungeonChest";
private static final HashMap<String, ChestGenHooks> chestInfo = new HashMap<String, ChestGenHooks>();
private static boolean hasInit = false;
static
{
init();
}
private static void init()
{
if (hasInit)
{
return;
}
hasInit = true;
addInfo(MINESHAFT_CORRIDOR, StructureMineshaftPieces.mineshaftChestContents, 3, 7);
addInfo(PYRAMID_DESERT_CHEST, DesertPyramid.itemsToGenerateInTemple, 2, 7);
addInfo(PYRAMID_JUNGLE_CHEST, JunglePyramid.junglePyramidsChestContents, 2, 7);
addInfo(PYRAMID_JUNGLE_DISPENSER, JunglePyramid.junglePyramidsDispenserContents, 2, 2);
addInfo(STRONGHOLD_CORRIDOR, ChestCorridor.strongholdChestContents, 2, 4);
addInfo(STRONGHOLD_LIBRARY, Library.strongholdLibraryChestContents, 1, 5);
addInfo(STRONGHOLD_CROSSING, RoomCrossing.strongholdRoomCrossingChestContents, 1, 5);
addInfo(VILLAGE_BLACKSMITH, House2.villageBlacksmithChestContents, 3, 9);
addInfo(BONUS_CHEST, WorldServer.bonusChestContent, 10, 10);
addInfo(DUNGEON_CHEST, WorldGenDungeons.field_111189_a, 8, 8);
ItemStack book = new ItemStack(Items.enchanted_book, 1, 0);
WeightedRandomChestContent tmp = new WeightedRandomChestContent(book, 1, 1, 1);
getInfo(MINESHAFT_CORRIDOR ).addItem(tmp);
getInfo(PYRAMID_DESERT_CHEST).addItem(tmp);
getInfo(PYRAMID_JUNGLE_CHEST).addItem(tmp);
getInfo(STRONGHOLD_CORRIDOR ).addItem(tmp);
getInfo(STRONGHOLD_LIBRARY ).addItem(new WeightedRandomChestContent(book, 1, 5, 2));
getInfo(STRONGHOLD_CROSSING ).addItem(tmp);
getInfo(DUNGEON_CHEST ).addItem(tmp);
}
static void addDungeonLoot(ChestGenHooks dungeon, ItemStack item, int weight, int min, int max)
{
dungeon.addItem(new WeightedRandomChestContent(item, min, max, weight));
}
private static void addInfo(String category, WeightedRandomChestContent[] items, int min, int max)
{
chestInfo.put(category, new ChestGenHooks(category, items, min, max));
}
/**
* Retrieves, or creates the info class for the specified category.
*
* @param category The category name
* @return A instance of ChestGenHooks for the specified category.
*/
public static ChestGenHooks getInfo(String category)
{
if (!chestInfo.containsKey(category))
{
chestInfo.put(category, new ChestGenHooks(category));
}
return chestInfo.get(category);
}
/**
* Generates an array of items based on the input min/max count.
* If the stack can not hold the total amount, it will be split into
* stacks of size 1.
*
* @param rand A random number generator
* @param source Source item stack
* @param min Minimum number of items
* @param max Maximum number of items
* @return An array containing the generated item stacks
*/
public static ItemStack[] generateStacks(Random rand, ItemStack source, int min, int max)
{
int count = min + (rand.nextInt(max - min + 1));
ItemStack[] ret;
if (source.getItem() == null)
{
ret = new ItemStack[0];
}
else if (count > source.getMaxStackSize())
{
ret = new ItemStack[count];
for (int x = 0; x < count; x++)
{
ret[x] = source.copy();
ret[x].stackSize = 1;
}
}
else
{
ret = new ItemStack[1];
ret[0] = source.copy();
ret[0].stackSize = count;
}
return ret;
}
//shortcut functions, See the non-static versions below
public static WeightedRandomChestContent[] getItems(String category, Random rnd){ return getInfo(category).getItems(rnd); }
public static int getCount(String category, Random rand){ return getInfo(category).getCount(rand); }
public static void addItem(String category, WeightedRandomChestContent item){ getInfo(category).addItem(item); }
public static void removeItem(String category, ItemStack item){ getInfo(category).removeItem(item); }
public static ItemStack getOneItem(String category, Random rand){ return getInfo(category).getOneItem(rand); }
private String category;
private int countMin = 0;
private int countMax = 0;
private ArrayList<WeightedRandomChestContent> contents = new ArrayList<WeightedRandomChestContent>();
public ChestGenHooks(String category)
{
this.category = category;
}
public ChestGenHooks(String category, WeightedRandomChestContent[] items, int min, int max)
{
this(category);
for (WeightedRandomChestContent item : items)
{
contents.add(item);
}
countMin = min;
countMax = max;
}
/**
* Adds a new entry into the possible items to generate.
*
* @param item The item to add.
*/
public void addItem(WeightedRandomChestContent item)
{
contents.add(item);
}
/**
* Removes all items that match the input item stack, Only metadata and item ID are checked.
* If the input item has a metadata of -1, all metadatas will match.
*
* @param item The item to check
*/
public void removeItem(ItemStack item)
{
Iterator<WeightedRandomChestContent> itr = contents.iterator();
while(itr.hasNext())
{
WeightedRandomChestContent cont = itr.next();
if (item.isItemEqual(cont.theItemId) || (item.getItemDamage() == OreDictionary.WILDCARD_VALUE && item.getItem() == cont.theItemId.getItem()))
{
itr.remove();
}
}
}
/**
* Gets an array of all random objects that are associated with this category.
*
* @return The random objects
*/
public WeightedRandomChestContent[] getItems(Random rnd)
{
ArrayList<WeightedRandomChestContent> ret = new ArrayList<WeightedRandomChestContent>();
for (WeightedRandomChestContent orig : contents)
{
Item item = orig.theItemId.getItem();
if (item != null)
{
WeightedRandomChestContent n = item.getChestGenBase(this, rnd, orig);
if (n != null)
{
ret.add(n);
}
}
}
return ret.toArray(new WeightedRandomChestContent[ret.size()]);
}
/**
* Gets a random number between countMin and countMax.
*
* @param rand A RNG
* @return A random number where countMin <= num <= countMax
*/
public int getCount(Random rand)
{
return countMin < countMax ? countMin + rand.nextInt(countMax - countMin) : countMin;
}
/**
* Returns a single ItemStack from the possible items in this registry,
* Useful if you just want a quick and dirty random Item.
*
* @param rand A Random Number gen
* @return A single ItemStack, or null if it could not get one.
*/
public ItemStack getOneItem(Random rand)
{
WeightedRandomChestContent[] items = getItems(rand);
WeightedRandomChestContent item = (WeightedRandomChestContent)WeightedRandom.getRandomItem(rand, items);
ItemStack[] stacks = ChestGenHooks.generateStacks(rand, item.theItemId, item.theMinimumChanceToGenerateItem, item.theMaximumChanceToGenerateItem);
return (stacks.length > 0 ? stacks[0] : null);
}
//Accessors
public int getMin(){ return countMin; }
public int getMax(){ return countMax; }
public void setMin(int value){ countMin = value; }
public void setMax(int value){ countMax = value; }
}