tutorial:networking
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
tutorial:networking [2021/01/20 13:51] – ytg1234 | tutorial:networking [2024/10/26 20:39] (current) – [How do I fix the crash?] double "be" fix 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: | The old page can be [[tutorial: | ||
+ | |||
+ | For the even newer networking API introduced at 1.20.5, read the [[# | ||
====== Networking ====== | ====== Networking ====== | ||
Line 15: | Line 15: | ||
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=" | <code java [enable_line_numbers=" | ||
- | class HighlightingWandItem extends Item { | + | public |
public HighlightingWand(Item.Settings settings) { | public HighlightingWand(Item.Settings settings) { | ||
super(settings) | super(settings) | ||
Line 51: | Line 51: | ||
[[Minecraft' | [[Minecraft' | ||
- | The diagram above shows that the game client and dedicated server | + | The diagram above shows that the game client and dedicated server |
^ Connection Type ^ Access to game client | ^ Connection Type ^ Access to game client | ||
Line 58: | Line 58: | ||
| Singleplayer (or LAN host) | Yes -> Full access | | Singleplayer (or LAN host) | Yes -> Full access | ||
- | It may seem complicated to have communication with the server in three different ways. However, you don't need to communicate in three different ways with the game client. Since all three connection types communicate with the game client using packets, you only need to communicate with the game client like you are always running on a dedicated server. Connection to a server over LAN or Singleplayer can be also be treated like the server is a remote dedicated server; so your game client cannot directly access the server instance. | + | It may seem complicated to have communication with the server in three different ways. However, you don't need to communicate in three different ways with the game client. Since all three connection types communicate with the game client using packets, you only need to communicate with the game client like you are always running on a dedicated server. Connection to a server over LAN or Singleplayer can also be treated like the server is a remote dedicated server; so your game client cannot directly access the server instance. |
===== An introduction to networking ===== | ===== An introduction to networking ===== | ||
Line 80: | Line 80: | ||
</ | </ | ||
- | Next, we need to send the packet to the game client. First, you need to define an '' | + | Next, we need to send the packet to the game client. First, you need to define an '' |
+ | <code java> | ||
+ | public class TutorialNetworkingConstants { | ||
+ | // Save the id of the packet so we can reference it later | ||
+ | public static final Identifier HIGHLIGHT_PACKET_ID = Identifier.of(" | ||
+ | } | ||
+ | </ | ||
To send the packet to the player, we will use some of the methods inside of '' | To send the packet to the player, we will use some of the methods inside of '' | ||
Line 95: | Line 101: | ||
<code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
.... | .... | ||
- | ServerPlayNetworking.send((ServerPlayerEntity) user, ModNetworkingConstants.HIGHLIGHT_PACKET_ID, | + | ServerPlayNetworking.send((ServerPlayerEntity) user, TutorialNetworkingConstants.HIGHLIGHT_PACKET_ID, |
return TypedActionResult.success(user.getHandStack(hand)); | return TypedActionResult.success(user.getHandStack(hand)); | ||
} | } | ||
Line 105: | Line 111: | ||
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 '' | + | In your client entrypoint, you will register the receiver for your packet using '' |
The '' | The '' | ||
Line 112: | Line 118: | ||
<code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
- | ClientPlayNetworking.registerGlobalReceiver(ModNetworkingConstants.HIGHLIGHT_PACKET_ID, | + | ClientPlayNetworking.registerGlobalReceiver(TutorialNetworkingConstants.HIGHLIGHT_PACKET_ID, |
... | ... | ||
}); | }); | ||
Line 122: | Line 128: | ||
<code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
- | ClientPlayNetworking.registerGlobalReceiver(ModNetworkingConstants.HIGHLIGHT_PACKET_ID, | + | ClientPlayNetworking.registerGlobalReceiver(TutorialNetworkingConstants.HIGHLIGHT_PACKET_ID, |
client.execute(() -> { | client.execute(() -> { | ||
// Everything in this lambda is run on the render thread | // Everything in this lambda is run on the render thread | ||
- | ClientBlockHighlighting.highlightBlock(client, | ||
}); | }); | ||
}); | }); | ||
Line 152: | Line 157: | ||
In the end, the client' | In the end, the client' | ||
<code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
- | ClientPlayNetworking.registerGlobalReceiver(ModNetworkingConstants.HIGHLIGHT_PACKET_ID, | + | ClientPlayNetworking.registerGlobalReceiver(TutorialNetworkingConstants.HIGHLIGHT_PACKET_ID, |
// 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 174: | ||
Firstly sending a packet to the server is done through '' | Firstly sending a packet to the server is done through '' | ||
- | ===== 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 188: | ||
buf.writeBlockPos(target); | buf.writeBlockPos(target); | ||
- | ServerPlayNetworking.send((ServerPlayerEntity) user, ModNetworkingConstants.HIGHLIGHT_PACKET_ID, | + | ServerPlayNetworking.send((ServerPlayerEntity) user, TutorialNetworkingConstants.HIGHLIGHT_PACKET_ID, |
return TypedActionResult.success(user.getHandStack(hand)); | return TypedActionResult.success(user.getHandStack(hand)); | ||
} | } | ||
Line 204: | Line 209: | ||
// 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, | + | ServerPlayNetworking.send(player, |
} | } | ||
Line 213: | Line 218: | ||
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 | + | ===== Networking |
+ | Since 1.20.5, the logic of networking has been totally rewritten. In 1.20.5, '' | ||
- | ^ Networking Topic ^ Description ^ | + | <code java> |
- | | [[tutorial:networking:connection_events|Connection Network connection events]] | Events related | + | 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 CustomPayload.Id< |
- | | [[tutorial:networking:login|Login phase networking]]| Sending requests to a client during login; and allowing delay of login for a short amount of time | | + | public static final PacketCodec< |
- | | [[tutorial:networking:dynamic_handlers|Dynamic registration of channel handlers]]| Allowing for a connection to receive a packet with a special handler | | + | // should you need to send more data, add the appropriate record parameters and change your codec: |
+ | // public static final PacketCodec< | ||
+ | // | ||
+ | // | ||
+ | // | ||
+ | // | ||
+ | // ); | ||
+ | @Override | ||
+ | public CustomPayload.Id<? | ||
+ | return ID; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | And then, register the receiver like this: | ||
+ | <code java> | ||
+ | // NOTE: PayloadTypeRegistry has 2 functions: | ||
+ | // - playS2C is for server -> client communication | ||
+ | // - playC2S is for client -> server communication | ||
+ | |||
+ | // In your common initializer method | ||
+ | PayloadTypeRegistry.playS2C().register(BlockHighlightPayload.ID, | ||
+ | |||
+ | // In your client-only initializer method | ||
+ | ClientPlayNetworking.registerGlobalReceiver(BlockHighlightPayload.ID, | ||
+ | context.client().execute(() -> { | ||
+ | ClientBlockHighlighting.highlightBlock(client, | ||
+ | }); | ||
+ | }); | ||
+ | </ | ||
+ | |||
+ | Now, on the server side, you can send the packet to players like this: | ||
+ | <code java> | ||
+ | public TypedActionResult< | ||
+ | if (world.isClient()) return super.use(world, | ||
+ | |||
+ | // ... | ||
+ | |||
+ | for (ServerPlayerEntity player : PlayerLookup.tracking((ServerWorld) world, target)) { | ||
+ | ServerPlayNetworking.send(player, | ||
+ | } | ||
+ | |||
+ | return TypedActionResult.success(user.getHandStack(hand)); | ||
+ | } | ||
+ | </ |
tutorial/networking.1611150692.txt.gz · Last modified: 2021/01/20 13:51 by ytg1234