Search in sources :

Example 26 with ChunkSection

use of com.viaversion.viaversion.api.minecraft.chunks.ChunkSection in project ViaBackwards by ViaVersion.

the class BlockItemPackets1_18 method registerPackets.

@Override
protected void registerPackets() {
    new RecipeRewriter1_16(protocol).registerDefaultHandler(ClientboundPackets1_18.DECLARE_RECIPES);
    registerSetCooldown(ClientboundPackets1_18.COOLDOWN);
    registerWindowItems1_17_1(ClientboundPackets1_18.WINDOW_ITEMS, Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT, Type.FLAT_VAR_INT_ITEM);
    registerSetSlot1_17_1(ClientboundPackets1_18.SET_SLOT, Type.FLAT_VAR_INT_ITEM);
    registerEntityEquipmentArray(ClientboundPackets1_18.ENTITY_EQUIPMENT, Type.FLAT_VAR_INT_ITEM);
    registerTradeList(ClientboundPackets1_18.TRADE_LIST, Type.FLAT_VAR_INT_ITEM);
    registerAdvancements(ClientboundPackets1_18.ADVANCEMENTS, Type.FLAT_VAR_INT_ITEM);
    registerClickWindow1_17_1(ServerboundPackets1_17.CLICK_WINDOW, Type.FLAT_VAR_INT_ITEM);
    protocol.registerClientbound(ClientboundPackets1_18.EFFECT, new PacketRemapper() {

        @Override
        public void registerMap() {
            // Effect id
            map(Type.INT);
            // Location
            map(Type.POSITION1_14);
            // Data
            map(Type.INT);
            handler(wrapper -> {
                int id = wrapper.get(Type.INT, 0);
                int data = wrapper.get(Type.INT, 1);
                if (id == 1010) {
                    // Play record
                    wrapper.set(Type.INT, 1, protocol.getMappingData().getNewItemId(data));
                }
            });
        }
    });
    registerCreativeInvAction(ServerboundPackets1_17.CREATIVE_INVENTORY_ACTION, Type.FLAT_VAR_INT_ITEM);
    protocol.registerClientbound(ClientboundPackets1_18.SPAWN_PARTICLE, new PacketRemapper() {

        @Override
        public void registerMap() {
            // Particle id
            map(Type.INT);
            // Override limiter
            map(Type.BOOLEAN);
            // X
            map(Type.DOUBLE);
            // Y
            map(Type.DOUBLE);
            // Z
            map(Type.DOUBLE);
            // Offset X
            map(Type.FLOAT);
            // Offset Y
            map(Type.FLOAT);
            // Offset Z
            map(Type.FLOAT);
            // Max speed
            map(Type.FLOAT);
            // Particle Count
            map(Type.INT);
            handler(wrapper -> {
                int id = wrapper.get(Type.INT, 0);
                if (id == 3) {
                    // Block marker
                    int blockState = wrapper.read(Type.VAR_INT);
                    if (blockState == 7786) {
                        // Light block
                        wrapper.set(Type.INT, 0, 3);
                    } else {
                        // Else assume barrier block
                        wrapper.set(Type.INT, 0, 2);
                    }
                    return;
                }
                ParticleMappings mappings = protocol.getMappingData().getParticleMappings();
                if (mappings.isBlockParticle(id)) {
                    int data = wrapper.passthrough(Type.VAR_INT);
                    wrapper.set(Type.VAR_INT, 0, protocol.getMappingData().getNewBlockStateId(data));
                } else if (mappings.isItemParticle(id)) {
                    handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM));
                }
                int newId = protocol.getMappingData().getNewParticleId(id);
                if (newId != id) {
                    wrapper.set(Type.INT, 0, newId);
                }
            });
        }
    });
    protocol.registerClientbound(ClientboundPackets1_18.BLOCK_ENTITY_DATA, new PacketRemapper() {

        @Override
        public void registerMap() {
            map(Type.POSITION1_14);
            handler(wrapper -> {
                final int id = wrapper.read(Type.VAR_INT);
                final CompoundTag tag = wrapper.read(Type.NBT);
                final int mappedId = BlockEntityIds.mappedId(id);
                if (mappedId == -1) {
                    wrapper.cancel();
                    return;
                }
                final String identifier = protocol.getMappingData().blockEntities().get(id);
                if (identifier == null) {
                    wrapper.cancel();
                    return;
                }
                // The 1.18 server doesn't include the id and positions (x, y, z) in the NBT anymore
                // If those were the only fields on the block entity (e.g.: skull, bed), we'll receive a null NBT
                // We initialize one and add the missing fields, so it can be handled correctly down the line
                final CompoundTag newTag = tag == null ? new CompoundTag() : tag;
                final Position pos = wrapper.get(Type.POSITION1_14, 0);
                // The protocol converters downstream rely on this field, let's add it back
                newTag.put("id", new StringTag("minecraft:" + identifier));
                // Weird glitches happen with the 1.17 client and below if these fields are missing
                // Some examples are block entity models becoming invisible (e.g.: signs, banners)
                newTag.put("x", new IntTag(pos.x()));
                newTag.put("y", new IntTag(pos.y()));
                newTag.put("z", new IntTag(pos.z()));
                handleSpawner(id, newTag);
                wrapper.write(Type.UNSIGNED_BYTE, (short) mappedId);
                wrapper.write(Type.NBT, newTag);
            });
        }
    });
    protocol.registerClientbound(ClientboundPackets1_18.CHUNK_DATA, new PacketRemapper() {

        @Override
        public void registerMap() {
            handler(wrapper -> {
                final EntityTracker tracker = protocol.getEntityRewriter().tracker(wrapper.user());
                final Chunk1_18Type chunkType = new Chunk1_18Type(tracker.currentWorldSectionHeight(), MathUtil.ceilLog2(protocol.getMappingData().getBlockStateMappings().size()), MathUtil.ceilLog2(tracker.biomesSent()));
                final Chunk oldChunk = wrapper.read(chunkType);
                final ChunkSection[] sections = oldChunk.getSections();
                final BitSet mask = new BitSet(oldChunk.getSections().length);
                final int[] biomeData = new int[sections.length * ChunkSection.BIOME_SIZE];
                int biomeIndex = 0;
                for (int j = 0; j < sections.length; j++) {
                    final ChunkSection section = sections[j];
                    // Write biome palette into biome array
                    final DataPalette biomePalette = section.palette(PaletteType.BIOMES);
                    for (int i = 0; i < ChunkSection.BIOME_SIZE; i++) {
                        biomeData[biomeIndex++] = biomePalette.idAt(i);
                    }
                    // Rewrite to empty section
                    if (section.getNonAirBlocksCount() == 0) {
                        sections[j] = null;
                    } else {
                        mask.set(j);
                    }
                }
                final List<CompoundTag> blockEntityTags = new ArrayList<>(oldChunk.blockEntities().size());
                for (final BlockEntity blockEntity : oldChunk.blockEntities()) {
                    final String id = protocol.getMappingData().blockEntities().get(blockEntity.typeId());
                    if (id == null) {
                        // Shrug
                        continue;
                    }
                    final CompoundTag tag;
                    if (blockEntity.tag() != null) {
                        tag = blockEntity.tag();
                        handleSpawner(blockEntity.typeId(), tag);
                    } else {
                        tag = new CompoundTag();
                    }
                    blockEntityTags.add(tag);
                    tag.put("x", new IntTag((oldChunk.getX() << 4) + blockEntity.sectionX()));
                    tag.put("y", new IntTag(blockEntity.y()));
                    tag.put("z", new IntTag((oldChunk.getZ() << 4) + blockEntity.sectionZ()));
                    tag.put("id", new StringTag("minecraft:" + id));
                }
                final Chunk chunk = new BaseChunk(oldChunk.getX(), oldChunk.getZ(), true, false, mask, oldChunk.getSections(), biomeData, oldChunk.getHeightMap(), blockEntityTags);
                wrapper.write(new Chunk1_17Type(tracker.currentWorldSectionHeight()), chunk);
                // Create and send light packet first
                final PacketWrapper lightPacket = wrapper.create(ClientboundPackets1_17_1.UPDATE_LIGHT);
                lightPacket.write(Type.VAR_INT, chunk.getX());
                lightPacket.write(Type.VAR_INT, chunk.getZ());
                // Trust edges
                lightPacket.write(Type.BOOLEAN, wrapper.read(Type.BOOLEAN));
                // Sky light mask
                lightPacket.write(Type.LONG_ARRAY_PRIMITIVE, wrapper.read(Type.LONG_ARRAY_PRIMITIVE));
                // Block light mask
                lightPacket.write(Type.LONG_ARRAY_PRIMITIVE, wrapper.read(Type.LONG_ARRAY_PRIMITIVE));
                // Empty sky light mask
                lightPacket.write(Type.LONG_ARRAY_PRIMITIVE, wrapper.read(Type.LONG_ARRAY_PRIMITIVE));
                // Empty block light mask
                lightPacket.write(Type.LONG_ARRAY_PRIMITIVE, wrapper.read(Type.LONG_ARRAY_PRIMITIVE));
                final int skyLightLength = wrapper.read(Type.VAR_INT);
                lightPacket.write(Type.VAR_INT, skyLightLength);
                for (int i = 0; i < skyLightLength; i++) {
                    lightPacket.write(Type.BYTE_ARRAY_PRIMITIVE, wrapper.read(Type.BYTE_ARRAY_PRIMITIVE));
                }
                final int blockLightLength = wrapper.read(Type.VAR_INT);
                lightPacket.write(Type.VAR_INT, blockLightLength);
                for (int i = 0; i < blockLightLength; i++) {
                    lightPacket.write(Type.BYTE_ARRAY_PRIMITIVE, wrapper.read(Type.BYTE_ARRAY_PRIMITIVE));
                }
                lightPacket.send(Protocol1_17_1To1_18.class);
            });
        }
    });
    protocol.cancelClientbound(ClientboundPackets1_18.SET_SIMULATION_DISTANCE);
}
Also used : MathUtil(com.viaversion.viaversion.util.MathUtil) ServerboundPackets1_17(com.viaversion.viaversion.protocols.protocol1_17to1_16_4.ServerboundPackets1_17) PacketWrapper(com.viaversion.viaversion.api.protocol.packet.PacketWrapper) ArrayList(java.util.ArrayList) PacketRemapper(com.viaversion.viaversion.api.protocol.remapper.PacketRemapper) Type(com.viaversion.viaversion.api.type.Type) Chunk1_17Type(com.viaversion.viaversion.protocols.protocol1_17to1_16_4.types.Chunk1_17Type) Chunk(com.viaversion.viaversion.api.minecraft.chunks.Chunk) Protocol1_17_1To1_18(com.viaversion.viabackwards.protocol.protocol1_17_1to1_18.Protocol1_17_1To1_18) ClientboundPackets1_17_1(com.viaversion.viaversion.protocols.protocol1_17_1to1_17.ClientboundPackets1_17_1) PaletteType(com.viaversion.viaversion.api.minecraft.chunks.PaletteType) IntTag(com.viaversion.viaversion.libs.opennbt.tag.builtin.IntTag) Chunk1_18Type(com.viaversion.viaversion.protocols.protocol1_18to1_17_1.types.Chunk1_18Type) BlockEntity(com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity) Position(com.viaversion.viaversion.api.minecraft.Position) ClientboundPackets1_18(com.viaversion.viaversion.protocols.protocol1_18to1_17_1.ClientboundPackets1_18) BlockEntityIds(com.viaversion.viabackwards.protocol.protocol1_17_1to1_18.data.BlockEntityIds) BaseChunk(com.viaversion.viaversion.api.minecraft.chunks.BaseChunk) EntityTracker(com.viaversion.viaversion.api.data.entity.EntityTracker) StringTag(com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag) DataPalette(com.viaversion.viaversion.api.minecraft.chunks.DataPalette) List(java.util.List) ItemRewriter(com.viaversion.viabackwards.api.rewriters.ItemRewriter) ParticleMappings(com.viaversion.viaversion.api.data.ParticleMappings) CompoundTag(com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag) ChunkSection(com.viaversion.viaversion.api.minecraft.chunks.ChunkSection) BitSet(java.util.BitSet) RecipeRewriter1_16(com.viaversion.viaversion.protocols.protocol1_16to1_15_2.data.RecipeRewriter1_16) StringTag(com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag) BaseChunk(com.viaversion.viaversion.api.minecraft.chunks.BaseChunk) Chunk1_17Type(com.viaversion.viaversion.protocols.protocol1_17to1_16_4.types.Chunk1_17Type) RecipeRewriter1_16(com.viaversion.viaversion.protocols.protocol1_16to1_15_2.data.RecipeRewriter1_16) Position(com.viaversion.viaversion.api.minecraft.Position) EntityTracker(com.viaversion.viaversion.api.data.entity.EntityTracker) PacketRemapper(com.viaversion.viaversion.api.protocol.remapper.PacketRemapper) BitSet(java.util.BitSet) Protocol1_17_1To1_18(com.viaversion.viabackwards.protocol.protocol1_17_1to1_18.Protocol1_17_1To1_18) Chunk(com.viaversion.viaversion.api.minecraft.chunks.Chunk) BaseChunk(com.viaversion.viaversion.api.minecraft.chunks.BaseChunk) DataPalette(com.viaversion.viaversion.api.minecraft.chunks.DataPalette) Chunk1_18Type(com.viaversion.viaversion.protocols.protocol1_18to1_17_1.types.Chunk1_18Type) PacketWrapper(com.viaversion.viaversion.api.protocol.packet.PacketWrapper) ArrayList(java.util.ArrayList) List(java.util.List) ParticleMappings(com.viaversion.viaversion.api.data.ParticleMappings) ChunkSection(com.viaversion.viaversion.api.minecraft.chunks.ChunkSection) CompoundTag(com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag) IntTag(com.viaversion.viaversion.libs.opennbt.tag.builtin.IntTag) BlockEntity(com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity)

Example 27 with ChunkSection

use of com.viaversion.viaversion.api.minecraft.chunks.ChunkSection in project ViaBackwards by ViaVersion.

the class BlockItemPackets1_16_2 method registerPackets.

@Override
protected void registerPackets() {
    BlockRewriter blockRewriter = new BlockRewriter(protocol, Type.POSITION1_14);
    new RecipeRewriter1_16(protocol).registerDefaultHandler(ClientboundPackets1_16_2.DECLARE_RECIPES);
    registerSetCooldown(ClientboundPackets1_16_2.COOLDOWN);
    registerWindowItems(ClientboundPackets1_16_2.WINDOW_ITEMS, Type.FLAT_VAR_INT_ITEM_ARRAY);
    registerSetSlot(ClientboundPackets1_16_2.SET_SLOT, Type.FLAT_VAR_INT_ITEM);
    registerEntityEquipmentArray(ClientboundPackets1_16_2.ENTITY_EQUIPMENT, Type.FLAT_VAR_INT_ITEM);
    registerTradeList(ClientboundPackets1_16_2.TRADE_LIST, Type.FLAT_VAR_INT_ITEM);
    registerAdvancements(ClientboundPackets1_16_2.ADVANCEMENTS, Type.FLAT_VAR_INT_ITEM);
    protocol.registerClientbound(ClientboundPackets1_16_2.UNLOCK_RECIPES, new PacketRemapper() {

        @Override
        public void registerMap() {
            handler(wrapper -> {
                wrapper.passthrough(Type.VAR_INT);
                // Open
                wrapper.passthrough(Type.BOOLEAN);
                // Filter
                wrapper.passthrough(Type.BOOLEAN);
                // Furnace Open
                wrapper.passthrough(Type.BOOLEAN);
                // Filter furnace
                wrapper.passthrough(Type.BOOLEAN);
                // Blast furnace / smoker
                wrapper.read(Type.BOOLEAN);
                wrapper.read(Type.BOOLEAN);
                wrapper.read(Type.BOOLEAN);
                wrapper.read(Type.BOOLEAN);
            });
        }
    });
    blockRewriter.registerAcknowledgePlayerDigging(ClientboundPackets1_16_2.ACKNOWLEDGE_PLAYER_DIGGING);
    blockRewriter.registerBlockAction(ClientboundPackets1_16_2.BLOCK_ACTION);
    blockRewriter.registerBlockChange(ClientboundPackets1_16_2.BLOCK_CHANGE);
    protocol.registerClientbound(ClientboundPackets1_16_2.CHUNK_DATA, new PacketRemapper() {

        @Override
        public void registerMap() {
            handler(wrapper -> {
                Chunk chunk = wrapper.read(new Chunk1_16_2Type());
                wrapper.write(new Chunk1_16Type(), chunk);
                chunk.setIgnoreOldLightData(true);
                for (int i = 0; i < chunk.getSections().length; i++) {
                    ChunkSection section = chunk.getSections()[i];
                    if (section == null)
                        continue;
                    for (int j = 0; j < section.getPaletteSize(); j++) {
                        int old = section.getPaletteEntry(j);
                        section.setPaletteEntry(j, protocol.getMappingData().getNewBlockStateId(old));
                    }
                }
                for (CompoundTag blockEntity : chunk.getBlockEntities()) {
                    if (blockEntity != null) {
                        handleBlockEntity(blockEntity);
                    }
                }
            });
        }
    });
    protocol.registerClientbound(ClientboundPackets1_16_2.BLOCK_ENTITY_DATA, new PacketRemapper() {

        @Override
        public void registerMap() {
            map(Type.POSITION1_14);
            map(Type.UNSIGNED_BYTE);
            handler(wrapper -> {
                handleBlockEntity(wrapper.passthrough(Type.NBT));
            });
        }
    });
    protocol.registerClientbound(ClientboundPackets1_16_2.MULTI_BLOCK_CHANGE, new PacketRemapper() {

        @Override
        public void registerMap() {
            handler(wrapper -> {
                long chunkPosition = wrapper.read(Type.LONG);
                // Ignore old light data
                wrapper.read(Type.BOOLEAN);
                int chunkX = (int) (chunkPosition >> 42);
                int chunkY = (int) (chunkPosition << 44 >> 44);
                int chunkZ = (int) (chunkPosition << 22 >> 42);
                wrapper.write(Type.INT, chunkX);
                wrapper.write(Type.INT, chunkZ);
                BlockChangeRecord[] blockChangeRecord = wrapper.read(Type.VAR_LONG_BLOCK_CHANGE_RECORD_ARRAY);
                wrapper.write(Type.BLOCK_CHANGE_RECORD_ARRAY, blockChangeRecord);
                for (int i = 0; i < blockChangeRecord.length; i++) {
                    BlockChangeRecord record = blockChangeRecord[i];
                    int blockId = protocol.getMappingData().getNewBlockStateId(record.getBlockId());
                    // Relative y -> absolute y
                    blockChangeRecord[i] = new BlockChangeRecord1_8(record.getSectionX(), record.getY(chunkY), record.getSectionZ(), blockId);
                }
            });
        }
    });
    blockRewriter.registerEffect(ClientboundPackets1_16_2.EFFECT, 1010, 2001);
    registerSpawnParticle(ClientboundPackets1_16_2.SPAWN_PARTICLE, Type.FLAT_VAR_INT_ITEM, Type.DOUBLE);
    registerClickWindow(ServerboundPackets1_16.CLICK_WINDOW, Type.FLAT_VAR_INT_ITEM);
    registerCreativeInvAction(ServerboundPackets1_16.CREATIVE_INVENTORY_ACTION, Type.FLAT_VAR_INT_ITEM);
    protocol.registerServerbound(ServerboundPackets1_16.EDIT_BOOK, new PacketRemapper() {

        @Override
        public void registerMap() {
            handler(wrapper -> handleItemToServer(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)));
        }
    });
}
Also used : BlockChangeRecord1_8(com.viaversion.viaversion.api.minecraft.BlockChangeRecord1_8) Tag(com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag) StringTag(com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag) ListTag(com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag) BlockChangeRecord(com.viaversion.viaversion.api.minecraft.BlockChangeRecord) ClientboundPackets1_16_2(com.viaversion.viaversion.protocols.protocol1_16_2to1_16_1.ClientboundPackets1_16_2) PacketRemapper(com.viaversion.viaversion.api.protocol.remapper.PacketRemapper) Type(com.viaversion.viaversion.api.type.Type) ServerboundPackets1_16(com.viaversion.viaversion.protocols.protocol1_16to1_15_2.ServerboundPackets1_16) Chunk(com.viaversion.viaversion.api.minecraft.chunks.Chunk) BlockRewriter(com.viaversion.viaversion.rewriter.BlockRewriter) Chunk1_16_2Type(com.viaversion.viaversion.protocols.protocol1_16_2to1_16_1.types.Chunk1_16_2Type) Chunk1_16Type(com.viaversion.viaversion.protocols.protocol1_16to1_15_2.types.Chunk1_16Type) CompoundTag(com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag) Protocol1_16_1To1_16_2(com.viaversion.viabackwards.protocol.protocol1_16_1to1_16_2.Protocol1_16_1To1_16_2) ChunkSection(com.viaversion.viaversion.api.minecraft.chunks.ChunkSection) IntArrayTag(com.viaversion.viaversion.libs.opennbt.tag.builtin.IntArrayTag) RecipeRewriter1_16(com.viaversion.viaversion.protocols.protocol1_16to1_15_2.data.RecipeRewriter1_16) BlockChangeRecord1_8(com.viaversion.viaversion.api.minecraft.BlockChangeRecord1_8) BlockRewriter(com.viaversion.viaversion.rewriter.BlockRewriter) BlockChangeRecord(com.viaversion.viaversion.api.minecraft.BlockChangeRecord) RecipeRewriter1_16(com.viaversion.viaversion.protocols.protocol1_16to1_15_2.data.RecipeRewriter1_16) Chunk1_16Type(com.viaversion.viaversion.protocols.protocol1_16to1_15_2.types.Chunk1_16Type) PacketRemapper(com.viaversion.viaversion.api.protocol.remapper.PacketRemapper) Chunk1_16_2Type(com.viaversion.viaversion.protocols.protocol1_16_2to1_16_1.types.Chunk1_16_2Type) Chunk(com.viaversion.viaversion.api.minecraft.chunks.Chunk) ChunkSection(com.viaversion.viaversion.api.minecraft.chunks.ChunkSection) CompoundTag(com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag)

