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