@Mod(modid = References.MOD_ID, name = References.MOD_NAME, version = References.MOD_VERSION, dependencies="required-after:Forge@10.13.0.1180;after:TConstruct")
public class OresPlus {
	
	@SidedProxy(clientSide="tw.oresplus.client.ClientProxy", serverSide="tw.oresplus.core.ServerProxy") 
	public static IProxy proxy;
	
	@Instance(References.MOD_ID)
	public static OresPlus instance;

    public static OreLog log;
    
    public static ConfigMain config = new ConfigMain();
    
    public static String regenKeyOre = "DEFAULT";
    public static String regenKeyOil = "DEFAULT";
    public static String regenKeyRubberTree = "DEFAULT";
    public static String regenKeyBeehives = "DEFAULT";

    public static boolean angryPigmen = true;
    public static boolean debugMode = false;
    public static boolean difficultAlloys = false;
    public static boolean easyMineralSmelt = true;
    public static boolean iridiumPlateRecipe = true;
    public static boolean logRegenerations = false;
    
    public static WorldGenCore worldGen = new WorldGenCore();
    public static OreEventHandler eventHandler = new OreEventHandler();
    public static BucketHandler bucketHandler = new BucketHandler();
    public static TickHandler tickHandler = new TickHandler();
    public static IMCHandler imcHandler = new IMCHandler();
    public static ItemMapHelper itemMapHelper;
    
    @EventHandler
    public void preInit(FMLPreInitializationEvent event) {
    	log.init();
    	
		RecipeManager.init();

		ConfigCore.setBaseDir(event.getModConfigurationDirectory());
		config.init(event);
		
		config.load();
		
	    angryPigmen = config.getBoolean("angryPigmen", angryPigmen, "set to false to prevent zombie pigmen from attacking when mining nether ores");
	    debugMode = config.getBoolean("debugMode", debugMode, "set to true to enable finer debug logging");
	    difficultAlloys = config.getBoolean("difficultAlloys", difficultAlloys, "enable true to set brass & bronze alloy recipes to output only 2 dusts");
	    easyMineralSmelt = config.getBoolean("easyMineralSmelt", easyMineralSmelt, "disable to prevent Mineral ores smelting directly into metal");
	    iridiumPlateRecipe = config.getBoolean("iridiumPlateRecipe", iridiumPlateRecipe, "enables an ore dictionary-enabled recipe for iridium plate");
	    logRegenerations = config.getBoolean("logRegenerations", logRegenerations, "enable to log all regenerations that occur");

	    regenKeyOre = config.getString(ConfigCore.CAT_REGEN, "regenKey", regenKeyOre, "change this to regenerate ores");
	    regenKeyOil = config.getString(ConfigCore.CAT_REGEN, "regenKeyOil", regenKeyOil, "change this to regenerate buildcraft oil wells");
	    regenKeyRubberTree = config.getString(ConfigCore.CAT_REGEN, "regenKeyRubberTree", regenKeyRubberTree, "change this to regenerate IC2 rubber trees");
	    regenKeyBeehives = config.getString(ConfigCore.CAT_REGEN, "regenKeyBeehives", regenKeyBeehives, "change this to regenerate Forestry beehives");
		
		Ores.manager = new OreManager();
		
    	BlockManager.init();
    	ItemManager.init();
    	FluidManager.init();
    	GasManager.init();

    	// register aluminium->aluminum ore dictionary 
    	OreDictionary.registerOre("oreAluminum", MetallicOres.Aluminium.ore.source);
    	OreDictionary.registerOre("oreNetherAluminum", MetallicOres.Aluminium.netherOre.source);
    	OreDictionary.registerOre("blockAluminum", MetallicOres.Aluminium.block.source);
    	OreDictionary.registerOre("ingotAluminum", MetallicOres.Aluminium.ingot.source);
    	OreDictionary.registerOre("nuggetAluminum", MetallicOres.Aluminium.nugget.source);
    	OreDictionary.registerOre("crushedAluminum", MetallicOres.Aluminium.crushedOre.source);
    	OreDictionary.registerOre("crushedPurifiedAluminum", MetallicOres.Aluminium.purifiedCrushedOre.source);
    	OreDictionary.registerOre("dustAluminum", MetallicOres.Aluminium.dust.source);
    	OreDictionary.registerOre("dustTinyAluminum", MetallicOres.Aluminium.tinyDust.source);
    	OreDictionary.registerOre("clusterAluminum", MetallicOres.Aluminium.cluster.source);
    	OreDictionary.registerOre("dustDirtyAluminum", MetallicOres.Aluminium.dirtyDust.source);
    	OreDictionary.registerOre("clumpAluminum", MetallicOres.Aluminium.clump.source);
    	OreDictionary.registerOre("shardAluminum", MetallicOres.Aluminium.shard.source);
    	OreDictionary.registerOre("crystalAluminum", MetallicOres.Aluminium.crystal.source);
    	// register mercury-> quicksilver ore dictionary
    	OreDictionary.registerOre("quicksilver", Items.itemMercury.item.source);
    	
    	//Register Ore Generators
    	log.info("Registering Ore Generators");
    	for (OreGenerators oreGen : OreGenerators.values()) {
    		oreGen.registerGenerator();
    	}
    	for (OreGeneratorsNether oreGen : OreGeneratorsNether.values()) {
    		oreGen.registerGenerator();
    	}
    	for (OreGeneratorsEnd oreGen : OreGeneratorsEnd.values()) {
    		oreGen.registerGenerator();
    	}
    	
		config.save();
		
    	for (Helpers helper : Helpers.values()) {
    		helper.preInit();
    	}
    }
    
