From 2094397bca5cbf46f12ba59cc769a211edeb3053 Mon Sep 17 00:00:00 2001 From: kennytv Date: Sat, 31 Jul 2021 23:17:52 +0200 Subject: [PATCH] Allow bypassing of packet type restriction in Protocol, amend packet creator --- .../api/protocol/AbstractProtocol.java | 38 +++++------ .../api/protocol/ProtocolManager.java | 32 +++++++--- .../api/protocol/packet/PacketWrapper.java | 9 ++- ...r.java => VersionedPacketTransformer.java} | 48 ++++++++++++-- .../protocol/ProtocolManagerImpl.java | 14 ++-- ...va => VersionedPacketTransformerImpl.java} | 64 ++++++++++++++++--- 6 files changed, 155 insertions(+), 50 deletions(-) rename api/src/main/java/com/viaversion/viaversion/api/protocol/packet/{VersionedPacketCreator.java => VersionedPacketTransformer.java} (71%) rename common/src/main/java/com/viaversion/viaversion/protocol/packet/{VersionedPacketCreatorImpl.java => VersionedPacketTransformerImpl.java} (67%) diff --git a/api/src/main/java/com/viaversion/viaversion/api/protocol/AbstractProtocol.java b/api/src/main/java/com/viaversion/viaversion/api/protocol/AbstractProtocol.java index c9fa40da8..5f533240b 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/protocol/AbstractProtocol.java +++ b/api/src/main/java/com/viaversion/viaversion/api/protocol/AbstractProtocol.java @@ -87,14 +87,14 @@ public abstract class AbstractProtocol newClientboundPackets = new HashMap<>(newConstants.length); - for (ClientboundPacketType newConstant : newConstants) { + C2[] newConstants = newClientboundPacketEnum.getEnumConstants(); + Map newClientboundPackets = new HashMap<>(newConstants.length); + for (C2 newConstant : newConstants) { newClientboundPackets.put(newConstant.getName(), newConstant); } for (C1 packet : oldClientboundPacketEnum.getEnumConstants()) { - C2 mappedPacket = (C2) newClientboundPackets.get(packet.getName()); + C2 mappedPacket = newClientboundPackets.get(packet.getName()); if (mappedPacket == null) { // Packet doesn't exist on new client Preconditions.checkArgument(hasRegisteredClientbound(packet), @@ -109,14 +109,14 @@ public abstract class AbstractProtocol oldServerboundConstants = new HashMap<>(oldConstants.length); - for (ServerboundPacketType oldConstant : oldConstants) { + S1[] oldConstants = oldServerboundPacketEnum.getEnumConstants(); + Map oldServerboundConstants = new HashMap<>(oldConstants.length); + for (S1 oldConstant : oldConstants) { oldServerboundConstants.put(oldConstant.getName(), oldConstant); } for (S2 packet : newServerboundPacketEnum.getEnumConstants()) { - S1 mappedPacket = (S1) oldServerboundConstants.get(packet.getName()); + S1 mappedPacket = oldServerboundConstants.get(packet.getName()); if (mappedPacket == null) { // Packet doesn't exist on old server Preconditions.checkArgument(hasRegisteredServerbound(packet), @@ -200,13 +200,13 @@ public abstract class AbstractProtocol en.getName().equals(packetType.getName())).findAny().orElse(null); Preconditions.checkNotNull(mappedPacket, "Packet type " + packetType + " in " + packetType.getClass().getSimpleName() + " could not be automatically mapped!"); - registerClientbound(packetType, (C2) mappedPacket, packetRemapper); + registerClientbound(packetType, mappedPacket, packetRemapper); } @Override @@ -226,13 +226,13 @@ public abstract class AbstractProtocol en.getName().equals(packetType.getName())).findAny().orElse(null); Preconditions.checkNotNull(mappedPacket, "Packet type " + packetType + " in " + packetType.getClass().getSimpleName() + " could not be automatically mapped!"); - registerServerbound(packetType, (S1) mappedPacket, packetRemapper); + registerServerbound(packetType, mappedPacket, packetRemapper); } @Override @@ -253,8 +253,8 @@ public abstract class AbstractProtocol packetMap, PacketType packetType, @Nullable PacketType mappedPacketType, Class unmappedPacketEnum, Class mappedPacketEnum, @Nullable PacketRemapper remapper, boolean override) { - checkPacketType(packetType, packetType.getClass() == unmappedPacketEnum); - checkPacketType(mappedPacketType, mappedPacketType == null || mappedPacketType.getClass() == mappedPacketEnum); + checkPacketType(packetType, unmappedPacketEnum == null || packetType.getClass() == unmappedPacketEnum); + checkPacketType(mappedPacketType, mappedPacketType == null || mappedPacketEnum == null || mappedPacketType.getClass() == mappedPacketEnum); Preconditions.checkArgument(mappedPacketType == null || packetType.state() == mappedPacketType.state(), "Packet type state does not match mapped packet type state"); ProtocolPacket protocolPacket = new ProtocolPacket(packetType.state(), packetType, mappedPacketType, remapper); @@ -277,8 +277,8 @@ public abstract class AbstractProtocol packetMap = (direction == Direction.CLIENTBOUND ? this.clientbound : serverbound); + Map packetMap = direction == Direction.CLIENTBOUND ? clientbound : serverbound; ProtocolPacket protocolPacket = packetMap.get(statePacket); if (protocolPacket == null) { return; diff --git a/api/src/main/java/com/viaversion/viaversion/api/protocol/ProtocolManager.java b/api/src/main/java/com/viaversion/viaversion/api/protocol/ProtocolManager.java index 6ae9757fa..be8a95b1f 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/protocol/ProtocolManager.java +++ b/api/src/main/java/com/viaversion/viaversion/api/protocol/ProtocolManager.java @@ -28,7 +28,7 @@ import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType; import com.viaversion.viaversion.api.protocol.packet.PacketType; import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType; -import com.viaversion.viaversion.api.protocol.packet.VersionedPacketCreator; +import com.viaversion.viaversion.api.protocol.packet.VersionedPacketTransformer; import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; import com.viaversion.viaversion.api.protocol.version.ServerProtocolVersion; import io.netty.buffer.ByteBuf; @@ -147,18 +147,34 @@ public interface ProtocolManager { @Nullable List getProtocolPath(int clientVersion, int serverVersion); /** - * Returns a versioned packet creator to send packets from a given base version to any client version supported by Via. + * Returns a versioned packet transformer to transform and send packets from a given base version to any client version supported by Via. * The used packet types have to match the given protocol version. + *

+ * It is important the correct packet type classes are passed. The ViaVersion given packet type enums + * are found in the common module. Examples for correct invocations are: + *

+     * createPacketTransformer(ProtocolVersion.v1_17_1, ClientboundPackets1_17_1.class, ServerboundPackets1_17.class);
+     * createPacketTransformer(ProtocolVersion.v1_12_2, ClientboundPackets1_12_1.class, ServerboundPackets1_12_1.class);
+     * createPacketTransformer(ProtocolVersion.v1_8, ClientboundPackets1_8.class, ServerboundPackets1_8.class);
+     * 
+ * If only clientbound or serverbound packets are used, the other class can be passed as null, see: + *
+     * VersionedPacketTransformer<?, ServerboundHandshakePackets> creator
+     *     = createPacketTransformer(ProtocolVersion.v1_17_1, null, ServerboundHandshakePackets.class);
+     * 
* * @param inputVersion input protocol version - * @param clientboundPacketsClass clientbound packets class - * @param serverboundPacketsClass serverbound packets class - * @return versioned packet creator + * @param clientboundPacketsClass clientbound packets class, or null if no clientbound packets will be sent or transformed with this + * @param serverboundPacketsClass serverbound packets class, or null if no serverbound packets will be sent or transformed with this + * @return versioned packet transformer to transform and send packets from a given protocol version * @throws IllegalArgumentException if either of the packet classes are the base {@link ClientboundPacketType} or {@link ServerboundPacketType} interfaces + * @throws IllegalArgumentException if both packet classes are null */ - VersionedPacketCreator createVersionedPacketCreator(ProtocolVersion inputVersion, - Class clientboundPacketsClass, - Class serverboundPacketsClass); + VersionedPacketTransformer createPacketTransformer(ProtocolVersion inputVersion, + @Nullable Class clientboundPacketsClass, + @Nullable Class serverboundPacketsClass); /** * Returns whether protocol path calculation expects the path to come closer to the expected version with each entry, true by default. diff --git a/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/PacketWrapper.java b/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/PacketWrapper.java index c042ffcda..00bfa92b4 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/PacketWrapper.java +++ b/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/PacketWrapper.java @@ -219,8 +219,10 @@ public interface PacketWrapper { */ ChannelFuture sendFuture(Class packetProtocol) throws Exception; - - @Deprecated + /** + * @deprecated misleading; use {@link #sendRaw()}. This method will be removed in 5.0.0 + */ + @Deprecated/*(forRemoval = true)*/ default void send() throws Exception { sendRaw(); } @@ -328,8 +330,9 @@ public interface PacketWrapper { * (Ensure the ID is suitable for viaversion) * * @throws Exception If it failed to write + * @deprecated misleading; use {@link #sendToServerRaw()}. This method will be removed in 5.0.0 */ - @Deprecated + @Deprecated/*(forRemoval = true)*/ default void sendToServer() throws Exception { sendToServerRaw(); } diff --git a/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/VersionedPacketCreator.java b/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/VersionedPacketTransformer.java similarity index 71% rename from api/src/main/java/com/viaversion/viaversion/api/protocol/packet/VersionedPacketCreator.java rename to api/src/main/java/com/viaversion/viaversion/api/protocol/packet/VersionedPacketTransformer.java index f4ef4aef4..1624bf9f5 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/VersionedPacketCreator.java +++ b/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/VersionedPacketTransformer.java @@ -23,12 +23,18 @@ package com.viaversion.viaversion.api.protocol.packet; import com.viaversion.viaversion.api.connection.ProtocolInfo; +import com.viaversion.viaversion.api.connection.UserConnection; import org.checkerframework.checker.nullness.qual.Nullable; +import java.util.function.Consumer; + /** * Utility to send packets from a given base version to or from any client version supported by Via. + * + * @param clientbound packet type + * @param serverbound packet type */ -public interface VersionedPacketCreator { +public interface VersionedPacketTransformer { /** * Sends a packet to the user or server, depending on the packet type given by {@link PacketWrapper#getPacketType()}. @@ -38,33 +44,63 @@ public interface VersionedPacketCreator { * @throws IllegalArgumentException if the packet type is not of the expected clientbound or serverbound packets class * @throws IllegalArgumentException if {@link PacketWrapper#user()} returns null * @throws RuntimeException if no path from the input version to the required client version exists - * @throws Exception if an error occurred while constructing the packet or sending it + * @throws Exception if an error occurred while transforming or sending the packet */ boolean send(PacketWrapper packet) throws Exception; + /** + * @see #send(PacketWrapper) + */ + boolean send(UserConnection connection, C packetType, Consumer packetWriter) throws Exception; + + /** + * @see #send(PacketWrapper) + */ + boolean send(UserConnection connection, S packetType, Consumer packetWriter) throws Exception; + /** * Sends a packet to the user or server, depending on the packet type given by {@link PacketWrapper#getPacketType()}, submitted to the netty event loop. * Returns false if the packet has been cancelled at some point, but does not indicate whether a replacement has been constructed. * * @param packet packet wrapper * @return whether this packet specifically has been sent, false if cancelled - * @throws IllegalArgumentException if the packet type is not of the expected clientbound packets class + * @throws IllegalArgumentException if the packet type is not of the expected clientbound or serverbound packets class * @throws IllegalArgumentException if {@link PacketWrapper#user()} returns null * @throws RuntimeException if no path from the input version to the required client version exists - * @throws Exception if an error occurred while constructing the packet or sending it + * @throws Exception if an error occurred while transforming or sending the packet */ boolean scheduleSend(PacketWrapper packet) throws Exception; + /** + * @see #scheduleSend(PacketWrapper) + */ + boolean scheduleSend(UserConnection connection, C packetType, Consumer packetWriter) throws Exception; + + /** + * @see #scheduleSend(PacketWrapper) + */ + boolean scheduleSend(UserConnection connection, S packetType, Consumer packetWriter) throws Exception; + /** * Transforms a packet to the protocol version of the given connection or server, or null if cancelled at some point. * The target version is given by {@link ProtocolInfo#getProtocolVersion()} or {@link ProtocolInfo#getServerProtocolVersion()}. * * @param packet packet wrapper * @return created and transformed packet wrapper, or null if cancelled at some point - * @throws IllegalArgumentException if the packet type is not of the expected clientbound packets class + * @throws IllegalArgumentException if the packet type is not of the expected clientbound or serverbound packets class * @throws IllegalArgumentException if {@link PacketWrapper#user()} returns null * @throws RuntimeException if no path from the input version to the required client version exists - * @throws Exception if an error occurred while constructing the packet + * @throws Exception if an error occurred while transforming the packet */ @Nullable PacketWrapper transform(PacketWrapper packet) throws Exception; + + /** + * @see #transform(PacketWrapper) + */ + @Nullable PacketWrapper transform(UserConnection connection, C packetType, Consumer packetWriter) throws Exception; + + /** + * @see #transform(PacketWrapper) + */ + @Nullable PacketWrapper transform(UserConnection connection, S packetType, Consumer packetWriter) throws Exception; } diff --git a/common/src/main/java/com/viaversion/viaversion/protocol/ProtocolManagerImpl.java b/common/src/main/java/com/viaversion/viaversion/protocol/ProtocolManagerImpl.java index 7cb84d1f0..53e8bea45 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocol/ProtocolManagerImpl.java +++ b/common/src/main/java/com/viaversion/viaversion/protocol/ProtocolManagerImpl.java @@ -32,11 +32,11 @@ import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType; import com.viaversion.viaversion.api.protocol.packet.PacketType; import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType; -import com.viaversion.viaversion.api.protocol.packet.VersionedPacketCreator; +import com.viaversion.viaversion.api.protocol.packet.VersionedPacketTransformer; import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; import com.viaversion.viaversion.api.protocol.version.ServerProtocolVersion; import com.viaversion.viaversion.protocol.packet.PacketWrapperImpl; -import com.viaversion.viaversion.protocol.packet.VersionedPacketCreatorImpl; +import com.viaversion.viaversion.protocol.packet.VersionedPacketTransformerImpl; import com.viaversion.viaversion.protocols.base.BaseProtocol; import com.viaversion.viaversion.protocols.base.BaseProtocol1_16; import com.viaversion.viaversion.protocols.base.BaseProtocol1_7; @@ -267,11 +267,13 @@ public class ProtocolManagerImpl implements ProtocolManager { } @Override - public VersionedPacketCreator createVersionedPacketCreator(ProtocolVersion inputVersion, - Class clientboundPacketsClass, - Class serverboundPacketsClass) { + public VersionedPacketTransformer createPacketTransformer(ProtocolVersion inputVersion, + @Nullable Class clientboundPacketsClass, + @Nullable Class serverboundPacketsClass) { Preconditions.checkArgument(clientboundPacketsClass != ClientboundPacketType.class && serverboundPacketsClass != ServerboundPacketType.class); - return new VersionedPacketCreatorImpl(inputVersion, clientboundPacketsClass, serverboundPacketsClass); + return new VersionedPacketTransformerImpl<>(inputVersion, clientboundPacketsClass, serverboundPacketsClass); } /** diff --git a/common/src/main/java/com/viaversion/viaversion/protocol/packet/VersionedPacketCreatorImpl.java b/common/src/main/java/com/viaversion/viaversion/protocol/packet/VersionedPacketTransformerImpl.java similarity index 67% rename from common/src/main/java/com/viaversion/viaversion/protocol/packet/VersionedPacketCreatorImpl.java rename to common/src/main/java/com/viaversion/viaversion/protocol/packet/VersionedPacketTransformerImpl.java index 1a69b28f7..c7e7cfdf0 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocol/packet/VersionedPacketCreatorImpl.java +++ b/common/src/main/java/com/viaversion/viaversion/protocol/packet/VersionedPacketTransformerImpl.java @@ -28,24 +28,24 @@ import com.viaversion.viaversion.api.protocol.packet.PacketType; import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType; import com.viaversion.viaversion.api.protocol.packet.State; -import com.viaversion.viaversion.api.protocol.packet.VersionedPacketCreator; +import com.viaversion.viaversion.api.protocol.packet.VersionedPacketTransformer; import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.ArrayList; import java.util.List; +import java.util.function.Consumer; -public class VersionedPacketCreatorImpl implements VersionedPacketCreator { +public class VersionedPacketTransformerImpl implements VersionedPacketTransformer { private final int inputProtocolVersion; - private final Class clientboundPacketsClass; - private final Class serverboundPacketsClass; + private final Class clientboundPacketsClass; + private final Class serverboundPacketsClass; - public VersionedPacketCreatorImpl(ProtocolVersion inputVersion, - Class clientboundPacketsClass, Class serverboundPacketsClass) { + public VersionedPacketTransformerImpl(ProtocolVersion inputVersion, @Nullable Class clientboundPacketsClass, @Nullable Class serverboundPacketsClass) { Preconditions.checkNotNull(inputVersion); - Preconditions.checkNotNull(clientboundPacketsClass); - Preconditions.checkNotNull(serverboundPacketsClass); + Preconditions.checkArgument(clientboundPacketsClass != null || serverboundPacketsClass != null, + "Either the clientbound or serverbound packets class has to be non-null"); this.inputProtocolVersion = inputVersion.getVersion(); this.clientboundPacketsClass = clientboundPacketsClass; this.serverboundPacketsClass = serverboundPacketsClass; @@ -57,12 +57,32 @@ public class VersionedPacketCreatorImpl implements VersionedPacketCreator { return transformAndSendPacket(packet, true); } + @Override + public boolean send(UserConnection connection, C packetType, Consumer packetWriter) throws Exception { + return createAndSend(connection, packetType, packetWriter); + } + + @Override + public boolean send(UserConnection connection, S packetType, Consumer packetWriter) throws Exception { + return createAndSend(connection, packetType, packetWriter); + } + @Override public boolean scheduleSend(PacketWrapper packet) throws Exception { validatePacket(packet); return transformAndSendPacket(packet, false); } + @Override + public boolean scheduleSend(UserConnection connection, C packetType, Consumer packetWriter) throws Exception { + return scheduleCreateAndSend(connection, packetType, packetWriter); + } + + @Override + public boolean scheduleSend(UserConnection connection, S packetType, Consumer packetWriter) throws Exception { + return scheduleCreateAndSend(connection, packetType, packetWriter); + } + @Override public @Nullable PacketWrapper transform(PacketWrapper packet) throws Exception { validatePacket(packet); @@ -70,6 +90,16 @@ public class VersionedPacketCreatorImpl implements VersionedPacketCreator { return packet.isCancelled() ? null : packet; } + @Override + public @Nullable PacketWrapper transform(UserConnection connection, C packetType, Consumer packetWriter) throws Exception { + return createAndTransform(connection, packetType, packetWriter); + } + + @Override + public @Nullable PacketWrapper transform(UserConnection connection, S packetType, Consumer packetWriter) throws Exception { + return createAndTransform(connection, packetType, packetWriter); + } + private void validatePacket(PacketWrapper packet) { if (packet.user() == null) { throw new IllegalArgumentException("PacketWrapper does not have a targetted UserConnection"); @@ -140,4 +170,22 @@ public class VersionedPacketCreatorImpl implements VersionedPacketCreator { } } } + + private boolean createAndSend(UserConnection connection, PacketType packetType, Consumer packetWriter) throws Exception { + PacketWrapper packet = PacketWrapper.create(packetType, connection); + packetWriter.accept(packet); + return send(packet); + } + + private boolean scheduleCreateAndSend(UserConnection connection, PacketType packetType, Consumer packetWriter) throws Exception { + PacketWrapper packet = PacketWrapper.create(packetType, connection); + packetWriter.accept(packet); + return scheduleSend(packet); + } + + private @Nullable PacketWrapper createAndTransform(UserConnection connection, PacketType packetType, Consumer packetWriter) throws Exception { + PacketWrapper packet = PacketWrapper.create(packetType, connection); + packetWriter.accept(packet); + return transform(packet); + } }