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 }