    @EventHandler
    public void init(FMLInitializationEvent event) {
    	RecipeManager.initRecipes();
    	
    	GameRegistry.registerTileEntity(TileEntityGrinder.class, "TileEntityGrinder");
    	GameRegistry.registerTileEntity(TileEntityCracker.class, "TileEntityCracker");
    	
    	MinecraftForge.EVENT_BUS.register(eventHandler);
    	MinecraftForge.EVENT_BUS.register(bucketHandler);
    	MinecraftForge.ORE_GEN_BUS.register(eventHandler);
    	FMLCommonHandler.instance().bus().register(tickHandler);
    	
    	NetworkRegistry.INSTANCE.registerGuiHandler(instance, new GuiHandler());
    	
    	itemMapHelper = new ItemMapHelper();
    	
    	//OresTrigger.registerTriggers();
    	//ActionManager.registerTriggerProvider(new TriggerProvider());
    	
    	VillagerRegistry.instance().registerVillageTradeHandler(VillagerTradeHandler.VILLAGER_BLACKSMITH, new VillagerTradeHandler(VillagerTradeHandler.VILLAGER_BLACKSMITH));

    	NetHandler.init();
    	
    	for (Helpers helper : Helpers.values()) {
    		helper.init();
    	}
    }
    
    @EventHandler
    public void postInit(FMLPostInitializationEvent event) {
    	if (debugMode) {
    		Ores.grinderRecipes.debug();
    	}
    	
    	//RecipeManager.replaceRecipeResults();
    	
    	OreChestLoot.registerChestLoot();
    	
    	for (Helpers helper : Helpers.values()) {
    		helper.postInit();
    	}
    }
    
    @EventHandler
	public void recieveIMC(FMLInterModComms.IMCEvent event) {
    	imcHandler.recieveIMC(event);
    }
    
    @EventHandler
    public void handleMissingMaps(FMLMissingMappingsEvent event) {
    	itemMapHelper.handleMissingMaps(event);
    }
    
