обновление алгоритма для крупно-палитрых чанков
если в палитре больше 15 блоков, то используется больше битов на один блок
This commit is contained in:
@@ -9,7 +9,6 @@ import mc.core.network.NetOutputStream;
|
|||||||
import mc.core.network.SCPacket;
|
import mc.core.network.SCPacket;
|
||||||
import mc.core.network.proto_1_12_2.ByteArrayOutputNetStream;
|
import mc.core.network.proto_1_12_2.ByteArrayOutputNetStream;
|
||||||
import mc.core.utils.NibbleArray;
|
import mc.core.utils.NibbleArray;
|
||||||
import mc.core.world.Biome;
|
|
||||||
import mc.core.world.block.Block;
|
import mc.core.world.block.Block;
|
||||||
import mc.core.world.block.BlockLocation;
|
import mc.core.world.block.BlockLocation;
|
||||||
import mc.core.world.block.BlockType;
|
import mc.core.world.block.BlockType;
|
||||||
@@ -180,71 +179,116 @@ public class ChunkDataPacket implements SCPacket {
|
|||||||
/* writeNBT */
|
/* writeNBT */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ChunkDataPacket{" +
|
||||||
|
"x=" + x +
|
||||||
|
", z=" + z +
|
||||||
|
", chunk=" + chunk +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
private class PalettedChunkSection {
|
private class PalettedChunkSection {
|
||||||
private TIntList palette = new TIntArrayList();
|
private TIntList palette = new TIntArrayList();
|
||||||
private int dataItems = 0;
|
private byte[] blocks = new byte[4096];
|
||||||
private ByteArrayOutputNetStream dataArray = new ByteArrayOutputNetStream();
|
|
||||||
private NibbleArray blockLight = new NibbleArray();
|
private NibbleArray blockLight = new NibbleArray();
|
||||||
private NibbleArray skyLight = 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) {
|
private int serializeBlockState(BlockType blockType) {
|
||||||
return (blockType.getId() << 4) | blockType.getMeta();
|
return (blockType.getId() << 4) | blockType.getMeta();
|
||||||
}
|
}
|
||||||
|
|
||||||
int addBlockType(BlockType blockType) {
|
byte addBlockType(BlockType blockType) {
|
||||||
int blockState = serializeBlockState(blockType);
|
int blockState = serializeBlockState(blockType);
|
||||||
|
|
||||||
int idx;
|
int idx = palette.indexOf(blockState);
|
||||||
if (!palette.contains(blockState)) {
|
if (idx == -1) {
|
||||||
palette.add(blockState);
|
palette.add(blockState);
|
||||||
idx = palette.size()-1;
|
idx = palette.size()-1;
|
||||||
} else {
|
|
||||||
idx = palette.indexOf(blockState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return idx;
|
return (byte) idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addBlock(Block block) {
|
void addBlockLight(int x, int y, int z, int value) {
|
||||||
int idx = addBlockType(block.getBlockType());
|
blockLight.set(x, y, z, value);
|
||||||
|
|
||||||
//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 addSkyLight(int x, int y, int z, int value) {
|
void addSkyLight(int x, int y, int z, int value) {
|
||||||
// sky light data
|
|
||||||
skyLight.set(x, y, z, value);
|
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) {
|
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>
|
// <Palette>
|
||||||
netOutputStream.writeUnsignedByte(4); // Bits Per Block
|
netOutputStream.writeUnsignedByte(bitsPerBlock); // Bits Per Block
|
||||||
netOutputStream.writeVarInt(palette.size()); // Size of palette
|
netOutputStream.writeVarInt(palette.size()); // Size of palette
|
||||||
palette.forEach(value -> { netOutputStream.writeVarInt(value); return true; }); // Palette
|
palette.forEach(value -> { netOutputStream.writeVarInt(value); return true; }); // Palette
|
||||||
// </Palette>
|
// </Palette>
|
||||||
// <Data Array>
|
// <Data Array>
|
||||||
netOutputStream.writeVarInt(dataItems); // Size of Data Array
|
final int dataLength = (4096/*16*16*16*/ * bitsPerBlock) / 64;
|
||||||
netOutputStream.writeBytes(dataArray.toByteArray()); // Data Array
|
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>
|
// </Data Array>
|
||||||
// <Block Light>
|
// <Block Light>
|
||||||
netOutputStream.writeBytes(blockLight.getRawData());
|
netOutputStream.writeBytes(blockLight.getRawData());
|
||||||
@@ -254,13 +298,4 @@ public class ChunkDataPacket implements SCPacket {
|
|||||||
// </Sky Light>
|
// </Sky Light>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ChunkDataPacket{" +
|
|
||||||
"x=" + x +
|
|
||||||
", z=" + z +
|
|
||||||
", chunk=" + chunk +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user