deduplicate minecraft compact array code/decode

This commit is contained in:
creeper123123321 2019-10-19 15:31:50 -03:00
parent 28b7f6febc
commit 005c91eb4d
5 changed files with 68 additions and 94 deletions

View File

@ -3,6 +3,7 @@ package us.myles.ViaVersion.api.type.types.version;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.util.CompactArrayUtil;
public class ChunkSectionType1_13 extends Type<ChunkSection> {
private static final int GLOBAL_PALETTE = 14;
@ -23,8 +24,6 @@ public class ChunkSectionType1_13 extends Type<ChunkSection> {
bitsPerBlock = GLOBAL_PALETTE;
}
long maxEntryValue = (1L << bitsPerBlock) - 1;
int paletteLength = bitsPerBlock == GLOBAL_PALETTE ? 0 : Type.VAR_INT.read(buffer);
// Read palette
chunkSection.clearPalette();
@ -43,25 +42,9 @@ public class ChunkSectionType1_13 extends Type<ChunkSection> {
for (int i = 0; i < blockData.length; i++) {
blockData[i] = buffer.readLong();
}
for (int i = 0; i < ChunkSection.SIZE; i++) {
int bitIndex = i * bitsPerBlock;
int startIndex = bitIndex / 64;
int endIndex = ((i + 1) * bitsPerBlock - 1) / 64;
int startBitSubIndex = bitIndex % 64;
int val;
if (startIndex == endIndex) {
val = (int) (blockData[startIndex] >>> startBitSubIndex & maxEntryValue);
} else {
int endBitSubIndex = 64 - startBitSubIndex;
val = (int) ((blockData[startIndex] >>> startBitSubIndex | blockData[endIndex] << endBitSubIndex) & maxEntryValue);
}
if (bitsPerBlock == GLOBAL_PALETTE) {
chunkSection.setFlatBlock(i, val);
} else {
chunkSection.setPaletteIndex(i, val);
}
}
CompactArrayUtil.iterateCompactArray(bitsPerBlock, ChunkSection.SIZE, blockData,
bitsPerBlock == GLOBAL_PALETTE ? (i, val) -> chunkSection.setBlock(i, val >> 4, val & 0xF)
: chunkSection::setPaletteIndex);
}
return chunkSection;
@ -78,7 +61,6 @@ public class ChunkSectionType1_13 extends Type<ChunkSection> {
bitsPerBlock = GLOBAL_PALETTE;
}
long maxEntryValue = (1L << bitsPerBlock) - 1;
buffer.writeByte(bitsPerBlock);
// Write pallet (or not)
@ -89,21 +71,9 @@ public class ChunkSectionType1_13 extends Type<ChunkSection> {
}
}
int length = (int) Math.ceil(ChunkSection.SIZE * bitsPerBlock / 64.0);
Type.VAR_INT.write(buffer, length);
long[] data = new long[length];
for (int index = 0; index < ChunkSection.SIZE; index++) {
int value = bitsPerBlock == GLOBAL_PALETTE ? chunkSection.getFlatBlock(index) : chunkSection.getPaletteIndex(index);
int bitIndex = index * bitsPerBlock;
int startIndex = bitIndex / 64;
int endIndex = ((index + 1) * bitsPerBlock - 1) / 64;
int startBitSubIndex = bitIndex % 64;
data[startIndex] = data[startIndex] & ~(maxEntryValue << startBitSubIndex) | ((long) value & maxEntryValue) << startBitSubIndex;
if (startIndex != endIndex) {
int endBitSubIndex = 64 - startBitSubIndex;
data[endIndex] = data[endIndex] >>> endBitSubIndex << endBitSubIndex | ((long) value & maxEntryValue) >> endBitSubIndex;
}
}
long[] data = CompactArrayUtil.createCompactArray(bitsPerBlock, ChunkSection.SIZE,
bitsPerBlock == GLOBAL_PALETTE ? chunkSection::getFlatBlock : chunkSection::getPaletteIndex);
Type.VAR_INT.write(buffer, data.length);
for (long l : data) {
buffer.writeLong(l);
}

