From 1f5b0e1e03dae625a0982a17d74fad0d04ebb047 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Thu, 5 Nov 2020 17:07:49 -0500 Subject: [PATCH 01/14] Fix a few minor issues with the Java 11 compressor --- .../natives/compression/Java11VelocityCompressor.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/native/src/main/java/com/velocitypowered/natives/compression/Java11VelocityCompressor.java b/native/src/main/java/com/velocitypowered/natives/compression/Java11VelocityCompressor.java index 18397fee7..685152d07 100644 --- a/native/src/main/java/com/velocitypowered/natives/compression/Java11VelocityCompressor.java +++ b/native/src/main/java/com/velocitypowered/natives/compression/Java11VelocityCompressor.java @@ -63,7 +63,7 @@ public class Java11VelocityCompressor implements VelocityCompressor { checkArgument(destination.nioBufferCount() == 1, "destination has multiple backing buffers"); try { - int origIdx = source.readerIndex(); + final int origIdx = source.readerIndex(); INFLATE_SET_INPUT.invokeExact(inflater, source.nioBuffer()); while (!inflater.finished() && inflater.getBytesRead() < source.readableBytes()) { @@ -75,10 +75,10 @@ public class Java11VelocityCompressor implements VelocityCompressor { ByteBuffer destNioBuf = destination.nioBuffer(destination.writerIndex(), destination.writableBytes()); int produced = (int) INFLATE_CALL.invokeExact(inflater, destNioBuf); - source.readerIndex(origIdx + inflater.getTotalIn()); destination.writerIndex(destination.writerIndex() + produced); } + source.readerIndex(origIdx + inflater.getTotalIn()); inflater.reset(); } catch (Throwable e) { if (e instanceof DataFormatException) { @@ -97,7 +97,7 @@ public class Java11VelocityCompressor implements VelocityCompressor { checkArgument(destination.nioBufferCount() == 1, "destination has multiple backing buffers"); try { - int origIdx = source.readerIndex(); + final int origIdx = source.readerIndex(); DEFLATE_SET_INPUT.invokeExact(deflater, source.nioBuffer()); deflater.finish(); @@ -109,10 +109,10 @@ public class Java11VelocityCompressor implements VelocityCompressor { ByteBuffer destNioBuf = destination.nioBuffer(destination.writerIndex(), destination.writableBytes()); int produced = (int) DEFLATE_CALL.invokeExact(deflater, destNioBuf); - source.readerIndex(origIdx + deflater.getTotalIn()); destination.writerIndex(destination.writerIndex() + produced); } + source.readerIndex(origIdx + deflater.getTotalIn()); deflater.reset(); } catch (Throwable e) { if (e instanceof DataFormatException) { From 91b295ead5f22364cd50e6046effccd41ad21d29 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Thu, 5 Nov 2020 17:22:19 -0500 Subject: [PATCH 02/14] Further improve the inflate overflow checks in the Java 11 compressor native This brings the Java compressor in line with our libdeflate one. Backport this from Velocity 2.0.0. --- .../natives/compression/Java11VelocityCompressor.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/native/src/main/java/com/velocitypowered/natives/compression/Java11VelocityCompressor.java b/native/src/main/java/com/velocitypowered/natives/compression/Java11VelocityCompressor.java index 685152d07..845c3adcd 100644 --- a/native/src/main/java/com/velocitypowered/natives/compression/Java11VelocityCompressor.java +++ b/native/src/main/java/com/velocitypowered/natives/compression/Java11VelocityCompressor.java @@ -66,7 +66,7 @@ public class Java11VelocityCompressor implements VelocityCompressor { final int origIdx = source.readerIndex(); INFLATE_SET_INPUT.invokeExact(inflater, source.nioBuffer()); - while (!inflater.finished() && inflater.getBytesRead() < source.readableBytes()) { + while (!inflater.finished() && inflater.getBytesWritten() < uncompressedSize) { if (!destination.isWritable()) { ensureMaxSize(destination, uncompressedSize); destination.ensureWritable(ZLIB_BUFFER_SIZE); @@ -78,13 +78,18 @@ public class Java11VelocityCompressor implements VelocityCompressor { destination.writerIndex(destination.writerIndex() + produced); } + if (inflater.getBytesWritten() != uncompressedSize) { + throw new DataFormatException("Did not write the exact expected number of" + + " uncompressed bytes, expected " + uncompressedSize); + } source.readerIndex(origIdx + inflater.getTotalIn()); - inflater.reset(); } catch (Throwable e) { if (e instanceof DataFormatException) { throw (DataFormatException) e; } throw new RuntimeException(e); + } finally { + inflater.reset(); } } From cc89a2a1e5a4ccd72d0848ca6c31469f044d8332 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Thu, 5 Nov 2020 20:04:31 -0500 Subject: [PATCH 03/14] We don't need to retain/release the mod list buffer in readModList --- .../forge/legacy/LegacyForgeUtil.java | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeUtil.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeUtil.java index 8d2c9d410..e43847ebc 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeUtil.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeUtil.java @@ -39,31 +39,25 @@ class LegacyForgeUtil { */ static List readModList(PluginMessage message) { Preconditions.checkNotNull(message, "message"); - Preconditions - .checkArgument(message.getChannel().equals(FORGE_LEGACY_HANDSHAKE_CHANNEL), + Preconditions.checkArgument(message.getChannel().equals(FORGE_LEGACY_HANDSHAKE_CHANNEL), "message is not a FML HS plugin message"); - ByteBuf byteBuf = message.content().retainedSlice(); - try { - byte discriminator = byteBuf.readByte(); + ByteBuf contents = message.content().slice(); + byte discriminator = contents.readByte(); + if (discriminator == MOD_LIST_DISCRIMINATOR) { + ImmutableList.Builder mods = ImmutableList.builder(); + int modCount = ProtocolUtils.readVarInt(contents); - if (discriminator == MOD_LIST_DISCRIMINATOR) { - ImmutableList.Builder mods = ImmutableList.builder(); - int modCount = ProtocolUtils.readVarInt(byteBuf); - - for (int index = 0; index < modCount; index++) { - String id = ProtocolUtils.readString(byteBuf); - String version = ProtocolUtils.readString(byteBuf); - mods.add(new ModInfo.Mod(id, version)); - } - - return mods.build(); + for (int index = 0; index < modCount; index++) { + String id = ProtocolUtils.readString(contents); + String version = ProtocolUtils.readString(contents); + mods.add(new ModInfo.Mod(id, version)); } - return ImmutableList.of(); - } finally { - byteBuf.release(); + return mods.build(); } + + return ImmutableList.of(); } /** From fb888c3b8aaa7863625f9bdb950ed86fa9166a58 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Fri, 6 Nov 2020 09:38:26 -0500 Subject: [PATCH 04/14] Store players in VelocityRegisteredServer by UUID instead. Fixes an issue where players would be repeated in /glist and the like. --- .../proxy/server/VelocityRegisteredServer.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/server/VelocityRegisteredServer.java b/proxy/src/main/java/com/velocitypowered/proxy/server/VelocityRegisteredServer.java index bec7dab41..5987311e1 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/server/VelocityRegisteredServer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/server/VelocityRegisteredServer.java @@ -32,7 +32,8 @@ import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoop; import io.netty.handler.timeout.ReadTimeoutHandler; import java.util.Collection; -import java.util.Set; +import java.util.Map; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -45,7 +46,7 @@ public class VelocityRegisteredServer implements RegisteredServer, ForwardingAud private final @Nullable VelocityServer server; private final ServerInfo serverInfo; - private final Set players = ConcurrentHashMap.newKeySet(); + private final Map players = new ConcurrentHashMap<>(); public VelocityRegisteredServer(@Nullable VelocityServer server, ServerInfo serverInfo) { this.server = server; @@ -59,7 +60,7 @@ public class VelocityRegisteredServer implements RegisteredServer, ForwardingAud @Override public Collection getPlayersConnected() { - return ImmutableList.copyOf(players); + return ImmutableList.copyOf(players.values()); } @Override @@ -111,11 +112,11 @@ public class VelocityRegisteredServer implements RegisteredServer, ForwardingAud } public void addPlayer(ConnectedPlayer player) { - players.add(player); + players.put(player.getUniqueId(), player); } public void removePlayer(ConnectedPlayer player) { - players.remove(player); + players.remove(player.getUniqueId(), player); } @Override @@ -130,7 +131,7 @@ public class VelocityRegisteredServer implements RegisteredServer, ForwardingAud * @return whether or not the message was sent */ public boolean sendPluginMessage(ChannelIdentifier identifier, ByteBuf data) { - for (ConnectedPlayer player : players) { + for (ConnectedPlayer player : players.values()) { VelocityServerConnection connection = player.getConnectedServer(); if (connection != null && connection.getServerInfo().equals(serverInfo)) { return connection.sendPluginMessage(identifier, data); From 89e1a074483f6f5d90733aa17a86ce54c5829d2f Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Fri, 6 Nov 2020 18:52:00 -0500 Subject: [PATCH 05/14] Try and explicitly specify Java 8 in the modules. --- api/build.gradle | 5 +++++ build.gradle | 5 ----- native/build.gradle | 5 +++++ proxy/build.gradle | 5 +++++ 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/api/build.gradle b/api/build.gradle index ddbdbe951..7eca5c59d 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -8,6 +8,11 @@ apply from: '../gradle/checkstyle.gradle' apply from: '../gradle/publish.gradle' apply plugin: 'com.github.johnrengelman.shadow' +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + sourceSets { ap { compileClasspath += main.compileClasspath + main.output diff --git a/build.gradle b/build.gradle index 06f791981..f3572eff8 100644 --- a/build.gradle +++ b/build.gradle @@ -43,11 +43,6 @@ allprojects { } } - java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - repositories { mavenLocal() mavenCentral() diff --git a/native/build.gradle b/native/build.gradle index ed7cf0aa3..0a348523f 100644 --- a/native/build.gradle +++ b/native/build.gradle @@ -7,6 +7,11 @@ plugins { apply from: '../gradle/checkstyle.gradle' apply from: '../gradle/publish.gradle' +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + dependencies { implementation "com.google.guava:guava:${guavaVersion}" implementation "io.netty:netty-handler:${nettyVersion}" diff --git a/proxy/build.gradle b/proxy/build.gradle index e7eb88a84..ff2e1fe0a 100644 --- a/proxy/build.gradle +++ b/proxy/build.gradle @@ -8,6 +8,11 @@ plugins { apply from: '../gradle/checkstyle.gradle' apply plugin: 'com.github.johnrengelman.shadow' +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + jar { manifest { def buildNumber = System.getenv("BUILD_NUMBER") ?: "unknown" From 8a3b6403da678f291a34cfb47fabd36e6768aeee Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sat, 7 Nov 2020 09:40:09 -0500 Subject: [PATCH 06/14] Wrap plugin message copies in unreleasable copies. Trying to track down a very weird issue that barely makes sense to me. --- .../proxy/connection/backend/BackendPlaySessionHandler.java | 2 +- .../proxy/connection/client/ClientPlaySessionHandler.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java index abd1f7b91..34103f52d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java @@ -146,7 +146,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler { .thenAcceptAsync(pme -> { if (pme.getResult().isAllowed() && !playerConnection.isClosed()) { PluginMessage copied = new PluginMessage(packet.getChannel(), - Unpooled.wrappedBuffer(copy)); + Unpooled.unreleasableBuffer(Unpooled.wrappedBuffer(copy))); playerConnection.write(copied); } }, playerConnection.eventLoop()) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java index cd443ebe3..ae6d3bb3d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java @@ -230,7 +230,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { server.getEventManager().fire(event).thenAcceptAsync(pme -> { if (pme.getResult().isAllowed()) { PluginMessage message = new PluginMessage(packet.getChannel(), - Unpooled.wrappedBuffer(copy)); + Unpooled.unreleasableBuffer(Unpooled.wrappedBuffer(copy))); backendConn.write(message); } }, backendConn.eventLoop()) From d51f357fa8a8f8275fb36eb81d1de49eb5fc2d2a Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sat, 7 Nov 2020 10:57:03 -0500 Subject: [PATCH 07/14] Avoid unneeded copy in BackendPlaySessionHandler plugin messages --- .../proxy/connection/backend/BackendPlaySessionHandler.java | 2 +- .../proxy/connection/client/ClientPlaySessionHandler.java | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java index 34103f52d..abd1f7b91 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java @@ -146,7 +146,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler { .thenAcceptAsync(pme -> { if (pme.getResult().isAllowed() && !playerConnection.isClosed()) { PluginMessage copied = new PluginMessage(packet.getChannel(), - Unpooled.unreleasableBuffer(Unpooled.wrappedBuffer(copy))); + Unpooled.wrappedBuffer(copy)); playerConnection.write(copied); } }, playerConnection.eventLoop()) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java index ae6d3bb3d..5757b3040 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java @@ -225,12 +225,11 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { backendConn.write(packet.retain()); } else { byte[] copy = ByteBufUtil.getBytes(packet.content()); - PluginMessageEvent event = new PluginMessageEvent(player, serverConn, id, - ByteBufUtil.getBytes(packet.content())); + PluginMessageEvent event = new PluginMessageEvent(player, serverConn, id, copy); server.getEventManager().fire(event).thenAcceptAsync(pme -> { if (pme.getResult().isAllowed()) { PluginMessage message = new PluginMessage(packet.getChannel(), - Unpooled.unreleasableBuffer(Unpooled.wrappedBuffer(copy))); + Unpooled.wrappedBuffer(copy)); backendConn.write(message); } }, backendConn.eventLoop()) From 46da2553fb2215cc9558cd416757d917c662a7dd Mon Sep 17 00:00:00 2001 From: A248 Date: Sat, 7 Nov 2020 14:53:09 -0500 Subject: [PATCH 08/14] Permit passing PluginContainer to PluginManager#addToClasspath --- .../proxy/plugin/VelocityPluginManager.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/plugin/VelocityPluginManager.java b/proxy/src/main/java/com/velocitypowered/proxy/plugin/VelocityPluginManager.java index 232e8c254..bd84db592 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/plugin/VelocityPluginManager.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/plugin/VelocityPluginManager.java @@ -175,9 +175,12 @@ public class VelocityPluginManager implements PluginManager { public void addToClasspath(Object plugin, Path path) { checkNotNull(plugin, "instance"); checkNotNull(path, "path"); - checkArgument(pluginInstances.containsKey(plugin), "plugin is not loaded"); + Optional optContainer = fromInstance(plugin); + checkArgument(optContainer.isPresent(), "plugin is not loaded"); + Optional optInstance = optContainer.get().getInstance(); + checkArgument(optInstance.isPresent(), "plugin has no instance"); - ClassLoader pluginClassloader = plugin.getClass().getClassLoader(); + ClassLoader pluginClassloader = optInstance.get().getClass().getClassLoader(); if (pluginClassloader instanceof PluginClassLoader) { ((PluginClassLoader) pluginClassloader).addPath(path); } else { From 44f872eea436fe9963486ceecebd4b34f0e3e5d0 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sat, 7 Nov 2020 20:43:58 -0500 Subject: [PATCH 09/14] Better validate addresses in configuration. Fixes #385 --- .../proxy/util/AddressUtil.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/AddressUtil.java b/proxy/src/main/java/com/velocitypowered/proxy/util/AddressUtil.java index b4feb268b..706e80357 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/util/AddressUtil.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/util/AddressUtil.java @@ -7,6 +7,8 @@ import java.net.InetSocketAddress; import java.net.URI; public final class AddressUtil { + private static final int DEFAULT_MINECRAFT_PORT = 25565; + private AddressUtil() { throw new AssertionError(); } @@ -21,11 +23,16 @@ public final class AddressUtil { public static InetSocketAddress parseAddress(String ip) { Preconditions.checkNotNull(ip, "ip"); URI uri = URI.create("tcp://" + ip); + if (uri.getHost() == null) { + throw new IllegalStateException("Invalid hostname/IP " + ip); + } + + int port = uri.getPort() == -1 ? DEFAULT_MINECRAFT_PORT : uri.getPort(); try { InetAddress ia = InetAddresses.forUriString(uri.getHost()); - return new InetSocketAddress(ia, uri.getPort()); + return new InetSocketAddress(ia, port); } catch (IllegalArgumentException e) { - return InetSocketAddress.createUnresolved(uri.getHost(), uri.getPort()); + return InetSocketAddress.createUnresolved(uri.getHost(), port); } } @@ -39,6 +46,11 @@ public final class AddressUtil { public static InetSocketAddress parseAndResolveAddress(String ip) { Preconditions.checkNotNull(ip, "ip"); URI uri = URI.create("tcp://" + ip); - return new InetSocketAddress(uri.getHost(), uri.getPort()); + if (uri.getHost() == null) { + throw new IllegalStateException("Invalid hostname/IP " + ip); + } + + int port = uri.getPort() == -1 ? DEFAULT_MINECRAFT_PORT : uri.getPort(); + return new InetSocketAddress(uri.getHost(), port); } } From 511165415de38f77a61c9ad48e28eba7717e8f14 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sun, 15 Nov 2020 23:33:16 -0500 Subject: [PATCH 10/14] Switch to our internal Brigadier fork --- api/build.gradle | 2 +- build.gradle | 4 ++-- .../velocitypowered/proxy/command/CommandManagerTests.java | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/api/build.gradle b/api/build.gradle index 7eca5c59d..8361c827e 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -41,7 +41,7 @@ dependencies { api "org.slf4j:slf4j-api:${slf4jVersion}" api 'com.google.inject:guice:4.2.3' api "org.checkerframework:checker-qual:${checkerFrameworkVersion}" - api 'com.mojang:brigadier:1.0.17' + api 'com.velocitypowered:velocity-brigadier:1.0.0-SNAPSHOT' api "org.spongepowered:configurate-hocon:${configurateVersion}" api "org.spongepowered:configurate-yaml:${configurateVersion}" diff --git a/build.gradle b/build.gradle index f3572eff8..7a1b37c86 100644 --- a/build.gradle +++ b/build.gradle @@ -52,9 +52,9 @@ allprojects { url 'https://oss.sonatype.org/content/groups/public/' } - // Brigadier + // Velocity repo maven { - url "https://libraries.minecraft.net" + url "https://nexus.velocitypowered.com/repository/maven-public/" } } diff --git a/proxy/src/test/java/com/velocitypowered/proxy/command/CommandManagerTests.java b/proxy/src/test/java/com/velocitypowered/proxy/command/CommandManagerTests.java index c97f6dc51..ef2bf022f 100644 --- a/proxy/src/test/java/com/velocitypowered/proxy/command/CommandManagerTests.java +++ b/proxy/src/test/java/com/velocitypowered/proxy/command/CommandManagerTests.java @@ -94,6 +94,7 @@ public class CommandManagerTests { assertTrue(manager.hasCommand("foO")); manager.unregister("fOo"); assertFalse(manager.hasCommand("foo")); + assertFalse(manager.execute(MockCommandSource.INSTANCE, "foo")); manager.register("foo", command, "bAr", "BAZ"); assertTrue(manager.hasCommand("bar")); From 7ead4add671edb8736e8c46a597d2783a80e0b00 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Mon, 16 Nov 2020 02:58:00 -0500 Subject: [PATCH 11/14] Support custom mod argument tunneling (#390) --- .../brigadier/ArgumentPropertyRegistry.java | 8 ++++ .../packet/brigadier/ModArgumentProperty.java | 47 +++++++++++++++++++ .../ModArgumentPropertySerializer.java | 27 +++++++++++ 3 files changed, 82 insertions(+) create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ModArgumentProperty.java create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ModArgumentPropertySerializer.java diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java index c175f8dc4..b98365d3a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java @@ -5,6 +5,7 @@ import static com.velocitypowered.proxy.protocol.packet.brigadier.EmptyArgumentP import static com.velocitypowered.proxy.protocol.packet.brigadier.FloatArgumentPropertySerializer.FLOAT; import static com.velocitypowered.proxy.protocol.packet.brigadier.IntegerArgumentPropertySerializer.INTEGER; import static com.velocitypowered.proxy.protocol.packet.brigadier.LongArgumentPropertySerializer.LONG; +import static com.velocitypowered.proxy.protocol.packet.brigadier.ModArgumentPropertySerializer.MOD; import static com.velocitypowered.proxy.protocol.packet.brigadier.StringArgumentPropertySerializer.STRING; import com.mojang.brigadier.arguments.ArgumentType; @@ -76,6 +77,10 @@ public class ArgumentPropertyRegistry { if (property.getResult() != null) { property.getSerializer().serialize(property.getResult(), buf); } + } else if (type instanceof ModArgumentProperty) { + ModArgumentProperty property = (ModArgumentProperty) type; + ProtocolUtils.writeString(buf, property.getIdentifier()); + buf.writeBytes(property.getData()); } else { ArgumentPropertySerializer serializer = byClass.get(type.getClass()); String id = classToId.get(type.getClass()); @@ -98,6 +103,9 @@ public class ArgumentPropertyRegistry { GenericArgumentPropertySerializer.create(BoolArgumentType::bool)); register("brigadier:long", LongArgumentType.class, LONG); + // Crossstitch support + register("crossstitch:mod_argument", ModArgumentProperty.class, MOD); + // Minecraft argument types with extra properties empty("minecraft:entity", ByteArgumentPropertySerializer.BYTE); empty("minecraft:score_holder", ByteArgumentPropertySerializer.BYTE); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ModArgumentProperty.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ModArgumentProperty.java new file mode 100644 index 000000000..f82133260 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ModArgumentProperty.java @@ -0,0 +1,47 @@ +package com.velocitypowered.proxy.protocol.packet.brigadier; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import java.util.Collection; +import java.util.concurrent.CompletableFuture; + +public class ModArgumentProperty implements ArgumentType { + + private final String identifier; + private final ByteBuf data; + + public ModArgumentProperty(String identifier, ByteBuf data) { + this.identifier = identifier; + this.data = Unpooled.unreleasableBuffer(data.asReadOnly()); + } + + public String getIdentifier() { + return identifier; + } + + public ByteBuf getData() { + return data.slice(); + } + + @Override + public ByteBuf parse(StringReader reader) throws CommandSyntaxException { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture listSuggestions(CommandContext context, + SuggestionsBuilder builder) { + throw new UnsupportedOperationException(); + } + + @Override + public Collection getExamples() { + throw new UnsupportedOperationException(); + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ModArgumentPropertySerializer.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ModArgumentPropertySerializer.java new file mode 100644 index 000000000..6c6eebbd0 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ModArgumentPropertySerializer.java @@ -0,0 +1,27 @@ +package com.velocitypowered.proxy.protocol.packet.brigadier; + +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.checkerframework.checker.nullness.qual.Nullable; + +class ModArgumentPropertySerializer implements ArgumentPropertySerializer { + static final ModArgumentPropertySerializer MOD = new ModArgumentPropertySerializer(); + + private ModArgumentPropertySerializer() { + + } + + @Override + public @Nullable ModArgumentProperty deserialize(ByteBuf buf) { + String identifier = ProtocolUtils.readString(buf); + byte[] extraData = ProtocolUtils.readByteArray(buf); + return new ModArgumentProperty(identifier, Unpooled.wrappedBuffer(extraData)); + } + + @Override + public void serialize(ModArgumentProperty object, ByteBuf buf) { + // This is special-cased by ArgumentPropertyRegistry + throw new UnsupportedOperationException(); + } +} From 329e2b0dc972b8cdb5f09df9969af19deba71ef1 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Mon, 16 Nov 2020 12:24:14 -0500 Subject: [PATCH 12/14] Use our fork's removeChildByName --- .../proxy/command/VelocityCommandManager.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java b/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java index 92232a380..4165c0afa 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java @@ -125,11 +125,7 @@ public class VelocityCommandManager implements CommandManager { @Override public void unregister(final String alias) { Preconditions.checkNotNull(alias, "alias"); - CommandNode node = - dispatcher.getRoot().getChild(alias.toLowerCase(Locale.ENGLISH)); - if (node != null) { - dispatcher.getRoot().getChildren().remove(node); - } + dispatcher.getRoot().removeChildByName(alias.toLowerCase(Locale.ENGLISH)); } /** From 563a96e6242d6a22ec9023b9e3a395cf6cd0ff50 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Tue, 17 Nov 2020 04:38:24 -0500 Subject: [PATCH 13/14] Bump Netty version --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7a1b37c86..6d4f7e8d7 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ allprojects { junitVersion = '5.7.0' slf4jVersion = '1.7.30' log4jVersion = '2.13.3' - nettyVersion = '4.1.52.Final' + nettyVersion = '4.1.54.Final' guavaVersion = '25.1-jre' checkerFrameworkVersion = '3.6.1' configurateVersion = '3.7.1' From 3d0cb505699369eccdbdfdfac727f9b9ae53bade Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Tue, 17 Nov 2020 04:48:20 -0500 Subject: [PATCH 14/14] Better check for unfinished decompression --- .../natives/compression/Java11VelocityCompressor.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/native/src/main/java/com/velocitypowered/natives/compression/Java11VelocityCompressor.java b/native/src/main/java/com/velocitypowered/natives/compression/Java11VelocityCompressor.java index 845c3adcd..49ac1da26 100644 --- a/native/src/main/java/com/velocitypowered/natives/compression/Java11VelocityCompressor.java +++ b/native/src/main/java/com/velocitypowered/natives/compression/Java11VelocityCompressor.java @@ -78,9 +78,9 @@ public class Java11VelocityCompressor implements VelocityCompressor { destination.writerIndex(destination.writerIndex() + produced); } - if (inflater.getBytesWritten() != uncompressedSize) { - throw new DataFormatException("Did not write the exact expected number of" - + " uncompressed bytes, expected " + uncompressedSize); + if (!inflater.finished()) { + throw new DataFormatException("Received a deflate stream that was too large, wanted " + + uncompressedSize); } source.readerIndex(origIdx + inflater.getTotalIn()); } catch (Throwable e) {