package com.carpentersblocks.block;
import java.util.Arrays;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import com.carpentersblocks.data.ISided;
import com.carpentersblocks.tileentity.TEBase;
public class BlockSided extends BlockCoverable {
private ISided data = null;
public BlockSided(Material material, ISided data)
{
super(material);
this.data = data;
}
/**
* Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
* cleared to be reused)
*/
@Override
public AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int x, int y, int z)
{
setBlockBoundsBasedOnState(world, x, y, z);
return super.getCollisionBoundingBoxFromPool(world, x, y, z);
}
@Override
/**
* Checks to see if you can place this block can be placed on that side of a block: BlockLever overrides
*/
public boolean canPlaceBlockOnSide(World world, int x, int y, int z, int side)
{
if (canAttachToSide(side)) {
ForgeDirection dir = ForgeDirection.getOrientation(side);
return world.getBlock(x - dir.offsetX, y - dir.offsetY, z - dir.offsetZ).isSideSolid(world, x - dir.offsetX, y - dir.offsetY, z - dir.offsetZ, dir);
} else {
return false;
}
}
@Override
/**
* Called when a block is placed using its ItemBlock. Args: World, X, Y, Z, side, hitX, hitY, hitZ, block metadata
*/
public int onBlockPlaced(World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ, int metadata)
{
return side;
}
@Override
/**
* Called when the block is placed in the world.
*/
public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase entityLiving, ItemStack itemStack)
{
super.onBlockPlacedBy(world, x, y, z, entityLiving, itemStack);
if (!ignoreSidePlacement()) {
TEBase TE = getTileEntity(world, x, y, z);
if (TE != null) {
ForgeDirection dir = getPlacementDirection(world, x, y, z, entityLiving);
data.setDirection(TE, dir);
}
}
}
/**
* Gets placement direction when first placed in world.
*
* @param world the {@link World}
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coordinate
* @return the {@link ForgeDirection}
*/
protected ForgeDirection getPlacementDirection(World world, int x, int y, int z, EntityLivingBase entityLiving)
{
int meta = world.getBlockMetadata(x, y, z);
return ForgeDirection.getOrientation(meta);
}
/**
* Whether side block placed against influences initial direction of block.
*
* @return <code>true</code> if initial placement direction ignored
*/
protected boolean ignoreSidePlacement()
{
return false;
}
/**
* Called after a block is placed
*/
@Override
public void onPostBlockPlaced(World world, int x, int y, int z, int metadata)
{
/*
* Part of world.setBlock() involves updating neighbors. Since we
* prevent this in ItemBlockSided, we'll invoke it here.
*/
world.notifyBlocksOfNeighborChange(x, y, z, this);
}
@Override
/**
* How many world ticks before ticking
*/
public int tickRate(World world)
{
return 20;
}
@Override
/**
* Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
* their own) Args: x, y, z, neighbor blockID
*/
public void onNeighborBlockChange(World world, int x, int y, int z, Block block)
{
super.onNeighborBlockChange(world, x, y, z, block);
if (!world.isRemote) {
TEBase TE = getTileEntity(world, x, y, z);
if (TE != null && !canPlaceBlockOnSide(world, x, y, z, data.getDirection(TE).ordinal()) && !canFloat()) {
destroyBlock(world, x, y, z, true);
}
}
}
/**
* Notifies relevant blocks of a change in power output.
*
* @param world
* @param x
* @param y
* @param z
* @return nothing
*/
public void notifyBlocksOfPowerChange(World world, int x, int y, int z)
{
/* Notify strong power change. */
world.notifyBlockChange(x, y, z, this);
/* Notify weak power change. */
if (canProvidePower()) {
TEBase TE = getTileEntity(world, x, y, z);
if (TE != null) {
ForgeDirection dir = data.getDirection(TE);
world.notifyBlocksOfNeighborChange(x - dir.offsetX, y - dir.offsetY, z - dir.offsetZ, this);
} else {
/* When block is destroyed, notify neighbors in all directions. */
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
world.notifyBlocksOfNeighborChange(x - dir.offsetX, y - dir.offsetY, z - dir.offsetZ, this);
}
}
}
}
@Override
/**
* Returns true if the block is emitting indirect/weak redstone power on the specified side. If isBlockNormalCube
* returns true, standard redstone propagation rules will apply instead and this will not be called. Args: World, X,
* Y, Z, side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block.
*/
public int isProvidingWeakPower(IBlockAccess blockAccess, int x, int y, int z, int side)
{
int power = super.isProvidingWeakPower(blockAccess, x, y, z, side);
if (canProvidePower()) {
TEBase TE = getTileEntity(blockAccess, x, y, z);
if (TE != null) {
int tempPower = getPowerOutput(TE);
if (tempPower > power) {
power = tempPower;
}
}
}
return power;
}
@Override
/**
* Returns true if the block is emitting direct/strong redstone power on the specified side. Args: World, X, Y, Z,
* side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block.
*/
public int isProvidingStrongPower(IBlockAccess blockAccess, int x, int y, int z, int side)
{
int power = super.isProvidingStrongPower(blockAccess, x, y, z, side);
if (canProvidePower()) {
TEBase TE = getTileEntity(blockAccess, x, y, z);
if (TE != null) {
if (side == data.getDirection(TE).ordinal()) {
int tempPower = getPowerOutput(TE);
if (tempPower > power) {
power = tempPower;
}
}
}
}
return power;
}
@Override
/**
* Ejects contained items into the world, and notifies neighbors of an update, as appropriate
*/
public void breakBlock(World world, int x, int y, int z, Block block, int metadata)
{
if (canProvidePower()) {
notifyBlocksOfPowerChange(world, x, y, z);
}
super.breakBlock(world, x, y, z, block, metadata);
}
/**
* Gets block-specific power level from 0 to 15.
*
* @param TE the {@link TEBase}
* @return the power output
*/
public int getPowerOutput(TEBase TE)
{
return 0;
}
/**
* Whether block can be attached to specified side of another block.
*
* @param side the side
* @return whether side is supported
*/
public boolean canAttachToSide(int side)
{
return true;
}
/**
* Whether block requires an adjacent block with solid side for support.
*
* @return whether block can float freely
*/
public boolean canFloat()
{
return false;
}
@Override
public boolean rotateBlock(World world, int x, int y, int z, ForgeDirection axis)
{
if (Arrays.asList(getRotationAxes()).contains(axis)) {
TEBase TE = getTileEntity(world, x, y, z);
if (TE != null) {
ForgeDirection dir = data.getDirection(TE);
return data.setDirection(TE, dir.getRotation(axis));
}
}
return false;
}
/**
* Get supported axes of rotation.
*
* @return an array of {@link ForgeDirection} enums.
*/
protected ForgeDirection[] getRotationAxes()
{
return new ForgeDirection[] { ForgeDirection.DOWN, ForgeDirection.UP };
}
}