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