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