package common.init;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import common.block.Block;
import common.block.BlockBed;
import common.block.BlockDirt;
import common.block.BlockDoublePlant;
import common.block.BlockFlower;
import common.block.BlockQuartz;
import common.block.BlockSand;
import common.block.BlockSandStone;
import common.block.BlockStoneBrick;
import common.block.BlockWall;
import common.collect.Lists;
import common.collect.Maps;
import common.color.DyeColor;
import common.entity.animal.EntitySheep;
import common.inventory.InventoryCrafting;
import common.item.Item;
import common.item.ItemArmor;
import common.item.ItemDye;
import common.item.ItemStack;
import common.nbt.NBTTagCompound;
import common.nbt.NBTTagList;
import common.tileentity.TileEntityBanner;
import common.world.World;

public abstract class CraftingRegistry
{
    private static final String[][] TOOLS = new String[][] {
    	{"XXX", " # ", " # "}, {"X", "#", "#"}, {"XX", "X#", " #"}, {"XX", " #", " #"}
    };
//    private static final Object[][] toolItems = new Object[][] {
//		{Blocks.planks, Blocks.cobblestone}, // Items.iron_ingot, Items.diamond, Items.gold_ingot}, 
//		{Items.wooden_pickaxe, Items.stone_pickaxe}, // Items.iron_pickaxe, Items.diamond_pickaxe, Items.golden_pickaxe}, 
//		{Items.wooden_shovel, Items.stone_shovel}, // Items.iron_shovel, Items.diamond_shovel, Items.golden_shovel}, 
//		{Items.wooden_axe, Items.stone_axe}, // Items.iron_axe, Items.diamond_axe, Items.golden_axe}, 
//		{Items.wooden_hoe, Items.stone_hoe}, // Items.iron_hoe, Items.diamond_hoe, Items.golden_hoe}
//    };
    private static final String[][] WEAPONS = new String[][] {{"X", "X", "#"}};
//    private static final Object[][] weaponItems = new Object[][] {
//    	{Blocks.planks, Blocks.cobblestone}, // Items.iron_ingot, Items.diamond, Items.gold_ingot}, 
//    	{Items.wooden_sword, Items.stone_sword}, // Items.iron_sword, Items.diamond_sword, Items.golden_sword}
//    };
    private static final String[][] ARMOR = new String[][] {
    	{"XXX", "X X"}, {"X X", "XXX", "XXX"}, {"XXX", "X X", "X X"}, {"X X", "X X"}
    };
    private static final Object[][] COMPRESSED = new Object[][] {
    	/* {Blocks.gold_block, new ItemStack(Items.gold_ingot, 9)}, 
    	{Blocks.iron_block, new ItemStack(Items.iron_ingot, 9)}, */ 
//    	{Blocks.diamond_block, new ItemStack(Items.diamond, 9)}, 
    	{Blocks.emerald_block, new ItemStack(Items.emerald, 9)}, 
    	{Blocks.lapis_block, new ItemStack(Items.dye, 9, DyeColor.BLUE.getDyeDamage())}, 
    	{Blocks.redstone_block, new ItemStack(Items.redstone, 9)}, 
    	{Blocks.coal_block, new ItemStack(Items.coal, 9, 0)}, 
    	{Blocks.hay_block, new ItemStack(Items.wheats, 9)}, 
    	{Blocks.slime_block, new ItemStack(Items.slime_ball, 9)}
    };
//    private static final Item[][] armorItems = new Item[][] {
//    	{Items.leather}, // /* Items.iron_ingot, */ Items.diamond /* , Items.gold_ingot */}, 
//    	{Items.leather_helmet}, // /* Items.iron_helmet, */ Items.diamond_helmet /* , Items.golden_helmet */}, 
//    	{Items.leather_chestplate}, // /* Items.iron_chestplate, */ Items.diamond_chestplate /* , Items.golden_chestplate */}, 
//    	{Items.leather_leggings}, // /* Items.iron_leggings, */ Items.diamond_leggings /* , Items.golden_leggings */}, 
//    	{Items.leather_boots}, // /* Items.iron_boots, */ Items.diamond_boots /* , Items.golden_boots */}
//    };
    
    private static final List<IRecipe> recipes = Lists.<IRecipe>newArrayList();
    private static final List<IRecipe> base = Lists.<IRecipe>newArrayList();

