mirror of
https://github.com/GeyserMC/MCProtocolLib.git
synced 2024-11-14 19:34:58 -05:00
Initial update to 1.18 protocol
This commit is contained in:
parent
b3fb245b5b
commit
d527164d4c
20 changed files with 481 additions and 345 deletions
2
pom.xml
2
pom.xml
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<groupId>com.github.steveice10</groupId>
|
<groupId>com.github.steveice10</groupId>
|
||||||
<artifactId>mcprotocollib</artifactId>
|
<artifactId>mcprotocollib</artifactId>
|
||||||
<version>1.17.1-3-SNAPSHOT</version>
|
<version>1.18-pre-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>MCProtocolLib</name>
|
<name>MCProtocolLib</name>
|
||||||
|
|
|
@ -12,12 +12,12 @@ public final class MinecraftConstants {
|
||||||
/**
|
/**
|
||||||
* Current supported game version.
|
* Current supported game version.
|
||||||
*/
|
*/
|
||||||
public static final String GAME_VERSION = "1.17.1";
|
public static final String GAME_VERSION = "1.18-pre1";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current supported protocol version.
|
* Current supported protocol version.
|
||||||
*/
|
*/
|
||||||
public static final int PROTOCOL_VERSION = 756;
|
public static final int PROTOCOL_VERSION = (1 << 30) | 49;
|
||||||
|
|
||||||
// General Key Constants
|
// General Key Constants
|
||||||
|
|
||||||
|
|
|
@ -344,7 +344,7 @@ public class MinecraftProtocol extends PacketProtocol {
|
||||||
clientboundPackets.register(0x1F, ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new);
|
clientboundPackets.register(0x1F, ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new);
|
||||||
clientboundPackets.register(0x20, ClientboundInitializeBorderPacket.class, ClientboundInitializeBorderPacket::new);
|
clientboundPackets.register(0x20, ClientboundInitializeBorderPacket.class, ClientboundInitializeBorderPacket::new);
|
||||||
clientboundPackets.register(0x21, ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new);
|
clientboundPackets.register(0x21, ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new);
|
||||||
clientboundPackets.register(0x22, ClientboundLevelChunkPacket.class, ClientboundLevelChunkPacket::new);
|
clientboundPackets.register(0x22, ClientboundLevelChunkWithLightPacket.class, ClientboundLevelChunkWithLightPacket::new);
|
||||||
clientboundPackets.register(0x23, ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new);
|
clientboundPackets.register(0x23, ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new);
|
||||||
clientboundPackets.register(0x24, ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new);
|
clientboundPackets.register(0x24, ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new);
|
||||||
clientboundPackets.register(0x25, ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new);
|
clientboundPackets.register(0x25, ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new);
|
||||||
|
@ -397,22 +397,23 @@ public class MinecraftProtocol extends PacketProtocol {
|
||||||
clientboundPackets.register(0x54, ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new);
|
clientboundPackets.register(0x54, ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new);
|
||||||
clientboundPackets.register(0x55, ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new);
|
clientboundPackets.register(0x55, ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new);
|
||||||
clientboundPackets.register(0x56, ClientboundSetScorePacket.class, ClientboundSetScorePacket::new);
|
clientboundPackets.register(0x56, ClientboundSetScorePacket.class, ClientboundSetScorePacket::new);
|
||||||
clientboundPackets.register(0x57, ClientboundSetSubtitleTextPacket.class, ClientboundSetSubtitleTextPacket::new);
|
clientboundPackets.register(0x57, ClientboundSetSimulationDistancePacket.class, ClientboundSetSimulationDistancePacket::new);
|
||||||
clientboundPackets.register(0x58, ClientboundSetTimePacket.class, ClientboundSetTimePacket::new);
|
clientboundPackets.register(0x58, ClientboundSetSubtitleTextPacket.class, ClientboundSetSubtitleTextPacket::new);
|
||||||
clientboundPackets.register(0x59, ClientboundSetTitleTextPacket.class, ClientboundSetTitleTextPacket::new);
|
clientboundPackets.register(0x59, ClientboundSetTimePacket.class, ClientboundSetTimePacket::new);
|
||||||
clientboundPackets.register(0x5A, ClientboundSetTitlesAnimationPacket.class, ClientboundSetTitlesAnimationPacket::new);
|
clientboundPackets.register(0x5A, ClientboundSetTitleTextPacket.class, ClientboundSetTitleTextPacket::new);
|
||||||
clientboundPackets.register(0x5B, ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new);
|
clientboundPackets.register(0x5B, ClientboundSetTitlesAnimationPacket.class, ClientboundSetTitlesAnimationPacket::new);
|
||||||
clientboundPackets.register(0x5C, ClientboundSoundPacket.class, ClientboundSoundPacket::new);
|
clientboundPackets.register(0x5C, ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new);
|
||||||
clientboundPackets.register(0x5D, ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new);
|
clientboundPackets.register(0x5D, ClientboundSoundPacket.class, ClientboundSoundPacket::new);
|
||||||
clientboundPackets.register(0x5E, ClientboundTabListPacket.class, ClientboundTabListPacket::new);
|
clientboundPackets.register(0x5E, ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new);
|
||||||
clientboundPackets.register(0x5F, ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new);
|
clientboundPackets.register(0x5F, ClientboundTabListPacket.class, ClientboundTabListPacket::new);
|
||||||
clientboundPackets.register(0x60, ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new);
|
clientboundPackets.register(0x60, ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new);
|
||||||
clientboundPackets.register(0x61, ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new);
|
clientboundPackets.register(0x61, ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new);
|
||||||
clientboundPackets.register(0x62, ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new);
|
clientboundPackets.register(0x62, ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new);
|
||||||
clientboundPackets.register(0x63, ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new);
|
clientboundPackets.register(0x63, ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new);
|
||||||
clientboundPackets.register(0x64, ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new);
|
clientboundPackets.register(0x64, ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new);
|
||||||
clientboundPackets.register(0x65, ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new);
|
clientboundPackets.register(0x65, ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new);
|
||||||
clientboundPackets.register(0x66, ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new);
|
clientboundPackets.register(0x66, ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new);
|
||||||
|
clientboundPackets.register(0x67, ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new);
|
||||||
|
|
||||||
serverboundPackets.register(0x00, ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new);
|
serverboundPackets.register(0x00, ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new);
|
||||||
serverboundPackets.register(0x01, ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new);
|
serverboundPackets.register(0x01, ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new);
|
||||||
|
|
|
@ -1,16 +1,8 @@
|
||||||
package com.github.steveice10.mc.protocol.data.game.chunk;
|
package com.github.steveice10.mc.protocol.data.game.chunk;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.chunk.palette.GlobalPalette;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.chunk.palette.ListPalette;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.chunk.palette.MapPalette;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.chunk.palette.Palette;
|
|
||||||
import com.github.steveice10.packetlib.io.NetInput;
|
import com.github.steveice10.packetlib.io.NetInput;
|
||||||
import com.github.steveice10.packetlib.io.NetOutput;
|
import com.github.steveice10.packetlib.io.NetOutput;
|
||||||
import lombok.AccessLevel;
|
import lombok.*;
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -18,117 +10,48 @@ import java.io.IOException;
|
||||||
@Setter(AccessLevel.NONE)
|
@Setter(AccessLevel.NONE)
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class Chunk {
|
public class Chunk {
|
||||||
private static final int CHUNK_SIZE = 4096;
|
|
||||||
private static final int MIN_PALETTE_BITS_PER_ENTRY = 4;
|
|
||||||
private static final int MAX_PALETTE_BITS_PER_ENTRY = 8;
|
private static final int MAX_PALETTE_BITS_PER_ENTRY = 8;
|
||||||
private static final int GLOBAL_PALETTE_BITS_PER_ENTRY = 14;
|
private static final int MAX_BIOME_BITS_PER_ENTRY = 2;
|
||||||
|
|
||||||
private static final int AIR = 0;
|
private static final int AIR = 0;
|
||||||
|
|
||||||
private int blockCount;
|
private int blockCount;
|
||||||
private @NonNull Palette palette;
|
private @NonNull DataPalette chunkData;
|
||||||
private @NonNull BitStorage storage;
|
@Getter
|
||||||
|
private @NonNull DataPalette biomeData;
|
||||||
|
|
||||||
public Chunk() {
|
public Chunk() {
|
||||||
this(0, new ListPalette(MIN_PALETTE_BITS_PER_ENTRY), new BitStorage(MIN_PALETTE_BITS_PER_ENTRY, CHUNK_SIZE));
|
this(0, DataPalette.createEmpty(MAX_PALETTE_BITS_PER_ENTRY, DataPalette.CHUNK_SIZE), DataPalette.createEmpty(MAX_BIOME_BITS_PER_ENTRY, DataPalette.BIOME_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Chunk read(NetInput in) throws IOException {
|
public static Chunk read(NetInput in) throws IOException {
|
||||||
int blockCount = in.readShort();
|
int blockCount = in.readShort();
|
||||||
int bitsPerEntry = in.readUnsignedByte();
|
|
||||||
|
|
||||||
Palette palette = readPalette(bitsPerEntry, in);
|
DataPalette chunkPalette = DataPalette.read(in, MAX_PALETTE_BITS_PER_ENTRY, DataPalette.CHUNK_SIZE);
|
||||||
|
DataPalette biomePalette = DataPalette.read(in, MAX_BIOME_BITS_PER_ENTRY, DataPalette.BIOME_SIZE);
|
||||||
BitStorage storage = new BitStorage(bitsPerEntry, CHUNK_SIZE, in.readLongs(in.readVarInt()));
|
return new Chunk(blockCount, chunkPalette, biomePalette);
|
||||||
return new Chunk(blockCount, palette, storage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void write(NetOutput out, Chunk chunk) throws IOException {
|
public static void write(NetOutput out, Chunk chunk) throws IOException {
|
||||||
out.writeShort(chunk.blockCount);
|
out.writeShort(chunk.blockCount);
|
||||||
out.writeByte(chunk.storage.getBitsPerEntry());
|
DataPalette.write(out, chunk.chunkData);
|
||||||
|
DataPalette.write(out, chunk.biomeData);
|
||||||
if (!(chunk.palette instanceof GlobalPalette)) {
|
|
||||||
int paletteLength = chunk.palette.size();
|
|
||||||
out.writeVarInt(paletteLength);
|
|
||||||
for (int i = 0; i < paletteLength; i++) {
|
|
||||||
out.writeVarInt(chunk.palette.idToState(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
long[] data = chunk.storage.getData();
|
|
||||||
out.writeVarInt(data.length);
|
|
||||||
out.writeLongs(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int get(int x, int y, int z) {
|
public int getBlock(int x, int y, int z) {
|
||||||
int id = this.storage.get(index(x, y, z));
|
return this.chunkData.get(x, y, z);
|
||||||
return this.palette.idToState(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(int x, int y, int z, @NonNull int state) {
|
public void setBlock(int x, int y, int z, int state) {
|
||||||
int id = this.palette.stateToId(state);
|
int curr = this.chunkData.set(x, y, z, state);
|
||||||
if (id == -1) {
|
|
||||||
this.resizePalette();
|
|
||||||
id = this.palette.stateToId(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
int index = index(x, y, z);
|
|
||||||
int curr = this.storage.get(index);
|
|
||||||
if (state != AIR && curr == AIR) {
|
if (state != AIR && curr == AIR) {
|
||||||
this.blockCount++;
|
this.blockCount++;
|
||||||
} else if (state == AIR && curr != AIR) {
|
} else if (state == AIR && curr != AIR) {
|
||||||
this.blockCount--;
|
this.blockCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.storage.set(index, id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isBlockCountEmpty() {
|
||||||
return this.blockCount == 0;
|
return this.blockCount == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int sanitizeBitsPerEntry(int bitsPerEntry) {
|
|
||||||
if (bitsPerEntry <= MAX_PALETTE_BITS_PER_ENTRY) {
|
|
||||||
return Math.max(MIN_PALETTE_BITS_PER_ENTRY, bitsPerEntry);
|
|
||||||
} else {
|
|
||||||
return GLOBAL_PALETTE_BITS_PER_ENTRY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resizePalette() {
|
|
||||||
Palette oldPalette = this.palette;
|
|
||||||
BitStorage oldData = this.storage;
|
|
||||||
|
|
||||||
int bitsPerEntry = sanitizeBitsPerEntry(oldData.getBitsPerEntry() + 1);
|
|
||||||
this.palette = createPalette(bitsPerEntry);
|
|
||||||
this.storage = new BitStorage(bitsPerEntry, CHUNK_SIZE);
|
|
||||||
|
|
||||||
for (int i = 0; i < CHUNK_SIZE; i++) {
|
|
||||||
this.storage.set(i, this.palette.stateToId(oldPalette.idToState(oldData.get(i))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Palette createPalette(int bitsPerEntry) {
|
|
||||||
if (bitsPerEntry <= MIN_PALETTE_BITS_PER_ENTRY) {
|
|
||||||
return new ListPalette(bitsPerEntry);
|
|
||||||
} else if (bitsPerEntry <= MAX_PALETTE_BITS_PER_ENTRY) {
|
|
||||||
return new MapPalette(bitsPerEntry);
|
|
||||||
} else {
|
|
||||||
return new GlobalPalette();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Palette readPalette(int bitsPerEntry, NetInput in) throws IOException {
|
|
||||||
if (bitsPerEntry <= MIN_PALETTE_BITS_PER_ENTRY) {
|
|
||||||
return new ListPalette(bitsPerEntry, in);
|
|
||||||
} else if (bitsPerEntry <= MAX_PALETTE_BITS_PER_ENTRY) {
|
|
||||||
return new MapPalette(bitsPerEntry, in);
|
|
||||||
} else {
|
|
||||||
return new GlobalPalette();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int index(int x, int y, int z) {
|
|
||||||
return y << 8 | z << 4 | x;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
package com.github.steveice10.mc.protocol.data.game.chunk;
|
|
||||||
|
|
||||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NonNull;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class Column {
|
|
||||||
private final int x;
|
|
||||||
private final int z;
|
|
||||||
private final @NonNull Chunk[] chunks;
|
|
||||||
private final @NonNull CompoundTag[] tileEntities;
|
|
||||||
private final @NonNull CompoundTag heightMaps;
|
|
||||||
private final @NonNull int[] biomeData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Non-full chunks no longer exist since 1.17.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public Column(int x, int z, @NonNull Chunk[] chunks, @NonNull CompoundTag[] tileEntities, @NonNull CompoundTag heightMaps) {
|
|
||||||
this(x, z, chunks, tileEntities, heightMaps, new int[1024]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Column(int x, int z, @NonNull Chunk[] chunks, @NonNull CompoundTag[] tileEntities, @NonNull CompoundTag heightMaps, @NonNull int[] biomeData) {
|
|
||||||
this.x = x;
|
|
||||||
this.z = z;
|
|
||||||
this.chunks = Arrays.copyOf(chunks, chunks.length);
|
|
||||||
this.biomeData = biomeData != null ? Arrays.copyOf(biomeData, biomeData.length) : null;
|
|
||||||
this.tileEntities = tileEntities != null ? tileEntities : new CompoundTag[0];
|
|
||||||
this.heightMaps = heightMaps;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
package com.github.steveice10.mc.protocol.data.game.chunk;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.chunk.palette.*;
|
||||||
|
import com.github.steveice10.packetlib.io.NetInput;
|
||||||
|
import com.github.steveice10.packetlib.io.NetOutput;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode
|
||||||
|
public class DataPalette {
|
||||||
|
static final int BIOME_SIZE = 64;
|
||||||
|
static final int CHUNK_SIZE = 4096;
|
||||||
|
private static final int MAX_BIOME_BITS_PER_ENTRY = 2;
|
||||||
|
private static final int MIN_PALETTE_BITS_PER_ENTRY = 4;
|
||||||
|
private static final int MAX_PALETTE_BITS_PER_ENTRY = 8;
|
||||||
|
private static final int GLOBAL_PALETTE_BITS_PER_ENTRY = 14;
|
||||||
|
|
||||||
|
private @NonNull Palette palette;
|
||||||
|
private BitStorage storage;
|
||||||
|
private final int maxBitsForType;
|
||||||
|
private final int maxStorageSize;
|
||||||
|
|
||||||
|
public static DataPalette createForChunk() {
|
||||||
|
return createEmpty(MAX_PALETTE_BITS_PER_ENTRY, CHUNK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DataPalette createForBiome() {
|
||||||
|
return createEmpty(MAX_BIOME_BITS_PER_ENTRY, CHUNK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DataPalette createEmpty(int maxBitsForType, int maxStorageSize) {
|
||||||
|
return new DataPalette(new ListPalette(MIN_PALETTE_BITS_PER_ENTRY),
|
||||||
|
new BitStorage(MIN_PALETTE_BITS_PER_ENTRY, maxBitsForType), maxBitsForType, maxStorageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DataPalette read(NetInput in, int maxBitsForType, int maxSizeForType) throws IOException {
|
||||||
|
int bitsPerEntry = in.readByte();
|
||||||
|
Palette palette = readPalette(bitsPerEntry, maxBitsForType, in);
|
||||||
|
BitStorage storage;
|
||||||
|
if (!(palette instanceof SingletonPalette)) {
|
||||||
|
storage = new BitStorage(bitsPerEntry, maxSizeForType, in.readLongs(in.readVarInt()));
|
||||||
|
} else {
|
||||||
|
in.readVarInt();
|
||||||
|
storage = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DataPalette(palette, storage, maxBitsForType, maxSizeForType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void write(NetOutput out, DataPalette palette) throws IOException {
|
||||||
|
out.writeByte(palette.storage.getBitsPerEntry());
|
||||||
|
|
||||||
|
if (palette.palette instanceof SingletonPalette) {
|
||||||
|
out.writeVarInt(palette.palette.idToState(0));
|
||||||
|
out.writeVarInt(0); // Data length
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(palette.palette instanceof GlobalPalette)) {
|
||||||
|
int paletteLength = palette.palette.size();
|
||||||
|
out.writeVarInt(paletteLength);
|
||||||
|
for (int i = 0; i < paletteLength; i++) {
|
||||||
|
out.writeVarInt(palette.palette.idToState(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long[] data = palette.storage.getData();
|
||||||
|
out.writeVarInt(data.length);
|
||||||
|
out.writeLongs(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int get(int x, int y, int z) {
|
||||||
|
if (storage != null) {
|
||||||
|
int id = this.storage.get(index(x, y, z));
|
||||||
|
return this.palette.idToState(id);
|
||||||
|
} else {
|
||||||
|
return this.palette.idToState(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the old value present in the storage.
|
||||||
|
*/
|
||||||
|
public int set(int x, int y, int z, int state) {
|
||||||
|
int id = this.palette.stateToId(state);
|
||||||
|
if (id == -1) {
|
||||||
|
resize();
|
||||||
|
id = this.palette.stateToId(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = index(x, y, z);
|
||||||
|
int curr = this.storage.get(index);
|
||||||
|
|
||||||
|
this.storage.set(index, id);
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Palette readPalette(int bitsPerEntry, int maxBitsPerEntry, NetInput in) throws IOException {
|
||||||
|
if (bitsPerEntry > maxBitsPerEntry) {
|
||||||
|
return new GlobalPalette();
|
||||||
|
}
|
||||||
|
if (bitsPerEntry == 0) {
|
||||||
|
return new SingletonPalette(in);
|
||||||
|
}
|
||||||
|
if (bitsPerEntry <= MIN_PALETTE_BITS_PER_ENTRY) {
|
||||||
|
return new ListPalette(bitsPerEntry, in);
|
||||||
|
} else {
|
||||||
|
return new MapPalette(bitsPerEntry, in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int sanitizeBitsPerEntry(int bitsPerEntry) {
|
||||||
|
if (bitsPerEntry <= MAX_PALETTE_BITS_PER_ENTRY) {
|
||||||
|
return Math.max(MIN_PALETTE_BITS_PER_ENTRY, bitsPerEntry);
|
||||||
|
} else {
|
||||||
|
return GLOBAL_PALETTE_BITS_PER_ENTRY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resize() {
|
||||||
|
Palette oldPalette = this.palette;
|
||||||
|
BitStorage oldData = this.storage;
|
||||||
|
|
||||||
|
int bitsPerEntry = sanitizeBitsPerEntry(oldPalette instanceof SingletonPalette ? 1 : oldData.getBitsPerEntry() + 1);
|
||||||
|
this.palette = createPalette(bitsPerEntry);
|
||||||
|
this.storage = new BitStorage(bitsPerEntry, maxStorageSize);
|
||||||
|
|
||||||
|
if (oldPalette instanceof SingletonPalette) {
|
||||||
|
for (int i = 0; i < maxStorageSize; i++) {
|
||||||
|
// TODO necessary?
|
||||||
|
this.storage.set(i, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < maxStorageSize; i++) {
|
||||||
|
this.storage.set(i, this.palette.stateToId(oldPalette.idToState(oldData.get(i))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Palette createPalette(int bitsPerEntry) {
|
||||||
|
if (bitsPerEntry <= MIN_PALETTE_BITS_PER_ENTRY) {
|
||||||
|
return new ListPalette(bitsPerEntry);
|
||||||
|
} else if (bitsPerEntry <= MAX_PALETTE_BITS_PER_ENTRY) {
|
||||||
|
return new MapPalette(bitsPerEntry);
|
||||||
|
} else {
|
||||||
|
return new GlobalPalette();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int index(int x, int y, int z) {
|
||||||
|
return y << 8 | z << 4 | x;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.github.steveice10.mc.protocol.data.game.chunk.palette;
|
||||||
|
|
||||||
|
import com.github.steveice10.packetlib.io.NetInput;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A palette containing one state.
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode
|
||||||
|
public class SingletonPalette implements Palette {
|
||||||
|
private final int state;
|
||||||
|
|
||||||
|
public SingletonPalette(int state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SingletonPalette(NetInput in) throws IOException {
|
||||||
|
this.state = in.readVarInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int stateToId(int state) {
|
||||||
|
if (this.state == state) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int idToState(int id) {
|
||||||
|
if (id == 0) {
|
||||||
|
return this.state;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
package com.github.steveice10.mc.protocol.data.game.level;
|
||||||
|
|
||||||
|
import com.github.steveice10.packetlib.io.NetInput;
|
||||||
|
import com.github.steveice10.packetlib.io.NetOutput;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NonNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.BitSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class LightUpdateData {
|
||||||
|
private final @NonNull BitSet skyYMask;
|
||||||
|
private final @NonNull BitSet blockYMask;
|
||||||
|
private final @NonNull BitSet emptySkyYMask;
|
||||||
|
private final @NonNull BitSet emptyBlockYMask;
|
||||||
|
private final @NonNull List<byte[]> skyUpdates;
|
||||||
|
private final @NonNull List<byte[]> blockUpdates;
|
||||||
|
private final boolean trustEdges;
|
||||||
|
|
||||||
|
public static LightUpdateData read(NetInput in) throws IOException {
|
||||||
|
return new LightUpdateData(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LightUpdateData(NetInput in) throws IOException {
|
||||||
|
this.trustEdges = in.readBoolean();
|
||||||
|
|
||||||
|
this.skyYMask = BitSet.valueOf(in.readLongs(in.readVarInt()));
|
||||||
|
this.blockYMask = BitSet.valueOf(in.readLongs(in.readVarInt()));
|
||||||
|
this.emptySkyYMask = BitSet.valueOf(in.readLongs(in.readVarInt()));
|
||||||
|
this.emptyBlockYMask = BitSet.valueOf(in.readLongs(in.readVarInt()));
|
||||||
|
|
||||||
|
int skyUpdateSize = in.readVarInt();
|
||||||
|
skyUpdates = new ArrayList<>(skyUpdateSize);
|
||||||
|
for (int i = 0; i < skyUpdateSize; i++) {
|
||||||
|
skyUpdates.add(in.readBytes(in.readVarInt()));
|
||||||
|
}
|
||||||
|
|
||||||
|
int blockUpdateSize = in.readVarInt();
|
||||||
|
blockUpdates = new ArrayList<>(blockUpdateSize);
|
||||||
|
for (int i = 0; i < blockUpdateSize; i++) {
|
||||||
|
blockUpdates.add(in.readBytes(in.readVarInt()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void write(NetOutput out, LightUpdateData data) throws IOException {
|
||||||
|
data.write(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void write(NetOutput out) throws IOException {
|
||||||
|
out.writeBoolean(this.trustEdges);
|
||||||
|
|
||||||
|
writeBitSet(out, this.skyYMask);
|
||||||
|
writeBitSet(out, this.blockYMask);
|
||||||
|
writeBitSet(out, this.emptySkyYMask);
|
||||||
|
writeBitSet(out, this.emptyBlockYMask);
|
||||||
|
|
||||||
|
out.writeVarInt(this.skyUpdates.size());
|
||||||
|
for (byte[] array : this.skyUpdates) {
|
||||||
|
out.writeVarInt(array.length);
|
||||||
|
out.writeBytes(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
out.writeVarInt(this.blockUpdates.size());
|
||||||
|
for (byte[] array : this.blockUpdates) {
|
||||||
|
out.writeVarInt(array.length);
|
||||||
|
out.writeBytes(array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeBitSet(NetOutput out, BitSet bitSet) throws IOException {
|
||||||
|
long[] array = bitSet.toLongArray();
|
||||||
|
out.writeVarInt(array.length);
|
||||||
|
for (long content : array) {
|
||||||
|
out.writeLong(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.github.steveice10.mc.protocol.data.game.level.block;
|
||||||
|
|
||||||
|
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class BlockEntityInfo {
|
||||||
|
private final int x;
|
||||||
|
private final int y;
|
||||||
|
private final int z;
|
||||||
|
private final int id;
|
||||||
|
private final @Nullable CompoundTag nbt;
|
||||||
|
}
|
|
@ -32,6 +32,7 @@ public class ClientboundLoginPacket implements Packet {
|
||||||
private final long hashedSeed;
|
private final long hashedSeed;
|
||||||
private final int maxPlayers;
|
private final int maxPlayers;
|
||||||
private final int viewDistance;
|
private final int viewDistance;
|
||||||
|
private final int simulationDistance;
|
||||||
private final boolean reducedDebugInfo;
|
private final boolean reducedDebugInfo;
|
||||||
private final boolean enableRespawnScreen;
|
private final boolean enableRespawnScreen;
|
||||||
private final boolean debug;
|
private final boolean debug;
|
||||||
|
@ -55,6 +56,7 @@ public class ClientboundLoginPacket implements Packet {
|
||||||
this.hashedSeed = in.readLong();
|
this.hashedSeed = in.readLong();
|
||||||
this.maxPlayers = in.readVarInt();
|
this.maxPlayers = in.readVarInt();
|
||||||
this.viewDistance = in.readVarInt();
|
this.viewDistance = in.readVarInt();
|
||||||
|
this.simulationDistance = in.readVarInt();
|
||||||
this.reducedDebugInfo = in.readBoolean();
|
this.reducedDebugInfo = in.readBoolean();
|
||||||
this.enableRespawnScreen = in.readBoolean();
|
this.enableRespawnScreen = in.readBoolean();
|
||||||
this.debug = in.readBoolean();
|
this.debug = in.readBoolean();
|
||||||
|
@ -80,6 +82,7 @@ public class ClientboundLoginPacket implements Packet {
|
||||||
out.writeLong(this.hashedSeed);
|
out.writeLong(this.hashedSeed);
|
||||||
out.writeVarInt(this.maxPlayers);
|
out.writeVarInt(this.maxPlayers);
|
||||||
out.writeVarInt(this.viewDistance);
|
out.writeVarInt(this.viewDistance);
|
||||||
|
out.writeVarInt(this.simulationDistance);
|
||||||
out.writeBoolean(this.reducedDebugInfo);
|
out.writeBoolean(this.reducedDebugInfo);
|
||||||
out.writeBoolean(this.enableRespawnScreen);
|
out.writeBoolean(this.enableRespawnScreen);
|
||||||
out.writeBoolean(this.debug);
|
out.writeBoolean(this.debug);
|
||||||
|
|
|
@ -25,14 +25,14 @@ public class ClientboundBlockEntityDataPacket implements Packet {
|
||||||
|
|
||||||
public ClientboundBlockEntityDataPacket(NetInput in) throws IOException {
|
public ClientboundBlockEntityDataPacket(NetInput in) throws IOException {
|
||||||
this.position = Position.read(in);
|
this.position = Position.read(in);
|
||||||
this.type = MagicValues.key(UpdatedTileType.class, in.readUnsignedByte());
|
this.type = MagicValues.key(UpdatedTileType.class, in.readVarInt());
|
||||||
this.nbt = NBT.read(in);
|
this.nbt = NBT.read(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(NetOutput out) throws IOException {
|
public void write(NetOutput out) throws IOException {
|
||||||
Position.write(out, this.position);
|
Position.write(out, this.position);
|
||||||
out.writeByte(MagicValues.value(Integer.class, this.type));
|
out.writeVarInt(MagicValues.value(Integer.class, this.type));
|
||||||
NBT.write(out, this.nbt);
|
NBT.write(out, this.nbt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
package com.github.steveice10.mc.protocol.packet.ingame.clientbound.level;
|
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.NBT;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.chunk.Chunk;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.chunk.Column;
|
|
||||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
|
||||||
import com.github.steveice10.packetlib.io.NetInput;
|
|
||||||
import com.github.steveice10.packetlib.io.NetOutput;
|
|
||||||
import com.github.steveice10.packetlib.io.stream.StreamNetInput;
|
|
||||||
import com.github.steveice10.packetlib.io.stream.StreamNetOutput;
|
|
||||||
import com.github.steveice10.packetlib.packet.Packet;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.With;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.BitSet;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@With
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class ClientboundLevelChunkPacket implements Packet {
|
|
||||||
private final @NonNull Column column;
|
|
||||||
|
|
||||||
public ClientboundLevelChunkPacket(NetInput in) throws IOException {
|
|
||||||
int x = in.readInt();
|
|
||||||
int z = in.readInt();
|
|
||||||
BitSet chunkMask = BitSet.valueOf(in.readLongs(in.readVarInt()));
|
|
||||||
CompoundTag heightMaps = NBT.read(in);
|
|
||||||
int[] biomeData = new int[in.readVarInt()];
|
|
||||||
for (int index = 0; index < biomeData.length; index++) {
|
|
||||||
biomeData[index] = in.readVarInt();
|
|
||||||
}
|
|
||||||
byte[] data = in.readBytes(in.readVarInt());
|
|
||||||
|
|
||||||
NetInput dataIn = new StreamNetInput(new ByteArrayInputStream(data));
|
|
||||||
Chunk[] chunks = new Chunk[chunkMask.size()];
|
|
||||||
for (int index = 0; index < chunks.length; index++) {
|
|
||||||
if (chunkMask.get(index)) {
|
|
||||||
chunks[index] = Chunk.read(dataIn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CompoundTag[] tileEntities = new CompoundTag[in.readVarInt()];
|
|
||||||
for (int i = 0; i < tileEntities.length; i++) {
|
|
||||||
tileEntities[i] = NBT.read(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.column = new Column(x, z, chunks, tileEntities, heightMaps, biomeData);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(NetOutput out) throws IOException {
|
|
||||||
ByteArrayOutputStream dataBytes = new ByteArrayOutputStream();
|
|
||||||
NetOutput dataOut = new StreamNetOutput(dataBytes);
|
|
||||||
|
|
||||||
BitSet bitSet = new BitSet();
|
|
||||||
Chunk[] chunks = this.column.getChunks();
|
|
||||||
for (int index = 0; index < chunks.length; index++) {
|
|
||||||
Chunk chunk = chunks[index];
|
|
||||||
if (chunk != null && !chunk.isEmpty()) {
|
|
||||||
bitSet.set(index);
|
|
||||||
Chunk.write(dataOut, chunk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out.writeInt(this.column.getX());
|
|
||||||
out.writeInt(this.column.getZ());
|
|
||||||
long[] longArray = bitSet.toLongArray();
|
|
||||||
out.writeVarInt(longArray.length);
|
|
||||||
for (long content : longArray) {
|
|
||||||
out.writeLong(content);
|
|
||||||
}
|
|
||||||
NBT.write(out, this.column.getHeightMaps());
|
|
||||||
out.writeVarInt(this.column.getBiomeData().length);
|
|
||||||
for (int biomeData : this.column.getBiomeData()) {
|
|
||||||
out.writeVarInt(biomeData);
|
|
||||||
}
|
|
||||||
out.writeVarInt(dataBytes.size());
|
|
||||||
out.writeBytes(dataBytes.toByteArray(), dataBytes.size());
|
|
||||||
out.writeVarInt(this.column.getTileEntities().length);
|
|
||||||
for (CompoundTag tag : this.column.getTileEntities()) {
|
|
||||||
NBT.write(out, tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.github.steveice10.mc.protocol.packet.ingame.clientbound.level;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.NBT;
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.level.LightUpdateData;
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo;
|
||||||
|
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||||
|
import com.github.steveice10.packetlib.io.NetInput;
|
||||||
|
import com.github.steveice10.packetlib.io.NetOutput;
|
||||||
|
import com.github.steveice10.packetlib.packet.Packet;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.With;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@With
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ClientboundLevelChunkWithLightPacket implements Packet {
|
||||||
|
private final int x;
|
||||||
|
private final int z;
|
||||||
|
private final @NonNull byte[] chunkData;
|
||||||
|
private final @NonNull CompoundTag heightMaps;
|
||||||
|
private final @NonNull BlockEntityInfo[] blockEntities;
|
||||||
|
private final @NonNull LightUpdateData lightData;
|
||||||
|
|
||||||
|
public ClientboundLevelChunkWithLightPacket(NetInput in) throws IOException {
|
||||||
|
this.x = in.readInt();
|
||||||
|
this.z = in.readInt();
|
||||||
|
this.heightMaps = NBT.read(in);
|
||||||
|
this.chunkData = in.readBytes(in.readVarInt());
|
||||||
|
|
||||||
|
this.blockEntities = new BlockEntityInfo[in.readVarInt()];
|
||||||
|
for (int i = 0; i < blockEntities.length; i++) {
|
||||||
|
byte xz = in.readByte();
|
||||||
|
int blockEntityX = (xz >> 4) & 15;
|
||||||
|
int blockEntityZ = xz & 15;
|
||||||
|
int blockEntityY = in.readShort();
|
||||||
|
int type = in.readVarInt();
|
||||||
|
CompoundTag tag = NBT.read(in);
|
||||||
|
blockEntities[i] = new BlockEntityInfo(blockEntityX, blockEntityY, blockEntityZ, type, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lightData = LightUpdateData.read(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(NetOutput out) throws IOException {
|
||||||
|
out.writeInt(this.x);
|
||||||
|
out.writeInt(this.z);
|
||||||
|
NBT.write(out, this.heightMaps);
|
||||||
|
out.writeVarInt(this.chunkData.length);
|
||||||
|
out.writeBytes(this.chunkData);
|
||||||
|
|
||||||
|
out.writeVarInt(this.blockEntities.length);
|
||||||
|
for (BlockEntityInfo blockEntity : this.blockEntities) {
|
||||||
|
out.writeByte(((blockEntity.getX() & 15) << 4) | blockEntity.getZ() & 15);
|
||||||
|
out.writeShort(blockEntity.getY());
|
||||||
|
out.writeVarInt(blockEntity.getId());
|
||||||
|
NBT.write(out, blockEntity.getNbt());
|
||||||
|
}
|
||||||
|
|
||||||
|
LightUpdateData.write(out, this.lightData);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,32 +1,26 @@
|
||||||
package com.github.steveice10.mc.protocol.packet.ingame.clientbound.level;
|
package com.github.steveice10.mc.protocol.packet.ingame.clientbound.level;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.level.LightUpdateData;
|
||||||
import com.github.steveice10.packetlib.io.NetInput;
|
import com.github.steveice10.packetlib.io.NetInput;
|
||||||
import com.github.steveice10.packetlib.io.NetOutput;
|
import com.github.steveice10.packetlib.io.NetOutput;
|
||||||
import com.github.steveice10.packetlib.packet.Packet;
|
import com.github.steveice10.packetlib.packet.Packet;
|
||||||
import lombok.AccessLevel;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.With;
|
import lombok.With;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@With
|
@With
|
||||||
|
@AllArgsConstructor
|
||||||
public class ClientboundLightUpdatePacket implements Packet {
|
public class ClientboundLightUpdatePacket implements Packet {
|
||||||
private final int x;
|
private final int x;
|
||||||
private final int z;
|
private final int z;
|
||||||
private final @NonNull BitSet skyYMask;
|
private final @Nonnull LightUpdateData lightData;
|
||||||
private final @NonNull BitSet blockYMask;
|
|
||||||
private final @NonNull BitSet emptySkyYMask;
|
|
||||||
private final @NonNull BitSet emptyBlockYMask;
|
|
||||||
private final @NonNull List<byte[]> skyUpdates;
|
|
||||||
private final @NonNull List<byte[]> blockUpdates;
|
|
||||||
private final boolean trustEdges;
|
|
||||||
|
|
||||||
public ClientboundLightUpdatePacket(int x, int z, @NonNull BitSet skyYMask, @NonNull BitSet blockYMask,
|
public ClientboundLightUpdatePacket(int x, int z, @NonNull BitSet skyYMask, @NonNull BitSet blockYMask,
|
||||||
@NonNull BitSet emptySkyYMask, @NonNull BitSet emptyBlockYMask,
|
@NonNull BitSet emptySkyYMask, @NonNull BitSet emptyBlockYMask,
|
||||||
|
@ -43,72 +37,19 @@ public class ClientboundLightUpdatePacket implements Packet {
|
||||||
}
|
}
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
this.skyYMask = skyYMask;
|
this.lightData = new LightUpdateData(skyYMask, blockYMask, emptySkyYMask, emptyBlockYMask, skyUpdates, blockUpdates, trustEdges);
|
||||||
this.blockYMask = blockYMask;
|
|
||||||
this.emptySkyYMask = emptySkyYMask;
|
|
||||||
this.emptyBlockYMask = emptyBlockYMask;
|
|
||||||
this.skyUpdates = skyUpdates;
|
|
||||||
this.blockUpdates = blockUpdates;
|
|
||||||
this.trustEdges = trustEdges;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClientboundLightUpdatePacket(NetInput in) throws IOException {
|
public ClientboundLightUpdatePacket(NetInput in) throws IOException {
|
||||||
this.x = in.readVarInt();
|
this.x = in.readVarInt();
|
||||||
this.z = in.readVarInt();
|
this.z = in.readVarInt();
|
||||||
this.trustEdges = in.readBoolean();
|
this.lightData = LightUpdateData.read(in);
|
||||||
|
|
||||||
this.skyYMask = BitSet.valueOf(in.readLongs(in.readVarInt()));
|
|
||||||
this.blockYMask = BitSet.valueOf(in.readLongs(in.readVarInt()));
|
|
||||||
this.emptySkyYMask = BitSet.valueOf(in.readLongs(in.readVarInt()));
|
|
||||||
this.emptyBlockYMask = BitSet.valueOf(in.readLongs(in.readVarInt()));
|
|
||||||
|
|
||||||
int skyUpdateSize = in.readVarInt();
|
|
||||||
skyUpdates = new ArrayList<>(skyUpdateSize);
|
|
||||||
for (int i = 0; i < skyUpdateSize; i++) {
|
|
||||||
skyUpdates.add(in.readBytes(in.readVarInt()));
|
|
||||||
}
|
|
||||||
|
|
||||||
int blockUpdateSize = in.readVarInt();
|
|
||||||
blockUpdates = new ArrayList<>(blockUpdateSize);
|
|
||||||
for (int i = 0; i < blockUpdateSize; i++) {
|
|
||||||
blockUpdates.add(in.readBytes(in.readVarInt()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(NetOutput out) throws IOException {
|
public void write(NetOutput out) throws IOException {
|
||||||
out.writeVarInt(this.x);
|
out.writeVarInt(this.x);
|
||||||
out.writeVarInt(this.z);
|
out.writeVarInt(this.z);
|
||||||
out.writeBoolean(this.trustEdges);
|
LightUpdateData.write(out, this.lightData);
|
||||||
|
|
||||||
writeBitSet(out, this.skyYMask);
|
|
||||||
writeBitSet(out, this.blockYMask);
|
|
||||||
writeBitSet(out, this.emptySkyYMask);
|
|
||||||
writeBitSet(out, this.emptyBlockYMask);
|
|
||||||
|
|
||||||
out.writeVarInt(this.skyUpdates.size());
|
|
||||||
for (byte[] array : this.skyUpdates) {
|
|
||||||
out.writeVarInt(array.length);
|
|
||||||
out.writeBytes(array);
|
|
||||||
}
|
|
||||||
|
|
||||||
out.writeVarInt(this.blockUpdates.size());
|
|
||||||
for (byte[] array : this.blockUpdates) {
|
|
||||||
out.writeVarInt(array.length);
|
|
||||||
out.writeBytes(array);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPriority() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeBitSet(NetOutput out, BitSet bitSet) throws IOException {
|
|
||||||
long[] array = bitSet.toLongArray();
|
|
||||||
out.writeVarInt(array.length);
|
|
||||||
for (long content : array) {
|
|
||||||
out.writeLong(content);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.github.steveice10.mc.protocol.packet.ingame.clientbound.level;
|
||||||
|
|
||||||
|
import com.github.steveice10.packetlib.io.NetInput;
|
||||||
|
import com.github.steveice10.packetlib.io.NetOutput;
|
||||||
|
import com.github.steveice10.packetlib.packet.Packet;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.With;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@With
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ClientboundSetSimulationDistancePacket implements Packet {
|
||||||
|
private final int simulationDistance;
|
||||||
|
|
||||||
|
public ClientboundSetSimulationDistancePacket(NetInput in) throws IOException {
|
||||||
|
this.simulationDistance = in.readVarInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(NetOutput out) throws IOException {
|
||||||
|
out.writeVarInt(this.simulationDistance);
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,6 +27,10 @@ public class ServerboundClientInformationPacket implements Packet {
|
||||||
private final @NonNull List<SkinPart> visibleParts;
|
private final @NonNull List<SkinPart> visibleParts;
|
||||||
private final @NonNull HandPreference mainHand;
|
private final @NonNull HandPreference mainHand;
|
||||||
private final boolean textFilteringEnabled;
|
private final boolean textFilteringEnabled;
|
||||||
|
/**
|
||||||
|
* Whether the client permits being shown in server ping responses.
|
||||||
|
*/
|
||||||
|
private final boolean allowsListing;
|
||||||
|
|
||||||
public ServerboundClientInformationPacket(NetInput in) throws IOException {
|
public ServerboundClientInformationPacket(NetInput in) throws IOException {
|
||||||
this.locale = in.readString();
|
this.locale = in.readString();
|
||||||
|
@ -45,6 +49,7 @@ public class ServerboundClientInformationPacket implements Packet {
|
||||||
|
|
||||||
this.mainHand = MagicValues.key(HandPreference.class, in.readVarInt());
|
this.mainHand = MagicValues.key(HandPreference.class, in.readVarInt());
|
||||||
this.textFilteringEnabled = in.readBoolean();
|
this.textFilteringEnabled = in.readBoolean();
|
||||||
|
this.allowsListing = in.readBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -63,5 +68,6 @@ public class ServerboundClientInformationPacket implements Packet {
|
||||||
|
|
||||||
out.writeVarInt(MagicValues.value(Integer.class, this.mainHand));
|
out.writeVarInt(MagicValues.value(Integer.class, this.mainHand));
|
||||||
out.writeBoolean(this.textFilteringEnabled);
|
out.writeBoolean(this.textFilteringEnabled);
|
||||||
|
out.writeBoolean(allowsListing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class MinecraftProtocolTest {
|
||||||
Component.text("Hello world!"),
|
Component.text("Hello world!"),
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
private static final ClientboundLoginPacket JOIN_GAME_PACKET = new ClientboundLoginPacket(0, false, GameMode.SURVIVAL, GameMode.SURVIVAL, 1, new String[]{"minecraft:world"}, getDimensionTag(), getOverworldTag(), "minecraft:world", 100, 0, 16, false, false, false, false);
|
private static final ClientboundLoginPacket JOIN_GAME_PACKET = new ClientboundLoginPacket(0, false, GameMode.SURVIVAL, GameMode.SURVIVAL, 1, new String[]{"minecraft:world"}, getDimensionTag(), getOverworldTag(), "minecraft:world", 100, 0, 16, 16, false, false, false, false);
|
||||||
|
|
||||||
private static Server server;
|
private static Server server;
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ public abstract class PacketTest {
|
||||||
|
|
||||||
return constructor.newInstance(in);
|
return constructor.newInstance(in);
|
||||||
} catch (NoSuchMethodError e) {
|
} catch (NoSuchMethodError e) {
|
||||||
throw new IllegalStateException("Packet \"" + clazz.getName() + "\" does not have a no-params constructor for instantiation.");
|
throw new IllegalStateException("Packet \"" + clazz.getName() + "\" does not have a NetInput constructor for instantiation.");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IllegalStateException("Failed to instantiate packet \"" + clazz.getName() + "\".", e);
|
throw new IllegalStateException("Failed to instantiate packet \"" + clazz.getName() + "\".", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
package com.github.steveice10.mc.protocol.packet.ingame.clientbound.level;
|
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.chunk.Chunk;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.chunk.Column;
|
|
||||||
import com.github.steveice10.mc.protocol.packet.PacketTest;
|
|
||||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
|
||||||
import org.junit.Before;
|
|
||||||
|
|
||||||
public class ClientboundLevelChunkPacketTest extends PacketTest {
|
|
||||||
@Before
|
|
||||||
public void setup() {
|
|
||||||
Chunk chunk = new Chunk();
|
|
||||||
chunk.set(0, 0, 0, 10);
|
|
||||||
|
|
||||||
this.setPackets(
|
|
||||||
new ClientboundLevelChunkPacket(
|
|
||||||
new Column(0, 0, new Chunk[]{
|
|
||||||
null, null, null, null, null, null, null, chunk,
|
|
||||||
null, chunk, null, null, null, chunk, null, null, null, null, null, null, null, null, null,
|
|
||||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
|
|
||||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
|
|
||||||
null, null, null, null, null, null, null, null, null, null, null
|
|
||||||
}, new CompoundTag[0], new CompoundTag("HeightMaps"), new int[1024])
|
|
||||||
),
|
|
||||||
new ClientboundLevelChunkPacket(
|
|
||||||
new Column(1, 1, new Chunk[]{
|
|
||||||
chunk, chunk, chunk, chunk, chunk, chunk, chunk, chunk,
|
|
||||||
chunk, chunk, chunk, chunk, chunk, chunk, chunk, chunk, null, null, null, null, null,
|
|
||||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null,
|
|
||||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null,
|
|
||||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null
|
|
||||||
}, new CompoundTag[]{
|
|
||||||
new CompoundTag("TileEntity")
|
|
||||||
}, new CompoundTag("HeightMaps"), new int[1024])
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.github.steveice10.mc.protocol.packet.ingame.clientbound.level;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.chunk.Chunk;
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.level.LightUpdateData;
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo;
|
||||||
|
import com.github.steveice10.mc.protocol.packet.PacketTest;
|
||||||
|
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.BitSet;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
public class ClientboundLevelChunkWithLightPacketTest extends PacketTest {
|
||||||
|
@Before
|
||||||
|
public void setup() throws IOException {
|
||||||
|
Chunk chunk = new Chunk();
|
||||||
|
chunk.setBlock(0, 0, 0, 10);
|
||||||
|
|
||||||
|
this.setPackets(
|
||||||
|
new ClientboundLevelChunkWithLightPacket(0, 0,
|
||||||
|
new byte[0], new CompoundTag("HeightMaps"), new BlockEntityInfo[0],
|
||||||
|
new LightUpdateData(new BitSet(), new BitSet(), new BitSet(), new BitSet(), Collections.emptyList(), Collections.emptyList(), false)
|
||||||
|
),
|
||||||
|
new ClientboundLevelChunkWithLightPacket(1, 1,
|
||||||
|
new byte[256], new CompoundTag("HeightMaps"), new BlockEntityInfo[]{
|
||||||
|
new BlockEntityInfo(1, 0, 1, 0, null)
|
||||||
|
}, new LightUpdateData(new BitSet(), new BitSet(), new BitSet(), new BitSet(), Collections.emptyList(), Collections.emptyList(), true)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue