Skip to content

Packet sending order is not preserved #49

@coolomet

Description

@coolomet

Description

There is a chance that packets sent to a player will arrive out of order. Vanilla doesn't seem to be affected by this because I guess it sends packets in packet bundles. However, plugins that use NMS or ProtocolLib have issues with this.

For example, there's a plugin called DecentHolograms. Here's how it works: first it sends an entity spawn packet (armor stand), then it sends entity metadata (makes it invisible). The problem is that the sending order may not be preserved, and we can see it in the screenshot:

Image

That is, metadata arrives first, then spawn. By the way, disabling flush-queue-in-parallel in shreddedpaper.yml does not fix the issue.

Steps to reproduce

  1. Install DecentHolograms to your server.
  2. Create a bunch of holograms using /dh create <name> <display-name>.
  3. Spam /dh reload until you see an armor stand.

My workaround

I just synchronized the flushQueue method in net.minecraft.network.Connection:

// Paper start - Optimize network: Rewrite this to be safer if ran off main thread
public boolean flushQueue() { // ShreddedPaper - make public
    if (!this.isConnected()) {
        return true;
    }
//        if (io.papermc.paper.util.MCUtil.isMainThread()) {
//            return this.processQueue();
//        } else if (this.isPending) {
//            // Should only happen during login/status stages
//            synchronized (this.pendingActions) {
//                return this.processQueue();
//            }
//        }
//        return false;
    synchronized (this.pendingActions) { // coolomet - Preserve packet order
        return this.processQueue();
    }
}

This fixes the problem, but I assume that synchronization might lead to a performance loss, even if minor - meaning the packet queue is now processed by only one thread at a time. If this is acceptable, I can make a pull request, but if not, we probably need to implement some mechanism that ensures packet sending order, or add some kind of config option.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions