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    }