public class PlantHandlerRegistry
{
    private static final List<IPlantHandler> handlers = new ArrayList<IPlantHandler>();

    public static void init () {
        if (!register(new ModPlantMegaPackHandler()))
            register(new ModPlantMegaPackLegacyHandler());
    }

    public static boolean register (IPlantHandler handler) {
        if (handler.init()) {
            handlers.add(handler);
            return true;
        }

        return false;
    }

    public static boolean applyBonemeal (World world, int x, int y, int z) {
        for (IPlantHandler handler : handlers) {
            if (handler.applyBonemeal(world, x, y, z))
                return true;
        }

        return false;
    }
} public class WoodRegistry
{
    private static final Map<UniqueMetaIdentifier, Block> registry = new HashMap<UniqueMetaIdentifier, Block>();

    public static void registerWoodType (Block block, int meta) {
        if (block == null)
            return;

        UniqueMetaIdentifier id = new UniqueMetaIdentifier(ModBlocks.getQualifiedName(block), meta);
        if (!registry.containsKey(id))
            registry.put(id, block);
    }

    public static Set<Entry<UniqueMetaIdentifier, Block>> registeredTypes () {
        return registry.entrySet();
    }

    public static boolean contains (Block block, int meta) {
        UniqueMetaIdentifier id = ModBlocks.getUniqueMetaID(block, meta);
        return registry.containsKey(id);
    }
} public class ConfigManager
{
    private static final String CAT_PATTERNS = "1_patterns";
    private static final String CAT_SETTINGS = "2_pattern_settings";

    private final Configuration config;

    private ConfigCategory categoryPatterns;
    private ConfigCategory categoryPatternSettings;

    private ConfigCategory defaultPatternSettings;

    private PatternConfig defaultPattern;
    private PatternConfig[] patterns = new PatternConfig[256];
    private int patternCount;

    public ConfigManager (File file) {
        config = new Configuration(file);

        boolean firstGen = !config.hasCategory(CAT_PATTERNS);

        categoryPatterns = config.getCategory(CAT_PATTERNS);
        categoryPatterns.setComment("Patterns are additional textures that can be overlaid on top of large pots, both normal and colored.\n"
            + "For each pattern defined, a corresponding 'stamp' item is registered.  The stamp is used with the\n"
            + "pottery table to apply patterns to raw clay pots.\n\n"
            + "This mod can support up to 255 registered patterns.  To add a new pattern, create a new entry in the\n"
            + "config below using the form:\n\n"
            + "  S:pattern.#=texture_name; A Name\n\n"
            + "Where # is an id between 1 and 255 inclusive.\n"
            + "Place a corresponding texture_name.png file into the mod's jar file in assets/modularpots/textures/blocks.\n"
            + "To further control aspects of the pattern, seeing the next section, pattern_settings.\n\n"
            + "Note: Future versions of this mod may add new patterns.  If you haven't made any changes to this\n"
            + "configuration, simply delete it and let it regenerate.  Otherwise visit the mod's development thread\n"
            + "on Minecraft Forums to see what's changed.");

        categoryPatternSettings = config.getCategory(CAT_SETTINGS);
        categoryPatternSettings.setComment("Specifies all the attributes for patterns.  Attributes control how patterns can be found in the world.\n"
            + "In the future, they might control other aspects, such as how patterns are rendered.\n\n"
            + "By default, all patterns will take their attributes from the 'pattern_default' subcategory.  To\n"
            + "customize some or all attributes for a pattern, create a new subcategory modeled like this:\n\n"
            + "  pattern_# {\n"
            + "      S:gen=dungeonChest, 5; mineshaftCorridor, 5\n"
            + "  }\n\n"
            + "The S:gen option controls what kinds of dungeon chests the pattern's stamp item will appear in, and the\n"
            + "rarity of the item appearing.  The location and rarity are separated by a comma (,), and multiple locations\n"
            + "are separated with a semicolon (;).  Rarity is a value between 1 and 100, with 1 being very rare.  Golden\n"
            + "apples and diamond horse armor also have a rarity of 1.  Most vanilla items have a rarity of 10.  The valid\n"
            + "location strings are:\n\n"
            + "  mineshaftCorridor, pyramidDesertChest, pyramidJungleChest, strongholdCorridor, strongholdLibrary,\n"
            + "  strongholdCrossing, villageBlacksmith, dungeonChest");

        populateDefaultPattern();

        if (firstGen) {
            config.get(categoryPatterns.getQualifiedName(), "pattern.1", "large_pot_1; Serpent");
            config.get(categoryPatterns.getQualifiedName(), "pattern.2", "large_pot_2; Lattice");
            config.get(categoryPatterns.getQualifiedName(), "pattern.3", "large_pot_3; Offset Squares");
            config.get(categoryPatterns.getQualifiedName(), "pattern.4", "large_pot_4; Inset");
            config.get(categoryPatterns.getQualifiedName(), "pattern.5", "large_pot_5; Turtle");
            config.get(categoryPatterns.getQualifiedName(), "pattern.6", "large_pot_6; Creeper");
            config.get(categoryPatterns.getQualifiedName(), "pattern.7", "large_pot_7; Freewheel");
            config.get(categoryPatterns.getQualifiedName(), "pattern.8", "large_pot_8; Creepy Castle");
            config.get(categoryPatterns.getQualifiedName(), "pattern.9", "large_pot_9; Savannah");

            config.getCategory(CAT_SETTINGS + ".pattern_2");
            config.get(CAT_SETTINGS + ".pattern_2", "gen", "dungeonChest, 3; mineshaftCorridor, 2");

            config.save();
        }

        for (int i = 1; i < 256; i++) {
            if (config.hasKey(categoryPatterns.getQualifiedName(), "pattern." + i)) {
                String entry = config.get(categoryPatterns.getQualifiedName(), "pattern." + i, "").getString();
                String[] parts = entry.split("[ ]*;[ ]*");

                String overlay = parts[0];
                String name = (parts.length > 1) ? parts[1] : null;

                patterns[i] = new PatternConfig(i, overlay, name);
                if (config.hasCategory(CAT_SETTINGS + ".pattern_" + i))
                    parsePatternAttribs(patterns[i], CAT_SETTINGS + ".pattern_" + i);
                else {
                    if (patterns[i].getName() == null)
                        patterns[i].setName(defaultPattern.getName());

                    for (int j = 0; j < defaultPattern.getLocationCount(); j++)
                        patterns[i].addGenLocation(defaultPattern.getGenLocation(j), defaultPattern.getGenRarity(j));
                }

                patternCount++;
            }
        }
    }

    private void populateDefaultPattern () {
        defaultPattern = new PatternConfig(0, "", "");

        defaultPatternSettings = config.getCategory(CAT_SETTINGS + ".pattern_default");
        String name = config.get(defaultPatternSettings.getQualifiedName(), "name", "Unknown").getString();
        String gen = config.get(defaultPatternSettings.getQualifiedName(), "gen", "dungeonChest, 2; mineshaftCorridor, 1").getString();

        defaultPattern.setName(name);
        parseGenString(defaultPattern, gen);
    }

    private void parsePatternAttribs (PatternConfig pattern, String category) {
        if (config.hasKey(category, "name")) {
            String name = config.get(defaultPatternSettings.getQualifiedName(), "name", "Unknown").getString();
            pattern.setName(name);
        }
        else if (pattern.getName() == null)
            pattern.setName(defaultPattern.getName());

        if (config.hasKey(category, "gen")) {
            String gen = config.get(defaultPatternSettings.getQualifiedName(), "gen", "").getString();
            parseGenString(pattern, gen);
        }
        else {
            for (int j = 0; j < defaultPattern.getLocationCount(); j++)
                pattern.addGenLocation(defaultPattern.getGenLocation(j), defaultPattern.getGenRarity(j));
        }
    }

    private void parseGenString (PatternConfig pattern, String genString) {
        String[] strParts = genString.split("[ ]*;[ ]*");
        for (int i = 0; i < strParts.length; i++) {
            String[] locParts = strParts[i].split("[ ]*,[ ]*");
            if (locParts.length != 2)
                continue;

            String location = mapGenLocation(locParts[0]);
            int rarity = Integer.parseInt(locParts[1]);
            if (location == null)
                continue;

            pattern.addGenLocation(location, rarity);
        }
    }

    private String mapGenLocation (String location) {
        if (location.equals("mineshaftCorridor"))
            return ChestGenHooks.MINESHAFT_CORRIDOR;
        if (location.equals("pyramidDesertChest"))
            return ChestGenHooks.PYRAMID_DESERT_CHEST;
        if (location.equals("pyramidJungleChest"))
            return ChestGenHooks.PYRAMID_JUNGLE_CHEST;
        if (location.equals("strongholdCorridor"))
            return ChestGenHooks.STRONGHOLD_CORRIDOR;
        if (location.equals("strongholdLibrary"))
            return ChestGenHooks.STRONGHOLD_LIBRARY;
        if (location.equals("strongholdCrossing"))
            return ChestGenHooks.STRONGHOLD_CROSSING;
        if (location.equals("villageBlacksmith"))
            return ChestGenHooks.VILLAGE_BLACKSMITH;
        if (location.equals("dungeonChest"))
            return ChestGenHooks.DUNGEON_CHEST;

        return null;
    }

    public boolean hasPattern (int index) {
        return patterns[index] != null;
    }

    public PatternConfig getPattern (int index) {
        return patterns[index];
    }

    public int getPatternCount () {
        return patternCount;
    }

    /*public String getOverlayImage (int index) {
        return overlayImages[index];
    }

    public String getOverlayName (int index) {
        return overlayNames[index];
    }*/
} public class PatternConfig
{
    private int patternId;
    private String overlay;
    private String name;
    private List<String> genLocations = new ArrayList<String>();
    private List<Integer> genRarity = new ArrayList<Integer>();

    public PatternConfig (int id, String overlay, String name) {
        this.patternId = id;
        this.overlay = overlay;
        this.name = name;
    }

    public int getId () {
        return patternId;
    }

    public String getOverlay () {
        return overlay;
    }

    public String getName () {
        return name;
    }

    public int getLocationCount () {
        return genLocations.size();
    }

    public String getGenLocation (int index) {
        return genLocations.get(index);
    }

    public int getGenRarity (int index) {
        return genRarity.get(index);
    }

    public void setName (String name) {
        this.name = name;
    }

    public void addGenLocation (String location, int rarity) {
        genLocations.add(location);
        genRarity.add(rarity);
    }
} public class ModBlocks
{
    public static BlockLargePot largePot;
    public static BlockLargePot largePotColored;
    public static BlockLargePotPlantProxy largePotPlantProxy;
    public static BlockPotteryTable potteryTable;
    public static BlockThinLog thinLog;
    public static BlockThinLogFence thinLogFence;
    public static BlockFlowerLeaves flowerLeaves;

    public void init () {
        largePot = new BlockLargePot("largePot", false);
        largePotColored = new BlockLargePot("largePotColored", true);
        largePotPlantProxy = new BlockLargePotPlantProxy("largePotPlantProxy");
        potteryTable = new BlockPotteryTable("potteryTable");
        thinLog = new BlockThinLog("thinLog");
        thinLogFence = new BlockThinLogFence("thinLogFence");
        flowerLeaves = new BlockFlowerLeaves("flowerLeaves");

        String MOD_ID = ModularPots.MOD_ID;

        GameRegistry.registerBlock(largePot, ItemLargePot.class, "large_pot");
        GameRegistry.registerBlock(largePotColored, ItemLargePotColored.class, "large_pot_colored");
        GameRegistry.registerBlock(largePotPlantProxy, "large_pot_plant_proxy");
        GameRegistry.registerBlock(thinLog, ItemThinLog.class, "thin_log");
        GameRegistry.registerBlock(thinLogFence, ItemThinLogFence.class, "thin_log_fence");
        GameRegistry.registerBlock(potteryTable, "pottery_table");
        //GameRegistry.registerBlock(flowerLeaves, "flower_leaves");

        GameRegistry.registerTileEntity(TileEntityLargePot.class, ModBlocks.getQualifiedName(largePot));
        GameRegistry.registerTileEntity(TileEntityPotteryTable.class, ModBlocks.getQualifiedName(potteryTable));
        GameRegistry.registerTileEntity(TileEntityWoodProxy.class, ModBlocks.getQualifiedName(thinLog));
    }

    public static Block get (String name) {
        return GameRegistry.findBlock(ModularPots.MOD_ID, name);
    }

    public static String getQualifiedName (Block block) {
        return GameData.blockRegistry.getNameForObject(block);
    }

    public static UniqueMetaIdentifier getUniqueMetaID (Block block, int meta) {
        String name = GameData.blockRegistry.getNameForObject(block);
        if (name == null) {
            FMLLog.log(ModularPots.MOD_ID, Level.WARN, "Tried to make a UniqueMetaIdentifier from an invalid block");
            return null;
        }

        return new UniqueMetaIdentifier(name, meta);
    }
} public class ModIntegration
{
    public void init () {
        TreecapitatorIntegration.init();
        PlantMegaPackIntegration.init();
    }

    public void postInit () {
        BiomesOPlentyIntegration.init();

    }
} public class ModItems
{
    public static ItemSoilKit soilTestKit;
    public static ItemUsedSoilKit usedSoilTestKit;
    public static ItemPotteryPattern potteryPattern;

    public void init () {
        soilTestKit = new ItemSoilKit("soilTestKit");
        usedSoilTestKit = new ItemUsedSoilKit("soilTestKitUsed");
        potteryPattern = new ItemPotteryPattern("potteryPattern");

        String MOD_ID = ModularPots.MOD_ID;

        GameRegistry.registerItem(soilTestKit, "soil_test_kit");
        GameRegistry.registerItem(usedSoilTestKit, "soil_test_kit_used");
        GameRegistry.registerItem(potteryPattern, "pottery_pattern");
    }

    public static UniqueMetaIdentifier getUniqueMetaID (Item item, int meta) {
        String name = GameData.itemRegistry.getNameForObject(item);
        return new UniqueMetaIdentifier(name, meta);
    }

    public static UniqueMetaIdentifier getUniqueMetaID (ItemStack itemStack) {
        if (itemStack.getItem() == null)
            return null;
        return getUniqueMetaID(itemStack.getItem(), itemStack.getItemDamage());
    }
} public class ModRecipes
{
    private static final String TINKERS_ID = "TConstruct";

    private static final Item[] axeList = new Item[] {
        Items.wooden_axe, Items.stone_axe, Items.iron_axe, Items.golden_axe, Items.diamond_axe
    };

    public void init () {
        // Crafting

        GameRegistry.addRecipe(new ItemStack(ModBlocks.largePot, 3, 1), "x x", "x x", "xxx",
            'x', Blocks.clay);
        GameRegistry.addRecipe(new ItemStack(ModBlocks.largePot, 3), "x x", "x x", "xxx",
            'x', Blocks.hardened_clay);

        for (int i = 0; i < 16; i++) {
            GameRegistry.addRecipe(new ItemStack(ModBlocks.largePotColored, 3, i), "x x", "x x", "xxx",
                'x', new ItemStack(Blocks.stained_hardened_clay, 1, 15 - i));

            GameRegistry.addShapelessRecipe(new ItemStack(ModBlocks.largePotColored, 1, i),
                ModBlocks.largePot, new ItemStack(Items.dye, 1, i));
        }

        GameRegistry.addRecipe(new ItemStack(ModBlocks.potteryTable), "x", "y",
            'x', Items.clay_ball, 'y', Blocks.crafting_table);

        for (int i = 0; i < BlockThinLog.subNames.length; i++) {
            GameRegistry.addRecipe(new ItemStack(ModBlocks.thinLogFence, 2, i), "xyx", " y ",
                'x', Items.string, 'y', new ItemStack(ModBlocks.thinLog, 1, i));

            if (i / 4 == 0) {
                GameRegistry.addRecipe(new ItemStack(Blocks.log, 1, i % 4), "xx", "xx",
                    'x', new ItemStack(ModBlocks.thinLog, 1, i));
                if (!Loader.isModLoaded(TINKERS_ID))
                    GameRegistry.addRecipe(new ItemStack(ModBlocks.thinLog, 4, i), "x", "x",
                        'x', new ItemStack(Blocks.log, 1, i % 4));
                for (int j = 0; j < axeList.length; j++)
                    GameRegistry.addRecipe(new ItemStack(ModBlocks.thinLog, 4, i), "x", "y",
                        'x', new ItemStack(axeList[j], 1, OreDictionary.WILDCARD_VALUE), 'y', new ItemStack(Blocks.log, 1, i % 4));
            }
            else if (i / 4 == 1) {
                GameRegistry.addRecipe(new ItemStack(Blocks.log2, 1, i % 4), "xx", "xx",
                    'x', new ItemStack(ModBlocks.thinLog, 1, i));
                if (!Loader.isModLoaded(TINKERS_ID))
                    GameRegistry.addRecipe(new ItemStack(ModBlocks.thinLog, 4, i), "x", "x",
                        'x', new ItemStack(Blocks.log2, 1, i % 4));
                for (int j = 0; j < axeList.length; j++)
                    GameRegistry.addRecipe(new ItemStack(ModBlocks.thinLog, 4, i), "x", "y",
                        'x', new ItemStack(axeList[j], 1, OreDictionary.WILDCARD_VALUE), 'y', new ItemStack(Blocks.log2, 1, i % 4));
            }
        }

        addExtraWoodRecipes();

        GameRegistry.addRecipe(new ItemStack(ModItems.soilTestKit), "xy", "zz",
            'x', new ItemStack(Items.dye, 1, 1), 'y', new ItemStack(Items.dye, 1, 2), 'z', Items.glass_bottle);
        GameRegistry.addRecipe(new ItemStack(ModItems.soilTestKit), "yx", "zz",
            'x', new ItemStack(Items.dye, 1, 1), 'y', new ItemStack(Items.dye, 1, 2), 'z', Items.glass_bottle);

        // Smelting

        GameRegistry.addSmelting(new ItemStack(ModBlocks.largePot, 1, 1), new ItemStack(ModBlocks.largePot, 1, 0), 0);

        for (int i = 1; i < 256; i++) {
            if (ModularPots.config.hasPattern(i))
                GameRegistry.addSmelting(new ItemStack(ModBlocks.largePot, 1, 1 | (i << 8)), new ItemStack(ModBlocks.largePot, 1, (i << 8)), 0);
        }
    }

    private void addExtraWoodRecipes () {
        for (Map.Entry<UniqueMetaIdentifier, Block> entry : WoodRegistry.registeredTypes()) {
            UniqueMetaIdentifier id = entry.getKey();
            int meta = TileEntityWoodProxy.composeMetadata(id.getBlock(), id.meta);

            GameRegistry.addRecipe(new ItemStack(id.getBlock(), 1, id.meta), "xx", "xx",
                'x', new ItemStack(ModBlocks.thinLog, 1, meta));
            if (!Loader.isModLoaded(TINKERS_ID))
                GameRegistry.addRecipe(new ItemStack(ModBlocks.thinLog, 4, meta), "x", "x",
                    'x', new ItemStack(id.getBlock(), 1, id.meta));
            for (int j = 0; j < axeList.length; j++)
                GameRegistry.addRecipe(new ItemStack(ModBlocks.thinLog, 4, meta), "x", "y",
                    'x', new ItemStack(axeList[j], 1, OreDictionary.WILDCARD_VALUE), 'y', new ItemStack(id.getBlock(), 1, id.meta));

            GameRegistry.addRecipe(new ItemStack(ModBlocks.thinLogFence, 2, meta), "xyx", " y ",
                'x', Items.string, 'y', new ItemStack(ModBlocks.thinLog, 1, meta));
        }
    }
} public class GuiHandler implements IGuiHandler
{
    @Override
    public Object getServerGuiElement (int ID, EntityPlayer player, World world, int x, int y, int z) {
        TileEntity tileEntity = world.getTileEntity(x, y, z);
        if (tileEntity instanceof TileEntityPotteryTable)
            return new ContainerPotteryTable(player.inventory, (TileEntityPotteryTable) tileEntity);

        return null;
    }

    @Override
    public Object getClientGuiElement (int ID, EntityPlayer player, World world, int x, int y, int z) {
        TileEntity tileEntity = world.getTileEntity(x, y, z);
        if (tileEntity instanceof TileEntityPotteryTable)
            return new GuiPotteryTable(player.inventory, (TileEntityPotteryTable) tileEntity);

        return null;
    }
} public class VillagerTradeHandler implements VillagerRegistry.IVillageTradeHandler
{
    private static VillagerTradeHandler instance = new VillagerTradeHandler();

    public static VillagerTradeHandler instance () {
        return instance;
    }

    public void load () {
        VillagerRegistry.instance().registerVillageTradeHandler(1, this);
        VillagerRegistry.instance().registerVillageTradeHandler(2, this);
        VillagerRegistry.instance().registerVillageTradeHandler(3, this);
    }

    @Override
    public void manipulateTradesForVillager (EntityVillager villager, MerchantRecipeList recipeList, Random random) {
        float buyProb = 1.5f / ModularPots.config.getPatternCount();
        float sellProb = .5f / ModularPots.config.getPatternCount();

        for (int i = 1; i < 256; i++) {
            if (ModularPots.config.hasPattern(i)) {
                if (random.nextFloat() < buyProb) {
                    int emeralds = 1 + random.nextInt(4);
                    recipeList.add(new MerchantRecipe(new ItemStack(ModItems.potteryPattern, 1, i), new ItemStack(Items.emerald, emeralds)));
                }
                else if (random.nextFloat() < sellProb) {
                    int emeralds = 8 + random.nextInt(16);
                    recipeList.add(new MerchantRecipe(new ItemStack(Items.emerald, emeralds), new ItemStack(ModItems.potteryPattern, 1, i)));
                }
            }
        }
    }
} public class ModularPotsCreativeTab extends CreativeTabs
{
    public ModularPotsCreativeTab (String label) {
        super(label);
    }

    @SideOnly(Side.CLIENT)
    @Override
    public Item getTabIconItem () {
        return Item.getItemFromBlock(ModBlocks.largePot);
    }
} public class ItemThinLog extends ItemBlock
{
    public ItemThinLog (Block block) {
        super(block);
        setMaxDamage(0);
        setHasSubtypes(true);
    }

    @Override
    public int getMetadata (int meta) {
        return meta;
    }

    @Override
    public String getUnlocalizedName (ItemStack itemStack) {
        int meta = itemStack.getItemDamage();
        if (meta < 0 || meta >= BlockThinLog.subNames.length)
            return super.getUnlocalizedName();

        return super.getUnlocalizedName() + "." + BlockThinLog.subNames[meta];
    }

    @Override
    public String getItemStackDisplayName (ItemStack itemStack) {
        int meta = itemStack.getItemDamage();
        if (meta < 16)
            return super.getItemStackDisplayName(itemStack);

        Block block = TileEntityWoodProxy.getBlockFromComposedMetadata(meta);
        Item item = Item.getItemFromBlock(block);
        if (item == null)
            return super.getItemStackDisplayName(itemStack);

        String unlocName = item.getUnlocalizedName(new ItemStack(item, 1, TileEntityWoodProxy.getMetaFromComposedMetadata(meta)));

        return ("" + StatCollector.translateToLocal(unlocName + ".name") + " " + StatCollector.translateToLocal(getUnlocalizedName() + ".name")).trim();
    }

    @Override
    public IIcon getIconFromDamage (int meta) {
        return ModBlocks.thinLog.getIcon(0, meta);
    }

    @Override
    public int getColorFromItemStack (ItemStack itemStack, int meta) {
        return ModBlocks.thinLog.getRenderColor(itemStack.getItemDamage());
    }

    @Override
    public boolean placeBlockAt (ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ, int metadata)
    {
        int blockMeta = (metadata < 16) ? metadata : 0;
        if (!super.placeBlockAt(stack, player, world, x, y, z, side, hitX, hitY, hitZ, blockMeta))
            return false;

        TileEntityWoodProxy.syncTileEntityWithData(world, x, y, z, metadata);
        return true;
    }
} public class PlantRegistry
{
    private static PlantRegistry instance;

    private List<UniqueMetaIdentifier> blacklist;
    private List<UniqueMetaIdentifier> bonemealBlacklist;

    public static PlantRegistry instance () {
        if (instance == null)
            new PlantRegistry();
        return instance;
    }

    protected PlantRegistry () {
        instance = this;

        blacklist = new ArrayList<UniqueMetaIdentifier>();
        bonemealBlacklist = new ArrayList<UniqueMetaIdentifier>();
    }

    public boolean isBlacklisted (UniqueMetaIdentifier id) {
        return blacklist.contains(id);
    }

    public boolean isBlacklisted (UniqueMetaIdentifier id, RegistryGroup group) {
        switch (group) {
            case Plant:
                return blacklist.contains(id) || blacklist.contains(new UniqueMetaIdentifier(id.modId, id.name, OreDictionary.WILDCARD_VALUE));
            case Bonemeal:
                return bonemealBlacklist.contains(id) || bonemealBlacklist.contains(new UniqueMetaIdentifier(id.modId, id.name, OreDictionary.WILDCARD_VALUE));
            default:
                return false;
        }
    }

    public boolean isBlacklisted (ItemStack itemStack) {
        return isBlacklisted(ModItems.getUniqueMetaID(itemStack));
    }

    public void addToBlacklist (ItemStack itemStack) {
        UniqueMetaIdentifier id = ModItems.getUniqueMetaID(itemStack);
        if (id != null && !blacklist.contains(id)) {
            blacklist.add(id);
            FMLLog.log(ModularPots.MOD_ID, Level.INFO, "Blacklisting plant " + id.toString());
        }
    }

    public void addToBlacklist (ItemStack itemStack, RegistryGroup group) {
        List<UniqueMetaIdentifier> list = null;
        switch (group) {
            case Plant:
                list = blacklist;
                break;
            case Bonemeal:
                list = bonemealBlacklist;
                break;
        }

        UniqueMetaIdentifier id = ModItems.getUniqueMetaID(itemStack);
        if (id != null && list != null && !list.contains(id)) {
            list.add(id);
            FMLLog.log(ModularPots.MOD_ID, Level.INFO, "Blacklisting plant " + id.toString() + " (" + group.toString() + ")");
        }
    }

    public void addToBlacklist (NBTTagCompound tagData) {
        if (tagData.hasKey("items", Constants.NBT.TAG_LIST)) {
            NBTTagList list = tagData.getTagList("items", Constants.NBT.TAG_COMPOUND);
            for (int i = 0; i < list.tagCount(); i++)
                addToBlacklist(list.getCompoundTagAt(i));
            return;
        }

        try {
            ItemStack item = ItemStack.loadItemStackFromNBT(tagData);
            if (item != null)
                addToBlacklist(item);
        }
        catch (Exception e) { }
    }

    public void addToBlacklist (NBTTagCompound tagData, RegistryGroup group) {
        if (tagData.hasKey("items", Constants.NBT.TAG_LIST)) {
            NBTTagList list = tagData.getTagList("items", Constants.NBT.TAG_COMPOUND);
            for (int i = 0; i < list.tagCount(); i++)
                addToBlacklist(list.getCompoundTagAt(i), group);
            return;
        }

        try {
            ItemStack item = ItemStack.loadItemStackFromNBT(tagData);
            if (item != null)
                addToBlacklist(item, group);
        }
        catch (Exception e) { }
    }
} public enum RegistryGroup
{
    Plant,
    Bonemeal;
}
import com.jaquadro.minecraft.modularpots.addon.PlantHandlerRegistry;
import com.jaquadro.minecraft.modularpots.block.*;
import com.jaquadro.minecraft.modularpots.block.support.WoodRegistry;
import com.jaquadro.minecraft.modularpots.config.ConfigManager;
import com.jaquadro.minecraft.modularpots.config.PatternConfig;
import com.jaquadro.minecraft.modularpots.core.ModBlocks;
import com.jaquadro.minecraft.modularpots.core.ModIntegration;
import com.jaquadro.minecraft.modularpots.core.ModItems;
import com.jaquadro.minecraft.modularpots.core.ModRecipes;
import com.jaquadro.minecraft.modularpots.core.handlers.GuiHandler;
import com.jaquadro.minecraft.modularpots.core.handlers.VillagerTradeHandler;
import com.jaquadro.minecraft.modularpots.creativetab.ModularPotsCreativeTab;
import com.jaquadro.minecraft.modularpots.item.ItemThinLog;
import com.jaquadro.minecraft.modularpots.registry.PlantRegistry;
import com.jaquadro.minecraft.modularpots.registry.RegistryGroup;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.SidedProxy;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLInterModComms;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.eventhandler.Event.Result;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.PlayerEvent;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.WeightedRandomChestContent;
import net.minecraftforge.common.ChestGenHooks;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.BonemealEvent;
import java.io.File;
package com.jaquadro.minecraft.modularpots;