Example 28 with ChunkSection

use of com.viaversion.viaversion.api.minecraft.chunks.ChunkSection in project ViaBackwards by ViaVersion.

the class WorldPackets1_13_1 method register.

public static void register(Protocol protocol) {
    BlockRewriter blockRewriter = new BlockRewriter(protocol, Type.POSITION);
    protocol.registerClientbound(ClientboundPackets1_13.CHUNK_DATA, new PacketRemapper() {

        @Override
        public void registerMap() {
            handler(new PacketHandler() {

                @Override
                public void handle(PacketWrapper wrapper) throws Exception {
                    ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
                    Chunk chunk = wrapper.passthrough(new Chunk1_13Type(clientWorld));
                    for (ChunkSection section : chunk.getSections()) {
                        if (section != null) {
                            for (int i = 0; i < section.getPaletteSize(); i++) {
                                section.setPaletteEntry(i, protocol.getMappingData().getNewBlockStateId(section.getPaletteEntry(i)));
                            }
                        }
                    }
                }
            });
        }
    });
    blockRewriter.registerBlockAction(ClientboundPackets1_13.BLOCK_ACTION);
    blockRewriter.registerBlockChange(ClientboundPackets1_13.BLOCK_CHANGE);
    blockRewriter.registerMultiBlockChange(ClientboundPackets1_13.MULTI_BLOCK_CHANGE);
    blockRewriter.registerEffect(ClientboundPackets1_13.EFFECT, 1010, 2001);
}
Also used : BlockRewriter(com.viaversion.viaversion.rewriter.BlockRewriter) PacketHandler(com.viaversion.viaversion.api.protocol.remapper.PacketHandler) PacketWrapper(com.viaversion.viaversion.api.protocol.packet.PacketWrapper) Chunk1_13Type(com.viaversion.viaversion.protocols.protocol1_13to1_12_2.types.Chunk1_13Type) PacketRemapper(com.viaversion.viaversion.api.protocol.remapper.PacketRemapper) ClientWorld(com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld) Chunk(com.viaversion.viaversion.api.minecraft.chunks.Chunk) ChunkSection(com.viaversion.viaversion.api.minecraft.chunks.ChunkSection)

