    001package net.minecraft.tileentity;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import java.util.ArrayList;
    006import java.util.Iterator;
    007import java.util.List;
    008import net.minecraft.block.Block;
    009import net.minecraft.entity.Entity;
    010import net.minecraft.nbt.NBTTagCompound;
    011import net.minecraft.util.AxisAlignedBB;
    012import net.minecraft.util.Facing;
    013
    014public class TileEntityPiston extends TileEntity
    015{
    016    private int storedBlockID;
    017    private int storedMetadata;
    018
    019    /** the side the front of the piston is on */
    020    private int storedOrientation;
    021
    022    /** if this piston is extending or not */
    023    private boolean extending;
    024    private boolean shouldHeadBeRendered;
    025    private float progress;
    026
    027    /** the progress in (de)extending */
    028    private float lastProgress;
    029    private List pushedObjects = new ArrayList();
    030
    031    public TileEntityPiston() {}
    032
    033    public TileEntityPiston(int par1, int par2, int par3, boolean par4, boolean par5)
    034    {
    035        this.storedBlockID = par1;
    036        this.storedMetadata = par2;
    037        this.storedOrientation = par3;
    038        this.extending = par4;
    039        this.shouldHeadBeRendered = par5;
    040    }
    041
    042    public int getStoredBlockID()
    043    {
    044        return this.storedBlockID;
    045    }
    046
    047    /**
    048     * Returns block data at the location of this entity (client-only).
    049     */
    050    public int getBlockMetadata()
    051    {
    052        return this.storedMetadata;
    053    }
    054
    055    /**
    056     * Returns true if a piston is extending
    057     */
    058    public boolean isExtending()
    059    {
    060        return this.extending;
    061    }
    062
    063    /**
    064     * Returns the orientation of the piston as an int
    065     */
    066    public int getPistonOrientation()
    067    {
    068        return this.storedOrientation;
    069    }
    070
    071    @SideOnly(Side.CLIENT)
    072    public boolean shouldRenderHead()
    073    {
    074        return this.shouldHeadBeRendered;
    075    }
    076
    077    /**
    078     * Get interpolated progress value (between lastProgress and progress) given the fractional time between ticks as an
    079     * argument.
    080     */
    081    public float getProgress(float par1)
    082    {
    083        if (par1 > 1.0F)
    084        {
    085            par1 = 1.0F;
    086        }
    087
    088        return this.lastProgress + (this.progress - this.lastProgress) * par1;
    089    }
    090
    091    private void updatePushedObjects(float par1, float par2)
    092    {
    093        if (this.extending)
    094        {
    095            par1 = 1.0F - par1;
    096        }
    097        else
    098        {
    099            --par1;
    100        }
    101
    102        AxisAlignedBB var3 = Block.pistonMoving.getAxisAlignedBB(this.worldObj, this.xCoord, this.yCoord, this.zCoord, this.storedBlockID, par1, this.storedOrientation);
    103
    104        if (var3 != null)
    105        {
    106            List var4 = this.worldObj.getEntitiesWithinAABBExcludingEntity((Entity)null, var3);
    107
    108            if (!var4.isEmpty())
    109            {
    110                this.pushedObjects.addAll(var4);
    111                Iterator var5 = this.pushedObjects.iterator();
    112
    113                while (var5.hasNext())
    114                {
    115                    Entity var6 = (Entity)var5.next();
    116                    var6.moveEntity((double)(par2 * (float)Facing.offsetsXForSide[this.storedOrientation]), (double)(par2 * (float)Facing.offsetsYForSide[this.storedOrientation]), (double)(par2 * (float)Facing.offsetsZForSide[this.storedOrientation]));
    117                }
    118
    119                this.pushedObjects.clear();
    120            }
    121        }
    122    }
    123
    124    @SideOnly(Side.CLIENT)
    125    public float getOffsetX(float par1)
    126    {
    127        return this.extending ? (this.getProgress(par1) - 1.0F) * (float)Facing.offsetsXForSide[this.storedOrientation] : (1.0F - this.getProgress(par1)) * (float)Facing.offsetsXForSide[this.storedOrientation];
    128    }
    129
    130    @SideOnly(Side.CLIENT)
    131    public float getOffsetY(float par1)
    132    {
    133        return this.extending ? (this.getProgress(par1) - 1.0F) * (float)Facing.offsetsYForSide[this.storedOrientation] : (1.0F - this.getProgress(par1)) * (float)Facing.offsetsYForSide[this.storedOrientation];
    134    }
    135
    136    @SideOnly(Side.CLIENT)
    137    public float getOffsetZ(float par1)
    138    {
    139        return this.extending ? (this.getProgress(par1) - 1.0F) * (float)Facing.offsetsZForSide[this.storedOrientation] : (1.0F - this.getProgress(par1)) * (float)Facing.offsetsZForSide[this.storedOrientation];
    140    }
    141
    142    /**
    143     * removes a pistons tile entity (and if the piston is moving, stops it)
    144     */
    145    public void clearPistonTileEntity()
    146    {
    147        if (this.lastProgress < 1.0F && this.worldObj != null)
    148        {
    149            this.lastProgress = this.progress = 1.0F;
    150            this.worldObj.removeBlockTileEntity(this.xCoord, this.yCoord, this.zCoord);
    151            this.invalidate();
    152
    153            if (this.worldObj.getBlockId(this.xCoord, this.yCoord, this.zCoord) == Block.pistonMoving.blockID)
    154            {
    155                this.worldObj.setBlockAndMetadataWithNotify(this.xCoord, this.yCoord, this.zCoord, this.storedBlockID, this.storedMetadata);
    156            }
    157        }
    158    }
    159
    160    /**
    161     * Allows the entity to update its state. Overridden in most subclasses, e.g. the mob spawner uses this to count
    162     * ticks and creates a new spawn inside its implementation.
    163     */
    164    public void updateEntity()
    165    {
    166        this.lastProgress = this.progress;
    167
    168        if (this.lastProgress >= 1.0F)
    169        {
    170            this.updatePushedObjects(1.0F, 0.25F);
    171            this.worldObj.removeBlockTileEntity(this.xCoord, this.yCoord, this.zCoord);
    172            this.invalidate();
    173
    174            if (this.worldObj.getBlockId(this.xCoord, this.yCoord, this.zCoord) == Block.pistonMoving.blockID)
    175            {
    176                this.worldObj.setBlockAndMetadataWithNotify(this.xCoord, this.yCoord, this.zCoord, this.storedBlockID, this.storedMetadata);
    177            }
    178        }
    179        else
    180        {
    181            this.progress += 0.5F;
    182
    183            if (this.progress >= 1.0F)
    184            {
    185                this.progress = 1.0F;
    186            }
    187
    188            if (this.extending)
    189            {
    190                this.updatePushedObjects(this.progress, this.progress - this.lastProgress + 0.0625F);
    191            }
    192        }
    193    }
    194
    195    /**
    196     * Reads a tile entity from NBT.
    197     */
    198    public void readFromNBT(NBTTagCompound par1NBTTagCompound)
    199    {
    200        super.readFromNBT(par1NBTTagCompound);
    201        this.storedBlockID = par1NBTTagCompound.getInteger("blockId");
    202        this.storedMetadata = par1NBTTagCompound.getInteger("blockData");
    203        this.storedOrientation = par1NBTTagCompound.getInteger("facing");
    204        this.lastProgress = this.progress = par1NBTTagCompound.getFloat("progress");
    205        this.extending = par1NBTTagCompound.getBoolean("extending");
    206    }
    207
    208    /**
    209     * Writes a tile entity to NBT.
    210     */
    211    public void writeToNBT(NBTTagCompound par1NBTTagCompound)
    212    {
    213        super.writeToNBT(par1NBTTagCompound);
    214        par1NBTTagCompound.setInteger("blockId", this.storedBlockID);
    215        par1NBTTagCompound.setInteger("blockData", this.storedMetadata);
    216        par1NBTTagCompound.setInteger("facing", this.storedOrientation);
    217        par1NBTTagCompound.setFloat("progress", this.lastProgress);
    218        par1NBTTagCompound.setBoolean("extending", this.extending);
    219    }
    220}