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 @SideOnly(Side.CLIENT) 054 055 /** 056 * Returns the worldObj for this tileEntity. 057 */ 058 public World getWorldObj() 059 { 060 return this.worldObj; 061 } 062 063 /** 064 * Sets the worldObj for this tileEntity. 065 */ 066 public void setWorldObj(World par1World) 067 { 068 this.worldObj = par1World; 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 public double func_82115_m() 185 { 186 return 4096.0D; 187 } 188 189 /** 190 * Gets the block type at the location of this entity (client-only). 191 */ 192 public Block getBlockType() 193 { 194 if (this.blockType == null) 195 { 196 this.blockType = Block.blocksList[this.worldObj.getBlockId(this.xCoord, this.yCoord, this.zCoord)]; 197 } 198 199 return this.blockType; 200 } 201 202 /** 203 * Overriden in a sign to provide the text. 204 */ 205 public Packet getDescriptionPacket() 206 { 207 return null; 208 } 209 210 /** 211 * returns true if tile entity is invalid, false otherwise 212 */ 213 public boolean isInvalid() 214 { 215 return this.tileEntityInvalid; 216 } 217 218 /** 219 * invalidates a tile entity 220 */ 221 public void invalidate() 222 { 223 this.tileEntityInvalid = true; 224 } 225 226 /** 227 * validates a tile entity 228 */ 229 public void validate() 230 { 231 this.tileEntityInvalid = false; 232 } 233 234 /** 235 * Called when a client event is received with the event number and argument, see World.sendClientEvent 236 */ 237 public void receiveClientEvent(int par1, int par2) {} 238 239 /** 240 * Causes the TileEntity to reset all it's cached values for it's container block, blockID, metaData and in the case 241 * of chests, the adjcacent chest check 242 */ 243 public void updateContainingBlockInfo() 244 { 245 this.blockType = null; 246 this.blockMetadata = -1; 247 } 248 249 static 250 { 251 addMapping(TileEntityFurnace.class, "Furnace"); 252 addMapping(TileEntityChest.class, "Chest"); 253 addMapping(TileEntityEnderChest.class, "EnderChest"); 254 addMapping(TileEntityRecordPlayer.class, "RecordPlayer"); 255 addMapping(TileEntityDispenser.class, "Trap"); 256 addMapping(TileEntitySign.class, "Sign"); 257 addMapping(TileEntityMobSpawner.class, "MobSpawner"); 258 addMapping(TileEntityNote.class, "Music"); 259 addMapping(TileEntityPiston.class, "Piston"); 260 addMapping(TileEntityBrewingStand.class, "Cauldron"); 261 addMapping(TileEntityEnchantmentTable.class, "EnchantTable"); 262 addMapping(TileEntityEndPortal.class, "Airportal"); 263 addMapping(TileEntityCommandBlock.class, "Control"); 264 addMapping(TileEntityBeacon.class, "Beacon"); 265 addMapping(TileEntitySkull.class, "Skull"); 266 } 267 268 /** 269 * Determines if this TileEntity requires update calls. 270 * @return True if you want updateEntity() to be called, false if not 271 */ 272 public boolean canUpdate() 273 { 274 return true; 275 } 276 277 /** 278 * Called when you receive a TileEntityData packet for the location this 279 * TileEntity is currently in. On the client, the NetworkManager will always 280 * be the remote server. On the server, it will be whomever is responsible for 281 * sending the packet. 282 * 283 * @param net The NetworkManager the packet originated from 284 * @param pkt The data packet 285 */ 286 public void onDataPacket(INetworkManager net, Packet132TileEntityData pkt) 287 { 288 } 289 290 /** 291 * Called when the chunk this TileEntity is on is Unloaded. 292 */ 293 public void onChunkUnload() 294 { 295 } 296 }