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 }