mirror of
https://github.com/GeyserMC/MCProtocolLib.git
synced 2024-11-14 19:34:58 -05:00
Properly implement block entity IDs and add tests
This commit is contained in:
parent
8b7386a46a
commit
ff76494a65
11 changed files with 144 additions and 41 deletions
|
@ -38,7 +38,6 @@ import com.github.steveice10.mc.protocol.data.game.level.block.BlockFace;
|
|||
import com.github.steveice10.mc.protocol.data.game.level.block.CommandBlockMode;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.StructureMirror;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.StructureRotation;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.value.ChestValueType;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.value.EndGatewayValueType;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.value.GenericBlockValueType;
|
||||
|
@ -597,21 +596,6 @@ public class MagicValues {
|
|||
|
||||
register(AnvilProperty.MAXIMUM_COST, 0);
|
||||
|
||||
register(BlockEntityType.MOB_SPAWNER, 1);
|
||||
register(BlockEntityType.COMMAND_BLOCK, 2);
|
||||
register(BlockEntityType.BEACON, 3);
|
||||
register(BlockEntityType.SKULL, 4);
|
||||
register(BlockEntityType.CONDUIT, 5);
|
||||
register(BlockEntityType.BANNER, 6);
|
||||
register(BlockEntityType.STRUCTURE_BLOCK, 7);
|
||||
register(BlockEntityType.END_GATEWAY, 8);
|
||||
register(BlockEntityType.SIGN, 9);
|
||||
register(BlockEntityType.SHULKER_BOX, 10);
|
||||
register(BlockEntityType.BED, 11);
|
||||
register(BlockEntityType.JIGSAW_BLOCK, 12);
|
||||
register(BlockEntityType.CAMPFIRE, 13);
|
||||
register(BlockEntityType.BEEHIVE, 14);
|
||||
|
||||
register(GameEvent.INVALID_BED, 0);
|
||||
register(GameEvent.STOP_RAIN, 1);
|
||||
register(GameEvent.START_RAIN, 2);
|
||||
|
|
|
@ -2,18 +2,14 @@ package com.github.steveice10.mc.protocol.data.game.chunk;
|
|||
|
||||
import com.github.steveice10.packetlib.io.NetInput;
|
||||
import com.github.steveice10.packetlib.io.NetOutput;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
import lombok.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Data
|
||||
@Setter(AccessLevel.NONE)
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
public class ChunkSection {
|
||||
private static final int MAX_PALETTE_BITS_PER_ENTRY = 8;
|
||||
private static final int MAX_BIOME_BITS_PER_ENTRY = 2;
|
||||
|
@ -26,7 +22,7 @@ public class ChunkSection {
|
|||
private @NonNull DataPalette biomeData;
|
||||
|
||||
public ChunkSection() {
|
||||
this(0, DataPalette.createEmpty(MAX_PALETTE_BITS_PER_ENTRY, DataPalette.CHUNK_SIZE), DataPalette.createEmpty(MAX_BIOME_BITS_PER_ENTRY, DataPalette.BIOME_SIZE));
|
||||
this(0, DataPalette.createForChunk(), DataPalette.createForBiome());
|
||||
}
|
||||
|
||||
public static ChunkSection read(NetInput in) throws IOException {
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.io.IOException;
|
|||
@Setter
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
@ToString
|
||||
public class DataPalette {
|
||||
static final int BIOME_SIZE = 64;
|
||||
static final int CHUNK_SIZE = 4096;
|
||||
|
@ -29,7 +30,7 @@ public class DataPalette {
|
|||
}
|
||||
|
||||
public static DataPalette createForBiome() {
|
||||
return createEmpty(MAX_BIOME_BITS_PER_ENTRY, CHUNK_SIZE);
|
||||
return createEmpty(MAX_BIOME_BITS_PER_ENTRY, BIOME_SIZE);
|
||||
}
|
||||
|
||||
public static DataPalette createEmpty(int maxBitsForType, int maxStorageSize) {
|
||||
|
@ -52,14 +53,15 @@ public class DataPalette {
|
|||
}
|
||||
|
||||
public static void write(NetOutput out, DataPalette palette) throws IOException {
|
||||
out.writeByte(palette.storage.getBitsPerEntry());
|
||||
|
||||
if (palette.palette instanceof SingletonPalette) {
|
||||
out.writeByte(0); // Bits per entry
|
||||
out.writeVarInt(palette.palette.idToState(0));
|
||||
out.writeVarInt(0); // Data length
|
||||
return;
|
||||
}
|
||||
|
||||
out.writeByte(palette.storage.getBitsPerEntry());
|
||||
|
||||
if (!(palette.palette instanceof GlobalPalette)) {
|
||||
int paletteLength = palette.palette.size();
|
||||
out.writeVarInt(paletteLength);
|
||||
|
|
|
@ -12,6 +12,6 @@ public class BlockEntityInfo {
|
|||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private final int id;
|
||||
private final BlockEntityType type;
|
||||
private final @Nullable CompoundTag nbt;
|
||||
}
|
||||
|
|
|
@ -1,18 +1,67 @@
|
|||
package com.github.steveice10.mc.protocol.data.game.level.block;
|
||||
|
||||
import com.github.steveice10.packetlib.io.NetInput;
|
||||
import com.github.steveice10.packetlib.io.NetOutput;
|
||||
import io.netty.util.collection.IntObjectHashMap;
|
||||
import io.netty.util.collection.IntObjectMap;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
|
||||
public enum BlockEntityType {
|
||||
FURNACE,
|
||||
CHEST,
|
||||
TRAPPED_CHEST,
|
||||
ENDER_CHEST,
|
||||
JUKEBOX,
|
||||
DISPENSER,
|
||||
DROPPER,
|
||||
SIGN,
|
||||
MOB_SPAWNER,
|
||||
COMMAND_BLOCK,
|
||||
PISTON,
|
||||
BREWING_STAND,
|
||||
ENCHANTING_TABLE,
|
||||
END_PORTAL,
|
||||
BEACON,
|
||||
SKULL,
|
||||
CONDUIT,
|
||||
DAYLIGHT_DETECTOR,
|
||||
HOPPER,
|
||||
COMPARATOR,
|
||||
BANNER,
|
||||
STRUCTURE_BLOCK,
|
||||
END_GATEWAY,
|
||||
SIGN,
|
||||
COMMAND_BLOCK,
|
||||
SHULKER_BOX,
|
||||
BED,
|
||||
JIGSAW_BLOCK,
|
||||
CONDUIT,
|
||||
BARREL,
|
||||
SMOKER,
|
||||
BLAST_FURNACE,
|
||||
LECTERN,
|
||||
BELL,
|
||||
JIGSAW,
|
||||
CAMPFIRE,
|
||||
BEEHIVE;
|
||||
BEEHIVE,
|
||||
SCULK_SENSOR;
|
||||
|
||||
private static final IntObjectMap<BlockEntityType> NETWORK_TO_BLOCK_ENTITY = new IntObjectHashMap<>();
|
||||
|
||||
static {
|
||||
for (BlockEntityType type : values()) {
|
||||
NETWORK_TO_BLOCK_ENTITY.put(type.ordinal(), type);
|
||||
}
|
||||
}
|
||||
|
||||
public static @Nonnull BlockEntityType read(NetInput in) throws IOException {
|
||||
int networkId = in.readVarInt();
|
||||
BlockEntityType type = NETWORK_TO_BLOCK_ENTITY.get(networkId);
|
||||
if (type == null) {
|
||||
throw new IllegalStateException("Cannot find type for network ID " + networkId);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public static void write(NetOutput out, @Nonnull BlockEntityType type) throws IOException {
|
||||
out.writeVarInt(type.ordinal());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.github.steveice10.mc.protocol.packet.ingame.clientbound.level;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.MagicValues;
|
||||
import com.github.steveice10.mc.protocol.data.game.NBT;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
|
||||
|
@ -25,14 +24,14 @@ public class ClientboundBlockEntityDataPacket implements Packet {
|
|||
|
||||
public ClientboundBlockEntityDataPacket(NetInput in) throws IOException {
|
||||
this.position = Position.read(in);
|
||||
this.type = MagicValues.key(BlockEntityType.class, in.readVarInt());
|
||||
this.type = BlockEntityType.read(in);
|
||||
this.nbt = NBT.read(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(NetOutput out) throws IOException {
|
||||
Position.write(out, this.position);
|
||||
out.writeVarInt(MagicValues.value(Integer.class, this.type));
|
||||
BlockEntityType.write(out, this.type);
|
||||
NBT.write(out, this.nbt);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ 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.mc.protocol.data.game.level.block.BlockEntityType;
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.packetlib.io.NetInput;
|
||||
import com.github.steveice10.packetlib.io.NetOutput;
|
||||
|
@ -37,7 +38,7 @@ public class ClientboundLevelChunkWithLightPacket implements Packet {
|
|||
int blockEntityX = (xz >> 4) & 15;
|
||||
int blockEntityZ = xz & 15;
|
||||
int blockEntityY = in.readShort();
|
||||
int type = in.readVarInt();
|
||||
BlockEntityType type = BlockEntityType.read(in);
|
||||
CompoundTag tag = NBT.read(in);
|
||||
this.blockEntities[i] = new BlockEntityInfo(blockEntityX, blockEntityY, blockEntityZ, type, tag);
|
||||
}
|
||||
|
@ -57,7 +58,7 @@ public class ClientboundLevelChunkWithLightPacket implements Packet {
|
|||
for (BlockEntityInfo blockEntity : this.blockEntities) {
|
||||
out.writeByte(((blockEntity.getX() & 15) << 4) | blockEntity.getZ() & 15);
|
||||
out.writeShort(blockEntity.getY());
|
||||
out.writeVarInt(blockEntity.getId());
|
||||
BlockEntityType.write(out, blockEntity.getType());
|
||||
NBT.write(out, blockEntity.getNbt());
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package com.github.steveice10.mc.protocol.data;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.chunk.ChunkSection;
|
||||
import com.github.steveice10.mc.protocol.data.game.chunk.DataPalette;
|
||||
import com.github.steveice10.mc.protocol.data.game.chunk.palette.SingletonPalette;
|
||||
import com.github.steveice10.packetlib.io.stream.StreamNetInput;
|
||||
import com.github.steveice10.packetlib.io.stream.StreamNetOutput;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ChunkTest {
|
||||
private final List<ChunkSection> chunkSectionsToTest = new ArrayList<>();
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
chunkSectionsToTest.add(new ChunkSection());
|
||||
|
||||
ChunkSection section = new ChunkSection();
|
||||
section.setBlock(0, 0, 0, 10);
|
||||
chunkSectionsToTest.add(section);
|
||||
|
||||
SingletonPalette singletonPalette = new SingletonPalette(20);
|
||||
DataPalette dataPalette = new DataPalette(singletonPalette, null, 8, 4096);
|
||||
DataPalette biomePalette = new DataPalette(singletonPalette, null, 2, 64);
|
||||
section = new ChunkSection(4096, dataPalette, biomePalette);
|
||||
chunkSectionsToTest.add(section);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChunkSectionEncoding() throws IOException {
|
||||
for (ChunkSection section : chunkSectionsToTest) {
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
StreamNetOutput out = new StreamNetOutput(stream);
|
||||
ChunkSection.write(out, section);
|
||||
StreamNetInput in = new StreamNetInput(new ByteArrayInputStream(stream.toByteArray()));
|
||||
ChunkSection decoded;
|
||||
try {
|
||||
decoded = ChunkSection.read(in);
|
||||
} catch (Exception e) {
|
||||
System.out.println(section);
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
Assert.assertEquals("Decoded packet does not match original: " + section + " vs " + decoded, section, decoded);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -38,7 +38,6 @@ import com.github.steveice10.mc.protocol.data.game.level.block.BlockFace;
|
|||
import com.github.steveice10.mc.protocol.data.game.level.block.CommandBlockMode;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.StructureMirror;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.StructureRotation;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.value.ChestValueType;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.value.EndGatewayValueType;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.value.GenericBlockValueType;
|
||||
|
@ -147,7 +146,6 @@ public class MagicValuesTest {
|
|||
this.register(EnchantmentTableProperty.class, Integer.class);
|
||||
this.register(FurnaceProperty.class, Integer.class);
|
||||
this.register(AnvilProperty.class, Integer.class);
|
||||
this.register(BlockEntityType.class, Integer.class);
|
||||
this.register(GameEvent.class, Integer.class);
|
||||
this.register(CommandBlockMode.class, Integer.class);
|
||||
this.register(UpdateStructureBlockAction.class, Integer.class);
|
||||
|
|
|
@ -1,14 +1,33 @@
|
|||
package com.github.steveice10.mc.protocol.data;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.Effect;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
|
||||
import com.github.steveice10.packetlib.io.stream.StreamNetInput;
|
||||
import com.github.steveice10.packetlib.io.stream.StreamNetOutput;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Miscellaneous tests for reading and writing classes to/from the network
|
||||
*/
|
||||
public class NetworkDataTests {
|
||||
|
||||
@Test
|
||||
public void testBlockEntities() throws IOException {
|
||||
for (BlockEntityType type : BlockEntityType.values()) {
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
StreamNetOutput out = new StreamNetOutput(stream);
|
||||
BlockEntityType.write(out, type);
|
||||
StreamNetInput in = new StreamNetInput(new ByteArrayInputStream(stream.toByteArray()));
|
||||
|
||||
Assert.assertEquals(type, BlockEntityType.read(in));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEffects() {
|
||||
for (Effect effect : Effect.VALUES) {
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.github.steveice10.mc.protocol.packet.ingame.clientbound.level;
|
|||
|
||||
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.data.game.level.block.BlockEntityType;
|
||||
import com.github.steveice10.mc.protocol.packet.PacketTest;
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import org.junit.Before;
|
||||
|
@ -19,8 +20,8 @@ public class ClientboundLevelChunkWithLightPacketTest extends PacketTest {
|
|||
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 byte[256], new CompoundTag("HeightMaps"), new BlockEntityInfo[] {
|
||||
new BlockEntityInfo(1, 0, 1, BlockEntityType.CHEST, null)
|
||||
}, new LightUpdateData(new BitSet(), new BitSet(), new BitSet(), new BitSet(), Collections.emptyList(), Collections.emptyList(), true)
|
||||
)
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue