    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    }