From 53449a9de304edc22e4cdcb5994a9ab0bfb27bf6 Mon Sep 17 00:00:00 2001 From: Marc Hermans Date: Tue, 14 Nov 2023 11:42:49 +0100 Subject: [PATCH] Massively simplify the internals of how stuff is registered. --- .../network/NetworkInitialization.java | 34 +--- .../event/RegisterPacketHandlerEvent.java | 12 +- .../filters/VanillaPacketSplitter.java | 5 +- .../network/handling/IPlayPayloadHandler.java | 10 + .../network/payload/ConfigFilePayload.java | 17 ++ .../network/registration/NetworkRegistry.java | 6 +- .../ConfigurationPayloadHandler.java | 19 ++ .../registrar/ConfigurationRegistration.java | 4 +- .../registrar/IFlowBasedPayloadRegistrar.java | 28 --- .../INetworkPayloadVersioningBuilder.java | 16 ++ .../registrar/IPayloadRegistrar.java | 126 ++++++------ .../IPayloadRegistrarWithAcceptableRange.java | 14 -- .../registrar/IVersionedPayloadRegistrar.java | 6 - .../registrar/ModdedPacketRegistrar.java | 186 +++++++----------- .../registrar/PlayPayloadHandler.java | 19 ++ .../registrar/PlayRegistration.java | 4 +- .../RegistrationFailedException.java | 35 +--- 17 files changed, 246 insertions(+), 295 deletions(-) create mode 100644 src/main/java/net/neoforged/neoforge/network/payload/ConfigFilePayload.java delete mode 100644 src/main/java/net/neoforged/neoforge/network/registration/registrar/IFlowBasedPayloadRegistrar.java create mode 100644 src/main/java/net/neoforged/neoforge/network/registration/registrar/INetworkPayloadVersioningBuilder.java delete mode 100644 src/main/java/net/neoforged/neoforge/network/registration/registrar/IPayloadRegistrarWithAcceptableRange.java delete mode 100644 src/main/java/net/neoforged/neoforge/network/registration/registrar/IVersionedPayloadRegistrar.java diff --git a/src/main/java/net/neoforged/neoforge/network/NetworkInitialization.java b/src/main/java/net/neoforged/neoforge/network/NetworkInitialization.java index 818ad4c1988..ffba15f4190 100644 --- a/src/main/java/net/neoforged/neoforge/network/NetworkInitialization.java +++ b/src/main/java/net/neoforged/neoforge/network/NetworkInitialization.java @@ -5,51 +5,40 @@ package net.neoforged.neoforge.network; -import java.util.Arrays; -import java.util.List; - import net.minecraft.network.protocol.PacketFlow; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.Mod; import net.neoforged.neoforge.internal.versions.neoforge.NeoForgeVersion; -import net.neoforged.neoforge.network.event.EventNetworkChannel; import net.neoforged.neoforge.network.event.RegisterPacketHandlerEvent; import net.neoforged.neoforge.network.handlers.ClientForgeRegistryHandler; import net.neoforged.neoforge.network.handlers.ServerForgeRegistryHandler; -import net.neoforged.neoforge.network.handling.ConfigurationPayloadContext; -import net.neoforged.neoforge.network.handling.IConfigurationPayloadHandler; import net.neoforged.neoforge.network.payload.FrozenRegistryPayload; import net.neoforged.neoforge.network.payload.FrozenRegistrySyncCompletePayload; import net.neoforged.neoforge.network.payload.FrozenRegistrySyncStartPayload; -import net.neoforged.neoforge.network.simple.SimpleChannel; -import net.neoforged.neoforge.registries.RegistryManager; +import net.neoforged.neoforge.network.registration.registrar.IPayloadRegistrar; import org.jetbrains.annotations.ApiStatus; @Mod.EventBusSubscriber(modid = NeoForgeVersion.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) @ApiStatus.Internal public class NetworkInitialization { - + @SubscribeEvent public static void register(final RegisterPacketHandlerEvent event) { - event.registrar() - .withVersion(buildNetworkVersion()) - .flowing(PacketFlow.CLIENTBOUND) + final IPayloadRegistrar registrar = event.registrar(NeoForgeVersion.MOD_ID) + .versioned(buildNetworkVersion()); + registrar .configuration( FrozenRegistrySyncStartPayload.ID, - FrozenRegistrySyncStartPayload.class, FrozenRegistrySyncStartPayload::new, handlers -> handlers.client(ClientForgeRegistryHandler.getInstance()::handle) ) .configuration( FrozenRegistryPayload.ID, - FrozenRegistryPayload.class, FrozenRegistryPayload::new, handlers -> handlers.client(ClientForgeRegistryHandler.getInstance()::handle) ) - .bidirectional() .configuration( FrozenRegistrySyncCompletePayload.ID, - FrozenRegistrySyncCompletePayload.class, FrozenRegistrySyncCompletePayload::new, handlers -> handlers.client(ClientForgeRegistryHandler.getInstance()::handle) .server(ServerForgeRegistryHandler.getInstance()::handle) @@ -82,21 +71,8 @@ private static int buildNetworkVersion() { /* public static SimpleChannel getHandshakeChannel() { SimpleChannel handshakeChannel = NetworkRegistry.ChannelBuilder.named(NetworkConstants.FML_HANDSHAKE_RESOURCE).clientAcceptedVersions(a -> true).serverAcceptedVersions(a -> true).networkProtocolVersion(() -> NetworkConstants.NETVERSION).simpleChannel(); - handshakeChannel.simpleLoginMessageBuilder(HandshakeMessages.C2SAcknowledge.class, 99, LoginNetworkDirection.LOGIN_TO_SERVER).decoder(HandshakeMessages.C2SAcknowledge::decode).consumerNetworkThread(HandshakeHandler.indexFirst(HandshakeHandler::handleClientAck)).add(); - - handshakeChannel.simpleLoginMessageBuilder(HandshakeMessages.S2CModData.class, 5, LoginNetworkDirection.LOGIN_TO_CLIENT).decoder(HandshakeMessages.S2CModData::decode).markAsLoginPacket().noResponse().consumerNetworkThread(HandshakeHandler.consumerFor(HandshakeHandler::handleModData)).add(); - - handshakeChannel.simpleLoginMessageBuilder(HandshakeMessages.S2CModList.class, 1, LoginNetworkDirection.LOGIN_TO_CLIENT).decoder(HandshakeMessages.S2CModList::decode).markAsLoginPacket().consumerNetworkThread(HandshakeHandler.consumerFor(HandshakeHandler::handleServerModListOnClient)).add(); - - handshakeChannel.simpleLoginMessageBuilder(HandshakeMessages.C2SModListReply.class, 2, LoginNetworkDirection.LOGIN_TO_SERVER).decoder(HandshakeMessages.C2SModListReply::decode).consumerNetworkThread(HandshakeHandler.indexFirst(HandshakeHandler::handleClientModListOnServer)).add(); - - handshakeChannel.simpleLoginMessageBuilder(HandshakeMessages.S2CRegistry.class, 3, LoginNetworkDirection.LOGIN_TO_CLIENT).decoder(HandshakeMessages.S2CRegistry::decode).buildLoginPacketList(RegistryManager::generateRegistryPackets). //TODO: Make this non-static, and store a cache on the client. - consumerNetworkThread(HandshakeHandler.consumerFor(HandshakeHandler::handleRegistryMessage)).add(); - handshakeChannel.simpleLoginMessageBuilder(HandshakeMessages.S2CConfigData.class, 4, LoginNetworkDirection.LOGIN_TO_CLIENT).decoder(HandshakeMessages.S2CConfigData::decode).buildLoginPacketList(ConfigSync.INSTANCE::syncConfigs).consumerNetworkThread(HandshakeHandler.consumerFor(HandshakeHandler::handleConfigSync)).add(); - handshakeChannel.simpleLoginMessageBuilder(HandshakeMessages.S2CChannelMismatchData.class, 6, LoginNetworkDirection.LOGIN_TO_CLIENT).decoder(HandshakeMessages.S2CChannelMismatchData::decode).consumerNetworkThread(HandshakeHandler.consumerFor(HandshakeHandler::handleModMismatchData)).add(); - return handshakeChannel; } diff --git a/src/main/java/net/neoforged/neoforge/network/event/RegisterPacketHandlerEvent.java b/src/main/java/net/neoforged/neoforge/network/event/RegisterPacketHandlerEvent.java index feae8717d7d..9f33b2e2aba 100644 --- a/src/main/java/net/neoforged/neoforge/network/event/RegisterPacketHandlerEvent.java +++ b/src/main/java/net/neoforged/neoforge/network/event/RegisterPacketHandlerEvent.java @@ -3,20 +3,20 @@ import com.google.common.collect.ImmutableMap; import net.minecraft.resources.ResourceLocation; import net.neoforged.bus.api.Event; -import net.neoforged.fml.ModLoadingContext; -import net.neoforged.fml.event.IModBusEvent; import net.neoforged.neoforge.network.registration.registrar.ConfigurationRegistration; +import net.neoforged.neoforge.network.registration.registrar.IPayloadRegistrar; import net.neoforged.neoforge.network.registration.registrar.ModdedPacketRegistrar; import net.neoforged.neoforge.network.registration.registrar.PlayRegistration; -import java.util.*; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; -public class RegisterPacketHandlerEvent extends Event implements IModBusEvent { +public class RegisterPacketHandlerEvent extends Event { private final Map registrarsByNamespace = Collections.synchronizedMap(new HashMap<>()); - public ModdedPacketRegistrar registrar() { - final String namespace = ModLoadingContext.get().getActiveNamespace(); + public IPayloadRegistrar registrar(String namespace) { return registrarsByNamespace.computeIfAbsent(namespace, ModdedPacketRegistrar::new); } diff --git a/src/main/java/net/neoforged/neoforge/network/filters/VanillaPacketSplitter.java b/src/main/java/net/neoforged/neoforge/network/filters/VanillaPacketSplitter.java index 60e47afcbcd..3724295fb2e 100644 --- a/src/main/java/net/neoforged/neoforge/network/filters/VanillaPacketSplitter.java +++ b/src/main/java/net/neoforged/neoforge/network/filters/VanillaPacketSplitter.java @@ -49,11 +49,10 @@ public class VanillaPacketSplitter { @SubscribeEvent public static void register(final RegisterPacketHandlerEvent event) { - event.registrar() - .withVersion(VERSION) + event.registrar(NeoForgeVersion.MOD_ID) + .versioned(versioning -> versioning.withVersion(VERSION).optional()) .common( SplitPacketPayload.ID, - SplitPacketPayload.class, SplitPacketPayload::new, VanillaPacketSplitter::receivedPacket ); diff --git a/src/main/java/net/neoforged/neoforge/network/handling/IPlayPayloadHandler.java b/src/main/java/net/neoforged/neoforge/network/handling/IPlayPayloadHandler.java index 942a09bf214..d674a49d584 100644 --- a/src/main/java/net/neoforged/neoforge/network/handling/IPlayPayloadHandler.java +++ b/src/main/java/net/neoforged/neoforge/network/handling/IPlayPayloadHandler.java @@ -17,4 +17,14 @@ public interface IPlayPayloadHandler { * @param payload The payload. */ void handle(PlayPayloadContext context, T payload); + + /** + * Creates a handler that does nothing. + * + * @return The handler. + * @param The type of payload. + */ + static IPlayPayloadHandler noop() { + return (context, payload) -> {}; + } } diff --git a/src/main/java/net/neoforged/neoforge/network/payload/ConfigFilePayload.java b/src/main/java/net/neoforged/neoforge/network/payload/ConfigFilePayload.java new file mode 100644 index 00000000000..6bc2238e29e --- /dev/null +++ b/src/main/java/net/neoforged/neoforge/network/payload/ConfigFilePayload.java @@ -0,0 +1,17 @@ +package net.neoforged.neoforge.network.payload; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; + +public record ConfigFilePayload() implements CustomPacketPayload { + @Override + public void write(FriendlyByteBuf p_294947_) { + + } + + @Override + public ResourceLocation id() { + return null; + } +} diff --git a/src/main/java/net/neoforged/neoforge/network/registration/NetworkRegistry.java b/src/main/java/net/neoforged/neoforge/network/registration/NetworkRegistry.java index c2046840b09..10cbf72787f 100644 --- a/src/main/java/net/neoforged/neoforge/network/registration/NetworkRegistry.java +++ b/src/main/java/net/neoforged/neoforge/network/registration/NetworkRegistry.java @@ -26,6 +26,8 @@ import net.minecraft.util.thread.ReentrantBlockableEventLoop; import net.neoforged.fml.ModLoader; import net.neoforged.fml.config.ConfigTracker; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.common.NeoForgeMod; import net.neoforged.neoforge.internal.versions.neoforge.NeoForgeVersion; import net.neoforged.neoforge.network.connection.ConnectionUtils; import net.neoforged.neoforge.network.event.RegisterPacketHandlerEvent; @@ -104,9 +106,7 @@ public void setup() { setup = true; - final RegisterPacketHandlerEvent event = new RegisterPacketHandlerEvent(); - ModLoader.get().postEventWrapContainerInModOrder(event); - + final RegisterPacketHandlerEvent event = NeoForge.EVENT_BUS.post(new RegisterPacketHandlerEvent()); knownConfigurationRegistrations.clear(); knownPlayRegistrations.clear(); diff --git a/src/main/java/net/neoforged/neoforge/network/registration/registrar/ConfigurationPayloadHandler.java b/src/main/java/net/neoforged/neoforge/network/registration/registrar/ConfigurationPayloadHandler.java index 9cfe7c46614..811b05fbe33 100644 --- a/src/main/java/net/neoforged/neoforge/network/registration/registrar/ConfigurationPayloadHandler.java +++ b/src/main/java/net/neoforged/neoforge/network/registration/registrar/ConfigurationPayloadHandler.java @@ -1,11 +1,14 @@ package net.neoforged.neoforge.network.registration.registrar; +import net.minecraft.network.protocol.PacketFlow; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.neoforged.neoforge.network.handling.ConfigurationPayloadContext; import net.neoforged.neoforge.network.handling.IConfigurationPayloadHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Optional; + public final class ConfigurationPayloadHandler implements IConfigurationPayloadHandler { @Nullable @@ -31,6 +34,22 @@ public void handle(ConfigurationPayloadContext context, T payload) { } } + Optional flow() { + if (clientSide == null && serverSide == null) { + return Optional.empty(); + } + + if (clientSide == null) { + return Optional.of(PacketFlow.SERVERBOUND); + } + + if (serverSide == null) { + return Optional.of(PacketFlow.CLIENTBOUND); + } + + return Optional.empty(); + } + public static class Builder { private @Nullable IConfigurationPayloadHandler clientSide; private @Nullable IConfigurationPayloadHandler serverSide; diff --git a/src/main/java/net/neoforged/neoforge/network/registration/registrar/ConfigurationRegistration.java b/src/main/java/net/neoforged/neoforge/network/registration/registrar/ConfigurationRegistration.java index 1c030baa29a..27d74f6bb2a 100644 --- a/src/main/java/net/neoforged/neoforge/network/registration/registrar/ConfigurationRegistration.java +++ b/src/main/java/net/neoforged/neoforge/network/registration/registrar/ConfigurationRegistration.java @@ -12,7 +12,6 @@ import java.util.OptionalInt; public record ConfigurationRegistration( - Class type, IPayloadReader reader, IConfigurationPayloadHandler handler, OptionalInt version, @@ -21,9 +20,10 @@ public record ConfigurationRegistration( Optional flow, boolean optional ) implements IConfigurationPayloadHandler, IPayloadReader { + @SuppressWarnings({"rawtypes", "unchecked"}) @Override public void handle(ConfigurationPayloadContext context, CustomPacketPayload payload) { - handler.handle(context, type.cast(payload)); + ((IConfigurationPayloadHandler) handler).handle(context, payload); } @Override diff --git a/src/main/java/net/neoforged/neoforge/network/registration/registrar/IFlowBasedPayloadRegistrar.java b/src/main/java/net/neoforged/neoforge/network/registration/registrar/IFlowBasedPayloadRegistrar.java deleted file mode 100644 index 40caa089b67..00000000000 --- a/src/main/java/net/neoforged/neoforge/network/registration/registrar/IFlowBasedPayloadRegistrar.java +++ /dev/null @@ -1,28 +0,0 @@ -package net.neoforged.neoforge.network.registration.registrar; - -import net.minecraft.network.protocol.PacketFlow; - -/** - * A registrar that is bound to a specific {@link PacketFlow}. - */ -public interface IFlowBasedPayloadRegistrar extends IPayloadRegistrar { - - /** - * Forces all payloads registered with this registrar to be only capable of flowing in a given packet flow. - * - * @param flow The flow. - * @return A registrar that is bound to the given flow. - */ - IPayloadRegistrarWithAcceptableRange flowing(PacketFlow flow); - - /** - * Enables payloads registered with this registrar to flow in both directions. - *

- * This is the default value for all registrars, unless {@link #flowing(PacketFlow)} has been called. - * Invoking this method as such is only needed to reset the ability to flow in both directions. - *

- * - * @return A registrar that is bound to both directions. - */ - IPayloadRegistrarWithAcceptableRange bidirectional(); -} diff --git a/src/main/java/net/neoforged/neoforge/network/registration/registrar/INetworkPayloadVersioningBuilder.java b/src/main/java/net/neoforged/neoforge/network/registration/registrar/INetworkPayloadVersioningBuilder.java new file mode 100644 index 00000000000..ecbe1ad1409 --- /dev/null +++ b/src/main/java/net/neoforged/neoforge/network/registration/registrar/INetworkPayloadVersioningBuilder.java @@ -0,0 +1,16 @@ +package net.neoforged.neoforge.network.registration.registrar; + +public interface INetworkPayloadVersioningBuilder { + + INetworkPayloadVersioningBuilder withVersion(int version); + + INetworkPayloadVersioningBuilder withMinimalVersion(int min); + + INetworkPayloadVersioningBuilder withMaximalVersion(int max); + + INetworkPayloadVersioningBuilder optional(); + + default INetworkPayloadVersioningBuilder withAcceptableRange(int min, int max) { + return withMinimalVersion(min).withMaximalVersion(max); + } +} diff --git a/src/main/java/net/neoforged/neoforge/network/registration/registrar/IPayloadRegistrar.java b/src/main/java/net/neoforged/neoforge/network/registration/registrar/IPayloadRegistrar.java index a28cb62515c..c7c1d3501bc 100644 --- a/src/main/java/net/neoforged/neoforge/network/registration/registrar/IPayloadRegistrar.java +++ b/src/main/java/net/neoforged/neoforge/network/registration/registrar/IPayloadRegistrar.java @@ -20,8 +20,8 @@ *
* When you implement your {@link CustomPacketPayload#write(FriendlyByteBuf)} method you do not need to write the id of the payload, * neither do you need to read it in your {@link IPayloadReader} implementation. However, you do need to make sure that the - * id you pass into {@link #play(ResourceLocation, Class, IPayloadReader, IPlayPayloadHandler)} and - * {@link #configuration(ResourceLocation, Class, IPayloadReader, IConfigurationPayloadHandler)} is the same as the id you + * id you pass into {@link #play(ResourceLocation, IPayloadReader, IPlayPayloadHandler)} and + * {@link #configuration(ResourceLocation, IPayloadReader, IConfigurationPayloadHandler)} is the same as the id you * return from your {@link CustomPacketPayload#id()}. We suggest using a public static final ResourceLocation field * to store it and then reference it in both places. *
@@ -43,8 +43,8 @@ *
  • Play payloads: These are payloads that are sent from the client to the server, or from the server to the client, during normal gameplay.
  • *
  • Configuration payloads: These are payloads that are sent from the server to the client, or from the client to the server, during the login process, before the player is spawned.
  • * - * You can register a custom payload for either of these types of payloads using the {@link #play(ResourceLocation, Class, IPayloadReader, IPlayPayloadHandler)} - * and {@link #configuration(ResourceLocation, Class, IPayloadReader, IConfigurationPayloadHandler)} methods respectively. + * You can register a custom payload for either of these types of payloads using the {@link #play(ResourceLocation, IPayloadReader, IPlayPayloadHandler)} + * and {@link #configuration(ResourceLocation, IPayloadReader, IConfigurationPayloadHandler)} methods respectively. *
    * The difference between the play and configuration phases, if you like to call them that, is that the configuration phase generally requires * a confirmation payload to be returned to the server to trigger the next phase. In the {@link ConfigurationPayloadContext context} passed into @@ -56,7 +56,7 @@ * Note: the processing of payloads happens solely on the network thread. You are yourself responsible for ensuring that any data you access * in your handlers is either thread safe, or that you queue up your work to be done on the main thread, of the relevant side. * This is particularly important for the {@link IPlayPayloadHandler} or {@link IConfigurationPayloadHandler} implementations that you pass to - * {@link #play(ResourceLocation, Class, IPayloadReader, IPlayPayloadHandler)} or {@link #configuration(ResourceLocation, Class, IPayloadReader, IConfigurationPayloadHandler)} + * {@link #play(ResourceLocation, IPayloadReader, IPlayPayloadHandler)} or {@link #configuration(ResourceLocation, IPayloadReader, IConfigurationPayloadHandler)} * respectively, since those are also invoked on the network thread. *
    * The {@link PlayPayloadContext} and {@link ConfigurationPayloadContext} given to each of these handlers contains a {@link ISynchronizedWorkHandler} @@ -67,125 +67,119 @@ public interface IPayloadRegistrar { /** - * Gets the namespace of this registrar. + * Configurers the copy of this registrar that is returned to use a specific version. + *

    + * This is a short circuit for calling {@link INetworkPayloadVersioningBuilder#withVersion(int)} in the callback passed to + * {@link #versioned(Consumer)}. + *

    + * @param version The version to use. + * @return A copy of this registrar with the version configured. + */ + default IPayloadRegistrar versioned(int version) { + return versioned(builder -> builder.withVersion(version)); + } + + /** + * Configures a copy of this registrar using the given configurer with respect to versioning of the payloads registered throuh it. * - * @return The namespace of this registrar. + * @param configurer The configurer to use. + * @return A copy of this registrar with the versioning configured. */ - String getNamespace(); + IPayloadRegistrar versioned(Consumer configurer); /** * Registers a new payload type for the play phase. * - * @param id The id of the payload. - * @param type The class of the payload. - * @param reader The reader for the payload. + * @param The type of the payload. + * @param id The id of the payload. + * @param reader The reader for the payload. * @param handler The handler for the payload. - * @param The type of the payload. * @return The registrar. - * * @implNote This method will capture all internal errors and wrap them in a {@link RegistrationFailedException}. */ - IPayloadRegistrarWithAcceptableRange play(ResourceLocation id, Class type, IPayloadReader reader, IPlayPayloadHandler handler); + IPayloadRegistrar play(ResourceLocation id, IPayloadReader reader, IPlayPayloadHandler handler); /** * Registers a new payload type for the play phase. *

    - * This method allows different handlers to be registered for different packet-flows. - *
    - * In practice this means that you can register a different handler for clientbound and serverbound packets, - * which allows you to handle them differently on the client and server side. + * This method allows different handlers to be registered for different packet-flows. + *
    + * In practice this means that you can register a different handler for clientbound and serverbound packets, + * which allows you to handle them differently on the client and server side. *

    * - * @param id The id of the payload. - * @param type The class of the payload. - * @param reader The reader for the payload. + * @param The type of the payload. + * @param id The id of the payload. + * @param reader The reader for the payload. * @param handler The handler for the payload. - * @param The type of the payload. * @return The registrar. - * * @implNote This method will capture all internal errors and wrap them in a {@link RegistrationFailedException}. */ - default IPayloadRegistrarWithAcceptableRange play(ResourceLocation id, Class type, IPayloadReader reader, Consumer> handler) { - final PlayPayloadHandler.Builder builder = new PlayPayloadHandler.Builder<>(); - handler.accept(builder); - return play(id, type, reader, builder.create()); - } + IPayloadRegistrar play(ResourceLocation id, IPayloadReader reader, Consumer> handler); /** * Registers a new payload type for the configuration phase. * - * @param id The id of the payload. - * @param type The class of the payload. - * @param reader The reader for the payload. + * @param The type of the payload. + * @param id The id of the payload. + * @param reader The reader for the payload. * @param handler The handler for the payload. - * @param The type of the payload. * @return The registrar. - * * @implNote This method will capture all internal errors and wrap them in a {@link RegistrationFailedException}. */ - IPayloadRegistrarWithAcceptableRange configuration(ResourceLocation id, Class type, IPayloadReader reader, IConfigurationPayloadHandler handler); + IPayloadRegistrar configuration(ResourceLocation id, IPayloadReader reader, IConfigurationPayloadHandler handler); /** * Registers a new payload type for the configuration phase. *

    - * This method allows different handlers to be registered for different packet-flows. - *
    - * In practice this means that you can register a different handler for clientbound and serverbound packets, - * which allows you to handle them differently on the client and server side. + * This method allows different handlers to be registered for different packet-flows. + *
    + * In practice this means that you can register a different handler for clientbound and serverbound packets, + * which allows you to handle them differently on the client and server side. *

    * - * @param id The id of the payload. - * @param type The class of the payload. - * @param reader The reader for the payload. + * @param The type of the payload. + * @param id The id of the payload. + * @param reader The reader for the payload. * @param handler The handler for the payload. - * @param The type of the payload. * @return The registrar. - * * @implNote This method will capture all internal errors and wrap them in a {@link RegistrationFailedException}. */ - default IPayloadRegistrarWithAcceptableRange configuration(ResourceLocation id, Class type, IPayloadReader reader, Consumer> handler) { - final ConfigurationPayloadHandler.Builder builder = new ConfigurationPayloadHandler.Builder<>(); - handler.accept(builder); - return configuration(id, type, reader, builder.create()); - } + IPayloadRegistrar configuration(ResourceLocation id, IPayloadReader reader, Consumer> handler); /** * Registers a new payload type for all supported phases. * - * @param id The id of the payload. - * @param type The class of the payload. - * @param reader The reader for the payload. + * @param The type of the payload. + * @param id The id of the payload. + * @param reader The reader for the payload. * @param handler The handler for the payload. * @return The registrar. - * - * @param The type of the payload. */ - default IPayloadRegistrarWithAcceptableRange common(ResourceLocation id, Class type, IPayloadReader reader, IPayloadHandler handler) { - return play(id, type, reader, handler::handle).configuration(id, type, reader, handler::handle); + default IPayloadRegistrar common(ResourceLocation id, IPayloadReader reader, IPayloadHandler handler) { + return play(id, reader, handler::handle).configuration(id, reader, handler::handle); } /** * Registers a new payload type for all supported phases. *

    - * This method allows different handlers to be registered for different packet-flows. - *
    - * In practice this means that you can register a different handler for clientbound and serverbound packets, - * which allows you to handle them differently on the client and server side. + * This method allows different handlers to be registered for different packet-flows. + *
    + * In practice this means that you can register a different handler for clientbound and serverbound packets, + * which allows you to handle them differently on the client and server side. *

    * - * @param id The id of the payload. - * @param type The class of the payload. - * @param reader The reader for the payload. + * @param The type of the payload. + * @param id The id of the payload. + * @param reader The reader for the payload. * @param handler The handler for the payload. * @return The registrar. - * - * @param The type of the payload. */ - default IPayloadRegistrarWithAcceptableRange common(ResourceLocation id, Class type, IPayloadReader reader, Consumer> handler) { + default IPayloadRegistrar common(ResourceLocation id, IPayloadReader reader, Consumer> handler) { final PayloadHandlerBuilder builder = new PayloadHandlerBuilder<>(); handler.accept(builder); - return play(id, type, reader, builder::handle).configuration(id, type, reader, builder::handle); + return play(id, reader, builder::handle).configuration(id, reader, builder::handle); } } diff --git a/src/main/java/net/neoforged/neoforge/network/registration/registrar/IPayloadRegistrarWithAcceptableRange.java b/src/main/java/net/neoforged/neoforge/network/registration/registrar/IPayloadRegistrarWithAcceptableRange.java deleted file mode 100644 index 21c5da2d86f..00000000000 --- a/src/main/java/net/neoforged/neoforge/network/registration/registrar/IPayloadRegistrarWithAcceptableRange.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.neoforged.neoforge.network.registration.registrar; - -public interface IPayloadRegistrarWithAcceptableRange extends IVersionedPayloadRegistrar { - - IPayloadRegistrarWithAcceptableRange withMinimalVersion(int min); - - IPayloadRegistrarWithAcceptableRange withMaximalVersion(int max); - - IPayloadRegistrarWithAcceptableRange optional(); - - default IPayloadRegistrarWithAcceptableRange withAcceptableRange(int min, int max) { - return withMinimalVersion(min).withMaximalVersion(max); - } -} diff --git a/src/main/java/net/neoforged/neoforge/network/registration/registrar/IVersionedPayloadRegistrar.java b/src/main/java/net/neoforged/neoforge/network/registration/registrar/IVersionedPayloadRegistrar.java deleted file mode 100644 index 5193593b445..00000000000 --- a/src/main/java/net/neoforged/neoforge/network/registration/registrar/IVersionedPayloadRegistrar.java +++ /dev/null @@ -1,6 +0,0 @@ -package net.neoforged.neoforge.network.registration.registrar; - -public interface IVersionedPayloadRegistrar extends IFlowBasedPayloadRegistrar { - - IPayloadRegistrarWithAcceptableRange withVersion(int version); -} diff --git a/src/main/java/net/neoforged/neoforge/network/registration/registrar/ModdedPacketRegistrar.java b/src/main/java/net/neoforged/neoforge/network/registration/registrar/ModdedPacketRegistrar.java index 85a4aa964f4..e206962d237 100644 --- a/src/main/java/net/neoforged/neoforge/network/registration/registrar/ModdedPacketRegistrar.java +++ b/src/main/java/net/neoforged/neoforge/network/registration/registrar/ModdedPacketRegistrar.java @@ -2,7 +2,6 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; -import net.minecraft.network.protocol.PacketFlow; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.network.handling.IConfigurationPayloadHandler; @@ -12,15 +11,34 @@ import java.util.Map; import java.util.Optional; import java.util.OptionalInt; +import java.util.function.Consumer; -public class ModdedPacketRegistrar implements IPayloadRegistrarWithAcceptableRange { +@SuppressWarnings("OptionalUsedAsFieldOrParameterType") +public class ModdedPacketRegistrar implements IPayloadRegistrar, INetworkPayloadVersioningBuilder { private final String modId; - private final Map> configurationPayloads = Maps.newHashMap(); - private final Map> playPayloads = Maps.newHashMap(); + private final Map> configurationPayloads; + private final Map> playPayloads; + private OptionalInt version = OptionalInt.empty(); + private OptionalInt minimalVersion = OptionalInt.empty(); + private OptionalInt maximalVersion = OptionalInt.empty(); + private boolean optional = false; + public ModdedPacketRegistrar(String modId) { this.modId = modId; + playPayloads = Maps.newHashMap(); + configurationPayloads = Maps.newHashMap(); + } + + private ModdedPacketRegistrar(ModdedPacketRegistrar source) { + this.modId = source.modId; + this.playPayloads = source.playPayloads; + this.configurationPayloads = source.configurationPayloads; + this.version = source.version; + this.minimalVersion = source.minimalVersion; + this.maximalVersion = source.maximalVersion; + this.optional = source.optional; } public Map> getConfigurationRegistrations() { @@ -31,157 +49,103 @@ public Map> getPlayRegistrations() { return ImmutableMap.copyOf(playPayloads); } - @Override - public String getNamespace() { - return modId; - } @Override - public IPayloadRegistrarWithAcceptableRange play(ResourceLocation id, Class type, IPayloadReader reader, IPlayPayloadHandler handler) { + public IPayloadRegistrar play(ResourceLocation id, IPayloadReader reader, IPlayPayloadHandler handler) { play( id, new PlayRegistration<>( - type, reader, handler, OptionalInt.empty(), OptionalInt.empty(), OptionalInt.empty(), Optional.empty(), false + reader, handler, version, minimalVersion, maximalVersion, Optional.empty(), optional ) ); return this; } @Override - public IPayloadRegistrarWithAcceptableRange configuration(ResourceLocation id, Class type, IPayloadReader reader, IConfigurationPayloadHandler handler) { + public IPayloadRegistrar configuration(ResourceLocation id, IPayloadReader reader, IConfigurationPayloadHandler handler) { configuration( id, new ConfigurationRegistration<>( - type, reader, handler, OptionalInt.empty(), OptionalInt.empty(), OptionalInt.empty(), Optional.empty(), false + reader, handler, version, minimalVersion, maximalVersion, Optional.empty(), optional ) ); return this; } @Override - public IPayloadRegistrarWithAcceptableRange withVersion(int version) { - final Configured configured = new Configured(); - return configured.withVersion(version); - } - - @Override - public IPayloadRegistrarWithAcceptableRange withMinimalVersion(int min) { - final Configured configured = new Configured(); - return configured.withMinimalVersion(min); - } - - @Override - public IPayloadRegistrarWithAcceptableRange withMaximalVersion(int max) { - final Configured configured = new Configured(); - return configured.withMaximalVersion(max); - } - - @Override - public IPayloadRegistrarWithAcceptableRange optional() { - final Configured configured = new Configured(); - return configured.optional(); + public IPayloadRegistrar versioned(Consumer configurer) { + final ModdedPacketRegistrar copy = new ModdedPacketRegistrar(this); + configurer.accept(copy); + return copy; } @Override - public IPayloadRegistrarWithAcceptableRange flowing(PacketFlow flow) { - final Configured configured = new Configured(); - return configured.flowing(flow); + public IPayloadRegistrar play(ResourceLocation id, IPayloadReader reader, Consumer> handler) { + final PlayPayloadHandler.Builder builder = new PlayPayloadHandler.Builder<>(); + handler.accept(builder); + final PlayPayloadHandler innerHandler = builder.create(); + play( + id, new PlayRegistration<>( + reader, innerHandler, version, minimalVersion, maximalVersion, innerHandler.flow(), optional + ) + ); + return this; } @Override - public IPayloadRegistrarWithAcceptableRange bidirectional() { + public IPayloadRegistrar configuration(ResourceLocation id, IPayloadReader reader, Consumer> handler) { + final ConfigurationPayloadHandler.Builder builder = new ConfigurationPayloadHandler.Builder<>(); + handler.accept(builder); + final ConfigurationPayloadHandler innerHandler = builder.create(); + configuration( + id, new ConfigurationRegistration<>( + reader, innerHandler, version, minimalVersion, maximalVersion, innerHandler.flow(), optional + ) + ); return this; } private void configuration(final ResourceLocation id, ConfigurationRegistration registration) { - validatePayload(id, registration.type(), configurationPayloads); + validatePayload(id, configurationPayloads); configurationPayloads.put(id, registration); } private void play(final ResourceLocation id, PlayRegistration registration) { - validatePayload(id, registration.type(), playPayloads); + validatePayload(id, playPayloads); playPayloads.put(id, registration); } - private void validatePayload(ResourceLocation id, Class type, final Map payloads) { + private void validatePayload(ResourceLocation id, final Map payloads) { if (payloads.containsKey(id)) { - throw new RegistrationFailedException(type, id, modId, RegistrationFailedException.Reason.DUPLICATE_ID); + throw new RegistrationFailedException(id, modId, RegistrationFailedException.Reason.DUPLICATE_ID); } if (!id.getNamespace().equals(modId)) { - throw new RegistrationFailedException(type, id, modId, RegistrationFailedException.Reason.INVALID_NAMESPACE); + throw new RegistrationFailedException(id, modId, RegistrationFailedException.Reason.INVALID_NAMESPACE); } } - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - private class Configured implements IPayloadRegistrarWithAcceptableRange { - - private OptionalInt version = OptionalInt.empty(); - private OptionalInt minimalVersion = OptionalInt.empty(); - private OptionalInt maximalVersion = OptionalInt.empty(); - private PacketFlow flow = null; - private boolean optional = false; - - @Override - public String getNamespace() { - return modId; - } - - @Override - public IPayloadRegistrarWithAcceptableRange play(ResourceLocation id, Class type, IPayloadReader reader, IPlayPayloadHandler handler) { - ModdedPacketRegistrar.this.play( - id, new PlayRegistration<>( - type, reader, handler, version, minimalVersion, maximalVersion, Optional.ofNullable(flow), optional - ) - ); - return this; - } - - @Override - public IPayloadRegistrarWithAcceptableRange configuration(ResourceLocation id, Class type, IPayloadReader reader, IConfigurationPayloadHandler handler) { - ModdedPacketRegistrar.this.configuration( - id, new ConfigurationRegistration<>( - type, reader, handler, version, minimalVersion, maximalVersion, Optional.ofNullable(flow), optional - ) - ); - return this; - } - - @Override - public IPayloadRegistrarWithAcceptableRange withVersion(int version) { - this.version = OptionalInt.of(version); - return this; - } - - @Override - public IPayloadRegistrarWithAcceptableRange withMinimalVersion(int min) { - this.minimalVersion = OptionalInt.of(min); - return this; - } - - @Override - public IPayloadRegistrarWithAcceptableRange withMaximalVersion(int max) { - this.maximalVersion = OptionalInt.of(max); - return this; - } - - @Override - public IPayloadRegistrarWithAcceptableRange optional() { - this.optional = true; - return this; - } - - @Override - public IPayloadRegistrarWithAcceptableRange flowing(PacketFlow flow) { - this.flow = flow; - return this; - } - - @Override - public IPayloadRegistrarWithAcceptableRange bidirectional() { - this.flow = null; - return this; - } + @Override + public INetworkPayloadVersioningBuilder withVersion(int version) { + this.version = OptionalInt.of(version); + return this; } + @Override + public INetworkPayloadVersioningBuilder withMinimalVersion(int min) { + this.minimalVersion = OptionalInt.of(min); + return this; + } + + @Override + public INetworkPayloadVersioningBuilder withMaximalVersion(int max) { + this.maximalVersion = OptionalInt.of(max); + return this; + } + + @Override + public INetworkPayloadVersioningBuilder optional() { + this.optional = true; + return this; + } } diff --git a/src/main/java/net/neoforged/neoforge/network/registration/registrar/PlayPayloadHandler.java b/src/main/java/net/neoforged/neoforge/network/registration/registrar/PlayPayloadHandler.java index f79dd617b38..288bc4a790c 100644 --- a/src/main/java/net/neoforged/neoforge/network/registration/registrar/PlayPayloadHandler.java +++ b/src/main/java/net/neoforged/neoforge/network/registration/registrar/PlayPayloadHandler.java @@ -1,11 +1,14 @@ package net.neoforged.neoforge.network.registration.registrar; +import net.minecraft.network.protocol.PacketFlow; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.neoforged.neoforge.network.handling.IPlayPayloadHandler; import net.neoforged.neoforge.network.handling.PlayPayloadContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Optional; + public final class PlayPayloadHandler implements IPlayPayloadHandler { @Nullable @@ -31,6 +34,22 @@ public void handle(PlayPayloadContext context, T payload) { } } + Optional flow() { + if (clientSide == null && serverSide == null) { + return Optional.empty(); + } + + if (clientSide == null) { + return Optional.of(PacketFlow.SERVERBOUND); + } + + if (serverSide == null) { + return Optional.of(PacketFlow.CLIENTBOUND); + } + + return Optional.empty(); + } + public static class Builder { private @Nullable IPlayPayloadHandler clientSide; private @Nullable IPlayPayloadHandler serverSide; diff --git a/src/main/java/net/neoforged/neoforge/network/registration/registrar/PlayRegistration.java b/src/main/java/net/neoforged/neoforge/network/registration/registrar/PlayRegistration.java index 6e20b36a73f..fe2e794c704 100644 --- a/src/main/java/net/neoforged/neoforge/network/registration/registrar/PlayRegistration.java +++ b/src/main/java/net/neoforged/neoforge/network/registration/registrar/PlayRegistration.java @@ -12,7 +12,6 @@ import java.util.OptionalInt; public record PlayRegistration( - Class type, IPayloadReader reader, IPlayPayloadHandler handler, OptionalInt version, @@ -22,9 +21,10 @@ public record PlayRegistration( Optional flow, boolean optional ) implements IPlayPayloadHandler, IPayloadReader { + @SuppressWarnings({"rawtypes", "unchecked"}) @Override public void handle(PlayPayloadContext context, CustomPacketPayload payload) { - handler.handle(context, type.cast(payload)); + ((IPlayPayloadHandler) handler).handle(context, payload); } @Override diff --git a/src/main/java/net/neoforged/neoforge/network/registration/registrar/RegistrationFailedException.java b/src/main/java/net/neoforged/neoforge/network/registration/registrar/RegistrationFailedException.java index bf1319675b6..cd1fa1cf756 100644 --- a/src/main/java/net/neoforged/neoforge/network/registration/registrar/RegistrationFailedException.java +++ b/src/main/java/net/neoforged/neoforge/network/registration/registrar/RegistrationFailedException.java @@ -19,7 +19,6 @@ */ public class RegistrationFailedException extends RuntimeException { - private final Class payloadClass; private final ResourceLocation id; private final String namespace; private final Reason reason; @@ -28,14 +27,12 @@ public class RegistrationFailedException extends RuntimeException { * Creates a new exception with the given parameters. * The reason can not be unknown. * - * @param payloadClass The class of the payload that was being registered. * @param id The id of the payload that was being registered. * @param namespace The namespace the payload was being registered in. * @param reason The reason the registration failed. */ - public RegistrationFailedException(Class payloadClass, ResourceLocation id, String namespace, Reason reason) { - super(reason.format(payloadClass, id, namespace)); - this.payloadClass = payloadClass; + public RegistrationFailedException(ResourceLocation id, String namespace, Reason reason) { + super(reason.format(id, namespace)); this.id = id; this.namespace = namespace; this.reason = reason; @@ -49,28 +46,17 @@ public RegistrationFailedException(Class payloadClass, ResourceLocation id, S * Creates a new exception with the given parameters. * Automatically sets the reason to unknown, and passes the given throwable to the super constructor as reason for the exception. * - * @param payloadClass The class of the payload that was being registered. * @param id The id of the payload that was being registered. * @param namespace The namespace the payload was being registered in. * @param throwable The throwable that caused the registration to fail. */ - public RegistrationFailedException(Class payloadClass, ResourceLocation id, String namespace, Throwable throwable) { - super(Reason.UNKNOWN.format(payloadClass, id, namespace), throwable); - this.payloadClass = payloadClass; + public RegistrationFailedException(ResourceLocation id, String namespace, Throwable throwable) { + super(Reason.UNKNOWN.format(id, namespace), throwable); this.id = id; this.namespace = namespace; reason = Reason.UNKNOWN; } - /** - * The class of the payload that was being registered. - * - * @return The class of the payload that was being registered. - */ - public Class getpayloadClass() { - return payloadClass; - } - /** * The id of the payload that was being registered. * @@ -105,15 +91,15 @@ public enum Reason implements ReasonFormatter { /** * The payload id is already registered. */ - DUPLICATE_ID((payloadClass, id, namespace) -> "Duplicate payload id " + id + " for payload " + payloadClass.getName() + " in namespace " + namespace + "."), + DUPLICATE_ID((id, namespace) -> "Duplicate payload id " + id + " for payload in namespace " + namespace + "."), /** * The payload id is registered in the wrong namespace. */ - INVALID_NAMESPACE((payloadClass, id, namespace) -> "Try registering payload in namespace " + namespace + " for payload " + payloadClass.getName() + " with id " + id + "."), + INVALID_NAMESPACE((id, namespace) -> "Try registering payload in namespace " + namespace + " for payload with id " + id + "."), /** * Some other unknown reason, an exception was thrown downstream. */ - UNKNOWN((payloadClass, id, namespace) -> "General payload registration failure for payload " + payloadClass.getName() + " with id " + id + " in namespace " + namespace + "."); + UNKNOWN((id, namespace) -> "General payload registration failure for payload with id " + id + " in namespace " + namespace + "."); /** * The internal formatter used to format the reason. @@ -128,8 +114,8 @@ public enum Reason implements ReasonFormatter { * {@inheritDoc} */ @Override - public String format(Class payloadClass, ResourceLocation id, String namespace) { - return this.formatter.format(payloadClass, id, namespace); + public String format(ResourceLocation id, String namespace) { + return this.formatter.format(id, namespace); } } @@ -142,11 +128,10 @@ private interface ReasonFormatter { /** * Creates a nice error message for the given parameters. * - * @param payloadClass The class of the payload that was being registered. * @param id The id of the payload that was being registered. * @param namespace The namespace the payload was being registered in. * @return A nice error message for the given parameters. */ - String format(Class payloadClass, ResourceLocation id, String namespace); + String format(ResourceLocation id, String namespace); } }