Skip to content

Commit

Permalink
Improved networking docs + apis
Browse files Browse the repository at this point in the history
  • Loading branch information
modmuss50 committed Aug 6, 2023
1 parent 0ac3dec commit f85c746
Show file tree
Hide file tree
Showing 19 changed files with 276 additions and 134 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@
import java.util.function.Consumer;

import io.netty.buffer.Unpooled;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.minecraft.screen.ScreenHandler;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;
import net.minecraft.network.PacketByteBuf;

import net.fabricmc.fabric.api.container.ContainerFactory;
import net.fabricmc.fabric.api.container.ContainerProviderRegistry;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.fabricmc.fabric.mixin.container.ServerPlayerEntityAccessor;

public class ContainerProviderImpl implements ContainerProviderRegistry {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
package net.fabricmc.fabric.api.registry;

import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import net.minecraft.registry.Registries;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.minecraft.registry.Registries;
import net.minecraft.registry.tag.GameEventTags;
import net.minecraft.world.event.GameEvent;
import net.minecraft.world.event.Vibrations;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@

import java.util.List;

import org.jetbrains.annotations.ApiStatus;

import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientConfigurationNetworkHandler;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.util.Identifier;

Expand Down Expand Up @@ -50,6 +53,28 @@ public final class C2SPlayChannelEvents {
}
});

/**
* An event for the client configuration network handler receiving an update indicating the connected server's ability to receive packets in certain channels.
* This event may be invoked at any time after login and up to disconnection.
*/
@ApiStatus.Experimental
public static final Event<RegisterConfiguration> REGISTER_CONFIGURATION = EventFactory.createArrayBacked(RegisterConfiguration.class, callbacks -> (handler, sender, client, channels) -> {
for (RegisterConfiguration callback : callbacks) {
callback.onChannelRegister(handler, sender, client, channels);
}
});

/**
* An event for the client configuration network handler receiving an update indicating the connected server's lack of ability to receive packets in certain channels.
* This event may be invoked at any time after login and up to disconnection.
*/
@ApiStatus.Experimental
public static final Event<UnregisterConfiguration> UNREGISTER_CONFIGURATION = EventFactory.createArrayBacked(UnregisterConfiguration.class, callbacks -> (handler, sender, client, channels) -> {
for (UnregisterConfiguration callback : callbacks) {
callback.onChannelUnregister(handler, sender, client, channels);
}
});

private C2SPlayChannelEvents() {
}

