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 }