Remove invalid chunk entities for 1.20.5 clients

Fixes #3804
This commit is contained in:
Nassim Jahnke 2024-05-14 18:47:57 +02:00
parent 7e268a6f87
commit 2d41eb52a6
No known key found for this signature in database
GPG Key ID: EF6771C01F6EF02F
2 changed files with 51 additions and 19 deletions

View File

@ -35,6 +35,8 @@ import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
@ -137,10 +139,27 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
blockRewriter.registerBlockChange(ClientboundPackets1_20_3.BLOCK_CHANGE);
blockRewriter.registerVarLongMultiBlockChange1_20(ClientboundPackets1_20_3.MULTI_BLOCK_CHANGE);
blockRewriter.registerEffect(ClientboundPackets1_20_3.EFFECT, 1010, 2001);
blockRewriter.registerChunkData1_19(ClientboundPackets1_20_3.CHUNK_DATA, ChunkType1_20_2::new, (user, blockEntity) -> updateBlockEntityTag(user, null, blockEntity.tag()));
protocol.registerClientbound(ClientboundPackets1_20_3.CHUNK_DATA, wrapper -> {
final Chunk chunk = blockRewriter.handleChunk1_19(wrapper, ChunkType1_20_2::new);
for (int i = 0; i < chunk.blockEntities().size(); i++) {
final BlockEntity blockEntity = chunk.blockEntities().get(i);
if (isUnknownBlockEntity(blockEntity.typeId())) {
// The client no longer ignores unknown block entities
chunk.blockEntities().remove(i--);
continue;
}
updateBlockEntityTag(wrapper.user(), null, blockEntity.tag());
}
});
protocol.registerClientbound(ClientboundPackets1_20_3.BLOCK_ENTITY_DATA, wrapper -> {
wrapper.passthrough(Type.POSITION1_14); // Position
wrapper.passthrough(Type.VAR_INT); // Block entity type
final int typeId = wrapper.passthrough(Type.VAR_INT);
if (isUnknownBlockEntity(typeId)) {
wrapper.cancel();
return;
}
CompoundTag tag = wrapper.read(Type.COMPOUND_TAG);
if (tag != null) {
@ -1346,6 +1365,10 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
}
}
private boolean isUnknownBlockEntity(final int id) {
return id < 0 || id > 42;
}
private void updateBlockEntityTag(final UserConnection connection, @Nullable final StructuredDataContainer data, final CompoundTag tag) {
if (tag == null) {
return;

View File

@ -32,6 +32,7 @@ import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
@ -186,28 +187,18 @@ public class BlockRewriter<C extends ClientboundPacketType> {
public PacketHandler chunkDataHandler1_19(ChunkTypeSupplier chunkTypeSupplier, @Nullable BiConsumer<UserConnection, BlockEntity> blockEntityHandler) {
return wrapper -> {
final EntityTracker tracker = protocol.getEntityRewriter().tracker(wrapper.user());
Preconditions.checkArgument(tracker.biomesSent() != -1, "Biome count not set");
Preconditions.checkArgument(tracker.currentWorldSectionHeight() != -1, "Section height not set");
final Type<Chunk> chunkType = chunkTypeSupplier.supply(tracker.currentWorldSectionHeight(),
MathUtil.ceilLog2(protocol.getMappingData().getBlockStateMappings().mappedSize()),
MathUtil.ceilLog2(tracker.biomesSent()));
final Chunk chunk = wrapper.passthrough(chunkType);
for (final ChunkSection section : chunk.getSections()) {
final DataPalette blockPalette = section.palette(PaletteType.BLOCKS);
for (int i = 0; i < blockPalette.size(); i++) {
final int id = blockPalette.idByIndex(i);
blockPalette.setIdByIndex(i, protocol.getMappingData().getNewBlockStateId(id));
}
}
final Chunk chunk = handleChunk1_19(wrapper, chunkTypeSupplier);
final Mappings blockEntityMappings = protocol.getMappingData().getBlockEntityMappings();
if (blockEntityMappings != null || blockEntityHandler != null) {
List<BlockEntity> blockEntities = chunk.blockEntities();
final List<BlockEntity> blockEntities = chunk.blockEntities();
for (int i = 0; i < blockEntities.size(); i++) {
final BlockEntity blockEntity = blockEntities.get(i);
if (blockEntityMappings != null) {
blockEntities.set(i, blockEntity.withTypeId(blockEntityMappings.getNewIdOrDefault(blockEntity.typeId(), blockEntity.typeId())));
final int id = blockEntity.typeId();
final int mappedId = blockEntityMappings.getNewIdOrDefault(id, id);
if (id != mappedId) {
blockEntities.set(i, blockEntity.withTypeId(mappedId));
}
}
if (blockEntityHandler != null && blockEntity.tag() != null) {
@ -218,6 +209,24 @@ public class BlockRewriter<C extends ClientboundPacketType> {
};
}
public Chunk handleChunk1_19(PacketWrapper wrapper, ChunkTypeSupplier chunkTypeSupplier) throws Exception {
final EntityTracker tracker = protocol.getEntityRewriter().tracker(wrapper.user());
Preconditions.checkArgument(tracker.biomesSent() != -1, "Biome count not set");
Preconditions.checkArgument(tracker.currentWorldSectionHeight() != -1, "Section height not set");
final Type<Chunk> chunkType = chunkTypeSupplier.supply(tracker.currentWorldSectionHeight(),
MathUtil.ceilLog2(protocol.getMappingData().getBlockStateMappings().mappedSize()),
MathUtil.ceilLog2(tracker.biomesSent()));
final Chunk chunk = wrapper.passthrough(chunkType);
for (final ChunkSection section : chunk.getSections()) {
final DataPalette blockPalette = section.palette(PaletteType.BLOCKS);
for (int i = 0; i < blockPalette.size(); i++) {
final int id = blockPalette.idByIndex(i);
blockPalette.setIdByIndex(i, protocol.getMappingData().getNewBlockStateId(id));
}
}
return chunk;
}
public void registerBlockEntityData(C packetType) {
registerBlockEntityData(packetType, null);
}