package de.take_weiland.mods.commons.util; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.registry.GameRegistry; import de.take_weiland.mods.commons.internal.SevenCommons; import de.take_weiland.mods.commons.inv.Inventories; import de.take_weiland.mods.commons.meta.HasSubtypes; import de.take_weiland.mods.commons.meta.MetadataProperty; import de.take_weiland.mods.commons.meta.Subtype; import de.take_weiland.mods.commons.templates.SCItemBlock; import de.take_weiland.mods.commons.templates.TypedItemBlock; import net.minecraft.block.Block; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.world.World; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import java.util.List; import static de.take_weiland.mods.commons.util.RegistrationUtil.checkPhase; @ParametersAreNonnullByDefault public final class Blocks { private Blocks() { } /** * <p>Equivalent to {@link #init(net.minecraft.block.Block, String, Class, String)} using the currently active mod and a default ItemBlock class.</p> * * @param block the Block instance * @param baseName base name for this block */ public static void init(Block block, String baseName) { init(block, baseName, getItemBlockClass(block, null)); } /** * <p>Equivalent to {@link #init(net.minecraft.block.Block, String, Class, String)} using a default ItemBlock class.</p> * * @param modId Your ModId * @param block the Block instance * @param baseName base name for this block */ public static void init(String modId, Block block, String baseName) { init(block, baseName, getItemBlockClass(block, null), modId); } /** * <p>Equivalent to {@link #init(net.minecraft.block.Block, String, Class, String)} using the currently active mod.</p> * * @param block the Block instance * @param baseName base name for this block * @param itemClass the ItemBlock class to use */ public static void init(Block block, String baseName, Class<? extends ItemBlock> itemClass) { // check phase here already so that we don't fail with a NPE on activeModContainer instead checkPhase("Block"); init(block, baseName, itemClass, Loader.instance().activeModContainer().getModId()); } /** * <p>Generic initialization for Blocks:</p> * <ul> * <li>Sets the Block's texture to <tt>modId:baseName</tt>, unless it is already set</li> * <li>Sets the Block's unlocalized name to <tt>modId.baseName</tt>, unless it is already set</li> * <li>Register the block with {@link cpw.mods.fml.common.registry.GameRegistry#registerBlock(net.minecraft.block.Block, Class, String, String)}</li> * <li><i>TODO!</i></li> * </ul> * <p>The ItemBlock class provided should extend {@link de.take_weiland.mods.commons.templates.SCItemBlock} (resp. * {@link de.take_weiland.mods.commons.templates.TypedItemBlock} for Blocks that implement {@link de.take_weiland.mods.commons.meta.HasSubtypes}) * to enable all features of SevenCommons for this Block.</p> * * @param block the Block instance * @param baseName base name for this block * @param itemClass the ItemBlock class to use * @param modId Your ModId */ public static void init(Block block, String baseName, Class<? extends ItemBlock> itemClass, String modId) { checkPhase("Block"); if (SCReflector.instance.getRawIconName(block) == null) { block.setTextureName(modId + ":" + baseName); } if (SCReflector.instance.getRawUnlocalizedName(block) == null) { block.setUnlocalizedName(modId + "." + baseName); } GameRegistry.registerBlock(block, getItemBlockClass(block, itemClass), baseName); if (block instanceof HasSubtypes) { ItemStacks.registerSubstacks(baseName, getItem(block)); } } public static Item getItem(Block block) { return Item.itemsList[block.blockID]; } public static Block fromItem(Item item) { if (item instanceof ItemBlock) { return Block.blocksList[((ItemBlock) item).getBlockID()]; } else { throw new IllegalArgumentException("Not an ItemBlock"); } } /** * <p>Generic implementation for {@link net.minecraft.block.Block#breakBlock}. This method drops the contents of any Inventory * associated with the block and should therefor be called before any TileEntity is removed.</p> * * @param block the Block instance * @param world the World * @param x x position * @param y y position * @param z z position * @param meta the metadata of the block being broken */ public static void genericBreak(Block block, World world, int x, int y, int z, int meta) { if (block.hasTileEntity(meta)) { Inventories.spillIfInventory(world.getBlockTileEntity(x, y, z)); } } /** * <p>Generic implementation for {@link net.minecraft.block.Block#getSubBlocks(int, net.minecraft.creativetab.CreativeTabs, java.util.List)}. * This method takes the {@link de.take_weiland.mods.commons.meta.HasSubtypes} interface into account.</p> * * @param block the Block instance * @param list the list to add ItemStacks to */ @SuppressWarnings({ "rawtypes", "unchecked" }) public static void getSubBlocksImpl(Block block, List list) { if (block instanceof HasSubtypes) { // this should technically be <? extends Subtype> but Java has no way of doing this MetadataProperty<Subtype> property = ((HasSubtypes<Subtype>) block).subtypeProperty(); for (Subtype type : property.values()) { list.add(property.apply(type, new ItemStack(block))); } } else { list.add(new ItemStack(block)); } } public static Block byID(int id) { return Block.blocksList[id]; } private static Class<? extends ItemBlock> getItemBlockClass(Block block, @Nullable Class<? extends ItemBlock> itemBlock) { Class<? extends ItemBlock> defaultClass = getDefaultItemBlock(block); if (itemBlock == null) { return defaultClass; } if (!defaultClass.isAssignableFrom(itemBlock)) { SevenCommons.LOGGER.warning(String.format("ItemBlock class %s should extend %s to enable all SevenCommons features!", itemBlock.getName(), defaultClass.getSimpleName())); } return itemBlock; } private static Class<? extends ItemBlock> getDefaultItemBlock(Block block) { return block instanceof HasSubtypes ? TypedItemBlock.class : SCItemBlock.class; } private static final short BLOCK_NULL_ID = -1; }