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 }