#Is Networking Async now?

17 messages · Page 1 of 1 (latest)

wicked mural
#

When porting to 1.21 I noticed that my packets now experience race conditions (or just out of order, not sure yet):
Specifically the vanilla ClientboundContainerSetContentPacket arrives faster than my OpenGui packet, thus getting discarded.
My current hotfix is to just sleep 100ms but thats really not a permanent solution.

Old code, no longer works despite sending OpenGuiRequest first, then ClientboundContainerSetContentPacket through setSynchronizer.

    public void openInventory(ServerPlayer player) {
        ((ServerPlayerEntityMixin)player).ic$nextContainerCounter();
        AbstractContainerMenu screenHandler = createMenu(((ServerPlayerEntityMixin)player).getContainerCounter(), player.getInventory(), player);
        if (screenHandler != null) {
            NetworkHandler.sendToPlayer(new OpenGuiRequest(this, screenHandler.containerId), player);
            // A sleep here would "fix" the issue.
            player.containerMenu = screenHandler;
            ServerPlayerEntityMixin playerAccessor = (ServerPlayerEntityMixin) player;
            screenHandler.setSynchronizer(playerAccessor.getContainerSynchronizer());
        }
    }
wicked mural
#

The current fix is this and its horrible concern

    public void openInventory(ServerPlayer player) {
        ((ServerPlayerEntityMixin) player).ic$nextContainerCounter();
        AbstractContainerMenu screenHandler = createMenu(((ServerPlayerEntityMixin) player).getContainerCounter(), player.getInventory(), player);
        if (screenHandler != null) {
            NetworkHandler.sendToPlayer(new OpenGuiRequest(this, screenHandler.containerId), player);
            new Thread(() -> {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                MinecraftServer server = level().getServer();
                if (server != null) {
                    server.execute(() -> {
                        player.containerMenu = screenHandler;
                        ServerPlayerEntityMixin playerAccessor = (ServerPlayerEntityMixin) player;
                        screenHandler.setSynchronizer(playerAccessor.getContainerSynchronizer());
                    });
                }
            }).start();
        }
    }
bold briar
#

could you cache the necessary action and then mixin to the "ontick" method and execute the next tick?

That way they should be queued up nicely on the client aswell

wicked mural
#

Hmm, that would work, but its still odd that the network order is not granted anymore. NeoForge for example works as expected. I believe that I just misunderstood something

warm trout
wicked mural
#

You can have several parallel connections open tho, and the networking consists of more than just a plain socket. I could stumble across a problem with multiple channels handled one after another or whatelse.
What I see is this call order: OpenGui::new -> ClientboundContainerSetContentPacket::new -> ClientboundContainerSetContentPacket::handle -> OpenGui::handle

warm trout
#

um what

#

it doesn't matter if you can have multiple connections if minecraft only uses one

wicked mural
#

thats the question of this post

#

So packets should still be in order, and I need to look somewhere else

warm trout
#

yes

#

there's not enough information for me to provide any useful hints

wicked mural
wicked mural
#

Debugged more, the packets gets decoded in the correct order, but not handled.

wicked mural
#

Got it: For whatever reason I assumed the network handler to be on the netty thread and added an extra .execute(), which obviously delayed execution by up to one tick.

ServerPlayNetworking.registerGlobalReceiver(type, (payload, context) -> context.server().execute(() -> serverHandler.handle(payload, context.player())));
formal root
#

why aren't you using PlayerEntity#openHandledScreen to open your screen in the first place?

wicked mural
#

Good question. Legacy code or maybe registering menutypes was a bit more painful in 1.16.5, I don't remember