From 3618914ce91bb3bf156b3031d00b0bc15fa15ad0 Mon Sep 17 00:00:00 2001 From: KennyTV Date: Sat, 29 May 2021 20:53:47 +0200 Subject: [PATCH] Add method to get Protocol by supported versions, some cleanup --- .../api/protocol/ProtocolManager.java | 50 +++++--- .../type/types/minecraft/BaseChunkType.java | 5 +- .../types/minecraft/BaseItemArrayType.java | 5 +- .../type/types/minecraft/BaseItemType.java | 5 +- .../protocol/ProtocolManagerImpl.java | 17 ++- .../protocol/packet/PacketWrapperImpl.java | 107 ++++++++---------- .../protocols/base/BaseProtocol.java | 8 +- 7 files changed, 110 insertions(+), 87 deletions(-) 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 35ef78221..d9cf45098 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 @@ -53,6 +53,28 @@ public interface ProtocolManager { */ @Nullable T getProtocol(Class protocolClass); + /** + * Returns a protocol transforming packets for server version to the given client version. + * + * @param clientVersion client protocol version + * @param serverVersion server protocol version + * @return protocol if present, else null + * @see #getProtocolPath(int, int) to get a full path of Protocols between a larger gap of versions + */ + default @Nullable Protocol getProtocol(ProtocolVersion clientVersion, ProtocolVersion serverVersion) { + return getProtocol(clientVersion.getVersion(), serverVersion.getVersion()); + } + + /** + * Returns a protocol transforming packets for server version to the given client version. + * + * @param clientVersion client protocol version + * @param serverVersion server protocol version + * @return protocol if present, else null + * @see #getProtocolPath(int, int) to get a full path of Protocols between a larger gap of versions + */ + @Nullable Protocol getProtocol(int clientVersion, int serverVersion); + /** * Returns the base protocol handling serverbound handshake packets. * @@ -84,37 +106,37 @@ public interface ProtocolManager { /** * Register a protocol. * - * @param protocol protocol to register - * @param supported supported client versions - * @param output output server version the protocol converts to + * @param protocol protocol to register + * @param clientVersion supported client protocol versions + * @param serverVersion output server protocol version the protocol converts to */ - void registerProtocol(Protocol protocol, ProtocolVersion supported, ProtocolVersion output); + void registerProtocol(Protocol protocol, ProtocolVersion clientVersion, ProtocolVersion serverVersion); /** * Register a protocol. * - * @param protocol protocol to register - * @param supported supported client versions - * @param output output server version the protocol converts to + * @param protocol protocol to register + * @param supportedClientVersion supported client protocol versions + * @param serverVersion output server protocol version the protocol converts to */ - void registerProtocol(Protocol protocol, List supported, int output); + void registerProtocol(Protocol protocol, List supportedClientVersion, int serverVersion); /** * Registers a base protocol. Base Protocols registered later have higher priority. * Only base protocol will always be added to pipeline. * * @param baseProtocol base protocol to register - * @param supportedProtocols versions supported by the base protocol + * @param supportedProtocols protocol versions supported by the base protocol * @throws IllegalArgumentException if the protocol is not a base protocol as given by {@link Protocol#isBaseProtocol()} */ void registerBaseProtocol(Protocol baseProtocol, Range supportedProtocols); /** - * Calculates and returns the protocol path from a client version to server version. + * Calculates and returns the protocol path from a client protocol version to server protocol version. * Returns null if no path could be found or the path length exceeds the value given by {@link #getMaxProtocolPathSize()}. * - * @param clientVersion input client version - * @param serverVersion desired output server version + * @param clientVersion input client protocol version + * @param serverVersion desired output server protocol version * @return path generated, or null if not supported or the length exceeds {@link #getMaxProtocolPathSize()} */ @Nullable List getProtocolPath(int clientVersion, int serverVersion); @@ -135,9 +157,9 @@ public interface ProtocolManager { void setMaxProtocolPathSize(int maxProtocolPathSize); /** - * Returns the versions compatible with the server. + * Returns the protocol versions compatible with the server. * - * @return sorted, immutable set of supported versions + * @return sorted, immutable set of supported protocol versions */ SortedSet getSupportedVersions(); diff --git a/api/src/main/java/com/viaversion/viaversion/api/type/types/minecraft/BaseChunkType.java b/api/src/main/java/com/viaversion/viaversion/api/type/types/minecraft/BaseChunkType.java index 8b34bb0cb..004c8382d 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/type/types/minecraft/BaseChunkType.java +++ b/api/src/main/java/com/viaversion/viaversion/api/type/types/minecraft/BaseChunkType.java @@ -26,11 +26,12 @@ import com.viaversion.viaversion.api.minecraft.chunks.Chunk; import com.viaversion.viaversion.api.type.Type; public abstract class BaseChunkType extends Type { - public BaseChunkType() { + + protected BaseChunkType() { super(Chunk.class); } - public BaseChunkType(String typeName) { + protected BaseChunkType(String typeName) { super(typeName, Chunk.class); } diff --git a/api/src/main/java/com/viaversion/viaversion/api/type/types/minecraft/BaseItemArrayType.java b/api/src/main/java/com/viaversion/viaversion/api/type/types/minecraft/BaseItemArrayType.java index bf6159e62..bfe925921 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/type/types/minecraft/BaseItemArrayType.java +++ b/api/src/main/java/com/viaversion/viaversion/api/type/types/minecraft/BaseItemArrayType.java @@ -26,11 +26,12 @@ import com.viaversion.viaversion.api.minecraft.item.Item; import com.viaversion.viaversion.api.type.Type; public abstract class BaseItemArrayType extends Type { - public BaseItemArrayType() { + + protected BaseItemArrayType() { super(Item[].class); } - public BaseItemArrayType(String typeName) { + protected BaseItemArrayType(String typeName) { super(typeName, Item[].class); } diff --git a/api/src/main/java/com/viaversion/viaversion/api/type/types/minecraft/BaseItemType.java b/api/src/main/java/com/viaversion/viaversion/api/type/types/minecraft/BaseItemType.java index cc5744868..99f7ef867 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/type/types/minecraft/BaseItemType.java +++ b/api/src/main/java/com/viaversion/viaversion/api/type/types/minecraft/BaseItemType.java @@ -26,11 +26,12 @@ import com.viaversion.viaversion.api.minecraft.item.Item; import com.viaversion.viaversion.api.type.Type; public abstract class BaseItemType extends Type { - public BaseItemType() { + + protected BaseItemType() { super(Item.class); } - public BaseItemType(String typeName) { + protected BaseItemType(String typeName) { super(typeName, Item.class); } 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 346cb89ef..0c46ae171 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocol/ProtocolManagerImpl.java +++ b/common/src/main/java/com/viaversion/viaversion/protocol/ProtocolManagerImpl.java @@ -160,12 +160,12 @@ public class ProtocolManagerImpl implements ProtocolManager { } @Override - public void registerProtocol(Protocol protocol, ProtocolVersion supported, ProtocolVersion output) { - registerProtocol(protocol, Collections.singletonList(supported.getVersion()), output.getVersion()); + public void registerProtocol(Protocol protocol, ProtocolVersion clientVersion, ProtocolVersion serverVersion) { + registerProtocol(protocol, Collections.singletonList(clientVersion.getVersion()), serverVersion.getVersion()); } @Override - public void registerProtocol(Protocol protocol, List supported, int output) { + public void registerProtocol(Protocol protocol, List supportedClientVersion, int serverVersion) { // Clear cache as this may make new routes. if (!pathCache.isEmpty()) { pathCache.clear(); @@ -173,9 +173,9 @@ public class ProtocolManagerImpl implements ProtocolManager { protocols.put(protocol.getClass(), protocol); - for (int version : supported) { + for (int version : supportedClientVersion) { Int2ObjectMap protocolMap = registryMap.computeIfAbsent(version, s -> new Int2ObjectOpenHashMap<>(2)); - protocolMap.put(output, protocol); + protocolMap.put(serverVersion, protocol); } if (Via.getPlatform().isPluginEnabled()) { @@ -249,6 +249,7 @@ public class ProtocolManagerImpl implements ProtocolManager { * @return path that has been generated, null if failed */ private @Nullable List getProtocolPath(List current, int clientVersion, int serverVersion) { + //TODO optimize? if (clientVersion == serverVersion) return null; // We're already there if (current.size() > maxProtocolPathSize) return null; // Fail safe, protocol too complicated. @@ -297,6 +298,12 @@ public class ProtocolManagerImpl implements ProtocolManager { return (T) protocols.get(protocolClass); } + @Override + public @Nullable Protocol getProtocol(int clientVersion, int serverVersion) { + Int2ObjectMap map = registryMap.get(clientVersion); + return map != null ? map.get(serverVersion) : null; + } + @Override public Protocol getBaseProtocol(int serverVersion) { for (Pair, Protocol> rangeProtocol : Lists.reverse(baseProtocols)) { diff --git a/common/src/main/java/com/viaversion/viaversion/protocol/packet/PacketWrapperImpl.java b/common/src/main/java/com/viaversion/viaversion/protocol/packet/PacketWrapperImpl.java index 02fa6c57e..5a12da332 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocol/packet/PacketWrapperImpl.java +++ b/common/src/main/java/com/viaversion/viaversion/protocol/packet/PacketWrapperImpl.java @@ -63,12 +63,11 @@ public class PacketWrapperImpl implements PacketWrapper { public T get(Type type, int index) throws Exception { int currentIndex = 0; for (Pair packetValue : packetValues) { - if (packetValue.getKey() == type) { // Ref check - if (currentIndex == index) { - return (T) packetValue.getValue(); - } - currentIndex++; + if (packetValue.getKey() != type) continue; + if (currentIndex == index) { + return (T) packetValue.getValue(); } + currentIndex++; } Exception e = new ArrayIndexOutOfBoundsException("Could not find type " + type.getTypeName() + " at " + index); @@ -79,12 +78,11 @@ public class PacketWrapperImpl implements PacketWrapper { public boolean is(Type type, int index) { int currentIndex = 0; for (Pair packetValue : packetValues) { - if (packetValue.getKey() == type) { // Ref check - if (currentIndex == index) { - return true; - } - currentIndex++; + if (packetValue.getKey() != type) continue; + if (currentIndex == index) { + return true; } + currentIndex++; } return false; } @@ -93,12 +91,11 @@ public class PacketWrapperImpl implements PacketWrapper { public boolean isReadable(Type type, int index) { int currentIndex = 0; for (Pair packetValue : readableObjects) { - if (packetValue.getKey().getBaseClass() == type.getBaseClass()) { // Ref check - if (currentIndex == index) { - return true; - } - currentIndex++; + if (packetValue.getKey().getBaseClass() != type.getBaseClass()) continue; + if (currentIndex == index) { + return true; } + currentIndex++; } return false; } @@ -108,13 +105,12 @@ public class PacketWrapperImpl implements PacketWrapper { public void set(Type type, int index, T value) throws Exception { int currentIndex = 0; for (Pair packetValue : packetValues) { - if (packetValue.getKey() == type) { // Ref check - if (currentIndex == index) { - packetValue.setValue(value); - return; - } - currentIndex++; + if (packetValue.getKey() != type) continue; + if (currentIndex == index) { + packetValue.setValue(attemptTransform(type, value)); + return; } + currentIndex++; } Exception e = new ArrayIndexOutOfBoundsException("Could not find type " + type.getTypeName() + " at " + index); throw new InformativeException(e).set("Type", type.getTypeName()).set("Index", index).set("Packet ID", getId()); @@ -131,37 +127,44 @@ public class PacketWrapperImpl implements PacketWrapper { } catch (Exception e) { throw new InformativeException(e).set("Type", type.getTypeName()).set("Packet ID", getId()).set("Data", packetValues); } + } + + Pair read = readableObjects.poll(); + Type rtype = read.getKey(); + if (rtype == type + || (type.getBaseClass() == rtype.getBaseClass() + && type.getOutputClass() == rtype.getOutputClass())) { + return (T) read.getValue(); + } else if (rtype == Type.NOTHING) { + return read(type); // retry } else { - Pair read = readableObjects.poll(); - Type rtype = read.getKey(); - if (rtype.equals(type) - || (type.getBaseClass().equals(rtype.getBaseClass()) - && type.getOutputClass().equals(rtype.getOutputClass()))) { - return (T) read.getValue(); - } else { - if (rtype == Type.NOTHING) { - return read(type); // retry - } else { - Exception e = new IOException("Unable to read type " + type.getTypeName() + ", found " + read.getKey().getTypeName()); - throw new InformativeException(e).set("Type", type.getTypeName()).set("Packet ID", getId()).set("Data", packetValues); - } - } + Exception e = new IOException("Unable to read type " + type.getTypeName() + ", found " + read.getKey().getTypeName()); + throw new InformativeException(e).set("Type", type.getTypeName()).set("Packet ID", getId()).set("Data", packetValues); } } @Override public void write(Type type, T value) { - if (value != null) { - if (!type.getOutputClass().isAssignableFrom(value.getClass())) { - // attempt conversion - if (type instanceof TypeConverter) { - value = (T) ((TypeConverter) type).from(value); - } else { - Via.getPlatform().getLogger().warning("Possible type mismatch: " + value.getClass().getName() + " -> " + type.getOutputClass()); - } + packetValues.add(new Pair<>(type, attemptTransform(type, value))); + } + + /** + * Returns the value if already matching, else the converted value or possibly unmatched value. + * + * @param expectedType expected type + * @param value value + * @return value if already matching, else the converted value or possibly unmatched value + */ + private @Nullable Object attemptTransform(Type expectedType, @Nullable Object value) { + if (value != null && !expectedType.getOutputClass().isAssignableFrom(value.getClass())) { + // Attempt conversion + if (expectedType instanceof TypeConverter) { + return ((TypeConverter) expectedType).from(value); } + + Via.getPlatform().getLogger().warning("Possible type mismatch: " + value.getClass().getName() + " -> " + expectedType.getOutputClass()); } - packetValues.add(new Pair<>(type, value)); + return value; } @Override @@ -195,18 +198,7 @@ public class PacketWrapperImpl implements PacketWrapper { int index = 0; for (Pair packetValue : packetValues) { try { - Object value = packetValue.getValue(); - if (value != null) { - if (!packetValue.getKey().getOutputClass().isAssignableFrom(value.getClass())) { - // attempt conversion - if (packetValue.getKey() instanceof TypeConverter) { - value = ((TypeConverter) packetValue.getKey()).from(value); - } else { - Via.getPlatform().getLogger().warning("Possible type mismatch: " + value.getClass().getName() + " -> " + packetValue.getKey().getOutputClass()); - } - } - } - packetValue.getKey().write(buffer, value); + packetValue.getKey().write(buffer, packetValue.getValue()); } catch (Exception e) { throw new InformativeException(e).set("Index", index).set("Type", packetValue.getKey().getTypeName()).set("Packet ID", getId()).set("Data", packetValues); } @@ -428,8 +420,7 @@ public class PacketWrapperImpl implements PacketWrapper { this.id = id; } - @Nullable - public ByteBuf getInputBuffer() { + public @Nullable ByteBuf getInputBuffer() { return inputBuffer; } diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/base/BaseProtocol.java b/common/src/main/java/com/viaversion/viaversion/protocols/base/BaseProtocol.java index ca6bbee7b..619cfaf91 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/base/BaseProtocol.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/base/BaseProtocol.java @@ -55,13 +55,14 @@ public class BaseProtocol extends AbstractSimpleProtocol { ProtocolInfo info = wrapper.user().getProtocolInfo(); info.setProtocolVersion(protocolVersion); // Ensure the server has a version provider - if (Via.getManager().getProviders().get(VersionProvider.class) == null) { + VersionProvider versionProvider = Via.getManager().getProviders().get(VersionProvider.class); + if (versionProvider == null) { wrapper.user().setActive(false); return; } // Choose the pipe - int serverProtocol = Via.getManager().getProviders().get(VersionProvider.class).getClosestServerProtocol(wrapper.user()); + int serverProtocol = versionProvider.getClosestServerProtocol(wrapper.user()); info.setServerProtocolVersion(serverProtocol); List protocolPath = null; @@ -94,8 +95,7 @@ public class BaseProtocol extends AbstractSimpleProtocol { // Change state if (state == 1) { info.setState(State.STATUS); - } - if (state == 2) { + } else if (state == 2) { info.setState(State.LOGIN); } });