    static void register()
    {
//    	for (int i = 0; i < toolItems[0].length; ++i)
//        {
//            Object object = toolItems[0][i];
//
//            for (int j = 0; j < toolItems.length - 1; ++j)
//            {
//                Item item = (Item)toolItems[j + 1][i];
//                add(new ItemStack(item), toolPatterns[j], '#', Items.stick, 'X', object);
//            }
//        }

//        add(new ItemStack(Items.shears), " #", "# ", '#', Items.iron_ingot);
//        add(new ItemStack(Items.diamond_shears), " #", "# ", '#', Items.diamond);

        for(OreType ore : OreType.values()) {
        	Item item = ItemRegistry.getRegisteredItem(ore.item);
        	ore.material.addRepairItem(item);
        	if(ore.material.hasTools()) {
	        	add(new ItemStack(ItemRegistry.getRegisteredItem(ore.name + "_pickaxe")), TOOLS[0], '#', Items.stick, 'X', item);
	        	add(new ItemStack(ItemRegistry.getRegisteredItem(ore.name + "_shovel")), TOOLS[1], '#', Items.stick, 'X', item);
	        	add(new ItemStack(ItemRegistry.getRegisteredItem(ore.name + "_axe")), TOOLS[2], '#', Items.stick, 'X', item);
	        	add(new ItemStack(ItemRegistry.getRegisteredItem(ore.name + "_hoe")), TOOLS[3], '#', Items.stick, 'X', item);
        	}
        	if(ore.material.hasExtras()) {
	        	add(new ItemStack(ItemRegistry.getRegisteredItem(ore.name + "_shears")), " #", "# ", '#', item);
        	}
        	if(ore.material.hasWeapons()) {
	        	add(new ItemStack(ItemRegistry.getRegisteredItem(ore.name + "_sword")), WEAPONS[0], '#', Items.stick, 'X', item);
        	}
        	if(ore.material.hasArmor()) {
	            add(new ItemStack(ItemRegistry.getRegisteredItem(ore.name + "_helmet")), ARMOR[0], 'X', item);
	            add(new ItemStack(ItemRegistry.getRegisteredItem(ore.name + "_chestplate")), ARMOR[1], 'X', item);
	            add(new ItemStack(ItemRegistry.getRegisteredItem(ore.name + "_leggings")), ARMOR[2], 'X', item);
	            add(new ItemStack(ItemRegistry.getRegisteredItem(ore.name + "_boots")), ARMOR[3], 'X', item);
        	}
        	Block block = BlockRegistry.getRegisteredBlock(ore.name + "_block");
        	add(new ItemStack(block), "###", "###", "###", '#', item);
            add(new ItemStack(item, 9), "#", '#', block);
        }
        for(MetalType metal : MetalType.values()) {
        	Item item = ItemRegistry.getRegisteredItem(metal.isPowder ? (metal.name + "_powder") : (metal.name + "_ingot"));
        	if(metal.material != null)
        		metal.material.addRepairItem(item);
        	if(metal.material != null && metal.material.hasTools()) {
	        	add(new ItemStack(ItemRegistry.getRegisteredItem(metal.name + "_pickaxe")), TOOLS[0], '#', Items.stick, 'X', item);
	        	add(new ItemStack(ItemRegistry.getRegisteredItem(metal.name + "_shovel")), TOOLS[1], '#', Items.stick, 'X', item);
	        	add(new ItemStack(ItemRegistry.getRegisteredItem(metal.name + "_axe")), TOOLS[2], '#', Items.stick, 'X', item);
	        	add(new ItemStack(ItemRegistry.getRegisteredItem(metal.name + "_hoe")), TOOLS[3], '#', Items.stick, 'X', item);
        	}
        	if(metal.material != null && metal.material.hasExtras()) {
	        	add(new ItemStack(ItemRegistry.getRegisteredItem(metal.name + "_shears")), " #", "# ", '#', item);
        	}
        	if(metal.material != null && metal.material.hasWeapons()) {
	        	add(new ItemStack(ItemRegistry.getRegisteredItem(metal.name + "_sword")), WEAPONS[0], '#', Items.stick, 'X', item);
        	}
        	if(metal.material != null && metal.material.hasArmor()) {
	            add(new ItemStack(ItemRegistry.getRegisteredItem(metal.name + "_helmet")), ARMOR[0], 'X', item);
	            add(new ItemStack(ItemRegistry.getRegisteredItem(metal.name + "_chestplate")), ARMOR[1], 'X', item);
	            add(new ItemStack(ItemRegistry.getRegisteredItem(metal.name + "_leggings")), ARMOR[2], 'X', item);
	            add(new ItemStack(ItemRegistry.getRegisteredItem(metal.name + "_boots")), ARMOR[3], 'X', item);
        	}
        	Block block = BlockRegistry.getRegisteredBlock(metal.name + "_block");
        	add(new ItemStack(block), "###", "###", "###", '#', item);
            add(new ItemStack(item, 9), "#", '#', block);
        }
        for(ToolType tool : ToolType.values()) {
        	for(String itm : tool.items) {
	        	Item item = ItemRegistry.getRegisteredItem(itm);
	        	tool.material.addRepairItem(item);
	        	if(tool.material.hasTools()) {
		        	add(new ItemStack(ItemRegistry.getRegisteredItem(tool.name + "_pickaxe")), TOOLS[0], '#', Items.stick, 'X', item);
		        	add(new ItemStack(ItemRegistry.getRegisteredItem(tool.name + "_shovel")), TOOLS[1], '#', Items.stick, 'X', item);
		        	add(new ItemStack(ItemRegistry.getRegisteredItem(tool.name + "_axe")), TOOLS[2], '#', Items.stick, 'X', item);
		        	add(new ItemStack(ItemRegistry.getRegisteredItem(tool.name + "_hoe")), TOOLS[3], '#', Items.stick, 'X', item);
	        	}
	        	if(tool.material.hasExtras()) {
		        	add(new ItemStack(ItemRegistry.getRegisteredItem(tool.name + "_shears")), " #", "# ", '#', item);
	        	}
	        	if(tool.material.hasWeapons()) {
		        	add(new ItemStack(ItemRegistry.getRegisteredItem(tool.name + "_sword")), WEAPONS[0], '#', Items.stick, 'X', item);
	        	}
	        	if(tool.material.hasArmor()) {
		            add(new ItemStack(ItemRegistry.getRegisteredItem(tool.name + "_helmet")), ARMOR[0], 'X', item);
		            add(new ItemStack(ItemRegistry.getRegisteredItem(tool.name + "_chestplate")), ARMOR[1], 'X', item);
		            add(new ItemStack(ItemRegistry.getRegisteredItem(tool.name + "_leggings")), ARMOR[2], 'X', item);
		            add(new ItemStack(ItemRegistry.getRegisteredItem(tool.name + "_boots")), ARMOR[3], 'X', item);
	        	}
        	}
        }
        
//        for (int i = 0; i < weaponItems[0].length; ++i)
//        {
//            Object object = weaponItems[0][i];
//
//            for (int j = 0; j < weaponItems.length - 1; ++j)
//            {
//                Item item = (Item)weaponItems[j + 1][i];
//                add(new ItemStack(item), weaponPatterns[j], '#', Items.stick, 'X', object);
//            }
//        }

        add(new ItemStack(Items.bow, 1), " #X", "# X", " #X", 'X', Items.string, '#', Items.stick);
        add(new ItemStack(Items.arrow, 4), "X", "#", "Y", 'Y', Items.feather, 'X', Items.flint, '#', Items.stick);
        
        for (int i = 0; i < COMPRESSED.length; ++i)
        {
            Block block = (Block)COMPRESSED[i][0];
            ItemStack itemstack = (ItemStack)COMPRESSED[i][1];
            add(new ItemStack(block), "###", "###", "###", '#', itemstack);
            add(itemstack, "#", '#', block);
        }

        add(new ItemStack(Items.gold_ingot), "###", "###", "###", '#', Items.gold_nugget);
        add(new ItemStack(Items.gold_nugget, 9), "#", '#', Items.gold_ingot);
        
        addShapeless(new ItemStack(Items.mushroom_stew), Blocks.brown_mushroom, Blocks.red_mushroom, Items.bowl);
        add(new ItemStack(Items.cookie, 8), "#X#", 'X', new ItemStack(Items.dye, 1, DyeColor.BROWN.getDyeDamage()), '#', Items.wheats);
//        addRecipe(new ItemStack(Items.rabbit_stew), " R ", "CPM", " B ", 'R', new ItemStack(Items.cooked_rabbit), 'C', Items.carrot, 'P', Items.baked_potato, 'M', Blocks.brown_mushroom, 'B', Items.bowl);
//        addRecipe(new ItemStack(Items.rabbit_stew), " R ", "CPD", " B ", 'R', new ItemStack(Items.cooked_rabbit), 'C', Items.carrot, 'P', Items.baked_potato, 'D', Blocks.red_mushroom, 'B', Items.bowl);
        add(new ItemStack(Blocks.melon_block), "MMM", "MMM", "MMM", 'M', Items.melon);
        add(new ItemStack(Items.melon_stem), "M", 'M', Items.melon);
        add(new ItemStack(Items.pumpkin_stem, 4), "M", 'M', Blocks.pumpkin);
        addShapeless(new ItemStack(Items.pumpkin_pie), Blocks.pumpkin, Items.sugar, Items.egg);
        addShapeless(new ItemStack(Items.fermented_spider_eye), Items.spider_eye, Blocks.brown_mushroom, Items.sugar);
        addShapeless(new ItemStack(Items.blaze_powder, 2), Items.blaze_rod);
        addShapeless(new ItemStack(Items.magma_cream), Items.blaze_powder, Items.slime_ball);
        
        add(new ItemStack(Blocks.trapped_chest), "#-", '#', Blocks.chest, '-', Blocks.tripwire_hook);
        add(new ItemStack(Blocks.warp_chest), "###", "#E#", "###", '#', Blocks.obsidian, 'E', Items.charged_orb);
        add(new ItemStack(Blocks.furnace), "###", "# #", "###", '#', Blocks.cobblestone);
        add(new ItemStack(Blocks.sandstone), "##", "##", '#', new ItemStack(Blocks.sand, 1, BlockSand.EnumType.SAND.getMetadata()));
//        addRecipe(new ItemStack(Blocks.red_sandstone), "##", "##", '#', new ItemStack(Blocks.sand, 1, BlockSand.EnumType.RED_SAND.getMetadata()));
        add(new ItemStack(Blocks.sandstone, 4, BlockSandStone.EnumType.SMOOTH.getMetadata()), "##", "##", '#', new ItemStack(Blocks.sandstone, 1, BlockSandStone.EnumType.DEFAULT.getMetadata()));
//        addRecipe(new ItemStack(Blocks.red_sandstone, 4, BlockRedSandstone.EnumType.SMOOTH.getMetadata()), "##", "##", '#', new ItemStack(Blocks.red_sandstone, 1, BlockRedSandstone.EnumType.DEFAULT.getMetadata()));
//        addRecipe(new ItemStack(Blocks.red_sandstone, 1, BlockRedSandstone.EnumType.CHISELED.getMetadata()), "#", "#", '#', new ItemStack(Blocks.stone_slab2, 1, BlockStoneSlabNew.EnumType.RED_SANDSTONE.getMetadata()));
        add(new ItemStack(Blocks.quartz_block, 2, BlockQuartz.EnumType.LINES_Y.getMetadata()), "#", "#", '#', new ItemStack(Blocks.quartz_block, 1, BlockQuartz.EnumType.DEFAULT.getMetadata()));
        add(new ItemStack(Blocks.stonebrick, 4), "##", "##", '#', Blocks.stone);
        addShapeless(new ItemStack(Blocks.stonebrick, 1, BlockStoneBrick.MOSSY_META), Blocks.stonebrick, Blocks.vine);
        addShapeless(new ItemStack(Blocks.mossy_cobblestone, 1), Blocks.cobblestone, Blocks.vine);
        add(new ItemStack(Blocks.iron_bars, 16), "###", "###", '#', Items.iron_ingot);
        add(new ItemStack(Blocks.glass_pane, 16), "###", "###", '#', Blocks.glass);
        add(new ItemStack(Blocks.redstone_lamp, 1), " R ", "RGR", " R ", 'R', Items.redstone, 'G', Blocks.glowstone);
        add(new ItemStack(Blocks.beacon, 1), "GGG", "GSG", "OOO", 'G', Blocks.glass, 'S', Items.charge_crystal, 'O', Blocks.obsidian);
        add(new ItemStack(Blocks.blood_brick, 1), "NN", "NN", 'N', Items.bloodbrick);
//        addRecipe(new ItemStack(Blocks.stone, 2, BlockStone.EnumType.DIORITE.getMetadata()), "CQ", "QC", 'C', Blocks.cobblestone, 'Q', Items.quartz);
//        addShapelessRecipe(new ItemStack(Blocks.stone, 1, BlockStone.EnumType.GRANITE.getMetadata()), new ItemStack(Blocks.stone, 1, BlockStone.EnumType.DIORITE.getMetadata()), Items.quartz);
//        addShapelessRecipe(new ItemStack(Blocks.stone, 2, BlockStone.EnumType.ANDESITE.getMetadata()), new ItemStack(Blocks.stone, 1, BlockStone.EnumType.DIORITE.getMetadata()), Blocks.cobblestone);
        add(new ItemStack(Blocks.dirt, 4, BlockDirt.DirtType.COARSE_DIRT.getMetadata()), "DG", "GD", 'D', new ItemStack(Blocks.dirt, 1, BlockDirt.DirtType.DIRT.getMetadata()), 'G', Blocks.gravel);
//        addRecipe(new ItemStack(Blocks.stone, 4, BlockStone.EnumType.DIORITE_SMOOTH.getMetadata()), "SS", "SS", 'S', new ItemStack(Blocks.stone, 1, BlockStone.EnumType.DIORITE.getMetadata()));
//        addRecipe(new ItemStack(Blocks.stone, 4, BlockStone.EnumType.GRANITE_SMOOTH.getMetadata()), "SS", "SS", 'S', new ItemStack(Blocks.stone, 1, BlockStone.EnumType.GRANITE.getMetadata()));
//        addRecipe(new ItemStack(Blocks.stone, 4, BlockStone.EnumType.ANDESITE_SMOOTH.getMetadata()), "SS", "SS", 'S', new ItemStack(Blocks.stone, 1, BlockStone.EnumType.ANDESITE.getMetadata()));
//        addRecipe(new ItemStack(Blocks.prismarine, 1, BlockPrismarine.ROUGH_META), "SS", "SS", 'S', Items.prismarine_shard);
//        addRecipe(new ItemStack(Blocks.prismarine, 1, BlockPrismarine.BRICKS_META), "SSS", "SSS", "SSS", 'S', Items.prismarine_shard);
//        addRecipe(new ItemStack(Blocks.prismarine, 1, BlockPrismarine.DARK_META), "SSS", "SIS", "SSS", 'S', Items.prismarine_shard, 'I', new ItemStack(Items.dye, 1, EnumDyeColor.BLACK.getDyeDamage()));
//        addRecipe(new ItemStack(Blocks.sea_lantern, 1, 0), "SCS", "CCC", "SCS", 'S', Items.prismarine_shard, 'C', Items.prismarine_crystals);

        add(new ItemStack(Blocks.lamp, 1), " R ", "RGR", " R ", 'R', Blocks.glass, 'G', Blocks.glowstone);
        
//        for (int i = 0; i < armorItems[0].length; ++i)
//        {
//            Item item = armorItems[0][i];
//
//            for (int j = 0; j < armorItems.length - 1; ++j)
//            {
//                Item item1 = armorItems[j + 1][i];
//                add(new ItemStack(item1), armorPatterns[j], 'X', item);
//            }
//        }
        
        for (int i = 0; i < 16; ++i)
        {
            addShapeless(new ItemStack(Blocks.wool, 1, i), new ItemStack(Items.dye, 1, 15 - i), new ItemStack(Blocks.wool, 1, 0));
            add(new ItemStack(Blocks.stained_hardened_clay, 8, 15 - i), "###", "#X#", "###", '#', new ItemStack(Blocks.hardened_clay), 'X', new ItemStack(Items.dye, 1, i));
            add(new ItemStack(Blocks.stained_glass, 8, 15 - i), "###", "#X#", "###", '#', new ItemStack(Blocks.glass), 'X', new ItemStack(Items.dye, 1, i));
            add(new ItemStack(Blocks.stained_glass_pane, 16, i), "###", "###", '#', new ItemStack(Blocks.stained_glass, 1, i));
        }

        addShapeless(new ItemStack(Items.dye, 1, DyeColor.YELLOW.getDyeDamage()), new ItemStack(Blocks.flower, 1, BlockFlower.EnumFlowerType.DANDELION.getMeta()));
        addShapeless(new ItemStack(Items.dye, 1, DyeColor.RED.getDyeDamage()), new ItemStack(Blocks.flower, 1, BlockFlower.EnumFlowerType.ROSE.getMeta()));
        addShapeless(new ItemStack(Items.dye, 1, DyeColor.RED.getDyeDamage()), new ItemStack(Blocks.flower, 1, BlockFlower.EnumFlowerType.POPPY.getMeta()));
        addShapeless(new ItemStack(Items.dye, 3, DyeColor.WHITE.getDyeDamage()), Items.bone);
        addShapeless(new ItemStack(Items.dye, 2, DyeColor.PINK.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.RED.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.WHITE.getDyeDamage()));
        addShapeless(new ItemStack(Items.dye, 2, DyeColor.ORANGE.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.RED.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.YELLOW.getDyeDamage()));
        addShapeless(new ItemStack(Items.dye, 2, DyeColor.LIME.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.GREEN.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.WHITE.getDyeDamage()));
        addShapeless(new ItemStack(Items.dye, 2, DyeColor.GRAY.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.BLACK.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.WHITE.getDyeDamage()));
        addShapeless(new ItemStack(Items.dye, 2, DyeColor.SILVER.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.GRAY.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.WHITE.getDyeDamage()));
        addShapeless(new ItemStack(Items.dye, 3, DyeColor.SILVER.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.BLACK.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.WHITE.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.WHITE.getDyeDamage()));
        addShapeless(new ItemStack(Items.dye, 2, DyeColor.LIGHT_BLUE.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.BLUE.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.WHITE.getDyeDamage()));
        addShapeless(new ItemStack(Items.dye, 2, DyeColor.CYAN.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.BLUE.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.GREEN.getDyeDamage()));
        addShapeless(new ItemStack(Items.dye, 2, DyeColor.PURPLE.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.BLUE.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.RED.getDyeDamage()));
        addShapeless(new ItemStack(Items.dye, 2, DyeColor.MAGENTA.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.PURPLE.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.PINK.getDyeDamage()));
        addShapeless(new ItemStack(Items.dye, 3, DyeColor.MAGENTA.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.BLUE.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.RED.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.PINK.getDyeDamage()));
        addShapeless(new ItemStack(Items.dye, 4, DyeColor.MAGENTA.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.BLUE.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.RED.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.RED.getDyeDamage()), new ItemStack(Items.dye, 1, DyeColor.WHITE.getDyeDamage()));
        addShapeless(new ItemStack(Items.dye, 1, DyeColor.LIGHT_BLUE.getDyeDamage()), new ItemStack(Blocks.flower, 1, BlockFlower.EnumFlowerType.BLUE_ORCHID.getMeta()));
        addShapeless(new ItemStack(Items.dye, 1, DyeColor.MAGENTA.getDyeDamage()), new ItemStack(Blocks.flower, 1, BlockFlower.EnumFlowerType.ALLIUM.getMeta()));
        addShapeless(new ItemStack(Items.dye, 1, DyeColor.SILVER.getDyeDamage()), new ItemStack(Blocks.flower, 1, BlockFlower.EnumFlowerType.HOUSTONIA.getMeta()));
        addShapeless(new ItemStack(Items.dye, 1, DyeColor.RED.getDyeDamage()), new ItemStack(Blocks.flower, 1, BlockFlower.EnumFlowerType.RED_TULIP.getMeta()));
        addShapeless(new ItemStack(Items.dye, 1, DyeColor.ORANGE.getDyeDamage()), new ItemStack(Blocks.flower, 1, BlockFlower.EnumFlowerType.ORANGE_TULIP.getMeta()));
        addShapeless(new ItemStack(Items.dye, 1, DyeColor.SILVER.getDyeDamage()), new ItemStack(Blocks.flower, 1, BlockFlower.EnumFlowerType.WHITE_TULIP.getMeta()));
        addShapeless(new ItemStack(Items.dye, 1, DyeColor.PINK.getDyeDamage()), new ItemStack(Blocks.flower, 1, BlockFlower.EnumFlowerType.PINK_TULIP.getMeta()));
        addShapeless(new ItemStack(Items.dye, 1, DyeColor.SILVER.getDyeDamage()), new ItemStack(Blocks.flower, 1, BlockFlower.EnumFlowerType.OXEYE_DAISY.getMeta()));
        addShapeless(new ItemStack(Items.dye, 2, DyeColor.YELLOW.getDyeDamage()), new ItemStack(Blocks.double_plant, 1, BlockDoublePlant.EnumPlantType.SUNFLOWER.getMeta()));
        addShapeless(new ItemStack(Items.dye, 2, DyeColor.MAGENTA.getDyeDamage()), new ItemStack(Blocks.double_plant, 1, BlockDoublePlant.EnumPlantType.SYRINGA.getMeta()));
        addShapeless(new ItemStack(Items.dye, 2, DyeColor.RED.getDyeDamage()), new ItemStack(Blocks.double_plant, 1, BlockDoublePlant.EnumPlantType.ROSE.getMeta()));
        addShapeless(new ItemStack(Items.dye, 2, DyeColor.PINK.getDyeDamage()), new ItemStack(Blocks.double_plant, 1, BlockDoublePlant.EnumPlantType.PAEONIA.getMeta()));

        for (int j = 0; j < 16; ++j)
        {
            add(new ItemStack(Blocks.carpet, 3, j), "##", '#', new ItemStack(Blocks.wool, 1, j));
        }
        
        recipes.add(new RecipesArmorDyes());
//        this.recipes.add(new RecipeBookCloning());
//        recipes.add(new RecipesMapCloning());
//        recipes.add(new RecipesMapExtending());
        recipes.add(new RecipeFireworks());
        recipes.add(new RecipeRepairItem());
        
        for (DyeColor enumdyecolor : DyeColor.values())
        {
            add(new ItemStack(Items.banner, 1, enumdyecolor.getDyeDamage()), "###", "###", " | ", '#', new ItemStack(Blocks.wool, 1, enumdyecolor.getMetadata()), '|', Items.stick);
        }

        recipes.add(new RecipeDuplicatePattern());
        recipes.add(new RecipeAddPattern());
        
        add(new ItemStack(Items.paper, 3), "###", '#', Items.reeds);
        addShapeless(new ItemStack(Items.book, 1), Items.paper, Items.paper, Items.paper, Items.leather);
        addShapeless(new ItemStack(Items.writable_book, 1), Items.book, new ItemStack(Items.dye, 1, DyeColor.BLACK.getDyeDamage()), Items.feather);
        for(WoodType wood : WoodType.values()) {
        	Item planks = ItemRegistry.getRegisteredItem(wood.getName() + "_planks");
	        add(new ItemStack(ItemRegistry.getRegisteredItem(wood.getName() + "_fence"), 3), "W#W", "W#W", '#', Items.stick, 'W', planks);
	        add(new ItemStack(ItemRegistry.getRegisteredItem(wood.getName() + "_fence_gate"), 1), "#W#", "#W#", '#', Items.stick, 'W', planks);
	        add(new ItemStack(ItemRegistry.getRegisteredItem(wood.getName() + "_door"), 3), "##", "##", "##", '#', planks);
	        addBasic(new ItemStack(planks, 4), "#", '#', ItemRegistry.getRegisteredItem(wood.getName() + "_log"));
	        Item slab = ItemRegistry.getRegisteredItem(wood.getName() + "_slab");
	        add(new ItemStack(slab, 6, 0), "###", '#', planks);
	        add(new ItemStack(ItemRegistry.getRegisteredItem(wood.getName() + "_stairs"), 4), "#  ", "## ", "###", '#', planks);
	        add(new ItemStack(Blocks.daylight_detector), "GGG", "QQQ", "WWW", 'G', Blocks.glass, 'Q', Items.quartz, 'W', slab);
	        
	        add(new ItemStack(Blocks.chest), "###", "# #", "###", '#', planks);
	        addBasic(new ItemStack(Blocks.crafting_table), "##", "##", '#', planks);
	        

	        add(new ItemStack(Blocks.jukebox, 1), "###", "#X#", "###", '#', planks, 'X', Items.diamond);
	        add(new ItemStack(Blocks.noteblock, 1), "###", "#X#", "###", '#', planks, 'X', Items.redstone);
	        add(new ItemStack(Blocks.bookshelf, 1), "###", "XXX", "###", '#', planks, 'X', Items.book);
	        add(new ItemStack(Blocks.trapdoor, 2), "###", "###", '#', planks);
	        add(new ItemStack(Items.sign, 3), "###", "###", " X ", '#', planks, 'X', Items.stick);
	        add(new ItemStack(Items.stick, 4), "#", "#", '#', planks);
	        add(new ItemStack(Items.bowl, 4), "# #", " # ", '#', planks);
	        add(new ItemStack(Items.boat, 1), "# #", "###", '#', planks);
	        add(new ItemStack(Blocks.tripwire_hook, 2), "I", "S", "#", '#', planks, 'S', Items.stick, 'I', Items.iron_ingot);
	        add(new ItemStack(Blocks.wooden_button, 1), "#", '#', planks);
	        add(new ItemStack(Blocks.wooden_pressure_plate, 1), "##", '#', planks);
	        add(new ItemStack(Blocks.piston, 1), "TTT", "#X#", "#R#", '#', Blocks.cobblestone, 'X', Items.iron_ingot, 'R', Items.redstone, 'T', planks);
	        for(DyeColor color : BlockBed.COLORS) {
	        	add(new ItemStack(ItemRegistry.getRegisteredItem(color.getName() + "_bed"), 1), "###", "XXX", '#', new ItemStack(Blocks.wool, 1, color.getMetadata()), 'X', planks);
	        }
        }

        add(new ItemStack(Blocks.cobblestone_wall, 6, BlockWall.EnumType.NORMAL.getMetadata()), "###", "###", '#', Blocks.cobblestone);
        add(new ItemStack(Blocks.cobblestone_wall, 6, BlockWall.EnumType.MOSSY.getMetadata()), "###", "###", '#', Blocks.mossy_cobblestone);
        add(new ItemStack(Blocks.blood_brick_fence, 6), "###", "###", '#', Blocks.blood_brick);
        
        add(new ItemStack(Items.lead, 2), "~~ ", "~O ", "  ~", '~', Items.string, 'O', Items.slime_ball);
        add(new ItemStack(Blocks.snow, 1), "##", "##", '#', Items.snowball);
        add(new ItemStack(Blocks.snow_layer, 6), "###", '#', Blocks.snow);
        add(new ItemStack(Blocks.clay, 1), "##", "##", '#', Items.clay_ball);
        add(new ItemStack(Blocks.brick_block, 1), "##", "##", '#', Items.brick);
        add(new ItemStack(Blocks.glowstone, 1), "##", "##", '#', Items.glowstone_dust);
        add(new ItemStack(Blocks.quartz_block, 1), "##", "##", '#', Items.quartz);
        add(new ItemStack(Blocks.wool, 1), "##", "##", '#', Items.string);
        add(new ItemStack(Blocks.tnt, 1), "X#X", "#X#", "X#X", 'X', Items.gunpowder, '#', Blocks.sand);

        add(new ItemStack(Blocks.tnt, 1, 1), "X#X", "#X#", "X#X", 'X', Items.gunpowder, '#', new ItemStack(Blocks.tnt, 1, 0));
        add(new ItemStack(Blocks.tnt, 1, 2), "##", "##", '#', new ItemStack(Blocks.tnt, 1, 1));
        addShapeless(new ItemStack(Blocks.tnt, 1, 3), new ItemStack(Blocks.tnt, 1, 2), new ItemStack(Blocks.tnt, 1, 2));
        addShapeless(new ItemStack(Blocks.tnt, 1, 4), new ItemStack(Blocks.tnt, 1, 3), new ItemStack(Blocks.tnt, 1, 3));
        addShapeless(new ItemStack(Blocks.tnt, 1, 5), new ItemStack(Blocks.tnt, 1, 4), new ItemStack(Blocks.tnt, 1, 4));
        addShapeless(new ItemStack(Blocks.tnt, 1, 6), new ItemStack(Blocks.tnt, 1, 5), new ItemStack(Blocks.tnt, 1, 5));
        addShapeless(new ItemStack(Blocks.tnt, 1, 7), new ItemStack(Blocks.tnt, 1, 6), new ItemStack(Blocks.tnt, 1, 6));
        add(new ItemStack(Blocks.nuke, 1), "###", "###", "###", '#', new ItemStack(Blocks.tnt, 1, 7));

//        add(new ItemStack(Blocks.sandstone, 1, BlockSandStone.EnumType.CHISELED.getMetadata()), "#", "#", '#', new ItemStack(Blocks.stone_slab, 1, BlockStoneSlab.EnumType.SAND.getMetadata()));
//        add(new ItemStack(Blocks.quartz_block, 1, BlockQuartz.EnumType.CHISELED.getMetadata()), "#", "#", '#', new ItemStack(Blocks.stone_slab, 1, BlockStoneSlab.EnumType.QUARTZ.getMetadata()));
//        add(new ItemStack(Blocks.stonebrick, 1, BlockStoneBrick.CHISELED_META), "#", "#", '#', new ItemStack(Blocks.stone_slab, 1, BlockStoneSlab.EnumType.SMOOTHBRICK.getMetadata()));
//        add(new ItemStack(Blocks.stone_slab, 6, BlockStoneSlab.EnumType.COBBLESTONE.getMetadata()), "###", '#', Blocks.cobblestone);
//        add(new ItemStack(Blocks.stone_slab, 6, BlockStoneSlab.EnumType.STONE.getMetadata()), "###", '#', Blocks.stone);
//        add(new ItemStack(Blocks.stone_slab, 6, BlockStoneSlab.EnumType.SAND.getMetadata()), "###", '#', Blocks.sandstone);
//        add(new ItemStack(Blocks.stone_slab, 6, BlockStoneSlab.EnumType.BRICK.getMetadata()), "###", '#', Blocks.brick_block);
//        add(new ItemStack(Blocks.stone_slab, 6, BlockStoneSlab.EnumType.SMOOTHBRICK.getMetadata()), "###", '#', Blocks.stonebrick);
//        add(new ItemStack(Blocks.stone_slab, 6, BlockStoneSlab.EnumType.BLOODBRICK.getMetadata()), "###", '#', Blocks.blood_brick);
//        add(new ItemStack(Blocks.stone_slab, 6, BlockStoneSlab.EnumType.QUARTZ.getMetadata()), "###", '#', Blocks.quartz_block);
        
        add(new ItemStack(Blocks.ladder, 3), "# #", "###", "# #", '#', Items.stick);
        
        add(new ItemStack(Items.iron_door, 3), "##", "##", "##", '#', Items.iron_ingot);
        add(new ItemStack(Blocks.iron_trapdoor, 1), "##", "##", '#', Items.iron_ingot);
        add(new ItemStack(Items.cake, 1), "AAA", "BEB", "CCC", 'A', Items.milk_bucket, 'B', Items.sugar, 'C', Items.wheats, 'E', Items.egg);
        add(new ItemStack(Items.sugar, 1), "#", '#', Items.reeds);
        
        add(new ItemStack(Blocks.torch, 4), "X", "#", 'X', Items.coal, '#', Items.stick);
        add(new ItemStack(Blocks.torch, 4), "X", "#", 'X', new ItemStack(Items.coal, 1, 1), '#', Items.stick);
        add(new ItemStack(Items.glass_bottle, 3), "# #", " # ", '#', Blocks.glass);
        add(new ItemStack(Blocks.rail, 16), "X X", "X#X", "X X", 'X', Items.iron_ingot, '#', Items.stick);
        add(new ItemStack(Blocks.golden_rail, 6), "X X", "X#X", "XRX", 'X', Items.gold_ingot, 'R', Items.redstone, '#', Items.stick);
        add(new ItemStack(Blocks.activator_rail, 6), "XSX", "X#X", "XSX", 'X', Items.iron_ingot, '#', Blocks.redstone_torch, 'S', Items.stick);
        add(new ItemStack(Blocks.detector_rail, 6), "X X", "X#X", "XRX", 'X', Items.iron_ingot, 'R', Items.redstone, '#', Blocks.stone_pressure_plate);
        add(new ItemStack(Items.minecart, 1), "# #", "###", '#', Items.iron_ingot);
        add(new ItemStack(Items.cauldron, 1), "# #", "# #", "###", '#', Items.iron_ingot);
        add(new ItemStack(Items.brewing_stand, 1), " B ", "###", '#', Blocks.cobblestone, 'B', Items.blaze_rod);
        add(new ItemStack(Blocks.lit_pumpkin, 1), "A", "B", 'A', Blocks.pumpkin, 'B', Blocks.torch);
        add(new ItemStack(Items.chest_minecart, 1), "A", "B", 'A', Blocks.chest, 'B', Items.minecart);
//        add(new ItemStack(Items.furnace_minecart, 1), "A", "B", 'A', Blocks.furnace, 'B', Items.minecart);
        add(new ItemStack(Items.tnt_minecart, 1), "A", "B", 'A', new ItemStack(Blocks.tnt, 1, 0), 'B', Items.minecart);
        add(new ItemStack(Items.hopper_minecart, 1), "A", "B", 'A', Blocks.hopper, 'B', Items.minecart);
        add(new ItemStack(Items.bucket, 1), "# #", " # ", '#', Items.iron_ingot);
        add(new ItemStack(Items.flower_pot, 1), "# #", " # ", '#', Items.brick);
        addShapeless(new ItemStack(Items.flint_and_steel, 1), new ItemStack(Items.iron_ingot, 1), new ItemStack(Items.flint, 1));
        add(new ItemStack(Items.bread, 1), "###", '#', Items.wheats);
        
        add(new ItemStack(Items.fishing_rod, 1), "  #", " #X", "# X", '#', Items.stick, 'X', Items.string);
        add(new ItemStack(Items.carrot_on_a_stick, 1), "# ", " X", '#', Items.fishing_rod, 'X', Items.carrot);
        add(new ItemStack(Blocks.cobblestone_stairs, 4), "#  ", "## ", "###", '#', Blocks.cobblestone);
        add(new ItemStack(Blocks.brick_stairs, 4), "#  ", "## ", "###", '#', Blocks.brick_block);
        add(new ItemStack(Blocks.stonebrick_stairs, 4), "#  ", "## ", "###", '#', Blocks.stonebrick);
        add(new ItemStack(Blocks.blood_brick_stairs, 4), "#  ", "## ", "###", '#', Blocks.blood_brick);
        add(new ItemStack(Blocks.sandstone_stairs, 4), "#  ", "## ", "###", '#', Blocks.sandstone);
//        addRecipe(new ItemStack(Blocks.red_sandstone_stairs, 4), "#  ", "## ", "###", '#', Blocks.red_sandstone);
        add(new ItemStack(Blocks.quartz_stairs, 4), "#  ", "## ", "###", '#', Blocks.quartz_block);
//        add(new ItemStack(Items.painting, 1), "###", "#X#", "###", '#', Items.stick, 'X', Blocks.wool);
//        add(new ItemStack(Items.item_frame, 1), "###", "#X#", "###", '#', Items.stick, 'X', Items.leather);
        add(new ItemStack(Items.golden_apple, 1, 0), "###", "#X#", "###", '#', Items.gold_ingot, 'X', Items.apple);
        add(new ItemStack(Items.golden_apple, 1, 1), "###", "#X#", "###", '#', Blocks.gold_block, 'X', Items.apple);
        add(new ItemStack(Items.golden_carrot, 1, 0), "###", "#X#", "###", '#', Items.gold_nugget, 'X', Items.carrot);
        add(new ItemStack(Items.speckled_melon, 1), "###", "#X#", "###", '#', Items.gold_nugget, 'X', Items.melon);
        add(new ItemStack(Blocks.lever, 1), "X", "#", '#', Blocks.cobblestone, 'X', Items.stick);
        add(new ItemStack(Blocks.redstone_torch, 1), "X", "#", '#', Items.stick, 'X', Items.redstone);
        add(new ItemStack(Items.repeater, 1), "#X#", "III", '#', Blocks.redstone_torch, 'X', Items.redstone, 'I', Blocks.stone);
        add(new ItemStack(Items.comparator, 1), " # ", "#X#", "III", '#', Blocks.redstone_torch, 'X', Items.quartz, 'I', Blocks.stone);
//        add(new ItemStack(Items.clock, 1), " # ", "#X#", " # ", '#', Items.gold_ingot, 'X', Items.redstone);
        add(new ItemStack(Items.navigator, 1), " # ", "#X#", " # ", '#', Items.iron_ingot, 'X', Items.redstone);
//        add(new ItemStack(Items.map, 1), "###", "#X#", "###", '#', Items.paper, 'X', Items.compass);
        add(new ItemStack(Blocks.stone_button, 1), "#", '#', Blocks.stone);
        add(new ItemStack(Blocks.stone_pressure_plate, 1), "##", '#', Blocks.stone);
        add(new ItemStack(Blocks.heavy_weighted_pressure_plate, 1), "##", '#', Items.iron_ingot);
        add(new ItemStack(Blocks.light_weighted_pressure_plate, 1), "##", '#', Items.gold_ingot);
        add(new ItemStack(Blocks.dispenser, 1), "###", "#X#", "#R#", '#', Blocks.cobblestone, 'X', Items.bow, 'R', Items.redstone);
        add(new ItemStack(Blocks.dropper, 1), "###", "# #", "#R#", '#', Blocks.cobblestone, 'R', Items.redstone);
        add(new ItemStack(Blocks.sticky_piston, 1), "S", "P", 'S', Items.slime_ball, 'P', Blocks.piston);
        add(new ItemStack(Blocks.enchanting_table, 1), " B ", "D#D", "###", '#', Blocks.obsidian, 'B', Items.book, 'D', Items.diamond);
        add(new ItemStack(Blocks.anvil, 1), "III", " i ", "iii", 'I', Blocks.iron_block, 'i', Items.iron_ingot);
//        addRecipe(new ItemStack(Items.leather), "##", "##", '#', Items.rabbit_hide);
        addShapeless(new ItemStack(Items.charged_orb, 1), Items.orb, Items.blaze_powder);
        addShapeless(new ItemStack(Items.fire_charge, 3), Items.gunpowder, Items.blaze_powder, Items.coal);
        addShapeless(new ItemStack(Items.fire_charge, 3), Items.gunpowder, Items.blaze_powder, new ItemStack(Items.coal, 1, 1));
        add(new ItemStack(Blocks.hopper), "I I", "ICI", " I ", 'I', Items.iron_ingot, 'C', Blocks.chest);
//        addRecipe(new ItemStack(Items.armor_stand, 1), "///", " / ", "/_/", '/', Items.stick, '_', new ItemStack(Blocks.stone_slab, 1, BlockStoneSlab.EnumType.STONE.getMetadata()));
        
        
        add(new ItemStack(Items.dynamite, 1), "X#X", "#X#", "X#X", 'X', Items.gunpowder, '#', Items.clay_ball);
        add(new ItemStack(Items.dynamite, 1, 1), "X#X", "#X#", "X#X", 'X', Items.gunpowder, '#', new ItemStack(Items.dynamite, 1, 0));
        add(new ItemStack(Items.dynamite, 1, 2), "##", "##", '#', new ItemStack(Items.dynamite, 1, 1));
        addShapeless(new ItemStack(Items.dynamite, 1, 3), new ItemStack(Items.dynamite, 1, 2), new ItemStack(Items.dynamite, 1, 2));
        addShapeless(new ItemStack(Items.dynamite, 1, 4), new ItemStack(Items.dynamite, 1, 3), new ItemStack(Items.dynamite, 1, 3));
        addShapeless(new ItemStack(Items.dynamite, 1, 5), new ItemStack(Items.dynamite, 1, 4), new ItemStack(Items.dynamite, 1, 4));
        addShapeless(new ItemStack(Items.dynamite, 1, 6), new ItemStack(Items.dynamite, 1, 5), new ItemStack(Items.dynamite, 1, 5));
        addShapeless(new ItemStack(Items.dynamite, 1, 7), new ItemStack(Items.dynamite, 1, 6), new ItemStack(Items.dynamite, 1, 6));

        add(new ItemStack(Items.portal_frame, 1), "XYX", "X#X", "XXX", 'X', Blocks.obsidian, 'Y', Items.orb, '#', Items.charged_orb);
//        add(new ItemStack(Blocks.monster_egg, 1, 0), "XXX", "X#X", "XXX", 'X', new ItemStack(Blocks.stone, 1, 0), '#', new ItemStack(Items.spawn_egg, 1, 60));
//        add(new ItemStack(Blocks.monster_egg, 1, 1), "XXX", "X#X", "XXX", 'X', Blocks.cobblestone, '#', new ItemStack(Items.spawn_egg, 1, 60));
//        for(int z = 0; z < 4; z++) {
//        	add(new ItemStack(Blocks.monster_egg, 1, z + 2), "XXX", "X#X", "XXX", 'X', new ItemStack(Blocks.stonebrick, 1, z), '#', new ItemStack(Items.spawn_egg, 1, 60));
//        }
        add(new ItemStack(Items.experience_bottle, 1), "YXY", "X#X", "YXY", 'X', Blocks.glass_pane, 'Y', Blocks.glowstone, '#', Items.emerald);
        add(new ItemStack(Blocks.mob_spawner, 1), "###", "#X#", "###", 'X', Items.charge_crystal, '#', Blocks.iron_bars);
        add(new ItemStack(Blocks.dragon_egg, 1), "###", "#X#", "#D#", 'X', Items.charge_crystal, 'D', Items.diamond, '#', Blocks.obsidian);
//        addRecipe(new ItemStack(Blocks.command_block, 1), "###", "#X#", "###", 'X', Items.redstone, '#', Items.quartz);

//        addShapeless(new ItemStack(Items.spawn_egg, 1, 51), new ItemStack(Items.skull, 1, 0));
//        addShapeless(new ItemStack(Items.spawn_egg, 1, 51), new ItemStack(Items.skull, 1, 1));
//        addShapeless(new ItemStack(Items.spawn_egg, 1, 54), new ItemStack(Items.skull, 1, 2));
//        addShapeless(new ItemStack(Items.spawn_egg, 1, 50), new ItemStack(Items.skull, 1, 4));
//        addShapeless(new ItemStack(Items.spawn_egg, 1, 124), Items.flint, Items.egg, Blocks.cobblestone, Items.slime_ball);
//        addRecipe(new ItemStack(Items.command_block_minecart, 1), "A", "B", 'A', Blocks.command_block, 'B', Items.minecart);
        add(new ItemStack(Blocks.red_button, 1), "#", '#', Items.redstone);
        add(new ItemStack(Items.chick_magnet, 1), "A A", "N N", " C ", 'A', Items.aluminium_ingot, 'N', Items.nickel_ingot, 'C', Items.cobalt_ingot);
        add(new ItemStack(Items.magnet, 1), "I I", "N N", " R ", 'I', Items.iron_ingot, 'N', Items.neodymium_ingot, 'R', Items.redstone);
        
        addShapeless(new ItemStack(Items.potion, 1, 16384), new ItemStack(Items.potion, 1, 0), Items.gunpowder);
        
        Collections.sort(recipes, new Comparator<IRecipe>()
        {
            public int compare(IRecipe r1, IRecipe r2)
            {
                return r1 instanceof ShapelessRecipes && r2 instanceof ShapedRecipes ? 1 : (r2 instanceof ShapelessRecipes && r1 instanceof ShapedRecipes ? -1 : (r2.getRecipeSize() < r1.getRecipeSize() ? -1 : (r2.getRecipeSize() > r1.getRecipeSize() ? 1 : 0)));
            }
        });
    }
    