Example 29 with ChunkSection

use of com.viaversion.viaversion.api.minecraft.chunks.ChunkSection in project ViaVersion by ViaVersion.

the class WorldPackets method setNonFullLight.

private static void setNonFullLight(Chunk chunk, ChunkSection section, int ySection, int x, int y, int z) {
    int skyLight = 0;
    int blockLight = 0;
    for (BlockFace blockFace : BlockFace.values()) {
        NibbleArray skyLightArray = section.getLight().getSkyLightNibbleArray();
        NibbleArray blockLightArray = section.getLight().getBlockLightNibbleArray();
        int neighbourX = x + blockFace.modX();
        int neighbourY = y + blockFace.modY();
        int neighbourZ = z + blockFace.modZ();
        if (blockFace.modX() != 0) {
            // Another chunk, nothing we can do without an unnecessary amount of caching
            if (neighbourX == 16 || neighbourX == -1)
                continue;
        } else if (blockFace.modY() != 0) {
            if (neighbourY == 16 || neighbourY == -1) {
                if (neighbourY == 16) {
                    ySection += 1;
                    neighbourY = 0;
                } else {
                    ySection -= 1;
                    neighbourY = 15;
                }
                if (ySection == 16 || ySection == -1)
                    continue;
                ChunkSection newSection = chunk.getSections()[ySection];
                if (newSection == null)
                    continue;
                skyLightArray = newSection.getLight().getSkyLightNibbleArray();
                blockLightArray = newSection.getLight().getBlockLightNibbleArray();
            }
        } else if (blockFace.modZ() != 0) {
            // Another chunk, nothing we can do without an unnecessary amount of caching
            if (neighbourZ == 16 || neighbourZ == -1)
                continue;
        }
        if (blockLightArray != null && blockLight != 15) {
            int neighbourBlockLight = blockLightArray.get(neighbourX, neighbourY, neighbourZ);
            if (neighbourBlockLight == 15) {
                blockLight = 14;
            } else if (neighbourBlockLight > blockLight) {
                // lower light level by one
                blockLight = neighbourBlockLight - 1;
            }
        }
        if (skyLightArray != null && skyLight != 15) {
            int neighbourSkyLight = skyLightArray.get(neighbourX, neighbourY, neighbourZ);
            if (neighbourSkyLight == 15) {
                if (blockFace.modY() == 1) {
                    // Keep 15 if block is exposed to sky
                    skyLight = 15;
                    continue;
                }
                skyLight = 14;
            } else if (neighbourSkyLight > skyLight) {
                // lower light level by one
                skyLight = neighbourSkyLight - 1;
            }
        }
    }
    if (skyLight != 0) {
        if (!section.getLight().hasSkyLight()) {
            byte[] newSkyLight = new byte[2028];
            section.getLight().setSkyLight(newSkyLight);
        }
        section.getLight().getSkyLightNibbleArray().set(x, y, z, skyLight);
    }
    if (blockLight != 0) {
        section.getLight().getBlockLightNibbleArray().set(x, y, z, blockLight);
    }
}
Also used : NibbleArray(com.viaversion.viaversion.api.minecraft.chunks.NibbleArray) BlockFace(com.viaversion.viaversion.api.minecraft.BlockFace) ChunkSection(com.viaversion.viaversion.api.minecraft.chunks.ChunkSection)

