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 }