Archived
0

обновление алгоритма для крупно-палитрых чанков

если в палитре больше 15 блоков, то используется больше битов на один блок
This commit is contained in:
2018-11-11 02:45:41 +03:00
parent be2b2e6ef8
commit ca7968a0d5

View File

@@ -9,7 +9,6 @@ import mc.core.network.NetOutputStream;
import mc.core.network.SCPacket;
import mc.core.network.proto_1_12_2.ByteArrayOutputNetStream;
import mc.core.utils.NibbleArray;
import mc.core.world.Biome;
import mc.core.world.block.Block;
import mc.core.world.block.BlockLocation;
import mc.core.world.block.BlockType;
@@ -180,71 +179,116 @@ public class ChunkDataPacket implements SCPacket {
/* writeNBT */
}
@Override
public String toString() {
return "ChunkDataPacket{" +
"x=" + x +
", z=" + z +
", chunk=" + chunk +
'}';
}
private class PalettedChunkSection {
private TIntList palette = new TIntArrayList();
private int dataItems = 0;
private ByteArrayOutputNetStream dataArray = new ByteArrayOutputNetStream();
private byte[] blocks = new byte[4096];
private NibbleArray blockLight = new NibbleArray();
private NibbleArray skyLight = new NibbleArray();
private int idxHalfLong = 0;
private int coordsToIndex(BlockLocation location) {
return coordsToIndex(location.getX(), location.getY(), location.getZ());
}
private long dataValueCompacted = 0;
private int coordsToIndex(int x, int y, int z) {
return y << 8 | z << 4 | x;
}
private int serializeBlockState(BlockType blockType) {
return (blockType.getId() << 4) | blockType.getMeta();
}
int addBlockType(BlockType blockType) {
byte addBlockType(BlockType blockType) {
int blockState = serializeBlockState(blockType);
int idx;
if (!palette.contains(blockState)) {
int idx = palette.indexOf(blockState);
if (idx == -1) {
palette.add(blockState);
idx = palette.size()-1;
} else {
idx = palette.indexOf(blockState);
}
return idx;
return (byte) idx;
}
void addBlock(Block block) {
int idx = addBlockType(block.getBlockType());
//TODO нужно убрать этот позор
// block data
if (idxHalfLong == 0) {
dataValueCompacted = idx;
idxHalfLong++;
} else if (idxHalfLong > 0 && idxHalfLong < 15) {
dataValueCompacted = (dataValueCompacted << 4) | idx;
idxHalfLong++;
} else {
dataValueCompacted = (dataValueCompacted << 4) | idx;
dataArray.writeLong(dataValueCompacted);
idxHalfLong = 0;
dataItems++;
}
// block light data
blockLight.set(block.getLocation().toLocal(), block.getLight());
void addBlockLight(int x, int y, int z, int value) {
blockLight.set(x, y, z, value);
}
void addSkyLight(int x, int y, int z, int value) {
// sky light data
skyLight.set(x, y, z, value);
}
void addBlock(Block block) {
BlockLocation location = block.getLocation().toLocal();
blocks[coordsToIndex(location)] = addBlockType(block.getBlockType());
addBlockLight(location.getX(), location.getY(), location.getZ(), block.getLight());
}
void writeToNetStream(final NetOutputStream netOutputStream) {
int bitsPerBlock = 4;
if (palette.size() > 15) {
if (palette.size() <= 31)
bitsPerBlock = 5;
else if (palette.size() > 31 && palette.size() <= 63)
bitsPerBlock = 6;
else if (palette.size() > 63 && palette.size() <= 127)
bitsPerBlock = 7;
else if (palette.size() > 127 && palette.size() <= 255)
bitsPerBlock = 8;
}
// <Palette>
netOutputStream.writeUnsignedByte(4); // Bits Per Block
netOutputStream.writeUnsignedByte(bitsPerBlock); // Bits Per Block
netOutputStream.writeVarInt(palette.size()); // Size of palette
palette.forEach(value -> { netOutputStream.writeVarInt(value); return true; }); // Palette
// </Palette>
// <Data Array>
netOutputStream.writeVarInt(dataItems); // Size of Data Array
netOutputStream.writeBytes(dataArray.toByteArray()); // Data Array
final int dataLength = (4096/*16*16*16*/ * bitsPerBlock) / 64;
netOutputStream.writeVarInt(dataLength); // Size of Data Array
// <Array>
long value = 0;
int lastPos = 0;
boolean fairy = false;
long fairyValue = 0;
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
final int blockNumber = (((y << 4) + z) << 4) + x;
final int startLong = ( blockNumber * bitsPerBlock ) / 64;
final int startOffset = ( blockNumber * bitsPerBlock ) % 64;
final int endLong = ((blockNumber + 1) * bitsPerBlock - 1) / 64;
final long idxBlockInPalette = blocks[coordsToIndex(x, y, z)];
if (startLong != lastPos) {
netOutputStream.writeLong(value);
lastPos = startLong;
if (fairy) {
value = fairyValue;
fairy = false;
} else {
value = 0;
}
}
value |= (idxBlockInPalette << startOffset);
if (startLong != endLong) {
fairyValue = idxBlockInPalette >> (64 - startOffset);
fairy = true;
}
}
}
}
netOutputStream.writeLong(value);
// </Array>
// </Data Array>
// <Block Light>
netOutputStream.writeBytes(blockLight.getRawData());
@@ -254,13 +298,4 @@ public class ChunkDataPacket implements SCPacket {
// </Sky Light>
}
}
@Override
public String toString() {
return "ChunkDataPacket{" +
"x=" + x +
", z=" + z +
", chunk=" + chunk +
'}';
}
}