/** * Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team * http://www.mod-buildcraft.com * * BuildCraft is distributed under the terms of the Minecraft Mod Public * License 1.0, or MMPL. Please check the contents of the license located in * http://www.mod-buildcraft.com/MMPL-1.0.txt */ package buildcraft.transport; import java.util.LinkedList; import java.util.List; import java.util.Set; import buildcraft.core.BlockSpring; import buildcraft.core.BuildCraftConfiguration; import net.minecraft.block.Block; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.IRecipe; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import buildcraft.BuildCraftTransport; import buildcraft.api.core.Position; import buildcraft.api.recipes.BuildcraftRecipes; import buildcraft.core.CreativeTabBuildCraft; import buildcraft.core.ItemBuildCraft; import buildcraft.core.proxy.CoreProxy; import com.google.common.base.Strings; import com.google.common.collect.Sets; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public class ItemFacade extends ItemBuildCraft { public final static LinkedList allFacades = new LinkedList(); public final static LinkedList blacklistedFacades = new LinkedList(); public ItemFacade() { super(); setHasSubtypes(true); setMaxDamage(0); setCreativeTab(CreativeTabBuildCraft.FACADES.get()); } @Override public String getItemStackDisplayName(ItemStack itemstack) { String name = super.getItemStackDisplayName(itemstack); Block decodedBlock = ItemFacade.getBlock(itemstack); int decodedMeta = ItemFacade.getMetaData(itemstack); if (decodedBlock != null && decodedBlock.getRenderType() == 31) { decodedMeta &= 0x3; } ItemStack newStack = new ItemStack(decodedBlock, 1, decodedMeta); if (Item.getItemFromBlock(decodedBlock) != null) { name += ": " + CoreProxy.proxy.getItemDisplayName(newStack); } else { String localizedName; try { localizedName = decodedBlock.getLocalizedName(); } catch(NullPointerException npe) { localizedName = "Null"; } name += " < BROKEN (" + localizedName + ":" + decodedMeta + " )>"; } return name; } @Override public String getUnlocalizedName(ItemStack itemstack) { return "item.Facade"; } @SuppressWarnings({"unchecked", "rawtypes"}) @Override @SideOnly(Side.CLIENT) public void getSubItems(Item item, CreativeTabs par2CreativeTabs, List itemList) { // Do not call super, that would add a 0:0 facade for (ItemStack stack : allFacades) { itemList.add(stack.copy()); } } @Override public boolean onItemUse(ItemStack stack, EntityPlayer player, World worldObj, int x, int y, int z, int side, float hitX, float hitY, float hitZ) { if (worldObj.isRemote) return false; Position pos = new Position(x, y, z, ForgeDirection.getOrientation(side)); pos.moveForwards(1.0); TileEntity tile = worldObj.getTileEntity((int) pos.x, (int) pos.y, (int) pos.z); if (!(tile instanceof TileGenericPipe)) return false; TileGenericPipe pipeTile = (TileGenericPipe) tile; if (pipeTile.addFacade(ForgeDirection.getOrientation(side).getOpposite(), ItemFacade.getBlock(stack), ItemFacade.getMetaData(stack))) { stack.stackSize--; return true; } return false; } public static void initialize() { for (Object o : Block.blockRegistry) { Block b = (Block) o; if (!isBlockValidForFacade(b)) { continue; } Item item = Item.getItemFromBlock(b); if (item == null) { continue; } if (isBlockBlacklisted(b)) { continue; } registerValidFacades(b, item); } } private static void registerValidFacades(Block block, Item item) { Set names = Sets.newHashSet(); for(int i=0; i <= 15; i++) { try { ItemStack stack = new ItemStack(item, 1, i); if(!Strings.isNullOrEmpty(stack.getUnlocalizedName()) && names.add(stack.getUnlocalizedName())) { ItemFacade.addFacade(stack); // prevent adding multiple facades if it's a rotatable block if(block.getRenderType() == 31) { break; } } } catch(IndexOutOfBoundsException _){ } catch(Throwable t) { t.printStackTrace(); } } } private static boolean isBlockBlacklisted(Block block) { String blockName = Block.blockRegistry.getNameForObject(block); for (String blacklistedBlock : BuildCraftTransport.facadeBlacklist) { if(blockName.equals(BuildCraftConfiguration.stripSurroundingQuotes(blacklistedBlock))) { return true; } } for(String blacklistedBlock : blacklistedFacades){ if(blockName.equals(blacklistedBlock)){ return true; } } return false; } private static boolean isBlockValidForFacade(Block block) { if(block.getRenderType() != 0 && block.getRenderType() != 31) { return false; } if(block.getBlockBoundsMaxX() != 1.0 || block.getBlockBoundsMaxY() != 1.0 || block.getBlockBoundsMaxZ() != 1.0){ return false; } if(block instanceof BlockSpring || block instanceof BlockGenericPipe) { return false; } return true; } public static int getMetaData(ItemStack stack) { if (stack.hasTagCompound() && stack.getTagCompound().hasKey("meta")) { return stack.getTagCompound().getInteger("meta"); } else { return stack.getItemDamage() & 0x0000F; } } public static Block getBlock(ItemStack stack) { if(!stack.hasTagCompound()) { return null; } Block facadeBlock = null; NBTTagCompound stackTagCompound = stack.getTagCompound(); // reading the 'id' tag is kept to maintain back-compat. // The stack gets upgraded the first time this code is run. if(stackTagCompound.hasKey("id")) { facadeBlock = (Block)Block.blockRegistry.getObjectById(stackTagCompound.getInteger("id")); stackTagCompound.removeTag("id"); stackTagCompound.setString("name", Block.blockRegistry.getNameForObject(facadeBlock)); } else if (stackTagCompound.hasKey("name")) { facadeBlock = (Block) Block.blockRegistry.getObject(stackTagCompound.getString("name")); } return facadeBlock; } @Override public boolean doesSneakBypassUse(World world, int x, int y, int z, EntityPlayer player) { // Simply send shift click to the pipe / mod block. return true; } public static void addFacade(ItemStack itemStack) { if(itemStack.stackSize == 0) { itemStack.stackSize = 1; } ItemStack facade = getStack(Block.getBlockFromItem(itemStack.getItem()), itemStack.getItemDamage()); if(!allFacades.contains(facade)) { allFacades.add(facade); ItemStack facade6 = facade.copy(); facade6.stackSize = 6; // 3 Structurepipes + this block makes 6 facades BuildcraftRecipes.assemblyTable.addRecipe(8000, facade6, new ItemStack(BuildCraftTransport.pipeStructureCobblestone, 3), itemStack); } } public static void blacklistFacade(String blockName) { if(!blacklistedFacades.contains(blockName)) { blacklistedFacades.add(blockName); } } private static final Block NULL_BLOCK = null; private static final ItemStack NO_MATCH = new ItemStack(NULL_BLOCK, 0, 0); public class FacadeRecipe implements IRecipe { @Override public boolean matches(InventoryCrafting inventorycrafting, World world) { Object[] facade = getFacadeBlockFromCraftingGrid(inventorycrafting); return facade != null && facade[0] != null; } @Override public ItemStack getCraftingResult(InventoryCrafting inventorycrafting) { Object[] facade = getFacadeBlockFromCraftingGrid(inventorycrafting); if(facade == null) { return null; } Block block = (Block)facade[0]; ItemStack originalFacade = (ItemStack)facade[1]; if(block == null) { return null; } return getNextFacadeItemStack(block, originalFacade); } private Object[] getFacadeBlockFromCraftingGrid(InventoryCrafting inventorycrafting) { ItemStack slotmatch = null; int countOfItems = 0; for (int i = 0; i < inventorycrafting.getSizeInventory(); i++) { ItemStack slot = inventorycrafting.getStackInSlot(i); if (slot != null && slot.getItem() == ItemFacade.this && slotmatch == null) { slotmatch = slot; countOfItems++; } else if (slot != null) { slotmatch = NO_MATCH; } if(countOfItems > 1) { return null; } } if (slotmatch != null && slotmatch != NO_MATCH) { return new Object[] { ItemFacade.getBlock(slotmatch), slotmatch }; } return null; } private ItemStack getNextFacadeItemStack(Block block, ItemStack originalFacade) { int blockMeta = ItemFacade.getMetaData(originalFacade); int stackMeta = 0; switch(block.getRenderType()) { case 1: //supports cycling through variants (wool, planks, etc) if(blockMeta >= 15) { stackMeta = 0; } else { stackMeta = blockMeta + 1; } break; case 31: if ((blockMeta & 0xC) == 0) { // Meta | 4 = true stackMeta = (blockMeta & 0x3) | 4; } else if ((blockMeta & 0x8) == 0) { // Meta | 8 = true stackMeta = (blockMeta & 0x3) | 8; } else if ((blockMeta & 0x4) == 0) { stackMeta = (blockMeta & 0x3); } break; default: stackMeta = blockMeta; } return getStack(block, stackMeta); } @Override public int getRecipeSize() { return 1; } @Override public ItemStack getRecipeOutput() { return null; } } @Override @SideOnly(Side.CLIENT) public void registerIcons(IIconRegister par1IconRegister) { // NOOP } @Override @SideOnly(Side.CLIENT) public int getSpriteNumber() { return 0; } public static ItemStack getStack(Block block, int metadata) { ItemStack stack = new ItemStack(BuildCraftTransport.facadeItem, 1, 0); NBTTagCompound nbt = new NBTTagCompound(); nbt.setInteger("meta", metadata); nbt.setString("name", Block.blockRegistry.getNameForObject(block)); stack.setTagCompound(nbt); return stack; } }