diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSection.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSection.java index 814a122fe..06b5cdd0c 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSection.java +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSection.java @@ -117,13 +117,10 @@ public class ChunkSection { } public int getPaletteEntry(int index) { - if (index < 0 || index >= palette.size()) throw new IndexOutOfBoundsException(); return palette.getInt(index); } public void setPaletteEntry(int index, int id) { - if (index < 0 || index >= palette.size()) throw new IndexOutOfBoundsException(); - int oldId = palette.set(index, id); if (oldId == id) return; diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_17to1_16_4/Protocol1_17To1_16_4.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_17to1_16_4/Protocol1_17To1_16_4.java index e81837a93..6e34b57c1 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_17to1_16_4/Protocol1_17To1_16_4.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_17to1_16_4/Protocol1_17To1_16_4.java @@ -31,7 +31,6 @@ import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.metadata.Metadat import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.packets.EntityPackets; import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.packets.InventoryPackets; import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.packets.WorldPackets; -import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.storage.BiomeStorage; import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.storage.EntityTracker1_17; import com.viaversion.viaversion.rewriter.MetadataRewriter; import com.viaversion.viaversion.rewriter.RegistryType; @@ -235,7 +234,6 @@ public class Protocol1_17To1_16_4 extends AbstractProtocol { Chunk chunk = wrapper.read(new Chunk1_16_2Type()); + if (!chunk.isFullChunk()) { + // All chunks are full chunk packets now (1.16 already stopped sending non-full chunks) + // Construct multi block change packets instead + writeMultiBlockChangePacket(wrapper, chunk); + wrapper.cancel(); + return; + } + + // Normal full chunk writing wrapper.write(new Chunk1_17Type(chunk.getSections().length), chunk); // 1.17 uses a bitset for the mask chunk.setChunkMask(BitSet.valueOf(new long[]{chunk.getBitmask()})); - BiomeStorage biomeStorage = wrapper.user().get(BiomeStorage.class); - if (chunk.isFullChunk()) { - biomeStorage.setBiomes(chunk.getX(), chunk.getZ(), chunk.getBiomeData()); - } else { - // Biomes always have to be sent now - int[] biomes = biomeStorage.getBiomes(chunk.getX(), chunk.getZ()); - if (biomes != null) { - chunk.setBiomeData(biomes); - } else { - Via.getPlatform().getLogger().warning("Biome data not found for chunk at " + chunk.getX() + ", " + chunk.getZ()); - chunk.setBiomeData(new int[chunk.getSections().length * 64]); - } - } - for (int s = 0; s < chunk.getSections().length; s++) { ChunkSection section = chunk.getSections()[s]; if (section == null) continue; @@ -190,11 +185,7 @@ public class WorldPackets { CompoundTag currentDimensionTag = wrapper.get(Type.NBT, 1); addNewDimensionData(currentDimensionTag); - // Tracking - String world = wrapper.passthrough(Type.STRING); - UserConnection user = wrapper.user(); - user.get(BiomeStorage.class).setWorld(world); user.get(EntityTracker1_17.class).addEntity(wrapper.get(Type.INT, 0), Entity1_17Types.PLAYER); }); } @@ -206,25 +197,6 @@ public class WorldPackets { handler(wrapper -> { CompoundTag dimensionData = wrapper.passthrough(Type.NBT); addNewDimensionData(dimensionData); - - String world = wrapper.passthrough(Type.STRING); - BiomeStorage biomeStorage = wrapper.user().get(BiomeStorage.class); - if (!world.equals(biomeStorage.getWorld())) { - biomeStorage.clearBiomes(); - } - - biomeStorage.setWorld(world); - }); - } - }); - - protocol.registerClientbound(ClientboundPackets1_16_2.UNLOAD_CHUNK, new PacketRemapper() { - @Override - public void registerMap() { - handler(wrapper -> { - int x = wrapper.passthrough(Type.INT); - int z = wrapper.passthrough(Type.INT); - wrapper.user().get(BiomeStorage.class).clearBiomes(x, z); }); } }); @@ -232,6 +204,36 @@ public class WorldPackets { blockRewriter.registerEffect(ClientboundPackets1_16_2.EFFECT, 1010, 2001); } + private static void writeMultiBlockChangePacket(PacketWrapper wrapper, Chunk chunk) throws Exception { + long chunkPosition = (chunk.getX() & 0x3FFFFFL) << 42; + chunkPosition |= (chunk.getZ() & 0x3FFFFFL) << 20; + + ChunkSection[] sections = chunk.getSections(); + for (int chunkY = 0; chunkY < sections.length; chunkY++) { + ChunkSection section = sections[chunkY]; + if (section == null) continue; + + PacketWrapper blockChangePacket = wrapper.create(ClientboundPackets1_17.MULTI_BLOCK_CHANGE); + blockChangePacket.write(Type.LONG, chunkPosition | (chunkY & 0xFFFFFL)); + blockChangePacket.write(Type.BOOLEAN, true); // Suppress light updates + + //TODO this can be optimized + BlockChangeRecord[] blockChangeRecords = new BlockChangeRecord[4096]; + int j = 0; + for (int x = 0; x < 16; x++) { + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + int blockStateId = Protocol1_17To1_16_4.MAPPINGS.getNewBlockStateId(section.getFlatBlock(x, y, z)); + blockChangeRecords[j++] = new BlockChangeRecord1_16_2(x, y, z, blockStateId); + } + } + } + + blockChangePacket.write(Type.VAR_LONG_BLOCK_CHANGE_RECORD_ARRAY, blockChangeRecords); + blockChangePacket.send(Protocol1_17To1_16_4.class, true, true); + } + } + private static void addNewDimensionData(CompoundTag tag) { tag.put("min_y", new IntTag(0)); tag.put("height", new IntTag(256)); diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_17to1_16_4/storage/BiomeStorage.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_17to1_16_4/storage/BiomeStorage.java deleted file mode 100644 index 04bb620cd..000000000 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_17to1_16_4/storage/BiomeStorage.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion - * Copyright (C) 2016-2021 ViaVersion and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.viaversion.viaversion.protocols.protocol1_17to1_16_4.storage; - -import com.viaversion.viaversion.api.connection.StoredObject; -import com.viaversion.viaversion.api.connection.UserConnection; -import org.checkerframework.checker.nullness.qual.Nullable; - -import java.util.HashMap; -import java.util.Map; - -public class BiomeStorage extends StoredObject { - - private final Map chunkBiomes = new HashMap<>(); - private String world; - - public BiomeStorage(UserConnection user) { - super(user); - } - - public @Nullable String getWorld() { - return world; - } - - public void setWorld(String world) { - this.world = world; - } - - public int @Nullable [] getBiomes(int x, int z) { - return chunkBiomes.get(getChunkSectionIndex(x, z)); - } - - public void setBiomes(int x, int z, int[] biomes) { - chunkBiomes.put(getChunkSectionIndex(x, z), biomes); - } - - public void clearBiomes(int x, int z) { - chunkBiomes.remove(getChunkSectionIndex(x, z)); - } - - public void clearBiomes() { - chunkBiomes.clear(); - } - - private long getChunkSectionIndex(int x, int z) { - return ((x & 0x3FFFFFFL) << 38) | (z & 0x3FFFFFFL); - } -}