    @EventHandler
    public void handRemaps(FMLModIdMappingEvent event) {
    	BlockManager.handleRemaps(event);
    }
    
} public class Ores {
	private static Ores instance = new Ores();
	
	public static IOreManager manager;
	
	public static IOreFluidManager fluidManager;
	
	public static IOreRecipeManager grinderRecipes;
	public static IOreFluidRecipeManager crackerRecipes;

	private Ores () {}
	
	private class BlockInfo {
		public String ownerMod;
		public Block block;
		
		public BlockInfo(String owner, Block newBlock) {
			this.ownerMod = owner;
			this.block = newBlock;
		}

	}
	
	
} public class BlockManager {
	private static boolean isInitialized = false;
	
	public static OreItemStack grinder;
	public static OreItemStack grinder_lit;
	public static OreItemStack cracker;
	public static OreItemStack cracker_lit;
	
	public static void init() {
		if (isInitialized) {
			OresPlus.log.info("Block initialization failed, already initialized");
			return;
		}
		OresPlus.log.info("Initializing Blocks");

		for (MetallicOres ore : MetallicOres.values()) {
			ore.registerBlocks();
		}
		
		for (GemstoneOres ore : GemstoneOres.values()) {
			ore.registerBlocks();
		}
		
		for (DustyOres ore : DustyOres.values()) {
			ore.registerBlocks();
		}
		
		for (MineralOres ore : MineralOres.values()) {
			ore.registerBlocks();
		}
		
		for (GeneralOres ore : GeneralOres.values()) {
			ore.registerBlocks();
		}
		
		//nAdditional Ore Dictionary Support
		OreDictionary.registerOre("oreYellorite", MetallicOres.Yellorium.ore.source);
		
		// register machine blocks
		grinder = new OreItemStack(new BlockGrinder(false));
		grinder_lit = new OreItemStack(new BlockGrinder(true));
		RecipeManager.hideItem(grinder_lit);
		
		cracker = new OreItemStack(new BlockCracker(false));
		cracker_lit = new OreItemStack(new BlockCracker(true));
		RecipeManager.hideItem(cracker_lit);
		
		// register vanilla ores for custom ore generators
		Ores.manager.registerOre("oreIron", net.minecraft.init.Blocks.iron_ore);
		Ores.manager.registerOre("oreGold", net.minecraft.init.Blocks.gold_ore);
		Ores.manager.registerOre("oreDiamond", net.minecraft.init.Blocks.diamond_ore);
		Ores.manager.registerOre("oreEmerald", net.minecraft.init.Blocks.emerald_ore);
		Ores.manager.registerOre("oreLapis",  net.minecraft.init.Blocks.lapis_ore);
		Ores.manager.registerOre("oreQuartz", net.minecraft.init.Blocks.quartz_ore);
		Ores.manager.registerOre("oreCoal", net.minecraft.init.Blocks.coal_ore);
		
		isInitialized=true;
	}
	
	public static void handleRemaps(FMLModIdMappingEvent event) {
		OresPlus.log.info("recieved remap event");
		
	}

	public static void registerAspects() {
	    ThaumcraftApi.registerObjectTag(cracker.source, new AspectList());
	    ThaumcraftApi.registerObjectTag(grinder.source, new AspectList());
	}
	
} public class OreDictHelper {
	public static String getName(ItemStack item) {
		int id = OreDictionary.getOreID(item);
		String oreName = OreDictionary.getOreName(id);
		return oreName;
	}
} public class References {
	public static final String MOD_ID = "OresPlus";
    public static final String MOD_NAME = "OresPlus";
    public static final String MOD_VERSION = "@VERSION@";
} public class ConfigMain extends ConfigCore {
	public boolean enableMachines = true;

	public void init(FMLPreInitializationEvent event) {
		
		File configFile = new File(baseConfigDir, References.MOD_ID + ".cfg");
		if (!configFile.exists()) {
			File oldConfigFile = event.getSuggestedConfigurationFile();
			if (oldConfigFile.exists())
				oldConfigFile.renameTo(configFile);
		}
		
		super.init("Main", configFile);
		
	    config.addCustomCategoryComment(CAT_REGEN, "Configure general regeneration options here");
		
		configured = true;
	}
	
	public void load() {
		this.enableMachines = this.getBoolean("enableMachines", this.enableMachines, "Set to false to disable crafting of this mods machinary");
	}

} public class BCHelper extends OresHelper {
	private Class genOilClass;
	private Object genOilClassObj;
	private Method genOilMethod;
	private String[] subMods = { "BuildCraft|Builders", "BuildCraft|Energy", "BuildCraft|Factory", "BuildCraft|Silicon", "BuildCraft|Transport" };
	
	public BCHelper() {
		super("BuildCraft|Core");
	}
	
	public void preInit() {
		if (!this.isLoaded()) {
			OresPlus.log.info("BuildCraft not found, integration helper disabled");
			return;
		}
		
		if (this.isEnergyLoaded()) {
			try {
				this.genOilClass = Class.forName("buildcraft.energy.worldgen.OilPopulate");
			} catch (ClassNotFoundException e) {
				OresPlus.log.info("Could not find OilPopulate class");
				e.printStackTrace();
			}
			
			Constructor c = null;
			try {
				c = this.genOilClass.getDeclaredConstructor();
			} catch (NoSuchMethodException e) {
				OresPlus.log.info("Could not find constructor");
				e.printStackTrace();
			} catch (SecurityException e) {
				OresPlus.log.info("Access denied to contructor");
				e.printStackTrace();
			}
			if (c != null) {
				c.setAccessible(true);
				try {
					this.genOilClassObj = c.newInstance();
				} catch (InstantiationException e) {
					OresPlus.log.info("InstatianException");
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					OresPlus.log.info("Illegal Access");
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					OresPlus.log.info("Illrgal args");
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					OresPlus.log.info("Target exception");
					e.printStackTrace();
				}
			}
			
			if (this.genOilClass != null && this.genOilClassObj != null)
				for (Method method : this.genOilClass.getMethods()) {
					if (method.getName().equals("generateOil")) 
						this.genOilMethod = method;
				
				}
		}	
		OresPlus.log.info("BuildCraft found, integration helper initialized");
	}
	
	@Override
	public void init() {
		if (!this.isLoaded()) 
			return;
	}

	@Override
	public void postInit() {
		if (!this.isLoaded()) 
			return;
	}
	
	private boolean isEnergyLoaded() {
		return Loader.isModLoaded("BuildCraft|Energy");
	}
	
	public void generate(World world, Random rand, int chunkX, int chunkZ) {
		if (!this.isEnergyLoaded() || this.genOilMethod == null)
			return;
		
		try {
			this.genOilMethod.invoke(this.genOilClassObj, world, rand, chunkX, chunkZ);
		} catch (IllegalAccessException e) {
			OresPlus.log.info("Call to OilPopulate.generate was denied");
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			OresPlus.log.info("Call to OilPopulate.generate was failed, illegal arguments");
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			OresPlus.log.info("OilPopulate.generate caused an exception");
			e.printStackTrace();
		}
		
	}

	@Override
	public void registerRecipe(RecipeType recipeType, ItemStack input,
			NBTTagCompound metadata, ItemStack... outputs) { }
	
	@Override
	public Block getBlock(String blockName) {
		Block result = super.getBlock(blockName);
		if (result == null) {
			for (String subModName : subMods ) {
				Block subModResult = GameRegistry.findBlock(subModName, blockName);
				if (subModResult != null) {
					result = subModResult;
				}
			}
		}
		return result;
	}

	@Override
	public void registerGasRecipe(RecipeType recipeType, Object input,
			NBTTagCompound metadata, Object output, Object secondaryOutput) { }

} public enum Helpers {
	AppliedEnergistics(new AppEngHelper()),
	BuildCraft(new BCHelper()),
	Forestry(new ForestryHelper()),
	IC2(new IC2Helper()),
	Mekanism(new MekanismHelper()),
	RailCraft(new RCHelper()),
	ThaumCraft(new TCHelper()),
	ThermalExpansion(new TEHelper()),
	Tinkers(new TinkersHelper()),
	Treecapitator(new TreecapitatorHelper()), 
	BigReactors(new BigReactorsHelper()), 
	MineFactoryReloaded(new MFRHelper());
	
	private OresHelper _oresHelper;
	
	private Helpers(OresHelper oresHelper) {
		_oresHelper = oresHelper;
	}
	
	public void preInit() {
		this._oresHelper.preInit();
	}
	
	public void init() {
		this._oresHelper.init();
	}
	
	public void postInit() {
		this._oresHelper.postInit();
	}
	
	public boolean isLoaded() {
		return this._oresHelper.isLoaded();
	}
	
	public void generate(World world, Random rand, int chunkX, int chunkZ) {
		this._oresHelper.generate(world, rand, chunkX, chunkZ);
	}
	
	public Block getBlock(String blockName) {
		return this._oresHelper.getBlock(blockName);
	}
	
	public Item getItem(String itemName) {
		return this._oresHelper.getItem(itemName);
	}
	
	public void registerRecipe(RecipeType recipeType, ItemStack input, ItemStack... outputs) {
		this.registerRecipe(recipeType, input, null, outputs);
	}
	
	public void registerRecipe(RecipeType recipeType, ItemStack input, NBTTagCompound metadata, ItemStack... outputs) {
		this._oresHelper.registerRecipe(recipeType, input, metadata, outputs);
	}

	public void registerGasRecipe(RecipeType recipeType,
			Object input, NBTTagCompound metadata, Object output) {
		this.registerGasRecipe(recipeType, input, metadata, output, null);
	}
	
	public void registerGasRecipe(RecipeType recipeType,
			Object input, NBTTagCompound metadata, Object output, Object secondaryOutput) {
		// TODO Auto-generated method stub
		this._oresHelper.registerGasRecipe(recipeType, input, metadata, output, secondaryOutput);
	}
	
} public enum Fluids {
	CopperSulfide,
	Mercury,
	Oil;
	
	public Fluid fluid;
	
	public void registerFluid() {
		switch (this) {
		case Oil:
			if (Helpers.BuildCraft.isLoaded()) {
				this.fluid = FluidRegistry.getFluid(this.toString());
			}
			else {
				this.fluid = new OreFluid(this.toString());
			}
			break;
		default:
			this.fluid = new OreFluid(this.toString());
			break;
		}
	}
} public enum Gases {
	CopperSulfide(Fluids.CopperSulfide.fluid),
	Mercury(Fluids.Mercury.fluid),
	oxygen(null),
	slurryCleanAntimony(null),
	slurryCleanTitanium(null),
	sulfurDioxideGas(null);
	
	public Gas gas;
	
	private Fluid fluid;
	
	private Gases(Fluid fluid) {
		this.fluid = fluid;
	}
	
	public void registerGas() {
		if (!GasRegistry.containsGas(this.toString())) {
			if (this.fluid != null) {
				this.gas = GasRegistry.register(new Gas(this.fluid));
			}
			else {
				this.gas = GasRegistry.register(new Gas(this.toString()));
			}
		}
		else {
			this.gas = GasRegistry.getGas(this.toString());
		}
	}
} 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 enum Items {
	clumpAntimony,
	clumpTitanium,
	crushedUranium,
	crystalAntimony,
	crystalTitanium,
	dustAntimony,
	dustCharcoal (108.6D), 
	dustCoal (108.6D), 
	dustDirtyAntimony,
	dustDirtyTitanium,
	dustMagnesium,
	dustSodalite,
	dustTinyTitanium,
	dustTinyTungsten,
	dustTitanium,
	dustTungsten,
	gemIridium (12000.0),
	gemOlivine,
	gemRedGarnet,
	gemYellowGarnet,
	machineCasing,
	shardAntimony,
	shardTitanium,
	itemBitumen,
	itemMercury; 
	
	public OreItemStack item;
	private AspectList _aspects;
	private double _uuCost;
	
	private Items(AspectList aspects, double uuCost) {
		this._aspects = aspects;
		this._uuCost = uuCost;
	}
	
	private Items() {
		this(new AspectList(), 0.0D);
	}
	
	private Items(double uuCost) {
		this(new AspectList(), uuCost);
	}
	
	public void registerItems() {
		item = new OreItemStack(new ItemCore(this.toString()).setCreativeTab(CreativeTabs.tabMaterials));
	}

	public void registerAspects() {
		if (Helpers.ThaumCraft.isLoaded() && this._aspects.size() > 0)
			ThaumcraftApi.registerObjectTag(this.item.source, this._aspects);
	}
	
	public void registerRecipes() {
		if (this._uuCost != 0.0D) {
			RecipeManager.addUUMatterRecipe(this.item.source, this._uuCost);
		}
	}
} public enum MineralOres implements IOreList {
	Bauxite (1, new AspectList().add(Aspect.EXCHANGE, 2), 0.0D),
	Cassiterite (2, new AspectList().add(Aspect.EXCHANGE, 1).add(Aspect.CRYSTAL, 1), 0.0D),
	Cinnabar (2, new AspectList().add(Aspect.FIRE, 1).add(Aspect.POISON, 1), OreDrops.CINNABAR, 0.0D),
	Cooperite (2, new AspectList().add(Aspect.ELDRITCH, 1).add(Aspect.GREED, 1), 0.0D),
	Galena (2, new AspectList().add(Aspect.EXCHANGE, 1).add(Aspect.ORDER, 1), 0.0D),
	Ilmenite(3, new AspectList(), 0.0D),
	Pyrite (2, new AspectList().add(Aspect.FIRE, 1).add(Aspect.METAL, 1), OreDrops.PYRITE, 0.0D),
	Sphalerite (2, new AspectList().add(Aspect.FIRE, 1).add(Aspect.CRYSTAL, 1), OreDrops.SPHALERITE, 0.0D),
	Tetrahedrite (2, new AspectList().add(Aspect.EXCHANGE, 2), 0.0D)
	;
	
	public String oreName;
	public String crushedOreName;
	public String purifiedCrushedOreName;
	public String dustName;
	public String tinyDustName;
	public String dirtyDustName;
	public String clumpName;
	public String shardName;
	public String slurryName;
	public String cleanSlurryName;
	public String fluidSlurryName;
	
	public OreItemStack ore;
	public OreItemStack crushedOre;
	public OreItemStack purifiedCrushedOre;
	public OreItemStack dust;
	public OreItemStack tinyDust;
	public OreItemStack dirtyDust;
	public OreItemStack clump;
	public OreItemStack shard;
	
	public Gas slurry;
	public Gas cleanSlurry;
	
	public Fluid fluidSlurry;
	
	private int _harvestLevel;
	private AspectList _aspects;
	private double _uuCost;
	private OreDrops drops;
	
	private MineralOres(int harvestLevel, double uuCost) {
		this(harvestLevel, new AspectList(), uuCost);
	}
	
	private MineralOres(int harvestLevel, AspectList aspects, double uuCost) {
		this(harvestLevel, aspects, OreDrops.ORE, uuCost);
	}
	
	private MineralOres(int harvestLevel, AspectList aspects, OreDrops drops, double uuCost) {
		this.oreName = "ore" + this.toString();
		this.crushedOreName = "crushed" + this.toString();
		this.purifiedCrushedOreName = "crushedPurified" + this.toString();
		this.dustName = "dust" + this.toString();
		this.tinyDustName = "dustTiny" + this.toString();
		this.dirtyDustName = "dustDirty" + this.toString();
		this.clumpName = "clump" + this.toString();
		this.shardName = "shard" + this.toString();
		this.slurryName = "slurry" + this.toString();
		this.cleanSlurryName = "slurryClean" + this.toString();
		
		this._harvestLevel = harvestLevel;
		this._aspects = aspects;
		this._uuCost = uuCost;
		this.drops = drops;
	}

	@Override
	public OreClass getDefaultConfig() {
		return new OreClass(this.oreName, true, this._harvestLevel, 0, 0, this.drops, OreSources.DEFAULT);
	}

	@Override
	public OreClass getDefaultConfigNether() {
		return null;
	}

	@Override
	public void registerBlocks() {
		this.ore = new OreItemStack(new BlockOre(this.getDefaultConfig()));
	}

	@Override
	public void registerItems() {
		this.crushedOre = new OreItemStack(new ItemCore(this.crushedOreName).setCreativeTab(CreativeTabs.tabMaterials));
		this.purifiedCrushedOre = new OreItemStack(new ItemCore(this.purifiedCrushedOreName).setCreativeTab(CreativeTabs.tabMaterials));
		this.dust = new OreItemStack(new ItemCore(this.dustName).setCreativeTab(CreativeTabs.tabMaterials));
		this.tinyDust = new OreItemStack(new ItemCore(this.tinyDustName).setCreativeTab(CreativeTabs.tabMaterials));
		this.dirtyDust = new OreItemStack(new ItemCore(this.dirtyDustName).setCreativeTab(CreativeTabs.tabMaterials));
		this.clump = new OreItemStack(new ItemCore(this.clumpName).setCreativeTab(CreativeTabs.tabMaterials));
		this.shard = new OreItemStack(new ItemCore(this.shardName).setCreativeTab(CreativeTabs.tabMaterials));
	}

	@Override
	public void registerRecipes() {
		// Dust -> Tiny Dust Recipe
		RecipeManager.addShapelessRecipe(this.tinyDust.newStack(9), this.dustName);
		// Tiny Dust -> Dust Recipe
		RecipeManager.addShapedRecipe(this.dust.newStack(), "ttt", "ttt", "ttt", 't', this.tinyDustName);
		// Grinding Recipes
		RecipeManager.addGrinderRecipe(this.ore.newStack(), this.crushedOre.newStack(2));
		// Ore Washing Recipe
		if (Helpers.IC2.isLoaded()) {
			OreItemStack stoneDust = new OreItemStack(new ItemStack(Helpers.IC2.getItem("itemDust"), 1, 9));
			NBTTagCompound metadata = new NBTTagCompound();
			metadata.setInteger("amount", 1000);
			Helpers.IC2.registerRecipe(RecipeType.OreWasher, this.crushedOre.newStack(), (NBTTagCompound)(metadata.copy()), this.purifiedCrushedOre.newStack(), stoneDust.newStack(), this.tinyDust.newStack(2));
		}
		// Thermal Centrifuge Recipe
		if (Helpers.IC2.isLoaded()) {
			NBTTagCompound metadata = new NBTTagCompound();
			metadata.setInteger("minHeat", 1500);
			Helpers.IC2.registerRecipe(RecipeType.Centrifuge, this.purifiedCrushedOre.newStack(), (NBTTagCompound)(metadata.copy()), this.dust.newStack(2));
			metadata.setInteger("minHeat", 2500);
			switch (this) {
			case Bauxite:
				Helpers.IC2.registerRecipe(RecipeType.Centrifuge, this.dust.newStack(), (NBTTagCompound)(metadata.copy()), MetallicOres.Aluminium.dust.newStack(), MetallicOres.Iron.tinyDust.newStack());				
				break;
			case Cassiterite:
				Helpers.IC2.registerRecipe(RecipeType.Centrifuge, this.dust.newStack(), (NBTTagCompound)(metadata.copy()), MetallicOres.Tin.dust.newStack());
				break;
			case Cinnabar:
			    Helpers.IC2.registerRecipe(RecipeType.Centrifuge, this.dust.newStack(2), (NBTTagCompound)(metadata.copy()), Items.itemMercury.item.newStack(), DustyOres.Sulfur.dust.newStack());
			    break;
			case Cooperite:
				Helpers.IC2.registerRecipe(RecipeType.Centrifuge, this.dust.newStack(2), (NBTTagCompound)(metadata.copy()), MetallicOres.Platinum.dust.newStack(), DustyOres.Sulfur.dust.newStack());
				break;
			case Galena:
				Helpers.IC2.registerRecipe(RecipeType.Centrifuge, this.dust.newStack(2), (NBTTagCompound)(metadata.copy()), MetallicOres.Lead.dust.newStack(), DustyOres.Sulfur.dust.newStack());
				break;
			case Ilmenite:
				Helpers.IC2.registerRecipe(RecipeType.Centrifuge, this.dust.newStack(2), (NBTTagCompound)(metadata.copy()), MetallicOres.Iron.dust.newStack(), Items.dustTitanium.item.newStack(), MetallicOres.Manganese.tinyDust.newStack());
				break;
			case Pyrite:
			    Helpers.IC2.registerRecipe(RecipeType.Centrifuge, this.dust.newStack(3), (NBTTagCompound)(metadata.copy()), MetallicOres.Iron.dust.newStack(), DustyOres.Sulfur.dust.newStack(2));
				break;
			case Sphalerite:
			    Helpers.IC2.registerRecipe(RecipeType.Centrifuge, this.dust.newStack(2), (NBTTagCompound)(metadata.copy()), MetallicOres.Zinc.dust.newStack(), DustyOres.Sulfur.dust.newStack());
				break;
			case Tetrahedrite:
				Helpers.IC2.registerRecipe(RecipeType.Centrifuge, this.dust.newStack(7), (NBTTagCompound)(metadata.copy()), MetallicOres.Copper.dust.newStack(3), Items.dustAntimony.item.newStack(), DustyOres.Sulfur.dust.newStack(3));
				break;
			default:
			}
		}
		// Smelting Recipes
		if (OresPlus.easyMineralSmelt) {
			ItemStack smeltResult = null;
			switch (this) {
			case Bauxite:
				smeltResult = MetallicOres.Aluminium.ingot.newStack();
				break;
			case Cassiterite:
				smeltResult = MetallicOres.Tin.ingot.newStack();
				break;
			case Cinnabar:
				smeltResult = Items.itemMercury.item.newStack();
				break;
			case Cooperite:
				smeltResult = MetallicOres.Platinum.ingot.newStack();
				break;
			case Galena:
				smeltResult = MetallicOres.Lead.ingot.newStack();
				break;
			case Ilmenite:
				smeltResult = MetallicOres.Iron.ingot.newStack();
				break;
			case Pyrite:
				smeltResult = MetallicOres.Iron.ingot.newStack();
				break;
			case Sphalerite:
				smeltResult = MetallicOres.Zinc.ingot.newStack();
				break;
			case Tetrahedrite:
				smeltResult = MetallicOres.Copper.ingot.newStack();
				break;
			}
			if (smeltResult != null) {
				RecipeManager.addSmelting(this.ore.newStack(), smeltResult, 0.0f);
				RecipeManager.addSmelting(this.crushedOre.newStack(), smeltResult, 0.0f);
				RecipeManager.addSmelting(this.purifiedCrushedOre.newStack(), smeltResult, 0.0f);
				RecipeManager.addSmelting(this.dust.newStack(), smeltResult, 0.0f);
			}
		}
		if (Helpers.Mekanism.isLoaded()) {
			//register Slurries
			this.slurry = GasRegistry.register(new Gas(this.slurryName));
			this.cleanSlurry = GasRegistry.register(new Gas(this.fluidSlurry).setUnlocalizedName(this.fluidSlurryName));
			
			// enrichment chamber recipes
			Helpers.Mekanism.registerRecipe(RecipeType.EnrichmentChamber, this.ore.newStack(), this.dust.newStack(2));
			Helpers.Mekanism.registerRecipe(RecipeType.EnrichmentChamber, this.dirtyDust.newStack(), this.dust.newStack());
			// crusher recipes
			Helpers.Mekanism.registerRecipe(RecipeType.Crusher, this.clump.newStack(), this.dirtyDust.newStack());
			// purification chamber recipes
			Helpers.Mekanism.registerRecipe(RecipeType.PurificationChamber, this.ore.newStack(), this.clump.newStack(3));
			Helpers.Mekanism.registerRecipe(RecipeType.PurificationChamber, this.shard.newStack(), this.clump.newStack());
			// chemical injection chamber recipes
			Helpers.Mekanism.registerRecipe(RecipeType.ChemicalInjector, this.ore.newStack(), this.shard.newStack(4));
			// chemical dissolution chamber recipes
			Helpers.Mekanism.registerGasRecipe(RecipeType.ChemicalDissolver, this.ore.newStack(), null, new GasStack(this.slurry, 1000));
			// chemical washer recipes
			Helpers.Mekanism.registerGasRecipe(RecipeType.ChemicalWasher, new GasStack(this.slurry, 1), null, new GasStack(this.cleanSlurry, 1));
			// note there are no chemical crystalizer recipes as the clean slurries will need seperation into more base elements
			// Electrolytic Seperator Recipes
			switch (this) {
			case Bauxite:
				Helpers.Mekanism.registerGasRecipe(RecipeType.ElectrolyticSeperator, new FluidStack(this.fluidSlurry, 10), null, new GasStack(MetallicOres.Aluminium.cleanSlurry, 9), new GasStack(MetallicOres.Iron.cleanSlurry, 1));
				break;
			case Cassiterite:
				Helpers.Mekanism.registerGasRecipe(RecipeType.ElectrolyticSeperator, new FluidStack(this.fluidSlurry, 1), null, new GasStack(MetallicOres.Tin.cleanSlurry, 1), new GasStack(Gases.oxygen.gas, 1));
				break;
			case Cinnabar:
				Helpers.Mekanism.registerGasRecipe(RecipeType.ElectrolyticSeperator, new FluidStack(this.fluidSlurry, 2), null, new GasStack(Gases.Mercury.gas, 1), new GasStack(Gases.sulfurDioxideGas.gas, 1));
				break;
			case Cooperite:
				Helpers.Mekanism.registerGasRecipe(RecipeType.ElectrolyticSeperator, new FluidStack(this.fluidSlurry, 2), null, new GasStack(MetallicOres.Platinum.cleanSlurry, 1), new GasStack(Gases.sulfurDioxideGas.gas, 1));
				break;
			case Galena:
				Helpers.Mekanism.registerGasRecipe(RecipeType.ElectrolyticSeperator, new FluidStack(this.fluidSlurry, 2), null, new GasStack(MetallicOres.Lead.cleanSlurry, 1), new GasStack(Gases.sulfurDioxideGas.gas, 1));
				break;
			case Ilmenite:
				Helpers.Mekanism.registerGasRecipe(RecipeType.ElectrolyticSeperator, new FluidStack(this.fluidSlurry, 2), null, new GasStack(MetallicOres.Iron.cleanSlurry, 1), new GasStack(Gases.slurryCleanTitanium.gas, 1));
				break;
			case Pyrite:
				Helpers.Mekanism.registerGasRecipe(RecipeType.ElectrolyticSeperator, new FluidStack(this.fluidSlurry, 3), null, new GasStack(MetallicOres.Iron.cleanSlurry, 1), new GasStack(Gases.sulfurDioxideGas.gas, 2));
				break;
			case Sphalerite:
				Helpers.Mekanism.registerGasRecipe(RecipeType.ElectrolyticSeperator, new FluidStack(this.fluidSlurry, 2), null, new GasStack(MetallicOres.Zinc.cleanSlurry, 1), new GasStack(Gases.sulfurDioxideGas.gas, 1));
				break;
			case Tetrahedrite:
				Helpers.Mekanism.registerGasRecipe(RecipeType.ElectrolyticSeperator, new FluidStack(this.fluidSlurry, 7), null, new GasStack(Gases.CopperSulfide.gas, 6), new GasStack(Gases.slurryCleanAntimony.gas, 1));
				break;
			default:
				break;
			}
		}
	}

	@Override
	public void registerAspects() {
		if (!Helpers.ThaumCraft.isLoaded())
			return;
		ThaumcraftApi.registerObjectTag(this.oreName, this._aspects.add(Aspect.EARTH, 1).add(Aspect.METAL, 2));
		ThaumcraftApi.registerObjectTag(this.crushedOreName, this._aspects.add(Aspect.EARTH, 1).add(Aspect.METAL, 2));
		ThaumcraftApi.registerObjectTag(this.purifiedCrushedOreName, this._aspects.add(Aspect.METAL, 3));
		ThaumcraftApi.registerObjectTag(this.dustName, this._aspects.add(Aspect.METAL, 2).add(Aspect.ENTROPY, 1));
		ThaumcraftApi.registerObjectTag(this.tinyDustName, this._aspects.add(Aspect.METAL, 1).add(Aspect.ENTROPY, 1));
	}

	@Override
	public int getTradeToAmount(Random random) {
		return 0;
	}

	@Override
	public int getTradeFromAmount(Random random) {
		return 0;
	}

	@Override
	public void registerFluids() {
		// TODO Auto-generated method stub
		if (FluidRegistry.isFluidRegistered(this.fluidSlurryName)) {
			this.fluidSlurry = FluidRegistry.getFluid(this.fluidSlurryName);
		}
		else {
			this.fluidSlurry = new OreFluid(this.fluidSlurryName);
		}
	}

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

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

} public enum DustyOres implements IOreList {
		Nikolite(2, Aspect.ENERGY, Aspect.MECHANISM, OreDrops.NIKOLITE, 230.0D),
		Phosphorite(1, Aspect.ENERGY, Aspect.HARVEST, OreDrops.PHOSPHORITE, 75.0D),
		Potash(1, Aspect.ENERGY, Aspect.HARVEST, OreDrops.POTASH, 60.0D),
		Redstone(2, Aspect.ENERGY, Aspect.MECHANISM, 0.0D), // 140.22961579311882
		Saltpeter(1, Aspect.FIRE, Aspect.HARVEST, OreDrops.SALTPETER, 550.7D), // 4.0
		Sulfur(1, Aspect.FIRE, Aspect.ENTROPY, OreDrops.SULFUR, 300.6D)
	;
		
	public String oreName;
	public String netherOreName;
	public String blockName;
	public String dustName;
	public String tinyDustName;
	
	public OreItemStack ore;
	public OreItemStack netherOre;
	public OreItemStack block;
	public OreItemStack dust;
	public OreItemStack tinyDust;
	
	private int _harvestLevel;
	private OreDrops _drops;
	private Aspect _aspect;
	private Aspect _secondaryAspect;
	private double _uuCost;
		
	private DustyOres (int harvestLevel, Aspect aspect, Aspect secondaryAspect, double uuCost) {
		this(harvestLevel, aspect, secondaryAspect, OreDrops.ORE, uuCost);
	}
	
	private DustyOres (int harvestLevel, Aspect aspect, Aspect secondaryAspect, OreDrops drops, double uuCost) {
		this.oreName = "ore" + this.toString();
		this.netherOreName = "oreNether" + this.toString();
		this.blockName = "block" + this.toString();
		this.dustName = "dust" + this.toString();
		this.tinyDustName = "dustTiny" + this.toString();
		this._harvestLevel = harvestLevel;
		this._drops = drops;
		this._aspect = aspect;
		this._secondaryAspect = secondaryAspect;
		this._uuCost = uuCost;
	}

	@Override
	public OreClass getDefaultConfig() {
		return new OreClass(this.oreName, true, this._harvestLevel, 0, 0,
				this._drops, OreSources.DEFAULT);
	}

	@Override
	public OreClass getDefaultConfigNether() {
		return new OreClass(this.netherOreName, true, this._harvestLevel, 0, 0,
				OreDrops.ORE, OreSources.DEFAULT);
	}

	@Override
	public void registerBlocks() {
		// Register ore & storage block
		OreClass oreClass;
		switch (this) {
		case Redstone:
			this.ore = new OreItemStack(net.minecraft.init.Blocks.redstone_ore);
			Ores.manager.registerOre(this.oreName, net.minecraft.init.Blocks.redstone_ore);
			this.block = new OreItemStack(net.minecraft.init.Blocks.redstone_block);
			Ores.manager.registerOre(this.blockName, net.minecraft.init.Blocks.redstone_block);
			break;
		default:
			this.ore = new OreItemStack(new BlockOre(this.getDefaultConfig()));
			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);
		}
		
		// Register Nether Ore
		this.netherOre = new OreItemStack(new BlockOre(this.getDefaultConfigNether(), true));
		
	}

	@Override
	public void registerItems() {
		switch (this) {
		case Redstone:
			this.dust = new OreItemStack(net.minecraft.init.Items.redstone);
			break;
		default:
			this.dust = new OreItemStack(new ItemCore(this.dustName).setCreativeTab(CreativeTabs.tabMaterials));
		}
		this.tinyDust = new OreItemStack(new ItemCore(this.tinyDustName).setCreativeTab(CreativeTabs.tabMaterials));
	}

	@Override
	public void registerRecipes() {
		//Add tiny dust -> dust recipes
		RecipeManager.addShapedRecipe(this.dust.newStack(), "ttt", "ttt", "ttt", 't', this.tinyDustName);
		
		//Add dust -> tiny dust recipes
		RecipeManager.addShapelessRecipe(this.tinyDust.newStack(9), this.dustName);
		
		//Add nether ore smelting
		RecipeManager.addSmelting(this.netherOre.newStack(), this.ore.newStack(2), 0.0F);
		
		//Add ore grinding
		RecipeManager.addGrinderRecipe(this.ore.newStack(), this.dust.newStack(6));
		
		//Add dust -> ore block
		RecipeManager.addShapedRecipe(this.block.newStack(), "ddd", "ddd", "ddd", 'd', this.dustName);
		
		//Add ore block -> dust
		RecipeManager.addShapelessRecipe(this.dust.newStack(9), this.block.newStack());
		
		// Add uuMatter costs
		if (this._uuCost != 0.0D) {
			RecipeManager.addUUMatterRecipe(this.dust.source, this._uuCost);
		}
	}

	@Override
	public void registerAspects() {
		if (!Helpers.ThaumCraft.isLoaded())
			return;
		
	    if (this != Redstone) {
	        ThaumcraftApi.registerObjectTag(this.oreName, new AspectList().add(Aspect.EARTH, 1).add(this._aspect, 2).add(this._secondaryAspect, 2));
	        ThaumcraftApi.registerObjectTag(this.dustName, new AspectList().add(this._aspect, 2).add(this._secondaryAspect, 1));
	        ThaumcraftApi.registerObjectTag(this.blockName, new AspectList().add(this._aspect, 3).add(this._secondaryAspect, 4));
	      }
	      ThaumcraftApi.registerObjectTag(this.netherOreName, new AspectList().add(Aspect.EARTH, 1).add(Aspect.FIRE, 1).add(this._aspect, 2).add(this._secondaryAspect, 2));
	}

	@Override
	public int getTradeToAmount(Random random) {
		return 0;
	}

	@Override
	public int getTradeFromAmount(Random random) {
		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 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 GeneralOres implements IOreList {
	Bitumen (1, OreDrops.BITUMEN, 0.0D),
	CertusQuartz (1, OreDrops.CERTUSQUARTZ, 1250.0D),
	Iridium (3, OreDrops.IRIDIUM, 0.0D),
	Magnesium (1, OreDrops.MAGNESIUM, 0.0D),
	NetherCoal (1, new AspectList().add(Aspect.FIRE, 1), 0.0D),
	NetherLapis (1, new AspectList().add(Aspect.FIRE, 1), 0.0D),
	NetherUranium (2, new AspectList().add(Aspect.FIRE, 1), 0.0D),
	Olivine (2, new AspectList().add(Aspect.ELDRITCH, 1), OreDrops.OLIVINE, 0.0D),
	Sodalite (2, new AspectList().add(Aspect.ELDRITCH, 1), OreDrops.SODALITE, 0.0D),
	Tungstate (2, new AspectList().add(Aspect.ELDRITCH, 1), 0.0D),
	Tungsten (2, 0.0D),
	Uranium (2, 2608.8982568638758D);
	
	public String oreName;
	
	public OreItemStack ore;
	
	private boolean _enabled;
	private int _harvestLevel;
	private OreDrops _drops;
	private OreSources _source;
	private int _xpdropLow;
	private int _xpdropHigh;
	private AspectList _aspects;
	private double _uuCost;
	
	private GeneralOres (int harvestLevel, int xpdropLow, int xpdropHigh, AspectList aspects, OreDrops drops, double uuCost) {
		this.oreName = "ore" + this.toString();
		this._enabled = true;
		this._harvestLevel = harvestLevel;
		this._drops = drops;
		this._source = OreSources.DEFAULT;
		this._xpdropLow = xpdropLow;
		this._xpdropHigh = xpdropHigh;
		this._aspects = aspects;
		this._uuCost = uuCost;
	}
	
	private GeneralOres(int harvestLevel, AspectList aspects, double uuCost) {
		this(harvestLevel, 0, 0, aspects, OreDrops.ORE, uuCost);
	}
	
	private GeneralOres(int harvestLevel, AspectList aspects, OreDrops drops, double uuCost) {
		this(harvestLevel, 0, 0, aspects, drops, uuCost);
	}
	
	private GeneralOres(int harvestLevel, int xpdropLow, int xpdropHigh, OreDrops drops, double uuCost) {
		this(harvestLevel, xpdropLow, xpdropHigh, new AspectList(), drops, uuCost);
	}
	
	private GeneralOres(int harvestLevel, OreDrops drops, double uuCost) {
		this(harvestLevel, 0, 0, new AspectList(), drops, uuCost);
	}
	
	private GeneralOres(int harvestLevel, int xpdropLow, int xpdropHigh, double uuCost) {
		this(harvestLevel, xpdropLow, xpdropHigh, new AspectList(), OreDrops.ORE, uuCost);
	}
	
	private GeneralOres(int harvestLevel, double uuCost) {
		this(harvestLevel, 0, 0, new AspectList(), OreDrops.ORE, uuCost);
	}
	
	@Override
	public OreClass getDefaultConfig() {
		return new OreClass(this.oreName, this._enabled, this._harvestLevel, 
				this._xpdropLow, this._xpdropHigh, this._drops, this._source);
	}
	
	@Override
	public void registerBlocks() {
		this.ore = new OreItemStack(new BlockOre(this.getDefaultConfig()));
	}

	@Override
	public OreClass getDefaultConfigNether() {
		return null;
	}

	@Override
	public void registerItems() { }

	@Override
	public void registerRecipes() {
		// register uuMatter costs
		if (this._uuCost != 0.0D) {
			RecipeManager.addUUMatterRecipe(this.ore.source, this._uuCost);
		}
	}

	@Override
	public void registerAspects() {
		if (!Helpers.ThaumCraft.isLoaded())
			return;
		
	    if (this != Uranium) {
	        ThaumcraftApi.registerObjectTag(this.oreName, this._aspects.add(Aspect.EARTH, 1));
	    }
	}

	@Override
	public int getTradeToAmount(Random random) {
		return 0;
	}

	@Override
	public int getTradeFromAmount(Random random) {
		return 0;
	}

	@Override
	public void registerFluids() { }

	@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
		
	}
	
}
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import cpw.mods.fml.common.registry.GameData;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.GameRegistry.UniqueIdentifier;
import thaumcraft.api.ThaumcraftApi;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList;
import tw.oresplus.OresPlus;
import tw.oresplus.api.Ores;
import tw.oresplus.blocks.BlockManager;
import tw.oresplus.core.OreDictHelper;
import tw.oresplus.core.References;
import tw.oresplus.core.config.ConfigMain;
import tw.oresplus.core.helpers.BCHelper;
import tw.oresplus.core.helpers.Helpers;
import tw.oresplus.fluids.Fluids;
import tw.oresplus.gases.Gases;
import tw.oresplus.items.ItemManager;
import tw.oresplus.items.Items;
import tw.oresplus.ores.MineralOres;
import tw.oresplus.ores.DustyOres;
import tw.oresplus.ores.GemstoneOres;
import tw.oresplus.ores.GeneralOres;
import tw.oresplus.ores.MetallicOres;
import mekanism.api.gas.GasRegistry;
import mekanism.api.gas.GasStack;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.CraftingManager;
import net.minecraft.item.crafting.FurnaceRecipes;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.oredict.ShapedOreRecipe;
import net.minecraftforge.oredict.ShapelessOreRecipe;
package tw.oresplus.recipes;



