001    package net.minecraft.tileentity;
002    
003    import cpw.mods.fml.relauncher.Side;
004    import cpw.mods.fml.relauncher.SideOnly;
005    import java.util.ArrayList;
006    import java.util.Iterator;
007    import java.util.List;
008    import net.minecraft.block.Block;
009    import net.minecraft.entity.Entity;
010    import net.minecraft.nbt.NBTTagCompound;
011    import net.minecraft.util.AxisAlignedBB;
012    import net.minecraft.util.Facing;
013    
014    public 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    }