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 axisalignedbb = Block.pistonMoving.getAxisAlignedBB(this.worldObj, this.xCoord, this.yCoord, this.zCoord, this.storedBlockID, par1, this.storedOrientation); 103 104 if (axisalignedbb != null) 105 { 106 List list = this.worldObj.getEntitiesWithinAABBExcludingEntity((Entity)null, axisalignedbb); 107 108 if (!list.isEmpty()) 109 { 110 this.pushedObjects.addAll(list); 111 Iterator iterator = this.pushedObjects.iterator(); 112 113 while (iterator.hasNext()) 114 { 115 Entity entity = (Entity)iterator.next(); 116 entity.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.setBlock(this.xCoord, this.yCoord, this.zCoord, this.storedBlockID, this.storedMetadata, 3); 156 this.worldObj.notifyBlockOfNeighborChange(this.xCoord, this.yCoord, this.zCoord, this.storedBlockID); 157 } 158 } 159 } 160 161 /** 162 * Allows the entity to update its state. Overridden in most subclasses, e.g. the mob spawner uses this to count 163 * ticks and creates a new spawn inside its implementation. 164 */ 165 public void updateEntity() 166 { 167 this.lastProgress = this.progress; 168 169 if (this.lastProgress >= 1.0F) 170 { 171 this.updatePushedObjects(1.0F, 0.25F); 172 this.worldObj.removeBlockTileEntity(this.xCoord, this.yCoord, this.zCoord); 173 this.invalidate(); 174 175 if (this.worldObj.getBlockId(this.xCoord, this.yCoord, this.zCoord) == Block.pistonMoving.blockID) 176 { 177 this.worldObj.setBlock(this.xCoord, this.yCoord, this.zCoord, this.storedBlockID, this.storedMetadata, 3); 178 this.worldObj.notifyBlockOfNeighborChange(this.xCoord, this.yCoord, this.zCoord, this.storedBlockID); 179 } 180 } 181 else 182 { 183 this.progress += 0.5F; 184 185 if (this.progress >= 1.0F) 186 { 187 this.progress = 1.0F; 188 } 189 190 if (this.extending) 191 { 192 this.updatePushedObjects(this.progress, this.progress - this.lastProgress + 0.0625F); 193 } 194 } 195 } 196 197 /** 198 * Reads a tile entity from NBT. 199 */ 200 public void readFromNBT(NBTTagCompound par1NBTTagCompound) 201 { 202 super.readFromNBT(par1NBTTagCompound); 203 this.storedBlockID = par1NBTTagCompound.getInteger("blockId"); 204 this.storedMetadata = par1NBTTagCompound.getInteger("blockData"); 205 this.storedOrientation = par1NBTTagCompound.getInteger("facing"); 206 this.lastProgress = this.progress = par1NBTTagCompound.getFloat("progress"); 207 this.extending = par1NBTTagCompound.getBoolean("extending"); 208 } 209 210 /** 211 * Writes a tile entity to NBT. 212 */ 213 public void writeToNBT(NBTTagCompound par1NBTTagCompound) 214 { 215 super.writeToNBT(par1NBTTagCompound); 216 par1NBTTagCompound.setInteger("blockId", this.storedBlockID); 217 par1NBTTagCompound.setInteger("blockData", this.storedMetadata); 218 par1NBTTagCompound.setInteger("facing", this.storedOrientation); 219 par1NBTTagCompound.setFloat("progress", this.lastProgress); 220 par1NBTTagCompound.setBoolean("extending", this.extending); 221 } 222}