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