    private static ShapedRecipes addBasic(ItemStack stack, Object ... recipeComponents) {
    	ShapedRecipes recipe = add(stack, recipeComponents);
    	base.add(recipe);
    	return recipe;
    }
    
    private static ShapedRecipes add(ItemStack stack, Object ... recipeComponents)
    {
        String s = "";
        int i = 0;
        int j = 0;
        int k = 0;

        if (recipeComponents[i] instanceof String[])
        {
            String[] astring = (String[])((String[])recipeComponents[i++]);

            for (int l = 0; l < astring.length; ++l)
            {
                String s2 = astring[l];
                ++k;
                j = s2.length();
                s = s + s2;
            }
        }
        else
        {
            while (recipeComponents[i] instanceof String)
            {
                String s1 = (String)recipeComponents[i++];
                ++k;
                j = s1.length();
                s = s + s1;
            }
        }

        Map<Character, ItemStack> map;

        for (map = Maps.<Character, ItemStack>newHashMap(); i < recipeComponents.length; i += 2)
        {
            Character character = (Character)recipeComponents[i];
            ItemStack itemstack = null;

            if (recipeComponents[i + 1] instanceof Item)
            {
                itemstack = new ItemStack((Item)recipeComponents[i + 1]);
            }
            else if (recipeComponents[i + 1] instanceof Block)
            {
                itemstack = new ItemStack((Block)recipeComponents[i + 1], 1, 32767);
            }
            else if (recipeComponents[i + 1] instanceof ItemStack)
            {
                itemstack = (ItemStack)recipeComponents[i + 1];
            }

            map.put(character, itemstack);
        }

        ItemStack[] aitemstack = new ItemStack[j * k];

        for (int i1 = 0; i1 < j * k; ++i1)
        {
            char c0 = s.charAt(i1);

            if (map.containsKey(Character.valueOf(c0)))
            {
                aitemstack[i1] = ((ItemStack)map.get(Character.valueOf(c0))).copy();
            }
            else
            {
                aitemstack[i1] = null;
            }
        }

        ShapedRecipes shapedrecipes = new ShapedRecipes(j, k, aitemstack, stack);
        recipes.add(shapedrecipes);
        return shapedrecipes;
    }
    
