GeyserMC / MCProtocolLib

A library for communication with a Minecraft client/server.
MIT License
728 stars 202 forks source link

Correctly applying ServerBlockChangePacket/MultiChange to loaded chunks #525

Closed CatCoderr closed 4 years ago

CatCoderr commented 4 years ago

Hello. How I can correctly apply block state from ServerBlockChangePacket to BlockStorage in Chunk? Here is my code, but client does not see any changes: This method called when ServerBlockChangePacket/MultiBlockChange was received.

private void changeBlockState(int x, int y, int z, BlockState state) {
        Column column = chunkCache.get(new Key(x >> 4, z >> 4));
        if (column == null) {
            return;
        }

        int sectionIdx = y >> 4;
        if (sectionIdx < column.getChunks().length) {
            Chunk chunk = column.getChunks()[sectionIdx];
            chunk.getBlocks().set(x >> 4, y & 0xf, z, state);
        }
    }

Thanks for help.

CatCoderr commented 4 years ago

I've fixed the code above. It worked only with ServerBlockChangePacket with single record.

Here is updated code:

    private void changeBlockState(int x, int y, int z, BlockState state) {
        Column column = chunkCache.get(new Key(x >> 4, z >> 4));
        if (column == null) {
            return;
        }

        int sectionIdx = y >> 4;
        Chunk[] chunks = column.getChunks();

        if (sectionIdx < chunks.length) {
            Chunk chunk = chunks[sectionIdx];

            if (chunk == null) {
                if (state.getId() == 0) {
                    return;
                }
                chunks[sectionIdx] = chunk = new Chunk(column.hasSkylight());
            }

            chunk.getBlocks().set(x & 0xf, y & 0xf, z & 0xf, state);
        }
    }

Packet handling:

    private void handleBlockChanges(PacketReceivedEvent event) {
        if (event.getPacket() instanceof ServerBlockChangePacket) {
            BlockChangeRecord record = ((ServerBlockChangePacket) event.getPacket()).getRecord();
            Position position = record.getPosition();

            // It works.
            changeBlockState(position.getX(), position.getY(), position.getZ(), record.getBlock());
        }
        if (event.getPacket() instanceof ServerMultiBlockChangePacket) {
            ServerMultiBlockChangePacket packet = event.getPacket();

            for (BlockChangeRecord record : packet.getRecords()) {
                Position position = record.getPosition();

                // It doesn't work. 
                changeBlockState(position.getX(), position.getY(), position.getZ(), record.getBlock());
            }
        }
    }