public class ItemManager {
	private static boolean isInitialized = false;
	
	public static ItemArmor.ArmorMaterial armorAdamantine = EnumHelper.addArmorMaterial("ADAMANTINE", 35, new int[] { 3, 8, 6, 3 }, 8);
	public static ItemArmor.ArmorMaterial armorColdiron = EnumHelper.addArmorMaterial("COLDIRON", 15, new int[] { 2, 6, 5, 2 }, 18);
	public static ItemArmor.ArmorMaterial armorMithral = EnumHelper.addArmorMaterial("MITHRAL", 20, new int[] { 3, 8, 6, 3 }, 25);

	public static Item.ToolMaterial toolAdamantine = EnumHelper.addToolMaterial("ADAMANTINE", 3, 1250, 12.0F, 3.0F, 16);
	public static Item.ToolMaterial toolColdiron = EnumHelper.addToolMaterial("COLDIRON", 2, 250, 6.0F, 2.0F, 17);
	public static Item.ToolMaterial toolMithral = EnumHelper.addToolMaterial("MITHRAL", 2, 560, 8.0F, 3.0F, 20);
	
	public static OreItemStack armorAdamantineHelmet;
	public static OreItemStack armorAdamantineChestplate;
	public static OreItemStack armorAdamantineLeggings;
	public static OreItemStack armorAdamantineBoots;
	public static OreItemStack armorColdironHelmet;
	public static OreItemStack armorColdironChestplate;
	public static OreItemStack armorColdironLeggings;
	public static OreItemStack armorColdironBoots;
	public static OreItemStack armorMithralHelmet;
	public static OreItemStack armorMithralChestplate;
	public static OreItemStack armorMithralLeggings;
	public static OreItemStack armorMithralBoots;
	public static OreItemStack toolAdamantineAxe;
	public static OreItemStack toolAdamantineHoe;
	public static OreItemStack toolAdamantinePickaxe;
	public static OreItemStack toolAdamantineSpade;
	public static OreItemStack toolAdamantineSword;
	public static OreItemStack toolColdironAxe;
	public static OreItemStack toolColdironHoe;
	public static OreItemStack toolColdironPickaxe;
	public static OreItemStack toolColdironSpade;
	public static OreItemStack toolColdironSword;
	public static OreItemStack toolMithralAxe;
	public static OreItemStack toolMithralHoe;
	public static OreItemStack toolMithralPickaxe;
	public static OreItemStack toolMithralSpade;
	public static OreItemStack toolMithralSword;

	public static void init() {
		if (isInitialized)
		{
			OresPlus.log.info("Item initialization failed, already initialized");
		}
		else
		{
			OresPlus.log.info("Initializing Items");
			
			for (MetallicOres ore : MetallicOres.values()) {
				ore.registerItems();
			}
			
			for (GemstoneOres ore : GemstoneOres.values()) {
				ore.registerItems();
			}
			
			for (DustyOres ore : DustyOres.values()) {
				ore.registerItems();
			}
			
			for (MineralOres ore : MineralOres.values()) {
				ore.registerItems();
			}
			
			for (Items item : Items.values()) {
				item.registerItems();;
			}
			
		    armorAdamantineHelmet = new OreItemStack(new OreArmor("armorAdamantineHelmet", armorAdamantine, 2, 0));
		    armorAdamantineChestplate = new OreItemStack(new OreArmor("armorAdamantineChestplate", armorAdamantine, 2, 1));
		    armorAdamantineLeggings = new OreItemStack(new OreArmor("armorAdamantineLeggings", armorAdamantine, 2, 2));
		    armorAdamantineBoots = new OreItemStack(new OreArmor("armorAdamantineBoots", armorAdamantine, 2, 3));
		    armorColdironHelmet = new OreItemStack(new OreArmor("armorColdironHelmet", armorColdiron, 2, 0));
		    armorColdironChestplate = new OreItemStack(new OreArmor("armorColdironChestplate", armorColdiron, 2, 1));
		    armorColdironLeggings = new OreItemStack(new OreArmor("armorColdironLeggings", armorColdiron, 2, 2));
		    armorColdironBoots = new OreItemStack(new OreArmor("armorColdironBoots", armorColdiron, 2, 3));
		    armorMithralHelmet = new OreItemStack(new OreArmor("armorMithralHelmet", armorMithral, 2, 0));
		    armorMithralChestplate = new OreItemStack(new OreArmor("armorMithralChestplate", armorMithral, 2, 1));
		    armorMithralLeggings = new OreItemStack(new OreArmor("armorMithralLeggings", armorMithral, 2, 2));
		    armorMithralBoots = new OreItemStack(new OreArmor("armorMithralBoots", armorMithral, 2, 3));
		    toolAdamantineAxe = new OreItemStack(new OreAxe("toolAdamantineAxe", toolAdamantine));
		    toolAdamantineHoe = new OreItemStack(new OreHoe("toolAdamantineHoe", toolAdamantine));
		    toolAdamantinePickaxe = new OreItemStack(new OrePickaxe("toolAdamantinePickaxe", toolAdamantine));
		    toolAdamantineSpade = new OreItemStack(new OreSpade("toolAdamantineSpade", toolAdamantine));
		    toolAdamantineSword = new OreItemStack(new OreSword("toolAdamantineSword", toolAdamantine));
		    toolColdironAxe = new OreItemStack(new OreAxe("toolColdironAxe", toolColdiron));
		    toolColdironHoe = new OreItemStack(new OreHoe("toolColdironHoe", toolColdiron));
		    toolColdironPickaxe = new OreItemStack(new OrePickaxe("toolColdironPickaxe", toolColdiron));
		    toolColdironSpade = new OreItemStack(new OreSpade("toolColdironSpade", toolColdiron));
		    toolColdironSword = new OreItemStack(new OreSword("toolColdironSword", toolColdiron));
		    toolMithralAxe = new OreItemStack(new OreAxe("toolMithralAxe", toolMithral));
		    toolMithralHoe = new OreItemStack(new OreHoe("toolMithralHoe", toolMithral));
		    toolMithralPickaxe = new OreItemStack(new OrePickaxe("toolMithralPickaxe", toolMithral));
		    toolMithralSpade = new OreItemStack(new OreSpade("toolMithralSpade", toolMithral));
		    toolMithralSword = new OreItemStack(new OreSword("toolMithralSword", toolMithral));

			isInitialized = true;
		}
	}