Expand All @@ -68,4 +93,22 @@ public interface Register {
public interface Unregister {
void onChannelUnregister(ClientPlayNetworkHandler handler, PacketSender sender, MinecraftClient client, List<Identifier> channels);
}

/**
* @see C2SPlayChannelEvents#REGISTER_CONFIGURATION
*/
@FunctionalInterface
@ApiStatus.Experimental
public interface RegisterConfiguration {
void onChannelRegister(ClientConfigurationNetworkHandler handler, PacketSender sender, MinecraftClient client, List<Identifier> channels);
}

/**
* @see C2SPlayChannelEvents#UNREGISTER_CONFIGURATION
*/
@FunctionalInterface
@ApiStatus.Experimental
public interface UnregisterConfiguration {
void onChannelUnregister(ClientConfigurationNetworkHandler handler, PacketSender sender, MinecraftClient client, List<Identifier> channels);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,65 @@

package net.fabricmc.fabric.api.client.networking.v1;

import org.jetbrains.annotations.ApiStatus;

import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientConfigurationNetworkHandler;
import net.minecraft.util.Identifier;

import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;

/**
* Offers access to events related to the configuration connection to a server on a logical client.
*/
@ApiStatus.Experimental
public class ClientConfigurationConnectionEvents {
/**
* Event indicating a connection entered the CONFIGURATION state, ready for registering channel handlers.
*
* @see ClientConfigurationNetworking#registerReceiver(Identifier, ClientConfigurationNetworking.ConfigurationChannelHandler)
*/
public static final Event<ClientConfigurationConnectionEvents.Init> INIT = EventFactory.createArrayBacked(ClientConfigurationConnectionEvents.Init.class, callbacks -> (handler, client) -> {
for (ClientConfigurationConnectionEvents.Init callback : callbacks) {
callback.onConfigurationInit(handler, client);
}
});

/**
* An event called after the ReadyS2CPacket has been received, just before switching to the PLAY state.
*
* <p>No packets should be sent when this event is invoked.
*/
public static final Event<ClientConfigurationConnectionEvents.Ready> READY = EventFactory.createArrayBacked(ClientConfigurationConnectionEvents.Ready.class, callbacks -> (handler, client) -> {
for (ClientConfigurationConnectionEvents.Ready callback : callbacks) {
callback.onConfigurationReady(handler, client);
}
});

/**
* An event for the disconnection of the client configuration network handler.
*
* <p>No packets should be sent when this event is invoked.
*/
public static final Event<ClientConfigurationConnectionEvents.Disconnect> DISCONNECT = EventFactory.createArrayBacked(ClientConfigurationConnectionEvents.Disconnect.class, callbacks -> (handler, client) -> {
for (ClientConfigurationConnectionEvents.Disconnect callback : callbacks) {
callback.onConfigurationDisconnect(handler, client);
}
});

@FunctionalInterface
public interface Init {
void onConfigurationInit(ClientConfigurationNetworkHandler handler, MinecraftClient client);
}

@FunctionalInterface
public interface Ready {
void onConfigurationReady(ClientConfigurationNetworkHandler handler, MinecraftClient client);
}

@FunctionalInterface
public interface Disconnect {
void onConfigurationDisconnect(ClientConfigurationNetworkHandler handler, MinecraftClient client);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.Objects;
import java.util.Set;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;

import net.minecraft.client.MinecraftClient;
Expand All @@ -33,10 +34,25 @@
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.PacketSender;
import net.fabricmc.fabric.api.networking.v1.PacketType;
import net.fabricmc.fabric.api.networking.v1.ServerConfigurationNetworking;
import net.fabricmc.fabric.impl.networking.client.ClientConfigurationNetworkAddon;
import net.fabricmc.fabric.impl.networking.client.ClientNetworkingImpl;
import net.fabricmc.fabric.mixin.networking.client.accessor.ClientCommonNetworkHandlerAccessor;

/**
* Offers access to configurtion stage client-side networking functionalities.
*
* <p>Client-side networking functionalities include receiving clientbound packets,
* sending serverbound packets, and events related to client-side network handlers.
*
* <p>This class should be only used on the physical client and for the logical client.
*
* <p>See {@link net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking} for information on how to use the packet
* object-based API.
*
* @see ServerConfigurationNetworking
*/
@ApiStatus.Experimental
public final class ClientConfigurationNetworking {
/**
* Registers a handler to a channel.
Expand Down Expand Up @@ -169,7 +185,7 @@ public static boolean registerReceiver(Identifier channelName, ConfigurationChan
return addon.registerChannel(channelName, channelHandler);
}

throw new IllegalStateException("Cannot register receiver while not in game!");
throw new IllegalStateException("Cannot register receiver while not configuring!");
}

/**
Expand Down Expand Up @@ -230,7 +246,7 @@ public static ClientConfigurationNetworking.ConfigurationChannelHandler unregist
return addon.unregisterChannel(channelName);
}

throw new IllegalStateException("Cannot unregister receiver while not in game!");
throw new IllegalStateException("Cannot unregister receiver while not configuring!");
}

/**
Expand Down Expand Up @@ -263,7 +279,7 @@ public static Set<Identifier> getReceived() throws IllegalStateException {
return addon.getReceivableChannels();
}

throw new IllegalStateException("Cannot get a list of channels the client can receive packets on while not in game!");
throw new IllegalStateException("Cannot get a list of channels the client can receive packets on while not configuring!");
}

/**
Expand All @@ -279,7 +295,7 @@ public static Set<Identifier> getSendable() throws IllegalStateException {
return addon.getSendableChannels();
}

throw new IllegalStateException("Cannot get a list of channels the server can receive packets on while not in game!");
throw new IllegalStateException("Cannot get a list of channels the server can receive packets on while not configuring!");
}

/**
Expand All @@ -290,12 +306,13 @@ public static Set<Identifier> getSendable() throws IllegalStateException {
* False if the client is not in game.
*/
public static boolean canSend(Identifier channelName) throws IllegalArgumentException {
// You cant send without a client player, so this is fine
if (MinecraftClient.getInstance().getNetworkHandler() != null) {
return ClientNetworkingImpl.getAddon(MinecraftClient.getInstance().getNetworkHandler()).getSendableChannels().contains(channelName);
final ClientConfigurationNetworkAddon addon = ClientNetworkingImpl.getClientConfigurationAddon();

if (addon != null) {
return addon.getSendableChannels().contains(channelName);
}

return false;
throw new IllegalStateException("Cannot get a list of channels the server can receive packets on while not configuring!");
}

/**
Expand All @@ -320,7 +337,7 @@ public static Packet<ServerCommonPacketListener> createC2SPacket(Identifier chan
Objects.requireNonNull(channelName, "Channel name cannot be null");
Objects.requireNonNull(buf, "Buf cannot be null");

return ClientNetworkingImpl.createPlayC2SPacket(channelName, buf);
return ClientNetworkingImpl.createC2SPacket(channelName, buf);
}

/**
Expand All @@ -330,12 +347,13 @@ public static Packet<ServerCommonPacketListener> createC2SPacket(Identifier chan
* @throws IllegalStateException if the client is not connected to a server
*/
public static PacketSender getSender() throws IllegalStateException {
// You cant send without a client player, so this is fine
if (MinecraftClient.getInstance().getNetworkHandler() != null) {
return ClientNetworkingImpl.getAddon(MinecraftClient.getInstance().getNetworkHandler());
final ClientConfigurationNetworkAddon addon = ClientNetworkingImpl.getClientConfigurationAddon();

if (addon != null) {
return addon;
}

throw new IllegalStateException("Cannot get packet sender when not in game!");
throw new IllegalStateException("Cannot get PacketSender while not configuring!");
}

/**
Expand All @@ -346,13 +364,14 @@ public static PacketSender getSender() throws IllegalStateException {
* @throws IllegalStateException if the client is not connected to a server
*/
public static void send(Identifier channelName, PacketByteBuf buf) throws IllegalStateException {
// You cant send without a client player, so this is fine
if (MinecraftClient.getInstance().getNetworkHandler() != null) {
MinecraftClient.getInstance().getNetworkHandler().sendPacket(createC2SPacket(channelName, buf));
final ClientConfigurationNetworkAddon addon = ClientNetworkingImpl.getClientConfigurationAddon();

if (addon != null) {
addon.sendPacket(createC2SPacket(channelName, buf));
return;
}

throw new IllegalStateException("Cannot send packets when not in game!");
throw new IllegalStateException("Cannot send packet while not configuring!");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
* object-based API.
*
* @see ClientLoginNetworking
* @see ClientConfigurationNetworking
* @see ServerPlayNetworking
*/
public final class ClientPlayNetworking {
Expand Down Expand Up @@ -335,7 +336,7 @@ public static Packet<ServerCommonPacketListener> createC2SPacket(Identifier chan
Objects.requireNonNull(channelName, "Channel name cannot be null");
Objects.requireNonNull(buf, "Buf cannot be null");

return ClientNetworkingImpl.createPlayC2SPacket(channelName, buf);
return ClientNetworkingImpl.createC2SPacket(channelName, buf);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,14 @@
import java.util.List;
import java.util.Map;

import com.mojang.logging.LogUtils;
import org.slf4j.Logger;

import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientConfigurationNetworkHandler;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.packet.Packet;
import net.minecraft.util.Identifier;

import net.fabricmc.fabric.api.client.networking.v1.C2SPlayChannelEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientConfigurationConnectionEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientConfigurationNetworking;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.impl.networking.AbstractChanneledNetworkAddon;
Expand All @@ -43,8 +42,6 @@ public final class ClientConfigurationNetworkAddon extends AbstractChanneledNetw
private final MinecraftClient client;
private boolean sentInitialRegisterPacket;

private static final Logger LOGGER = LogUtils.getLogger();

public ClientConfigurationNetworkAddon(ClientConfigurationNetworkHandler handler, MinecraftClient client) {
super(ClientNetworkingImpl.CONFIGURATION, ((ClientCommonNetworkHandlerAccessor) handler).getConnection(), "ClientPlayNetworkAddon for " + ((ClientConfigurationNetworkHandlerAccessor) handler).getProfile().getName());
this.handler = handler;
Expand All @@ -62,6 +59,8 @@ public void lateInit() {
for (Map.Entry<Identifier, ClientConfigurationNetworking.ConfigurationChannelHandler> entry : this.receiver.getHandlers().entrySet()) {
this.registerChannel(entry.getKey(), entry.getValue());
}

ClientConfigurationConnectionEvents.INIT.invoker().onConfigurationInit(this.handler, this.client);
}

public void onServerReady() {
Expand Down Expand Up @@ -103,12 +102,12 @@ public Packet<?> createPacket(Identifier channelName, PacketByteBuf buf) {

@Override
protected void invokeRegisterEvent(List<Identifier> ids) {
// C2SPlayChannelEvents.REGISTER.invoker().onChannelRegister(this.handler, this, this.client, ids);
C2SPlayChannelEvents.REGISTER_CONFIGURATION.invoker().onChannelRegister(this.handler, this, this.client, ids);
}

@Override
protected void invokeUnregisterEvent(List<Identifier> ids) {
// C2SPlayChannelEvents.UNREGISTER.invoker().onChannelUnregister(this.handler, this, this.client, ids);
C2SPlayChannelEvents.UNREGISTER_CONFIGURATION.invoker().onChannelUnregister(this.handler, this, this.client, ids);
}

@Override
Expand All @@ -135,9 +134,14 @@ protected void handleUnregistration(Identifier channelName) {
}
}

public void handleReady() {
ClientConfigurationConnectionEvents.READY.invoker().onConfigurationReady(this.handler, this.client);
ClientNetworkingImpl.setClientConfigurationAddon(null);
}

@Override
protected void invokeDisconnectEvent() {
// ClientPlayConnectionEvents.DISCONNECT.invoker().onPlayDisconnect(this.handler, this.client);
ClientConfigurationConnectionEvents.DISCONNECT.invoker().onConfigurationDisconnect(this.handler, this.client);
this.receiver.endSession(this);
}

Expand Down
Loading

0 comments on commit f85c746

Please sign in to comment.