Skip to content

Screen networking

Juuxel edited this page Aug 20, 2022 · 5 revisions

Screen handlers synchronize a lot of data between the server and the client automatically, including items and int properties (via PropertyDelegate).

Sometimes that isn't enough when you're dealing with client→server syncing or custom data types. This is where LibGui's ScreenNetworking comes to the rescue! It is a painless custom packet API for SyncedGuiDescriptions.

Introduction to ScreenNetworking

You can obtain a ScreenNetworking instance for your GUI description with ScreenNetworking.of, which needs the GUI description and a network side to be passed in as parameters. The instance is only active on that side.

For example, ScreenNetworking.of(this, NetworkSide.SERVER) can be used to send network messages from the server and register server-side receivers for messages.

Messages

Messages are the screen networking analogue of packets.

Each message has a unique ID which LibGui uses to check that the receiving can check whether it can handle the message.

Messages can carry arbitrary data in their packet byte buffer. The data can be useful for syncing inputs like text fields or slider values to the server.

Receiving messages

You can register a receiver using ScreenNetworking.receive. For example, to receive a client→server message you would receive on a server:

ScreenNetworking.of(this, NetworkSide.SERVER).receive(MESSAGE_ID, buf -> {
    // This lambda executes when your message is received.
    // You can also read your custom data from the buffer if needed.
});

Sending messages

Sending is done in a similar way using ScreenNetworking.send.

// NetworkSide.CLIENT means that you are sending the message from the client.
ScreenNetworking.of(this, NetworkSide.CLIENT).send(MESSAGE_ID, buf -> {
    // If needed, you can write any custom data to the buffer here.
});

Full example: button clicks

Here's an example for a common use case of ScreenNetworking: sending inputs (button clicks) from the client to the server.

// In your GUI description class:

// The unique ID for the message. This can be any ID, it just has to match between the sender and the receiver.
private static final Identifier BUTTON_CLICK_MESSAGE = new Identifier("my_mod", "button_click");

public MyGuiDescription(...) {
    // ...

    // Receiving
    ScreenNetworking.of(this, NetworkSide.SERVER).receive(MESSAGE_ID, buf -> {
        // Example data: a lucky number as an int
        System.out.println("Your lucky number is " + buf.readInt() + "!");
    });

    // Sending
    WButton button = ...;
    button.setOnClick(() -> {
        ScreenNetworking.of(this, NetworkSide.CLIENT).send(MESSAGE_ID, buf .> {
            // Write the lucky number
            buf.writeInt(123);
        });
    });
}