public class RecipeManager {
	private static ICraftingHandler neiHandler;
	private static ICraftingHandler tmiHandler;
	
	private static ArrayList<ItemStack> maceratorBlackList = new ArrayList();
	private static ArrayList<ItemStack> grinderBlackList = new ArrayList();
	private static ArrayList<ItemStack> rockCrusherBlackList = new ArrayList();
	private static ArrayList<ItemStack> pulverizerBlackList = new ArrayList();
	
	public static void init() {
		Ores.grinderRecipes = new GrinderRecipeManager();
		Ores.crackerRecipes = new CrackerRecipeManager();
		
		neiHandler = new NeiHandler();
		tmiHandler = new TmiHandler();
	}
	
	public static void initRecipes() {
		maceratorBlackList.add(new ItemStack(net.minecraft.init.Items.coal, 1, 0));
		maceratorBlackList.add(new ItemStack(net.minecraft.init.Items.coal, 1, 1));

		OreItemStack bucketEmpty = new OreItemStack(net.minecraft.init.Items.bucket);
		OreItemStack coal = new OreItemStack(net.minecraft.init.Items.coal, 0);
		OreItemStack charcoal = new OreItemStack(net.minecraft.init.Items.coal, 1);
		OreItemStack chest = new OreItemStack(net.minecraft.init.Blocks.chest);
	    OreItemStack fertalizer = new OreItemStack(Helpers.Forestry.getItem("fertilizerCompound"));