mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Gracefully handle invalid block entity types
This commit is contained in:
parent
295e71627b
commit
75d1a6364c
4 changed files with 26 additions and 26 deletions
|
@ -155,7 +155,7 @@
|
|||
<dependency>
|
||||
<groupId>com.github.GeyserMC</groupId>
|
||||
<artifactId>MCProtocolLib</artifactId>
|
||||
<version>ed29b72</version>
|
||||
<version>6edba11</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
|
|
@ -35,7 +35,7 @@ import org.geysermc.geyser.translator.text.MessageTranslator;
|
|||
public class CommandBlockBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
|
||||
@Override
|
||||
public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
|
||||
if (tag.size() < 5) {
|
||||
if (tag == null || tag.size() < 5) {
|
||||
return; // These values aren't here
|
||||
}
|
||||
// Java infers from the block state, but Bedrock needs it in the tag
|
||||
|
|
|
@ -46,7 +46,11 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator<ClientboundB
|
|||
|
||||
@Override
|
||||
public void translate(GeyserSession session, ClientboundBlockEntityDataPacket packet) {
|
||||
BlockEntityTranslator translator = BlockEntityUtils.getBlockEntityTranslator(packet.getType());
|
||||
final BlockEntityType type = packet.getType();
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
BlockEntityTranslator translator = BlockEntityUtils.getBlockEntityTranslator(type);
|
||||
// The Java block state is used in BlockEntityTranslator.translateTag() to make up for some inconsistencies
|
||||
// between Java block states and Bedrock block entity data
|
||||
int blockState;
|
||||
|
@ -57,7 +61,7 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator<ClientboundB
|
|||
}
|
||||
|
||||
Position position = packet.getPosition();
|
||||
BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(packet.getType(), position.getX(), position.getY(), position.getZ(),
|
||||
BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(type, position.getX(), position.getY(), position.getZ(),
|
||||
packet.getNbt(), blockState), packet.getPosition());
|
||||
// Check for custom skulls.
|
||||
if (session.getPreferencesCache().showCustomSkulls() && packet.getNbt() != null && packet.getNbt().contains("SkullOwner")) {
|
||||
|
@ -66,7 +70,7 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator<ClientboundB
|
|||
|
||||
// If block entity is command block, OP permission level is appropriate, player is in creative mode and the NBT is not empty
|
||||
// TODO 1.18 re-test
|
||||
if (packet.getType() == BlockEntityType.COMMAND_BLOCK && session.getOpPermissionLevel() >= 2 &&
|
||||
if (type == BlockEntityType.COMMAND_BLOCK && session.getOpPermissionLevel() >= 2 &&
|
||||
session.getGameMode() == GameMode.CREATIVE && packet.getNbt() != null && packet.getNbt().size() > 5) {
|
||||
ContainerOpenPacket openPacket = new ContainerOpenPacket();
|
||||
openPacket.setBlockPosition(Vector3i.from(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()));
|
||||
|
|
|
@ -50,6 +50,7 @@ import io.netty.buffer.ByteBufOutputStream;
|
|||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import it.unimi.dsi.fastutil.ints.IntLists;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import org.geysermc.geyser.entity.type.ItemFrameEntity;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
|
@ -88,11 +89,12 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||
int chunkSize = session.getChunkCache().getChunkHeightY();
|
||||
int biomeGlobalPalette = session.getBiomeGlobalPalette();
|
||||
|
||||
// Temporarily stores compound tags of Bedrock-only block entities
|
||||
List<NbtMap> bedrockOnlyBlockEntities = new ArrayList<>();
|
||||
DataPalette[] javaChunks = new DataPalette[chunkSize];
|
||||
DataPalette[] javaBiomes = new DataPalette[chunkSize];
|
||||
|
||||
final BlockEntityInfo[] blockEntities = packet.getBlockEntities();
|
||||
final List<NbtMap> bedrockBlockEntities = new ObjectArrayList<>(blockEntities.length);
|
||||
|
||||
BitSet waterloggedPaletteIds = new BitSet();
|
||||
BitSet pistonOrFlowerPaletteIds = new BitSet();
|
||||
|
||||
|
@ -140,7 +142,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||
|
||||
// Check if block is piston or flower to see if we'll need to create additional block entities, as they're only block entities in Bedrock
|
||||
if (BlockStateValues.getFlowerPotValues().containsKey(javaId) || BlockStateValues.getPistonValues().containsKey(javaId)) {
|
||||
bedrockOnlyBlockEntities.add(BedrockOnlyBlockEntity.getTag(session,
|
||||
bedrockBlockEntities.add(BedrockOnlyBlockEntity.getTag(session,
|
||||
Vector3i.from((packet.getX() << 4) + (yzx & 0xF), ((sectionY + yOffset) << 4) + ((yzx >> 8) & 0xF), (packet.getZ() << 4) + ((yzx >> 4) & 0xF)),
|
||||
javaId
|
||||
));
|
||||
|
@ -192,7 +194,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||
for (int yzx = 0; yzx < BlockStorage.SIZE; yzx++) {
|
||||
int paletteId = javaData.get(yzx);
|
||||
if (pistonOrFlowerPaletteIds.get(paletteId)) {
|
||||
bedrockOnlyBlockEntities.add(BedrockOnlyBlockEntity.getTag(session,
|
||||
bedrockBlockEntities.add(BedrockOnlyBlockEntity.getTag(session,
|
||||
Vector3i.from((packet.getX() << 4) + (yzx & 0xF), ((sectionY + yOffset) << 4) + ((yzx >> 8) & 0xF), (packet.getZ() << 4) + ((yzx >> 4) & 0xF)),
|
||||
javaPalette.idToState(paletteId)
|
||||
));
|
||||
|
@ -240,15 +242,16 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||
|
||||
session.getChunkCache().addToCache(packet.getX(), packet.getZ(), javaChunks);
|
||||
|
||||
BlockEntityInfo[] blockEntities = packet.getBlockEntities();
|
||||
NbtMap[] bedrockBlockEntities = new NbtMap[blockEntities.length + bedrockOnlyBlockEntities.size()];
|
||||
int blockEntityCount = 0;
|
||||
final int chunkBlockX = packet.getX() << 4;
|
||||
final int chunkBlockZ = packet.getZ() << 4;
|
||||
while (blockEntityCount < blockEntities.length) {
|
||||
BlockEntityInfo blockEntity = blockEntities[blockEntityCount];
|
||||
CompoundTag tag = blockEntity.getNbt();
|
||||
for (BlockEntityInfo blockEntity : blockEntities) {
|
||||
BlockEntityType type = blockEntity.getType();
|
||||
if (type == null) {
|
||||
// As an example: ViaVersion will send -1 if it cannot find the block entity type
|
||||
// Vanilla Minecraft gracefully handles this
|
||||
continue;
|
||||
}
|
||||
CompoundTag tag = blockEntity.getNbt();
|
||||
int x = blockEntity.getX(); // Relative to chunk
|
||||
int y = blockEntity.getY();
|
||||
int z = blockEntity.getZ(); // Relative to chunk
|
||||
|
@ -259,25 +262,18 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||
|
||||
if (type == BlockEntityType.LECTERN && BlockStateValues.getLecternBookStates().get(blockState)) {
|
||||
// If getLecternBookStates is false, let's just treat it like a normal block entity
|
||||
bedrockBlockEntities[blockEntityCount++] = session.getGeyser().getWorldManager().getLecternDataAt(
|
||||
session, x + chunkBlockX, y, z + chunkBlockZ, true);
|
||||
bedrockBlockEntities.add(session.getGeyser().getWorldManager().getLecternDataAt(
|
||||
session, x + chunkBlockX, y, z + chunkBlockZ, true));
|
||||
continue;
|
||||
}
|
||||
|
||||
BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(type);
|
||||
bedrockBlockEntities[blockEntityCount] = blockEntityTranslator.getBlockEntityTag(type, x + chunkBlockX, y, z + chunkBlockZ, tag, blockState);
|
||||
bedrockBlockEntities.add(blockEntityTranslator.getBlockEntityTag(type, x + chunkBlockX, y, z + chunkBlockZ, tag, blockState));
|
||||
|
||||
// Check for custom skulls
|
||||
if (session.getPreferencesCache().showCustomSkulls() && type == BlockEntityType.SKULL && tag != null && tag.contains("SkullOwner")) {
|
||||
SkullBlockEntityTranslator.spawnPlayer(session, tag, x + chunkBlockX, y, z + chunkBlockZ, blockState);
|
||||
}
|
||||
blockEntityCount++;
|
||||
}
|
||||
|
||||
// Append Bedrock-exclusive block entities to output array
|
||||
for (NbtMap tag : bedrockOnlyBlockEntities) {
|
||||
bedrockBlockEntities[blockEntityCount] = tag;
|
||||
blockEntityCount++;
|
||||
}
|
||||
|
||||
// Find highest section
|
||||
|
@ -300,7 +296,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||
size += ChunkUtils.EMPTY_CHUNK_DATA.length; // Consists only of biome data
|
||||
size += 1; // Border blocks
|
||||
size += 1; // Extra data length (always 0)
|
||||
size += bedrockBlockEntities.length * 64; // Conservative estimate of 64 bytes per tile entity
|
||||
size += bedrockBlockEntities.size() * 64; // Conservative estimate of 64 bytes per tile entity
|
||||
|
||||
// Allocate output buffer
|
||||
byteBuf = ByteBufAllocator.DEFAULT.buffer(size);
|
||||
|
|
Loading…
Reference in a new issue