обновление алгоритма для крупно-палитрых чанков
если в палитре больше 15 блоков, то используется больше битов на один блок
This commit is contained in:
@@ -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 +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user