    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        public void func_85027_a(CrashReportCategory par1CrashReportCategory)
    262        {
    263            par1CrashReportCategory.addCrashSectionCallable("Name", new CallableTileEntityName(this));
    264            CrashReportCategory.func_85068_a(par1CrashReportCategory, this.xCoord, this.yCoord, this.zCoord, this.blockType.blockID, this.blockMetadata);
    265        }
    266
    267        static Map func_85028_t()
    268        {
    269            return classToNameMap;
    270        }
    271
    272        static
    273        {
    274            addMapping(TileEntityFurnace.class, "Furnace");
    275            addMapping(TileEntityChest.class, "Chest");
    276            addMapping(TileEntityEnderChest.class, "EnderChest");
    277            addMapping(TileEntityRecordPlayer.class, "RecordPlayer");
    278            addMapping(TileEntityDispenser.class, "Trap");
    279            addMapping(TileEntitySign.class, "Sign");
    280            addMapping(TileEntityMobSpawner.class, "MobSpawner");
    281            addMapping(TileEntityNote.class, "Music");
    282            addMapping(TileEntityPiston.class, "Piston");
    283            addMapping(TileEntityBrewingStand.class, "Cauldron");
    284            addMapping(TileEntityEnchantmentTable.class, "EnchantTable");
    285            addMapping(TileEntityEndPortal.class, "Airportal");
    286            addMapping(TileEntityCommandBlock.class, "Control");
    287            addMapping(TileEntityBeacon.class, "Beacon");
    288            addMapping(TileEntitySkull.class, "Skull");
    289        }
    290
    291        /**
    292         * Determines if this TileEntity requires update calls.
    293         * @return True if you want updateEntity() to be called, false if not
    294         */
    295        public boolean canUpdate()
    296        {
    297            return true;
    298        }
    299
    300        /**
    301         * Called when you receive a TileEntityData packet for the location this
    302         * TileEntity is currently in. On the client, the NetworkManager will always
    303         * be the remote server. On the server, it will be whomever is responsible for
    304         * sending the packet.
    305         *
    306         * @param net The NetworkManager the packet originated from
    307         * @param pkt The data packet
    308         */
    309        public void onDataPacket(INetworkManager net, Packet132TileEntityData pkt)
    310        {
    311        }
    312
    313        /**
    314         * Called when the chunk this TileEntity is on is Unloaded.
    315         */
    316        public void onChunkUnload()
    317        {
    318        }
    319    }