Skip to content

Async Chunk Processing & World switching issues #412

@Leymooo

Description

@Leymooo

Description

New versions of MC do not include available chunk section mask and for chunk sections decoding a current world height is used.

Due to async packet proccesing there is possible that server changed world for player(RESPAWN packet) while there is some chunks in orebfuscation process what will cause orebfucator to send chunks belong to other world.

This cause some issues:

  1. If world height is different then client will fail to decode packet, due to not reading all sections or overeading sections, what should cause disconnect from server. ViaVersion also will fail to transform chunk packets, and will disconnect player (https://pastebin.com/NBqj7jB3).

  2. May cause some client chunks artefacts due to some chunks are leaked from old world to new world.

  3. New versions introduce some nice packets like Chunk Batch Start/End, Bundle Delimiter, putting some packets to be out of order breaks usage for these packets.

  4. Its possible that server may send chunks belong to one world, then player got instanly switched to another world and then when ProtocolLib scheduled packets to be executed in Orebfuscator async pool the player.getWorld() may return a new world instead of actual world where chunks came from. I think this what happened here: https://pastebin.com/JYdvK9UB

My idea how to resolve this issue:

I think we need an custom packet queue implementation, what will not cause any packet order issues, but will allow parralel chunk obfuscation.

What i mean: When we get chunk packet we start obfuscating process for that chunk (getting neighbours and then actual obfuscation), all next other packets we put into queue. When obfuscation is ready we drain queue until next chunk packet. So we pause all packet sending until chunk obfuscation is done.

I am not sure if this is doable with ProtocolLib. But should not be very hard to implement this queue with some handler in netty pipeline sitting before minecraft encoder. So you can simply put minecraft packet objects into some queue if there is chunk in obfuscation progress, or passthrough it to the next handler. You can still use ProtocolLib for easely reading values from minecraft packet objects.
This approach still requires manual world tracking to know exact chunk section count to read and what world instance to use for getting neighbours. Should not be very hard to map RESPAWN packet dimension field to Bukkit world across multiple server versions.

Reproduction Steps

Currently i just analyzed code and logs, so i didnt tried to replicate it, but i belive it should be easy to replicate with plugin that will constantly teleport player between worlds with different world heights.

Expected Behaviour

No issues with async processing

Orebfuscator Dump

Extra Details

I am using a custom fork with some additions, but i am 100% sure they do not cause this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions