User Tools

Site Tools


tutorial:networking

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Last revisionBoth sides next revision
tutorial:networking [2021/01/20 13:51] ytg1234tutorial:networking [2024/04/24 18:53] – [Networking in 1.20.5] Grammar skycatminepokie
Line 1: Line 1:
-====== Page Information ====== +**Note: **This page has replaced the old networking page.
- +
-This page has replaced the old networking page.+
 It is recommended to use the new networking API described on this page. It is recommended to use the new networking API described on this page.
 The old page can be [[tutorial:legacy:networking-v0|found here]]. The old page can be [[tutorial:legacy:networking-v0|found here]].
Line 15: Line 13:
 Say you had a wand which highlights the block you are looking at to all nearby players. Say you had a wand which highlights the block you are looking at to all nearby players.
 <code java [enable_line_numbers="true"]> <code java [enable_line_numbers="true"]>
-class HighlightingWandItem extends Item {+public class HighlightingWandItem extends Item {
     public HighlightingWand(Item.Settings settings) {     public HighlightingWand(Item.Settings settings) {
         super(settings)         super(settings)
Line 51: Line 49:
 [[Minecraft's Logical Sides|{{tutorial:sides.png?700}}]] [[Minecraft's Logical Sides|{{tutorial:sides.png?700}}]]
  
-The diagram above shows that the game client and dedicated server art separate systems bridged together using packets. This packet bridge does not only exist between a game client and dedicated server, but also between your client and another client connected over LAN. The packet bridge is also present even in singleplayer! This is because the game client will spin up a special integrated server instance to run the game on. The key difference between the three types of connections that are shown in the table below:+The diagram above shows that the game client and dedicated server are separate systems bridged together using packets. This packet bridge does not only exist between a game client and dedicated server, but also between your client and another client connected over LAN. The packet bridge is also present even in singleplayer! This is because the game client will spin up a special integrated server instance to run the game on. The key difference between the three types of connections that are shown in the table below:
  
 ^ Connection Type               ^ Access to game client       ^ ^ Connection Type               ^ Access to game client       ^
Line 80: Line 78:
 </code> </code>
  
-Next, we need to send the packet to the game client. First, you need to define an ''Identifier'' used to identify your packet. For this example our Identifier will be ''wiki_example:highlight_block''. In order to send the packet to the game client, you need to specify which player's game client you want to packet to be received by. Since the action is occurring on the logical server, we may upcast the ''player'' to a ''ServerPlayerEntity''.+Next, we need to send the packet to the game client. First, you need to define an ''Identifier'' used to identify your packet. For this example our Identifier will be ''wiki_example:highlight_block''. In order to send the packet to the game client, you need to specify which player's game client you want the packet to be received by. Since the action is occurring on the logical server, we may upcast the ''player'' to a ''ServerPlayerEntity''. 
 +<code java> 
 +public class TutorialNetworkingConstants { 
 +    // Save the id of the packet so we can reference it later 
 +    public static final Identifier HIGHLIGHT_PACKET_ID = new Identifier("wiki_example", "highlight_block"); 
 +
 +</code>
  
 To send the packet to the player, we will use some of the methods inside of ''ServerPlayNetworking''. We will use the following method inside of that class: To send the packet to the player, we will use some of the methods inside of ''ServerPlayNetworking''. We will use the following method inside of that class:
Line 95: Line 99:
 <code java [enable_line_numbers="true", highlight_lines_extra="2"]> <code java [enable_line_numbers="true", highlight_lines_extra="2"]>
     ....     ....
-    ServerPlayNetworking.send((ServerPlayerEntity) user, ModNetworkingConstants.HIGHLIGHT_PACKET_ID, PacketByteBufs.empty());+    ServerPlayNetworking.send((ServerPlayerEntity) user, TutorialNetworkingConstants.HIGHLIGHT_PACKET_ID, PacketByteBufs.empty());
     return TypedActionResult.success(user.getHandStack(hand));     return TypedActionResult.success(user.getHandStack(hand));
 } }
Line 105: Line 109:
  
 To receive a packet from a server on the game client, your mod needs to specify how it will handle the incoming packet. To receive a packet from a server on the game client, your mod needs to specify how it will handle the incoming packet.
-In your client entrypoint, you will register the receiver for your packet using ''PlayClientNetworking.registerGlobalReceiver(Identifier channelName, ChannelHandler channelHandler)''+In your client entrypoint, you will register the receiver for your packet using ''ClientPlayNetworking.registerGlobalReceiver(Identifier channelName, ChannelHandler channelHandler)''
  
 The ''Identifier'' should match the same Identifier you use to send the packet to the client. The ''ChannelHandler'' is the functional interface you will use to implement how the packet is handled. **Note the ''ChannelHandler'' should be the one that is a nested interface of ''ClientPlayNetworking''** The ''Identifier'' should match the same Identifier you use to send the packet to the client. The ''ChannelHandler'' is the functional interface you will use to implement how the packet is handled. **Note the ''ChannelHandler'' should be the one that is a nested interface of ''ClientPlayNetworking''**
Line 112: Line 116:
  
 <code java [enable_line_numbers="true"]> <code java [enable_line_numbers="true"]>
-ClientPlayNetworking.registerGlobalReceiver(ModNetworkingConstants.HIGHLIGHT_PACKET_ID, (client, handler, buf, responseSender) -> {+ClientPlayNetworking.registerGlobalReceiver(TutorialNetworkingConstants.HIGHLIGHT_PACKET_ID, (client, handler, buf, responseSender) -> {
     ...     ...
 }); });
Line 122: Line 126:
  
 <code java [enable_line_numbers="true"]> <code java [enable_line_numbers="true"]>
-ClientPlayNetworking.registerGlobalReceiver(ModNetworkingConstants.HIGHLIGHT_PACKET_ID, (client, handler, buf, responseSender) -> {+ClientPlayNetworking.registerGlobalReceiver(TutorialNetworkingConstants.HIGHLIGHT_PACKET_ID, (client, handler, buf, responseSender) -> {
     client.execute(() -> {     client.execute(() -> {
         // Everything in this lambda is run on the render thread         // Everything in this lambda is run on the render thread
Line 152: Line 156:
 In the end, the client's handler would look like this: In the end, the client's handler would look like this:
 <code java [enable_line_numbers="true"]> <code java [enable_line_numbers="true"]>
-ClientPlayNetworking.registerGlobalReceiver(ModNetworkingConstants.HIGHLIGHT_PACKET_ID, (client, handler, buf, responseSender) -> {+ClientPlayNetworking.registerGlobalReceiver(TutorialNetworkingConstants.HIGHLIGHT_PACKET_ID, (client, handler, buf, responseSender) -> {
     // Read packet data on the event loop     // Read packet data on the event loop
     BlockPos target = buf.readBlockPos();     BlockPos target = buf.readBlockPos();
Line 169: Line 173:
 Firstly sending a packet to the server is done through ''ClientPlayNetworking.send''. Receiving a packet on the server is similar to receiving a packet on the client, using the ''ServerPlayNetworking.registerGlobalReceiver(Identifier channelName, ChannelHandler channelHandler)'' method. The ''ChannelHandler'' for the server networking also passes the ''ServerPlayerEntity'' (player) who sent the packet through the ''player'' parameter. Firstly sending a packet to the server is done through ''ClientPlayNetworking.send''. Receiving a packet on the server is similar to receiving a packet on the client, using the ''ServerPlayNetworking.registerGlobalReceiver(Identifier channelName, ChannelHandler channelHandler)'' method. The ''ChannelHandler'' for the server networking also passes the ''ServerPlayerEntity'' (player) who sent the packet through the ''player'' parameter.
  
-===== The concept of tracking and why you only see the highlighted block =====+===== The concept of tracking and why only you see the highlighted block =====
  
 Now that the highlighting wand properly uses networking so the dedicated server does not crash, you invite your friend back on the server to show off the highlighting wand. You use the wand and the block is highlighted on your client and the server does not crash. However, your friend does not see the highlighted block. This is intentional with the code that you already have here. To solve this issue let us take a look at the item's use code: Now that the highlighting wand properly uses networking so the dedicated server does not crash, you invite your friend back on the server to show off the highlighting wand. You use the wand and the block is highlighted on your client and the server does not crash. However, your friend does not see the highlighted block. This is intentional with the code that you already have here. To solve this issue let us take a look at the item's use code:
Line 183: Line 187:
         buf.writeBlockPos(target);         buf.writeBlockPos(target);
  
-        ServerPlayNetworking.send((ServerPlayerEntity) user, ModNetworkingConstants.HIGHLIGHT_PACKET_ID, buf);+        ServerPlayNetworking.send((ServerPlayerEntity) user, TutorialNetworkingConstants.HIGHLIGHT_PACKET_ID, buf);
         return TypedActionResult.success(user.getHandStack(hand));         return TypedActionResult.success(user.getHandStack(hand));
     }     }
Line 204: Line 208:
         // Iterate over all players tracking a position in the world and send the packet to each player         // Iterate over all players tracking a position in the world and send the packet to each player
         for (ServerPlayerEntity player : PlayerLookup.tracking((ServerWorld) world, target)) {         for (ServerPlayerEntity player : PlayerLookup.tracking((ServerWorld) world, target)) {
-            ServerPlayNetworking.send(player, ModNetworkingConstants.HIGHLIGHT_PACKET_ID, buf);+            ServerPlayNetworking.send(player, TutorialNetworkingConstants.HIGHLIGHT_PACKET_ID, buf);
         }         }
  
Line 213: Line 217:
 After this change, when you use the wand, your friend should also see the highlighted block on their own client. After this change, when you use the wand, your friend should also see the highlighted block on their own client.
  
-====== Advanced Networking topics ====== 
  
-The Networking system Fabric API supplies is very flexible and supports additional features other than just sending and receiving simple packetsAs some of these more advanced topics are longhere are links to their specific pages:+===== Networking in 1.20.5 ===== 
 +Since 1.20.5, the logic of networking has been totally rewritten. In 1.20.5you have to define a custom ''Payload''. First, define the payload that includes a ''BlockPos'':
  
-^ Networking Topic ^ Description ^ +<code java> 
-| [[tutorial:networking:connection_events|Connection Network connection events]] | Events related to the the lifecycle of a connection to a client or server | +public record BlockHighlightPayload(BlockPos blockPos) implements CustomPayload { 
-| [[tutorial:networking:channel_events|Channel registration events]] | Events related to a server of client declaring the ability to receive a packet on a channel of a specific name | +  public static final Id<BlockHighlightPayload> ID = CustomPayload.id("tutorial:block_highlight"); 
-| [[tutorial:networking:login|Login phase networking]]| Sending requests to a client during loginand allowing delay of login for a short amount of time | +  public static final PacketCodec<PacketByteBuf, BlockHighlightPayload> CODEC = PacketCodec.tuple(BlockPos.PACKET_CODEC, BlockHighlightPayload::blockPos, BlockHighlightPayload::new)
-| [[tutorial:networking:dynamic_handlers|Dynamic registration of channel handlers]]| Allowing for a connection to receive a packet with a special handler |+  // or you can also write like this: 
 +  // public static final PacketCodec<PacketByteBuf, BlockHighlightPayload> CODEC = PacketCodec.of((value, buf) -> buf.writeBlockPos(value.blockPos), buf -> new BlockHighlightPayload(buf.readBlockPos()));
  
 +  @Override
 +  public Id<? extends CustomPayload> getId() {
 +    return ID;
 +  }
 +}
 +</code>
 +
 +And then, register the receiver like this:
 +<code java>
 +PayloadTypeRegistry.playS2C().register(BlockHighlightPayload.ID, BlockHighlightPayload.CODEC);
 +ClientPlayNetworking.registerGlobalReceiver(BlockHighlightPayload.ID, (payload, context) -> {
 +  context.client().execute(() -> {
 +    ClientBlockHighlighting.highlightBlock(client, target);
 +  });
 +});
 +</code>
 +
 +Now, on the server side, you can send the packet to players like this:
 +<code java>
 +    public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) {
 +        if (world.isClient()) return super.use(world, user, hand);
 +
 +        // ...
 +
 +        for (ServerPlayerEntity player : PlayerLookup.tracking((ServerWorld) world, target)) {
 +            ServerPlayNetworking.send(player, new BlockHighlightPayload(blockPos));
 +        }
 +
 +        return TypedActionResult.success(user.getHandStack(hand));
 +    }
 +</code>
tutorial/networking.txt · Last modified: 2024/05/04 19:51 by bluemeanial