    private static void addShapeless(ItemStack stack, Object ... recipeComponents)
    {
        List<ItemStack> list = Lists.<ItemStack>newArrayList();

        for (Object object : recipeComponents)
        {
            if (object instanceof ItemStack)
            {
                list.add(((ItemStack)object).copy());
            }
            else if (object instanceof Item)
            {
                list.add(new ItemStack((Item)object));
            }
            else
            {
                if (!(object instanceof Block))
                {
                    throw new IllegalArgumentException("Invalid shapeless recipe: unknown type " + object.getClass().getName() + "!");
                }

                list.add(new ItemStack((Block)object));
            }
        }

        recipes.add(new ShapelessRecipes(stack, list));
    }
    
    public static ItemStack getMatching(InventoryCrafting inv, World world)
    {
        for (IRecipe irecipe : recipes)
        {
            if (irecipe.matches(inv, world))
            {
                return irecipe.getCraftingResult(inv);
            }
        }

        return null;
    }
    
    public static ItemStack getBasic(InventoryCrafting inv, World world)
    {
    	for (IRecipe irecipe : base)
        {
            if (irecipe.matches(inv, world))
            {
                return irecipe.getCraftingResult(inv);
            }
        }

        return null;
    }

    public static ItemStack[] getRequired(InventoryCrafting inv, World world)
    {
        for (IRecipe irecipe : recipes)
        {
            if (irecipe.matches(inv, world))
            {
                return irecipe.getRemainingItems(inv);
            }
        }

        ItemStack[] aitemstack = new ItemStack[inv.getSizeInventory()];

        for (int i = 0; i < aitemstack.length; ++i)
        {
            aitemstack[i] = inv.getStackInSlot(i);
        }

        return aitemstack;
    }

