package com.jaquadro.minecraft.gardentrees.block; import com.jaquadro.minecraft.gardentrees.GardenTrees; import com.jaquadro.minecraft.gardentrees.core.ClientProxy; import com.jaquadro.minecraft.gardentrees.core.ModCreativeTabs; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.Direction; import net.minecraft.util.IIcon; import net.minecraft.world.ColorizerFoliage; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.common.IShearable; import net.minecraftforge.common.util.ForgeDirection; import java.util.ArrayList; import java.util.Random; public class BlockIvy extends Block implements IShearable { @SideOnly(Side.CLIENT) private IIcon[] textures; public BlockIvy (String name) { super(Material.vine); setBlockName(name); setTickRandomly(true); setStepSound(Block.soundTypeGrass); setCreativeTab(ModCreativeTabs.tabGardenTrees); } @Override public void setBlockBoundsForItemRender () { setBlockBounds(0, 0, 0, 1, 1, 1); } @Override public int getRenderType () { return ClientProxy.ivyRenderID; } @Override public boolean isOpaqueCube () { return false; } @Override public boolean renderAsNormalBlock () { return false; } @Override public void setBlockBoundsBasedOnState (IBlockAccess blockAccess, int x, int y, int z) { float unit = .0625f; int meta = blockAccess.getBlockMetadata(x, y, z); float xMin = 1; float yMin = 1; float zMin = 1; float xMax = 0; float yMax = 0; float zMax = 0; if ((meta & 2) != 0) { xMin = 0; yMin = 0; zMin = 0; xMax = Math.max(xMax, unit); yMax = 1; zMax = 1; } if ((meta & 8) != 0) { xMin = Math.min(xMin, 1 - unit); yMin = 0; zMin = 0; xMax = 1; yMax = 1; zMax = 1; } if ((meta & 4) != 0) { xMin = 0; yMin = 0; zMin = 0; xMax = 1; yMax = 1; zMax = Math.max(zMax, unit); } if ((meta & 1) != 0) { xMin = 0; yMin = 0; zMin = Math.min(zMin, 1 - unit); xMax = 1; yMax = 1; zMax = 1; } setBlockBounds(xMin, yMin, zMin, xMax, yMax, zMax); } @Override public AxisAlignedBB getCollisionBoundingBoxFromPool (World world, int x, int y, int z) { return null; } @Override public boolean canPlaceBlockOnSide (World world, int x, int y, int z, int side) { int opSide = side - (side % 2); switch (side) { case 2: return canPlaceOnBlock(world, x, y, z + 1, opSide); case 3: return canPlaceOnBlock(world, x, y, z - 1, opSide); case 4: return canPlaceOnBlock(world, x + 1, y, z, opSide); case 5: return canPlaceOnBlock(world, x - 1, y, z, opSide); default: return false; } } private boolean canPlaceOnBlock (World world, int x, int y, int z, int side) { Block block = world.getBlock(x, y, z); return block.getMaterial().blocksMovement() && block.isSideSolid(world, x, y, z, ForgeDirection.getOrientation(side)); } @Override public int getBlockColor () { return ColorizerFoliage.getFoliageColorBasic(); } @Override public int getRenderColor (int meta) { return ColorizerFoliage.getFoliageColorBasic(); } @Override public int colorMultiplier (IBlockAccess blockAccess, int x, int y, int z) { return blockAccess.getBiomeGenForCoords(x, z).getBiomeFoliageColor(x, y, z); } @Override public void onNeighborBlockChange (World world, int x, int y, int z, Block block) { if (!world.isRemote && !isBlockStateValid(world, x, y, z)) { dropBlockAsItem(world, x, y, z, world.getBlockMetadata(x, y, z), 0); world.setBlockToAir(x, y, z); } } @Override public void updateTick (World world, int x, int y, int z, Random random) { if (!world.isRemote && world.rand.nextInt(2) == 0) { int limit = 9; worldSearch: for (int dx = x - 4; dx <= x + 4; dx++) { for (int dz = z - 4; dz <= z + 4; dz++) { for (int dy = y - 1; dy <= y + 1; dy++) { if (world.getBlock(dx, dy, dz) == this) { limit--; if (limit <= 0) break worldSearch; } } } } int meta = world.getBlockMetadata(x, y, z); int dir = world.rand.nextInt(6); int facingDir = Direction.facingToDirection[dir]; if (dir == 1 && y < 255 && world.isAirBlock(x, y + 1, z)) { if (limit <= 0) return; int chance = world.rand.nextInt(16) & meta; if (chance > 0) { for (int i = 0; i <= 3; i++) { int opSide = Direction.directionToFacing[Direction.rotateOpposite[i]]; if (!canPlaceOnBlock(world, x + Direction.offsetX[i], y + 1, z + Direction.offsetZ[i], opSide)) chance &= ~(1 << i); } if (chance > 0) world.setBlock(x, y + 1, z, this, chance, 2); } } else { if (dir >= 2 && dir <= 5 && (meta & 1 << facingDir) == 0) { if (limit <= 4) return; Block block = world.getBlock(x + Direction.offsetX[facingDir], y, z + Direction.offsetZ[facingDir]); int opSide = Direction.directionToFacing[Direction.rotateOpposite[facingDir]]; if (block.getMaterial() == Material.air) { int dirRight = Direction.rotateRight[facingDir]; int dirLeft = Direction.rotateLeft[facingDir]; int opSideRight = Direction.directionToFacing[Direction.rotateOpposite[dirRight]]; int opSideLeft = Direction.directionToFacing[Direction.rotateOpposite[dirLeft]]; if ((meta & 1 << dirRight) != 0 && canPlaceOnBlock(world, x + Direction.offsetX[facingDir] + Direction.offsetX[dirRight], y, z + Direction.offsetZ[facingDir] + Direction.offsetZ[dirRight], opSideRight)) world.setBlock(x + Direction.offsetX[facingDir], y, z + Direction.offsetZ[facingDir], this, 1 << dirRight, 2); else if ((meta & 1 << dirLeft) != 0 && canPlaceOnBlock(world, x + Direction.offsetX[facingDir] + Direction.offsetX[dirLeft], y, z + Direction.offsetZ[facingDir] + Direction.offsetZ[dirLeft], opSideLeft)) world.setBlock(x + Direction.offsetX[facingDir], y, z + Direction.offsetZ[facingDir], this, 1 << dirLeft, 2); else if ((meta & 1 << dirRight) != 0 && world.isAirBlock(x + Direction.offsetX[facingDir] + Direction.offsetX[dirRight], y, z + Direction.offsetZ[facingDir] + Direction.offsetZ[dirRight]) && canPlaceOnBlock(world, x + Direction.offsetX[dirRight], y, z + Direction.offsetZ[dirRight], opSide)) world.setBlock(x + Direction.offsetX[facingDir] + Direction.offsetX[dirRight], y, z + Direction.offsetZ[facingDir] + Direction.offsetZ[dirRight], this, 1 << (facingDir + 2 & 3), 2); else if ((meta & 1 << dirLeft) != 0 && world.isAirBlock(x + Direction.offsetX[facingDir] + Direction.offsetX[dirLeft], y, z + Direction.offsetZ[facingDir] + Direction.offsetZ[dirLeft]) && canPlaceOnBlock(world, x + Direction.offsetX[dirLeft], y, z + Direction.offsetZ[dirLeft], opSide)) world.setBlock(x + Direction.offsetX[facingDir] + Direction.offsetX[dirLeft], y, z + Direction.offsetZ[facingDir] + Direction.offsetZ[dirLeft], this, 1 << (facingDir + 2 & 3), 2); } else if (canPlaceOnBlock(world, x + Direction.offsetX[facingDir], y, z + Direction.offsetZ[facingDir], opSide)) world.setBlockMetadataWithNotify(x, y, z, meta | 1 << facingDir, 2); } } } } private boolean isBlockStateValid (World world, int x, int y, int z) { int meta = world.getBlockMetadata(x, y, z); int mask = meta; if (meta > 0) { for (int i = 0; i <= 3; i++) { int bit = 1 << i; int opSide = Direction.directionToFacing[Direction.rotateOpposite[i]]; if ((meta & bit) != 0 && !canPlaceOnBlock(world, x + Direction.offsetX[i], y, z + Direction.offsetZ[i], opSide) && (world.getBlock(x, y + 1, z) != this || (world.getBlockMetadata(x, y + 1, z) & bit) == 0)) mask &= ~bit; } } if (mask == 0) return false; if (mask != meta) world.setBlockMetadataWithNotify(x, y, z, mask, 2); return true; } @Override public int onBlockPlaced (World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ, int meta) { int bit = 0; switch (side) { case 2: bit = 1; break; case 3: bit = 4; break; case 4: bit = 8; break; case 5: bit = 2; break; } return bit != 0 ? bit : meta; } @Override public Item getItemDropped (int meta, Random random, int fortune) { return null; } @Override public int quantityDropped (Random random) { return 0; } @Override public boolean isShearable (ItemStack item, IBlockAccess world, int x, int y, int z) { return true; } @Override public ArrayList<ItemStack> onSheared (ItemStack item, IBlockAccess world, int x, int y, int z, int fortune) { ArrayList<ItemStack> ret = new ArrayList<ItemStack>(); ret.add(new ItemStack(this, 1)); return ret; } @Override public boolean isLadder (IBlockAccess world, int x, int y, int z, EntityLivingBase entity) { return true; } @Override @SideOnly(Side.CLIENT) public IIcon getIcon (int side, int meta) { return textures[0]; } @SideOnly(Side.CLIENT) public IIcon getIconFull () { return textures[7]; } @Override @SideOnly(Side.CLIENT) public IIcon getIcon (IBlockAccess blockAccess, int x, int y, int z, int side) { boolean nTop = blockAccess.getBlock(x, y + 1, z) == this; boolean nLeft = false; boolean nRight = false; int meta = blockAccess.getBlockMetadata(x, y, z); switch (side) { case 2: nLeft = (meta & 8) != 0 || (blockAccess.getBlock(x + 1, y, z) == this && (blockAccess.getBlockMetadata(x + 1, y, z) & 1) != 0) || (blockAccess.getBlock(x + 1, y, z + 1) == this && (blockAccess.getBlockMetadata(x + 1, y, z + 1) & 2) != 0); nRight = (meta & 2) != 0 || (blockAccess.getBlock(x - 1, y, z) == this && (blockAccess.getBlockMetadata(x - 1, y, z) & 1) != 0) || (blockAccess.getBlock(x - 1, y, z + 1) == this && (blockAccess.getBlockMetadata(x - 1, y, z + 1) & 8) != 0); break; case 3: nLeft = (meta & 2) != 0 || (blockAccess.getBlock(x - 1, y, z) == this && (blockAccess.getBlockMetadata(x - 1, y, z) & 4) != 0) || (blockAccess.getBlock(x - 1, y, z - 1) == this && (blockAccess.getBlockMetadata(x - 1, y, z - 1) & 8) != 0); nRight = (meta & 8) != 0 || (blockAccess.getBlock(x + 1, y, z) == this && (blockAccess.getBlockMetadata(x + 1, y, z) & 4) != 0) || (blockAccess.getBlock(x + 1, y, z - 1) == this && (blockAccess.getBlockMetadata(x + 1, y, z - 1) & 2) != 0); break; case 4: nLeft = (meta & 4) != 0 || (blockAccess.getBlock(x, y, z - 1) == this && (blockAccess.getBlockMetadata(x, y, z - 1) & 8) != 0) || (blockAccess.getBlock(x + 1, y, z - 1) == this && (blockAccess.getBlockMetadata(x + 1, y, z - 1) & 1) != 0); nRight = (meta & 1) != 0 || (blockAccess.getBlock(x, y, z + 1) == this && (blockAccess.getBlockMetadata(x, y, z + 1) & 8) != 0) || (blockAccess.getBlock(x + 1, y, z + 1) == this && (blockAccess.getBlockMetadata(x + 1, y, z + 1) & 4) != 0); break; case 5: nLeft = (meta & 1) != 0 || (blockAccess.getBlock(x, y, z + 1) == this && (blockAccess.getBlockMetadata(x, y, z + 1) & 2) != 0) || (blockAccess.getBlock(x - 1, y, z + 1) == this && (blockAccess.getBlockMetadata(x - 1, y, z + 1) & 4) != 0); nRight = (meta & 4) != 0 || (blockAccess.getBlock(x, y, z - 1) == this && (blockAccess.getBlockMetadata(x, y, z - 1) & 2) != 0) || (blockAccess.getBlock(x - 1, y, z - 1) == this && (blockAccess.getBlockMetadata(x - 1, y, z - 1) & 1) != 0); break; } if (nTop) { if (nLeft && nRight) return textures[4]; else if (nLeft) return textures[3]; else if (nRight) return textures[2]; else return textures[1]; } else { if (nLeft && nRight) return textures[7]; else if (nLeft) return textures[6]; else if (nRight) return textures[5]; else return textures[0]; } } @Override @SideOnly(Side.CLIENT) public void registerBlockIcons (IIconRegister register) { textures = new IIcon[8]; for (int i = 0; i < textures.length; i++) textures[i] = register.registerIcon(GardenTrees.MOD_ID + ":ivy" + i); } }