--- ../src-base/minecraft/net/minecraft/world/chunk/NibbleArray.java +++ ../src-work/minecraft/net/minecraft/world/chunk/NibbleArray.java @@ -1,47 +1,215 @@ package net.minecraft.world.chunk; +import java.util.Arrays; // Spigot + public class NibbleArray { - public final byte[] data; + public byte[] data; // Spigot - remove final // Cauldron - make public private final int depthBits; private final int depthBitsPlusFour; private static final String __OBFID = "CL_00000371"; - public NibbleArray(int p_i1992_1_, int p_i1992_2_) + // Spigot start + private byte trivialValue; + private byte trivialByte; + private int length; + private static final int LEN2K = 2048; // Universal length used right now - optimize around this + private static final byte[][] TrivLen2k; + + static { - this.data = new byte[p_i1992_1_ >> 1]; - this.depthBits = p_i1992_2_; - this.depthBitsPlusFour = p_i1992_2_ + 4; + TrivLen2k = new byte[16][]; + + for (int i = 0; i < 16; i++) + { + TrivLen2k[i] = new byte[LEN2K]; + Arrays.fill(TrivLen2k[i], (byte)(i | (i << 4))); + } } - public NibbleArray(byte[] p_i1993_1_, int p_i1993_2_) + // Try to convert array to trivial array + public void detectAndProcessTrivialArray() { - this.data = p_i1993_1_; - this.depthBits = p_i1993_2_; - this.depthBitsPlusFour = p_i1993_2_ + 4; + trivialValue = (byte)(data[0] & 0xF); + trivialByte = (byte)(trivialValue | (trivialValue << 4)); + + for (int i = 0; i < data.length; i++) + { + if (data[i] != trivialByte) + { + return; + } + } + + // All values matches, so array is trivial + this.length = data.length; + this.data = null; } - public int get(int p_76582_1_, int p_76582_2_, int p_76582_3_) + // Force array to non-trivial state + public void forceToNonTrivialArray() { - int l = p_76582_2_ << this.depthBitsPlusFour | p_76582_3_ << this.depthBits | p_76582_1_; + if (this.data == null) + { + this.data = new byte[this.length]; + + if (this.trivialByte != 0) + { + Arrays.fill(this.data, this.trivialByte); + } + } + } + + // Test if array is in trivial state + public boolean isTrivialArray() + { + return (this.data == null); + } + + // Get value of all elements (only valid if array is in trivial state) + public int getTrivialArrayValue() + { + return this.trivialValue; + } + + // Get logical length of byte array for nibble data (whether trivial or non-trivial) + public int getByteLength() + { + if (this.data == null) + { + return this.length; + } + else + { + return this.data.length; + } + } + + // Return byte encoding of array (whether trivial or non-trivial) - returns read-only array if trivial (do not modify!) + public byte[] getValueArray() + { + if (this.data != null) + { + return this.data; + } + else + { + byte[] rslt; + + if (this.length == LEN2K) // All current uses are 2k long, but be safe + { + rslt = TrivLen2k[this.trivialValue]; + } + else + { + rslt = new byte[this.length]; + + if (this.trivialByte != 0) + { + Arrays.fill(rslt, this.trivialByte); + } + } + + return rslt; + } + } + + // Copy byte representation of array to given offset in given byte array + public int copyToByteArray(byte[] dest, int off) + { + if (this.data == null) + { + Arrays.fill(dest, off, off + this.length, this.trivialByte); + return off + this.length; + } + else + { + System.arraycopy(this.data, 0, dest, off, this.data.length); + return off + this.data.length; + } + } + + // Resize array to given byte length + public void resizeArray(int len) + { + if (this.data == null) + { + this.length = len; + } + else if (this.data.length != len) + { + byte[] newa = new byte[len]; + System.arraycopy(this.data, 0, newa, 0, ((this.data.length > len) ? len : this.data.length)); + this.data = newa; + } + } + // Spigot end + + public NibbleArray(int par1, int par2) + { + // Spigot start + //this.a = new byte[i >> 1]; + this.data = null; // Start off as trivial value (all same zero value) + this.length = par1 >> 1; + this.trivialByte = this.trivialValue = 0; + // Spigot end + this.depthBits = par2; + this.depthBitsPlusFour = par2 + 4; + } + + public NibbleArray(byte[] par1ArrayOfByte, int par2) + { + this.data = par1ArrayOfByte; + this.depthBits = par2; + this.depthBitsPlusFour = par2 + 4; + detectAndProcessTrivialArray(); // Spigot + } + + public int get(int par1, int par2, int par3) + { + if (this.data == null) + { + return this.trivialValue; // Spigot + } + + int l = par2 << this.depthBitsPlusFour | par3 << this.depthBits | par1; int i1 = l >> 1; int j1 = l & 1; return j1 == 0 ? this.data[i1] & 15 : this.data[i1] >> 4 & 15; } - public void set(int p_76581_1_, int p_76581_2_, int p_76581_3_, int p_76581_4_) + public void set(int par1, int par2, int par3, int par4) { - int i1 = p_76581_2_ << this.depthBitsPlusFour | p_76581_3_ << this.depthBits | p_76581_1_; + // Spigot start + if (this.data == null) + { + if (par4 != this.trivialValue) // Not same as trivial value, array no longer trivial + { + this.data = new byte[this.length]; + + if (this.trivialByte != 0) + { + Arrays.fill(this.data, this.trivialByte); + } + } + else + { + return; + } + } + + // Spigot end + int i1 = par2 << this.depthBitsPlusFour | par3 << this.depthBits | par1; int j1 = i1 >> 1; int k1 = i1 & 1; if (k1 == 0) { - this.data[j1] = (byte)(this.data[j1] & 240 | p_76581_4_ & 15); + this.data[j1] = (byte)(this.data[j1] & 240 | par4 & 15); } else { - this.data[j1] = (byte)(this.data[j1] & 15 | (p_76581_4_ & 15) << 4); + this.data[j1] = (byte)(this.data[j1] & 15 | (par4 & 15) << 4); } } }