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.HashMap; 006 import java.util.Map; 007 008 public class TileEntity 009 { 010 /** 011 * A HashMap storing string names of classes mapping to the actual java.lang.Class type. 012 */ 013 private static Map nameToClassMap = new HashMap(); 014 015 /** 016 * A HashMap storing the classes and mapping to the string names (reverse of nameToClassMap). 017 */ 018 private static Map classToNameMap = new HashMap(); 019 020 /** The reference to the world. */ 021 public World worldObj; 022 023 /** The x coordinate of the tile entity. */ 024 public int xCoord; 025 026 /** The y coordinate of the tile entity. */ 027 public int yCoord; 028 029 /** The z coordinate of the tile entity. */ 030 public int zCoord; 031 protected boolean tileEntityInvalid; 032 public int blockMetadata = -1; 033 034 /** the Block type that this TileEntity is contained within */ 035 public Block blockType; 036 037 /** 038 * Adds a new two-way mapping between the class and its string name in both hashmaps. 039 */ 040 public static void addMapping(Class par0Class, String par1Str) 041 { 042 if (nameToClassMap.containsKey(par1Str)) 043 { 044 throw new IllegalArgumentException("Duplicate id: " + par1Str); 045 } 046 else 047 { 048 nameToClassMap.put(par1Str, par0Class); 049 classToNameMap.put(par0Class, par1Str); 050 } 051 } 052 053 /** 054 * Sets the worldObj for this tileEntity. 055 */ 056 public void setWorldObj(World par1World) 057 { 058 this.worldObj = par1World; 059 } 060 061 @SideOnly(Side.CLIENT) 062 063 /** 064 * Returns the worldObj for this tileEntity. 065 */ 066 public World getWorldObj() 067 { 068 return this.worldObj; 069 } 070 071 public boolean func_70309_m() 072 { 073 return this.worldObj != null; 074 } 075 076 /** 077 * Reads a tile entity from NBT. 078 */ 079 public void readFromNBT(NBTTagCompound par1NBTTagCompound) 080 { 081 this.xCoord = par1NBTTagCompound.getInteger("x"); 082 this.yCoord = par1NBTTagCompound.getInteger("y"); 083 this.zCoord = par1NBTTagCompound.getInteger("z"); 084 } 085 086 /** 087 * Writes a tile entity to NBT. 088 */ 089 public void writeToNBT(NBTTagCompound par1NBTTagCompound) 090 { 091 String var2 = (String)classToNameMap.get(this.getClass()); 092 093 if (var2 == null) 094 { 095 throw new RuntimeException(this.getClass() + " is missing a mapping! This is a bug!"); 096 } 097 else 098 { 099 par1NBTTagCompound.setString("id", var2); 100 par1NBTTagCompound.setInteger("x", this.xCoord); 101 par1NBTTagCompound.setInteger("y", this.yCoord); 102 par1NBTTagCompound.setInteger("z", this.zCoord); 103 } 104 } 105 106 /** 107 * Allows the entity to update its state. Overridden in most subclasses, e.g. the mob spawner uses this to count 108 * ticks and creates a new spawn inside its implementation. 109 */ 110 public void updateEntity() {} 111 112 /** 113 * Creates a new entity and loads its data from the specified NBT. 114 */ 115 public static TileEntity createAndLoadEntity(NBTTagCompound par0NBTTagCompound) 116 { 117 TileEntity var1 = null; 118 119 try 120 { 121 Class var2 = (Class)nameToClassMap.get(par0NBTTagCompound.getString("id")); 122 123 if (var2 != null) 124 { 125 var1 = (TileEntity)var2.newInstance(); 126 } 127 } 128 catch (Exception var3) 129 { 130 var3.printStackTrace(); 131 } 132 133 if (var1 != null) 134 { 135 var1.readFromNBT(par0NBTTagCompound); 136 } 137 else 138 { 139 System.out.println("Skipping TileEntity with id " + par0NBTTagCompound.getString("id")); 140 } 141 142 return var1; 143 } 144 145 /** 146 * Returns block data at the location of this entity (client-only). 147 */ 148 public int getBlockMetadata() 149 { 150 if (this.blockMetadata == -1) 151 { 152 this.blockMetadata = this.worldObj.getBlockMetadata(this.xCoord, this.yCoord, this.zCoord); 153 } 154 155 return this.blockMetadata; 156 } 157 158 /** 159 * Called when an the contents of an Inventory change, usually 160 */ 161 public void onInventoryChanged() 162 { 163 if (this.worldObj != null) 164 { 165 this.blockMetadata = this.worldObj.getBlockMetadata(this.xCoord, this.yCoord, this.zCoord); 166 this.worldObj.updateTileEntityChunkAndDoNothing(this.xCoord, this.yCoord, this.zCoord, this); 167 } 168 } 169 170 @SideOnly(Side.CLIENT) 171 172 /** 173 * Returns the square of the distance between this entity and the passed in coordinates. 174 */ 175 public double getDistanceFrom(double par1, double par3, double par5) 176 { 177 double var7 = (double)this.xCoord + 0.5D - par1; 178 double var9 = (double)this.yCoord + 0.5D - par3; 179 double var11 = (double)this.zCoord + 0.5D - par5; 180 return var7 * var7 + var9 * var9 + var11 * var11; 181 } 182 183 @SideOnly(Side.CLIENT) 184 185 /** 186 * Gets the block type at the location of this entity (client-only). 187 */ 188 public Block getBlockType() 189 { 190 if (this.blockType == null) 191 { 192 this.blockType = Block.blocksList[this.worldObj.getBlockId(this.xCoord, this.yCoord, this.zCoord)]; 193 } 194 195 return this.blockType; 196 } 197 198 /** 199 * Overriden in a sign to provide the text. 200 */ 201 public Packet getDescriptionPacket() 202 { 203 return null; 204 } 205 206 /** 207 * returns true if tile entity is invalid, false otherwise 208 */ 209 public boolean isInvalid() 210 { 211 return this.tileEntityInvalid; 212 } 213 214 /** 215 * invalidates a tile entity 216 */ 217 public void invalidate() 218 { 219 this.tileEntityInvalid = true; 220 } 221 222 /** 223 * validates a tile entity 224 */ 225 public void validate() 226 { 227 this.tileEntityInvalid = false; 228 } 229 230 /** 231 * Called when a client event is received with the event number and argument, see World.sendClientEvent 232 */ 233 public void receiveClientEvent(int par1, int par2) {} 234 235 /** 236 * Causes the TileEntity to reset all it's cached values for it's container block, blockID, metaData and in the case 237 * of chests, the adjcacent chest check 238 */ 239 public void updateContainingBlockInfo() 240 { 241 this.blockType = null; 242 this.blockMetadata = -1; 243 } 244 245 static 246 { 247 addMapping(TileEntityFurnace.class, "Furnace"); 248 addMapping(TileEntityChest.class, "Chest"); 249 addMapping(TileEntityEnderChest.class, "EnderChest"); 250 addMapping(TileEntityRecordPlayer.class, "RecordPlayer"); 251 addMapping(TileEntityDispenser.class, "Trap"); 252 addMapping(TileEntitySign.class, "Sign"); 253 addMapping(TileEntityMobSpawner.class, "MobSpawner"); 254 addMapping(TileEntityNote.class, "Music"); 255 addMapping(TileEntityPiston.class, "Piston"); 256 addMapping(TileEntityBrewingStand.class, "Cauldron"); 257 addMapping(TileEntityEnchantmentTable.class, "EnchantTable"); 258 addMapping(TileEntityEndPortal.class, "Airportal"); 259 } 260 261 /** 262 * Determines if this TileEntity requires update calls. 263 * @return True if you want updateEntity() to be called, false if not 264 */ 265 public boolean canUpdate() 266 { 267 return true; 268 } 269 270 /** 271 * Called when you receive a TileEntityData packet for the location this 272 * TileEntity is currently in. On the client, the NetworkManager will always 273 * be the remote server. On the server, it will be whomever is responsible for 274 * sending the packet. 275 * 276 * @param net The NetworkManager the packet originated from 277 * @param pkt The data packet 278 */ 279 public void onDataPacket(NetworkManager net, Packet132TileEntityData pkt) 280 { 281 } 282 283 /** 284 * Called when the chunk this TileEntity is on is Unloaded. 285 */ 286 public void onChunkUnload() 287 { 288 } 289 290 /** 291 * @return The maximum distance between the player and the TileEntity at which the TileEntitySpecialRenderer will be called 292 */ 293 public double getRenderDistance() 294 { 295 return 64; 296 } 297 }