diff --git a/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/api/client/networking/v1/ClientConfigurationNetworking.java b/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/api/client/networking/v1/ClientConfigurationNetworking.java index 455771367e..e209899a60 100644 --- a/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/api/client/networking/v1/ClientConfigurationNetworking.java +++ b/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/api/client/networking/v1/ClientConfigurationNetworking.java @@ -32,9 +32,11 @@ import net.fabricmc.fabric.api.networking.v1.FabricPacket; 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.impl.networking.payload.RetainedPayload; +import net.fabricmc.fabric.impl.networking.payload.TypedPayload; +import net.fabricmc.fabric.impl.networking.payload.UntypedPayload; import net.fabricmc.fabric.mixin.networking.client.accessor.ClientCommonNetworkHandlerAccessor; /** @@ -71,7 +73,7 @@ public final class ClientConfigurationNetworking { * @see ClientConfigurationNetworking#registerReceiver(Identifier, ConfigurationChannelHandler) */ public static boolean registerGlobalReceiver(Identifier channelName, ConfigurationChannelHandler channelHandler) { - return ClientNetworkingImpl.CONFIGURATION.registerGlobalReceiver(channelName, channelHandler); + return ClientNetworkingImpl.CONFIGURATION.registerGlobalReceiver(channelName, wrapUntyped(channelHandler)); } /** @@ -88,29 +90,7 @@ public static boolean registerGlobalReceiver(Identifier channelName, Configurati * @see ClientConfigurationNetworking#registerReceiver(PacketType, ConfigurationPacketHandler) */ public static boolean registerGlobalReceiver(PacketType type, ConfigurationPacketHandler handler) { - return registerGlobalReceiver(type.getId(), new ConfigurationChannelHandlerProxy() { - @Override - public ConfigurationPacketHandler getOriginalHandler() { - return handler; - } - - @Override - public void receive(MinecraftClient client, ClientConfigurationNetworkHandler networkHandler, PacketByteBuf buf, PacketSender sender) { - T packet = type.read(buf); - - if (client.isOnThread()) { - // Do not submit to the render thread if we're already running there. - // Normally, packets are handled on the network IO thread - though it is - // not guaranteed (for example, with 1.19.4 S2C packet bundling) - // Since we're handling it right now, connection check is redundant. - handler.receive(packet, sender); - } else { - client.execute(() -> { - if (((ClientCommonNetworkHandlerAccessor) networkHandler).getConnection().isOpen()) handler.receive(packet, sender); - }); - } - } - }); + return ClientNetworkingImpl.CONFIGURATION.registerGlobalReceiver(type.getId(), wrapTyped(type, handler)); } /** @@ -126,7 +106,7 @@ public void receive(MinecraftClient client, ClientConfigurationNetworkHandler ne */ @Nullable public static ClientConfigurationNetworking.ConfigurationChannelHandler unregisterGlobalReceiver(Identifier channelName) { - return ClientNetworkingImpl.CONFIGURATION.unregisterGlobalReceiver(channelName); + return unwrapUntyped(ClientNetworkingImpl.CONFIGURATION.unregisterGlobalReceiver(channelName)); } /** @@ -142,10 +122,8 @@ public static ClientConfigurationNetworking.ConfigurationChannelHandler unregist * @see ClientConfigurationNetworking#unregisterReceiver(PacketType) */ @Nullable - @SuppressWarnings("unchecked") public static ClientConfigurationNetworking.ConfigurationPacketHandler unregisterGlobalReceiver(PacketType type) { - ConfigurationChannelHandler handler = ClientNetworkingImpl.CONFIGURATION.unregisterGlobalReceiver(type.getId()); - return handler instanceof ConfigurationChannelHandlerProxy proxy ? (ConfigurationPacketHandler) proxy.getOriginalHandler() : null; + return unwrapTyped(ClientNetworkingImpl.CONFIGURATION.unregisterGlobalReceiver(type.getId())); } /** @@ -179,7 +157,7 @@ public static boolean registerReceiver(Identifier channelName, ConfigurationChan final ClientConfigurationNetworkAddon addon = ClientNetworkingImpl.getClientConfigurationAddon(); if (addon != null) { - return addon.registerChannel(channelName, channelHandler); + return addon.registerChannel(channelName, wrapUntyped(channelHandler)); } throw new IllegalStateException("Cannot register receiver while not configuring!"); @@ -201,29 +179,13 @@ public static boolean registerReceiver(Identifier channelName, ConfigurationChan * @see ClientPlayConnectionEvents#INIT */ public static boolean registerReceiver(PacketType type, ConfigurationPacketHandler handler) { - return registerReceiver(type.getId(), new ConfigurationChannelHandlerProxy() { - @Override - public ConfigurationPacketHandler getOriginalHandler() { - return handler; - } + final ClientConfigurationNetworkAddon addon = ClientNetworkingImpl.getClientConfigurationAddon(); - @Override - public void receive(MinecraftClient client, ClientConfigurationNetworkHandler networkHandler, PacketByteBuf buf, PacketSender sender) { - T packet = type.read(buf); - - if (client.isOnThread()) { - // Do not submit to the render thread if we're already running there. - // Normally, packets are handled on the network IO thread - though it is - // not guaranteed (for example, with 1.19.4 S2C packet bundling) - // Since we're handling it right now, connection check is redundant. - handler.receive(packet, sender); - } else { - client.execute(() -> { - if (((ClientCommonNetworkHandlerAccessor) networkHandler).getConnection().isOpen()) handler.receive(packet, sender); - }); - } - } - }); + if (addon != null) { + return addon.registerChannel(type.getId(), wrapTyped(type, handler)); + } + + throw new IllegalStateException("Cannot register receiver while not configuring!"); } /** @@ -240,7 +202,7 @@ public static ClientConfigurationNetworking.ConfigurationChannelHandler unregist final ClientConfigurationNetworkAddon addon = ClientNetworkingImpl.getClientConfigurationAddon(); if (addon != null) { - return addon.unregisterChannel(channelName); + return unwrapUntyped(addon.unregisterChannel(channelName)); } throw new IllegalStateException("Cannot unregister receiver while not configuring!"); @@ -257,10 +219,14 @@ public static ClientConfigurationNetworking.ConfigurationChannelHandler unregist * @throws IllegalStateException if the client is not connected to a server */ @Nullable - @SuppressWarnings("unchecked") public static ClientConfigurationNetworking.ConfigurationPacketHandler unregisterReceiver(PacketType type) { - ConfigurationChannelHandler handler = unregisterReceiver(type.getId()); - return handler instanceof ConfigurationChannelHandlerProxy proxy ? (ConfigurationPacketHandler) proxy.getOriginalHandler() : null; + final ClientConfigurationNetworkAddon addon = ClientNetworkingImpl.getClientConfigurationAddon(); + + if (addon != null) { + return unwrapTyped(addon.unregisterChannel(type.getId())); + } + + throw new IllegalStateException("Cannot unregister receiver while not configuring!"); } /** @@ -394,6 +360,48 @@ public static void send(T packet) { private ClientConfigurationNetworking() { } + private static RetainedPayload.Handler wrapUntyped(ConfigurationChannelHandler actualHandler) { + return new RetainedPayload.Handler<>(UntypedPayload.RESOLVER, (client, handler, payload, responseSender) -> { + actualHandler.receive(client, handler, ((UntypedPayload) payload).buffer(), responseSender); + }, actualHandler); + } + + @SuppressWarnings("unchecked") + private static RetainedPayload.Handler wrapTyped(PacketType type, ConfigurationPacketHandler actualHandler) { + return new RetainedPayload.Handler<>(TypedPayload.resolver(type), (client, handler, payload, responseSender) -> { + T packet = (T) ((TypedPayload) payload).packet(); + + if (client.isOnThread()) { + // Do not submit to the render thread if we're already running there. + // Normally, packets are handled on the network IO thread - though it is + // not guaranteed (for example, with 1.19.4 S2C packet bundling) + // Since we're handling it right now, connection check is redundant. + actualHandler.receive(packet, responseSender); + } else { + client.execute(() -> { + if (((ClientCommonNetworkHandlerAccessor) handler).getConnection().isOpen()) { + actualHandler.receive(packet, responseSender); + } + }); + } + }, actualHandler); + } + + @Nullable + private static ConfigurationChannelHandler unwrapUntyped(@Nullable RetainedPayload.Handler handler) { + if (handler == null) return null; + if (handler.actualHandler() instanceof ConfigurationChannelHandler actual) return actual; + return null; + } + + @Nullable + @SuppressWarnings({"rawtypes", "unchecked"}) + private static ConfigurationPacketHandler unwrapTyped(@Nullable RetainedPayload.Handler handler) { + if (handler == null) return null; + if (handler.actualHandler() instanceof ConfigurationPacketHandler actual) return actual; + return null; + } + @FunctionalInterface public interface ConfigurationChannelHandler { /** @@ -421,14 +429,6 @@ public interface ConfigurationChannelHandler { void receive(MinecraftClient client, ClientConfigurationNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender); } - /** - * An internal packet handler that works as a proxy between old and new API. - * @param the type of the packet - */ - private interface ConfigurationChannelHandlerProxy extends ConfigurationChannelHandler { - ConfigurationPacketHandler getOriginalHandler(); - } - /** * A thread-safe packet handler utilizing {@link FabricPacket}. * @param the type of the packet diff --git a/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/api/client/networking/v1/ClientPlayNetworking.java b/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/api/client/networking/v1/ClientPlayNetworking.java index e0493d1255..ed9549d15c 100644 --- a/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/api/client/networking/v1/ClientPlayNetworking.java +++ b/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/api/client/networking/v1/ClientPlayNetworking.java @@ -36,6 +36,9 @@ import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.fabric.impl.networking.client.ClientNetworkingImpl; import net.fabricmc.fabric.impl.networking.client.ClientPlayNetworkAddon; +import net.fabricmc.fabric.impl.networking.payload.RetainedPayload; +import net.fabricmc.fabric.impl.networking.payload.TypedPayload; +import net.fabricmc.fabric.impl.networking.payload.UntypedPayload; /** * Offers access to play stage client-side networking functionalities. @@ -73,7 +76,7 @@ public final class ClientPlayNetworking { * @see ClientPlayNetworking#registerReceiver(Identifier, PlayChannelHandler) */ public static boolean registerGlobalReceiver(Identifier channelName, PlayChannelHandler channelHandler) { - return ClientNetworkingImpl.PLAY.registerGlobalReceiver(channelName, channelHandler); + return ClientNetworkingImpl.PLAY.registerGlobalReceiver(channelName, wrapUntyped(channelHandler)); } /** @@ -90,29 +93,7 @@ public static boolean registerGlobalReceiver(Identifier channelName, PlayChannel * @see ClientPlayNetworking#registerReceiver(PacketType, PlayPacketHandler) */ public static boolean registerGlobalReceiver(PacketType type, PlayPacketHandler handler) { - return registerGlobalReceiver(type.getId(), new PlayChannelHandlerProxy() { - @Override - public PlayPacketHandler getOriginalHandler() { - return handler; - } - - @Override - public void receive(MinecraftClient client, ClientPlayNetworkHandler networkHandler, PacketByteBuf buf, PacketSender sender) { - T packet = type.read(buf); - - if (client.isOnThread()) { - // Do not submit to the render thread if we're already running there. - // Normally, packets are handled on the network IO thread - though it is - // not guaranteed (for example, with 1.19.4 S2C packet bundling) - // Since we're handling it right now, connection check is redundant. - handler.receive(packet, client.player, sender); - } else { - client.execute(() -> { - if (networkHandler.getConnection().isOpen()) handler.receive(packet, client.player, sender); - }); - } - } - }); + return ClientNetworkingImpl.PLAY.registerGlobalReceiver(type.getId(), wrapTyped(type, handler)); } /** @@ -128,7 +109,7 @@ public void receive(MinecraftClient client, ClientPlayNetworkHandler networkHand */ @Nullable public static PlayChannelHandler unregisterGlobalReceiver(Identifier channelName) { - return ClientNetworkingImpl.PLAY.unregisterGlobalReceiver(channelName); + return unwrapUntyped(ClientNetworkingImpl.PLAY.unregisterGlobalReceiver(channelName)); } /** @@ -144,10 +125,8 @@ public static PlayChannelHandler unregisterGlobalReceiver(Identifier channelName * @see ClientPlayNetworking#unregisterReceiver(PacketType) */ @Nullable - @SuppressWarnings("unchecked") public static PlayPacketHandler unregisterGlobalReceiver(PacketType type) { - PlayChannelHandler handler = ClientNetworkingImpl.PLAY.unregisterGlobalReceiver(type.getId()); - return handler instanceof PlayChannelHandlerProxy proxy ? (PlayPacketHandler) proxy.getOriginalHandler() : null; + return unwrapTyped(ClientNetworkingImpl.PLAY.unregisterGlobalReceiver(type.getId())); } /** @@ -181,7 +160,7 @@ public static boolean registerReceiver(Identifier channelName, PlayChannelHandle final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon(); if (addon != null) { - return addon.registerChannel(channelName, channelHandler); + return addon.registerChannel(channelName, wrapUntyped(channelHandler)); } throw new IllegalStateException("Cannot register receiver while not in game!"); @@ -203,29 +182,13 @@ public static boolean registerReceiver(Identifier channelName, PlayChannelHandle * @see ClientPlayConnectionEvents#INIT */ public static boolean registerReceiver(PacketType type, PlayPacketHandler handler) { - return registerReceiver(type.getId(), new PlayChannelHandlerProxy() { - @Override - public PlayPacketHandler getOriginalHandler() { - return handler; - } + final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon(); - @Override - public void receive(MinecraftClient client, ClientPlayNetworkHandler networkHandler, PacketByteBuf buf, PacketSender sender) { - T packet = type.read(buf); - - if (client.isOnThread()) { - // Do not submit to the render thread if we're already running there. - // Normally, packets are handled on the network IO thread - though it is - // not guaranteed (for example, with 1.19.4 S2C packet bundling) - // Since we're handling it right now, connection check is redundant. - handler.receive(packet, client.player, sender); - } else { - client.execute(() -> { - if (networkHandler.getConnection().isOpen()) handler.receive(packet, client.player, sender); - }); - } - } - }); + if (addon != null) { + return addon.registerChannel(type.getId(), wrapTyped(type, handler)); + } + + throw new IllegalStateException("Cannot register receiver while not in game!"); } /** @@ -242,7 +205,7 @@ public static PlayChannelHandler unregisterReceiver(Identifier channelName) thro final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon(); if (addon != null) { - return addon.unregisterChannel(channelName); + return unwrapUntyped(addon.unregisterChannel(channelName)); } throw new IllegalStateException("Cannot unregister receiver while not in game!"); @@ -259,10 +222,14 @@ public static PlayChannelHandler unregisterReceiver(Identifier channelName) thro * @throws IllegalStateException if the client is not connected to a server */ @Nullable - @SuppressWarnings("unchecked") public static PlayPacketHandler unregisterReceiver(PacketType type) { - PlayChannelHandler handler = unregisterReceiver(type.getId()); - return handler instanceof PlayChannelHandlerProxy proxy ? (PlayPacketHandler) proxy.getOriginalHandler() : null; + final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon(); + + if (addon != null) { + return unwrapTyped(addon.unregisterChannel(type.getId())); + } + + throw new IllegalStateException("Cannot unregister receiver while not in game!"); } /** @@ -402,6 +369,46 @@ public static void send(T packet) { private ClientPlayNetworking() { } + private static RetainedPayload.Handler wrapUntyped(PlayChannelHandler actualHandler) { + return new RetainedPayload.Handler<>(UntypedPayload.RESOLVER, (client, handler, payload, responseSender) -> { + actualHandler.receive(client, handler, ((UntypedPayload) payload).buffer(), responseSender); + }, actualHandler); + } + + @SuppressWarnings("unchecked") + private static RetainedPayload.Handler wrapTyped(PacketType type, PlayPacketHandler actualHandler) { + return new RetainedPayload.Handler<>(TypedPayload.resolver(type), (client, handler, payload, responseSender) -> { + T packet = (T) ((TypedPayload) payload).packet(); + + if (client.isOnThread()) { + // Do not submit to the render thread if we're already running there. + // Normally, packets are handled on the network IO thread - though it is + // not guaranteed (for example, with 1.19.4 S2C packet bundling) + // Since we're handling it right now, connection check is redundant. + actualHandler.receive(packet, client.player, responseSender); + } else { + client.execute(() -> { + if (handler.getConnection().isOpen()) actualHandler.receive(packet, client.player, responseSender); + }); + } + }, actualHandler); + } + + @Nullable + private static PlayChannelHandler unwrapUntyped(@Nullable RetainedPayload.Handler handler) { + if (handler == null) return null; + if (handler.actualHandler() instanceof PlayChannelHandler actual) return actual; + return null; + } + + @Nullable + @SuppressWarnings({"rawtypes", "unchecked"}) + private static PlayPacketHandler unwrapTyped(@Nullable RetainedPayload.Handler handler) { + if (handler == null) return null; + if (handler.actualHandler() instanceof PlayPacketHandler actual) return actual; + return null; + } + @FunctionalInterface public interface PlayChannelHandler { /** @@ -429,14 +436,6 @@ public interface PlayChannelHandler { void receive(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender); } - /** - * An internal packet handler that works as a proxy between old and new API. - * @param the type of the packet - */ - private interface PlayChannelHandlerProxy extends PlayChannelHandler { - PlayPacketHandler getOriginalHandler(); - } - /** * A thread-safe packet handler utilizing {@link FabricPacket}. * @param the type of the packet diff --git a/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/impl/networking/client/ClientConfigurationNetworkAddon.java b/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/impl/networking/client/ClientConfigurationNetworkAddon.java index 17ca09e3d1..9b598d018f 100644 --- a/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/impl/networking/client/ClientConfigurationNetworkAddon.java +++ b/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/impl/networking/client/ClientConfigurationNetworkAddon.java @@ -28,17 +28,18 @@ import net.fabricmc.fabric.api.client.networking.v1.C2SConfigurationChannelEvents; 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.api.networking.v1.FabricPacket; +import net.fabricmc.fabric.api.networking.v1.PacketSender; import net.fabricmc.fabric.impl.networking.AbstractChanneledNetworkAddon; import net.fabricmc.fabric.impl.networking.ChannelInfoHolder; import net.fabricmc.fabric.impl.networking.NetworkingImpl; -import net.fabricmc.fabric.impl.networking.payload.PacketByteBufPayload; +import net.fabricmc.fabric.impl.networking.payload.ResolvablePayload; +import net.fabricmc.fabric.impl.networking.payload.ResolvedPayload; import net.fabricmc.fabric.mixin.networking.client.accessor.ClientCommonNetworkHandlerAccessor; import net.fabricmc.fabric.mixin.networking.client.accessor.ClientConfigurationNetworkHandlerAccessor; -public final class ClientConfigurationNetworkAddon extends AbstractChanneledNetworkAddon { +public final class ClientConfigurationNetworkAddon extends AbstractChanneledNetworkAddon { private final ClientConfigurationNetworkHandler handler; private final MinecraftClient client; private boolean sentInitialRegisterPacket; @@ -62,8 +63,8 @@ public void onServerReady() { } @Override - protected void receiveRegistration(boolean register, PacketByteBuf buf) { - super.receiveRegistration(register, buf); + protected void receiveRegistration(boolean register, ResolvablePayload resolvable) { + super.receiveRegistration(register, resolvable); if (register && !this.sentInitialRegisterPacket) { this.sendInitialChannelRegistrationPacket(); @@ -71,19 +72,9 @@ protected void receiveRegistration(boolean register, PacketByteBuf buf) { } } - /** - * Handles an incoming packet. - * - * @param payload the payload to handle - * @return true if the packet has been handled - */ - public boolean handle(PacketByteBufPayload payload) { - return this.handle(payload.id(), payload.data()); - } - @Override - protected void receive(ClientConfigurationNetworking.ConfigurationChannelHandler handler, PacketByteBuf buf) { - handler.receive(this.client, this.handler, buf, this); + protected void receive(Handler handler, ResolvedPayload payload) { + handler.receive(this.client, this.handler, payload, this); } // impl details @@ -155,4 +146,8 @@ protected boolean isReservedChannel(Identifier channelName) { public ChannelInfoHolder getChannelInfoHolder() { return (ChannelInfoHolder) ((ClientCommonNetworkHandlerAccessor) handler).getConnection(); } + + public interface Handler { + void receive(MinecraftClient client, ClientConfigurationNetworkHandler handler, ResolvedPayload payload, PacketSender responseSender); + } } diff --git a/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/impl/networking/client/ClientNetworkingImpl.java b/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/impl/networking/client/ClientNetworkingImpl.java index 61c5a2accd..d27b27931b 100644 --- a/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/impl/networking/client/ClientNetworkingImpl.java +++ b/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/impl/networking/client/ClientNetworkingImpl.java @@ -39,7 +39,6 @@ import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.networking.v1.FabricPacket; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.fabricmc.fabric.api.networking.v1.PacketSender; import net.fabricmc.fabric.impl.networking.CommonPacketsImpl; import net.fabricmc.fabric.impl.networking.CommonRegisterPayload; @@ -47,14 +46,17 @@ import net.fabricmc.fabric.impl.networking.GlobalReceiverRegistry; import net.fabricmc.fabric.impl.networking.NetworkHandlerExtensions; import net.fabricmc.fabric.impl.networking.NetworkingImpl; -import net.fabricmc.fabric.impl.networking.payload.PacketByteBufPayload; +import net.fabricmc.fabric.impl.networking.payload.RetainedPayload; +import net.fabricmc.fabric.impl.networking.payload.TypedPayload; +import net.fabricmc.fabric.impl.networking.payload.UntypedPayload; import net.fabricmc.fabric.mixin.networking.client.accessor.ConnectScreenAccessor; import net.fabricmc.fabric.mixin.networking.client.accessor.MinecraftClientAccessor; public final class ClientNetworkingImpl { public static final GlobalReceiverRegistry LOGIN = new GlobalReceiverRegistry<>(NetworkState.LOGIN); - public static final GlobalReceiverRegistry CONFIGURATION = new GlobalReceiverRegistry<>(NetworkState.CONFIGURATION); - public static final GlobalReceiverRegistry PLAY = new GlobalReceiverRegistry<>(NetworkState.PLAY); + public static final GlobalReceiverRegistry> CONFIGURATION = new GlobalReceiverRegistry<>(NetworkState.CONFIGURATION); + public static final GlobalReceiverRegistry> PLAY = new GlobalReceiverRegistry<>(NetworkState.PLAY); + private static ClientPlayNetworkAddon currentPlayAddon; private static ClientConfigurationNetworkAddon currentConfigurationAddon; @@ -71,16 +73,14 @@ public static ClientLoginNetworkAddon getAddon(ClientLoginNetworkHandler handler } public static Packet createC2SPacket(Identifier channelName, PacketByteBuf buf) { - return new CustomPayloadC2SPacket(new PacketByteBufPayload(channelName, buf)); + return new CustomPayloadC2SPacket(new UntypedPayload(channelName, buf)); } public static Packet createC2SPacket(FabricPacket packet) { Objects.requireNonNull(packet, "Packet cannot be null"); Objects.requireNonNull(packet.getType(), "Packet#getType cannot return null"); - PacketByteBuf buf = PacketByteBufs.create(); - packet.write(buf); - return createC2SPacket(packet.getType().getId(), buf); + return new CustomPayloadC2SPacket(new TypedPayload(packet)); } /** diff --git a/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/impl/networking/client/ClientPlayNetworkAddon.java b/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/impl/networking/client/ClientPlayNetworkAddon.java index 9b7b94b13f..cfe34baae0 100644 --- a/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/impl/networking/client/ClientPlayNetworkAddon.java +++ b/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/impl/networking/client/ClientPlayNetworkAddon.java @@ -33,12 +33,13 @@ import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.networking.v1.FabricPacket; +import net.fabricmc.fabric.api.networking.v1.PacketSender; import net.fabricmc.fabric.impl.networking.AbstractChanneledNetworkAddon; import net.fabricmc.fabric.impl.networking.ChannelInfoHolder; import net.fabricmc.fabric.impl.networking.NetworkingImpl; -import net.fabricmc.fabric.impl.networking.payload.PacketByteBufPayload; +import net.fabricmc.fabric.impl.networking.payload.ResolvedPayload; -public final class ClientPlayNetworkAddon extends AbstractChanneledNetworkAddon { +public final class ClientPlayNetworkAddon extends AbstractChanneledNetworkAddon { private final ClientPlayNetworkHandler handler; private final MinecraftClient client; private boolean sentInitialRegisterPacket; @@ -71,19 +72,9 @@ public void onServerReady() { this.sentInitialRegisterPacket = true; } - /** - * Handles an incoming packet. - * - * @param payload the payload to handle - * @return true if the packet has been handled - */ - public boolean handle(PacketByteBufPayload payload) { - return this.handle(payload.id(), payload.data()); - } - @Override - protected void receive(ClientPlayNetworking.PlayChannelHandler handler, PacketByteBuf buf) { - handler.receive(this.client, this.handler, buf, this); + protected void receive(Handler handler, ResolvedPayload payload) { + handler.receive(this.client, this.handler, payload, this); } // impl details @@ -146,4 +137,8 @@ protected void invokeDisconnectEvent() { protected boolean isReservedChannel(Identifier channelName) { return NetworkingImpl.isReservedCommonChannel(channelName); } + + public interface Handler { + void receive(MinecraftClient client, ClientPlayNetworkHandler handler, ResolvedPayload payload, PacketSender responseSender); + } } diff --git a/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/mixin/networking/client/ClientCommonNetworkHandlerMixin.java b/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/mixin/networking/client/ClientCommonNetworkHandlerMixin.java index 494811ee7f..5fc88f42ef 100644 --- a/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/mixin/networking/client/ClientCommonNetworkHandlerMixin.java +++ b/fabric-networking-api-v1/src/client/java/net/fabricmc/fabric/mixin/networking/client/ClientCommonNetworkHandlerMixin.java @@ -27,13 +27,14 @@ import net.fabricmc.fabric.impl.networking.NetworkHandlerExtensions; import net.fabricmc.fabric.impl.networking.client.ClientConfigurationNetworkAddon; import net.fabricmc.fabric.impl.networking.client.ClientPlayNetworkAddon; -import net.fabricmc.fabric.impl.networking.payload.PacketByteBufPayload; +import net.fabricmc.fabric.impl.networking.payload.ResolvablePayload; +import net.fabricmc.fabric.impl.networking.payload.RetainedPayload; @Mixin(ClientCommonNetworkHandler.class) public abstract class ClientCommonNetworkHandlerMixin implements NetworkHandlerExtensions { @Inject(method = "onCustomPayload(Lnet/minecraft/network/packet/s2c/common/CustomPayloadS2CPacket;)V", at = @At("HEAD"), cancellable = true) public void onCustomPayload(CustomPayloadS2CPacket packet, CallbackInfo ci) { - if (packet.payload() instanceof PacketByteBufPayload payload) { + if (packet.payload() instanceof ResolvablePayload payload) { boolean handled; if (this.getAddon() instanceof ClientPlayNetworkAddon addon) { @@ -46,8 +47,11 @@ public void onCustomPayload(CustomPayloadS2CPacket packet, CallbackInfo ci) { if (handled) { ci.cancel(); - } else { - payload.data().skipBytes(payload.data().readableBytes()); + } else if (payload instanceof RetainedPayload retained && retained.buf().refCnt() > 0) { + // Vanilla forces to use the render thread for its payloads, + // that means this method can get called multiple times. + retained.buf().skipBytes(retained.buf().readableBytes()); + retained.buf().release(); } } } diff --git a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/api/networking/v1/ServerConfigurationNetworking.java b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/api/networking/v1/ServerConfigurationNetworking.java index 2261d5817c..eb8808870a 100644 --- a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/api/networking/v1/ServerConfigurationNetworking.java +++ b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/api/networking/v1/ServerConfigurationNetworking.java @@ -29,6 +29,10 @@ import net.minecraft.util.Identifier; import net.minecraft.util.thread.ThreadExecutor; +import net.fabricmc.fabric.impl.networking.payload.RetainedPayload; +import net.fabricmc.fabric.impl.networking.payload.TypedPayload; +import net.fabricmc.fabric.impl.networking.payload.UntypedPayload; +import net.fabricmc.fabric.impl.networking.server.ServerConfigurationNetworkAddon; import net.fabricmc.fabric.impl.networking.server.ServerNetworkingImpl; import net.fabricmc.fabric.mixin.networking.accessor.ServerCommonNetworkHandlerAccessor; @@ -68,7 +72,7 @@ public final class ServerConfigurationNetworking { * @see ServerConfigurationNetworking#registerReceiver(ServerConfigurationNetworkHandler, Identifier, ConfigurationChannelHandler) */ public static boolean registerGlobalReceiver(Identifier channelName, ConfigurationChannelHandler channelHandler) { - return ServerNetworkingImpl.CONFIGURATION.registerGlobalReceiver(channelName, channelHandler); + return ServerNetworkingImpl.CONFIGURATION.registerGlobalReceiver(channelName, wrapUntyped(channelHandler)); } /** @@ -85,18 +89,7 @@ public static boolean registerGlobalReceiver(Identifier channelName, Configurati * @see ServerConfigurationNetworking#registerReceiver(ServerConfigurationNetworkHandler, PacketType, ConfigurationPacketHandler) */ public static boolean registerGlobalReceiver(PacketType type, ConfigurationPacketHandler handler) { - return registerGlobalReceiver(type.getId(), new ConfigurationChannelHandlerProxy() { - @Override - public ConfigurationPacketHandler getOriginalHandler() { - return handler; - } - - @Override - public void receive(MinecraftServer server, ServerConfigurationNetworkHandler networkHandler, PacketByteBuf buf, PacketSender sender) { - T packet = type.read(buf); - handler.receive(packet, networkHandler, sender); - } - }); + return ServerNetworkingImpl.CONFIGURATION.registerGlobalReceiver(type.getId(), wrapTyped(type, handler)); } /** @@ -112,7 +105,7 @@ public void receive(MinecraftServer server, ServerConfigurationNetworkHandler ne */ @Nullable public static ServerConfigurationNetworking.ConfigurationChannelHandler unregisterGlobalReceiver(Identifier channelName) { - return ServerNetworkingImpl.CONFIGURATION.unregisterGlobalReceiver(channelName); + return unwrapUntyped(ServerNetworkingImpl.CONFIGURATION.unregisterGlobalReceiver(channelName)); } /** @@ -128,10 +121,8 @@ public static ServerConfigurationNetworking.ConfigurationChannelHandler unregist * @see ServerConfigurationNetworking#unregisterReceiver(ServerConfigurationNetworkHandler, PacketType) */ @Nullable - @SuppressWarnings("unchecked") public static ServerConfigurationNetworking.ConfigurationPacketHandler unregisterGlobalReceiver(PacketType type) { - ConfigurationChannelHandler handler = ServerNetworkingImpl.CONFIGURATION.unregisterGlobalReceiver(type.getId()); - return handler instanceof ConfigurationChannelHandlerProxy proxy ? (ConfigurationPacketHandler) proxy.getOriginalHandler() : null; + return unwrapTyped(ServerNetworkingImpl.CONFIGURATION.unregisterGlobalReceiver(type.getId())); } /** @@ -170,7 +161,7 @@ public static Set getGlobalReceivers() { public static boolean registerReceiver(ServerConfigurationNetworkHandler networkHandler, Identifier channelName, ConfigurationChannelHandler channelHandler) { Objects.requireNonNull(networkHandler, "Network handler cannot be null"); - return ServerNetworkingImpl.getAddon(networkHandler).registerChannel(channelName, channelHandler); + return ServerNetworkingImpl.getAddon(networkHandler).registerChannel(channelName, wrapUntyped(channelHandler)); } /** @@ -191,18 +182,7 @@ public static boolean registerReceiver(ServerConfigurationNetworkHandler network * @see ServerPlayConnectionEvents#INIT */ public static boolean registerReceiver(ServerConfigurationNetworkHandler networkHandler, PacketType type, ConfigurationPacketHandler handler) { - return registerReceiver(networkHandler, type.getId(), new ConfigurationChannelHandlerProxy() { - @Override - public ConfigurationPacketHandler getOriginalHandler() { - return handler; - } - - @Override - public void receive(MinecraftServer server, ServerConfigurationNetworkHandler networkHandler2, PacketByteBuf buf, PacketSender sender) { - T packet = type.read(buf); - handler.receive(packet, networkHandler2, sender); - } - }); + return ServerNetworkingImpl.getAddon(networkHandler).registerChannel(type.getId(), wrapTyped(type, handler)); } /** @@ -217,7 +197,7 @@ public void receive(MinecraftServer server, ServerConfigurationNetworkHandler ne public static ServerConfigurationNetworking.ConfigurationChannelHandler unregisterReceiver(ServerConfigurationNetworkHandler networkHandler, Identifier channelName) { Objects.requireNonNull(networkHandler, "Network handler cannot be null"); - return ServerNetworkingImpl.getAddon(networkHandler).unregisterChannel(channelName); + return unwrapUntyped(ServerNetworkingImpl.getAddon(networkHandler).unregisterChannel(channelName)); } /** @@ -230,10 +210,8 @@ public static ServerConfigurationNetworking.ConfigurationChannelHandler unregist * or it was not registered using {@link #registerReceiver(ServerConfigurationNetworkHandler, PacketType, ConfigurationPacketHandler)} */ @Nullable - @SuppressWarnings("unchecked") public static ServerConfigurationNetworking.ConfigurationPacketHandler unregisterReceiver(ServerConfigurationNetworkHandler networkHandler, PacketType type) { - ConfigurationChannelHandler handler = unregisterReceiver(networkHandler, type.getId()); - return handler instanceof ConfigurationChannelHandlerProxy proxy ? (ConfigurationPacketHandler) proxy.getOriginalHandler() : null; + return unwrapTyped(ServerNetworkingImpl.getAddon(networkHandler).unregisterChannel(type.getId())); } /** @@ -372,6 +350,35 @@ public static MinecraftServer getServer(ServerConfigurationNetworkHandler handle private ServerConfigurationNetworking() { } + private static RetainedPayload.Handler wrapUntyped(ConfigurationChannelHandler actualHandler) { + return new RetainedPayload.Handler<>(UntypedPayload.RESOLVER, (server, handler, payload, responseSender) -> { + actualHandler.receive(server, handler, ((UntypedPayload) payload).buffer(), responseSender); + }, actualHandler); + } + + @SuppressWarnings("unchecked") + private static RetainedPayload.Handler wrapTyped(PacketType type, ConfigurationPacketHandler actualHandler) { + return new RetainedPayload.Handler<>(TypedPayload.resolver(type), (server, handler, payload, responseSender) -> { + T packet = (T) ((TypedPayload) payload).packet(); + actualHandler.receive(packet, handler, responseSender); + }, actualHandler); + } + + @Nullable + private static ConfigurationChannelHandler unwrapUntyped(@Nullable RetainedPayload.Handler handler) { + if (handler == null) return null; + if (handler.actualHandler() instanceof ConfigurationChannelHandler actual) return actual; + return null; + } + + @Nullable + @SuppressWarnings({"rawtypes", "unchecked"}) + private static ConfigurationPacketHandler unwrapTyped(@Nullable RetainedPayload.Handler handler) { + if (handler == null) return null; + if (handler.actualHandler() instanceof ConfigurationPacketHandler actual) return actual; + return null; + } + @FunctionalInterface public interface ConfigurationChannelHandler { /** @@ -399,14 +406,6 @@ public interface ConfigurationChannelHandler { void receive(MinecraftServer server, ServerConfigurationNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender); } - /** - * An internal packet handler that works as a proxy between old and new API. - * @param the type of the packet - */ - private interface ConfigurationChannelHandlerProxy extends ConfigurationChannelHandler { - ConfigurationPacketHandler getOriginalHandler(); - } - /** * A thread-safe packet handler utilizing {@link FabricPacket}. * @param the type of the packet diff --git a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/api/networking/v1/ServerPlayNetworking.java b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/api/networking/v1/ServerPlayNetworking.java index 9ac7ce58da..0d8f11617d 100644 --- a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/api/networking/v1/ServerPlayNetworking.java +++ b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/api/networking/v1/ServerPlayNetworking.java @@ -30,7 +30,11 @@ import net.minecraft.util.Identifier; import net.minecraft.util.thread.ThreadExecutor; +import net.fabricmc.fabric.impl.networking.payload.RetainedPayload; +import net.fabricmc.fabric.impl.networking.payload.TypedPayload; +import net.fabricmc.fabric.impl.networking.payload.UntypedPayload; import net.fabricmc.fabric.impl.networking.server.ServerNetworkingImpl; +import net.fabricmc.fabric.impl.networking.server.ServerPlayNetworkAddon; /** * Offers access to play stage server-side networking functionalities. @@ -83,7 +87,7 @@ public final class ServerPlayNetworking { * @see ServerPlayNetworking#registerReceiver(ServerPlayNetworkHandler, Identifier, PlayChannelHandler) */ public static boolean registerGlobalReceiver(Identifier channelName, PlayChannelHandler channelHandler) { - return ServerNetworkingImpl.PLAY.registerGlobalReceiver(channelName, channelHandler); + return ServerNetworkingImpl.PLAY.registerGlobalReceiver(channelName, wrapUntyped(channelHandler)); } /** @@ -100,29 +104,7 @@ public static boolean registerGlobalReceiver(Identifier channelName, PlayChannel * @see ServerPlayNetworking#registerReceiver(ServerPlayNetworkHandler, PacketType, PlayPacketHandler) */ public static boolean registerGlobalReceiver(PacketType type, PlayPacketHandler handler) { - return registerGlobalReceiver(type.getId(), new PlayChannelHandlerProxy() { - @Override - public PlayPacketHandler getOriginalHandler() { - return handler; - } - - @Override - public void receive(MinecraftServer server, ServerPlayerEntity player, ServerPlayNetworkHandler networkHandler, PacketByteBuf buf, PacketSender sender) { - T packet = type.read(buf); - - if (server.isOnThread()) { - // Do not submit to the server thread if we're already running there. - // Normally, packets are handled on the network IO thread - though it is - // not guaranteed (for example, with 1.19.4 S2C packet bundling) - // Since we're handling it right now, connection check is redundant. - handler.receive(packet, player, sender); - } else { - server.execute(() -> { - if (networkHandler.isConnectionOpen()) handler.receive(packet, player, sender); - }); - } - } - }); + return ServerNetworkingImpl.PLAY.registerGlobalReceiver(type.getId(), wrapTyped(type, handler)); } /** @@ -138,7 +120,7 @@ public void receive(MinecraftServer server, ServerPlayerEntity player, ServerPla */ @Nullable public static PlayChannelHandler unregisterGlobalReceiver(Identifier channelName) { - return ServerNetworkingImpl.PLAY.unregisterGlobalReceiver(channelName); + return unwrapUntyped(ServerNetworkingImpl.PLAY.unregisterGlobalReceiver(channelName)); } /** @@ -154,10 +136,8 @@ public static PlayChannelHandler unregisterGlobalReceiver(Identifier channelName * @see ServerPlayNetworking#unregisterReceiver(ServerPlayNetworkHandler, PacketType) */ @Nullable - @SuppressWarnings("unchecked") public static PlayPacketHandler unregisterGlobalReceiver(PacketType type) { - PlayChannelHandler handler = ServerNetworkingImpl.PLAY.unregisterGlobalReceiver(type.getId()); - return handler instanceof PlayChannelHandlerProxy proxy ? (PlayPacketHandler) proxy.getOriginalHandler() : null; + return unwrapTyped(ServerNetworkingImpl.PLAY.unregisterGlobalReceiver(type.getId())); } /** @@ -196,7 +176,7 @@ public static Set getGlobalReceivers() { public static boolean registerReceiver(ServerPlayNetworkHandler networkHandler, Identifier channelName, PlayChannelHandler channelHandler) { Objects.requireNonNull(networkHandler, "Network handler cannot be null"); - return ServerNetworkingImpl.getAddon(networkHandler).registerChannel(channelName, channelHandler); + return ServerNetworkingImpl.getAddon(networkHandler).registerChannel(channelName, wrapUntyped(channelHandler)); } /** @@ -217,29 +197,7 @@ public static boolean registerReceiver(ServerPlayNetworkHandler networkHandler, * @see ServerPlayConnectionEvents#INIT */ public static boolean registerReceiver(ServerPlayNetworkHandler networkHandler, PacketType type, PlayPacketHandler handler) { - return registerReceiver(networkHandler, type.getId(), new PlayChannelHandlerProxy() { - @Override - public PlayPacketHandler getOriginalHandler() { - return handler; - } - - @Override - public void receive(MinecraftServer server, ServerPlayerEntity player, ServerPlayNetworkHandler networkHandler2, PacketByteBuf buf, PacketSender sender) { - T packet = type.read(buf); - - if (server.isOnThread()) { - // Do not submit to the server thread if we're already running there. - // Normally, packets are handled on the network IO thread - though it is - // not guaranteed (for example, with 1.19.4 S2C packet bundling) - // Since we're handling it right now, connection check is redundant. - handler.receive(packet, player, sender); - } else { - server.execute(() -> { - if (networkHandler2.isConnectionOpen()) handler.receive(packet, player, sender); - }); - } - } - }); + return ServerNetworkingImpl.getAddon(networkHandler).registerChannel(type.getId(), wrapTyped(type, handler)); } /** @@ -254,7 +212,7 @@ public void receive(MinecraftServer server, ServerPlayerEntity player, ServerPla public static PlayChannelHandler unregisterReceiver(ServerPlayNetworkHandler networkHandler, Identifier channelName) { Objects.requireNonNull(networkHandler, "Network handler cannot be null"); - return ServerNetworkingImpl.getAddon(networkHandler).unregisterChannel(channelName); + return unwrapUntyped(ServerNetworkingImpl.getAddon(networkHandler).unregisterChannel(channelName)); } /** @@ -267,10 +225,8 @@ public static PlayChannelHandler unregisterReceiver(ServerPlayNetworkHandler net * or it was not registered using {@link #registerReceiver(ServerPlayNetworkHandler, PacketType, PlayPacketHandler)} */ @Nullable - @SuppressWarnings("unchecked") public static PlayPacketHandler unregisterReceiver(ServerPlayNetworkHandler networkHandler, PacketType type) { - PlayChannelHandler handler = unregisterReceiver(networkHandler, type.getId()); - return handler instanceof PlayChannelHandlerProxy proxy ? (PlayPacketHandler) proxy.getOriginalHandler() : null; + return unwrapTyped(ServerNetworkingImpl.getAddon(networkHandler).unregisterChannel(type.getId())); } /** @@ -468,6 +424,46 @@ public static MinecraftServer getServer(ServerPlayNetworkHandler handler) { private ServerPlayNetworking() { } + private static RetainedPayload.Handler wrapUntyped(PlayChannelHandler actualHandler) { + return new RetainedPayload.Handler<>(UntypedPayload.RESOLVER, (server, player, handler, payload, responseSender) -> { + actualHandler.receive(server, player, handler, ((UntypedPayload) payload).buffer(), responseSender); + }, actualHandler); + } + + @SuppressWarnings("unchecked") + private static RetainedPayload.Handler wrapTyped(PacketType type, PlayPacketHandler actualHandler) { + return new RetainedPayload.Handler<>(TypedPayload.resolver(type), (server, player, handler, payload, responseSender) -> { + T packet = (T) ((TypedPayload) payload).packet(); + + if (server.isOnThread()) { + // Do not submit to the server thread if we're already running there. + // Normally, packets are handled on the network IO thread - though it is + // not guaranteed (for example, with 1.19.4 S2C packet bundling) + // Since we're handling it right now, connection check is redundant. + actualHandler.receive(packet, player, responseSender); + } else { + server.execute(() -> { + if (handler.isConnectionOpen()) actualHandler.receive(packet, player, responseSender); + }); + } + }, actualHandler); + } + + @Nullable + private static PlayChannelHandler unwrapUntyped(@Nullable RetainedPayload.Handler handler) { + if (handler == null) return null; + if (handler.actualHandler() instanceof PlayChannelHandler actual) return actual; + return null; + } + + @Nullable + @SuppressWarnings({"rawtypes", "unchecked"}) + private static PlayPacketHandler unwrapTyped(@Nullable RetainedPayload.Handler handler) { + if (handler == null) return null; + if (handler.actualHandler() instanceof PlayPacketHandler actual) return actual; + return null; + } + @FunctionalInterface public interface PlayChannelHandler { /** @@ -496,14 +492,6 @@ public interface PlayChannelHandler { void receive(MinecraftServer server, ServerPlayerEntity player, ServerPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender); } - /** - * An internal packet handler that works as a proxy between old and new API. - * @param the type of the packet - */ - private interface PlayChannelHandlerProxy extends PlayChannelHandler { - PlayPacketHandler getOriginalHandler(); - } - /** * A thread-safe packet handler utilizing {@link FabricPacket}. * @param the type of the packet diff --git a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/AbstractChanneledNetworkAddon.java b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/AbstractChanneledNetworkAddon.java index 203d4dbffa..fef21b0023 100644 --- a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/AbstractChanneledNetworkAddon.java +++ b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/AbstractChanneledNetworkAddon.java @@ -40,20 +40,24 @@ import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.fabricmc.fabric.impl.networking.payload.ResolvablePayload; +import net.fabricmc.fabric.impl.networking.payload.ResolvedPayload; +import net.fabricmc.fabric.impl.networking.payload.RetainedPayload; +import net.fabricmc.fabric.impl.networking.payload.UntypedPayload; /** * A network addon which is aware of the channels the other side may receive. * * @param the channel handler type */ -public abstract class AbstractChanneledNetworkAddon extends AbstractNetworkAddon implements PacketSender, CommonPacketHandler { +public abstract class AbstractChanneledNetworkAddon extends AbstractNetworkAddon> implements PacketSender, CommonPacketHandler { protected final ClientConnection connection; - protected final GlobalReceiverRegistry receiver; + protected final GlobalReceiverRegistry> receiver; protected final Set sendableChannels; protected int commonVersion = -1; - protected AbstractChanneledNetworkAddon(GlobalReceiverRegistry receiver, ClientConnection connection, String description) { + protected AbstractChanneledNetworkAddon(GlobalReceiverRegistry> receiver, ClientConnection connection, String description) { super(receiver, description); this.connection = connection; this.receiver = receiver; @@ -70,28 +74,34 @@ protected void registerPendingChannels(ChannelInfoHolder holder, NetworkState st } // always supposed to handle async! - protected boolean handle(Identifier channelName, PacketByteBuf buf) { + public boolean handle(ResolvablePayload resolvable) { + Identifier channelName = resolvable.id(); this.logger.debug("Handling inbound packet from channel with name \"{}\"", channelName); // Handle reserved packets if (NetworkingImpl.REGISTER_CHANNEL.equals(channelName)) { - this.receiveRegistration(true, buf); + this.receiveRegistration(true, resolvable); return true; } if (NetworkingImpl.UNREGISTER_CHANNEL.equals(channelName)) { - this.receiveRegistration(false, buf); + this.receiveRegistration(false, resolvable); return true; } - @Nullable H handler = this.getHandler(channelName); + @Nullable RetainedPayload.Handler handler = this.getHandler(channelName); if (handler == null) { return false; } + try { - this.receive(handler, buf); + ResolvedPayload resolved = resolvable instanceof RetainedPayload retained + ? handler.resolver().resolve(retained) + : (ResolvedPayload) resolvable; + + this.receive(handler.handler(), resolved); } catch (Throwable ex) { this.logger.error("Encountered exception while handling in channel with name \"{}\"", channelName, ex); throw ex; @@ -100,7 +110,7 @@ protected boolean handle(Identifier channelName, PacketByteBuf buf) { return true; } - protected abstract void receive(H handler, PacketByteBuf buf); + protected abstract void receive(H handler, ResolvedPayload payload); protected void sendInitialChannelRegistrationPacket() { final PacketByteBuf buf = this.createRegistrationPacket(this.getReceivableChannels()); @@ -133,7 +143,13 @@ protected PacketByteBuf createRegistrationPacket(Collection channels } // wrap in try with res (buf) - protected void receiveRegistration(boolean register, PacketByteBuf buf) { + protected void receiveRegistration(boolean register, ResolvablePayload resolvable) { + UntypedPayload payload = resolvable instanceof RetainedPayload retained + ? (UntypedPayload) UntypedPayload.RESOLVER.resolve(retained) + : (UntypedPayload) resolvable; + + PacketByteBuf buf = payload.buffer(); + List ids = new ArrayList<>(); StringBuilder active = new StringBuilder(); diff --git a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/GlobalReceiverRegistry.java b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/GlobalReceiverRegistry.java index 4529445390..8f1cf1de71 100644 --- a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/GlobalReceiverRegistry.java +++ b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/GlobalReceiverRegistry.java @@ -86,6 +86,7 @@ public boolean registerGlobalReceiver(Identifier channelName, H handler) { } } + @Nullable public H unregisterGlobalReceiver(Identifier channelName) { Objects.requireNonNull(channelName, "Channel name cannot be null"); diff --git a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/PacketByteBufPayload.java b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/ResolvablePayload.java similarity index 72% rename from fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/PacketByteBufPayload.java rename to fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/ResolvablePayload.java index 78ac1cc39f..00602b3b93 100644 --- a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/PacketByteBufPayload.java +++ b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/ResolvablePayload.java @@ -16,13 +16,7 @@ package net.fabricmc.fabric.impl.networking.payload; -import net.minecraft.network.PacketByteBuf; import net.minecraft.network.packet.CustomPayload; -import net.minecraft.util.Identifier; -public record PacketByteBufPayload(Identifier id, PacketByteBuf data) implements CustomPayload { - @Override - public void write(PacketByteBuf buf) { - PayloadHelper.write(buf, data()); - } +public sealed interface ResolvablePayload extends CustomPayload permits ResolvedPayload, RetainedPayload { } diff --git a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/ResolvedPayload.java b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/ResolvedPayload.java new file mode 100644 index 0000000000..04b5e7d33d --- /dev/null +++ b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/ResolvedPayload.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.networking.payload; + +public sealed interface ResolvedPayload extends ResolvablePayload permits TypedPayload, UntypedPayload { +} diff --git a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/RetainedPayload.java b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/RetainedPayload.java new file mode 100644 index 0000000000..e516babcb1 --- /dev/null +++ b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/RetainedPayload.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.networking.payload; + +import net.minecraft.network.PacketByteBuf; +import net.minecraft.util.Identifier; + +public record RetainedPayload(Identifier id, PacketByteBuf buf) implements ResolvablePayload { + @Override + public void write(PacketByteBuf buf) { + throw new UnsupportedOperationException("RetainedPayload shouldn't be used to send"); + } + + public record Handler(Resolver resolver, H handler, Object actualHandler) { + } + + @FunctionalInterface + public interface Resolver { + @Deprecated + @SuppressWarnings("DeprecatedIsStillUsed") + ResolvedPayload resolve0(RetainedPayload retained); + + default ResolvedPayload resolve(RetainedPayload retained) { + try { + ResolvedPayload resolved = resolve0(retained); + int dangling = retained.buf.readableBytes(); + + if (dangling > 0) { + throw new IllegalStateException("Found " + dangling + " extra bytes when reading packet " + retained.id); + } + + return resolved; + } finally { + retained.buf.release(); + } + } + } +} diff --git a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/TypedPayload.java b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/TypedPayload.java new file mode 100644 index 0000000000..d0184700af --- /dev/null +++ b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/TypedPayload.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.networking.payload; + +import net.minecraft.network.PacketByteBuf; +import net.minecraft.util.Identifier; + +import net.fabricmc.fabric.api.networking.v1.FabricPacket; +import net.fabricmc.fabric.api.networking.v1.PacketType; + +public record TypedPayload(FabricPacket packet) implements ResolvedPayload { + public static RetainedPayload.Resolver resolver(PacketType type) { + return retained -> new TypedPayload(type.read(retained.buf())); + } + + @Override + public void write(PacketByteBuf buf) { + packet.write(buf); + } + + @Override + public Identifier id() { + return packet.getType().getId(); + } +} diff --git a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/UntypedPayload.java b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/UntypedPayload.java new file mode 100644 index 0000000000..353b1f486b --- /dev/null +++ b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/UntypedPayload.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.networking.payload; + +import net.minecraft.network.PacketByteBuf; +import net.minecraft.util.Identifier; + +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; + +public record UntypedPayload(Identifier id, PacketByteBuf buffer) implements ResolvedPayload { + public static final RetainedPayload.Resolver RESOLVER = retained -> { + PacketByteBuf copy = PacketByteBufs.create(); + copy.writeBytes(retained.buf()); + return new UntypedPayload(retained.id(), copy); + }; + + @Override + public void write(PacketByteBuf buf) { + buf.writeBytes(buffer); + } +} diff --git a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/server/ServerConfigurationNetworkAddon.java b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/server/ServerConfigurationNetworkAddon.java index 93357b5968..338a2d6212 100644 --- a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/server/ServerConfigurationNetworkAddon.java +++ b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/server/ServerConfigurationNetworkAddon.java @@ -29,17 +29,18 @@ import net.minecraft.util.Identifier; import net.fabricmc.fabric.api.networking.v1.FabricPacket; +import net.fabricmc.fabric.api.networking.v1.PacketSender; import net.fabricmc.fabric.api.networking.v1.S2CConfigurationChannelEvents; import net.fabricmc.fabric.api.networking.v1.ServerConfigurationConnectionEvents; -import net.fabricmc.fabric.api.networking.v1.ServerConfigurationNetworking; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.fabric.impl.networking.AbstractChanneledNetworkAddon; import net.fabricmc.fabric.impl.networking.ChannelInfoHolder; import net.fabricmc.fabric.impl.networking.NetworkingImpl; -import net.fabricmc.fabric.impl.networking.payload.PacketByteBufPayload; +import net.fabricmc.fabric.impl.networking.payload.ResolvablePayload; +import net.fabricmc.fabric.impl.networking.payload.ResolvedPayload; import net.fabricmc.fabric.mixin.networking.accessor.ServerCommonNetworkHandlerAccessor; -public final class ServerConfigurationNetworkAddon extends AbstractChanneledNetworkAddon { +public final class ServerConfigurationNetworkAddon extends AbstractChanneledNetworkAddon { private final ServerConfigurationNetworkHandler handler; private final MinecraftServer server; private RegisterState registerState = RegisterState.NOT_SENT; @@ -83,8 +84,8 @@ public boolean startConfiguration() { } @Override - protected void receiveRegistration(boolean register, PacketByteBuf buf) { - super.receiveRegistration(register, buf); + protected void receiveRegistration(boolean register, ResolvablePayload resolvable) { + super.receiveRegistration(register, resolvable); if (register && registerState == RegisterState.SENT) { // We received the registration packet, thus we know this is a modded client, continue with configuration. @@ -101,19 +102,9 @@ public void onPong(int parameter) { } } - /** - * Handles an incoming packet. - * - * @param payload the payload to handle - * @return true if the packet has been handled - */ - public boolean handle(PacketByteBufPayload payload) { - return this.handle(payload.id(), payload.data()); - } - @Override - protected void receive(ServerConfigurationNetworking.ConfigurationChannelHandler handler, PacketByteBuf buf) { - handler.receive(this.server, this.handler, buf, this); + protected void receive(Handler handler, ResolvedPayload payload) { + handler.receive(this.server, this.handler, payload, this); } // impl details @@ -192,4 +183,8 @@ private enum RegisterState { public ChannelInfoHolder getChannelInfoHolder() { return (ChannelInfoHolder) ((ServerCommonNetworkHandlerAccessor) handler).getConnection(); } + + public interface Handler { + void receive(MinecraftServer server, ServerConfigurationNetworkHandler handler, ResolvedPayload payload, PacketSender responseSender); + } } diff --git a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/server/ServerNetworkingImpl.java b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/server/ServerNetworkingImpl.java index 2a3c88e596..8e6fec62e8 100644 --- a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/server/ServerNetworkingImpl.java +++ b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/server/ServerNetworkingImpl.java @@ -29,18 +29,17 @@ import net.minecraft.util.Identifier; import net.fabricmc.fabric.api.networking.v1.FabricPacket; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; -import net.fabricmc.fabric.api.networking.v1.ServerConfigurationNetworking; import net.fabricmc.fabric.api.networking.v1.ServerLoginNetworking; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.fabric.impl.networking.GlobalReceiverRegistry; import net.fabricmc.fabric.impl.networking.NetworkHandlerExtensions; -import net.fabricmc.fabric.impl.networking.payload.PacketByteBufPayload; +import net.fabricmc.fabric.impl.networking.payload.RetainedPayload; +import net.fabricmc.fabric.impl.networking.payload.TypedPayload; +import net.fabricmc.fabric.impl.networking.payload.UntypedPayload; public final class ServerNetworkingImpl { public static final GlobalReceiverRegistry LOGIN = new GlobalReceiverRegistry<>(NetworkState.LOGIN); - public static final GlobalReceiverRegistry CONFIGURATION = new GlobalReceiverRegistry<>(NetworkState.CONFIGURATION); - public static final GlobalReceiverRegistry PLAY = new GlobalReceiverRegistry<>(NetworkState.PLAY); + public static final GlobalReceiverRegistry> CONFIGURATION = new GlobalReceiverRegistry<>(NetworkState.CONFIGURATION); + public static final GlobalReceiverRegistry> PLAY = new GlobalReceiverRegistry<>(NetworkState.PLAY); public static ServerPlayNetworkAddon getAddon(ServerPlayNetworkHandler handler) { return (ServerPlayNetworkAddon) ((NetworkHandlerExtensions) handler).getAddon(); @@ -55,15 +54,13 @@ public static ServerConfigurationNetworkAddon getAddon(ServerConfigurationNetwor } public static Packet createS2CPacket(Identifier channel, PacketByteBuf buf) { - return new CustomPayloadS2CPacket(new PacketByteBufPayload(channel, buf)); + return new CustomPayloadS2CPacket(new UntypedPayload(channel, buf)); } public static Packet createS2CPacket(FabricPacket packet) { Objects.requireNonNull(packet, "Packet cannot be null"); Objects.requireNonNull(packet.getType(), "Packet#getType cannot return null"); - PacketByteBuf buf = PacketByteBufs.create(); - packet.write(buf); - return createS2CPacket(packet.getType().getId(), buf); + return new CustomPayloadS2CPacket(new TypedPayload(packet)); } } diff --git a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/server/ServerPlayNetworkAddon.java b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/server/ServerPlayNetworkAddon.java index 0ed9f6a4b3..052b4a2e3b 100644 --- a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/server/ServerPlayNetworkAddon.java +++ b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/server/ServerPlayNetworkAddon.java @@ -25,18 +25,20 @@ import net.minecraft.network.packet.Packet; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import net.fabricmc.fabric.api.networking.v1.FabricPacket; +import net.fabricmc.fabric.api.networking.v1.PacketSender; import net.fabricmc.fabric.api.networking.v1.S2CPlayChannelEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.fabric.impl.networking.AbstractChanneledNetworkAddon; import net.fabricmc.fabric.impl.networking.ChannelInfoHolder; import net.fabricmc.fabric.impl.networking.NetworkingImpl; -import net.fabricmc.fabric.impl.networking.payload.PacketByteBufPayload; +import net.fabricmc.fabric.impl.networking.payload.ResolvedPayload; -public final class ServerPlayNetworkAddon extends AbstractChanneledNetworkAddon { +public final class ServerPlayNetworkAddon extends AbstractChanneledNetworkAddon { private final ServerPlayNetworkHandler handler; private final MinecraftServer server; private boolean sentInitialRegisterPacket; @@ -62,19 +64,9 @@ public void onClientReady() { this.sentInitialRegisterPacket = true; } - /** - * Handles an incoming packet. - * - * @param payload the payload to handle - * @return true if the packet has been handled - */ - public boolean handle(PacketByteBufPayload payload) { - return this.handle(payload.id(), payload.data()); - } - @Override - protected void receive(ServerPlayNetworking.PlayChannelHandler handler, PacketByteBuf buf) { - handler.receive(this.server, this.handler.player, this.handler, buf, this); + protected void receive(Handler handler, ResolvedPayload payload) { + handler.receive(this.server, this.handler.player, this.handler, payload, this); } // impl details @@ -137,4 +129,8 @@ protected void invokeDisconnectEvent() { protected boolean isReservedChannel(Identifier channelName) { return NetworkingImpl.isReservedCommonChannel(channelName); } + + public interface Handler { + void receive(MinecraftServer server, ServerPlayerEntity player, ServerPlayNetworkHandler handler, ResolvedPayload payload, PacketSender responseSender); + } } diff --git a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/mixin/networking/CustomPayloadC2SPacketMixin.java b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/mixin/networking/CustomPayloadC2SPacketMixin.java index bb1966cc23..9b7567ca22 100644 --- a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/mixin/networking/CustomPayloadC2SPacketMixin.java +++ b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/mixin/networking/CustomPayloadC2SPacketMixin.java @@ -16,9 +16,7 @@ package net.fabricmc.fabric.mixin.networking; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -28,21 +26,18 @@ import net.minecraft.network.packet.c2s.common.CustomPayloadC2SPacket; import net.minecraft.util.Identifier; -import net.fabricmc.fabric.impl.networking.payload.PacketByteBufPayload; -import net.fabricmc.fabric.impl.networking.payload.PayloadHelper; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.impl.networking.payload.RetainedPayload; @Mixin(CustomPayloadC2SPacket.class) public class CustomPayloadC2SPacketMixin { - @Shadow - @Final - private static int MAX_PAYLOAD_SIZE; - @Inject( method = "readPayload", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/c2s/common/CustomPayloadC2SPacket;readUnknownPayload(Lnet/minecraft/util/Identifier;Lnet/minecraft/network/PacketByteBuf;)Lnet/minecraft/network/packet/UnknownCustomPayload;"), cancellable = true ) private static void readPayload(Identifier id, PacketByteBuf buf, CallbackInfoReturnable cir) { - cir.setReturnValue(new PacketByteBufPayload(id, PayloadHelper.read(buf, MAX_PAYLOAD_SIZE))); + cir.setReturnValue(new RetainedPayload(id, PacketByteBufs.retainedSlice(buf))); + buf.skipBytes(buf.readableBytes()); } } diff --git a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/mixin/networking/CustomPayloadS2CPacketMixin.java b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/mixin/networking/CustomPayloadS2CPacketMixin.java index 59e905f976..0b5a3c2723 100644 --- a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/mixin/networking/CustomPayloadS2CPacketMixin.java +++ b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/mixin/networking/CustomPayloadS2CPacketMixin.java @@ -16,9 +16,7 @@ package net.fabricmc.fabric.mixin.networking; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -28,21 +26,18 @@ import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket; import net.minecraft.util.Identifier; -import net.fabricmc.fabric.impl.networking.payload.PacketByteBufPayload; -import net.fabricmc.fabric.impl.networking.payload.PayloadHelper; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.impl.networking.payload.RetainedPayload; @Mixin(CustomPayloadS2CPacket.class) public class CustomPayloadS2CPacketMixin { - @Shadow - @Final - private static int MAX_PAYLOAD_SIZE; - @Inject( method = "readPayload", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/s2c/common/CustomPayloadS2CPacket;readUnknownPayload(Lnet/minecraft/util/Identifier;Lnet/minecraft/network/PacketByteBuf;)Lnet/minecraft/network/packet/UnknownCustomPayload;"), cancellable = true ) private static void readPayload(Identifier id, PacketByteBuf buf, CallbackInfoReturnable cir) { - cir.setReturnValue(new PacketByteBufPayload(id, PayloadHelper.read(buf, MAX_PAYLOAD_SIZE))); + cir.setReturnValue(new RetainedPayload(id, PacketByteBufs.retainedSlice(buf))); + buf.skipBytes(buf.readableBytes()); } } diff --git a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/mixin/networking/ServerCommonNetworkHandlerMixin.java b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/mixin/networking/ServerCommonNetworkHandlerMixin.java index 22e31cf1af..2d90a2e218 100644 --- a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/mixin/networking/ServerCommonNetworkHandlerMixin.java +++ b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/mixin/networking/ServerCommonNetworkHandlerMixin.java @@ -26,7 +26,8 @@ import net.minecraft.server.network.ServerCommonNetworkHandler; import net.fabricmc.fabric.impl.networking.NetworkHandlerExtensions; -import net.fabricmc.fabric.impl.networking.payload.PacketByteBufPayload; +import net.fabricmc.fabric.impl.networking.payload.ResolvablePayload; +import net.fabricmc.fabric.impl.networking.payload.RetainedPayload; import net.fabricmc.fabric.impl.networking.server.ServerConfigurationNetworkAddon; import net.fabricmc.fabric.impl.networking.server.ServerPlayNetworkAddon; @@ -34,7 +35,7 @@ public abstract class ServerCommonNetworkHandlerMixin implements NetworkHandlerExtensions { @Inject(method = "onCustomPayload", at = @At("HEAD"), cancellable = true) private void handleCustomPayloadReceivedAsync(CustomPayloadC2SPacket packet, CallbackInfo ci) { - if (packet.payload() instanceof PacketByteBufPayload payload) { + if (packet.payload() instanceof ResolvablePayload payload) { boolean handled; if (getAddon() instanceof ServerPlayNetworkAddon addon) { @@ -47,8 +48,9 @@ private void handleCustomPayloadReceivedAsync(CustomPayloadC2SPacket packet, Cal if (handled) { ci.cancel(); - } else { - payload.data().skipBytes(payload.data().readableBytes()); + } else if (payload instanceof RetainedPayload retained) { + retained.buf().skipBytes(retained.buf().readableBytes()); + retained.buf().release(); } } } diff --git a/fabric-networking-api-v1/src/testmod/java/net/fabricmc/fabric/test/networking/play/NetworkingPlayPacketTest.java b/fabric-networking-api-v1/src/testmod/java/net/fabricmc/fabric/test/networking/play/NetworkingPlayPacketTest.java index 87ff660824..12c76ffc91 100644 --- a/fabric-networking-api-v1/src/testmod/java/net/fabricmc/fabric/test/networking/play/NetworkingPlayPacketTest.java +++ b/fabric-networking-api-v1/src/testmod/java/net/fabricmc/fabric/test/networking/play/NetworkingPlayPacketTest.java @@ -71,14 +71,9 @@ public static void registerCommand(CommandDispatcher dispat return Command.SINGLE_SUCCESS; })) .then(literal("bundled").executes(ctx -> { - PacketByteBuf buf1 = PacketByteBufs.create(); - buf1.writeText(Text.literal("bundled #1")); - PacketByteBuf buf2 = PacketByteBufs.create(); - buf2.writeText(Text.literal("bundled #2")); - BundleS2CPacket packet = new BundleS2CPacket((List>) (Object) List.of( - ServerPlayNetworking.createS2CPacket(TEST_CHANNEL, buf1), - ServerPlayNetworking.createS2CPacket(TEST_CHANNEL, buf2))); + ServerPlayNetworking.createS2CPacket(new OverlayPacket(Text.literal("bundled #1"))), + ServerPlayNetworking.createS2CPacket(new OverlayPacket(Text.literal("bundled #2"))))); ctx.getSource().getPlayer().networkHandler.sendPacket(packet); return Command.SINGLE_SUCCESS; })));