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