package net.minecraft.block;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.util.List;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.server.management.PlayerManager;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityPiston;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.Facing;
import net.minecraft.util.IIcon;
import net.minecraft.util.MathHelper;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
public class BlockPistonBase extends Block
{
/** This piston is the sticky one? */
private final boolean isSticky;
/** Only visible when piston is extended */
@SideOnly(Side.CLIENT)
private IIcon innerTopIcon;
/** Bottom side texture */
@SideOnly(Side.CLIENT)
private IIcon bottomIcon;
/** Top icon of piston depends on (either sticky or normal) */
@SideOnly(Side.CLIENT)
private IIcon topIcon;
private static final String __OBFID = "CL_00000366";
public BlockPistonBase(boolean p_i45443_1_)
{
super(Material.piston);
this.isSticky = p_i45443_1_;
this.setStepSound(soundTypePiston);
this.setHardness(0.5F);
this.setCreativeTab(CreativeTabs.tabRedstone);
}
@SideOnly(Side.CLIENT)
public IIcon getPistonExtensionTexture()
{
return this.topIcon;
}
@SideOnly(Side.CLIENT)
public void func_150070_b(float p_150070_1_, float p_150070_2_, float p_150070_3_, float p_150070_4_, float p_150070_5_, float p_150070_6_)
{
this.setBlockBounds(p_150070_1_, p_150070_2_, p_150070_3_, p_150070_4_, p_150070_5_, p_150070_6_);
}
/**
* The type of render function that is called for this block
*/
public int getRenderType()
{
return 16;
}
/**
* Gets the block's texture. Args: side, meta
*/
@SideOnly(Side.CLIENT)
public IIcon getIcon(int side, int meta)
{
int k = getPistonOrientation(meta);
return k > 5 ? this.topIcon : (side == k ? (!isExtended(meta) && this.minX <= 0.0D && this.minY <= 0.0D && this.minZ <= 0.0D && this.maxX >= 1.0D && this.maxY >= 1.0D && this.maxZ >= 1.0D ? this.topIcon : this.innerTopIcon) : (side == Facing.oppositeSide[k] ? this.bottomIcon : this.blockIcon));
}
@SideOnly(Side.CLIENT)
public static IIcon getPistonBaseIcon(String p_150074_0_)
{
return p_150074_0_ == "piston_side" ? Blocks.piston.blockIcon : (p_150074_0_ == "piston_top_normal" ? Blocks.piston.topIcon : (p_150074_0_ == "piston_top_sticky" ? Blocks.sticky_piston.topIcon : (p_150074_0_ == "piston_inner" ? Blocks.piston.innerTopIcon : null)));
}
@SideOnly(Side.CLIENT)
public void registerIcons(IIconRegister reg)
{
this.blockIcon = reg.registerIcon("piston_side");
this.topIcon = reg.registerIcon(this.isSticky ? "piston_top_sticky" : "piston_top_normal");
this.innerTopIcon = reg.registerIcon("piston_inner");
this.bottomIcon = reg.registerIcon("piston_bottom");
}
public boolean isOpaqueCube()
{
return false;
}
/**
* Called upon block activation (right click on the block). Args : world, x, y, z, player, side, hitX, hitY, hitZ.
* Return : Swing hand (client), abort the block placement (server)
*/
public boolean onBlockActivated(World worldIn, int x, int y, int z, EntityPlayer player, int side, float subX, float subY, float subZ)
{
return false;
}
/**
* Called when the block is placed in the world.
*/
public void onBlockPlacedBy(World worldIn, int x, int y, int z, EntityLivingBase placer, ItemStack itemIn)
{
int l = determineOrientation(worldIn, x, y, z, placer);
worldIn.setBlockMetadataWithNotify(x, y, z, l, 2);
if (!worldIn.isRemote)
{
this.updatePistonState(worldIn, x, y, z);
}
}
public void onNeighborBlockChange(World worldIn, int x, int y, int z, Block neighbor)
{
if (!worldIn.isRemote)
{
this.updatePistonState(worldIn, x, y, z);
}
}
public void onBlockAdded(World worldIn, int x, int y, int z)
{
if (!worldIn.isRemote && worldIn.getTileEntity(x, y, z) == null)
{
this.updatePistonState(worldIn, x, y, z);
}
}
/**
* handles attempts to extend or retract the piston.
*/
private void updatePistonState(World p_150078_1_, int p_150078_2_, int p_150078_3_, int p_150078_4_)
{
int l = p_150078_1_.getBlockMetadata(p_150078_2_, p_150078_3_, p_150078_4_);
int i1 = getPistonOrientation(l);
if (i1 != 7)
{
boolean flag = this.isIndirectlyPowered(p_150078_1_, p_150078_2_, p_150078_3_, p_150078_4_, i1);
if (flag && !isExtended(l))
{
if (canExtend(p_150078_1_, p_150078_2_, p_150078_3_, p_150078_4_, i1))
{
p_150078_1_.addBlockEvent(p_150078_2_, p_150078_3_, p_150078_4_, this, 0, i1);
}
}
else if (!flag && isExtended(l))
{
p_150078_1_.setBlockMetadataWithNotify(p_150078_2_, p_150078_3_, p_150078_4_, i1, 2);
p_150078_1_.addBlockEvent(p_150078_2_, p_150078_3_, p_150078_4_, this, 1, i1);
}
}
}
private boolean isIndirectlyPowered(World p_150072_1_, int p_150072_2_, int p_150072_3_, int p_150072_4_, int p_150072_5_)
{
return p_150072_5_ != 0 && p_150072_1_.getIndirectPowerOutput(p_150072_2_, p_150072_3_ - 1, p_150072_4_, 0) ? true : (p_150072_5_ != 1 && p_150072_1_.getIndirectPowerOutput(p_150072_2_, p_150072_3_ + 1, p_150072_4_, 1) ? true : (p_150072_5_ != 2 && p_150072_1_.getIndirectPowerOutput(p_150072_2_, p_150072_3_, p_150072_4_ - 1, 2) ? true : (p_150072_5_ != 3 && p_150072_1_.getIndirectPowerOutput(p_150072_2_, p_150072_3_, p_150072_4_ + 1, 3) ? true : (p_150072_5_ != 5 && p_150072_1_.getIndirectPowerOutput(p_150072_2_ + 1, p_150072_3_, p_150072_4_, 5) ? true : (p_150072_5_ != 4 && p_150072_1_.getIndirectPowerOutput(p_150072_2_ - 1, p_150072_3_, p_150072_4_, 4) ? true : (p_150072_1_.getIndirectPowerOutput(p_150072_2_, p_150072_3_, p_150072_4_, 0) ? true : (p_150072_1_.getIndirectPowerOutput(p_150072_2_, p_150072_3_ + 2, p_150072_4_, 1) ? true : (p_150072_1_.getIndirectPowerOutput(p_150072_2_, p_150072_3_ + 1, p_150072_4_ - 1, 2) ? true : (p_150072_1_.getIndirectPowerOutput(p_150072_2_, p_150072_3_ + 1, p_150072_4_ + 1, 3) ? true : (p_150072_1_.getIndirectPowerOutput(p_150072_2_ - 1, p_150072_3_ + 1, p_150072_4_, 4) ? true : p_150072_1_.getIndirectPowerOutput(p_150072_2_ + 1, p_150072_3_ + 1, p_150072_4_, 5)))))))))));
}
public boolean onBlockEventReceived(World worldIn, int x, int y, int z, int eventId, int eventData)
{
if (!worldIn.isRemote)
{
boolean flag = this.isIndirectlyPowered(worldIn, x, y, z, eventData);
if (flag && eventId == 1)
{
worldIn.setBlockMetadataWithNotify(x, y, z, eventData | 8, 2);
return false;
}
if (!flag && eventId == 0)
{
return false;
}
}
if (eventId == 0)
{
if (!this.tryExtend(worldIn, x, y, z, eventData))
{
return false;
}
worldIn.setBlockMetadataWithNotify(x, y, z, eventData | 8, 2);
worldIn.playSoundEffect((double)x + 0.5D, (double)y + 0.5D, (double)z + 0.5D, "tile.piston.out", 0.5F, worldIn.rand.nextFloat() * 0.25F + 0.6F);
}
else if (eventId == 1)
{
TileEntity tileentity1 = worldIn.getTileEntity(x + Facing.offsetsXForSide[eventData], y + Facing.offsetsYForSide[eventData], z + Facing.offsetsZForSide[eventData]);
if (tileentity1 instanceof TileEntityPiston)
{
((TileEntityPiston)tileentity1).clearPistonTileEntity();
}
worldIn.setBlock(x, y, z, Blocks.piston_extension, eventData, 3);
worldIn.setTileEntity(x, y, z, BlockPistonMoving.getTileEntity(this, eventData, eventData, false, true));
if (this.isSticky)
{
int j1 = x + Facing.offsetsXForSide[eventData] * 2;
int k1 = y + Facing.offsetsYForSide[eventData] * 2;
int l1 = z + Facing.offsetsZForSide[eventData] * 2;
Block block = worldIn.getBlock(j1, k1, l1);
int i2 = worldIn.getBlockMetadata(j1, k1, l1);
boolean flag1 = false;
if (block == Blocks.piston_extension)
{
TileEntity tileentity = worldIn.getTileEntity(j1, k1, l1);
if (tileentity instanceof TileEntityPiston)
{
TileEntityPiston tileentitypiston = (TileEntityPiston)tileentity;
if (tileentitypiston.getPistonOrientation() == eventData && tileentitypiston.isExtending())
{
tileentitypiston.clearPistonTileEntity();
block = tileentitypiston.getStoredBlockID();
i2 = tileentitypiston.getBlockMetadata();
flag1 = true;
}
}
}
if (!flag1 && block.getMaterial() != Material.air && canPushBlock(block, worldIn, j1, k1, l1, false) && (block.getMobilityFlag() == 0 || block == Blocks.piston || block == Blocks.sticky_piston))
{
x += Facing.offsetsXForSide[eventData];
y += Facing.offsetsYForSide[eventData];
z += Facing.offsetsZForSide[eventData];
worldIn.setBlock(x, y, z, Blocks.piston_extension, i2, 3);
worldIn.setTileEntity(x, y, z, BlockPistonMoving.getTileEntity(block, i2, eventData, false, false));
worldIn.setBlockToAir(j1, k1, l1);
}
else if (!flag1)
{
worldIn.setBlockToAir(x + Facing.offsetsXForSide[eventData], y + Facing.offsetsYForSide[eventData], z + Facing.offsetsZForSide[eventData]);
}
}
else
{
worldIn.setBlockToAir(x + Facing.offsetsXForSide[eventData], y + Facing.offsetsYForSide[eventData], z + Facing.offsetsZForSide[eventData]);
}
worldIn.playSoundEffect((double)x + 0.5D, (double)y + 0.5D, (double)z + 0.5D, "tile.piston.in", 0.5F, worldIn.rand.nextFloat() * 0.15F + 0.6F);
}
return true;
}
public void setBlockBoundsBasedOnState(IBlockAccess worldIn, int x, int y, int z)
{
int l = worldIn.getBlockMetadata(x, y, z);
if (isExtended(l))
{
float f = 0.25F;
switch (getPistonOrientation(l))
{
case 0:
this.setBlockBounds(0.0F, 0.25F, 0.0F, 1.0F, 1.0F, 1.0F);
break;
case 1:
this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.75F, 1.0F);
break;
case 2:
this.setBlockBounds(0.0F, 0.0F, 0.25F, 1.0F, 1.0F, 1.0F);
break;
case 3:
this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.75F);
break;
case 4:
this.setBlockBounds(0.25F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
break;
case 5:
this.setBlockBounds(0.0F, 0.0F, 0.0F, 0.75F, 1.0F, 1.0F);
}
}
else
{
this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
}
}
/**
* Sets the block's bounds for rendering it as an item
*/
public void setBlockBoundsForItemRender()
{
this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
}
public void addCollisionBoxesToList(World worldIn, int x, int y, int z, AxisAlignedBB mask, List list, Entity collider)
{
this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
super.addCollisionBoxesToList(worldIn, x, y, z, mask, list, collider);
}
/**
* 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)
*/
public AxisAlignedBB getCollisionBoundingBoxFromPool(World worldIn, int x, int y, int z)
{
this.setBlockBoundsBasedOnState(worldIn, x, y, z);
return super.getCollisionBoundingBoxFromPool(worldIn, x, y, z);
}
public boolean renderAsNormalBlock()
{
return false;
}
public static int getPistonOrientation(int p_150076_0_)
{
return p_150076_0_ & 7;
}
/**
* Determine if the metadata is related to something powered.
*/
public static boolean isExtended(int p_150075_0_)
{
return (p_150075_0_ & 8) != 0;
}
/**
* gets the way this piston should face for that entity that placed it.
*/
public static int determineOrientation(World p_150071_0_, int p_150071_1_, int p_150071_2_, int p_150071_3_, EntityLivingBase p_150071_4_)
{
if (MathHelper.abs((float)p_150071_4_.posX - (float)p_150071_1_) < 2.0F && MathHelper.abs((float)p_150071_4_.posZ - (float)p_150071_3_) < 2.0F)
{
double d0 = p_150071_4_.posY + 1.82D - (double)p_150071_4_.yOffset;
if (d0 - (double)p_150071_2_ > 2.0D)
{
return 1;
}
if ((double)p_150071_2_ - d0 > 0.0D)
{
return 0;
}
}
int l = MathHelper.floor_double((double)(p_150071_4_.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
return l == 0 ? 2 : (l == 1 ? 5 : (l == 2 ? 3 : (l == 3 ? 4 : 0)));
}
/**
* returns true if the piston can push the specified block
*/
private static boolean canPushBlock(Block p_150080_0_, World p_150080_1_, int p_150080_2_, int p_150080_3_, int p_150080_4_, boolean p_150080_5_)
{
if (p_150080_0_ == Blocks.obsidian)
{
return false;
}
else
{
if (p_150080_0_ != Blocks.piston && p_150080_0_ != Blocks.sticky_piston)
{
if (p_150080_0_.getBlockHardness(p_150080_1_, p_150080_2_, p_150080_3_, p_150080_4_) == -1.0F)
{
return false;
}
if (p_150080_0_.getMobilityFlag() == 2)
{
return false;
}
if (p_150080_0_.getMobilityFlag() == 1)
{
if (!p_150080_5_)
{
return false;
}
return true;
}
}
else if (isExtended(p_150080_1_.getBlockMetadata(p_150080_2_, p_150080_3_, p_150080_4_)))
{
return false;
}
return !(p_150080_1_.getBlock(p_150080_2_, p_150080_3_, p_150080_4_).hasTileEntity(p_150080_1_.getBlockMetadata(p_150080_2_, p_150080_3_, p_150080_4_)));
}
}
/**
* checks to see if this piston could push the blocks in front of it.
*/
private static boolean canExtend(World p_150077_0_, int p_150077_1_, int p_150077_2_, int p_150077_3_, int p_150077_4_)
{
int i1 = p_150077_1_ + Facing.offsetsXForSide[p_150077_4_];
int j1 = p_150077_2_ + Facing.offsetsYForSide[p_150077_4_];
int k1 = p_150077_3_ + Facing.offsetsZForSide[p_150077_4_];
int l1 = 0;
while (true)
{
if (l1 < 13)
{
if (j1 <= 0 || j1 >= p_150077_0_.getHeight())
{
return false;
}
Block block = p_150077_0_.getBlock(i1, j1, k1);
if (!block.isAir(p_150077_0_, i1, j1, k1))
{
if (!canPushBlock(block, p_150077_0_, i1, j1, k1, true))
{
return false;
}
if (block.getMobilityFlag() != 1)
{
if (l1 == 12)
{
return false;
}
i1 += Facing.offsetsXForSide[p_150077_4_];
j1 += Facing.offsetsYForSide[p_150077_4_];
k1 += Facing.offsetsZForSide[p_150077_4_];
++l1;
continue;
}
}
}
return true;
}
}
/**
* attempts to extend the piston. returns false if impossible.
*/
private boolean tryExtend(World p_150079_1_, int p_150079_2_, int p_150079_3_, int p_150079_4_, int p_150079_5_)
{
int i1 = p_150079_2_ + Facing.offsetsXForSide[p_150079_5_];
int j1 = p_150079_3_ + Facing.offsetsYForSide[p_150079_5_];
int k1 = p_150079_4_ + Facing.offsetsZForSide[p_150079_5_];
int l1 = 0;
while (true)
{
if (l1 < 13)
{
if (j1 <= 0 || j1 >= p_150079_1_.getHeight())
{
return false;
}
Block block = p_150079_1_.getBlock(i1, j1, k1);
if (!block.isAir(p_150079_1_, i1, j1, k1))
{
if (!canPushBlock(block, p_150079_1_, i1, j1, k1, true))
{
return false;
}
if (block.getMobilityFlag() != 1)
{
if (l1 == 12)
{
return false;
}
i1 += Facing.offsetsXForSide[p_150079_5_];
j1 += Facing.offsetsYForSide[p_150079_5_];
k1 += Facing.offsetsZForSide[p_150079_5_];
++l1;
continue;
}
//With our change to how snowballs are dropped this needs to disallow to mimic vanilla behavior.
float chance = block instanceof BlockSnow ? -1.0f : 1.0f;
block.dropBlockAsItemWithChance(p_150079_1_, i1, j1, k1, p_150079_1_.getBlockMetadata(i1, j1, k1), chance, 0);
p_150079_1_.setBlockToAir(i1, j1, k1);
}
}
l1 = i1;
int k3 = j1;
int i2 = k1;
int j2 = 0;
Block[] ablock;
int k2;
int l2;
int i3;
for (ablock = new Block[13]; i1 != p_150079_2_ || j1 != p_150079_3_ || k1 != p_150079_4_; k1 = i3)
{
k2 = i1 - Facing.offsetsXForSide[p_150079_5_];
l2 = j1 - Facing.offsetsYForSide[p_150079_5_];
i3 = k1 - Facing.offsetsZForSide[p_150079_5_];
Block block1 = p_150079_1_.getBlock(k2, l2, i3);
int j3 = p_150079_1_.getBlockMetadata(k2, l2, i3);
if (block1 == this && k2 == p_150079_2_ && l2 == p_150079_3_ && i3 == p_150079_4_)
{
p_150079_1_.setBlock(i1, j1, k1, Blocks.piston_extension, p_150079_5_ | (this.isSticky ? 8 : 0), 4);
p_150079_1_.setTileEntity(i1, j1, k1, BlockPistonMoving.getTileEntity(Blocks.piston_head, p_150079_5_ | (this.isSticky ? 8 : 0), p_150079_5_, true, false));
}
else
{
p_150079_1_.setBlock(i1, j1, k1, Blocks.piston_extension, j3, 4);
p_150079_1_.setTileEntity(i1, j1, k1, BlockPistonMoving.getTileEntity(block1, j3, p_150079_5_, true, false));
}
ablock[j2++] = block1;
i1 = k2;
j1 = l2;
}
i1 = l1;
j1 = k3;
k1 = i2;
for (j2 = 0; i1 != p_150079_2_ || j1 != p_150079_3_ || k1 != p_150079_4_; k1 = i3)
{
k2 = i1 - Facing.offsetsXForSide[p_150079_5_];
l2 = j1 - Facing.offsetsYForSide[p_150079_5_];
i3 = k1 - Facing.offsetsZForSide[p_150079_5_];
p_150079_1_.notifyBlocksOfNeighborChange(k2, l2, i3, ablock[j2++]);
i1 = k2;
j1 = l2;
}
return true;
}
}
}