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 }