Skip to content

Conversations

mega12345mega edited this page Jan 26, 2023 · 1 revision

Replying to packets

To reply to a received packet, use Connection#reply(packet, response).

Example:

client.addPacketListener((packet, conn, wait) -> {
    if (packet instanceof TokenRequestPacket)
        conn.reply(packet, new TokenPacket(2718281828)); // Client#reply works too
});

Receiving a reply

You can attach a response packet listener when sending a packet. You can also use Connection#sendPacketWithResponse to avoid lots of nested callbacks in a long conversation. However, refer to the WaitState section to avoid issues with blocking when using this method.

If you want to extend the amount of time response listeners stick around, use Connection#setTimeout. If you set the timeout to -1, you must remove the response listener later to prevent memory leaks.

Example:

// Using nested callbacks
server.addConnectionListener((conn, wait) -> {
    conn.sendPacket(new TokenRequestPacket(), (response, conn2, wait2) -> {
        if (response instanceof TokenPacket token && token.getToken() == 2718281828)
            players.add(new Player(conn));
        else {
            conn.reply(response, new InvalidTokenPacket(), (invalidResponse, conn3, wait3) -> {
                if (invalidResponse instanceof JoinAnywayPacket && joinAnywayAllowed)
                    players.add(new Player(conn).setValidated(false));
                else
                    conn.close();
            });
        }
    });
});

// Using withResponse
server.addConnectionListener((conn, wait) -> {
    wait.dontWait(); // Prevent blocking issues
    Packet response = conn.sendPacketWithResponse(new TokenRequestPacket());
    if (response == null) { // Response timed out (5s default)
        conn.close();
        return;
    }
    if (response instanceof TokenPacket token && token.getToken() == 2718281828) {
        players.add(new Player(conn));
        return;
    }
    response = conn.replyWithResponse(response, new InvalidTokenPacket());
    if (response instanceof JoinAnywayPacket && joinAnywayAllowed)
        players.add(new Player(conn).setValidated(false));
    else
        conn.close();
});

WaitState

While a packet listener or connection listener is running, the library pauses reading in packets. This prevents race conditions in the ordering of received packets. However, this can cause issues when using a blocking function that waits for incoming packets - like sendPacketWithResponse. Since the library is not reading in packets, it can't read in the response packet that sendPacketWithResponse is waiting for. To solve this, use WaitState#dontWait() to tell the library to continue reading in packets.

Example:

client.addPacketListener((packet, conn, wait) -> {
    Packet response = client.sendPacketWithResponse(new TeleportRequestPacket(3, 1, 4)); // Will freeze packet handling for timeout, then return null
    
    wait.dontWait();
    response = client.sendPacketWithResponse(new TeleportRequestPacket(2, 7, 1)); // Will work properly
    if (!(response instanceof TeleportConfirmPacket))
        client.close();
});

Clone this wiki locally