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 }