From 01be943c3f45d13f13c355590018053edd18a268 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Fri, 10 May 2019 04:32:29 -0400 Subject: [PATCH 01/10] Initial work on cleaning up plugin message handling in Velocity --- .../backend/BackendPlaySessionHandler.java | 20 +------- .../backend/TransitionSessionHandler.java | 33 +----------- .../client/ClientPlaySessionHandler.java | 49 ++++-------------- .../connection/client/ConnectedPlayer.java | 43 ++++++++++++++-- .../client/InitialConnectSessionHandler.java | 36 ++----------- .../proxy/util/collect/CappedCollection.java | 51 +++++++++++++++++++ .../util/collect/CappedCollectionTest.java | 35 +++++++++++++ 7 files changed, 140 insertions(+), 127 deletions(-) create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedCollection.java create mode 100644 proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedCollectionTest.java 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 dad35321a..e6d75c1e6 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 @@ -86,7 +86,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler { @Override public boolean handle(PluginMessage packet) { - if (!canForwardPluginMessage(packet)) { + if (!serverConn.getPlayer().canForwardPluginMessage(packet)) { return true; } @@ -177,22 +177,4 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler { serverConn.getPlayer().disconnect(ConnectionMessages.UNEXPECTED_DISCONNECT); } } - - private boolean canForwardPluginMessage(PluginMessage message) { - MinecraftConnection mc = serverConn.getConnection(); - if (mc == null) { - return false; - } - boolean minecraftOrFmlMessage; - if (mc.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_12_2) <= 0) { - String channel = message.getChannel(); - minecraftOrFmlMessage = channel.startsWith("MC|") || channel - .startsWith(LegacyForgeConstants.FORGE_LEGACY_HANDSHAKE_CHANNEL); - } else { - minecraftOrFmlMessage = message.getChannel().startsWith("minecraft:"); - } - return minecraftOrFmlMessage - || playerSessionHandler.getKnownChannels().contains(message.getChannel()) - || server.getChannelRegistrar().registered(message.getChannel()); - } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java index 5ba01172e..302c70449 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java @@ -130,7 +130,7 @@ public class TransitionSessionHandler implements MinecraftSessionHandler { @Override public boolean handle(PluginMessage packet) { - if (!canForwardPluginMessage(packet)) { + if (!serverConn.getPlayer().canForwardPluginMessage(packet)) { return true; } @@ -160,35 +160,4 @@ public class TransitionSessionHandler implements MinecraftSessionHandler { resultFuture .completeExceptionally(new IOException("Unexpectedly disconnected from remote server")); } - - private Collection getClientKnownPluginChannels() { - MinecraftSessionHandler handler = serverConn.getPlayer().getMinecraftConnection() - .getSessionHandler(); - - if (handler instanceof InitialConnectSessionHandler) { - return ((InitialConnectSessionHandler) handler).getKnownChannels(); - } else if (handler instanceof ClientPlaySessionHandler) { - return ((ClientPlaySessionHandler) handler).getKnownChannels(); - } else { - return ImmutableList.of(); - } - } - - private boolean canForwardPluginMessage(PluginMessage message) { - MinecraftConnection mc = serverConn.getConnection(); - if (mc == null) { - return false; - } - boolean minecraftOrFmlMessage; - if (mc.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_12_2) <= 0) { - String channel = message.getChannel(); - minecraftOrFmlMessage = channel.startsWith("MC|") || channel - .startsWith(LegacyForgeConstants.FORGE_LEGACY_HANDSHAKE_CHANNEL); - } else { - minecraftOrFmlMessage = message.getChannel().startsWith("minecraft:"); - } - return minecraftOrFmlMessage - || server.getChannelRegistrar().registered(message.getChannel()) - || getClientKnownPluginChannels().contains(message.getChannel()); - } } 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 45b8674ee..0fbc0cbc6 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 @@ -50,12 +50,10 @@ import org.checkerframework.checker.nullness.qual.Nullable; public class ClientPlaySessionHandler implements MinecraftSessionHandler { private static final Logger logger = LogManager.getLogger(ClientPlaySessionHandler.class); - static final int MAX_PLUGIN_CHANNELS = 1024; private final ConnectedPlayer player; private boolean spawned = false; private final List serverBossBars = new ArrayList<>(); - private final Set knownChannels = new HashSet<>(); private final Queue loginPluginMessages = new ArrayDeque<>(); private final VelocityServer server; private @Nullable TabCompleteRequest legacyCommandTabComplete; @@ -68,19 +66,16 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { public ClientPlaySessionHandler(VelocityServer server, ConnectedPlayer player) { this.player = player; this.server = server; - - if (player.getMinecraftConnection().getSessionHandler() - instanceof InitialConnectSessionHandler) { - this.knownChannels.addAll(((InitialConnectSessionHandler) player.getMinecraftConnection() - .getSessionHandler()).getKnownChannels()); - } } @Override public void activated() { + Collection channels = server.getChannelRegistrar().getChannelsForProtocol(player + .getProtocolVersion()); PluginMessage register = PluginMessageUtil.constructChannelsPacket(player.getProtocolVersion(), - server.getChannelRegistrar().getChannelsForProtocol(player.getProtocolVersion())); + channels); player.getMinecraftConnection().write(register); + player.getKnownChannels().addAll(channels); } @Override @@ -215,25 +210,10 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { logger.warn("A plugin message was received while the backend server was not " + "ready. Channel: {}. Packet discarded.", packet.getChannel()); } else if (PluginMessageUtil.isRegister(packet)) { - List actuallyRegistered = new ArrayList<>(); - List channels = PluginMessageUtil.getChannels(packet); - for (String channel : channels) { - if (knownChannels.size() >= MAX_PLUGIN_CHANNELS && !knownChannels.contains(channel)) { - throw new IllegalStateException("Too many plugin message channels registered"); - } - if (knownChannels.add(channel)) { - actuallyRegistered.add(channel); - } - } - - if (!actuallyRegistered.isEmpty()) { - PluginMessage newRegisterPacket = PluginMessageUtil.constructChannelsPacket(backendConn - .getProtocolVersion(), actuallyRegistered); - backendConn.write(newRegisterPacket); - } + player.getKnownChannels().addAll(PluginMessageUtil.getChannels(packet)); + backendConn.write(packet); } else if (PluginMessageUtil.isUnregister(packet)) { - List channels = PluginMessageUtil.getChannels(packet); - knownChannels.removeAll(channels); + player.getKnownChannels().removeAll(PluginMessageUtil.getChannels(packet)); backendConn.write(packet); } else if (PluginMessageUtil.isMcBrand(packet)) { backendConn.write(PluginMessageUtil.rewriteMinecraftBrand(packet, server.getVersion())); @@ -385,14 +365,9 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { // Tell the server about this client's plugin message channels. ProtocolVersion serverVersion = serverMc.getProtocolVersion(); - Collection toRegister = new HashSet<>(knownChannels); - if (serverVersion.compareTo(MINECRAFT_1_13) >= 0) { - toRegister.addAll(server.getChannelRegistrar().getModernChannelIds()); - } else { - toRegister.addAll(server.getChannelRegistrar().getIdsForLegacyConnections()); - } - if (!toRegister.isEmpty()) { - serverMc.delayedWrite(PluginMessageUtil.constructChannelsPacket(serverVersion, toRegister)); + if (!player.getKnownChannels().isEmpty()) { + serverMc.delayedWrite(PluginMessageUtil.constructChannelsPacket(serverVersion, + player.getKnownChannels())); } // If we had plugin messages queued during login/FML handshake, send them now. @@ -415,10 +390,6 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { return serverBossBars; } - public Set getKnownChannels() { - return knownChannels; - } - /** * Handles additional tab complete for 1.12 and lower clients. * diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index 68bfd0798..837217778 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -31,6 +31,7 @@ import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation; import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; +import com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeConstants; import com.velocitypowered.proxy.connection.util.ConnectionMessages; import com.velocitypowered.proxy.connection.util.ConnectionRequestResults; import com.velocitypowered.proxy.connection.util.ConnectionRequestResults.Impl; @@ -45,12 +46,10 @@ import com.velocitypowered.proxy.protocol.packet.TitlePacket; import com.velocitypowered.proxy.server.VelocityRegisteredServer; import com.velocitypowered.proxy.tablist.VelocityTabList; import com.velocitypowered.proxy.util.VelocityMessages; +import com.velocitypowered.proxy.util.collect.CappedCollection; import io.netty.buffer.ByteBufUtil; import java.net.InetSocketAddress; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.ThreadLocalRandom; @@ -68,12 +67,16 @@ import org.checkerframework.checker.nullness.qual.Nullable; public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { + private static final int MAX_PLUGIN_CHANNELS = 1024; private static final PlainComponentSerializer PASS_THRU_TRANSLATE = new PlainComponentSerializer( c -> "", TranslatableComponent::key); static final PermissionProvider DEFAULT_PERMISSIONS = s -> PermissionFunction.ALWAYS_UNDEFINED; private static final Logger logger = LogManager.getLogger(ConnectedPlayer.class); + /** + * The actual Minecraft connection. This is actually a wrapper object around the Netty channel. + */ private final MinecraftConnection minecraftConnection; private final @Nullable InetSocketAddress virtualHost; private GameProfile profile; @@ -87,6 +90,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { private final VelocityTabList tabList; private final VelocityServer server; private ClientConnectionPhase connectionPhase; + private final Collection knownChannels; private @MonotonicNonNull List serversToTry = null; @@ -99,6 +103,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { this.virtualHost = virtualHost; this.permissionFunction = PermissionFunction.ALWAYS_UNDEFINED; this.connectionPhase = minecraftConnection.getType().getInitialClientPhase(); + this.knownChannels = CappedCollection.newCappedSet(MAX_PLUGIN_CHANNELS); } @Override @@ -631,6 +636,36 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { this.connectionPhase = connectionPhase; } + /** + * Return all the plugin message channels "known" to the client. + * @return the channels + */ + public Collection getKnownChannels() { + return knownChannels; + } + + /** + * Determines whether or not we can forward a plugin message onto the client. + * @param message the plugin message to forward to the client + * @return {@code true} if the message can be forwarded, {@code false} otherwise + */ + public boolean canForwardPluginMessage(PluginMessage message) { + // If we're forwarding a plugin message onto the client, that implies that we have a backend connection + // already. + MinecraftConnection mc = ensureBackendConnection(); + + boolean minecraftOrFmlMessage; + if (mc.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_12_2) <= 0) { + String channel = message.getChannel(); + minecraftOrFmlMessage = channel.startsWith("MC|") || channel + .startsWith(LegacyForgeConstants.FORGE_LEGACY_HANDSHAKE_CHANNEL); + } else { + minecraftOrFmlMessage = message.getChannel().startsWith("minecraft:"); + } + return minecraftOrFmlMessage || knownChannels.contains(message.getChannel()) + || server.getChannelRegistrar().registered(message.getChannel()); + } + private class ConnectionRequestBuilderImpl implements ConnectionRequestBuilder { private final RegisteredServer toConnect; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialConnectSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialConnectSessionHandler.java index c681f5d2b..59c2e9255 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialConnectSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialConnectSessionHandler.java @@ -1,24 +1,16 @@ package com.velocitypowered.proxy.connection.client; -import static com.velocitypowered.proxy.connection.client.ClientPlaySessionHandler.MAX_PLUGIN_CHANNELS; - import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; import com.velocitypowered.proxy.protocol.packet.PluginMessage; import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; public class InitialConnectSessionHandler implements MinecraftSessionHandler { private final ConnectedPlayer player; - private final Set knownChannels; InitialConnectSessionHandler(ConnectedPlayer player) { this.player = player; - this.knownChannels = new HashSet<>(); } @Override @@ -30,29 +22,11 @@ public class InitialConnectSessionHandler implements MinecraftSessionHandler { } if (PluginMessageUtil.isRegister(packet)) { - List actuallyRegistered = new ArrayList<>(); - List channels = PluginMessageUtil.getChannels(packet); - for (String channel : channels) { - if (knownChannels.size() >= MAX_PLUGIN_CHANNELS && !knownChannels.contains(channel)) { - throw new IllegalStateException("Too many plugin message channels registered"); - } - if (knownChannels.add(channel)) { - actuallyRegistered.add(channel); - } - } - - if (!actuallyRegistered.isEmpty()) { - PluginMessage newRegisterPacket = PluginMessageUtil.constructChannelsPacket(serverConn - .ensureConnected().getProtocolVersion(), actuallyRegistered); - serverConn.ensureConnected().write(newRegisterPacket); - } + player.getKnownChannels().addAll(PluginMessageUtil.getChannels(packet)); } else if (PluginMessageUtil.isUnregister(packet)) { - List channels = PluginMessageUtil.getChannels(packet); - knownChannels.removeAll(channels); - serverConn.ensureConnected().write(packet); - } else { - serverConn.ensureConnected().write(packet); + player.getKnownChannels().removeAll(PluginMessageUtil.getChannels(packet)); } + serverConn.ensureConnected().write(packet); } return true; } @@ -62,8 +36,4 @@ public class InitialConnectSessionHandler implements MinecraftSessionHandler { // the user cancelled the login process player.teardown(); } - - public Set getKnownChannels() { - return knownChannels; - } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedCollection.java b/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedCollection.java new file mode 100644 index 000000000..64f5e92a5 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedCollection.java @@ -0,0 +1,51 @@ +package com.velocitypowered.proxy.util.collect; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ForwardingCollection; + +import java.util.Collection; +import java.util.HashSet; + +/** + * An unsynchronized collection that puts an upper bound on the size of the collection. + */ +public class CappedCollection extends ForwardingCollection { + + private final Collection delegate; + private final int upperSize; + + private CappedCollection(Collection delegate, int upperSize) { + this.delegate = delegate; + this.upperSize = upperSize; + } + + /** + * Creates a capped collection backed by a {@link HashSet}. + * @param maxSize the maximum size of the collection + * @param the type of elements in the collection + * @return the new collection + */ + public static Collection newCappedSet(int maxSize) { + return new CappedCollection<>(new HashSet<>(), maxSize); + } + + @Override + protected Collection delegate() { + return delegate; + } + + @Override + public boolean add(T element) { + Preconditions.checkState(this.delegate.size() + 1 <= upperSize, "collection is too large (%s)", + this.delegate.size()); + return this.delegate.add(element); + } + + @Override + public boolean addAll(Collection collection) { + Preconditions.checkState(this.delegate.size() + collection.size() <= upperSize, + "collection would grow too large (%s + %s > %s)", + this.delegate.size(), collection.size(), upperSize); + return this.standardAddAll(collection); + } +} diff --git a/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedCollectionTest.java b/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedCollectionTest.java new file mode 100644 index 000000000..634cadf2c --- /dev/null +++ b/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedCollectionTest.java @@ -0,0 +1,35 @@ +package com.velocitypowered.proxy.util.collect; + +import static org.junit.jupiter.api.Assertions.*; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import java.util.Collection; +import java.util.Set; +import org.junit.jupiter.api.Test; + +class CappedCollectionTest { + + @Test + void basicVerification() { + Collection coll = CappedCollection.newCappedSet(1); + assertTrue(coll.add("coffee"), "did not add single item"); + assertThrows(IllegalStateException.class, () -> coll.add("tea"), + "item was added to collection although it is too full"); + assertEquals(1, coll.size(), "collection grew in size unexpectedly"); + } + + @Test + void testAddAll() { + Set doesFill1 = ImmutableSet.of("coffee", "tea"); + Set doesFill2 = ImmutableSet.of("chocolate"); + Set overfill = ImmutableSet.of("Coke", "Pepsi"); + + Collection coll = CappedCollection.newCappedSet(3); + assertTrue(coll.addAll(doesFill1), "did not add items"); + assertTrue(coll.addAll(doesFill2), "did not add items"); + assertThrows(IllegalStateException.class, () -> coll.addAll(overfill), + "items added to collection although it is too full"); + assertEquals(3, coll.size(), "collection grew in size unexpectedly"); + } +} \ No newline at end of file From c26dc75c44fa27b8bf6e749d1c12fb1b3f869aac Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Fri, 10 May 2019 04:44:01 -0400 Subject: [PATCH 02/10] More robust check --- .../proxy/util/collect/CappedCollection.java | 10 +++++----- .../proxy/util/collect/CappedCollectionTest.java | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedCollection.java b/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedCollection.java index 64f5e92a5..01645e973 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedCollection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedCollection.java @@ -36,16 +36,16 @@ public class CappedCollection extends ForwardingCollection { @Override public boolean add(T element) { - Preconditions.checkState(this.delegate.size() + 1 <= upperSize, "collection is too large (%s)", - this.delegate.size()); + if (this.delegate.size() >= upperSize) { + Preconditions.checkState(this.delegate.contains(element), "collection is too large (%s >= %s)", + this.delegate.size(), this.upperSize); + return false; + } return this.delegate.add(element); } @Override public boolean addAll(Collection collection) { - Preconditions.checkState(this.delegate.size() + collection.size() <= upperSize, - "collection would grow too large (%s + %s > %s)", - this.delegate.size(), collection.size(), upperSize); return this.standardAddAll(collection); } } diff --git a/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedCollectionTest.java b/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedCollectionTest.java index 634cadf2c..f6fbcd919 100644 --- a/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedCollectionTest.java +++ b/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedCollectionTest.java @@ -32,4 +32,18 @@ class CappedCollectionTest { "items added to collection although it is too full"); assertEquals(3, coll.size(), "collection grew in size unexpectedly"); } + + @Test + void handlesSetBehaviorCorrectly() { + Set doesFill1 = ImmutableSet.of("coffee", "tea"); + Set doesFill2 = ImmutableSet.of("coffee", "chocolate"); + Set overfill = ImmutableSet.of("coffee", "Coke", "Pepsi"); + + Collection coll = CappedCollection.newCappedSet(3); + assertTrue(coll.addAll(doesFill1), "did not add items"); + assertTrue(coll.addAll(doesFill2), "did not add items"); + assertThrows(IllegalStateException.class, () -> coll.addAll(overfill), + "items added to collection although it is too full"); + assertEquals(3, coll.size(), "collection grew in size unexpectedly"); + } } \ No newline at end of file From 74afcee9bae688438a5c3f049bb79e1e7321594c Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Fri, 10 May 2019 04:53:57 -0400 Subject: [PATCH 03/10] Suspect this is the fix to #203, but I'm unsure --- .../connection/backend/TransitionSessionHandler.java | 9 +++++++++ .../proxy/util/collect/CappedCollectionTest.java | 3 +++ 2 files changed, 12 insertions(+) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java index 302c70449..07a06c89e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java @@ -19,6 +19,7 @@ import com.velocitypowered.proxy.protocol.packet.Disconnect; import com.velocitypowered.proxy.protocol.packet.JoinGame; import com.velocitypowered.proxy.protocol.packet.KeepAlive; import com.velocitypowered.proxy.protocol.packet.PluginMessage; +import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; import java.io.IOException; import java.util.Collection; import java.util.concurrent.CompletableFuture; @@ -134,6 +135,14 @@ public class TransitionSessionHandler implements MinecraftSessionHandler { return true; } + // We need to specially handle REGISTER and UNREGISTER packets. Later on, we'll write them to + // the client. + if (PluginMessageUtil.isRegister(packet)) { + serverConn.getPlayer().getKnownChannels().addAll(PluginMessageUtil.getChannels(packet)); + } else if (PluginMessageUtil.isUnregister(packet)) { + serverConn.getPlayer().getKnownChannels().removeAll(PluginMessageUtil.getChannels(packet)); + } + // We always need to handle plugin messages, for Forge compatibility. if (serverConn.getPhase().handle(serverConn, serverConn.getPlayer(), packet)) { // Handled, but check the server connection phase. diff --git a/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedCollectionTest.java b/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedCollectionTest.java index f6fbcd919..d9bcab45d 100644 --- a/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedCollectionTest.java +++ b/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedCollectionTest.java @@ -44,6 +44,9 @@ class CappedCollectionTest { assertTrue(coll.addAll(doesFill2), "did not add items"); assertThrows(IllegalStateException.class, () -> coll.addAll(overfill), "items added to collection although it is too full"); + + assertFalse(coll.addAll(doesFill1), "added items?!?"); + assertEquals(3, coll.size(), "collection grew in size unexpectedly"); } } \ No newline at end of file From 5f0470fb0b12b62337d4bcc5c222d277c4b23583 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Fri, 10 May 2019 07:42:47 -0400 Subject: [PATCH 04/10] Checkstyle, CappedCollection -> CappedSet --- .../proxy/connection/client/ConnectedPlayer.java | 14 +++++++++----- .../{CappedCollection.java => CappedSet.java} | 15 ++++++++------- ...ppedCollectionTest.java => CappedSetTest.java} | 9 ++++----- 3 files changed, 21 insertions(+), 17 deletions(-) rename proxy/src/main/java/com/velocitypowered/proxy/util/collect/{CappedCollection.java => CappedSet.java} (72%) rename proxy/src/test/java/com/velocitypowered/proxy/util/collect/{CappedCollectionTest.java => CappedSetTest.java} (86%) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index 837217778..e77c20fd4 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -46,10 +46,14 @@ import com.velocitypowered.proxy.protocol.packet.TitlePacket; import com.velocitypowered.proxy.server.VelocityRegisteredServer; import com.velocitypowered.proxy.tablist.VelocityTabList; import com.velocitypowered.proxy.util.VelocityMessages; -import com.velocitypowered.proxy.util.collect.CappedCollection; +import com.velocitypowered.proxy.util.collect.CappedSet; import io.netty.buffer.ByteBufUtil; import java.net.InetSocketAddress; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.ThreadLocalRandom; @@ -103,7 +107,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { this.virtualHost = virtualHost; this.permissionFunction = PermissionFunction.ALWAYS_UNDEFINED; this.connectionPhase = minecraftConnection.getType().getInitialClientPhase(); - this.knownChannels = CappedCollection.newCappedSet(MAX_PLUGIN_CHANNELS); + this.knownChannels = CappedSet.newCappedSet(MAX_PLUGIN_CHANNELS); } @Override @@ -650,8 +654,8 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { * @return {@code true} if the message can be forwarded, {@code false} otherwise */ public boolean canForwardPluginMessage(PluginMessage message) { - // If we're forwarding a plugin message onto the client, that implies that we have a backend connection - // already. + // If we're forwarding a plugin message onto the client, that implies that we have a backend + // connection already. MinecraftConnection mc = ensureBackendConnection(); boolean minecraftOrFmlMessage; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedCollection.java b/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedSet.java similarity index 72% rename from proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedCollection.java rename to proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedSet.java index 01645e973..eeacda6a0 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedCollection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedSet.java @@ -1,20 +1,21 @@ package com.velocitypowered.proxy.util.collect; import com.google.common.base.Preconditions; -import com.google.common.collect.ForwardingCollection; +import com.google.common.collect.ForwardingSet; import java.util.Collection; import java.util.HashSet; +import java.util.Set; /** * An unsynchronized collection that puts an upper bound on the size of the collection. */ -public class CappedCollection extends ForwardingCollection { +public class CappedSet extends ForwardingSet { - private final Collection delegate; + private final Set delegate; private final int upperSize; - private CappedCollection(Collection delegate, int upperSize) { + private CappedSet(Set delegate, int upperSize) { this.delegate = delegate; this.upperSize = upperSize; } @@ -25,12 +26,12 @@ public class CappedCollection extends ForwardingCollection { * @param the type of elements in the collection * @return the new collection */ - public static Collection newCappedSet(int maxSize) { - return new CappedCollection<>(new HashSet<>(), maxSize); + public static Set newCappedSet(int maxSize) { + return new CappedSet<>(new HashSet<>(), maxSize); } @Override - protected Collection delegate() { + protected Set delegate() { return delegate; } diff --git a/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedCollectionTest.java b/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedSetTest.java similarity index 86% rename from proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedCollectionTest.java rename to proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedSetTest.java index d9bcab45d..8444961d0 100644 --- a/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedCollectionTest.java +++ b/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedSetTest.java @@ -2,17 +2,16 @@ package com.velocitypowered.proxy.util.collect; import static org.junit.jupiter.api.Assertions.*; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import java.util.Collection; import java.util.Set; import org.junit.jupiter.api.Test; -class CappedCollectionTest { +class CappedSetTest { @Test void basicVerification() { - Collection coll = CappedCollection.newCappedSet(1); + Collection coll = CappedSet.newCappedSet(1); assertTrue(coll.add("coffee"), "did not add single item"); assertThrows(IllegalStateException.class, () -> coll.add("tea"), "item was added to collection although it is too full"); @@ -25,7 +24,7 @@ class CappedCollectionTest { Set doesFill2 = ImmutableSet.of("chocolate"); Set overfill = ImmutableSet.of("Coke", "Pepsi"); - Collection coll = CappedCollection.newCappedSet(3); + Collection coll = CappedSet.newCappedSet(3); assertTrue(coll.addAll(doesFill1), "did not add items"); assertTrue(coll.addAll(doesFill2), "did not add items"); assertThrows(IllegalStateException.class, () -> coll.addAll(overfill), @@ -39,7 +38,7 @@ class CappedCollectionTest { Set doesFill2 = ImmutableSet.of("coffee", "chocolate"); Set overfill = ImmutableSet.of("coffee", "Coke", "Pepsi"); - Collection coll = CappedCollection.newCappedSet(3); + Collection coll = CappedSet.newCappedSet(3); assertTrue(coll.addAll(doesFill1), "did not add items"); assertTrue(coll.addAll(doesFill2), "did not add items"); assertThrows(IllegalStateException.class, () -> coll.addAll(overfill), From adfb33ad21e0e4db4df24e7019dcbc80e17a1c6e Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sun, 12 May 2019 10:05:22 -0400 Subject: [PATCH 05/10] Fix server-sent plugin message channels, fixing WDLCompanion and similar Closes #203 --- .../proxy/command/VelocityCommand.java | 2 +- .../backend/BackendPlaySessionHandler.java | 11 ++++++++++- .../backend/TransitionSessionHandler.java | 7 ++++--- .../proxy/connection/client/ConnectedPlayer.java | 15 +++++++++------ .../proxy/network/http/NettyHttpClient.java | 1 - .../proxy/protocol/packet/KeepAlive.java | 2 +- 6 files changed, 25 insertions(+), 13 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommand.java b/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommand.java index a67582a0a..3c12b493a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommand.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommand.java @@ -260,7 +260,7 @@ public class VelocityCommand implements Command { @Override public boolean hasPermission(CommandSource source, String @NonNull [] args) { - return source.getPermissionValue("velocity.command.plugins") == Tristate.TRUE; + return source.getPermissionValue("velocity.command.plugins").asBoolean(); } } } 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 e6d75c1e6..a2afbae6a 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 @@ -86,10 +86,19 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler { @Override public boolean handle(PluginMessage packet) { - if (!serverConn.getPlayer().canForwardPluginMessage(packet)) { + if (!serverConn.getPlayer().canForwardPluginMessage(serverConn.ensureConnected() + .getProtocolVersion(), packet)) { return true; } + // We need to specially handle REGISTER and UNREGISTER packets. Later on, we'll write them to + // the client. + if (PluginMessageUtil.isRegister(packet)) { + serverConn.getPlayer().getKnownChannels().addAll(PluginMessageUtil.getChannels(packet)); + } else if (PluginMessageUtil.isUnregister(packet)) { + serverConn.getPlayer().getKnownChannels().removeAll(PluginMessageUtil.getChannels(packet)); + } + if (PluginMessageUtil.isMcBrand(packet)) { PluginMessage rewritten = PluginMessageUtil.rewriteMinecraftBrand(packet, server.getVersion()); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java index 07a06c89e..42d063bce 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java @@ -131,15 +131,16 @@ public class TransitionSessionHandler implements MinecraftSessionHandler { @Override public boolean handle(PluginMessage packet) { - if (!serverConn.getPlayer().canForwardPluginMessage(packet)) { + if (!serverConn.getPlayer().canForwardPluginMessage(serverConn.ensureConnected() + .getProtocolVersion(), packet)) { return true; } - // We need to specially handle REGISTER and UNREGISTER packets. Later on, we'll write them to - // the client. if (PluginMessageUtil.isRegister(packet)) { + System.out.println("[TSH] I CAN HAZ REGISTER: " + PluginMessageUtil.getChannels(packet)); serverConn.getPlayer().getKnownChannels().addAll(PluginMessageUtil.getChannels(packet)); } else if (PluginMessageUtil.isUnregister(packet)) { + System.out.println("[TSH] I CAN HAZ UNREGISTER: " + PluginMessageUtil.getChannels(packet)); serverConn.getPlayer().getKnownChannels().removeAll(PluginMessageUtil.getChannels(packet)); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index e77c20fd4..f6f104bc3 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -43,6 +43,7 @@ import com.velocitypowered.proxy.protocol.packet.KeepAlive; import com.velocitypowered.proxy.protocol.packet.PluginMessage; import com.velocitypowered.proxy.protocol.packet.ResourcePackRequest; import com.velocitypowered.proxy.protocol.packet.TitlePacket; +import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; import com.velocitypowered.proxy.server.VelocityRegisteredServer; import com.velocitypowered.proxy.tablist.VelocityTabList; import com.velocitypowered.proxy.util.VelocityMessages; @@ -650,16 +651,18 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { /** * Determines whether or not we can forward a plugin message onto the client. + * @param version the Minecraft protocol version * @param message the plugin message to forward to the client * @return {@code true} if the message can be forwarded, {@code false} otherwise */ - public boolean canForwardPluginMessage(PluginMessage message) { - // If we're forwarding a plugin message onto the client, that implies that we have a backend - // connection already. - MinecraftConnection mc = ensureBackendConnection(); - + public boolean canForwardPluginMessage(ProtocolVersion version, PluginMessage message) { boolean minecraftOrFmlMessage; - if (mc.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_12_2) <= 0) { + + if (PluginMessageUtil.isRegister(message) || PluginMessageUtil.isUnregister(message)) { + return true; + } + + if (version.compareTo(ProtocolVersion.MINECRAFT_1_12_2) <= 0) { String channel = message.getChannel(); minecraftOrFmlMessage = channel.startsWith("MC|") || channel .startsWith(LegacyForgeConstants.FORGE_LEGACY_HANDSHAKE_CHANNEL); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/http/NettyHttpClient.java b/proxy/src/main/java/com/velocitypowered/proxy/network/http/NettyHttpClient.java index fa66b533d..f64639957 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/http/NettyHttpClient.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/http/NettyHttpClient.java @@ -15,7 +15,6 @@ import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslHandler; import java.net.InetSocketAddress; import java.net.URL; -import java.util.Objects; import java.util.concurrent.CompletableFuture; import javax.net.ssl.SSLEngine; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/KeepAlive.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/KeepAlive.java index e4b581617..ac6810a65 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/KeepAlive.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/KeepAlive.java @@ -32,7 +32,7 @@ public class KeepAlive implements MinecraftPacket { } else { randomId = ProtocolUtils.readVarInt(buf); } -} + } @Override public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { From b5fcf685be28b23e4688111a91f42e322b6919ff Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sun, 12 May 2019 10:06:01 -0400 Subject: [PATCH 06/10] Kill debug --- .../proxy/connection/backend/TransitionSessionHandler.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java index 42d063bce..b38d96ff8 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java @@ -137,10 +137,8 @@ public class TransitionSessionHandler implements MinecraftSessionHandler { } if (PluginMessageUtil.isRegister(packet)) { - System.out.println("[TSH] I CAN HAZ REGISTER: " + PluginMessageUtil.getChannels(packet)); serverConn.getPlayer().getKnownChannels().addAll(PluginMessageUtil.getChannels(packet)); } else if (PluginMessageUtil.isUnregister(packet)) { - System.out.println("[TSH] I CAN HAZ UNREGISTER: " + PluginMessageUtil.getChannels(packet)); serverConn.getPlayer().getKnownChannels().removeAll(PluginMessageUtil.getChannels(packet)); } From 16d557a109468b06c7acb6157a2ff4618ca8027e Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sun, 12 May 2019 10:46:11 -0400 Subject: [PATCH 07/10] Fix checkstyle --- .../com/velocitypowered/proxy/util/collect/CappedSet.java | 3 ++- .../velocitypowered/proxy/util/collect/CappedSetTest.java | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedSet.java b/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedSet.java index eeacda6a0..6b3453134 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedSet.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedSet.java @@ -38,7 +38,8 @@ public class CappedSet extends ForwardingSet { @Override public boolean add(T element) { if (this.delegate.size() >= upperSize) { - Preconditions.checkState(this.delegate.contains(element), "collection is too large (%s >= %s)", + Preconditions.checkState(this.delegate.contains(element), + "collection is too large (%s >= %s)", this.delegate.size(), this.upperSize); return false; } diff --git a/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedSetTest.java b/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedSetTest.java index 8444961d0..2315c82c4 100644 --- a/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedSetTest.java +++ b/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedSetTest.java @@ -1,6 +1,9 @@ package com.velocitypowered.proxy.util.collect; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.common.collect.ImmutableSet; import java.util.Collection; From 3c9cc2c4a8e20d83ce6707c7393746be12f0ed5c Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sun, 12 May 2019 10:48:47 -0400 Subject: [PATCH 08/10] Remove unrelated change --- .../java/com/velocitypowered/proxy/command/VelocityCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommand.java b/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommand.java index 3c12b493a..a67582a0a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommand.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommand.java @@ -260,7 +260,7 @@ public class VelocityCommand implements Command { @Override public boolean hasPermission(CommandSource source, String @NonNull [] args) { - return source.getPermissionValue("velocity.command.plugins").asBoolean(); + return source.getPermissionValue("velocity.command.plugins") == Tristate.TRUE; } } } From 57085feb42797351df1bb50ddc5327e7fbef99a6 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sun, 12 May 2019 11:09:50 -0400 Subject: [PATCH 09/10] Better document what plugin channels we need to forward onto clients. --- .../proxy/connection/client/ConnectedPlayer.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index f6f104bc3..9e950e201 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -658,10 +658,13 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { public boolean canForwardPluginMessage(ProtocolVersion version, PluginMessage message) { boolean minecraftOrFmlMessage; + // We should _always_ pass on new channels the server wishes to register (or unregister) with + // us. if (PluginMessageUtil.isRegister(message) || PluginMessageUtil.isUnregister(message)) { return true; } + // By default, all internal Minecraft and Forge channels are forwarded from the server. if (version.compareTo(ProtocolVersion.MINECRAFT_1_12_2) <= 0) { String channel = message.getChannel(); minecraftOrFmlMessage = channel.startsWith("MC|") || channel @@ -669,6 +672,9 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { } else { minecraftOrFmlMessage = message.getChannel().startsWith("minecraft:"); } + + // Otherwise, we need to see if the player already knows this channel or it's known by the + // proxy. return minecraftOrFmlMessage || knownChannels.contains(message.getChannel()) || server.getChannelRegistrar().registered(message.getChannel()); } From 5bd9f0a96fb234d9da81f73b8c7a300dfcab8f09 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Tue, 14 May 2019 04:11:49 -0400 Subject: [PATCH 10/10] CappedSet.newCappedSet() -> CappedSet.create() --- .../proxy/connection/client/ConnectedPlayer.java | 2 +- .../com/velocitypowered/proxy/util/collect/CappedSet.java | 2 +- .../velocitypowered/proxy/util/collect/CappedSetTest.java | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index 9e950e201..d8c7ee290 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -108,7 +108,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { this.virtualHost = virtualHost; this.permissionFunction = PermissionFunction.ALWAYS_UNDEFINED; this.connectionPhase = minecraftConnection.getType().getInitialClientPhase(); - this.knownChannels = CappedSet.newCappedSet(MAX_PLUGIN_CHANNELS); + this.knownChannels = CappedSet.create(MAX_PLUGIN_CHANNELS); } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedSet.java b/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedSet.java index 6b3453134..a0f775f9e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedSet.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/util/collect/CappedSet.java @@ -26,7 +26,7 @@ public class CappedSet extends ForwardingSet { * @param the type of elements in the collection * @return the new collection */ - public static Set newCappedSet(int maxSize) { + public static Set create(int maxSize) { return new CappedSet<>(new HashSet<>(), maxSize); } diff --git a/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedSetTest.java b/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedSetTest.java index 2315c82c4..11df2237d 100644 --- a/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedSetTest.java +++ b/proxy/src/test/java/com/velocitypowered/proxy/util/collect/CappedSetTest.java @@ -14,7 +14,7 @@ class CappedSetTest { @Test void basicVerification() { - Collection coll = CappedSet.newCappedSet(1); + Collection coll = CappedSet.create(1); assertTrue(coll.add("coffee"), "did not add single item"); assertThrows(IllegalStateException.class, () -> coll.add("tea"), "item was added to collection although it is too full"); @@ -27,7 +27,7 @@ class CappedSetTest { Set doesFill2 = ImmutableSet.of("chocolate"); Set overfill = ImmutableSet.of("Coke", "Pepsi"); - Collection coll = CappedSet.newCappedSet(3); + Collection coll = CappedSet.create(3); assertTrue(coll.addAll(doesFill1), "did not add items"); assertTrue(coll.addAll(doesFill2), "did not add items"); assertThrows(IllegalStateException.class, () -> coll.addAll(overfill), @@ -41,7 +41,7 @@ class CappedSetTest { Set doesFill2 = ImmutableSet.of("coffee", "chocolate"); Set overfill = ImmutableSet.of("coffee", "Coke", "Pepsi"); - Collection coll = CappedSet.newCappedSet(3); + Collection coll = CappedSet.create(3); assertTrue(coll.addAll(doesFill1), "did not add items"); assertTrue(coll.addAll(doesFill2), "did not add items"); assertThrows(IllegalStateException.class, () -> coll.addAll(overfill),