    public static void getRecipeList(Set<Item> set)
    {
        for (IRecipe irecipe : recipes)
        {
            if (irecipe.getRecipeOutput() != null)
            {
                set.add(irecipe.getRecipeOutput().getItem());
            }
        }
    }
    
    private static interface IRecipe {
        boolean matches(InventoryCrafting inv, World world);
        ItemStack getCraftingResult(InventoryCrafting inv);
        int getRecipeSize();
        ItemStack getRecipeOutput();
        ItemStack[] getRemainingItems(InventoryCrafting inv);
    }
    
    private static class RecipeAddPattern implements IRecipe
    {
        public boolean matches(InventoryCrafting inv, World worldIn)
        {
            boolean flag = false;

            for (int i = 0; i < inv.getSizeInventory(); ++i)
            {
                ItemStack itemstack = inv.getStackInSlot(i);

                if (itemstack != null && itemstack.getItem() == Items.banner)
                {
                    if (flag)
                    {
                        return false;
                    }

                    if (TileEntityBanner.getPatterns(itemstack) >= 6)
                    {
                        return false;
                    }

                    flag = true;
                }
            }

            if (!flag)
            {
                return false;
            }
            else
            {
                return this.getBannerPattern(inv) != null;
            }
        }

        public ItemStack getCraftingResult(InventoryCrafting inv)
        {
            ItemStack itemstack = null;

            for (int i = 0; i < inv.getSizeInventory(); ++i)
            {
                ItemStack itemstack1 = inv.getStackInSlot(i);

                if (itemstack1 != null && itemstack1.getItem() == Items.banner)
                {
                    itemstack = itemstack1.copy();
                    itemstack.stackSize = 1;
                    break;
                }
            }

            TileEntityBanner.EnumBannerPattern tileentitybanner$enumbannerpattern = this.getBannerPattern(inv);

            if (tileentitybanner$enumbannerpattern != null)
            {
                int k = 0;

                for (int j = 0; j < inv.getSizeInventory(); ++j)
                {
                    ItemStack itemstack2 = inv.getStackInSlot(j);

                    if (itemstack2 != null && itemstack2.getItem() == Items.dye)
                    {
                        k = itemstack2.getMetadata();
                        break;
                    }
                }

                NBTTagCompound nbttagcompound1 = itemstack.getSubCompound("BlockEntityTag", true);
                NBTTagList nbttaglist = null;

                if (nbttagcompound1.hasKey("Patterns", 9))
                {
                    nbttaglist = nbttagcompound1.getTagList("Patterns", 10);
                }
                else
                {
                    nbttaglist = new NBTTagList();
                    nbttagcompound1.setTag("Patterns", nbttaglist);
                }

                NBTTagCompound nbttagcompound = new NBTTagCompound();
                nbttagcompound.setString("Pattern", tileentitybanner$enumbannerpattern.getPatternID());
                nbttagcompound.setInteger("Color", k);
                nbttaglist.appendTag(nbttagcompound);
            }

            return itemstack;
        }

