Skip to content

Packet Types

Endor H edited this page Jan 24, 2023 · 2 revisions

Warning: When (or if) this mod gets ported to Fabric, this API is likely to be entirely redesigned.

Lazulib provides some useful base classes to create packets.

These classes define helpers to register your packet classes in a network channel.

All your packet subclasses must implement the serialize and deserialize methods, and have a public constructor with no arguments.

ClientPlayerPacket

Serverbound packet carrying a player reference.

You may override the onServer(Player player, Context ctx) method to handle this packet on the server.

You may send this packet to the server with its send() method.

ServerPlayerPacket

Clientbound packet carrying a player reference. You may override the onClient(Player player, Context ctx) method to handle this packet on the client.

You may use the sendTrackingAndSelf() method to send this packet to all players tracking the referred player, or sendTo(PacketTarget target) to send it to a specific target.

DistributedPlayerPacket

Special serverbound packet carrying a player reference, which is automatically relayed to other players (based on a PacketDistributor specified when registering the packet). For example, you may use the following registering methods, which provide default behaviors:

  • registerLocal relay the packet to any players tracking the sender
  • registerGlobal relay the packet to all players

You can override the following methods to handle the packet:

  • onCommon(Player sender, Context ctx) called from the default implementations of onClient and onServer
  • onServer(Player sender, Context ctx) handle the packet on the server. Here, you may also modify the packet before it is relayed to other players.
  • onServerCancellable(Player sender, Context ctx) like onServer but lets you cancel the relay by returning false
  • onClient(Player sender, Context ctx) handle the packet on the client side when relayed

You may use the send() method to send this packet from the client side. You may also use the sendBack() method on the server to send back the same packet to the original player with corrected values.

ValidatedDistributedPlayerPacket

Like a DistributedPlayerPacket, but with extra methods to invalidate packets:

  • invalidate() call this from your onServer method to reject this packet
  • validateClamp(value, min, max) clamp value between min and max and invalidate the packet if the clamp was necessary
  • validateClose(a, b, delta) check if a and b are closer than delta, clamping a to the maximum allowed deviation if not
  • setPropagate(propagate) if prapagate is set to false, the packet will not be elayed to other clients when invalidated. It is set to true by default.

Invalidated packets are still relayed to other players unless you call setPropagate(false). Invalidated packets are always sent back to the sender with corrected values.

ServerWorldPacket

Clientbound packet carrying a reference to a world/level.

You may override the onClient(Level world, Context ctx) method to handle this packet on the client side.

You may send this packet to all players in the relevant world/level with the sendTracking() method, and to a specific target by using sendTarget(PacketTarget target).


Registering packets

To register packets of one of the above classes, use their respective static with(SimpleChannel channel, Supplier<Integer> idSupplier) methods, which return a PacketRegisterer object. This object will support different registering methods depending on the packet type you're registering.

For an example, you may see how Aerobatic Elytra registers its packets on its network package.

@EventBusSubscriber(bus = Bus.FORGE)
public class NetworkHandler {
   protected static final String PROTOCOL_VERSION = "1";
   protected static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel(
     new ResourceLocation("mymodid:my-channel-id"),
     () -> PROTOCOL_VERSION,
     PROTOCOL_VERSION::equals,
     PROTOCOL_VERSION::equals);

   private static int ID_COUNT = 0;
   protected static Supplier<Integer> ID_GEN = () -> ID_COUNT++;
   
   // All packets must be registered in sequential order in both sides
   @SubscribeEvent
   public static void onCommonSetup(FMLCommonSetupEvent event) {
      ClientPlayerPacket.with(NetworkHandler.CHANNEL, ID_GEN)
        .register(UpgradeRecipePacket::new);
      ServerPlayerPacket.with(NetworkHandler.CHANNEL, NetworkHandler.ID_GEN)
        .register(SFlightDataPacket::new)
        .register(SAerobaticDataPacket::new);
      DistributedPlayerPacket.with(NetworkHandler.CHANNEL, NetworkHandler.ID_GEN)
        .registerLocal(DFlightModePacket::new)
        .registerLocal(DTiltPacket::new)
        .registerLocal(DAccelerationPacket::new)
        .registerLocal(DSneakingPacket::new)
        .registerLocal(DJumpingPacket::new)
        .registerLocal(DSprintingPacket::new)
        .registerLocal(DRotationPacket::new)
        .registerLocal(DLookAroundPacket::new);
      ServerWorldPacket.with(NetworkHandler.CHANNEL, NetworkHandler.ID_GEN)
        .register(SWindNodePacket::new);
   }
}

Clone this wiki locally