Mirror von
https://github.com/ViaVersion/ViaVersion.git
synchronisiert 2024-11-03 14:50:30 +01:00
Merge branch 'chunkFix' of https://github.com/Matsv/ViaVersion into upmaster
Dieser Commit ist enthalten in:
Commit
0f3daa5dc4
@ -1,5 +1,9 @@
|
|||||||
package us.myles.ViaVersion.api.minecraft.chunks;
|
package us.myles.ViaVersion.api.minecraft.chunks;
|
||||||
|
|
||||||
|
import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface Chunk {
|
public interface Chunk {
|
||||||
int getX();
|
int getX();
|
||||||
|
|
||||||
@ -14,4 +18,6 @@ public interface Chunk {
|
|||||||
byte[] getBiomeData();
|
byte[] getBiomeData();
|
||||||
|
|
||||||
int getBitmask();
|
int getBitmask();
|
||||||
|
|
||||||
|
List<CompoundTag> getBlockEntities();
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,10 @@ import us.myles.ViaVersion.api.remapper.PacketRemapper;
|
|||||||
import us.myles.ViaVersion.api.type.Type;
|
import us.myles.ViaVersion.api.type.Type;
|
||||||
import us.myles.ViaVersion.packets.State;
|
import us.myles.ViaVersion.packets.State;
|
||||||
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.chunks.BlockEntity;
|
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.chunks.BlockEntity;
|
||||||
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.chunks.Chunk1_9_3_4;
|
|
||||||
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.types.Chunk1_9_3_4Type;
|
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.types.Chunk1_9_3_4Type;
|
||||||
|
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
|
||||||
|
|
||||||
public class Protocol1_9_1_2TO1_9_3_4 extends Protocol {
|
public class Protocol1_9_1_2TO1_9_3_4 extends Protocol {
|
||||||
public static Type<Chunk> CHUNK = new Chunk1_9_3_4Type();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void registerPackets() {
|
protected void registerPackets() {
|
||||||
@ -60,8 +59,50 @@ public class Protocol1_9_1_2TO1_9_3_4 extends Protocol {
|
|||||||
handler(new PacketHandler() {
|
handler(new PacketHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void handle(PacketWrapper wrapper) throws Exception {
|
public void handle(PacketWrapper wrapper) throws Exception {
|
||||||
Chunk chunk = wrapper.passthrough(CHUNK);
|
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||||
BlockEntity.handle(((Chunk1_9_3_4) chunk).getBlockEntities(), wrapper.user());
|
|
||||||
|
Chunk1_9_3_4Type type = new Chunk1_9_3_4Type(clientWorld);
|
||||||
|
Chunk chunk = wrapper.passthrough(type);
|
||||||
|
|
||||||
|
BlockEntity.handle(chunk.getBlockEntities(), wrapper.user());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Join (save dimension id)
|
||||||
|
registerOutgoing(State.PLAY, 0x23, 0x23, new PacketRemapper() {
|
||||||
|
@Override
|
||||||
|
public void registerMap() {
|
||||||
|
map(Type.INT); // 0 - Entity ID
|
||||||
|
map(Type.UNSIGNED_BYTE); // 1 - Gamemode
|
||||||
|
map(Type.INT); // 2 - Dimension
|
||||||
|
|
||||||
|
handler(new PacketHandler() {
|
||||||
|
@Override
|
||||||
|
public void handle(PacketWrapper wrapper) throws Exception {
|
||||||
|
ClientWorld clientChunks = wrapper.user().get(ClientWorld.class);
|
||||||
|
|
||||||
|
int dimensionId = wrapper.get(Type.INT, 1);
|
||||||
|
clientChunks.setEnvironment(dimensionId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Respawn (save dimension id)
|
||||||
|
registerOutgoing(State.PLAY, 0x33, 0x33, new PacketRemapper() {
|
||||||
|
@Override
|
||||||
|
public void registerMap() {
|
||||||
|
map(Type.INT); // 0 - Dimension ID
|
||||||
|
|
||||||
|
handler(new PacketHandler() {
|
||||||
|
@Override
|
||||||
|
public void handle(PacketWrapper wrapper) throws Exception {
|
||||||
|
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||||
|
|
||||||
|
int dimensionId = wrapper.get(Type.INT, 0);
|
||||||
|
clientWorld.setEnvironment(dimensionId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -70,6 +111,7 @@ public class Protocol1_9_1_2TO1_9_3_4 extends Protocol {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(UserConnection userConnection) {
|
public void init(UserConnection userConnection) {
|
||||||
|
if (!userConnection.has(ClientWorld.class))
|
||||||
|
userConnection.put(new ClientWorld(userConnection));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,15 +15,11 @@ public class Chunk1_9_3_4 implements Chunk {
|
|||||||
private boolean groundUp;
|
private boolean groundUp;
|
||||||
private int bitmask;
|
private int bitmask;
|
||||||
private ChunkSection1_9_3_4[] sections;
|
private ChunkSection1_9_3_4[] sections;
|
||||||
List<CompoundTag> blockEntities;
|
private byte[] biomeData;
|
||||||
|
private List<CompoundTag> blockEntities;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isBiomeData() {
|
public boolean isBiomeData() {
|
||||||
return false;
|
return biomeData != null;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getBiomeData() {
|
|
||||||
return new byte[0];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,41 +1,293 @@
|
|||||||
package us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.chunks;
|
package us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.chunks;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import lombok.Getter;
|
||||||
import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection;
|
import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection;
|
||||||
|
import us.myles.ViaVersion.api.minecraft.chunks.NibbleArray;
|
||||||
|
import us.myles.ViaVersion.api.type.Type;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class ChunkSection1_9_3_4 implements ChunkSection {
|
public class ChunkSection1_9_3_4 implements ChunkSection {
|
||||||
private final byte[] data;
|
/**
|
||||||
|
* Size (dimensions) of blocks in a chunks section.
|
||||||
|
*/
|
||||||
|
public static final int SIZE = 16 * 16 * 16; // width * depth * height
|
||||||
|
/**
|
||||||
|
* Length of the sky and block light nibble arrays.
|
||||||
|
*/
|
||||||
|
public static final int LIGHT_LENGTH = 16 * 16 * 16 / 2; // size * size * size / 2 (nibble bit count)
|
||||||
|
/**
|
||||||
|
* Length of the block data array.
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private final List<Integer> palette = Lists.newArrayList();
|
||||||
|
private final int[] blocks;
|
||||||
|
private final NibbleArray blockLight;
|
||||||
|
private NibbleArray skyLight;
|
||||||
|
|
||||||
public ChunkSection1_9_3_4(byte[] data) {
|
public ChunkSection1_9_3_4() {
|
||||||
this.data = data;
|
this.blocks = new int[SIZE];
|
||||||
|
this.blockLight = new NibbleArray(SIZE);
|
||||||
|
palette.add(0); // AIR
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getData() {
|
/**
|
||||||
return data;
|
* Set a block in the chunks
|
||||||
|
*
|
||||||
|
* @param x Block X
|
||||||
|
* @param y Block Y
|
||||||
|
* @param z Block Z
|
||||||
|
* @param type The type of the block
|
||||||
|
* @param data The data value of the block
|
||||||
|
*/
|
||||||
|
public void setBlock(int x, int y, int z, int type, int data) {
|
||||||
|
setBlock(index(x, y, z), type, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getBlockId(int x, int y, int z) {
|
public int getBlockId(int x, int y, int z) {
|
||||||
throw new UnsupportedOperationException("Invalid chunk type!");
|
int index = blocks[index(x, y, z)];
|
||||||
|
return palette.get(index) >> 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Set a block in the chunks based on the index
|
||||||
|
*
|
||||||
|
* @param idx Index
|
||||||
|
* @param type The type of the block
|
||||||
|
* @param data The data value of the block
|
||||||
|
*/
|
||||||
|
public void setBlock(int idx, int type, int data) {
|
||||||
|
int hash = type << 4 | (data & 0xF);
|
||||||
|
int index = palette.indexOf(hash);
|
||||||
|
if (index == -1) {
|
||||||
|
index = palette.size();
|
||||||
|
palette.add(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
blocks[idx] = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the block light array
|
||||||
|
*
|
||||||
|
* @param data The value to set the block light to
|
||||||
|
*/
|
||||||
|
public void setBlockLight(byte[] data) {
|
||||||
|
blockLight.setHandle(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the sky light array
|
||||||
|
*
|
||||||
|
* @param data The value to set the sky light to
|
||||||
|
*/
|
||||||
|
public void setSkyLight(byte[] data) {
|
||||||
|
if (data.length != LIGHT_LENGTH) throw new IllegalArgumentException("Data length != " + LIGHT_LENGTH);
|
||||||
|
this.skyLight = new NibbleArray(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int index(int x, int y, int z) {
|
||||||
|
return y << 8 | z << 4 | x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read blocks from input stream.
|
||||||
|
* This reads all the block related data:
|
||||||
|
* <ul>
|
||||||
|
* <li>Block length/palette type</li>
|
||||||
|
* <li>Palette</li>
|
||||||
|
* <li>Block hashes/palette reference</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param input The buffer to read from.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void readBlocks(ByteBuf input) throws Exception {
|
||||||
|
palette.clear();
|
||||||
|
|
||||||
|
// Reaad bits per block
|
||||||
|
int bitsPerBlock = input.readUnsignedByte();
|
||||||
|
long maxEntryValue = (1L << bitsPerBlock) - 1;
|
||||||
|
|
||||||
|
if (bitsPerBlock == 0) {
|
||||||
|
bitsPerBlock = 13;
|
||||||
|
}
|
||||||
|
if (bitsPerBlock < 4) {
|
||||||
|
bitsPerBlock = 4;
|
||||||
|
}
|
||||||
|
if (bitsPerBlock > 8) {
|
||||||
|
bitsPerBlock = 13;
|
||||||
|
}
|
||||||
|
int paletteLength = Type.VAR_INT.read(input);
|
||||||
|
// Read palette
|
||||||
|
for (int i = 0; i < paletteLength; i++) {
|
||||||
|
if (bitsPerBlock != 13) {
|
||||||
|
palette.add(Type.VAR_INT.read(input));
|
||||||
|
} else {
|
||||||
|
Type.VAR_INT.read(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read blocks
|
||||||
|
Long[] blockData = Type.LONG_ARRAY.read(input);
|
||||||
|
if (blockData.length > 0) {
|
||||||
|
for (int i = 0; i < blocks.length; 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 == 13) {
|
||||||
|
int type = val >> 4;
|
||||||
|
int data = val & 0xF;
|
||||||
|
|
||||||
|
setBlock(i, type, data);
|
||||||
|
} else {
|
||||||
|
blocks[i] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read block light from buffer.
|
||||||
|
*
|
||||||
|
* @param input The buffer to read from
|
||||||
|
*/
|
||||||
|
public void readBlockLight(ByteBuf input) {
|
||||||
|
byte[] handle = new byte[LIGHT_LENGTH];
|
||||||
|
input.readBytes(handle);
|
||||||
|
blockLight.setHandle(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read sky light from buffer.
|
||||||
|
* Note: Only sent in overworld!
|
||||||
|
*
|
||||||
|
* @param input The buffer to read from
|
||||||
|
*/
|
||||||
|
public void readSkyLight(ByteBuf input) {
|
||||||
|
byte[] handle = new byte[LIGHT_LENGTH];
|
||||||
|
input.readBytes(handle);
|
||||||
|
if (skyLight != null) {
|
||||||
|
skyLight.setHandle(handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.skyLight = new NibbleArray(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the blocks to a buffer.
|
||||||
|
*
|
||||||
|
* @param output The buffer to write to.
|
||||||
|
* @throws Exception Throws if it failed to write.
|
||||||
|
*/
|
||||||
public void writeBlocks(ByteBuf output) throws Exception {
|
public void writeBlocks(ByteBuf output) throws Exception {
|
||||||
throw new UnsupportedOperationException("Invalid chunk type!");
|
// Write bits per block
|
||||||
|
int bitsPerBlock = 4;
|
||||||
|
while (palette.size() > 1 << bitsPerBlock) {
|
||||||
|
bitsPerBlock += 1;
|
||||||
|
}
|
||||||
|
long maxEntryValue = (1L << bitsPerBlock) - 1;
|
||||||
|
output.writeByte(bitsPerBlock);
|
||||||
|
|
||||||
|
// Write pallet (or not)
|
||||||
|
Type.VAR_INT.write(output, palette.size());
|
||||||
|
for (int mappedId : palette) {
|
||||||
|
Type.VAR_INT.write(output, mappedId);
|
||||||
|
}
|
||||||
|
|
||||||
|
int length = (int) Math.ceil(SIZE * bitsPerBlock / 64.0);
|
||||||
|
Type.VAR_INT.write(output, length);
|
||||||
|
long[] data = new long[length];
|
||||||
|
for (int index = 0; index < blocks.length; index++) {
|
||||||
|
int value = blocks[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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (long l : data) {
|
||||||
|
Type.LONG.write(output, l);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void writeBlockLight(ByteBuf output) throws Exception {
|
* Write the block light to a buffer
|
||||||
throw new UnsupportedOperationException("Invalid chunk type!");
|
*
|
||||||
|
* @param output The buffer to write to
|
||||||
|
*/
|
||||||
|
public void writeBlockLight(ByteBuf output) {
|
||||||
|
output.writeBytes(blockLight.getHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Write the sky light to a buffer
|
||||||
|
*
|
||||||
|
* @param output The buffer to write to
|
||||||
|
*/
|
||||||
|
public void writeSkyLight(ByteBuf output) {
|
||||||
|
output.writeBytes(skyLight.getHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if sky light is present
|
||||||
|
*
|
||||||
|
* @return True if skylight is present
|
||||||
|
*/
|
||||||
public boolean hasSkyLight() {
|
public boolean hasSkyLight() {
|
||||||
throw new UnsupportedOperationException("Invalid chunk type!");
|
return skyLight != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void writeSkyLight(ByteBuf output) throws Exception {
|
* Get expected size of this chunks section.
|
||||||
throw new UnsupportedOperationException("Invalid chunk type!");
|
*
|
||||||
|
* @return Amount of bytes sent by this section
|
||||||
|
* @throws Exception If it failed to calculate bits properly
|
||||||
|
*/
|
||||||
|
public int getExpectedSize() throws Exception {
|
||||||
|
int bitsPerBlock = palette.size() > 255 ? 16 : 8;
|
||||||
|
int bytes = 1; // bits per block
|
||||||
|
bytes += paletteBytes(); // palette
|
||||||
|
bytes += countBytes(bitsPerBlock == 16 ? SIZE * 2 : SIZE); // block data length
|
||||||
|
bytes += (palette.size() > 255 ? 2 : 1) * SIZE; // block data
|
||||||
|
bytes += LIGHT_LENGTH; // block light
|
||||||
|
bytes += hasSkyLight() ? LIGHT_LENGTH : 0; // sky light
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int paletteBytes() throws Exception {
|
||||||
|
// Count bytes used by pallet
|
||||||
|
int bytes = countBytes(palette.size());
|
||||||
|
for (int mappedId : palette) {
|
||||||
|
bytes += countBytes(mappedId);
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int countBytes(int value) throws Exception {
|
||||||
|
// Count amount of bytes that would be sent if the value were sent as a VarInt
|
||||||
|
ByteBuf buf = Unpooled.buffer();
|
||||||
|
Type.VAR_INT.write(buf, value);
|
||||||
|
buf.readerIndex(0);
|
||||||
|
int bitCount = buf.readableBytes();
|
||||||
|
buf.release();
|
||||||
|
return bitCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,56 +1,102 @@
|
|||||||
package us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.types;
|
package us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.types;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
||||||
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
|
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
|
||||||
|
import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection;
|
||||||
|
import us.myles.ViaVersion.api.type.PartialType;
|
||||||
import us.myles.ViaVersion.api.type.Type;
|
import us.myles.ViaVersion.api.type.Type;
|
||||||
import us.myles.ViaVersion.api.type.types.minecraft.BaseChunkType;
|
import us.myles.ViaVersion.api.type.types.minecraft.BaseChunkType;
|
||||||
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.chunks.Chunk1_9_3_4;
|
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.chunks.Chunk1_9_3_4;
|
||||||
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.chunks.ChunkSection1_9_3_4;
|
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.chunks.ChunkSection1_9_3_4;
|
||||||
|
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.Arrays;
|
||||||
|
import java.util.BitSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Chunk1_9_3_4Type extends BaseChunkType {
|
public class Chunk1_9_3_4Type extends PartialType<Chunk, ClientWorld> {
|
||||||
public Chunk1_9_3_4Type() {
|
|
||||||
super("1.9.3 Chunk");
|
public Chunk1_9_3_4Type(ClientWorld param) {
|
||||||
|
super(param, Chunk.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Chunk read(ByteBuf input) throws Exception {
|
public Chunk read(ByteBuf input, ClientWorld world) throws Exception {
|
||||||
int chunkX = input.readInt();
|
int chunkX = input.readInt();
|
||||||
int chunkZ = input.readInt();
|
int chunkZ = input.readInt();
|
||||||
|
|
||||||
boolean groundUp = input.readBoolean();
|
boolean groundUp = input.readBoolean();
|
||||||
int primaryBitmask = Type.VAR_INT.read(input);
|
int primaryBitmask = Type.VAR_INT.read(input);
|
||||||
int size = Type.VAR_INT.read(input);
|
Type.VAR_INT.read(input);
|
||||||
|
|
||||||
byte[] sections = new byte[size];
|
BitSet usedSections = new BitSet(16);
|
||||||
input.readBytes(sections);
|
ChunkSection1_9_3_4[] sections = new ChunkSection1_9_3_4[16];
|
||||||
|
// Calculate section count from bitmask
|
||||||
int blockEntities = Type.VAR_INT.read(input);
|
for (int i = 0; i < 16; i++) {
|
||||||
List<CompoundTag> nbtData = new ArrayList<>();
|
if ((primaryBitmask & (1 << i)) != 0) {
|
||||||
for (int i = 0; i < blockEntities; i++) {
|
usedSections.set(i);
|
||||||
nbtData.add(Type.NBT.read(input));
|
}
|
||||||
}
|
}
|
||||||
return new Chunk1_9_3_4(chunkX, chunkZ, groundUp, primaryBitmask, new ChunkSection1_9_3_4[] {new ChunkSection1_9_3_4(sections)}, nbtData);
|
|
||||||
|
// Read sections
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
if (!usedSections.get(i)) continue; // Section not set
|
||||||
|
ChunkSection1_9_3_4 section = new ChunkSection1_9_3_4();
|
||||||
|
sections[i] = section;
|
||||||
|
section.readBlocks(input);
|
||||||
|
section.readBlockLight(input);
|
||||||
|
if (world.getEnvironment() == World.Environment.NORMAL) {
|
||||||
|
section.readSkyLight(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] biomeData = groundUp ? new byte[256] : null;
|
||||||
|
if (groundUp) {
|
||||||
|
input.readBytes(biomeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<CompoundTag> nbtData = Arrays.asList(Type.NBT_ARRAY.read(input));
|
||||||
|
|
||||||
|
return new Chunk1_9_3_4(chunkX, chunkZ, groundUp, primaryBitmask, sections, biomeData, nbtData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(ByteBuf buffer, Chunk input) throws Exception {
|
public void write(ByteBuf output, ClientWorld world, Chunk chunk) throws Exception {
|
||||||
if (!(input instanceof Chunk1_9_3_4))
|
output.writeInt(chunk.getX());
|
||||||
throw new Exception("Tried to send the wrong chunk type from 1.9.3-4 chunk: " + input.getClass());
|
output.writeInt(chunk.getZ());
|
||||||
Chunk1_9_3_4 chunk = (Chunk1_9_3_4) input;
|
|
||||||
|
|
||||||
buffer.writeInt(chunk.getX());
|
output.writeBoolean(chunk.isGroundUp());
|
||||||
buffer.writeInt(chunk.getZ());
|
Type.VAR_INT.write(output, chunk.getBitmask());
|
||||||
|
|
||||||
buffer.writeBoolean(chunk.isGroundUp());
|
ByteBuf buf = Unpooled.buffer();
|
||||||
Type.VAR_INT.write(buffer, chunk.getBitmask());
|
for (int i = 0; i < 16; i++) {
|
||||||
|
ChunkSection section = chunk.getSections()[i];
|
||||||
|
if (section == null) continue; // Section not set
|
||||||
|
section.writeBlocks(buf);
|
||||||
|
section.writeBlockLight(buf);
|
||||||
|
|
||||||
Type.VAR_INT.write(buffer, chunk.getSections()[0].getData().length);
|
if (!section.hasSkyLight()) continue; // No sky light, we're done here.
|
||||||
buffer.writeBytes(chunk.getSections()[0].getData());
|
section.writeSkyLight(buf);
|
||||||
|
|
||||||
// no block entities as it's earlier
|
}
|
||||||
|
buf.readerIndex(0);
|
||||||
|
Type.VAR_INT.write(output, buf.readableBytes() + (chunk.isBiomeData() ? 256 : 0));
|
||||||
|
output.writeBytes(buf);
|
||||||
|
buf.release(); // release buffer
|
||||||
|
|
||||||
|
// Write biome data
|
||||||
|
if (chunk.isBiomeData()) {
|
||||||
|
output.writeBytes(chunk.getBiomeData());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't write block entities
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends Type> getBaseClass() {
|
||||||
|
return BaseChunkType.class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,6 +142,7 @@ public class Protocol1_9_3TO1_9_1_2 extends Protocol {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(UserConnection user) {
|
public void init(UserConnection user) {
|
||||||
user.put(new ClientWorld(user));
|
if (!user.has(ClientWorld.class))
|
||||||
|
user.put(new ClientWorld(user));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,12 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.chunks;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
||||||
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
|
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
@ -46,4 +50,9 @@ public class Chunk1_9to1_8 implements Chunk {
|
|||||||
public int getBitmask() {
|
public int getBitmask() {
|
||||||
return primaryBitmask;
|
return primaryBitmask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompoundTag> getBlockEntities() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren