diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle new file mode 100644 index 000000000..1cf8c5ddf --- /dev/null +++ b/annotation-processor/build.gradle @@ -0,0 +1,35 @@ +plugins { + id 'java-library' + id 'maven-publish' + id 'checkstyle' +} + +apply plugin: 'org.cadixdev.licenser' +apply from: '../gradle/checkstyle.gradle' +apply from: '../gradle/publish.gradle' +apply from: '../gradle/errorprone.gradle' + +java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} + +license { + header = project.rootProject.file('HEADER.txt') +} + +dependencies { + implementation project(':velocity-api') +} + +test { + useJUnitPlatform() +} + +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + } + } +} diff --git a/api/src/ap/java/com/velocitypowered/api/plugin/ap/PluginAnnotationProcessor.java b/annotation-processor/src/main/java/com/velocitypowered/annotationprocessor/PluginAnnotationProcessor.java similarity index 74% rename from api/src/ap/java/com/velocitypowered/api/plugin/ap/PluginAnnotationProcessor.java rename to annotation-processor/src/main/java/com/velocitypowered/annotationprocessor/PluginAnnotationProcessor.java index 6fd77ddf3..43d0e8c9d 100644 --- a/api/src/ap/java/com/velocitypowered/api/plugin/ap/PluginAnnotationProcessor.java +++ b/annotation-processor/src/main/java/com/velocitypowered/annotationprocessor/PluginAnnotationProcessor.java @@ -1,11 +1,21 @@ /* * Copyright (C) 2018 Velocity Contributors * - * The Velocity API is licensed under the terms of the MIT License. For more details, - * reference the LICENSE file in the api top-level directory. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ -package com.velocitypowered.api.plugin.ap; +package com.velocitypowered.annotationprocessor; import com.google.gson.Gson; import com.velocitypowered.api.plugin.Plugin; @@ -14,6 +24,7 @@ import java.io.IOException; import java.io.Writer; import java.util.Objects; import java.util.Set; +import javax.annotation.Nullable; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; @@ -30,15 +41,9 @@ import javax.tools.StandardLocation; @SupportedAnnotationTypes({"com.velocitypowered.api.plugin.Plugin"}) public class PluginAnnotationProcessor extends AbstractProcessor { - private ProcessingEnvironment environment; - private String pluginClassFound; + private @Nullable String pluginClassFound; private boolean warnedAboutMultiplePlugins; - @Override - public synchronized void init(ProcessingEnvironment processingEnv) { - this.environment = processingEnv; - } - @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latestSupported(); @@ -53,7 +58,7 @@ public class PluginAnnotationProcessor extends AbstractProcessor { for (Element element : roundEnv.getElementsAnnotatedWith(Plugin.class)) { if (element.getKind() != ElementKind.CLASS) { - environment.getMessager() + processingEnv.getMessager() .printMessage(Diagnostic.Kind.ERROR, "Only classes can be annotated with " + Plugin.class.getCanonicalName()); return false; @@ -63,7 +68,7 @@ public class PluginAnnotationProcessor extends AbstractProcessor { if (Objects.equals(pluginClassFound, qualifiedName.toString())) { if (!warnedAboutMultiplePlugins) { - environment.getMessager() + processingEnv.getMessager() .printMessage(Diagnostic.Kind.WARNING, "Velocity does not yet currently support " + "multiple plugins. We are using " + pluginClassFound + " for your plugin's main class."); @@ -74,7 +79,7 @@ public class PluginAnnotationProcessor extends AbstractProcessor { Plugin plugin = element.getAnnotation(Plugin.class); if (!SerializedPluginDescription.ID_PATTERN.matcher(plugin.id()).matches()) { - environment.getMessager().printMessage(Diagnostic.Kind.ERROR, "Invalid ID for plugin " + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Invalid ID for plugin " + qualifiedName + ". IDs must start alphabetically, have alphanumeric characters, and can " + "contain dashes or underscores."); @@ -85,14 +90,14 @@ public class PluginAnnotationProcessor extends AbstractProcessor { SerializedPluginDescription description = SerializedPluginDescription .from(plugin, qualifiedName.toString()); try { - FileObject object = environment.getFiler() + FileObject object = processingEnv.getFiler() .createResource(StandardLocation.CLASS_OUTPUT, "", "velocity-plugin.json"); try (Writer writer = new BufferedWriter(object.openWriter())) { new Gson().toJson(description, writer); } pluginClassFound = qualifiedName.toString(); } catch (IOException e) { - environment.getMessager() + processingEnv.getMessager() .printMessage(Diagnostic.Kind.ERROR, "Unable to generate plugin file"); } } diff --git a/api/src/ap/java/com/velocitypowered/api/plugin/ap/SerializedPluginDescription.java b/annotation-processor/src/main/java/com/velocitypowered/annotationprocessor/SerializedPluginDescription.java similarity index 87% rename from api/src/ap/java/com/velocitypowered/api/plugin/ap/SerializedPluginDescription.java rename to annotation-processor/src/main/java/com/velocitypowered/annotationprocessor/SerializedPluginDescription.java index e785d9adb..a085f4127 100644 --- a/api/src/ap/java/com/velocitypowered/api/plugin/ap/SerializedPluginDescription.java +++ b/annotation-processor/src/main/java/com/velocitypowered/annotationprocessor/SerializedPluginDescription.java @@ -1,11 +1,21 @@ /* * Copyright (C) 2018 Velocity Contributors * - * The Velocity API is licensed under the terms of the MIT License. For more details, - * reference the LICENSE file in the api top-level directory. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ -package com.velocitypowered.api.plugin.ap; +package com.velocitypowered.annotationprocessor; import com.google.common.base.Preconditions; import com.google.common.base.Strings; diff --git a/annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor new file mode 100644 index 000000000..98f9005d0 --- /dev/null +++ b/annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -0,0 +1 @@ +com.velocitypowered.annotationprocessor.PluginAnnotationProcessor \ No newline at end of file diff --git a/api/build.gradle b/api/build.gradle index db1147901..e214c967a 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -7,6 +7,7 @@ plugins { apply plugin: 'org.cadixdev.licenser' apply from: '../gradle/checkstyle.gradle' apply from: '../gradle/publish.gradle' +apply from: '../gradle/errorprone.gradle' apply plugin: 'com.github.johnrengelman.shadow' java { @@ -18,12 +19,6 @@ license { header = project.file('HEADER.txt') } -sourceSets { - ap { - compileClasspath += main.compileClasspath + main.output - } -} - dependencies { api 'com.google.code.gson:gson:2.8.6' api "com.google.guava:guava:${guavaVersion}" @@ -55,20 +50,10 @@ task javadocJar(type: Jar) { task sourcesJar(type: Jar) { classifier 'sources' from sourceSets.main.allSource - from sourceSets.ap.output -} - -jar { - from sourceSets.ap.output -} - -shadowJar { - from sourceSets.ap.output } artifacts { archives javadocJar - archives shadowJar archives sourcesJar } diff --git a/api/src/ap/resources/META-INF/services/javax.annotation.processing.Processor b/api/src/ap/resources/META-INF/services/javax.annotation.processing.Processor deleted file mode 100644 index a96abf5d2..000000000 --- a/api/src/ap/resources/META-INF/services/javax.annotation.processing.Processor +++ /dev/null @@ -1 +0,0 @@ -com.velocitypowered.api.plugin.ap.PluginAnnotationProcessor \ No newline at end of file diff --git a/api/src/main/java/com/velocitypowered/api/event/EventHandler.java b/api/src/main/java/com/velocitypowered/api/event/EventHandler.java index fdf25862e..2817fca8d 100644 --- a/api/src/main/java/com/velocitypowered/api/event/EventHandler.java +++ b/api/src/main/java/com/velocitypowered/api/event/EventHandler.java @@ -7,6 +7,8 @@ package com.velocitypowered.api.event; +import org.checkerframework.checker.nullness.qual.Nullable; + /** * Allows a listener to receive direct dispatches of events. This interface can be used directly * by a listener (using {@link EventManager#register(Object, Class, short, EventHandler)} or @@ -15,5 +17,5 @@ package com.velocitypowered.api.event; @FunctionalInterface public interface EventHandler { - EventTask execute(E event); + @Nullable EventTask execute(E event); } diff --git a/api/src/main/java/com/velocitypowered/api/event/EventManager.java b/api/src/main/java/com/velocitypowered/api/event/EventManager.java index b1fd542db..81c9c7c6d 100644 --- a/api/src/main/java/com/velocitypowered/api/event/EventManager.java +++ b/api/src/main/java/com/velocitypowered/api/event/EventManager.java @@ -64,7 +64,9 @@ public interface EventManager { * * @param event the event to fire */ + @SuppressWarnings("FutureReturnValueIgnored") default void fireAndForget(Object event) { + // Calling fire(Object) and not handling it is intentional. fire(event); } diff --git a/api/src/main/java/com/velocitypowered/api/event/EventTask.java b/api/src/main/java/com/velocitypowered/api/event/EventTask.java index 6dad00e58..3f72820c4 100644 --- a/api/src/main/java/com/velocitypowered/api/event/EventTask.java +++ b/api/src/main/java/com/velocitypowered/api/event/EventTask.java @@ -174,6 +174,9 @@ public abstract class EventTask { * @param future The task to wait for * @return The event task */ + // The Error Prone annotation here is spurious. The Future is handled via the CompletableFuture + // API, which does NOT use the traditional blocking model. + @SuppressWarnings("FutureReturnValueIgnored") public static EventTask.WithContinuation resumeWhenComplete( final CompletableFuture future) { requireNonNull(future, "future"); diff --git a/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java b/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java index 0e4727c70..9be0d2eb7 100644 --- a/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java @@ -88,7 +88,7 @@ public interface ResultedEvent { private final @Nullable Component reason; - protected ComponentResult(@Nullable Component reason) { + private ComponentResult(@Nullable Component reason) { this.reason = reason; } diff --git a/api/src/main/java/com/velocitypowered/api/event/connection/ConnectionHandshakeEventImpl.java b/api/src/main/java/com/velocitypowered/api/event/connection/ConnectionHandshakeEventImpl.java index ba0f83dcb..0a2ddb61f 100644 --- a/api/src/main/java/com/velocitypowered/api/event/connection/ConnectionHandshakeEventImpl.java +++ b/api/src/main/java/com/velocitypowered/api/event/connection/ConnectionHandshakeEventImpl.java @@ -22,7 +22,7 @@ public final class ConnectionHandshakeEventImpl implements ConnectionHandshakeEv private final String originalHostname; private String currentHostname; private ComponentResult result; - private SocketAddress currentRemoteAddress; + private @Nullable SocketAddress currentRemoteAddress; public ConnectionHandshakeEventImpl(InboundConnection connection, String originalHostname) { @@ -59,7 +59,7 @@ public final class ConnectionHandshakeEventImpl implements ConnectionHandshakeEv } @Override - public void setCurrentRemoteHostAddress(SocketAddress address) { + public void setCurrentRemoteHostAddress(@Nullable SocketAddress address) { currentRemoteAddress = address; } diff --git a/api/src/main/java/com/velocitypowered/api/event/player/KickedFromServerEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/KickedFromServerEvent.java index 4156e9d98..d3040f3c0 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/KickedFromServerEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/KickedFromServerEvent.java @@ -130,7 +130,7 @@ public interface KickedFromServerEvent extends */ final class RedirectPlayer implements ServerKickResult { - private final Component message; + private final @Nullable Component message; private final RegisteredServer server; private RedirectPlayer(RegisteredServer server, @@ -148,7 +148,7 @@ public interface KickedFromServerEvent extends return server; } - public Component message() { + public @Nullable Component message() { return message; } diff --git a/api/src/main/java/com/velocitypowered/api/event/player/ServerPostConnectEventImpl.java b/api/src/main/java/com/velocitypowered/api/event/player/ServerPostConnectEventImpl.java index fad2ff268..a2c21e2dd 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/ServerPostConnectEventImpl.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/ServerPostConnectEventImpl.java @@ -19,7 +19,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; public class ServerPostConnectEventImpl implements ServerPostConnectEvent { private final Player player; - private final RegisteredServer previousServer; + private final @Nullable RegisteredServer previousServer; public ServerPostConnectEventImpl(Player player, @Nullable RegisteredServer previousServer) { diff --git a/api/src/main/java/com/velocitypowered/api/event/player/ServerPreConnectEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/ServerPreConnectEvent.java index 2c727a1d8..4ae52d828 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/ServerPreConnectEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/ServerPreConnectEvent.java @@ -98,7 +98,7 @@ public interface ServerPreConnectEvent extends ResultedEvent { private final int protocol; private final int snapshotProtocol; - private final String[] names; + private final ImmutableList names; /** * Represents the lowest supported version. @@ -127,7 +127,7 @@ public enum ProtocolVersion implements Ordered { } this.protocol = protocol; - this.names = names; + this.names = ImmutableList.copyOf(names); } /** @@ -146,7 +146,7 @@ public enum ProtocolVersion implements Ordered { * @return the version name */ public String versionIntroducedIn() { - return names[0]; + return names.get(0); } /** @@ -156,7 +156,7 @@ public enum ProtocolVersion implements Ordered { * @return the version name */ public String mostRecentSupportedVersion() { - return names[names.length - 1]; + return names.get(names.size() - 1); } /** diff --git a/api/src/main/java/com/velocitypowered/api/proxy/connection/InboundConnection.java b/api/src/main/java/com/velocitypowered/api/proxy/connection/InboundConnection.java index 0479dde12..2a5fa370d 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/connection/InboundConnection.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/connection/InboundConnection.java @@ -22,7 +22,7 @@ public interface InboundConnection { * * @return the player's remote address */ - SocketAddress remoteAddress(); + @Nullable SocketAddress remoteAddress(); /** * Returns the hostname that the user entered into the client, if applicable. diff --git a/api/src/main/java/com/velocitypowered/api/proxy/connection/Player.java b/api/src/main/java/com/velocitypowered/api/proxy/connection/Player.java index 66d08844d..17806c5ad 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/connection/Player.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/connection/Player.java @@ -148,7 +148,7 @@ public interface Player extends CommandSource, Identified, InboundConnection, * from the player, you should use the equivalent method on the instance returned by * {@link #connectedServer()}. * - * @inheritDoc + * {@inheritDoc} */ @Override boolean sendPluginMessage(PluginChannelId identifier, byte[] data); diff --git a/api/src/main/java/com/velocitypowered/api/proxy/server/QueryResponse.java b/api/src/main/java/com/velocitypowered/api/proxy/server/QueryResponse.java index 1a948ea15..2794e52bb 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/server/QueryResponse.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/server/QueryResponse.java @@ -33,14 +33,14 @@ public final class QueryResponse { private final int maxPlayers; private final String proxyHost; private final int proxyPort; - private final ImmutableCollection players; + private final ImmutableList players; private final String proxyVersion; - private final ImmutableCollection plugins; + private final ImmutableList plugins; @VisibleForTesting QueryResponse(String hostname, String gameVersion, String map, int onlinePlayers, - int maxPlayers, String proxyHost, int proxyPort, ImmutableCollection players, - String proxyVersion, ImmutableCollection plugins) { + int maxPlayers, String proxyHost, int proxyPort, ImmutableList players, + String proxyVersion, ImmutableList plugins) { this.hostname = hostname; this.gameVersion = gameVersion; this.map = map; diff --git a/api/src/main/java/com/velocitypowered/api/proxy/server/ServerPing.java b/api/src/main/java/com/velocitypowered/api/proxy/server/ServerPing.java index 19ffee6fc..403f0009e 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/server/ServerPing.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/server/ServerPing.java @@ -150,7 +150,7 @@ public final class ServerPing { private final List samplePlayers = new ArrayList<>(); private String modType = "FML"; private final List mods = new ArrayList<>(); - private Component description; + private @Nullable Component description; private @Nullable Favicon favicon; private boolean nullOutPlayers; private boolean nullOutModinfo; diff --git a/build.gradle b/build.gradle index 9f7823941..c8b25bf0d 100644 --- a/build.gradle +++ b/build.gradle @@ -9,12 +9,12 @@ buildscript { plugins { id 'java' - id "com.github.spotbugs" version "4.2.4" apply false + id "net.ltgt.errorprone" version "2.0.1" apply false id 'org.cadixdev.licenser' version '0.5.1' apply false } allprojects { - apply plugin: "com.github.spotbugs" + apply plugin: "net.ltgt.errorprone" group 'com.velocitypowered' version '2.0.0-SNAPSHOT' @@ -67,14 +67,4 @@ allprojects { junitXml.enabled = true } } - - tasks.withType(com.github.spotbugs.snom.SpotBugsTask) { - reports { - html { - enabled = true - destination = file("$buildDir/reports/spotbugs/main/spotbugs.html") - stylesheet = 'fancy-hist.xsl' - } - } - } } diff --git a/gradle/errorprone.gradle b/gradle/errorprone.gradle new file mode 100644 index 000000000..5f25920d2 --- /dev/null +++ b/gradle/errorprone.gradle @@ -0,0 +1,17 @@ +dependencies { + annotationProcessor("com.uber.nullaway:nullaway:0.9.1") + testAnnotationProcessor("com.uber.nullaway:nullaway:0.9.1") + errorprone("com.google.errorprone:error_prone_core:2.6.0") +} + +tasks.withType(JavaCompile).configureEach { + options.errorprone { + allErrorsAsWarnings = true + error("NullAway") + + option("NullAway:AnnotatedPackages", "com.velocitypowered") + option("NullAway:ExcludedClasses", + "com.velocitypowered.proxy.network.packet.clientbound.ClientboundJoinGamePacket," + + "com.velocitypowered.proxy.network.packet.clientbound.ClientboundRespawnPacket") + } +} \ No newline at end of file diff --git a/native/build.gradle b/native/build.gradle index b58547459..8a666e2ca 100644 --- a/native/build.gradle +++ b/native/build.gradle @@ -7,6 +7,7 @@ plugins { apply plugin: 'org.cadixdev.licenser' apply from: '../gradle/checkstyle.gradle' apply from: '../gradle/publish.gradle' +apply from: '../gradle/errorprone.gradle' java { sourceCompatibility = JavaVersion.VERSION_11 diff --git a/native/src/main/java/com/velocitypowered/natives/util/NativeCodeLoader.java b/native/src/main/java/com/velocitypowered/natives/util/NativeCodeLoader.java index 58175e77f..ed6e0e67f 100644 --- a/native/src/main/java/com/velocitypowered/natives/util/NativeCodeLoader.java +++ b/native/src/main/java/com/velocitypowered/natives/util/NativeCodeLoader.java @@ -20,6 +20,7 @@ package com.velocitypowered.natives.util; import java.util.List; import java.util.function.BooleanSupplier; import java.util.function.Supplier; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; public final class NativeCodeLoader implements Supplier { @@ -56,7 +57,7 @@ public final class NativeCodeLoader implements Supplier { private final Runnable setup; private final String name; private final Supplier object; - private T constructed; + private @MonotonicNonNull T constructed; Variant(BooleanSupplier possiblyAvailable, Runnable setup, String name, T object) { this(possiblyAvailable, setup, name, () -> object); diff --git a/proxy/build.gradle b/proxy/build.gradle index cb267dbfe..3e6703aea 100644 --- a/proxy/build.gradle +++ b/proxy/build.gradle @@ -7,6 +7,7 @@ plugins { apply plugin: 'org.cadixdev.licenser' apply from: '../gradle/checkstyle.gradle' +apply from: '../gradle/errorprone.gradle' apply plugin: 'com.github.johnrengelman.shadow' license { @@ -50,9 +51,8 @@ tasks.withType(Checkstyle) { } dependencies { - // Note: we depend on the API twice, first the main sourceset, and then the annotation processor. implementation project(':velocity-api') - implementation project(':velocity-api').sourceSets.ap.output + implementation project(':velocity-annotation-processor') implementation project(':velocity-native') implementation "io.netty:netty-codec:${nettyVersion}" diff --git a/proxy/src/main/java/com/velocitypowered/proxy/Metrics.java b/proxy/src/main/java/com/velocitypowered/proxy/Metrics.java index e927ef559..f1996d55c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/Metrics.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/Metrics.java @@ -17,6 +17,8 @@ package com.velocitypowered.proxy; +import com.google.common.base.Splitter; +import com.google.common.collect.Iterables; import com.velocitypowered.proxy.config.VelocityConfiguration; import java.io.File; import java.io.IOException; @@ -25,6 +27,7 @@ import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.annotation.Nullable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.bstats.MetricsBase; @@ -37,7 +40,7 @@ import org.bstats.json.JsonObjectBuilder; public class Metrics { - private MetricsBase metricsBase; + private @Nullable MetricsBase metricsBase; private Metrics(Logger logger, int serviceId, boolean defaultEnabled) { File configFile = Paths.get("plugins").resolve("bStats").resolve("config.txt").toFile(); @@ -85,7 +88,9 @@ public class Metrics { * @param chart The chart to add. */ public void addCustomChart(CustomChart chart) { - metricsBase.addCustomChart(chart); + if (metricsBase != null) { + metricsBase.addCustomChart(chart); + } } private void appendPlatformData(JsonObjectBuilder builder) { @@ -126,7 +131,7 @@ public class Metrics { // java.version system property to return $major[.$minor][.$security][-ea], as opposed to // 1.$major.0_$identifier we can handle pre-9 by checking if the "major" is equal to "1", // otherwise, 9+ - String majorVersion = javaVersion.split("\\.")[0]; + String majorVersion = Iterables.get(Splitter.on('.').split(javaVersion), 0); String release; int indexOf = javaVersion.lastIndexOf('.'); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java index 2b8763752..cf261c4fc 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java @@ -90,6 +90,7 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.IntFunction; import java.util.stream.Collectors; +import java.util.stream.Stream; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.audience.ForwardingAudience; import net.kyori.adventure.key.Key; @@ -193,8 +194,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience { cm.getBossGroup().terminationFuture().syncUninterruptibly(); } - @EnsuresNonNull({"serverKeyPair", "servers", "pluginManager", "eventManager", "scheduler", - "console", "cm", "configuration"}) + @EnsuresNonNull({"serverKeyPair", "eventManager", "console", "cm", "configuration"}) void start() { logger.info("Booting up {} {}...", version().getName(), version().getVersion()); console.setupStreams(); @@ -252,8 +252,8 @@ public class VelocityServer implements ProxyServer, ForwardingAudience { FileSystemUtils.visitResources(VelocityServer.class, path -> { logger.info("Loading localizations..."); - try { - Files.walk(path).forEach(file -> { + try (Stream stream = Files.walk(path)) { + stream.forEach(file -> { if (!Files.isRegularFile(file)) { return; } @@ -396,12 +396,18 @@ public class VelocityServer implements ProxyServer, ForwardingAudience { RegisteredServer next = player.getNextServerToTry(); if (next != null) { player.createConnectionRequest(next).connectWithIndication() - .whenComplete((success, ex) -> { - if (ex != null || success == null || !success) { + .thenAccept((success) -> { + if (success == null || !success) { player.disconnect(Component.text("Your server has been changed, but we could " + "not move you to any fallback servers.")); } latch.countDown(); + }) + .exceptionally(throwable -> { + player.disconnect(Component.text("Your server has been changed, but we could " + + "not move you to any fallback servers.")); + latch.countDown(); + return null; }); } else { latch.countDown(); @@ -426,8 +432,8 @@ public class VelocityServer implements ProxyServer, ForwardingAudience { } if (configuration.isQueryEnabled() && (!newConfiguration.isQueryEnabled() - || newConfiguration.getQueryPort() != configuration.getQueryPort() - && oldBind instanceof InetSocketAddress)) { + || ((newConfiguration.getQueryPort() != configuration.getQueryPort()) + && (oldBind instanceof InetSocketAddress)))) { this.cm.close(new InetSocketAddress( ((InetSocketAddress) oldBind).getHostString(), configuration.getQueryPort())); } @@ -444,7 +450,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience { } /** - * Shuts down the proxy, kicking players with the specified {@param reason}. + * Shuts down the proxy, kicking players with the specified {@code reason}. * * @param explicitExit whether the user explicitly shut down the proxy * @param reason message to kick online players with diff --git a/proxy/src/main/java/com/velocitypowered/proxy/command/builtin/GlistCommand.java b/proxy/src/main/java/com/velocitypowered/proxy/command/builtin/GlistCommand.java index 3e6cd2031..69f1565cf 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/command/builtin/GlistCommand.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/command/builtin/GlistCommand.java @@ -38,6 +38,7 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TranslatableComponent; import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.Style; public class GlistCommand { @@ -122,7 +123,7 @@ public class GlistCommand { NamedTextColor.DARK_AQUA)) .append(Component.text("(" + onServer.size() + ")", NamedTextColor.GRAY)) .append(Component.text(": ")) - .resetStyle(); + .style(Style.empty()); for (int i = 0; i < onServer.size(); i++) { Player player = onServer.get(i); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java b/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java index 6678d39e9..4c8dc2af9 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java @@ -592,18 +592,10 @@ public class VelocityConfiguration implements ProxyConfig { } } - private ForcedHosts(Map> forcedHosts) { - this.forcedHosts = forcedHosts; - } - private Map> getForcedHosts() { return forcedHosts; } - private void setForcedHosts(Map> forcedHosts) { - this.forcedHosts = forcedHosts; - } - @Override public String toString() { return "ForcedHosts{" diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java index 952274ace..fb09e6482 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java @@ -94,6 +94,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter { this.remoteAddress = channel.remoteAddress(); this.server = server; this.state = ProtocolStates.HANDSHAKE; + this.protocolVersion = ProtocolVersion.UNKNOWN; } @Override 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 944500e5f..3bc4cc762 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 @@ -51,6 +51,7 @@ import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.handler.timeout.ReadTimeoutException; import java.util.Collection; +import javax.annotation.Nullable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -204,10 +205,8 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler { RootCommandNode rootNode = commands.getRootNode(); if (server.configuration().isAnnounceProxyCommands()) { // Inject commands from the proxy. - RootCommandNode dispatcherRootNode = - (RootCommandNode) - filterNode(server.commandManager().getDispatcher().getRoot()); - assert dispatcherRootNode != null : "Filtering root node returned null."; + RootCommandNode dispatcherRootNode = filterRootNode(server.commandManager() + .getDispatcher().getRoot()); Collection> proxyNodes = dispatcherRootNode.getChildren(); for (CommandNode node : proxyNodes) { CommandNode existingServerChild = rootNode.getChild(node.getName()); @@ -228,6 +227,27 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler { return true; } + /** + * Creates a deep copy of the provided command node, but removes any node that are not accessible + * by the player (respecting the requirement of the node). This function is specialized for + * root command nodes, so as to get better safety guarantees. + * + * @param source source node + * @return filtered node + */ + private RootCommandNode filterRootNode(CommandNode source) { + RootCommandNode dest = new RootCommandNode<>(); + for (CommandNode sourceChild : source.getChildren()) { + CommandNode destChild = filterNode(sourceChild); + if (destChild == null) { + continue; + } + dest.addChild(destChild); + } + + return dest; + } + /** * Creates a deep copy of the provided command node, but removes any node that are not accessible * by the player (respecting the requirement of the node). @@ -235,32 +255,27 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler { * @param source source node * @return filtered node */ - private CommandNode filterNode(CommandNode source) { - CommandNode dest; - if (source instanceof RootCommandNode) { - dest = new RootCommandNode<>(); - } else { - if (source.getRequirement() != null) { - try { - if (!source.getRequirement().test(serverConn.player())) { - return null; - } - } catch (Throwable e) { - // swallow everything because plugins - logger.error( - "Requirement test for command node " + source + " encountered an exception", e); + private @Nullable CommandNode filterNode(CommandNode source) { + if (source.getRequirement() != null) { + try { + if (!source.getRequirement().test(serverConn.player())) { + return null; } + } catch (Throwable e) { + // swallow everything because plugins + logger.error( + "Requirement test for command node " + source + " encountered an exception", e); } - - ArgumentBuilder destChildBuilder = source.createBuilder(); - destChildBuilder.requires((commandSource) -> true); - if (destChildBuilder.getRedirect() != null) { - destChildBuilder.redirect(filterNode(destChildBuilder.getRedirect())); - } - - dest = destChildBuilder.build(); } + ArgumentBuilder destChildBuilder = source.createBuilder(); + destChildBuilder.requires((commandSource) -> true); + if (destChildBuilder.getRedirect() != null) { + destChildBuilder.redirect(filterNode(destChildBuilder.getRedirect())); + } + + CommandNode dest = destChildBuilder.build(); + for (CommandNode sourceChild : source.getChildren()) { CommandNode destChild = filterNode(sourceChild); if (destChild == null) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BungeeCordMessageResponder.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BungeeCordMessageResponder.java index c9b8e6cf2..14c12a2a7 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BungeeCordMessageResponder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BungeeCordMessageResponder.java @@ -85,21 +85,12 @@ public class BungeeCordMessageResponder { } } - private void processIp(ByteBufDataInput in) { + private void processIp() { ByteBuf buf = Unpooled.buffer(); ByteBufDataOutput out = new ByteBufDataOutput(buf); out.writeUTF("IP"); - SocketAddress address = player.remoteAddress(); - if (address instanceof InetSocketAddress) { - InetSocketAddress serverInetAddr = (InetSocketAddress) address; - out.writeUTF(serverInetAddr.getHostString()); - out.writeInt(serverInetAddr.getPort()); - } else { - out.writeUTF("unix://" + ((DomainSocketAddress) address).path()); - out.writeInt(0); - } - sendResponseOnConnection(buf); + sendIpOutput(player, buf, out); } private void processPlayerCount(ByteBufDataInput in) { @@ -243,20 +234,24 @@ public class BungeeCordMessageResponder { out.writeUTF("IPOther"); out.writeUTF(player.username()); - SocketAddress address = player.remoteAddress(); - if (address instanceof InetSocketAddress) { - InetSocketAddress serverInetAddr = (InetSocketAddress) address; - out.writeUTF(serverInetAddr.getHostString()); - out.writeInt(serverInetAddr.getPort()); - } else { - out.writeUTF("unix://" + ((DomainSocketAddress) address).path()); - out.writeInt(0); - } - - sendResponseOnConnection(buf); + sendIpOutput(player, buf, out); } } + private void sendIpOutput(Player player, ByteBuf buf, ByteBufDataOutput out) { + SocketAddress address = player.remoteAddress(); + if (address instanceof InetSocketAddress) { + InetSocketAddress serverInetAddr = (InetSocketAddress) address; + out.writeUTF(serverInetAddr.getHostString()); + out.writeInt(serverInetAddr.getPort()); + } else { + out.writeUTF("127.0.0.1"); + out.writeInt(0); + } + + sendResponseOnConnection(buf); + } + private void processServerIp(ByteBufDataInput in) { RegisteredServer info = proxy.server(in.readUTF()); if (info != null) { @@ -360,7 +355,7 @@ public class BungeeCordMessageResponder { this.processConnectOther(in); break; case "IP": - this.processIp(in); + this.processIp(); break; case "PlayerCount": this.processPlayerCount(in); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java index b15bf1aee..f2cfda23e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java @@ -46,6 +46,7 @@ import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import net.kyori.adventure.text.Component; +import org.checkerframework.checker.nullness.qual.Nullable; public class LoginSessionHandler implements MinecraftSessionHandler { @@ -147,7 +148,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler { } } - private static String cleanRemoteAddress(SocketAddress address) { + private static String cleanRemoteAddress(@Nullable SocketAddress address) { if (address instanceof InetSocketAddress) { String addressString = ((InetSocketAddress) address).getAddress().getHostAddress(); int ipv6ScopeIdx = addressString.indexOf('%'); 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 d77339b6f..048d55c1f 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 @@ -231,7 +231,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { } @Override - public SocketAddress remoteAddress() { + public @Nullable SocketAddress remoteAddress() { return connection.getRemoteAddress(); } @@ -272,7 +272,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { type == MessageType.CHAT ? ClientboundChatPacket.CHAT_TYPE : ClientboundChatPacket.SYSTEM_TYPE, - identity.uuid() + identity )); } @@ -296,7 +296,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { connection.write(new ClientboundChatPacket( object.toString(), ClientboundChatPacket.GAME_INFO_TYPE, - Identity.nil().uuid() + Identity.nil() )); } } @@ -564,8 +564,14 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { case CONNECTION_IN_PROGRESS: // Fatal case case CONNECTION_CANCELLED: - disconnect(status.failureReason() != null ? status.failureReason() - : res.message()); + Component disconnectReason = status.failureReason(); + if (disconnectReason == null) { + disconnectReason = res.message(); + if (disconnectReason == null) { + disconnectReason = ConnectionMessages.INTERNAL_SERVER_CONNECTION_ERROR; + } + } + disconnect(disconnectReason); break; case SERVER_DISCONNECTED: Component reason = status.failureReason() != null ? status.failureReason() @@ -595,7 +601,12 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { // In case someone gets creative, assume we want to disconnect the player. disconnect(friendlyReason); } - }, connection.eventLoop()); + }, connection.eventLoop()) + .exceptionally(throwable -> { + logger.error("Unable to handle server disconnection for {}", this, throwable); + disconnect(friendlyReason); + return null; + }); } /** @@ -689,7 +700,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { Player connectedPlayer = server.player(this.id()); server.unregisterConnection(this); - DisconnectEventImpl.LoginStatus status; + LoginStatus status; if (connectedPlayer != null) { if (connectedPlayer.connectedServer() != null) { status = LoginStatus.PRE_SERVER_JOIN; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java index 68d411422..f95eb9f22 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java @@ -39,6 +39,7 @@ import com.velocitypowered.proxy.network.registry.state.ProtocolStates; import io.netty.buffer.ByteBuf; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.util.Objects; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -140,8 +141,9 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler { return; } - if (!event.result().isAllowed()) { - ic.disconnectQuietly(event.result().reason()); + @Nullable Component disconnectReason = event.result().reason(); + if (disconnectReason != null) { + ic.disconnectQuietly(disconnectReason); } else { // if the handshake is changed, propagate the change if (!event.currentHostname().equals(event.originalHostname())) { @@ -232,8 +234,8 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler { } @Override - public InetSocketAddress remoteAddress() { - return (InetSocketAddress) connection.getRemoteAddress(); + public @Nullable SocketAddress remoteAddress() { + return connection.getRemoteAddress(); } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialInboundConnection.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialInboundConnection.java index 0d4586629..448cf69ce 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialInboundConnection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialInboundConnection.java @@ -51,12 +51,12 @@ public final class InitialInboundConnection implements InboundConnection, } @Override - public SocketAddress remoteAddress() { + public @Nullable SocketAddress remoteAddress() { return connection.getRemoteAddress(); } @Override - public @Nullable InetSocketAddress connectedHostname() { + public InetSocketAddress connectedHostname() { return InetSocketAddress.createUnresolved(cleanedHostname, handshake.getPort()); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/StatusSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/StatusSessionHandler.java index 2dc9635bc..ad2e74b70 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/StatusSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/StatusSessionHandler.java @@ -228,9 +228,4 @@ public class StatusSessionHandler implements MinecraftSessionHandler { // what even is going on? connection.close(true); } - - private enum State { - AWAITING_REQUEST, - RECEIVED_REQUEST - } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeHandshakeClientPhase.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeHandshakeClientPhase.java index a1ec8a663..748925f86 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeHandshakeClientPhase.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeHandshakeClientPhase.java @@ -191,7 +191,7 @@ public enum LegacyForgeHandshakeClientPhase implements ClientConnectionPhase { * {@link #nextPhase()}. A null indicates there is no * further phase to transition to. */ - LegacyForgeHandshakeClientPhase(Integer packetToAdvanceOn) { + LegacyForgeHandshakeClientPhase(@Nullable Integer packetToAdvanceOn) { this.packetToAdvanceOn = packetToAdvanceOn; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionInfo.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionInfo.java index 8c7abd8cf..373b66b17 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionInfo.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionInfo.java @@ -23,7 +23,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; public final class DimensionInfo { private final String registryIdentifier; - private final String levelName; + private final @Nullable String levelName; private final boolean isFlat; private final boolean isDebugType; @@ -60,4 +60,14 @@ public final class DimensionInfo { public String getRegistryIdentifier() { return registryIdentifier; } + + @Override + public String toString() { + return "DimensionInfo{" + + "registryIdentifier='" + registryIdentifier + '\'' + + ", levelName='" + levelName + '\'' + + ", isFlat=" + isFlat + + ", isDebugType=" + isDebugType + + '}'; + } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionRegistry.java index 28c4c84c5..758e79ab3 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionRegistry.java @@ -118,4 +118,9 @@ public final class DimensionRegistry { } return mappings.build(); } + + @Override + public String toString() { + return levelNames.toString(); + } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/event/UntargetedEventHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/event/UntargetedEventHandler.java index a0fb6376a..aa6f0ff7e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/event/UntargetedEventHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/event/UntargetedEventHandler.java @@ -18,15 +18,16 @@ package com.velocitypowered.proxy.event; import com.velocitypowered.api.event.EventTask; +import org.checkerframework.checker.nullness.qual.Nullable; public interface UntargetedEventHandler { - EventTask execute(Object targetInstance, Object event); + @Nullable EventTask execute(Object targetInstance, Object event); - interface Void extends UntargetedEventHandler { + interface VoidHandler extends UntargetedEventHandler { @Override - default EventTask execute(final Object targetInstance, final Object event) { + default @Nullable EventTask execute(final Object targetInstance, final Object event) { executeVoid(targetInstance, event); return null; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/event/VelocityEventManager.java b/proxy/src/main/java/com/velocitypowered/proxy/event/VelocityEventManager.java index 27fbf639a..e544deb68 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/event/VelocityEventManager.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/event/VelocityEventManager.java @@ -21,6 +21,7 @@ import static java.util.Objects.requireNonNull; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; +import com.google.common.base.VerifyException; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.reflect.TypeToken; @@ -32,6 +33,7 @@ import com.velocitypowered.api.event.EventTask; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.plugin.PluginContainer; import com.velocitypowered.api.plugin.PluginManager; +import com.velocitypowered.proxy.event.UntargetedEventHandler.VoidHandler; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.lang.reflect.Method; @@ -67,8 +69,8 @@ public class VelocityEventManager implements EventManager { private static final MethodHandles.Lookup methodHandlesLookup = MethodHandles.lookup(); private static final LambdaType untargetedHandlerType = LambdaType.of(UntargetedEventHandler.class); - private static final LambdaType untargetedVoidHandlerType = - LambdaType.of(UntargetedEventHandler.Void.class); + private static final LambdaType untargetedVoidHandlerType = + LambdaType.of(VoidHandler.class); private static final Comparator handlerComparator = Comparator.comparingInt(o -> o.order); @@ -77,7 +79,7 @@ public class VelocityEventManager implements EventManager { private final PluginManager pluginManager; private final Multimap, HandlerRegistration> handlersByType = HashMultimap.create(); - private final LoadingCache, @Nullable HandlersCache> handlersCache = + private final LoadingCache, HandlersCache> handlersCache = Caffeine.newBuilder().build(this::bakeHandlers); private final LoadingCache untargetedMethodHandlers = @@ -341,9 +343,12 @@ public class VelocityEventManager implements EventManager { info.method.getName(), info.method.getDeclaringClass().getName(), info.errors); continue; } - final UntargetedEventHandler untargetedHandler = - untargetedMethodHandlers.get(info.method); + final UntargetedEventHandler untargetedHandler = untargetedMethodHandlers.get(info.method); assert untargetedHandler != null; + if (info.eventType == null) { + throw new VerifyException("Event type is not present and there are no errors"); + } + final EventHandler handler = event -> untargetedHandler.execute(listener, event); registrations.add(new HandlerRegistration(pluginContainer, info.order, info.eventType, listener, handler, info.asyncType)); @@ -456,7 +461,12 @@ public class VelocityEventManager implements EventManager { private final boolean currentlyAsync; private final E event; + // This field is modified via a VarHandle, so this field is used and cannot be final. + @SuppressWarnings({"UnusedVariable", "FieldMayBeFinal"}) private volatile int state = TASK_STATE_DEFAULT; + + // This field is modified via a VarHandle, so this field is used and cannot be final. + @SuppressWarnings({"UnusedVariable", "FieldMayBeFinal"}) private volatile boolean resumed = false; private ContinuationTask( diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/ProtocolUtils.java b/proxy/src/main/java/com/velocitypowered/proxy/network/ProtocolUtils.java index c855cb8ce..411b1c74f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/ProtocolUtils.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/ProtocolUtils.java @@ -95,7 +95,7 @@ public enum ProtocolUtils { int maxRead = Math.min(5, buf.readableBytes()); for (int j = 0; j < maxRead; j++) { int k = buf.readByte(); - i |= (k & 0x7F) << j * 7; + i |= (k & 0x7F) << (j * 7); if ((k & 0x80) != 128) { return i; } @@ -123,7 +123,7 @@ public enum ProtocolUtils { if ((value & (0xFFFFFFFF << 7)) == 0) { buf.writeByte(value); } else if ((value & (0xFFFFFFFF << 14)) == 0) { - int w = (value & 0x7F | 0x80) << 8 | (value >>> 7); + int w = ((value & 0x7F) | 0x80) << 8 | (value >>> 7); buf.writeShort(w); } else { writeVarIntFull(buf, value); @@ -135,18 +135,19 @@ public enum ProtocolUtils { if ((value & (0xFFFFFFFF << 7)) == 0) { buf.writeByte(value); } else if ((value & (0xFFFFFFFF << 14)) == 0) { - int w = (value & 0x7F | 0x80) << 8 | (value >>> 7); + int w = (((value & 0x7F) | 0x80) << 8) | (value >>> 7); buf.writeShort(w); } else if ((value & (0xFFFFFFFF << 21)) == 0) { - int w = (value & 0x7F | 0x80) << 16 | ((value >>> 7) & 0x7F | 0x80) << 8 | (value >>> 14); + int w = + (((value & 0x7F) | 0x80) << 16) | ((((value >>> 7) & 0x7F) | 0x80) << 8) | (value >>> 14); buf.writeMedium(w); } else if ((value & (0xFFFFFFFF << 28)) == 0) { - int w = (value & 0x7F | 0x80) << 24 | (((value >>> 7) & 0x7F | 0x80) << 16) - | ((value >>> 14) & 0x7F | 0x80) << 8 | (value >>> 21); + int w = (((value & 0x7F) | 0x80) << 24) | ((((value >>> 7) & 0x7F) | 0x80) << 16) + | ((((value >>> 14) & 0x7F) | 0x80) << 8) | (value >>> 21); buf.writeInt(w); } else { - int w = (value & 0x7F | 0x80) << 24 | ((value >>> 7) & 0x7F | 0x80) << 16 - | ((value >>> 14) & 0x7F | 0x80) << 8 | ((value >>> 21) & 0x7F | 0x80); + int w = (((value & 0x7F) | 0x80) << 24) | ((((value >>> 7) & 0x7F) | 0x80) << 16) + | ((((value >>> 14) & 0x7F) | 0x80) << 8) | (((value >>> 21) & 0x7F) | 0x80); buf.writeInt(w); buf.writeByte(value >>> 28); } @@ -160,7 +161,8 @@ public enum ProtocolUtils { */ public static void write21BitVarInt(ByteBuf buf, int value) { // See https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/ - int w = (value & 0x7F | 0x80) << 16 | ((value >>> 7) & 0x7F | 0x80) << 8 | (value >>> 14); + int w = + (((value & 0x7F) | 0x80) << 16) | ((((value >>> 7) & 0x7F) | 0x80) << 8) | (value >>> 14); buf.writeMedium(w); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/TransportType.java b/proxy/src/main/java/com/velocitypowered/proxy/network/TransportType.java index 695729feb..7a96fb114 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/TransportType.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/TransportType.java @@ -42,6 +42,7 @@ import io.netty.channel.unix.ServerDomainSocketChannel; import java.net.SocketAddress; import java.util.concurrent.ThreadFactory; import java.util.function.BiFunction; +import org.checkerframework.checker.nullness.qual.Nullable; enum TransportType { NIO("NIO", NioServerSocketChannel::new, @@ -61,16 +62,16 @@ enum TransportType { final ChannelFactory serverSocketChannelFactory; final ChannelFactory socketChannelFactory; final ChannelFactory datagramChannelFactory; - final ChannelFactory domainServerSocketChannelFactory; - final ChannelFactory domainSocketChannelFactory; + final @Nullable ChannelFactory domainServerSocketChannelFactory; + final @Nullable ChannelFactory domainSocketChannelFactory; final BiFunction eventLoopGroupFactory; TransportType(final String name, final ChannelFactory serverSocketChannelFactory, final ChannelFactory socketChannelFactory, final ChannelFactory datagramChannelFactory, - final ChannelFactory domainServerSocketChannelFactory, - final ChannelFactory domainSocketChannelFactory, + @Nullable final ChannelFactory domainServerSocketChannelFactory, + @Nullable final ChannelFactory domainSocketChannelFactory, final BiFunction eventLoopGroupFactory) { this.name = name; this.serverSocketChannelFactory = serverSocketChannelFactory; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/AbstractPluginMessagePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/AbstractPluginMessagePacket.java index 154a8f3f5..8f479cdac 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/AbstractPluginMessagePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/AbstractPluginMessagePacket.java @@ -20,6 +20,7 @@ package com.velocitypowered.proxy.network.packet; import static com.velocitypowered.proxy.network.PluginMessageUtil.transformLegacyToModernChannel; import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.network.ProtocolUtils; import com.velocitypowered.proxy.network.buffer.TypedDefaultByteBufHolder; @@ -60,18 +61,14 @@ public abstract class AbstractPluginMessagePacket { static

PacketReader

method(final Supplier

factory) { return (buf, version) -> { final P packet = factory.get(); - packet.decode(buf, null, version); + packet.decode(buf, version); return packet; }; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundAvailableCommandsPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundAvailableCommandsPacket.java index 259dfd4d4..8005c993d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundAvailableCommandsPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundAvailableCommandsPacket.java @@ -37,7 +37,6 @@ import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.network.ProtocolUtils; import com.velocitypowered.proxy.network.packet.Packet; -import com.velocitypowered.proxy.network.packet.PacketDirection; import com.velocitypowered.proxy.network.packet.PacketHandler; import com.velocitypowered.proxy.network.packet.PacketReader; import com.velocitypowered.proxy.network.packet.PacketWriter; @@ -84,7 +83,7 @@ public class ClientboundAvailableCommandsPacket implements Packet { } @Override - public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion protocolVersion) { + public void decode(ByteBuf buf, ProtocolVersion protocolVersion) { int commands = ProtocolUtils.readVarInt(buf); WireNode[] wireNodes = new WireNode[commands]; for (int i = 0; i < commands; i++) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundBossBarPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundBossBarPacket.java index d31faf043..f792808f6 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundBossBarPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundBossBarPacket.java @@ -21,7 +21,6 @@ import com.google.common.base.MoreObjects; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.network.ProtocolUtils; import com.velocitypowered.proxy.network.packet.Packet; -import com.velocitypowered.proxy.network.packet.PacketDirection; import com.velocitypowered.proxy.network.packet.PacketHandler; import com.velocitypowered.proxy.network.packet.PacketReader; import com.velocitypowered.proxy.network.packet.PacketWriter; @@ -109,7 +108,7 @@ public class ClientboundBossBarPacket implements Packet { } @Override - public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) { + public void decode(ByteBuf buf, ProtocolVersion version) { this.uuid = ProtocolUtils.readUuid(buf); this.action = ProtocolUtils.readVarInt(buf); switch (action) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundChatPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundChatPacket.java index 0208e7049..9b72311ec 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundChatPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundChatPacket.java @@ -21,60 +21,40 @@ import com.google.common.base.MoreObjects; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.network.ProtocolUtils; import com.velocitypowered.proxy.network.packet.Packet; -import com.velocitypowered.proxy.network.packet.PacketDirection; import com.velocitypowered.proxy.network.packet.PacketHandler; import com.velocitypowered.proxy.network.packet.PacketReader; import com.velocitypowered.proxy.network.packet.PacketWriter; import io.netty.buffer.ByteBuf; import java.util.UUID; +import net.kyori.adventure.identity.Identity; import org.checkerframework.checker.nullness.qual.Nullable; public class ClientboundChatPacket implements Packet { - public static final PacketReader DECODER = PacketReader.method(ClientboundChatPacket::new); - public static final PacketWriter ENCODER = PacketWriter.deprecatedEncode(); + public static final PacketReader DECODER = PacketReader.unsupported(); + public static final PacketWriter ENCODER = (out, packet, version) -> { + ProtocolUtils.writeString(out, packet.message); + if (version.gte(ProtocolVersion.MINECRAFT_1_8)) { + out.writeByte(packet.type); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { + ProtocolUtils.writeUuid(out, packet.sender.uuid()); + } + } + }; public static final byte CHAT_TYPE = (byte) 0; public static final byte SYSTEM_TYPE = (byte) 1; public static final byte GAME_INFO_TYPE = (byte) 2; - private @Nullable String message; + private String message; private byte type; - private @Nullable UUID sender; + private Identity sender; - private ClientboundChatPacket() { - } - - public ClientboundChatPacket(String message, byte type, UUID sender) { + public ClientboundChatPacket(String message, byte type, Identity sender) { this.message = message; this.type = type; this.sender = sender; } - @Override - public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) { - message = ProtocolUtils.readString(buf); - if (version.gte(ProtocolVersion.MINECRAFT_1_8)) { - type = buf.readByte(); - if (version.gte(ProtocolVersion.MINECRAFT_1_16)) { - sender = ProtocolUtils.readUuid(buf); - } - } - } - - @Override - public void encode(ByteBuf buf, ProtocolVersion version) { - if (message == null) { - throw new IllegalStateException("Message is not specified"); - } - ProtocolUtils.writeString(buf, message); - if (version.gte(ProtocolVersion.MINECRAFT_1_8)) { - buf.writeByte(type); - if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { - ProtocolUtils.writeUuid(buf, sender); - } - } - } - @Override public boolean handle(PacketHandler handler) { return handler.handle(this); @@ -91,10 +71,6 @@ public class ClientboundChatPacket implements Packet { return type; } - public UUID getSenderUuid() { - return sender; - } - @Override public String toString() { return MoreObjects.toStringHelper(this) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundEncryptionRequestPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundEncryptionRequestPacket.java index 95054d742..08fe4f4f1 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundEncryptionRequestPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundEncryptionRequestPacket.java @@ -23,7 +23,6 @@ import com.google.common.base.MoreObjects; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.network.ProtocolUtils; import com.velocitypowered.proxy.network.packet.Packet; -import com.velocitypowered.proxy.network.packet.PacketDirection; import com.velocitypowered.proxy.network.packet.PacketHandler; import com.velocitypowered.proxy.network.packet.PacketReader; import com.velocitypowered.proxy.network.packet.PacketWriter; @@ -54,7 +53,7 @@ public class ClientboundEncryptionRequestPacket implements Packet { } @Override - public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) { + public void decode(ByteBuf buf, ProtocolVersion version) { this.serverId = ProtocolUtils.readString(buf, 20); if (version.gte(ProtocolVersion.MINECRAFT_1_8)) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundJoinGamePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundJoinGamePacket.java index bce9a5806..e027a851e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundJoinGamePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundJoinGamePacket.java @@ -24,7 +24,6 @@ import com.velocitypowered.proxy.connection.registry.DimensionInfo; import com.velocitypowered.proxy.connection.registry.DimensionRegistry; import com.velocitypowered.proxy.network.ProtocolUtils; import com.velocitypowered.proxy.network.packet.Packet; -import com.velocitypowered.proxy.network.packet.PacketDirection; import com.velocitypowered.proxy.network.packet.PacketHandler; import com.velocitypowered.proxy.network.packet.PacketReader; import com.velocitypowered.proxy.network.packet.PacketWriter; @@ -35,6 +34,9 @@ import net.kyori.adventure.nbt.CompoundBinaryTag; import net.kyori.adventure.nbt.ListBinaryTag; import org.checkerframework.checker.nullness.qual.Nullable; +// TODO: This class is in dire need of a refactor. Suppressing the warning is only done as an +// implicit acknowledgement that this code is very bad. +@SuppressWarnings("WarnAway") public class ClientboundJoinGamePacket implements Packet { public static final PacketReader DECODER = PacketReader.method(ClientboundJoinGamePacket::new); public static final PacketWriter ENCODER = PacketWriter.deprecatedEncode(); @@ -188,7 +190,7 @@ public class ClientboundJoinGamePacket implements Packet { } @Override - public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) { + public void decode(ByteBuf buf, ProtocolVersion version) { this.entityId = buf.readInt(); if (version.gte(ProtocolVersion.MINECRAFT_1_16_2)) { this.isHardcore = buf.readBoolean(); @@ -196,7 +198,7 @@ public class ClientboundJoinGamePacket implements Packet { } else { this.gamemode = buf.readByte(); this.isHardcore = (this.gamemode & 0x08) != 0; - this.gamemode &= ~0x08; + this.gamemode &= (short) (this.gamemode & ~0x08); } String dimensionIdentifier = null; String levelName = null; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundLoginPluginMessagePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundLoginPluginMessagePacket.java index c2b6c343d..9945d0b81 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundLoginPluginMessagePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundLoginPluginMessagePacket.java @@ -84,7 +84,7 @@ public class ClientboundLoginPluginMessagePacket extends DefaultByteBufHolder im if (this == other) { return true; } - if (other == null || this.getClass() != other.getClass()) { + if (!(other instanceof ClientboundLoginPluginMessagePacket)) { return false; } final ClientboundLoginPluginMessagePacket that = (ClientboundLoginPluginMessagePacket) other; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundPlayerListItemPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundPlayerListItemPacket.java index 088bb2fdf..0c3a5fcf5 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundPlayerListItemPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundPlayerListItemPacket.java @@ -18,13 +18,13 @@ package com.velocitypowered.proxy.network.packet.clientbound; import com.google.common.base.MoreObjects; +import com.google.common.base.VerifyException; import com.google.common.collect.ImmutableList; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.player.TabListEntry; import com.velocitypowered.api.util.GameProfile; import com.velocitypowered.proxy.network.ProtocolUtils; import com.velocitypowered.proxy.network.packet.Packet; -import com.velocitypowered.proxy.network.packet.PacketDirection; import com.velocitypowered.proxy.network.packet.PacketHandler; import com.velocitypowered.proxy.network.packet.PacketReader; import com.velocitypowered.proxy.network.packet.PacketWriter; @@ -65,7 +65,7 @@ public class ClientboundPlayerListItemPacket implements Packet { } @Override - public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) { + public void decode(ByteBuf buf, ProtocolVersion version) { if (version.gte(ProtocolVersion.MINECRAFT_1_8)) { action = ProtocolUtils.readVarInt(buf); int length = ProtocolUtils.readVarInt(buf); @@ -121,7 +121,9 @@ public class ClientboundPlayerListItemPacket implements Packet { ProtocolUtils.writeVarInt(buf, items.size()); for (Item item : items) { UUID uuid = item.getUuid(); - assert uuid != null : "UUID-less entry serialization attempt - 1.7 component!"; + if (uuid == null) { + throw new VerifyException("UUID-less entry serialization attempt - 1.7 component!"); + } ProtocolUtils.writeUuid(buf, uuid); switch (action) { @@ -189,7 +191,7 @@ public class ClientboundPlayerListItemPacket implements Packet { public static class Item { - private final UUID uuid; + private final @Nullable UUID uuid; private String name = ""; private List properties = ImmutableList.of(); private int gameMode; @@ -200,7 +202,7 @@ public class ClientboundPlayerListItemPacket implements Packet { uuid = null; } - public Item(UUID uuid) { + public Item(@Nullable UUID uuid) { this.uuid = uuid; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundRespawnPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundRespawnPacket.java index d48a4c5ed..c66b1e096 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundRespawnPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundRespawnPacket.java @@ -23,14 +23,17 @@ import com.velocitypowered.proxy.connection.registry.DimensionData; import com.velocitypowered.proxy.connection.registry.DimensionInfo; import com.velocitypowered.proxy.network.ProtocolUtils; import com.velocitypowered.proxy.network.packet.Packet; -import com.velocitypowered.proxy.network.packet.PacketDirection; import com.velocitypowered.proxy.network.packet.PacketHandler; import com.velocitypowered.proxy.network.packet.PacketReader; import com.velocitypowered.proxy.network.packet.PacketWriter; import io.netty.buffer.ByteBuf; import net.kyori.adventure.nbt.BinaryTagIO; import net.kyori.adventure.nbt.CompoundBinaryTag; +import org.checkerframework.checker.nullness.qual.Nullable; +// TODO: This class is in dire need of a refactor. Suppressing the warning is only done as an +// implicit acknowledgement that this code is very bad. +@SuppressWarnings("WarnAway") public class ClientboundRespawnPacket implements Packet { public static final PacketReader DECODER = PacketReader.method(ClientboundRespawnPacket::new); public static final PacketWriter ENCODER = PacketWriter.deprecatedEncode(); @@ -49,13 +52,14 @@ public class ClientboundRespawnPacket implements Packet { } public ClientboundRespawnPacket(int dimension, long partialHashedSeed, short difficulty, short gamemode, - String levelType, boolean shouldKeepPlayerData, DimensionInfo dimensionInfo, - short previousGamemode, DimensionData currentDimensionData) { + @Nullable String levelType, boolean shouldKeepPlayerData, + DimensionInfo dimensionInfo, short previousGamemode, + DimensionData currentDimensionData) { this.dimension = dimension; this.partialHashedSeed = partialHashedSeed; this.difficulty = difficulty; this.gamemode = gamemode; - this.levelType = levelType; + this.levelType = levelType == null ? "" : levelType; this.shouldKeepPlayerData = shouldKeepPlayerData; this.dimensionInfo = dimensionInfo; this.previousGamemode = previousGamemode; @@ -119,7 +123,7 @@ public class ClientboundRespawnPacket implements Packet { } @Override - public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) { + public void decode(ByteBuf buf, ProtocolVersion version) { String dimensionIdentifier = null; String levelName = null; if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundStatusResponsePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundStatusResponsePacket.java index 40b785c71..5a1d9200a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundStatusResponsePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundStatusResponsePacket.java @@ -35,20 +35,12 @@ public class ClientboundStatusResponsePacket implements Packet { public static final PacketWriter ENCODER = (buf, packet, version) -> ProtocolUtils.writeString(buf, packet.status); - private final @Nullable CharSequence status; + private final CharSequence status; public ClientboundStatusResponsePacket(CharSequence status) { this.status = status; } - @Override - public void encode(ByteBuf buf, ProtocolVersion version) { - if (status == null) { - throw new IllegalStateException("Status is not specified"); - } - ProtocolUtils.writeString(buf, status); - } - @Override public boolean handle(PacketHandler handler) { return handler.handle(this); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundTabCompleteResponsePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundTabCompleteResponsePacket.java index 0f9ab6e63..98115e591 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundTabCompleteResponsePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/clientbound/ClientboundTabCompleteResponsePacket.java @@ -21,7 +21,6 @@ import com.google.common.base.MoreObjects; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.network.ProtocolUtils; import com.velocitypowered.proxy.network.packet.Packet; -import com.velocitypowered.proxy.network.packet.PacketDirection; import com.velocitypowered.proxy.network.packet.PacketHandler; import com.velocitypowered.proxy.network.packet.PacketReader; import com.velocitypowered.proxy.network.packet.PacketWriter; @@ -69,7 +68,7 @@ public class ClientboundTabCompleteResponsePacket implements Packet { } @Override - public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) { + public void decode(ByteBuf buf, ProtocolVersion version) { if (version.gte(ProtocolVersion.MINECRAFT_1_13)) { this.transactionId = ProtocolUtils.readVarInt(buf); this.start = ProtocolUtils.readVarInt(buf); @@ -146,7 +145,7 @@ public class ClientboundTabCompleteResponsePacket implements Packet { if (this == o) { return true; } - if (o == null || getClass() != o.getClass()) { + if (!(o instanceof Offer)) { return false; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundClientSettingsPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundClientSettingsPacket.java index 7cdba5d85..76f7edd1b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundClientSettingsPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundClientSettingsPacket.java @@ -21,7 +21,6 @@ import com.google.common.base.MoreObjects; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.network.ProtocolUtils; import com.velocitypowered.proxy.network.packet.Packet; -import com.velocitypowered.proxy.network.packet.PacketDirection; import com.velocitypowered.proxy.network.packet.PacketHandler; import com.velocitypowered.proxy.network.packet.PacketReader; import com.velocitypowered.proxy.network.packet.PacketWriter; @@ -54,7 +53,7 @@ public class ServerboundClientSettingsPacket implements Packet { } @Override - public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) { + public void decode(ByteBuf buf, ProtocolVersion version) { this.locale = ProtocolUtils.readString(buf, 16); this.viewDistance = buf.readByte(); this.chatVisibility = ProtocolUtils.readVarInt(buf); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundLoginPluginResponsePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundLoginPluginResponsePacket.java index 029c9f2fe..b1f54613b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundLoginPluginResponsePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundLoginPluginResponsePacket.java @@ -87,12 +87,12 @@ public class ServerboundLoginPluginResponsePacket extends DefaultByteBufHolder i if (this == other) { return true; } - if (other == null || this.getClass() != other.getClass()) { + if (!(other instanceof ServerboundLoginPluginResponsePacket)) { return false; } final ServerboundLoginPluginResponsePacket that = (ServerboundLoginPluginResponsePacket) other; return this.id == that.id - && Objects.equals(this.success, that.success) + && this.success == that.success && super.equals(other); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundResourcePackResponsePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundResourcePackResponsePacket.java index 97b8bbfc7..1a68ef0b7 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundResourcePackResponsePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundResourcePackResponsePacket.java @@ -52,7 +52,7 @@ public class ServerboundResourcePackResponsePacket implements Packet { @Override public void encode(ByteBuf buf, ProtocolVersion protocolVersion) { if (protocolVersion.lte(ProtocolVersion.MINECRAFT_1_9_4)) { - ProtocolUtils.writeString(buf, hash); + ProtocolUtils.writeString(buf, hash == null ? "" : hash); } ProtocolUtils.writeVarInt(buf, status.ordinal()); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundTabCompleteRequestPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundTabCompleteRequestPacket.java index 973ca4d48..f09e19601 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundTabCompleteRequestPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/packet/serverbound/ServerboundTabCompleteRequestPacket.java @@ -25,7 +25,6 @@ import com.google.common.base.MoreObjects; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.network.ProtocolUtils; import com.velocitypowered.proxy.network.packet.Packet; -import com.velocitypowered.proxy.network.packet.PacketDirection; import com.velocitypowered.proxy.network.packet.PacketHandler; import com.velocitypowered.proxy.network.packet.PacketReader; import com.velocitypowered.proxy.network.packet.PacketWriter; @@ -88,7 +87,7 @@ public class ServerboundTabCompleteRequestPacket implements Packet { } @Override - public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) { + public void decode(ByteBuf buf, ProtocolVersion version) { if (version.gte(MINECRAFT_1_13)) { this.transactionId = ProtocolUtils.readVarInt(buf); this.command = ProtocolUtils.readString(buf, VANILLA_MAX_TAB_COMPLETE_LEN); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/pipeline/VarintByteDecoder.java b/proxy/src/main/java/com/velocitypowered/proxy/network/pipeline/VarintByteDecoder.java index e2cdb8345..03f9ff73a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/pipeline/VarintByteDecoder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/pipeline/VarintByteDecoder.java @@ -27,7 +27,7 @@ class VarintByteDecoder implements ByteProcessor { @Override public boolean process(byte k) { - readVarint |= (k & 0x7F) << bytesRead++ * 7; + readVarint |= (k & 0x7F) << (bytesRead++ * 7); if (bytesRead > 3) { result = DecodeResult.TOO_BIG; return false; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/RegularPacketRegistryMap.java b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/RegularPacketRegistryMap.java index 0203acc0b..65291592b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/RegularPacketRegistryMap.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/packet/RegularPacketRegistryMap.java @@ -27,7 +27,6 @@ import io.netty.buffer.ByteBuf; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.checkerframework.checker.nullness.qual.Nullable; @@ -85,7 +84,7 @@ public class RegularPacketRegistryMap implements PacketRegistryMap { @Override public @Nullable Class lookupPacket(int id) { - for (Entry> entry : this.classesById.object2IntEntrySet()) { + for (Object2IntMap.Entry> entry : this.classesById.object2IntEntrySet()) { if (entry.getIntValue() == id) { return (Class) entry.getKey(); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/protocol/VersionSpecificProtocolRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/protocol/VersionSpecificProtocolRegistry.java index f8db927b3..41b9ca24a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/protocol/VersionSpecificProtocolRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/protocol/VersionSpecificProtocolRegistry.java @@ -19,6 +19,7 @@ package com.velocitypowered.proxy.network.registry.protocol; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.network.packet.PacketDirection; +import com.velocitypowered.proxy.network.registry.packet.EmptyPacketRegistryMap; import com.velocitypowered.proxy.network.registry.packet.PacketRegistryMap; import java.util.EnumMap; import java.util.EnumSet; @@ -49,9 +50,9 @@ public class VersionSpecificProtocolRegistry implements ProtocolRegistry { @Override public PacketRegistryMap lookup(PacketDirection direction, ProtocolVersion version) { if (direction == PacketDirection.SERVERBOUND) { - return this.serverboundByVersion.get(version); + return this.serverboundByVersion.getOrDefault(version, EmptyPacketRegistryMap.INSTANCE); } else if (direction == PacketDirection.CLIENTBOUND) { - return this.clientboundByVersion.get(version); + return this.clientboundByVersion.getOrDefault(version, EmptyPacketRegistryMap.INSTANCE); } else { throw new NullPointerException("direction"); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/PlayPacketRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/PlayPacketRegistry.java index 5cd4810b8..6abece2df 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/PlayPacketRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/registry/state/PlayPacketRegistry.java @@ -311,6 +311,7 @@ class PlayPacketRegistry implements ProtocolRegistry { public final PacketRegistry clientbound; public final PacketRegistry serverbound; + @Override public PacketRegistryMap lookup(PacketDirection direction, ProtocolVersion version) { return (direction == PacketDirection.SERVERBOUND ? this.serverbound : this.clientbound) @@ -319,24 +320,21 @@ class PlayPacketRegistry implements ProtocolRegistry { public static class PacketRegistry { - private final PacketDirection direction; - private final Map versions; + private final Map versions; PacketRegistry(PacketDirection direction) { - this.direction = direction; - - Map mutableVersions = new EnumMap<>(ProtocolVersion.class); + Map mutableVersions = new EnumMap<>(ProtocolVersion.class); for (ProtocolVersion version : ProtocolVersion.values()) { if (!version.isLegacy() && !version.isUnknown()) { - mutableVersions.put(version, new ProtocolRegistry(version)); + mutableVersions.put(version, new InternalRegistryMap(version, direction)); } } this.versions = mutableVersions; } - ProtocolRegistry getProtocolRegistry(final ProtocolVersion version) { - ProtocolRegistry registry = versions.get(version); + InternalRegistryMap getProtocolRegistry(final ProtocolVersion version) { + InternalRegistryMap registry = versions.get(version); if (registry == null) { throw new IllegalArgumentException("Could not find data for protocol version " + version); } @@ -364,7 +362,7 @@ class PlayPacketRegistry implements ProtocolRegistry { if (protocol == to && next != current) { break; } - ProtocolRegistry registry = this.versions.get(protocol); + InternalRegistryMap registry = this.versions.get(protocol); if (registry == null) { throw new IllegalArgumentException("Unknown protocol version " + current.protocolVersion); @@ -391,8 +389,12 @@ class PlayPacketRegistry implements ProtocolRegistry { } public void compact() { - ProtocolRegistry last = this.versions.get(MINIMUM_VERSION); - for (Entry entry : this.versions + InternalRegistryMap last = this.versions.get(MINIMUM_VERSION); + if (last == null) { + return; + } + + for (Map.Entry entry : this.versions .entrySet()) { if (entry.getValue() == last) { continue; @@ -406,73 +408,79 @@ class PlayPacketRegistry implements ProtocolRegistry { } } } + } - public class ProtocolRegistry implements PacketRegistryMap { + public static class InternalRegistryMap implements PacketRegistryMap { - private final ProtocolVersion version; - final IntObjectMap> packetIdToReader = - new IntObjectHashMap<>(16, 0.5f); - final Object2IntMap> packetClassToId = - new Object2IntOpenHashMap<>(16, 0.5f); - final Map, PacketWriter> packetClassToWriter = - new HashMap<>(16, 0.5f); + private final ProtocolVersion version; + final IntObjectMap> packetIdToReader = + new IntObjectHashMap<>(16, 0.5f); + final Object2IntMap> packetClassToId = + new Object2IntOpenHashMap<>(16, 0.5f); + final Map, PacketWriter> packetClassToWriter = + new HashMap<>(16, 0.5f); + private final PacketDirection direction; - ProtocolRegistry(final ProtocolVersion version) { - this.version = version; - this.packetClassToId.defaultReturnValue(Integer.MIN_VALUE); - } + InternalRegistryMap(final ProtocolVersion version, + PacketDirection direction) { + this.version = version; + this.direction = direction; + this.packetClassToId.defaultReturnValue(Integer.MIN_VALUE); + } - /** - * Attempts to create a packet from the specified {@code id}. - * - * @param id the packet ID - * @param buf the bytebuf - * @return the packet instance, or {@code null} if the ID is not registered - */ - public @Nullable Packet readPacket(final int id, ByteBuf buf, ProtocolVersion version) { - final PacketReader decoder = this.packetIdToReader.get(id); - if (decoder == null) { - return null; - } - return decoder.read(buf, version); - } - - /** - * Attempts to serialize the specified {@code packet}. - * - * @param packet the packet - * @param buf the bytebuf - */ - public

void writePacket(P packet, ByteBuf buf, ProtocolVersion version) { - final int id = this.packetClassToId.getInt(packet.getClass()); - if (id == Integer.MIN_VALUE) { - throw new IllegalArgumentException(String.format( - "Unable to find id for packet of type %s in %s protocol %s", - packet.getClass().getName(), PacketRegistry.this.direction, this.version - )); - } - - @SuppressWarnings("rawtypes") - // Safe because all registering actions are type-safe. - final PacketWriter encoder = this.packetClassToWriter.get(packet.getClass()); - - assert encoder != null : "Couldn't look up encoder - shouldn't happen!"; - - ProtocolUtils.writeVarInt(buf, id); - //noinspection unchecked - encoder.write(buf, packet, version); - } - - @Override - public @Nullable Class lookupPacket(int id) { - for (Object2IntMap.Entry> entry : this.packetClassToId - .object2IntEntrySet()) { - if (entry.getIntValue() == id) { - return entry.getKey(); - } - } + /** + * Attempts to create a packet from the specified {@code id}. + * + * @param id the packet ID + * @param buf the bytebuf + * @return the packet instance, or {@code null} if the ID is not registered + */ + @Override + public @Nullable Packet readPacket(final int id, ByteBuf buf, ProtocolVersion version) { + final PacketReader decoder = this.packetIdToReader.get(id); + if (decoder == null) { return null; } + return decoder.read(buf, version); + } + + /** + * Attempts to serialize the specified {@code packet}. + * + * @param packet the packet + * @param buf the bytebuf + */ + @Override + public

void writePacket(P packet, ByteBuf buf, ProtocolVersion version) { + final int id = this.packetClassToId.getInt(packet.getClass()); + if (id == Integer.MIN_VALUE) { + throw new IllegalArgumentException(String.format( + "Unable to find id for packet of type %s in %s protocol %s", + packet.getClass().getName(), this.direction, this.version + )); + } + + @SuppressWarnings("rawtypes") + // Safe because all registering actions are type-safe. + final PacketWriter encoder = this.packetClassToWriter.get(packet.getClass()); + if (encoder == null) { + throw new IllegalStateException("Couldn't look up encoder - shouldn't happen!"); + } + + ProtocolUtils.writeVarInt(buf, id); + //noinspection unchecked + encoder.write(buf, packet, version); + } + + @Override + public @Nullable Class lookupPacket(int id) { + for (Object2IntMap.Entry> entry : this.packetClassToId + .object2IntEntrySet()) { + if (entry.getIntValue() == id) { + return entry.getKey(); + } + } + return null; } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/resolver/SeparatePoolInetNameResolver.java b/proxy/src/main/java/com/velocitypowered/proxy/network/resolver/SeparatePoolInetNameResolver.java index 0346eb27c..0cc0a0b6c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/resolver/SeparatePoolInetNameResolver.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/resolver/SeparatePoolInetNameResolver.java @@ -35,13 +35,14 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; public final class SeparatePoolInetNameResolver extends InetNameResolver { private final ExecutorService resolveExecutor; private final InetNameResolver delegate; private final Cache> cache; - private AddressResolverGroup resolverGroup; + private @MonotonicNonNull AddressResolverGroup resolverGroup; /** * Creates a new instance of {@code SeparatePoolInetNameResolver}. 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 af87d2019..20d6e2667 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/plugin/VelocityPluginManager.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/plugin/VelocityPluginManager.java @@ -60,7 +60,7 @@ public class VelocityPluginManager implements PluginManager { private static final Logger logger = LogManager.getLogger(VelocityPluginManager.class); private final Map plugins = new LinkedHashMap<>(); - private final Map pluginInstances = new IdentityHashMap<>(); + private final IdentityHashMap pluginInstances = new IdentityHashMap<>(); private final VelocityServer server; public VelocityPluginManager(VelocityServer server) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/VelocityPluginContainer.java b/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/VelocityPluginContainer.java index 68c7bcd38..6d6e3e10f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/VelocityPluginContainer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/VelocityPluginContainer.java @@ -20,11 +20,12 @@ package com.velocitypowered.proxy.plugin.loader; import com.velocitypowered.api.plugin.PluginContainer; import com.velocitypowered.api.plugin.PluginDescription; import java.util.Optional; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; public class VelocityPluginContainer implements PluginContainer { private final PluginDescription description; - private Object instance; + private @MonotonicNonNull Object instance; public VelocityPluginContainer(PluginDescription description) { this.description = description; @@ -41,6 +42,10 @@ public class VelocityPluginContainer implements PluginContainer { } public void setInstance(Object instance) { - this.instance = instance; + if (this.instance == null) { + this.instance = instance; + } else { + throw new IllegalStateException("Plugin instance already set"); + } } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/VelocityPluginDescription.java b/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/VelocityPluginDescription.java index 14b550b07..901605c06 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/VelocityPluginDescription.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/VelocityPluginDescription.java @@ -39,7 +39,7 @@ public class VelocityPluginDescription implements PluginDescription { private final @Nullable String url; private final List authors; private final Map dependencies; - private final Path source; + private final @Nullable Path source; /** * Creates a new plugin description. @@ -54,7 +54,8 @@ public class VelocityPluginDescription implements PluginDescription { */ public VelocityPluginDescription(String id, @Nullable String name, @Nullable String version, @Nullable String description, @Nullable String url, - @Nullable List authors, Collection dependencies, Path source) { + @Nullable List authors, Collection dependencies, + @Nullable Path source) { this.id = checkNotNull(id, "id"); this.name = Strings.emptyToNull(name); this.version = Strings.emptyToNull(version); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/java/JavaPluginLoader.java b/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/java/JavaPluginLoader.java index 0f6204b96..4773cf44e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/java/JavaPluginLoader.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/java/JavaPluginLoader.java @@ -20,10 +20,10 @@ package com.velocitypowered.proxy.plugin.loader.java; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Module; +import com.velocitypowered.annotationprocessor.SerializedPluginDescription; import com.velocitypowered.api.plugin.InvalidPluginException; import com.velocitypowered.api.plugin.PluginContainer; import com.velocitypowered.api.plugin.PluginDescription; -import com.velocitypowered.api.plugin.ap.SerializedPluginDescription; import com.velocitypowered.api.plugin.meta.PluginDependency; import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.proxy.VelocityServer; @@ -48,11 +48,9 @@ import java.util.jar.JarInputStream; public class JavaPluginLoader implements PluginLoader { - private final ProxyServer server; private final Path baseDirectory; public JavaPluginLoader(ProxyServer server, Path baseDirectory) { - this.server = server; this.baseDirectory = baseDirectory; } @@ -60,7 +58,7 @@ public class JavaPluginLoader implements PluginLoader { public PluginDescription loadPluginDescription(Path source) throws Exception { Optional serialized = getSerializedPluginInfo(source); - if (!serialized.isPresent()) { + if (serialized.isEmpty()) { throw new InvalidPluginException("Did not find a valid velocity-plugin.json."); } @@ -79,7 +77,9 @@ public class JavaPluginLoader implements PluginLoader { } Path jarFilePath = source.file(); - assert jarFilePath != null; + if (jarFilePath == null) { + throw new IllegalStateException("JAR path not provided."); + } URL pluginJarUrl = jarFilePath.toUri().toURL(); PluginClassLoader loader = AccessController.doPrivileged( @@ -106,7 +106,7 @@ public class JavaPluginLoader implements PluginLoader { throw new IllegalArgumentException("No path in plugin description"); } - return new VelocityPluginModule(server, javaDescription, container, baseDirectory); + return new VelocityPluginModule(javaDescription, container, baseDirectory); } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/java/JavaVelocityPluginDescription.java b/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/java/JavaVelocityPluginDescription.java index 0fae80b08..3b67e3d2c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/java/JavaVelocityPluginDescription.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/java/JavaVelocityPluginDescription.java @@ -32,8 +32,8 @@ class JavaVelocityPluginDescription extends VelocityPluginDescription { JavaVelocityPluginDescription(String id, @Nullable String name, @Nullable String version, @Nullable String description, @Nullable String url, - @Nullable List authors, Collection dependencies, Path source, - Class mainClass) { + @Nullable List authors, Collection dependencies, + @Nullable Path source, Class mainClass) { super(id, name, version, description, url, authors, dependencies, source); this.mainClass = checkNotNull(mainClass); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/java/VelocityPluginModule.java b/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/java/VelocityPluginModule.java index 587bd523d..e561c3766 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/java/VelocityPluginModule.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/java/VelocityPluginModule.java @@ -30,14 +30,12 @@ import org.slf4j.LoggerFactory; class VelocityPluginModule implements Module { - private final ProxyServer server; private final JavaVelocityPluginDescription description; private final PluginContainer pluginContainer; private final Path basePluginPath; - VelocityPluginModule(ProxyServer server, JavaVelocityPluginDescription description, - PluginContainer pluginContainer, Path basePluginPath) { - this.server = server; + VelocityPluginModule(JavaVelocityPluginDescription description, + PluginContainer pluginContainer, Path basePluginPath) { this.description = description; this.pluginContainer = pluginContainer; this.basePluginPath = basePluginPath; 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 558829cbb..47701ea9a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/server/VelocityRegisteredServer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/server/VelocityRegisteredServer.java @@ -61,12 +61,12 @@ import org.checkerframework.checker.nullness.qual.Nullable; public class VelocityRegisteredServer implements RegisteredServer, ForwardingAudience { - private final @Nullable VelocityServer server; + private final @Nullable VelocityServer instance; private final ServerInfo serverInfo; private final Map players = new ConcurrentHashMap<>(); - public VelocityRegisteredServer(@Nullable VelocityServer server, ServerInfo serverInfo) { - this.server = server; + public VelocityRegisteredServer(@Nullable VelocityServer instance, ServerInfo serverInfo) { + this.instance = instance; this.serverInfo = Preconditions.checkNotNull(serverInfo, "serverInfo"); } @@ -93,18 +93,19 @@ public class VelocityRegisteredServer implements RegisteredServer, ForwardingAud * @return the server list ping response */ public CompletableFuture ping(@Nullable EventLoop loop, ProtocolVersion version) { - if (server == null) { + VelocityServer instance = this.instance; + if (instance == null) { throw new IllegalStateException("No Velocity proxy instance available"); } CompletableFuture pingFuture = new CompletableFuture<>(); - server.createBootstrap(loop, serverInfo.address()) - .handler(new ChannelInitializer() { + instance.createBootstrap(loop, serverInfo.address()) + .handler(new ChannelInitializer<>() { @Override protected void initChannel(Channel ch) throws Exception { ch.pipeline() .addLast(FRAME_DECODER, new MinecraftVarintFrameDecoder()) .addLast(READ_TIMEOUT, - new ReadTimeoutHandler(server.configuration().getReadTimeout(), + new ReadTimeoutHandler(instance.configuration().getReadTimeout(), TimeUnit.MILLISECONDS)) .addLast(FRAME_ENCODER, MinecraftVarintLengthEncoder.INSTANCE) .addLast(MINECRAFT_DECODER, @@ -112,7 +113,7 @@ public class VelocityRegisteredServer implements RegisteredServer, ForwardingAud .addLast(MINECRAFT_ENCODER, new MinecraftEncoder(PacketDirection.SERVERBOUND)); - ch.pipeline().addLast(HANDLER, new MinecraftConnection(ch, server)); + ch.pipeline().addLast(HANDLER, new MinecraftConnection(ch, instance)); } }) .connect(serverInfo.address()) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java index 384031fee..d2a47e3cf 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java @@ -144,7 +144,9 @@ public class VelocityTabList implements TabList { // Packets are already forwarded on, so no need to do that here for (ClientboundPlayerListItemPacket.Item item : packet.getItems()) { UUID uuid = item.getUuid(); - assert uuid != null : "1.7 tab list entry given to modern tab list handler!"; + if (uuid == null) { + throw new IllegalStateException("1.7 tab list entry given to modern tab list handler!"); + } if (packet.getAction() != ClientboundPlayerListItemPacket.ADD_PLAYER && !entries.containsKey(uuid)) { @@ -160,7 +162,7 @@ public class VelocityTabList implements TabList { if (name == null || properties == null) { throw new IllegalStateException("Got null game profile for ADD_PLAYER"); } - entries.put(item.getUuid(), (VelocityTabListEntry) TabListEntry.builder() + entries.put(uuid, (VelocityTabListEntry) TabListEntry.builder() .tabList(this) .profile(new GameProfile(uuid, name, properties)) .displayName(item.getDisplayName()) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListEntry.java b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListEntry.java index e3a4527d8..da74f3b20 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListEntry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListEntry.java @@ -28,12 +28,12 @@ public class VelocityTabListEntry implements TabListEntry { private final VelocityTabList tabList; private final GameProfile profile; - private net.kyori.adventure.text.Component displayName; + private @Nullable Component displayName; private int latency; private int gameMode; VelocityTabListEntry(VelocityTabList tabList, GameProfile profile, - net.kyori.adventure.text.@Nullable Component displayName, int latency, int gameMode) { + @Nullable Component displayName, int latency, int gameMode) { this.tabList = tabList; this.profile = profile; this.displayName = displayName; @@ -57,13 +57,13 @@ public class VelocityTabListEntry implements TabListEntry { } @Override - public TabListEntry setDisplayName(net.kyori.adventure.text.@Nullable Component displayName) { + public TabListEntry setDisplayName(@Nullable Component displayName) { this.displayName = displayName; tabList.updateEntry(ClientboundPlayerListItemPacket.UPDATE_DISPLAY_NAME, this); return this; } - void setDisplayNameInternal(net.kyori.adventure.text.@Nullable Component displayName) { + void setDisplayNameInternal(@Nullable Component displayName) { this.displayName = displayName; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/FileSystemUtils.java b/proxy/src/main/java/com/velocitypowered/proxy/util/FileSystemUtils.java index 591308bcb..3c6330021 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/util/FileSystemUtils.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/util/FileSystemUtils.java @@ -17,6 +17,8 @@ package com.velocitypowered.proxy.util; +import com.google.common.base.Splitter; +import com.google.common.collect.Iterables; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; import java.net.URI; @@ -56,7 +58,7 @@ public class FileSystemUtils { } if (knownResource.getProtocol().equals("jar")) { // Running from a JAR - String jarPathRaw = knownResource.toString().split("!")[0]; + String jarPathRaw = Iterables.get(Splitter.on('!').split(knownResource.toString()), 0); URI path = URI.create(jarPathRaw + "!/"); try (FileSystem fileSystem = FileSystems.newFileSystem(path, Map.of("create", "true"))) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/InformationUtils.java b/proxy/src/main/java/com/velocitypowered/proxy/util/InformationUtils.java index e712e98e0..51c401952 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/util/InformationUtils.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/util/InformationUtils.java @@ -17,6 +17,7 @@ package com.velocitypowered.proxy.util; +import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.gson.Gson; @@ -154,19 +155,19 @@ public enum InformationUtils { || v6.isSiteLocalAddress()) { return address.getHostAddress(); } else { - String[] bits = v6.getHostAddress().split(":"); + List bits = Splitter.on(':').splitToList(v6.getHostAddress()); String ret = ""; boolean flag = false; - for (int iter = 0; iter < bits.length; iter++) { + for (int iter = 0; iter < bits.size(); iter++) { if (flag) { ret += ":X"; continue; } - if (!bits[iter].equals("0")) { + if (!bits.get(iter).equals("0")) { if (iter == 0) { - ret = bits[iter]; + ret = bits.get(iter); } else { - ret = "::" + bits[iter]; + ret = "::" + bits.get(iter); } flag = true; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/bossbar/AdventureBossBarManager.java b/proxy/src/main/java/com/velocitypowered/proxy/util/bossbar/AdventureBossBarManager.java index 4dd617b7f..23ce2481b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/util/bossbar/AdventureBossBarManager.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/util/bossbar/AdventureBossBarManager.java @@ -274,7 +274,7 @@ public class AdventureBossBarManager implements BossBar.Listener { private byte serializeFlags(Set flags) { byte val = 0x0; for (Flag flag : flags) { - val |= FLAG_BITS_TO_PROTOCOL.get(flag); + val = (byte) (val | FLAG_BITS_TO_PROTOCOL.get(flag)); } return val; } diff --git a/proxy/src/test/java/com/velocitypowered/proxy/event/EventTest.java b/proxy/src/test/java/com/velocitypowered/proxy/event/EventTest.java index bd6941d45..cea6cc4da 100644 --- a/proxy/src/test/java/com/velocitypowered/proxy/event/EventTest.java +++ b/proxy/src/test/java/com/velocitypowered/proxy/event/EventTest.java @@ -25,6 +25,7 @@ import com.velocitypowered.api.event.PostOrder; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.proxy.testutil.FakePluginManager; import java.util.concurrent.atomic.AtomicInteger; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; @@ -70,7 +71,7 @@ public class EventTest { static final class AlwaysSyncListener { - Thread thread; + @MonotonicNonNull Thread thread; int result; @Subscribe @@ -92,9 +93,9 @@ public class EventTest { static final class AlwaysAsyncListener { - Thread threadA; - Thread threadB; - Thread threadC; + @MonotonicNonNull Thread threadA; + @MonotonicNonNull Thread threadB; + @MonotonicNonNull Thread threadC; int result; @Subscribe(async = true) @@ -129,10 +130,10 @@ public class EventTest { static final class SometimesAsyncListener { - Thread threadA; - Thread threadB; - Thread threadC; - Thread threadD; + @MonotonicNonNull Thread threadA; + @MonotonicNonNull Thread threadB; + @MonotonicNonNull Thread threadC; + @MonotonicNonNull Thread threadD; int result; @Subscribe(order = PostOrder.EARLY) @@ -169,9 +170,9 @@ public class EventTest { static final class ContinuationListener { - Thread threadA; - Thread threadB; - Thread threadC; + @MonotonicNonNull Thread threadA; + @MonotonicNonNull Thread threadB; + @MonotonicNonNull Thread threadC; final AtomicInteger value = new AtomicInteger(); @@ -211,9 +212,9 @@ public class EventTest { static final class AsyncContinuationListener { - Thread threadA; - Thread threadB; - Thread threadC; + @MonotonicNonNull Thread threadA; + @MonotonicNonNull Thread threadB; + @MonotonicNonNull Thread threadC; final AtomicInteger value = new AtomicInteger(); @@ -253,9 +254,9 @@ public class EventTest { static final class ResumeContinuationImmediatelyListener { - Thread threadA; - Thread threadB; - Thread threadC; + @MonotonicNonNull Thread threadA; + @MonotonicNonNull Thread threadB; + @MonotonicNonNull Thread threadC; int result; @Subscribe(order = PostOrder.EARLY) diff --git a/settings.gradle b/settings.gradle index d0f3098b4..36cfa5bb5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,8 +2,10 @@ rootProject.name = 'velocity' include( 'api', 'proxy', - 'native' + 'native', + 'annotation-processor' ) +findProject(':annotation-processor')?.name = 'velocity-annotation-processor' findProject(':api')?.name = 'velocity-api' findProject(':proxy')?.name = 'velocity-proxy' findProject(':native')?.name = 'velocity-native' \ No newline at end of file