        public int getRecipeSize()
        {
            return 10;
        }

        public ItemStack getRecipeOutput()
        {
            return null;
        }

        public ItemStack[] getRemainingItems(InventoryCrafting inv)
        {
            ItemStack[] aitemstack = new ItemStack[inv.getSizeInventory()];

            for (int i = 0; i < aitemstack.length; ++i)
            {
                ItemStack itemstack = inv.getStackInSlot(i);

                if (itemstack != null && itemstack.getItem().hasContainerItem())
                {
                    aitemstack[i] = new ItemStack(itemstack.getItem().getContainerItem());
                }
            }

            return aitemstack;
        }

        private TileEntityBanner.EnumBannerPattern getBannerPattern(InventoryCrafting p_179533_1_)
        {
            for (TileEntityBanner.EnumBannerPattern tileentitybanner$enumbannerpattern : TileEntityBanner.EnumBannerPattern.values())
            {
                if (tileentitybanner$enumbannerpattern.hasValidCrafting())
                {
                    boolean flag = true;

                    if (tileentitybanner$enumbannerpattern.hasCraftingStack())
                    {
                        boolean flag1 = false;
                        boolean flag2 = false;

                        for (int i = 0; i < p_179533_1_.getSizeInventory() && flag; ++i)
                        {
                            ItemStack itemstack = p_179533_1_.getStackInSlot(i);

                            if (itemstack != null && itemstack.getItem() != Items.banner)
                            {
                                if (itemstack.getItem() == Items.dye)
                                {
                                    if (flag2)
                                    {
                                        flag = false;
                                        break;
                                    }

                                    flag2 = true;
                                }
                                else
                                {
                                    if (flag1 || !itemstack.isItemEqual(tileentitybanner$enumbannerpattern.getCraftingStack()))
                                    {
                                        flag = false;
                                        break;
                                    }

                                    flag1 = true;
                                }
                            }
                        }

                        if (!flag1)
                        {
                            flag = false;
                        }
                    }
                    else if (p_179533_1_.getSizeInventory() == tileentitybanner$enumbannerpattern.getCraftingLayers().length * tileentitybanner$enumbannerpattern.getCraftingLayers()[0].length())
                    {
                        int j = -1;

                        for (int k = 0; k < p_179533_1_.getSizeInventory() && flag; ++k)
                        {
                            int l = k / 3;
                            int i1 = k % 3;
                            ItemStack itemstack1 = p_179533_1_.getStackInSlot(k);

                            if (itemstack1 != null && itemstack1.getItem() != Items.banner)
                            {
                                if (itemstack1.getItem() != Items.dye)
                                {
                                    flag = false;
                                    break;
                                }

                                if (j != -1 && j != itemstack1.getMetadata())
                                {
                                    flag = false;
                                    break;
                                }

                                if (tileentitybanner$enumbannerpattern.getCraftingLayers()[l].charAt(i1) == 32)
                                {
                                    flag = false;
                                    break;
                                }

                                j = itemstack1.getMetadata();
                            }
                            else if (tileentitybanner$enumbannerpattern.getCraftingLayers()[l].charAt(i1) != 32)
                            {
                                flag = false;
                                break;
                            }
                        }
                    }
                    else
                    {
                        flag = false;
                    }

                    if (flag)
                    {
                        return tileentitybanner$enumbannerpattern;
                    }
                }
            }

            return null;
        }
    }
    
    private static class RecipeDuplicatePattern implements IRecipe
    {
        public boolean matches(InventoryCrafting inv, World worldIn)
        {
            ItemStack itemstack = null;
            ItemStack itemstack1 = null;

            for (int i = 0; i < inv.getSizeInventory(); ++i)
            {
                ItemStack itemstack2 = inv.getStackInSlot(i);

                if (itemstack2 != null)
                {
                    if (itemstack2.getItem() != Items.banner)
                    {
                        return false;
                    }

                    if (itemstack != null && itemstack1 != null)
                    {
                        return false;
                    }

                    int j = TileEntityBanner.getBaseColor(itemstack2);
                    boolean flag = TileEntityBanner.getPatterns(itemstack2) > 0;

                    if (itemstack != null)
                    {
                        if (flag)
                        {
                            return false;
                        }

                        if (j != TileEntityBanner.getBaseColor(itemstack))
                        {
                            return false;
                        }

                        itemstack1 = itemstack2;
                    }
                    else if (itemstack1 != null)
                    {
                        if (!flag)
                        {
                            return false;
                        }

                        if (j != TileEntityBanner.getBaseColor(itemstack1))
                        {
                            return false;
                        }

                        itemstack = itemstack2;
                    }
                    else if (flag)
                    {
                        itemstack = itemstack2;
                    }
                    else
                    {
                        itemstack1 = itemstack2;
                    }
                }
            }

            return itemstack != null && itemstack1 != null;
        }

        public ItemStack getCraftingResult(InventoryCrafting inv)
        {
            for (int i = 0; i < inv.getSizeInventory(); ++i)
            {
                ItemStack itemstack = inv.getStackInSlot(i);

                if (itemstack != null && TileEntityBanner.getPatterns(itemstack) > 0)
                {
                    ItemStack itemstack1 = itemstack.copy();
                    itemstack1.stackSize = 1;
                    return itemstack1;
                }
            }

            return null;
        }

        public int getRecipeSize()
        {
            return 2;
        }

        public ItemStack getRecipeOutput()
        {
            return null;
        }

        public ItemStack[] getRemainingItems(InventoryCrafting inv)
        {
            ItemStack[] aitemstack = new ItemStack[inv.getSizeInventory()];

            for (int i = 0; i < aitemstack.length; ++i)
            {
                ItemStack itemstack = inv.getStackInSlot(i);

                if (itemstack != null)
                {
                    if (itemstack.getItem().hasContainerItem())
                    {
                        aitemstack[i] = new ItemStack(itemstack.getItem().getContainerItem());
                    }
                    else if (itemstack.hasTagCompound() && TileEntityBanner.getPatterns(itemstack) > 0)
                    {
                        aitemstack[i] = itemstack.copy();
                        aitemstack[i].stackSize = 1;
                    }
                }
            }

            return aitemstack;
        }
    }
    
    private static class RecipeFireworks implements IRecipe
    {
        private ItemStack field_92102_a;