View File

@ -3,6 +3,7 @@ package us.myles.ViaVersion.api.type.types.version;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.util.CompactArrayUtil;
public class ChunkSectionType1_9 extends Type<ChunkSection> {
private static final int GLOBAL_PALETTE = 13;
@ -18,7 +19,6 @@ public class ChunkSectionType1_9 extends Type<ChunkSection> {
// Reaad bits per block
int bitsPerBlock = buffer.readUnsignedByte();
int originalBitsPerBlock = bitsPerBlock;
long maxEntryValue = (1L << bitsPerBlock) - 1;
if (bitsPerBlock == 0) {
bitsPerBlock = GLOBAL_PALETTE;
@ -51,25 +51,9 @@ public class ChunkSectionType1_9 extends Type<ChunkSection> {
for (int i = 0; i < blockData.length; i++) {
blockData[i] = buffer.readLong();
}
for (int i = 0; i < ChunkSection.SIZE; i++) {
int bitIndex = i * bitsPerBlock;
int startIndex = bitIndex / 64;
int endIndex = ((i + 1) * bitsPerBlock - 1) / 64;
int startBitSubIndex = bitIndex % 64;
int val;
if (startIndex == endIndex) {
val = (int) (blockData[startIndex] >>> startBitSubIndex & maxEntryValue);
} else {
int endBitSubIndex = 64 - startBitSubIndex;
val = (int) ((blockData[startIndex] >>> startBitSubIndex | blockData[endIndex] << endBitSubIndex) & maxEntryValue);
}
if (bitsPerBlock == GLOBAL_PALETTE) {
chunkSection.setBlock(i, val >> 4, val & 0xF);
} else {
chunkSection.setPaletteIndex(i, val);
}
}
CompactArrayUtil.iterateCompactArray(bitsPerBlock, ChunkSection.SIZE, blockData,
bitsPerBlock == GLOBAL_PALETTE ? (i, val) -> chunkSection.setBlock(i, val >> 4, val & 0xF)
: chunkSection::setPaletteIndex);
}
return chunkSection;
@ -99,21 +83,9 @@ public class ChunkSectionType1_9 extends Type<ChunkSection> {
Type.VAR_INT.write(buffer, 0);
}
int length = (int) Math.ceil(ChunkSection.SIZE * bitsPerBlock / 64.0);
Type.VAR_INT.write(buffer, length);
long[] data = new long[length];
for (int index = 0; index < ChunkSection.SIZE; index++) {
int value = bitsPerBlock == GLOBAL_PALETTE ? chunkSection.getFlatBlock(index) : chunkSection.getPaletteIndex(index);
int bitIndex = index * bitsPerBlock;
int startIndex = bitIndex / 64;
int endIndex = ((index + 1) * bitsPerBlock - 1) / 64;
int startBitSubIndex = bitIndex % 64;
data[startIndex] = data[startIndex] & ~(maxEntryValue << startBitSubIndex) | ((long) value & maxEntryValue) << startBitSubIndex;
if (startIndex != endIndex) {
int endBitSubIndex = 64 - startBitSubIndex;
data[endIndex] = data[endIndex] >>> endBitSubIndex << endBitSubIndex | ((long) value & maxEntryValue) >> endBitSubIndex;
}
}
long[] data = CompactArrayUtil.createCompactArray(bitsPerBlock, ChunkSection.SIZE,
bitsPerBlock == GLOBAL_PALETTE ? chunkSection::getFlatBlock : chunkSection::getPaletteIndex);
Type.VAR_INT.write(buffer, data.length);
for (long l : data) {
buffer.writeLong(l);
}

View File

@ -4,7 +4,6 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.LongArrayTag;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.entities.Entity1_14Types;
import us.myles.ViaVersion.api.minecraft.BlockChangeRecord;
import us.myles.ViaVersion.api.minecraft.BlockFace;
@ -18,12 +17,13 @@ import us.myles.ViaVersion.api.remapper.ValueCreator;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.types.Chunk1_13Type;
import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.metadata.MetadataRewriter1_14To1_13_2;
import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.Protocol1_14To1_13_2;
import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data.MappingData;
import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.metadata.MetadataRewriter1_14To1_13_2;
import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.storage.EntityTracker1_14;
import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.types.Chunk1_14Type;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import us.myles.ViaVersion.util.CompactArrayUtil;
import java.util.Arrays;
@ -435,26 +435,7 @@ public class WorldPackets {
}
private static long[] encodeHeightMap(int[] heightMap) {
final int bitsPerBlock = 9;
long maxEntryValue = (1L << bitsPerBlock) - 1;
int length = (int) Math.ceil(heightMap.length * bitsPerBlock / 64.0);
long[] data = new long[length];
for (int index = 0; index < heightMap.length; index++) {
int value = heightMap[index];
int bitIndex = index * 9;
int startIndex = bitIndex / 64;
int endIndex = ((index + 1) * bitsPerBlock - 1) / 64;
int startBitSubIndex = bitIndex % 64;
data[startIndex] = data[startIndex] & ~(maxEntryValue << startBitSubIndex) | ((long) value & maxEntryValue) << startBitSubIndex;
if (startIndex != endIndex) {
int endBitSubIndex = 64 - startBitSubIndex;
data[endIndex] = data[endIndex] >>> endBitSubIndex << endBitSubIndex | ((long) value & maxEntryValue) >> endBitSubIndex;
}
}
return data;
return CompactArrayUtil.createCompactArray(9, heightMap.length, i -> heightMap[i]);
}
private static void setNonFullLight(Chunk chunk, ChunkSection section, int ySection, int x, int y, int z) {

View File

@ -0,0 +1,6 @@
package us.myles.ViaVersion.util;
@FunctionalInterface
public interface BiIntConsumer {
void consume(int i1, int i2);
}

View File

@ -0,0 +1,45 @@
package us.myles.ViaVersion.util;
import java.util.function.IntToLongFunction;
public class CompactArrayUtil {
private CompactArrayUtil() {
throw new AssertionError();
}
public static long[] createCompactArray(int bitsPerEntry, int entries, IntToLongFunction valueGetter) {
long maxEntryValue = (1L << bitsPerEntry) - 1;
long[] data = new long[(int) Math.ceil(entries * bitsPerEntry / 64.0)];
for (int index = 0; index < entries; index++) {
long value = valueGetter.applyAsLong(index);
int bitIndex = index * bitsPerEntry;
int startIndex = bitIndex / 64;
int endIndex = ((index + 1) * bitsPerEntry - 1) / 64;
int startBitSubIndex = bitIndex % 64;
data[startIndex] = data[startIndex] & ~(maxEntryValue << startBitSubIndex) | (value & maxEntryValue) << startBitSubIndex;
if (startIndex != endIndex) {
int endBitSubIndex = 64 - startBitSubIndex;
data[endIndex] = data[endIndex] >>> endBitSubIndex << endBitSubIndex | (value & maxEntryValue) >> endBitSubIndex;
}
}
return data;
}
public static void iterateCompactArray(int bitsPerEntry, int entries, long[] data, BiIntConsumer consumer) {
long maxEntryValue = (1L << bitsPerEntry) - 1;
for (int i = 0; i < entries; i++) {
int bitIndex = i * bitsPerEntry;
int startIndex = bitIndex / 64;
int endIndex = ((i + 1) * bitsPerEntry - 1) / 64;
int startBitSubIndex = bitIndex % 64;
int val;
if (startIndex == endIndex) {
val = (int) (data[startIndex] >>> startBitSubIndex & maxEntryValue);
} else {
int endBitSubIndex = 64 - startBitSubIndex;
val = (int) ((data[startIndex] >>> startBitSubIndex | data[endIndex] << endBitSubIndex) & maxEntryValue);
}
consumer.consume(i, val);
}
}
}