Skip to content

Screen networking

Juuz edited this page Jul 23, 2024 · 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 which is (de)serialized using a codec. 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, MESSAGE_CODEC, data -> {
    // This lambda executes when your message is received.
    // The custom data has been read by the given codec.
});

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, MESSAGE_CODEC, data);

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 = Identifier.of("my_mod", "button_click");

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

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

    // We're sending from a button. The packet data is our lucky number, 123.
    WButton button = ...;
    button.setOnClick(() -> {
        ScreenNetworking.of(this, NetworkSide.CLIENT).send(MESSAGE_ID, Codec.INT, 123);
    });
}