        /**
         * Used to check if a recipe matches current crafting inventory
         */
        public boolean matches(InventoryCrafting inv, World worldIn)
        {
            this.field_92102_a = null;
            int i = 0;
            int j = 0;
            int k = 0;
            int l = 0;
            int i1 = 0;
            int j1 = 0;

            for (int k1 = 0; k1 < inv.getSizeInventory(); ++k1)
            {
                ItemStack itemstack = inv.getStackInSlot(k1);

                if (itemstack != null)
                {
                    if (itemstack.getItem() == Items.gunpowder)
                    {
                        ++j;
                    }
                    else if (itemstack.getItem() == Items.firework_charge)
                    {
                        ++l;
                    }
                    else if (itemstack.getItem() == Items.dye)
                    {
                        ++k;
                    }
                    else if (itemstack.getItem() == Items.paper)
                    {
                        ++i;
                    }
                    else if (itemstack.getItem() == Items.glowstone_dust)
                    {
                        ++i1;
                    }
                    else if (itemstack.getItem() == Items.diamond)
                    {
                        ++i1;
                    }
                    else if (itemstack.getItem() == Items.fire_charge)
                    {
                        ++j1;
                    }
                    else if (itemstack.getItem() == Items.feather)
                    {
                        ++j1;
                    }
                    else if (itemstack.getItem() == Items.gold_nugget)
                    {
                        ++j1;
                    }
                    else
                    {
                        if (itemstack.getItem() != Items.skull)
                        {
                            return false;
                        }

                        ++j1;
                    }
                }
            }

            i1 = i1 + k + j1;

            if (j <= 3 && i <= 1)
            {
                if (j >= 1 && i == 1 && i1 == 0)
                {
                    this.field_92102_a = new ItemStack(Items.fireworks);

                    if (l > 0)
                    {
                        NBTTagCompound nbttagcompound1 = new NBTTagCompound();
                        NBTTagCompound nbttagcompound3 = new NBTTagCompound();
                        NBTTagList nbttaglist = new NBTTagList();

                        for (int k2 = 0; k2 < inv.getSizeInventory(); ++k2)
                        {
                            ItemStack itemstack3 = inv.getStackInSlot(k2);

                            if (itemstack3 != null && itemstack3.getItem() == Items.firework_charge && itemstack3.hasTagCompound() && itemstack3.getTagCompound().hasKey("Explosion", 10))
                            {
                                nbttaglist.appendTag(itemstack3.getTagCompound().getCompoundTag("Explosion"));
                            }
                        }

                        nbttagcompound3.setTag("Explosions", nbttaglist);
                        nbttagcompound3.setByte("Flight", (byte)j);
                        nbttagcompound1.setTag("Fireworks", nbttagcompound3);
                        this.field_92102_a.setTagCompound(nbttagcompound1);
                    }

                    return true;
                }
                else if (j == 1 && i == 0 && l == 0 && k > 0 && j1 <= 1)
                {
                    this.field_92102_a = new ItemStack(Items.firework_charge);
                    NBTTagCompound nbttagcompound = new NBTTagCompound();
                    NBTTagCompound nbttagcompound2 = new NBTTagCompound();
                    byte b0 = 0;
                    List<Integer> list = Lists.<Integer>newArrayList();

                    for (int l1 = 0; l1 < inv.getSizeInventory(); ++l1)
                    {
                        ItemStack itemstack2 = inv.getStackInSlot(l1);

                        if (itemstack2 != null)
                        {
                            if (itemstack2.getItem() == Items.dye)
                            {
                                list.add(ItemDye.dyeColors[itemstack2.getMetadata() & 15]);
                            }
                            else if (itemstack2.getItem() == Items.glowstone_dust)
                            {
                                nbttagcompound2.setBoolean("Flicker", true);
                            }
                            else if (itemstack2.getItem() == Items.diamond)
                            {
                                nbttagcompound2.setBoolean("Trail", true);
                            }
                            else if (itemstack2.getItem() == Items.fire_charge)
                            {
                                b0 = 1;
                            }
                            else if (itemstack2.getItem() == Items.feather)
                            {
                                b0 = 4;
                            }
                            else if (itemstack2.getItem() == Items.gold_nugget)
                            {
                                b0 = 2;
                            }
                            else if (itemstack2.getItem() == Items.skull)
                            {
                                b0 = 3;
                            }
                        }
                    }

                    int[] aint1 = new int[list.size()];

                    for (int l2 = 0; l2 < aint1.length; ++l2)
                    {
                        aint1[l2] = ((Integer)list.get(l2)).intValue();
                    }

                    nbttagcompound2.setIntArray("Colors", aint1);
                    nbttagcompound2.setByte("Type", b0);
                    nbttagcompound.setTag("Explosion", nbttagcompound2);
                    this.field_92102_a.setTagCompound(nbttagcompound);
                    return true;
                }
                else if (j == 0 && i == 0 && l == 1 && k > 0 && k == i1)
                {
                    List<Integer> list1 = Lists.<Integer>newArrayList();

                    for (int i2 = 0; i2 < inv.getSizeInventory(); ++i2)
                    {
                        ItemStack itemstack1 = inv.getStackInSlot(i2);

                        if (itemstack1 != null)
                        {
                            if (itemstack1.getItem() == Items.dye)
                            {
                                list1.add(ItemDye.dyeColors[itemstack1.getMetadata() & 15]);
                            }
                            else if (itemstack1.getItem() == Items.firework_charge)
                            {
                                this.field_92102_a = itemstack1.copy();
                                this.field_92102_a.stackSize = 1;
                            }
                        }
                    }

                    int[] aint = new int[list1.size()];

                    for (int j2 = 0; j2 < aint.length; ++j2)
                    {
                        aint[j2] = ((Integer)list1.get(j2)).intValue();
                    }

                    if (this.field_92102_a != null && this.field_92102_a.hasTagCompound())
                    {
                        NBTTagCompound nbttagcompound4 = this.field_92102_a.getTagCompound().getCompoundTag("Explosion");

                        if (nbttagcompound4 == null)
                        {
                            return false;
                        }
                        else
                        {
                            nbttagcompound4.setIntArray("FadeColors", aint);
                            return true;
                        }
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        /**
         * Returns an Item that is the result of this recipe
         */
        public ItemStack getCraftingResult(InventoryCrafting inv)
        {
            return this.field_92102_a.copy();
        }

        /**
         * Returns the size of the recipe area
         */
        public int getRecipeSize()
        {
            return 10;
        }

        public ItemStack getRecipeOutput()
        {
            return this.field_92102_a;
        }

        public ItemStack[] getRemainingItems(InventoryCrafting inv)
        {
            ItemStack[] aitemstack = new ItemStack[inv.getSizeInventory()];

            for (int i = 0; i < aitemstack.length; ++i)
            {
                ItemStack itemstack = inv.getStackInSlot(i);

                if (itemstack != null && itemstack.getItem().hasContainerItem())
                {
                    aitemstack[i] = new ItemStack(itemstack.getItem().getContainerItem());
                }
            }

            return aitemstack;
        }
    }
    
    private static class RecipeRepairItem implements IRecipe
    {
        /**
         * Used to check if a recipe matches current crafting inventory
         */
        public boolean matches(InventoryCrafting inv, World worldIn)
        {
            List<ItemStack> list = Lists.<ItemStack>newArrayList();

            for (int i = 0; i < inv.getSizeInventory(); ++i)
            {
                ItemStack itemstack = inv.getStackInSlot(i);

                if (itemstack != null)
                {
                    list.add(itemstack);

                    if (list.size() > 1)
                    {
                        ItemStack itemstack1 = (ItemStack)list.get(0);

                        if (itemstack.getItem() != itemstack1.getItem() || itemstack1.stackSize != 1 || itemstack.stackSize != 1 || !itemstack1.getItem().isDamageable())
                        {
                            return false;
                        }
                    }
                }
            }

            return list.size() == 2;
        }

        /**
         * Returns an Item that is the result of this recipe
         */
        public ItemStack getCraftingResult(InventoryCrafting inv)
        {
            List<ItemStack> list = Lists.<ItemStack>newArrayList();

            for (int i = 0; i < inv.getSizeInventory(); ++i)
            {
                ItemStack itemstack = inv.getStackInSlot(i);

                if (itemstack != null)
                {
                    list.add(itemstack);

                    if (list.size() > 1)
                    {
                        ItemStack itemstack1 = (ItemStack)list.get(0);

                        if (itemstack.getItem() != itemstack1.getItem() || itemstack1.stackSize != 1 || itemstack.stackSize != 1 || !itemstack1.getItem().isDamageable())
                        {
                            return null;
                        }
                    }
                }
            }

            if (list.size() == 2)
            {
                ItemStack itemstack2 = (ItemStack)list.get(0);
                ItemStack itemstack3 = (ItemStack)list.get(1);

                if (itemstack2.getItem() == itemstack3.getItem() && itemstack2.stackSize == 1 && itemstack3.stackSize == 1 && itemstack2.getItem().isDamageable())
                {
                    Item item = itemstack2.getItem();
                    int j = item.getMaxDamage() - itemstack2.getItemDamage();
                    int k = item.getMaxDamage() - itemstack3.getItemDamage();
                    int l = j + k + item.getMaxDamage() * 5 / 100;
                    int i1 = item.getMaxDamage() - l;

                    if (i1 < 0)
                    {
                        i1 = 0;
                    }

                    return new ItemStack(itemstack2.getItem(), 1, i1);
                }
            }

            return null;
        }

        /**
         * Returns the size of the recipe area
         */
        public int getRecipeSize()
        {
            return 4;
        }

        public ItemStack getRecipeOutput()
        {
            return null;
        }

        public ItemStack[] getRemainingItems(InventoryCrafting inv)
        {
            ItemStack[] aitemstack = new ItemStack[inv.getSizeInventory()];

            for (int i = 0; i < aitemstack.length; ++i)
            {
                ItemStack itemstack = inv.getStackInSlot(i);

                if (itemstack != null && itemstack.getItem().hasContainerItem())
                {
                    aitemstack[i] = new ItemStack(itemstack.getItem().getContainerItem());
                }
            }

            return aitemstack;
        }
    }
    
    private static class RecipesArmorDyes implements IRecipe
    {
        /**
         * Used to check if a recipe matches current crafting inventory
         */
        public boolean matches(InventoryCrafting inv, World worldIn)
        {
            ItemStack itemstack = null;
            List<ItemStack> list = Lists.<ItemStack>newArrayList();

            for (int i = 0; i < inv.getSizeInventory(); ++i)
            {
                ItemStack itemstack1 = inv.getStackInSlot(i);

                if (itemstack1 != null)
                {
                    if (itemstack1.getItem() instanceof ItemArmor)
                    {
                        ItemArmor itemarmor = (ItemArmor)itemstack1.getItem();

                        if (!itemarmor.getArmorMaterial().canBeDyed() || itemstack != null)
                        {
                            return false;
                        }

                        itemstack = itemstack1;
                    }
                    else
                    {
                        if (itemstack1.getItem() != Items.dye)
                        {
                            return false;
                        }

                        list.add(itemstack1);
                    }
                }
            }

            return itemstack != null && !list.isEmpty();
        }

        /**
         * Returns an Item that is the result of this recipe
         */
        public ItemStack getCraftingResult(InventoryCrafting inv)
        {
            ItemStack itemstack = null;
            int[] aint = new int[3];
            int i = 0;
            int j = 0;
            ItemArmor itemarmor = null;

            for (int k = 0; k < inv.getSizeInventory(); ++k)
            {
                ItemStack itemstack1 = inv.getStackInSlot(k);

                if (itemstack1 != null)
                {
                    if (itemstack1.getItem() instanceof ItemArmor)
                    {
                        itemarmor = (ItemArmor)itemstack1.getItem();

                        if (!itemarmor.getArmorMaterial().canBeDyed() || itemstack != null)
                        {
                            return null;
                        }

                        itemstack = itemstack1.copy();
                        itemstack.stackSize = 1;

                        if (itemarmor.hasColor(itemstack1))
                        {
                            int l = itemarmor.getArmorColor(itemstack);
                            float f = (float)(l >> 16 & 255) / 255.0F;
                            float f1 = (float)(l >> 8 & 255) / 255.0F;
                            float f2 = (float)(l & 255) / 255.0F;
                            i = (int)((float)i + Math.max(f, Math.max(f1, f2)) * 255.0F);
                            aint[0] = (int)((float)aint[0] + f * 255.0F);
                            aint[1] = (int)((float)aint[1] + f1 * 255.0F);
                            aint[2] = (int)((float)aint[2] + f2 * 255.0F);
                            ++j;
                        }
                    }
                    else
                    {
                        if (itemstack1.getItem() != Items.dye)
                        {
                            return null;
                        }

                        float[] afloat = EntitySheep.getDyeRgb(DyeColor.byDyeDamage(itemstack1.getMetadata()));
                        int l1 = (int)(afloat[0] * 255.0F);
                        int i2 = (int)(afloat[1] * 255.0F);
                        int j2 = (int)(afloat[2] * 255.0F);
                        i += Math.max(l1, Math.max(i2, j2));
                        aint[0] += l1;
                        aint[1] += i2;
                        aint[2] += j2;
                        ++j;
                    }
                }
            }

            if (itemarmor == null)
            {
                return null;
            }
            else
            {
                int i1 = aint[0] / j;
                int j1 = aint[1] / j;
                int k1 = aint[2] / j;
                float f3 = (float)i / (float)j;
                float f4 = (float)Math.max(i1, Math.max(j1, k1));
                i1 = (int)((float)i1 * f3 / f4);
                j1 = (int)((float)j1 * f3 / f4);
                k1 = (int)((float)k1 * f3 / f4);
                int lvt_12_3_ = (i1 << 8) + j1;
                lvt_12_3_ = (lvt_12_3_ << 8) + k1;
                itemarmor.setColor(itemstack, lvt_12_3_);
                return itemstack;
            }
        }

        /**
         * Returns the size of the recipe area
         */
        public int getRecipeSize()
        {
            return 10;
        }

        public ItemStack getRecipeOutput()
        {
            return null;
        }

        public ItemStack[] getRemainingItems(InventoryCrafting inv)
        {
            ItemStack[] aitemstack = new ItemStack[inv.getSizeInventory()];

            for (int i = 0; i < aitemstack.length; ++i)
            {
                ItemStack itemstack = inv.getStackInSlot(i);

                if (itemstack != null && itemstack.getItem().hasContainerItem())
                {
                    aitemstack[i] = new ItemStack(itemstack.getItem().getContainerItem());
                }
            }

            return aitemstack;
        }
    }
    
    private static class ShapedRecipes implements IRecipe
    {
        /** How many horizontal slots this recipe is wide. */
        private final int recipeWidth;

        /** How many vertical slots this recipe uses. */
        private final int recipeHeight;

        /** Is a array of ItemStack that composes the recipe. */
        private final ItemStack[] recipeItems;

        /** Is the ItemStack that you get when craft the recipe. */
        private final ItemStack recipeOutput;
        private boolean copyIngredientNBT;

        public ShapedRecipes(int width, int height, ItemStack[] p_i1917_3_, ItemStack output)
        {
            this.recipeWidth = width;
            this.recipeHeight = height;
            this.recipeItems = p_i1917_3_;
            this.recipeOutput = output;
        }

        public ItemStack getRecipeOutput()
        {
            return this.recipeOutput;
        }

        public ItemStack[] getRemainingItems(InventoryCrafting inv)
        {
            ItemStack[] aitemstack = new ItemStack[inv.getSizeInventory()];

            for (int i = 0; i < aitemstack.length; ++i)
            {
                ItemStack itemstack = inv.getStackInSlot(i);

                if (itemstack != null && itemstack.getItem().hasContainerItem())
                {
                    aitemstack[i] = new ItemStack(itemstack.getItem().getContainerItem());
                }
            }

            return aitemstack;
        }

        /**
         * Used to check if a recipe matches current crafting inventory
         */
        public boolean matches(InventoryCrafting inv, World worldIn)
        {
            for (int i = 0; i <= 3 - this.recipeWidth; ++i)
            {
                for (int j = 0; j <= 3 - this.recipeHeight; ++j)
                {
                    if (this.checkMatch(inv, i, j, true))
                    {
                        return true;
                    }

                    if (this.checkMatch(inv, i, j, false))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        /**
         * Checks if the region of a crafting inventory is match for the recipe.
         */
        private boolean checkMatch(InventoryCrafting p_77573_1_, int p_77573_2_, int p_77573_3_, boolean p_77573_4_)
        {
            for (int i = 0; i < 3; ++i)
            {
                for (int j = 0; j < 3; ++j)
                {
                    int k = i - p_77573_2_;
                    int l = j - p_77573_3_;
                    ItemStack itemstack = null;

                    if (k >= 0 && l >= 0 && k < this.recipeWidth && l < this.recipeHeight)
                    {
                        if (p_77573_4_)
                        {
                            itemstack = this.recipeItems[this.recipeWidth - k - 1 + l * this.recipeWidth];
                        }
                        else
                        {
                            itemstack = this.recipeItems[k + l * this.recipeWidth];
                        }
                    }

                    ItemStack itemstack1 = p_77573_1_.getStackInRowAndColumn(i, j);

                    if (itemstack1 != null || itemstack != null)
                    {
                        if (itemstack1 == null && itemstack != null || itemstack1 != null && itemstack == null)
                        {
                            return false;
                        }

                        if (itemstack.getItem() != itemstack1.getItem())
                        {
                            return false;
                        }

                        if (itemstack.getMetadata() != 32767 && itemstack.getMetadata() != itemstack1.getMetadata())
                        {
                            return false;
                        }
                    }
                }
            }

            return true;
        }

        /**
         * Returns an Item that is the result of this recipe
         */
        public ItemStack getCraftingResult(InventoryCrafting inv)
        {
            ItemStack itemstack = this.getRecipeOutput().copy();

            if (this.copyIngredientNBT)
            {
                for (int i = 0; i < inv.getSizeInventory(); ++i)
                {
                    ItemStack itemstack1 = inv.getStackInSlot(i);

                    if (itemstack1 != null && itemstack1.hasTagCompound())
                    {
                        itemstack.setTagCompound((NBTTagCompound)itemstack1.getTagCompound().copy());
                    }
                }
            }

            return itemstack;
        }

        /**
         * Returns the size of the recipe area
         */
        public int getRecipeSize()
        {
            return this.recipeWidth * this.recipeHeight;
        }
    }
    
    private static class ShapelessRecipes implements IRecipe
    {
        /** Is the ItemStack that you get when craft the recipe. */
        private final ItemStack recipeOutput;
        private final List<ItemStack> recipeItems;

        public ShapelessRecipes(ItemStack output, List<ItemStack> inputList)
        {
            this.recipeOutput = output;
            this.recipeItems = inputList;
        }

        public ItemStack getRecipeOutput()
        {
            return this.recipeOutput;
        }

        public ItemStack[] getRemainingItems(InventoryCrafting inv)
        {
            ItemStack[] aitemstack = new ItemStack[inv.getSizeInventory()];

            for (int i = 0; i < aitemstack.length; ++i)
            {
                ItemStack itemstack = inv.getStackInSlot(i);

                if (itemstack != null && itemstack.getItem().hasContainerItem())
                {
                    aitemstack[i] = new ItemStack(itemstack.getItem().getContainerItem());
                }
            }

            return aitemstack;
        }

        /**
         * Used to check if a recipe matches current crafting inventory
         */
        public boolean matches(InventoryCrafting inv, World worldIn)
        {
            List<ItemStack> list = Lists.newArrayList(this.recipeItems);

            for (int i = 0; i < inv.getHeight(); ++i)
            {
                for (int j = 0; j < inv.getWidth(); ++j)
                {
                    ItemStack itemstack = inv.getStackInRowAndColumn(j, i);

                    if (itemstack != null)
                    {
                        boolean flag = false;

                        for (ItemStack itemstack1 : list)
                        {
                            if (itemstack.getItem() == itemstack1.getItem() && (itemstack1.getMetadata() == 32767 || itemstack.getMetadata() == itemstack1.getMetadata()))
                            {
                                flag = true;
                                list.remove(itemstack1);
                                break;
                            }
                        }

                        if (!flag)
                        {
                            return false;
                        }
                    }
                }
            }

            return list.isEmpty();
        }

        /**
         * Returns an Item that is the result of this recipe
         */
        public ItemStack getCraftingResult(InventoryCrafting inv)
        {
            return this.recipeOutput.copy();
        }

        /**
         * Returns the size of the recipe area
         */
        public int getRecipeSize()
        {
            return this.recipeItems.size();
        }
    }
}