	public static void registerAspects() {
		if (Helpers.ThaumCraft.isLoaded()) {
			ThaumcraftApi.registerObjectTag(armorAdamantineHelmet.source, new AspectList());
			ThaumcraftApi.registerObjectTag(armorAdamantineChestplate.source, new AspectList());
			ThaumcraftApi.registerObjectTag(armorAdamantineLeggings.source, new AspectList());
			ThaumcraftApi.registerObjectTag(armorAdamantineBoots.source, new AspectList());
			ThaumcraftApi.registerObjectTag(armorColdironHelmet.source, new AspectList());
			ThaumcraftApi.registerObjectTag(armorColdironChestplate.source, new AspectList());
			ThaumcraftApi.registerObjectTag(armorColdironLeggings.source, new AspectList());
			ThaumcraftApi.registerObjectTag(armorColdironBoots.source, new AspectList());
			ThaumcraftApi.registerObjectTag(armorMithralHelmet.source, new AspectList());
			ThaumcraftApi.registerObjectTag(armorMithralChestplate.source, new AspectList());
			ThaumcraftApi.registerObjectTag(armorMithralLeggings.source, new AspectList());
			ThaumcraftApi.registerObjectTag(armorMithralBoots.source, new AspectList());
			ThaumcraftApi.registerObjectTag(toolAdamantineAxe.source, new AspectList());
			ThaumcraftApi.registerObjectTag(toolAdamantineHoe.source, new AspectList());
			ThaumcraftApi.registerObjectTag(toolAdamantinePickaxe.source, new AspectList());
			ThaumcraftApi.registerObjectTag(toolAdamantineSpade.source, new AspectList());
			ThaumcraftApi.registerObjectTag(toolAdamantineSword.source, new AspectList());
			ThaumcraftApi.registerObjectTag(toolColdironAxe.source, new AspectList());
			ThaumcraftApi.registerObjectTag(toolColdironHoe.source, new AspectList());
			ThaumcraftApi.registerObjectTag(toolColdironPickaxe.source, new AspectList());
			ThaumcraftApi.registerObjectTag(toolColdironSpade.source, new AspectList());
			ThaumcraftApi.registerObjectTag(toolColdironSword.source, new AspectList());
			ThaumcraftApi.registerObjectTag(toolMithralAxe.source, new AspectList());
			ThaumcraftApi.registerObjectTag(toolMithralHoe.source, new AspectList());
			ThaumcraftApi.registerObjectTag(toolMithralPickaxe.source, new AspectList());
			ThaumcraftApi.registerObjectTag(toolMithralSpade.source, new AspectList());
			ThaumcraftApi.registerObjectTag(toolMithralSword.source, new AspectList());
		}
	}
} public class OreArmor extends ItemArmor
{
  public OreArmor(String itemName, ItemArmor.ArmorMaterial material, int renderType, int armorType)
  {
    super(material, renderType, armorType);
    setUnlocalizedName(itemName);
    setTextureName("OresPlus:" + itemName);
    GameRegistry.registerItem(this, itemName);
  }
} public class OreAxe extends ItemAxe
{
	private static ArrayList<String> axeList = new ArrayList();
	
	public OreAxe(String itemName, Item.ToolMaterial material)
	{
		super(material);
		setUnlocalizedName(itemName);
		setTextureName("OresPlus:" + itemName);
		GameRegistry.registerItem(this, itemName);
		axeList.add(itemName);
	}
	
	public static ArrayList<String> getAxeList() {
		return axeList;
	}
} public class OreHoe extends ItemHoe
{
  public OreHoe(String itemName, Item.ToolMaterial material)
  {
    super(material);
    setUnlocalizedName(itemName);
    setTextureName("OresPlus:" + itemName);
    GameRegistry.registerItem(this, itemName);
  }
} public class OrePickaxe extends ItemPickaxe
{
  public OrePickaxe(String itemName, Item.ToolMaterial material)
  {
    super(material);
    setUnlocalizedName(itemName);
    setTextureName("OresPlus:" + itemName);
    GameRegistry.registerItem(this, itemName);
  }
} public class OreSpade extends ItemSpade {

	public OreSpade(String itemName, ToolMaterial material) {
		super(material);
		setUnlocalizedName(itemName);
		setTextureName("OresPlus:" + itemName);
		GameRegistry.registerItem(this, itemName);
	}

} public class OreSword extends ItemSword
{
  public OreSword(String itemName, Item.ToolMaterial material)
  {
    super(material);
    setUnlocalizedName(itemName);
    setTextureName("OresPlus:" + itemName);
    GameRegistry.registerItem(this, itemName);
  }
} public enum GemstoneOres implements IOreList {
		Amethyst (2, OreDrops.AMETHYST, 1500.0D),
		Apatite (1, OreDrops.APATITE, 800.0D),
		Diamond (2, 3, 7, OreDrops.DIAMOND, 0.0D), // 5050.057512219353
		Emerald (2, 3, 7, OreDrops.EMERALD, 0.0D), // 55643.450773700926
		Malachite (2, 3, 7, OreDrops.MALACHITE, 3000.0D),
		Peridot (2, 3, 7, OreDrops.PERIDOT, 3000.0D),
		Ruby (2, 3, 7, OreDrops.RUBY, 3000.0D),
		Sapphire (2, 3, 7, OreDrops.SAPPHIRE, 3000.0D),
		Tanzanite(2, 3, 7, OreDrops.TANZANITE, 3000.0D),
		Topaz (2, 3, 7, OreDrops.TOPAZ, 3000.0D)
	;
		
	public String oreName;
	public String netherOreName;
	public String blockName;
	public String gemName;
	
	public OreItemStack ore;
	public OreItemStack netherOre;
	public OreItemStack block;
	public OreItemStack gem;
	
	public boolean enabled;
	
	private int _harvestLevel;
	private int _xpLow;
	private int _xpHigh;
	private OreDrops _drops;
	private OreSources _source;
	private double _uuCost;
	
	GemstoneOres (int harvestLevel, int xpLow, int xpHigh, OreDrops drops, double uuCost) {
		this.oreName = "ore" + this.toString();
		this.netherOreName = "oreNether" + this.toString();
		this.blockName = "block" + this.toString();
		this.gemName = "gem" + this.toString();
		
		this.enabled = true;
		
		this._harvestLevel = harvestLevel;
		this._xpLow = xpLow;
		this._xpHigh = xpHigh;
		this._drops = drops;
		this._source = OreSources.DEFAULT;
		this._uuCost = uuCost;
	}
	
	GemstoneOres (int harvestLevel, OreDrops drops, double uuCost) {
		this(harvestLevel, 0, 0, drops, uuCost);
	}
	
	private boolean isVanilla() {
		return (this == Diamond || this == Emerald);
	}

	@Override
	public OreClass getDefaultConfig() {
		return new OreClass(this.oreName, this.enabled, this._harvestLevel, this._xpLow, 
				this._xpHigh, this._drops, this._source);
	}

	@Override
	public OreClass getDefaultConfigNether() {
		return new OreClass(this.netherOreName, this.enabled, this._harvestLevel, this._xpLow,
				this._xpHigh, OreDrops.ORE, this._source);
	}

	@Override
	public void registerBlocks() {
		//Register Ore
		if (!this.isVanilla()) {
			this.ore = new OreItemStack(new BlockOre(this.getDefaultConfig()));
		}
		else if (this == Diamond) {
			this.ore = new OreItemStack(net.minecraft.init.Blocks.diamond_ore);
			Ores.manager.registerOre(this.oreName, net.minecraft.init.Blocks.diamond_ore);
		}
		else if (this == Emerald) {
			this.ore = new OreItemStack(net.minecraft.init.Blocks.emerald_ore);
			Ores.manager.registerOre(this.oreName, net.minecraft.init.Blocks.emerald_ore);
		}
		
		// Register Nether Ore
		this.netherOre = new OreItemStack(new BlockOre(this.getDefaultConfigNether(), true));
		
		// Register Storage Block
		if (!this.isVanilla()) {
			this.block = new OreItemStack(new BlockCore(Material.iron, this.blockName)
				.setCreativeTab(CreativeTabs.tabBlock)
				.setHardness(5.0F)
				.setResistance(10.0F)
			.	setStepSound(Block.soundTypeMetal));
			OreDictionary.registerOre(this.blockName, this.block.source);
		}
		else if (this == Diamond) {
			this.block = new OreItemStack(net.minecraft.init.Blocks.diamond_block);
		}
		else if (this == Emerald) {
			this.block = new OreItemStack(net.minecraft.init.Blocks.emerald_block);
		}
		
	}

	@Override
	public void registerItems() {
		// Register Gem
		if (!this.isVanilla()) {
			this.gem = new OreItemStack(new ItemCore(this.gemName).setCreativeTab(CreativeTabs.tabMaterials));
		}
		else if (this == Diamond) {
			this.gem = new OreItemStack(net.minecraft.init.Items.diamond);
		}
		else if (this == Emerald) {
			this.gem = new OreItemStack(net.minecraft.init.Items.emerald);
		}
	}

	@Override
	public void registerRecipes() {
		// register ore smelt & grinds
		switch (this) {
		case Diamond:
		case Emerald:
			RecipeManager.addGrinderRecipe(this.ore.newStack(), this.gem.newStack(2));
			break;
		case Apatite:
			RecipeManager.addSmelting(this.ore.newStack(), this.gem.newStack(6), 0.0F);
			RecipeManager.addGrinderRecipe(this.ore.newStack(), this.gem.newStack(6));
			break;
		default:
			RecipeManager.addSmelting(this.ore.newStack(), this.gem.newStack(), 0.0F);
			RecipeManager.addGrinderRecipe(this.ore.newStack(), this.gem.newStack(2));
		}
		
		//register nether ore smelt
		RecipeManager.addSmelting(this.netherOre.newStack(), this.ore.newStack(2), 0.0F);
		
		// register gem -> oreblock
		if (!this.isVanilla()) {
			RecipeManager.addShapedRecipe(this.block.newStack(), "ggg", "ggg", "ggg", 'g', this.gemName);
		}
		// register oreblock -> gem
		if (!this.isVanilla()) {
			RecipeManager.addShapelessRecipe(this.gem.newStack(9), this.block.newStack());
		}
		// register uuMatter costs
		if (this._uuCost != 0.0D) {
			RecipeManager.addUUMatterRecipe(this.gem.source, this._uuCost);
		}
	}

	public void registerAspects() {
		if (!Helpers.ThaumCraft.isLoaded())
			return;
		
	    switch (this) {
	    case Apatite:
	      ThaumcraftApi.registerObjectTag(this.gemName, new AspectList().add(Aspect.CRYSTAL, 3).add(Aspect.CROP, 1));
	      ThaumcraftApi.registerObjectTag(this.oreName, new AspectList().add(Aspect.CRYSTAL, 2).add(Aspect.EARTH, 1));
	      ThaumcraftApi.registerObjectTag(this.blockName, new AspectList().add(Aspect.CRYSTAL, 6).add(Aspect.CROP, 4));
	      ThaumcraftApi.registerObjectTag(this.netherOreName, new AspectList().add(Aspect.CRYSTAL, 2).add(Aspect.ENERGY, 1).add(Aspect.EARTH, 1).add(Aspect.FIRE, 1));
	      break;
	    default:
	      if (!isVanilla()) {
	        ThaumcraftApi.registerObjectTag(this.gemName, new AspectList().add(Aspect.CRYSTAL, 4).add(Aspect.GREED, 4));
	        ThaumcraftApi.registerObjectTag(this.oreName, new AspectList().add(Aspect.EARTH, 1).add(Aspect.GREED, 3).add(Aspect.CRYSTAL, 3));
	        ThaumcraftApi.registerObjectTag(this.blockName, new AspectList().add(Aspect.CRYSTAL, 6).add(Aspect.GREED, 6));
	      }
	      ThaumcraftApi.registerObjectTag(this.netherOreName, new AspectList().add(Aspect.EARTH, 1).add(Aspect.FIRE, 1).add(Aspect.GREED, 3).add(Aspect.CRYSTAL, 3));
	    }
	}

	@Override
	public int getTradeToAmount(Random random) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int getTradeFromAmount(Random random) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void registerFluids() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public int getLaserWeight() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void registerGases() {
		// TODO Auto-generated method stub
		
	}

} public enum MetallicOres implements IOreList {
	Adamantine(3, Aspect.ARMOR, 3500.0D),
	Aluminium(2, Aspect.EXCHANGE, 650.0D),
	Ardite(4, Aspect.VOID, 2200.0D),
	Brass(Aspect.MECHANISM, true),
	Bronze(Aspect.MECHANISM, true),
	Cobalt(4, Aspect.CRAFT, 1500.0D),
	Coldiron(2, Aspect.COLD, 2000.0D),
	Copper(1, Aspect.EXCHANGE, 165.32555827439467D),
	Electrum(Aspect.EXCHANGE, true),
	Gold(2, Aspect.GREED, 0.0D), // 1888.8470535343595
	Iron(1, Aspect.METAL, 0.0D), // 200.16909378760914
	Lead(1, Aspect.ORDER, 1673.377568334827D),
	Manganese(2, Aspect.ORDER, 800.0D),
	Mithril(3, Aspect.MAGIC, 3200.0D),
	Nickel(2, Aspect.ORDER, 1200.0D),
	Osmium(1, Aspect.ARMOR, 1000.D),
	Platinum(2, Aspect.GREED, 2500.0D),
	Silver(2, Aspect.GREED, 1750.0D),
	Tin(1, Aspect.CRYSTAL, 199.90120532935603D),
	Yellorium(2, Aspect.ENERGY, 2608.8982568638758D),
	Zinc(2, Aspect.CRYSTAL, 1100.0D);
	
	public static ArrayList<MetallicOres> mekanismOres = new ArrayList();

	public String oreName;
	public String netherOreName;
	public String blockName;
	public String ingotName;
	public String nuggetName;
	public String dustName;
	public String tinyDustName;
	public String crushedOreName;
	public String purifiedCrushedOreName;
	public String clusterName;
	public String clumpName;
	public String dirtyDustName;
	public String shardName;
	public String slurryName;
	public String cleanSlurryName;
	public String crystalName;
	public String moltenFluidName;
	public String moltenFluidBlockName;
	public String bucketName;
	
	public OreItemStack ore;
	public OreItemStack netherOre;
	public OreItemStack block;
	public OreItemStack ingot;
	public OreItemStack nugget;
	public OreItemStack dust;
	public OreItemStack tinyDust;
	public OreItemStack crushedOre;
	public OreItemStack purifiedCrushedOre;
	public OreItemStack cluster;
	public OreItemStack clump;
	public OreItemStack dirtyDust;
	public OreItemStack shard;
	public OreItemStack crystal;
	public OreItemStack bucket;
	
	public OreGas slurry;
	public OreGas cleanSlurry;
	
	public Fluid moltenFluid;
	public Block moltenFluidBlock;
	
	public boolean isAlloy;

	private int _harvestLevel;
	private int _xpLow;
	private int _xpHigh;
	private OreDrops _drops;
	private OreSources _source;
	private float _smeltXP;
	private Aspect _secondaryAspect;
	private int _tradeToAmount;
	private int _tradeFromAmount;
	private double _uuCost;
	
	public boolean enabled;
	
	private MetallicOres(Aspect secondaryAspect, boolean isAlloy) {
		this(0, secondaryAspect, isAlloy, 0.0D);
	}
	
	private MetallicOres(int harvestLevel, Aspect secondaryAspect, double uuCost) {
		this(harvestLevel, secondaryAspect, false, uuCost);
	}
		
	private MetallicOres(int harvestLevel, Aspect secondaryAspect, boolean isAlloy, double uuCost) {
		this(harvestLevel, secondaryAspect, isAlloy, 0, 0, uuCost);
	}
	
	private MetallicOres(int harvestLevel, Aspect secondaryAspect, boolean isAlloy, int tradeToAmount, int tradeFromAmount, double uuCost) {
		this.oreName = "ore" + this.toString();
		this.netherOreName = "oreNether" + this.toString();
		this.blockName = "block" + this.toString();

		this.ingotName = "ingot" + this.toString();
		this.nuggetName = "nugget" + this.toString();
		this.dustName = "dust" + this.toString();
		this.tinyDustName = "dustTiny" + this.toString(); 
		this.crushedOreName = "crushed" + this.toString();
		this.purifiedCrushedOreName = "crushedPurified" + this.toString(); 
		this.clusterName = "cluster" + this.toString();
		this.clumpName = "clump" + this.toString();
		this.dirtyDustName = "dustDirty" + this.toString();
		this.shardName = "shard" + this.toString();
		this.crystalName = "crystal" + this.toString();
		this.slurryName = "slurry" + this.toString();
		this.cleanSlurryName = "slurryClean" + this.toString();
		this.moltenFluidName = this.toString().toLowerCase() + ".molten";
		this.moltenFluidBlockName = "fluid.molten." + this.toString().toLowerCase();
		this.bucketName = "bucketMolten" + this.toString();
		
		this.enabled = true;

		this._harvestLevel = harvestLevel;
		this._xpLow = 0;
		this._xpHigh = 0;
		this._source = OreSources.DEFAULT;
		this.isAlloy = isAlloy;
		this._drops = OreDrops.ORE;
		this._secondaryAspect = secondaryAspect;
		this._uuCost = uuCost;
	}

	@Override
	public OreClass getDefaultConfig() {
		return new OreClass(this.oreName, this.enabled, this._harvestLevel, 
				this._xpLow, this._xpHigh, this._drops, this._source);
	}

	@Override
	public OreClass getDefaultConfigNether() {
		return new OreClass(this.netherOreName, this.enabled, this._harvestLevel, 
				this._xpLow, this._xpHigh, this._drops, this._source);
	}
	
	private boolean isVanilla() {
		return (this == Iron || this == Gold);
	}

	@Override
	public void registerBlocks() {
		// Register Ore
		if (!this.isVanilla() && !this.isAlloy) {
			this.ore = new OreItemStack(new BlockOre(this.getDefaultConfig()));
		}
		else if (this == Gold) {
			this.ore = new OreItemStack(net.minecraft.init.Blocks.gold_ore);
		}
		else if (this == Iron) {
			this.ore = new OreItemStack(net.minecraft.init.Blocks.iron_ore);
		}
		
		// Register Nether Ore
		if (!this.isAlloy)	{
			this.netherOre = new OreItemStack(new BlockOre(this.getDefaultConfigNether(), true));
		}
		
		// Register Storage Block
		if (!this.isVanilla()) {
			this.block = new OreItemStack(new BlockCore(Material.iron, this.blockName)
				.setCreativeTab(CreativeTabs.tabBlock)
				.setHardness(5.0F)
				.setResistance(10.0F)
				.setStepSound(Block.soundTypeMetal));
			OreDictionary.registerOre(this.blockName, this.block.source);
		}
		else if (this == Gold) {
			this.block = new OreItemStack(net.minecraft.init.Blocks.gold_block);
		}
		else if (this == Iron) {
			this.block = new OreItemStack(net.minecraft.init.Blocks.iron_block);
		}
	}

	@Override
	public void registerItems() {
		// Register Ingot
		if (!this.isVanilla()) {
			this.ingot = new OreItemStack(new ItemCore(this.ingotName).setCreativeTab(CreativeTabs.tabMaterials));
		}
		else if (this == Gold) {
			this.ingot = new OreItemStack(net.minecraft.init.Items.gold_ingot);
		}
		else if (this == Iron) {
			this.ingot = new OreItemStack(net.minecraft.init.Items.iron_ingot);
		}
		
		// Register Nugget
		if (this != Gold) {
			this.nugget = new OreItemStack(new ItemCore(this.nuggetName).setCreativeTab(CreativeTabs.tabMaterials));
		}
		else {
			this.nugget = new OreItemStack(net.minecraft.init.Items.gold_nugget);
		}
		
		// Register Dust & Tiny Dust
		this.dust = new OreItemStack(new ItemCore(this.dustName).setCreativeTab(CreativeTabs.tabMaterials));
		this.tinyDust = new OreItemStack(new ItemCore(this.tinyDustName).setCreativeTab(CreativeTabs.tabMaterials));

		// Register Crushed & Purified Crushed Ores
		if (!this.isAlloy) {
			this.crushedOre = new OreItemStack(new ItemCore(this.crushedOreName).setCreativeTab(CreativeTabs.tabMaterials));
			this.purifiedCrushedOre = new OreItemStack(new ItemCore(this.purifiedCrushedOreName).setCreativeTab(CreativeTabs.tabMaterials));
		}
		
		// register native clusters
		if (!this.isAlloy) {
			this.cluster = new OreItemStack(new ItemCore(this.clusterName).setCreativeTab(CreativeTabs.tabMaterials));
		}
		
		// register clumps & dirty dusts
		if (!this.isAlloy) {
			this.clump = new OreItemStack(new ItemCore(this.clumpName).setCreativeTab(CreativeTabs.tabMaterials));
			this.dirtyDust = new OreItemStack(new ItemCore(this.dirtyDustName).setCreativeTab(CreativeTabs.tabMaterials));
			this.shard = new OreItemStack(new ItemCore(this.shardName).setCreativeTab(CreativeTabs.tabMaterials));
			this.crystal = new OreItemStack(new ItemCore(this.crystalName).setCreativeTab(CreativeTabs.tabMaterials));
		}
		
		// register bucket of molten ore
		this.bucket = new OreItemStack(new OreBucket(this.bucketName, this.moltenFluidBlock).setCreativeTab(CreativeTabs.tabMisc));
	}

	@Override
	public void registerRecipes() {
		OreItemStack stoneDust = new OreItemStack(new ItemStack(Helpers.IC2.getItem("itemDust"), 1, 9));

		if (!this.isVanilla()) {
			// add ingot -> oreBlock recipe
			RecipeManager.addShapedRecipe(this.block.newStack(), "iii", "iii", "iii", 'i', ingotName);
			
			// add oreBlock -> ingot recipe
			RecipeManager.addShapelessRecipe(this.ingot.newStack(9), this.block.newStack());
			
			// add ore smelting recipe
			if (!this.isAlloy) {
				RecipeManager.addSmelting(this.ore.newStack(), this.ingot.newStack(), this._smeltXP);
			}
		}
		
		if (!this.toString().equals("Gold")) {
			// add ingot -> nugget recipe
			if (this.toString().equals("Iron")) {
				RecipeManager.addShapelessRecipe(this.nugget.newStack(9), this.ingot.newStack());
			}
			else {
				RecipeManager.addShapelessRecipe(this.nugget.newStack(9), ingotName);
			}
			
			// add nugget -> ingot recipe
			RecipeManager.addShapedRecipe(this.ingot.newStack(), "nnn", "nnn", "nnn", 'n', this.nuggetName);
		}
		
		// add ingot Grinder recipes
		RecipeManager.addGrinderRecipe(this.ingot.newStack(), this.dust.newStack());
		
		// add ingot pulverizer (TE) recipes
		if (Helpers.ThermalExpansion.isLoaded()) {
			NBTTagCompound metadata = new NBTTagCompound();
			metadata.setInteger("energy", 2400);
			Helpers.ThermalExpansion.registerRecipe(RecipeType.Grinder, this.ingot.newStack(), metadata, this.dust.newStack());
		}
		
		if (!this.isAlloy) {
			// add nether ore -> ore smelting recipe
			RecipeManager.addSmelting(this.netherOre.newStack(), this.ore.newStack(2), 0.0F);
			
			// add crushed ore smelting recipe
			RecipeManager.addSmelting(this.crushedOre.newStack(), this.ingot.newStack(), this._smeltXP);
			
			// add purified crushed ore smelting recipe
			RecipeManager.addSmelting(this.purifiedCrushedOre.newStack(), this.ingot.newStack(), this._smeltXP);
			
			// add ore grinder recipe
			RecipeManager.addGrinderRecipe(this.ore.newStack(), this.crushedOre.newStack(2));
			
			// Register Thermal Expansion Pulverizer recipe
			if (Helpers.ThermalExpansion.isLoaded()) {
				NBTTagCompound metadata = new NBTTagCompound();
				metadata.setInteger("energy", 4000);
				Helpers.ThermalExpansion.registerRecipe(RecipeType.Grinder, this.ore.newStack(), metadata, this.crushedOre.newStack(2));
			}
			
			if (Helpers.Mekanism.isLoaded() && !mekanismOres.contains(this)) {
				// register slurrys
				this.cleanSlurry = (OreGas)GasRegistry.register(new OreGas(this.cleanSlurryName, this.cleanSlurryName).setVisible(false));
				this.slurry = (OreGas)GasRegistry.register(new OreGas(this.slurryName, this.slurryName).setCleanGas(this.cleanSlurry).setVisible(false));
				
				NBTTagCompound metadata = new NBTTagCompound();
				metadata.setString("gas", "hydrogenChloride");
				
				for (ItemStack dictionaryOre : OreDictionary.getOres(this.oreName)) {
					OreItemStack oreStack = new OreItemStack(dictionaryOre);
					
					// register Mekanism ore->dust enrichment chamber recipe
					Helpers.Mekanism.registerRecipe(RecipeType.EnrichmentChamber, oreStack.newStack(), this.dust.newStack(2));
					
					// register Mekanism ore->clump purification chamber recipe
					Helpers.Mekanism.registerRecipe(RecipeType.PurificationChamber, oreStack.newStack(), this.clump.newStack(3));
					
					// register Mekanism ore->shard chemical injector recipe
					Helpers.Mekanism.registerRecipe(RecipeType.ChemicalInjector, oreStack.newStack(), metadata, this.shard.newStack(4));
					
					// register Mekanism chemical dissolution chamber recipe
					Helpers.Mekanism.registerGasRecipe(RecipeType.ChemicalDissolver, oreStack.newStack(), null, new GasStack(this.slurry, 1000));
					
				}
				
				// register Mekanism dirty dust to dust
				Helpers.Mekanism.registerRecipe(RecipeType.EnrichmentChamber, this.dirtyDust.newStack(), this.dust.newStack());
				
				// register Mekanism shard to clump recipe
				Helpers.Mekanism.registerRecipe(RecipeType.PurificationChamber, this.shard.newStack(), this.clump.newStack());
				
				// register Mekanism crystal to shard recipe
				Helpers.Mekanism.registerRecipe(RecipeType.ChemicalInjector, this.crystal.newStack(), metadata, this.shard.newStack());
				
				// register Mekanism clump to dirty dust recipe
				Helpers.Mekanism.registerRecipe(RecipeType.Crusher, this.clump.newStack(), this.dirtyDust.newStack());
				
				// register Mekanism chemical washer recipe
				Helpers.Mekanism.registerGasRecipe(RecipeType.ChemicalWasher, new GasStack(this.slurry, 1), null, new GasStack(this.cleanSlurry, 1));
				
				// register Mekanism chemical crystallizer recipe
				Helpers.Mekanism.registerGasRecipe(RecipeType.ChemicalCrystalizer, new GasStack(this.cleanSlurry, 200), null, this.crystal.newStack());
			}
			
			if (Helpers.IC2.isLoaded()) {
				// add ore washing recipe
				NBTTagCompound metadata = new NBTTagCompound();
				metadata.setInteger("amount", 1000);
				switch(this) {
				case Lead:
					Helpers.IC2.registerRecipe(RecipeType.OreWasher, this.crushedOre.newStack(), metadata, new ItemStack[] {
						this.purifiedCrushedOre.newStack(),
						DustyOres.Sulfur.tinyDust.newStack(3),
						stoneDust.newStack()	});
					break;
				default:
					Helpers.IC2.registerRecipe(RecipeType.OreWasher, this.crushedOre.newStack(), metadata, new ItemStack[] {
						this.purifiedCrushedOre.newStack(),
						this.tinyDust.newStack(2),
						stoneDust.newStack()	});
				}
			}
		}
		
		// add centrifuge recipes
		if (Helpers.IC2.isLoaded()) {
			NBTTagCompound metadata = new NBTTagCompound();
			switch (this) {
			case Adamantine:
				this.registerIC2Centrifuge(4000, MetallicOres.Iron.tinyDust.newStack());
				break;
			case Aluminium:
				this.registerIC2Centrifuge(1000, MetallicOres.Iron.tinyDust.newStack());
				break;
			case Ardite:
				this.registerIC2Centrifuge(4000, Items.dustTinyTungsten.item.newStack());
				break;
			case Brass:
				metadata.setInteger("minHeat", 2000);
				Helpers.IC2.registerRecipe(RecipeType.Centrifuge, this.dust.newStack(4), metadata, new ItemStack[] {
					MetallicOres.Copper.dust.newStack(3),
					MetallicOres.Zinc.dust.newStack()		});
				break;
			case Bronze:
				metadata.setInteger("minHeat", 2000);
				Helpers.IC2.registerRecipe(RecipeType.Centrifuge, this.dust.newStack(4), metadata, new ItemStack[] {
					MetallicOres.Copper.dust.newStack(3),
					MetallicOres.Tin.dust.newStack()		});
				break;
			case Cobalt:
				this.registerIC2Centrifuge(3000, MetallicOres.Copper.tinyDust.newStack());
				break;
			case Coldiron:
				this.registerIC2Centrifuge(1500, MetallicOres.Iron.tinyDust.newStack());
				break;
			case Electrum:
				metadata.setInteger("minHeat", 2500);
				Helpers.IC2.registerRecipe(RecipeType.Centrifuge, this.dust.newStack(2), metadata, new ItemStack[] {
					MetallicOres.Gold.dust.newStack(),
					MetallicOres.Silver.dust.newStack()		});
				break;
			case Manganese:
				this.registerIC2Centrifuge(1500, MetallicOres.Iron.tinyDust.newStack());
				break;
			case Mithril:
				this.registerIC2Centrifuge(2500, MetallicOres.Silver.tinyDust.newStack());
				break;
			case Nickel:
				this.registerIC2Centrifuge(2000, DustyOres.Sulfur.tinyDust.newStack());
				break;
			case Osmium:
				this.registerIC2Centrifuge(4000, DustyOres.Sulfur.tinyDust.newStack());
				break;
			case Platinum:
				this.registerIC2Centrifuge(3000, DustyOres.Sulfur.tinyDust.newStack());
				break;
			case Yellorium:
				this.registerIC2Centrifuge(3000, MetallicOres.Iron.tinyDust.newStack());
				break;
			case Zinc:
				this.registerIC2Centrifuge(500, DustyOres.Sulfur.tinyDust.newStack());
				break;
			default:
			}

		}
		
		// add uuMatter Scanner costs
		if (this._uuCost != 0.0D) {
			RecipeManager.addUUMatterRecipe(this.ore.source, this._uuCost);
		}
		
		// add dust smelting recipe
		RecipeManager.addSmelting(this.dust.newStack(), this.ingot.newStack(), this._smeltXP);
		
		// add tiny dust -> dust recipe
		RecipeManager.addShapedRecipe(this.dust.newStack(), "ttt", "ttt", "ttt", 't', this.tinyDustName);
		
		// add dust -> tiny dust recipe
		RecipeManager.addShapelessRecipe(this.tinyDust.newStack(9), this.dust.newStack());
		
		if (!this.isAlloy) {
			// add thaumcraft ore -> native cluster crucible recipes
			switch (this) {
			case Iron:
			case Gold:
			case Tin:
			case Copper:
			case Lead:
			case Silver:
				break;
			default:
				RecipeManager.addCrucibleRecipe("PUREIRON", this.cluster.newStack(), this.oreName, new AspectList().add(Aspect.METAL, 1).add(Aspect.ORDER, 1));
				break;
			}
			
			// add native cluster smelting
			RecipeManager.addSmelting(this.cluster.newStack(), this.ingot.newStack(2), this._smeltXP);
		}
	}
	
	private void registerIC2Centrifuge(int minHeat, ItemStack secondary) {
		OreItemStack stoneDust = new OreItemStack(new ItemStack(Helpers.IC2.getItem("itemDust"), 1, 9));
		NBTTagCompound metadata = new NBTTagCompound();
		metadata.setInteger("minHeat", minHeat);
		Helpers.IC2.registerRecipe(RecipeType.Centrifuge, this.crushedOre.newStack(), metadata, new ItemStack[] {
			this.dust.newStack(),
			secondary,
			stoneDust.newStack()
		});
		Helpers.IC2.registerRecipe(RecipeType.Centrifuge, this.purifiedCrushedOre.newStack(), metadata, new ItemStack[] {
			this.dust.newStack(),
			secondary
		});
	}

	public void registerAspects() {
	    if (!Helpers.ThaumCraft.isLoaded()) {
	        return;
	      }
	      if ((!isVanilla()) && (this != Copper) && (this != Tin) && (this != Silver) && (this != Lead)) {
	        ThaumcraftApi.registerObjectTag(this.nuggetName, new AspectList().add(Aspect.METAL, 1));
	        ThaumcraftApi.registerObjectTag(this.ingotName, new AspectList().add(Aspect.METAL, 3).add(this._secondaryAspect, 1));
	        ThaumcraftApi.registerObjectTag(this.dustName, new AspectList().add(Aspect.METAL, 2).add(Aspect.ENTROPY, 1).add(this._secondaryAspect, 1));
	        ThaumcraftApi.registerObjectTag(this.oreName, new AspectList().add(Aspect.METAL, 2).add(Aspect.EARTH, 1).add(this._secondaryAspect, 1));
	        ThaumcraftApi.registerObjectTag(this.blockName, new AspectList().add(Aspect.METAL, 5).add(this._secondaryAspect, 3));
	      }
	      ThaumcraftApi.registerObjectTag(this.netherOreName, new AspectList().add(Aspect.METAL, 2).add(this._secondaryAspect, 2).add(Aspect.EARTH, 1).add(Aspect.FIRE, 1));
	}

	@Override
	public int getTradeToAmount(Random random) {
		if (this._tradeToAmount <= 0) {
			return 0;
		}
		return this._tradeToAmount + random.nextInt(this._tradeToAmount / 4);
	}

	@Override
	public int getTradeFromAmount(Random random) {
		if (this._tradeFromAmount <= 0) {
			return 0;
		}
		return this._tradeFromAmount + random.nextInt(this._tradeFromAmount / 4);
	}

	@Override
	public void registerFluids() {
		if (FluidRegistry.isFluidRegistered(this.moltenFluidName)) {
			this.moltenFluid = FluidRegistry.getFluid(this.moltenFluidName);
			this.moltenFluidBlock = this.moltenFluid.getBlock();
			if (this.moltenFluidBlock == null) {
				this.moltenFluidBlock = new BlockOreFluid(this.moltenFluid, this.moltenFluidBlockName);
			}
			
		}
		else {
			this.moltenFluid = new OreFluid(this.moltenFluidName);
			this.moltenFluidBlock = new BlockOreFluid(this.moltenFluid, this.moltenFluidBlockName).setCreativeTab(CreativeTabs.tabMaterials);
		}
		if (FluidContainerRegistry.fillFluidContainer(new FluidStack(this.moltenFluid, 1000), new ItemStack(net.minecraft.init.Items.bucket)) == null) {
			FluidContainerRegistry.registerFluidContainer(
					new FluidStack(this.moltenFluid, 1000), 
					this.bucket.newStack(), 
					new ItemStack(net.minecraft.init.Items.bucket));
		}

	}

	@Override
	public int getLaserWeight() {
		// TODO Auto-generated method stub
		return 0;
	}
	
	static {
		mekanismOres.add(Iron);
		mekanismOres.add(Gold);
		mekanismOres.add(Osmium);
		mekanismOres.add(Copper);
		mekanismOres.add(Tin);
		mekanismOres.add(Lead);
		mekanismOres.add(Silver);
	}

	@Override
	public void registerGases() {
		// TODO Auto-generated method stub
		
	}
	
} public class OreItemStack implements IRecipeInput {
	public ItemStack source;
	
	public OreItemStack(ItemStack input) {
		if (input == null) {
			this.source = null;
		}
		else {
			this.source = input.copy();
			this.source.stackSize = 1;
		}
	}
	
	public OreItemStack(Item input) {
		this(new ItemStack(input, 1));
	}
	
	public OreItemStack(Item input, int damageValue) {
		this(new ItemStack(input, 1, damageValue));
	}
	
	public OreItemStack(Block input) {
		this(new ItemStack(input, 1));
	}
	
	public OreItemStack(Block input, int meta) {
		this(new ItemStack(input, 1, meta));
	}
	
	@Override
	public boolean matches(ItemStack subject) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public int getAmount() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public List<ItemStack> getInputs() {
		// TODO Auto-generated method stub
		return null;
	}

	public ItemStack newStack() {
		return this.newStack(1);
	}
	
	public ItemStack newStack(int size) {
		if (this.source == null) {
			return null;
		}
		this.source.stackSize = size;
		return this.source.copy();
	}
	
	public Block getSourceBlock() {
		return Block.getBlockFromItem(this.getSourceItem());
	}
	
	public Item getSourceItem() {
		return this.source.getItem();
	}
	
}
import java.util.Random;
import tw.oresplus.items.ItemManager;
import tw.oresplus.items.OreArmor;
import tw.oresplus.items.OreAxe;
import tw.oresplus.items.OreHoe;
import tw.oresplus.items.OrePickaxe;
import tw.oresplus.items.OreSpade;
import tw.oresplus.items.OreSword;
import tw.oresplus.ores.GemstoneOres;
import tw.oresplus.ores.MetallicOres;
import tw.oresplus.recipes.OreItemStack;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.item.Item;
import net.minecraft.item.Item.ToolMaterial;
import net.minecraft.item.ItemArmor.ArmorMaterial;
import net.minecraft.item.ItemTool;
import net.minecraft.village.MerchantRecipe;
import net.minecraft.village.MerchantRecipeList;
import cpw.mods.fml.common.registry.VillagerRegistry;
import cpw.mods.fml.common.registry.VillagerRegistry.IVillageTradeHandler;
package tw.oresplus.worldgen;