Example 30 with ChunkSection

use of com.viaversion.viaversion.api.minecraft.chunks.ChunkSection in project ViaVersion by ViaVersion.

the class WorldPackets method register.

public static void register(Protocol1_14To1_13_2 protocol) {
    BlockRewriter blockRewriter = new BlockRewriter(protocol, null);
    protocol.registerClientbound(ClientboundPackets1_13.BLOCK_BREAK_ANIMATION, new PacketRemapper() {

        @Override
        public void registerMap() {
            map(Type.VAR_INT);
            map(Type.POSITION, Type.POSITION1_14);
            map(Type.BYTE);
        }
    });
    protocol.registerClientbound(ClientboundPackets1_13.BLOCK_ENTITY_DATA, new PacketRemapper() {

        @Override
        public void registerMap() {
            map(Type.POSITION, Type.POSITION1_14);
        }
    });
    protocol.registerClientbound(ClientboundPackets1_13.BLOCK_ACTION, new PacketRemapper() {

        @Override
        public void registerMap() {
            // Location
            map(Type.POSITION, Type.POSITION1_14);
            // Action id
            map(Type.UNSIGNED_BYTE);
            // Action param
            map(Type.UNSIGNED_BYTE);
            // Block id - /!\ NOT BLOCK STATE
            map(Type.VAR_INT);
            handler(new PacketHandler() {

                @Override
                public void handle(PacketWrapper wrapper) throws Exception {
                    wrapper.set(Type.VAR_INT, 0, protocol.getMappingData().getNewBlockId(wrapper.get(Type.VAR_INT, 0)));
                }
            });
        }
    });
    protocol.registerClientbound(ClientboundPackets1_13.BLOCK_CHANGE, new PacketRemapper() {

        @Override
        public void registerMap() {
            map(Type.POSITION, Type.POSITION1_14);
            map(Type.VAR_INT);
            handler(new PacketHandler() {

                @Override
                public void handle(PacketWrapper wrapper) throws Exception {
                    int id = wrapper.get(Type.VAR_INT, 0);
                    wrapper.set(Type.VAR_INT, 0, protocol.getMappingData().getNewBlockStateId(id));
                }
            });
        }
    });
    protocol.registerClientbound(ClientboundPackets1_13.SERVER_DIFFICULTY, new PacketRemapper() {

        @Override
        public void registerMap() {
            map(Type.UNSIGNED_BYTE);
            handler(new PacketHandler() {

                @Override
                public void handle(PacketWrapper wrapper) throws Exception {
                    // Added in 19w11a. Maybe https://bugs.mojang.com/browse/MC-44471 ?
                    wrapper.write(Type.BOOLEAN, false);
                }
            });
        }
    });
    blockRewriter.registerMultiBlockChange(ClientboundPackets1_13.MULTI_BLOCK_CHANGE);
    protocol.registerClientbound(ClientboundPackets1_13.EXPLOSION, new PacketRemapper() {

        @Override
        public void registerMap() {
            // X
            map(Type.FLOAT);
            // Y
            map(Type.FLOAT);
            // Z
            map(Type.FLOAT);
            // Radius
            map(Type.FLOAT);
            handler(new PacketHandler() {

                @Override
                public void handle(PacketWrapper wrapper) throws Exception {
                    for (int i = 0; i < 3; i++) {
                        float coord = wrapper.get(Type.FLOAT, i);
                        if (coord < 0f) {
                            coord = (int) coord;
                            wrapper.set(Type.FLOAT, i, coord);
                        }
                    }
                }
            });
        }
    });
    protocol.registerClientbound(ClientboundPackets1_13.CHUNK_DATA, new PacketRemapper() {

        @Override
        public void registerMap() {
            handler(new PacketHandler() {

                @Override
                public void handle(PacketWrapper wrapper) throws Exception {
                    ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
                    Chunk chunk = wrapper.read(new Chunk1_13Type(clientWorld));
                    wrapper.write(new Chunk1_14Type(), chunk);
                    int[] motionBlocking = new int[16 * 16];
                    int[] worldSurface = new int[16 * 16];
                    for (int s = 0; s < chunk.getSections().length; s++) {
                        ChunkSection section = chunk.getSections()[s];
                        if (section == null)
                            continue;
                        boolean hasBlock = false;
                        for (int i = 0; i < section.getPaletteSize(); i++) {
                            int old = section.getPaletteEntry(i);
                            int newId = protocol.getMappingData().getNewBlockStateId(old);
                            if (!hasBlock && newId != air && newId != voidAir && newId != caveAir) {
                                // air, void_air, cave_air
                                hasBlock = true;
                            }
                            section.setPaletteEntry(i, newId);
                        }
                        if (!hasBlock) {
                            section.setNonAirBlocksCount(0);
                            continue;
                        }
                        int nonAirBlockCount = 0;
                        for (int x = 0; x < 16; x++) {
                            for (int y = 0; y < 16; y++) {
                                for (int z = 0; z < 16; z++) {
                                    int id = section.getFlatBlock(x, y, z);
                                    if (id != air && id != voidAir && id != caveAir) {
                                        nonAirBlockCount++;
                                        // +1 (top of the block)
                                        worldSurface[x + z * 16] = y + s * 16 + 1;
                                    }
                                    if (protocol.getMappingData().getMotionBlocking().contains(id)) {
                                        // +1 (top of the block)
                                        motionBlocking[x + z * 16] = y + s * 16 + 1;
                                    }
                                    // Manually update light for non full blocks (block light must not be sent)
                                    if (Via.getConfig().isNonFullBlockLightFix() && protocol.getMappingData().getNonFullBlocks().contains(id)) {
                                        setNonFullLight(chunk, section, s, x, y, z);
                                    }
                                }
                            }
                        }
                        section.setNonAirBlocksCount(nonAirBlockCount);
                    }
                    CompoundTag heightMap = new CompoundTag();
                    heightMap.put("MOTION_BLOCKING", new LongArrayTag(encodeHeightMap(motionBlocking)));
                    heightMap.put("WORLD_SURFACE", new LongArrayTag(encodeHeightMap(worldSurface)));
                    chunk.setHeightMap(heightMap);
                    PacketWrapper lightPacket = wrapper.create(ClientboundPackets1_14.UPDATE_LIGHT);
                    lightPacket.write(Type.VAR_INT, chunk.getX());
                    lightPacket.write(Type.VAR_INT, chunk.getZ());
                    // all 18 bits set if ground up
                    int skyLightMask = chunk.isFullChunk() ? 0x3ffff : 0;
                    int blockLightMask = 0;
                    for (int i = 0; i < chunk.getSections().length; i++) {
                        ChunkSection sec = chunk.getSections()[i];
                        if (sec == null)
                            continue;
                        if (!chunk.isFullChunk() && sec.getLight().hasSkyLight()) {
                            skyLightMask |= (1 << (i + 1));
                        }
                        blockLightMask |= (1 << (i + 1));
                    }
                    lightPacket.write(Type.VAR_INT, skyLightMask);
                    lightPacket.write(Type.VAR_INT, blockLightMask);
                    // empty sky light mask
                    lightPacket.write(Type.VAR_INT, 0);
                    // empty block light mask
                    lightPacket.write(Type.VAR_INT, 0);
                    // only do this on the initial chunk send (not when chunk.isGroundUp() is false)
                    if (chunk.isFullChunk())
                        // chunk below 0
                        lightPacket.write(Type.BYTE_ARRAY_PRIMITIVE, FULL_LIGHT);
                    for (ChunkSection section : chunk.getSections()) {
                        if (section == null || !section.getLight().hasSkyLight()) {
                            if (chunk.isFullChunk()) {
                                lightPacket.write(Type.BYTE_ARRAY_PRIMITIVE, FULL_LIGHT);
                            }
                            continue;
                        }
                        lightPacket.write(Type.BYTE_ARRAY_PRIMITIVE, section.getLight().getSkyLight());
                    }
                    if (chunk.isFullChunk())
                        // chunk above 255
                        lightPacket.write(Type.BYTE_ARRAY_PRIMITIVE, FULL_LIGHT);
                    for (ChunkSection section : chunk.getSections()) {
                        if (section == null)
                            continue;
                        lightPacket.write(Type.BYTE_ARRAY_PRIMITIVE, section.getLight().getBlockLight());
                    }
                    EntityTracker1_14 entityTracker = wrapper.user().getEntityTracker(Protocol1_14To1_13_2.class);
                    int diffX = Math.abs(entityTracker.getChunkCenterX() - chunk.getX());
                    int diffZ = Math.abs(entityTracker.getChunkCenterZ() - chunk.getZ());
                    if (entityTracker.isForceSendCenterChunk() || diffX >= SERVERSIDE_VIEW_DISTANCE || diffZ >= SERVERSIDE_VIEW_DISTANCE) {
                        // Set center chunk
                        PacketWrapper fakePosLook = wrapper.create(ClientboundPackets1_14.UPDATE_VIEW_POSITION);
                        fakePosLook.write(Type.VAR_INT, chunk.getX());
                        fakePosLook.write(Type.VAR_INT, chunk.getZ());
                        fakePosLook.send(Protocol1_14To1_13_2.class);
                        entityTracker.setChunkCenterX(chunk.getX());
                        entityTracker.setChunkCenterZ(chunk.getZ());
                    }
                    lightPacket.send(Protocol1_14To1_13_2.class);
                    // Remove light references from chunk sections
                    for (ChunkSection section : chunk.getSections()) {
                        if (section != null) {
                            section.setLight(null);
                        }
                    }
                }
            });
        }
    });
    protocol.registerClientbound(ClientboundPackets1_13.EFFECT, new PacketRemapper() {

        @Override
        public void registerMap() {
            // Effect Id
            map(Type.INT);
            // Location
            map(Type.POSITION, Type.POSITION1_14);
            // Data
            map(Type.INT);
            handler(new PacketHandler() {

                @Override
                public void handle(PacketWrapper wrapper) throws Exception {
                    int id = wrapper.get(Type.INT, 0);
                    int data = wrapper.get(Type.INT, 1);
                    if (id == 1010) {
                        // Play record
                        wrapper.set(Type.INT, 1, protocol.getMappingData().getNewItemId(data));
                    } else if (id == 2001) {
                        // Block break + block break sound
                        wrapper.set(Type.INT, 1, protocol.getMappingData().getNewBlockStateId(data));
                    }
                }
            });
        }
    });
    protocol.registerClientbound(ClientboundPackets1_13.JOIN_GAME, new PacketRemapper() {

        @Override
        public void registerMap() {
            // 0 - Entity ID
            map(Type.INT);
            // 1 - Gamemode
            map(Type.UNSIGNED_BYTE);
            // 2 - Dimension
            map(Type.INT);
            handler(new PacketHandler() {

                @Override
                public void handle(PacketWrapper wrapper) throws Exception {
                    // Store the player
                    ClientWorld clientChunks = wrapper.user().get(ClientWorld.class);
                    int dimensionId = wrapper.get(Type.INT, 1);
                    clientChunks.setEnvironment(dimensionId);
                    int entityId = wrapper.get(Type.INT, 0);
                    Entity1_14Types entType = Entity1_14Types.PLAYER;
                    // Register Type ID
                    EntityTracker1_14 tracker = wrapper.user().getEntityTracker(Protocol1_14To1_13_2.class);
                    tracker.addEntity(entityId, entType);
                    tracker.setClientEntityId(entityId);
                }
            });
            handler(new PacketHandler() {

                @Override
                public void handle(PacketWrapper wrapper) throws Exception {
                    // 19w11a removed difficulty from join game
                    short difficulty = wrapper.read(Type.UNSIGNED_BYTE);
                    PacketWrapper difficultyPacket = wrapper.create(ClientboundPackets1_14.SERVER_DIFFICULTY);
                    difficultyPacket.write(Type.UNSIGNED_BYTE, difficulty);
                    // Unknown value added in 19w11a
                    difficultyPacket.write(Type.BOOLEAN, false);
                    difficultyPacket.scheduleSend(protocol.getClass());
                    // Max Players
                    wrapper.passthrough(Type.UNSIGNED_BYTE);
                    // Level Type
                    wrapper.passthrough(Type.STRING);
                    // Serverside view distance, added in 19w13a
                    wrapper.write(Type.VAR_INT, SERVERSIDE_VIEW_DISTANCE);
                }
            });
            handler(wrapper -> {
                // Manually send the packet
                wrapper.send(Protocol1_14To1_13_2.class);
                wrapper.cancel();
                // View distance has to be sent after the join packet
                sendViewDistancePacket(wrapper.user());
            });
        }
    });
    protocol.registerClientbound(ClientboundPackets1_13.MAP_DATA, new PacketRemapper() {

        @Override
        public void registerMap() {
            map(Type.VAR_INT);
            map(Type.BYTE);
            map(Type.BOOLEAN);
            handler(new PacketHandler() {

                @Override
                public void handle(PacketWrapper wrapper) throws Exception {
                    // new value, probably if the map is locked (added in 19w02a), old maps are not locked
                    wrapper.write(Type.BOOLEAN, false);
                }
            });
        }
    });
    protocol.registerClientbound(ClientboundPackets1_13.RESPAWN, new PacketRemapper() {

        @Override
        public void registerMap() {
            // 0 - Dimension ID
            map(Type.INT);
            handler(new PacketHandler() {

                @Override
                public void handle(PacketWrapper wrapper) throws Exception {
                    ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
                    int dimensionId = wrapper.get(Type.INT, 0);
                    clientWorld.setEnvironment(dimensionId);
                    EntityTracker1_14 entityTracker = wrapper.user().getEntityTracker(Protocol1_14To1_13_2.class);
                    // The client may reset the center chunk if dimension is changed
                    entityTracker.setForceSendCenterChunk(true);
                }
            });
            handler(new PacketHandler() {

                @Override
                public void handle(PacketWrapper wrapper) throws Exception {
                    // 19w11a removed difficulty from respawn
                    short difficulty = wrapper.read(Type.UNSIGNED_BYTE);
                    PacketWrapper difficultyPacket = wrapper.create(ClientboundPackets1_14.SERVER_DIFFICULTY);
                    difficultyPacket.write(Type.UNSIGNED_BYTE, difficulty);
                    // Unknown value added in 19w11a
                    difficultyPacket.write(Type.BOOLEAN, false);
                    difficultyPacket.scheduleSend(protocol.getClass());
                }
            });
            handler(wrapper -> {
                // Manually send the packet and update the viewdistance after
                wrapper.send(Protocol1_14To1_13_2.class);
                wrapper.cancel();
                sendViewDistancePacket(wrapper.user());
            });
        }
    });
    protocol.registerClientbound(ClientboundPackets1_13.SPAWN_POSITION, new PacketRemapper() {

        @Override
        public void registerMap() {
            map(Type.POSITION, Type.POSITION1_14);
        }
    });
}
Also used : PacketHandler(com.viaversion.viaversion.api.protocol.remapper.PacketHandler) Arrays(java.util.Arrays) EntityTracker1_14(com.viaversion.viaversion.protocols.protocol1_14to1_13_2.storage.EntityTracker1_14) ClientWorld(com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld) PacketWrapper(com.viaversion.viaversion.api.protocol.packet.PacketWrapper) Chunk1_14Type(com.viaversion.viaversion.protocols.protocol1_14to1_13_2.types.Chunk1_14Type) Via(com.viaversion.viaversion.api.Via) CompactArrayUtil(com.viaversion.viaversion.util.CompactArrayUtil) NibbleArray(com.viaversion.viaversion.api.minecraft.chunks.NibbleArray) PacketRemapper(com.viaversion.viaversion.api.protocol.remapper.PacketRemapper) ClientboundPackets1_13(com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13) Type(com.viaversion.viaversion.api.type.Type) Chunk(com.viaversion.viaversion.api.minecraft.chunks.Chunk) BlockRewriter(com.viaversion.viaversion.rewriter.BlockRewriter) Protocol1_14To1_13_2(com.viaversion.viaversion.protocols.protocol1_14to1_13_2.Protocol1_14To1_13_2) CompoundTag(com.github.steveice10.opennbt.tag.builtin.CompoundTag) LongArrayTag(com.github.steveice10.opennbt.tag.builtin.LongArrayTag) UserConnection(com.viaversion.viaversion.api.connection.UserConnection) BlockFace(com.viaversion.viaversion.api.minecraft.BlockFace) ChunkSection(com.viaversion.viaversion.api.minecraft.chunks.ChunkSection) ClientboundPackets1_14(com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ClientboundPackets1_14) Chunk1_13Type(com.viaversion.viaversion.protocols.protocol1_13to1_12_2.types.Chunk1_13Type) Entity1_14Types(com.viaversion.viaversion.api.minecraft.entities.Entity1_14Types) EntityTracker1_14(com.viaversion.viaversion.protocols.protocol1_14to1_13_2.storage.EntityTracker1_14) PacketRemapper(com.viaversion.viaversion.api.protocol.remapper.PacketRemapper) Chunk1_14Type(com.viaversion.viaversion.protocols.protocol1_14to1_13_2.types.Chunk1_14Type) Chunk(com.viaversion.viaversion.api.minecraft.chunks.Chunk) BlockRewriter(com.viaversion.viaversion.rewriter.BlockRewriter) PacketHandler(com.viaversion.viaversion.api.protocol.remapper.PacketHandler) PacketWrapper(com.viaversion.viaversion.api.protocol.packet.PacketWrapper) Chunk1_13Type(com.viaversion.viaversion.protocols.protocol1_13to1_12_2.types.Chunk1_13Type) LongArrayTag(com.github.steveice10.opennbt.tag.builtin.LongArrayTag) Entity1_14Types(com.viaversion.viaversion.api.minecraft.entities.Entity1_14Types) Protocol1_14To1_13_2(com.viaversion.viaversion.protocols.protocol1_14to1_13_2.Protocol1_14To1_13_2) ClientWorld(com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld) ChunkSection(com.viaversion.viaversion.api.minecraft.chunks.ChunkSection) CompoundTag(com.github.steveice10.opennbt.tag.builtin.CompoundTag)