@Mod(modid = ModularPots.MOD_ID, name = ModularPots.MOD_NAME, version = ModularPots.MOD_VERSION)
public class ModularPots
{
    public static final String MOD_ID = "modularpots";
    static final String MOD_NAME = "Modular Flower Pots";
    static final String MOD_VERSION = "1.7.10.14";
    static final String SOURCE_PATH = "com.jaquadro.minecraft.modularpots.";

    public static CreativeTabs tabModularPots = new ModularPotsCreativeTab("modularPots");

    public static final ModBlocks blocks = new ModBlocks();
    public static final ModItems items = new ModItems();
    public static final ModRecipes recipes = new ModRecipes();
    public static final ModIntegration integration = new ModIntegration();

    public static int potteryTableGuiID = 0;

    public static ConfigManager config;

    @Mod.Instance(MOD_ID)
    public static ModularPots instance;

    @SidedProxy(clientSide = SOURCE_PATH + "client.ClientProxy", serverSide = SOURCE_PATH + "CommonProxy")
    public static CommonProxy proxy;

    @Mod.EventHandler
    public void preInit (FMLPreInitializationEvent event) {
        config = new ConfigManager(new File(event.getModConfigurationDirectory(), MOD_ID + ".patterns.cfg"));

        blocks.init();
        items.init();
    }

    @Mod.EventHandler
    public void load (FMLInitializationEvent event) {
        proxy.registerRenderers();
        MinecraftForge.EVENT_BUS.register(this);
        FMLCommonHandler.instance().bus().register(this);
        NetworkRegistry.INSTANCE.registerGuiHandler(this, new GuiHandler());

        for (int i = 1; i < 256; i++) {
            if (!config.hasPattern(i))
                continue;

            PatternConfig pattern = config.getPattern(i);
            for (int j = 0; j < pattern.getLocationCount(); j++)
                ChestGenHooks.addItem(pattern.getGenLocation(j), new WeightedRandomChestContent(items.potteryPattern, i, 1, 1, pattern.getGenRarity(j)));
        }

        VillagerTradeHandler.instance().load();