public class VillagerTradeHandler implements IVillageTradeHandler {
	public static final int VILLAGER_FARMER = 0;
	public static final int VILLAGER_LIBRARIAN = 1;
	public static final int VILLAGER_PRIEST = 2;
	public static final int VILLAGER_BLACKSMITH = 3;
	public static final int VILLAGER_BUTCHER = 4;

	private int _villagerID;
	
	public VillagerTradeHandler(int villagerID) {
		this._villagerID = villagerID;
	}
	
	@Override
	public void manipulateTradesForVillager(EntityVillager villager,
			MerchantRecipeList recipeList, Random random) {
		switch (this._villagerID) {
		case VILLAGER_BLACKSMITH:
			recipeList.add(this.getMerchantRecipeFor(ItemManager.armorAdamantineBoots, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.armorAdamantineChestplate, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.armorAdamantineHelmet, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.armorAdamantineLeggings, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.toolAdamantineAxe, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.toolAdamantineHoe, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.toolAdamantinePickaxe, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.toolAdamantineSpade, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.toolAdamantineSword, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.armorColdironBoots, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.armorColdironChestplate, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.armorColdironHelmet, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.armorColdironLeggings, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.toolColdironAxe, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.toolColdironHoe, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.toolColdironPickaxe, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.toolColdironSpade, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.toolColdironSword, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.armorMithralBoots, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.armorMithralChestplate, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.armorMithralHelmet, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.armorMithralLeggings, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.toolMithralAxe, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.toolMithralHoe, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.toolMithralPickaxe, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.toolMithralSpade, random));
			recipeList.add(this.getMerchantRecipeFor(ItemManager.toolMithralSword, random));
			int tradeAmount;
			for (MetallicOres ore : MetallicOres.values()) {
				tradeAmount = ore.getTradeToAmount(random);
				if (tradeAmount > 0) {
					recipeList.add(new MerchantRecipe(ore.ingot.newStack(tradeAmount), GemstoneOres.Emerald.gem.newStack()));
				}
				tradeAmount = ore.getTradeFromAmount(random);
				if (tradeAmount > 0) {
					recipeList.add(new MerchantRecipe(GemstoneOres.Emerald.gem.newStack(), ore.ingot.newStack(tradeAmount)));
				}
			}
			break;
		default:
		}
	}
	
	private MerchantRecipe getMerchantRecipeFor(OreItemStack item, Random random) {
		int itemTypeCost = 0;
		int materialCost = 0;
		Item source = item.source.getItem();
		if (source instanceof OreArmor) {