Aggregations

ChunkSection (com.viaversion.viaversion.api.minecraft.chunks.ChunkSection)48 Chunk (com.viaversion.viaversion.api.minecraft.chunks.Chunk)20 CompoundTag (com.github.steveice10.opennbt.tag.builtin.CompoundTag)19 PacketRemapper (com.viaversion.viaversion.api.protocol.remapper.PacketRemapper)19 PacketWrapper (com.viaversion.viaversion.api.protocol.packet.PacketWrapper)18 ArrayList (java.util.ArrayList)16 Type (com.viaversion.viaversion.api.type.Type)14 ByteBuf (io.netty.buffer.ByteBuf)13 PacketHandler (com.viaversion.viaversion.api.protocol.remapper.PacketHandler)12 BlockRewriter (com.viaversion.viaversion.rewriter.BlockRewriter)12 BaseChunk (com.viaversion.viaversion.api.minecraft.chunks.BaseChunk)11 ClientWorld (com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld)10 Position (com.viaversion.viaversion.api.minecraft.Position)8 BlockChangeRecord (com.viaversion.viaversion.api.minecraft.BlockChangeRecord)7 CompoundTag (com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag)7 List (java.util.List)7 StringTag (com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag)6 Tag (com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag)6 StringTag (com.github.steveice10.opennbt.tag.builtin.StringTag)5 Via (com.viaversion.viaversion.api.Via)5