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 }