    001    package net.minecraft.world.chunk.storage;
    002
    003    import cpw.mods.fml.common.Side;
    004    import cpw.mods.fml.common.asm.SideOnly;
    005    import net.minecraft.block.Block;
    006    import net.minecraft.world.chunk.NibbleArray;
    007
    008    public class ExtendedBlockStorage
    009    {
    010        /**
    011         * Contains the bottom-most Y block represented by this ExtendedBlockStorage. Typically a multiple of 16.
    012         */
    013        private int yBase;
    014
    015        /**
    016         * A total count of the number of non-air blocks in this block storage's Chunk.
    017         */
    018        private int blockRefCount;
    019
    020        /**
    021         * Contains the number of blocks in this block storage's parent chunk that require random ticking. Used to cull the
    022         * Chunk from random tick updates for performance reasons.
    023         */
    024        private int tickRefCount;
    025
    026        /**
    027         * Contains the least significant 8 bits of each block ID belonging to this block storage's parent Chunk.
    028         */
    029        private byte[] blockLSBArray;
    030
    031        /**
    032         * Contains the most significant 4 bits of each block ID belonging to this block storage's parent Chunk.
    033         */
    034        private NibbleArray blockMSBArray;
    035
    036        /**
    037         * Stores the metadata associated with blocks in this ExtendedBlockStorage.
    038         */
    039        private NibbleArray blockMetadataArray;
    040
    041        /** The NibbleArray containing a block of Block-light data. */
    042        private NibbleArray blocklightArray;
    043
    044        /** The NibbleArray containing a block of Sky-light data. */
    045        private NibbleArray skylightArray;
    046
    047        public ExtendedBlockStorage(int par1)
    048        {
    049            this.yBase = par1;
    050            this.blockLSBArray = new byte[4096];
    051            this.blockMetadataArray = new NibbleArray(this.blockLSBArray.length, 4);
    052            this.skylightArray = new NibbleArray(this.blockLSBArray.length, 4);
    053            this.blocklightArray = new NibbleArray(this.blockLSBArray.length, 4);
    054        }
    055
    056        /**
    057         * Returns the extended block ID for a location in a chunk, merged from a byte array and a NibbleArray to form a
    058         * full 12-bit block ID.
    059         */
    060        public int getExtBlockID(int par1, int par2, int par3)
    061        {
    062            int var4 = this.blockLSBArray[par2 << 8 | par3 << 4 | par1] & 255;
    063            return this.blockMSBArray != null ? this.blockMSBArray.get(par1, par2, par3) << 8 | var4 : var4;
    064        }
    065
    066        /**
    067         * Sets the extended block ID for a location in a chunk, splitting bits 11..8 into a NibbleArray and bits 7..0 into
    068         * a byte array. Also performs reference counting to determine whether or not to broadly cull this Chunk from the
    069         * random-update tick list.
    070         */
    071        public void setExtBlockID(int par1, int par2, int par3, int par4)
    072        {
    073            int var5 = this.blockLSBArray[par2 << 8 | par3 << 4 | par1] & 255;
    074
    075            if (this.blockMSBArray != null)
    076            {
    077                var5 |= this.blockMSBArray.get(par1, par2, par3) << 8;
    078            }
    079
    080            if (var5 == 0 && par4 != 0)
    081            {
    082                ++this.blockRefCount;
    083
    084                if (Block.blocksList[par4] != null && Block.blocksList[par4].getTickRandomly())
    085                {
    086                    ++this.tickRefCount;
    087                }
    088            }
    089            else if (var5 != 0 && par4 == 0)
    090            {
    091                --this.blockRefCount;
    092
    093                if (Block.blocksList[var5] != null && Block.blocksList[var5].getTickRandomly())
    094                {
    095                    --this.tickRefCount;
    096                }
    097            }
    098            else if (Block.blocksList[var5] != null && Block.blocksList[var5].getTickRandomly() && (Block.blocksList[par4] == null || !Block.blocksList[par4].getTickRandomly()))
    099            {
    100                --this.tickRefCount;
    101            }
    102            else if ((Block.blocksList[var5] == null || !Block.blocksList[var5].getTickRandomly()) && Block.blocksList[par4] != null && Block.blocksList[par4].getTickRandomly())
    103            {
    104                ++this.tickRefCount;
    105            }
    106
    107            this.blockLSBArray[par2 << 8 | par3 << 4 | par1] = (byte)(par4 & 255);
    108
    109            if (par4 > 255)
    110            {
    111                if (this.blockMSBArray == null)
    112                {
    113                    this.blockMSBArray = new NibbleArray(this.blockLSBArray.length, 4);
    114                }
    115
    116                this.blockMSBArray.set(par1, par2, par3, (par4 & 3840) >> 8);
    117            }
    118            else if (this.blockMSBArray != null)
    119            {
    120                this.blockMSBArray.set(par1, par2, par3, 0);
    121            }
    122        }
    123
    124        /**
    125         * Returns the metadata associated with the block at the given coordinates in this ExtendedBlockStorage.
    126         */
    127        public int getExtBlockMetadata(int par1, int par2, int par3)
    128        {
    129            return this.blockMetadataArray.get(par1, par2, par3);
    130        }
    131
    132        /**
    133         * Sets the metadata of the Block at the given coordinates in this ExtendedBlockStorage to the given metadata.
    134         */
    135        public void setExtBlockMetadata(int par1, int par2, int par3, int par4)
    136        {
    137            this.blockMetadataArray.set(par1, par2, par3, par4);
    138        }
    139
    140        /**
    141         * Returns whether or not this block storage's Chunk is fully empty, based on its internal reference count.
    142         */
    143        public boolean isEmpty()
    144        {
    145            return this.blockRefCount == 0;
    146        }
    147
    148        /**
    149         * Returns whether or not this block storage's Chunk will require random ticking, used to avoid looping through
    150         * random block ticks when there are no blocks that would randomly tick.
    151         */
    152        public boolean getNeedsRandomTick()
    153        {
    154            return this.tickRefCount > 0;
    155        }
    156
    157        /**
    158         * Returns the Y location of this ExtendedBlockStorage.
    159         */
    160        public int getYLocation()
    161        {
    162            return this.yBase;
    163        }
    164
    165        /**
    166         * Sets the saved Sky-light value in the extended block storage structure.
    167         */
    168        public void setExtSkylightValue(int par1, int par2, int par3, int par4)
    169        {
    170            this.skylightArray.set(par1, par2, par3, par4);
    171        }
    172
    173        /**
    174         * Gets the saved Sky-light value in the extended block storage structure.
    175         */
    176        public int getExtSkylightValue(int par1, int par2, int par3)
    177        {
    178            return this.skylightArray.get(par1, par2, par3);
    179        }
    180
    181        /**
    182         * Sets the saved Block-light value in the extended block storage structure.
    183         */
    184        public void setExtBlocklightValue(int par1, int par2, int par3, int par4)
    185        {
    186            this.blocklightArray.set(par1, par2, par3, par4);
    187        }
    188
    189        /**
    190         * Gets the saved Block-light value in the extended block storage structure.
    191         */
    192        public int getExtBlocklightValue(int par1, int par2, int par3)
    193        {
    194            return this.blocklightArray.get(par1, par2, par3);
    195        }
    196
    197        public void removeInvalidBlocks()
    198        {
    199            this.blockRefCount = 0;
    200            this.tickRefCount = 0;
    201
    202            for (int var1 = 0; var1 < 16; ++var1)
    203            {
    204                for (int var2 = 0; var2 < 16; ++var2)
    205                {
    206                    for (int var3 = 0; var3 < 16; ++var3)
    207                    {
    208                        int var4 = this.getExtBlockID(var1, var2, var3);
    209
    210                        if (var4 > 0)
    211                        {
    212                            if (Block.blocksList[var4] == null)
    213                            {
    214                                this.blockLSBArray[var2 << 8 | var3 << 4 | var1] = 0;
    215
    216                                if (this.blockMSBArray != null)
    217                                {
    218                                    this.blockMSBArray.set(var1, var2, var3, 0);
    219                                }
    220                            }
    221                            else
    222                            {
    223                                ++this.blockRefCount;
    224
    225                                if (Block.blocksList[var4].getTickRandomly())
    226                                {
    227                                    ++this.tickRefCount;
    228                                }
    229                            }
    230                        }
    231                    }
    232                }
    233            }
    234        }
    235
    236        public byte[] getBlockLSBArray()
    237        {
    238            return this.blockLSBArray;
    239        }
    240
    241        @SideOnly(Side.CLIENT)
    242        public void clearMSBArray()
    243        {
    244            this.blockMSBArray = null;
    245        }
    246
    247        /**
    248         * Returns the block ID MSB (bits 11..8) array for this storage array's Chunk.
    249         */
    250        public NibbleArray getBlockMSBArray()
    251        {
    252            return this.blockMSBArray;
    253        }
    254
    255        public NibbleArray getMetadataArray()
    256        {
    257            return this.blockMetadataArray;
    258        }
    259
    260        /**
    261         * Returns the NibbleArray instance containing Block-light data.
    262         */
    263        public NibbleArray getBlocklightArray()
    264        {
    265            return this.blocklightArray;
    266        }
    267
    268        /**
    269         * Returns the NibbleArray instance containing Sky-light data.
    270         */
    271        public NibbleArray getSkylightArray()
    272        {
    273            return this.skylightArray;
    274        }
    275
    276        /**
    277         * Sets the array of block ID least significant bits for this ExtendedBlockStorage.
    278         */
    279        public void setBlockLSBArray(byte[] par1ArrayOfByte)
    280        {
    281            this.blockLSBArray = par1ArrayOfByte;
    282        }
    283
    284        /**
    285         * Sets the array of blockID most significant bits (blockMSBArray) for this ExtendedBlockStorage.
    286         */
    287        public void setBlockMSBArray(NibbleArray par1NibbleArray)
    288        {
    289            this.blockMSBArray = par1NibbleArray;
    290        }
    291
    292        /**
    293         * Sets the NibbleArray of block metadata (blockMetadataArray) for this ExtendedBlockStorage.
    294         */
    295        public void setBlockMetadataArray(NibbleArray par1NibbleArray)
    296        {
    297            this.blockMetadataArray = par1NibbleArray;
    298        }
    299
    300        /**
    301         * Sets the NibbleArray instance used for Block-light values in this particular storage block.
    302         */
    303        public void setBlocklightArray(NibbleArray par1NibbleArray)
    304        {
    305            this.blocklightArray = par1NibbleArray;
    306        }
    307
    308        /**
    309         * Sets the NibbleArray instance used for Sky-light values in this particular storage block.
    310         */
    311        public void setSkylightArray(NibbleArray par1NibbleArray)
    312        {
    313            this.skylightArray = par1NibbleArray;
    314        }
    315
    316        @SideOnly(Side.CLIENT)
    317
    318        /**
    319         * Called by a Chunk to initialize the MSB array if getBlockMSBArray returns null. Returns the newly-created
    320         * NibbleArray instance.
    321         */
    322        public NibbleArray createBlockMSBArray()
    323        {
    324            this.blockMSBArray = new NibbleArray(this.blockLSBArray.length, 4);
    325            return this.blockMSBArray;
    326        }
    327    }