Interface IPayloadRegistrar

All Known Implementing Classes:
ModdedPacketRegistrar

public interface IPayloadRegistrar
Defines a registrar for custom payloads that can be sent over the network.

A custom payload is a class which extends CustomPacketPayload, it is recommended to use a record for this.

The payload is written to the networks outgoing buffer using the CustomPacketPayload.write(FriendlyByteBuf) method. However, to read the payload from the incoming buffer, your registered FriendlyByteBuf.Reader is used.
When you implement your CustomPacketPayload.write(FriendlyByteBuf) method you do not need to write the id of the payload, neither do you need to read it in your FriendlyByteBuf.Reader implementation. However, you do need to make sure that the id you pass into play(ResourceLocation, FriendlyByteBuf.Reader, IPlayPayloadHandler) and configuration(ResourceLocation, FriendlyByteBuf.Reader, IConfigurationPayloadHandler) is the same as the id you return from your CustomPacketPayload.id(). We suggest using a public static final ResourceLocation field to store it and then reference it in both places.
Ids can be reused between play and configuration payloads, but it is needed to use different ids for different payloads.
Under certain situations you are not able to register a payload:

  • If the id you are trying to register is already in use, meaning you used the same id twice for different packets of the same kind.
  • If you are trying to register a payload to a namespace that is not your own.
  • If the registrar has become invalid.
This means that the registration will fail if any of these cases occur. The exception thrown in these cases is a RegistrationFailedException.

There are two kinds of payloads:

  • Play payloads: These are payloads that are sent from the client to the server, or from the server to the client, during normal gameplay.
  • Configuration payloads: These are payloads that are sent from the server to the client, or from the client to the server, during the login process, before the player is spawned.
You can register a custom payload for either of these types of payloads using the play(ResourceLocation, FriendlyByteBuf.Reader, IPlayPayloadHandler) and configuration(ResourceLocation, FriendlyByteBuf.Reader, IConfigurationPayloadHandler) methods respectively.
The difference between the play and configuration phases, if you like to call them that, is that the configuration phase generally requires a confirmation payload to be returned to the server to trigger the next phase. In the context passed into your IConfigurationPayloadHandler you will find a ITaskCompletedHandler which you can use, on the server side, to notify the connection management system that a given ConfigurationTask.Type has been completed. This will trigger the next phase of the login process. Invoking the ITaskCompletedHandler.onTaskCompleted(ConfigurationTask.Type) method on the client, will throw an exception.

Note: the processing of payloads happens solely on the network thread. You are responsible for ensuring that any data you access in your handlers is either thread safe, or that you queue up your work to be done on the main thread, of the relevant side. This is particularly important for the IPlayPayloadHandler or IConfigurationPayloadHandler implementations that you pass to play(ResourceLocation, FriendlyByteBuf.Reader, IPlayPayloadHandler) or configuration(ResourceLocation, FriendlyByteBuf.Reader, IConfigurationPayloadHandler) respectively, since those are also invoked on the network thread.
The PlayPayloadContext and ConfigurationPayloadContext given to each of these handlers contains a ISynchronizedWorkHandler which you can use to submit work to be run on the main thread of the game. This is the recommended way to handle any work that needs to be done on the main thread.
Note the reader passed to any of the registration methods in this interface is invoked only if the payload is actually transferred over a connection which is not marked as Connection.isMemoryConnection(). This is important for single-player of lan-opened worlds since there the writer and reader are not invoked. That is because the payload is not actually transferred over the network, but only passed around in memory.

  • Method Details

    • play

      Registers a new payload type for the play phase.
      Type Parameters:
      T - The type of the payload.
      Parameters:
      id - The id of the payload.
      reader - The reader for the payload.
      handler - The handler for the payload.
      Returns:
      The registrar.
    • play

      Registers a new payload type for the play phase.

      This method allows different handlers to be registered for different packet-flows.
      In practice this means that you can register a different handler for clientbound and serverbound packets, which allows you to handle them differently on the client and server side.

      Type Parameters:
      T - The type of the payload.
      Parameters:
      id - The id of the payload.
      reader - The reader for the payload.
      handler - The handler for the payload.
      Returns:
      The registrar.
    • configuration

      Registers a new payload type for the configuration phase.
      Type Parameters:
      T - The type of the payload.
      Parameters:
      id - The id of the payload.
      reader - The reader for the payload.
      handler - The handler for the payload.
      Returns:
      The registrar.
    • configuration

      Registers a new payload type for the configuration phase.

      This method allows different handlers to be registered for different packet-flows.
      In practice this means that you can register a different handler for clientbound and serverbound packets, which allows you to handle them differently on the client and server side.

      Type Parameters:
      T - The type of the payload.
      Parameters:
      id - The id of the payload.
      reader - The reader for the payload.
      handler - The handler for the payload.
      Returns:
      The registrar.
    • common

      default <T extends CustomPacketPayload> IPayloadRegistrar common(ResourceLocation id, FriendlyByteBuf.Reader<T> reader, IPayloadHandler<T> handler)
      Registers a new payload type for all supported phases.
      Type Parameters:
      T - The type of the payload.
      Parameters:
      id - The id of the payload.
      reader - The reader for the payload.
      handler - The handler for the payload.
      Returns:
      The registrar.
    • common

      Registers a new payload type for all supported phases.

      This method allows different handlers to be registered for different packet-flows.
      In practice this means that you can register a different handler for clientbound and serverbound packets, which allows you to handle them differently on the client and server side.

      Type Parameters:
      T - The type of the payload.
      Parameters:
      id - The id of the payload.
      reader - The reader for the payload.
      handler - The handler for the payload.
      Returns:
      The registrar.
    • versioned

      IPayloadRegistrar versioned(String version)
      Defines that the payloads registered by this registrar have a specific version associated with them. Clients connecting to a server with these payloads, will only be able to connect if they have the same version.
      Parameters:
      version - The version to use.
      Returns:
      A new registrar, ready to configure payloads with that version.
    • optional

      IPayloadRegistrar optional()
      Defines that the payloads registered by this registrar are optional. Clients connecting to a server which do not have the payloads registered, will still be able to connect.

      If clients have also a version set, and a version mismatch occurs (so both client and server have the payloads registered, yet have different versions), the connection attempt will fail. In other words, marking a payload as optional does not exempt it from versioning, if it has that configured.

      Returns:
      A new registrar, ready to configure payloads as optional.