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 }