3
0
Mirror von https://github.com/PaperMC/Velocity.git synchronisiert 2024-11-16 21:10:30 +01:00

Switch over to Error Prone (now with NullAway!)

There is one major change: we now have a separate artifact for the annotation processor.

As for NullAway, we are currently exempting the clientbound join game/respawn packets. They are ugly and need to be refactored.
Dieser Commit ist enthalten in:
Andrew Steinborn 2021-05-13 04:13:15 -04:00
Ursprung c496d912ea
Commit 3c41211163
79 geänderte Dateien mit 494 neuen und 401 gelöschten Zeilen

Datei anzeigen

@ -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
}
}
}

Datei anzeigen

@ -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 <https://www.gnu.org/licenses/>.
*/
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");
}
}

Datei anzeigen

@ -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 <https://www.gnu.org/licenses/>.
*/
package com.velocitypowered.api.plugin.ap;
package com.velocitypowered.annotationprocessor;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;

Datei anzeigen

@ -0,0 +1 @@
com.velocitypowered.annotationprocessor.PluginAnnotationProcessor

Datei anzeigen

@ -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
}

Datei anzeigen

@ -1 +0,0 @@
com.velocitypowered.api.plugin.ap.PluginAnnotationProcessor

Datei anzeigen

@ -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<E> {
EventTask execute(E event);
@Nullable EventTask execute(E event);
}

Datei anzeigen

@ -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);
}

Datei anzeigen

@ -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");

Datei anzeigen

@ -88,7 +88,7 @@ public interface ResultedEvent<R extends ResultedEvent.Result> {
private final @Nullable Component reason;
protected ComponentResult(@Nullable Component reason) {
private ComponentResult(@Nullable Component reason) {
this.reason = reason;
}

Datei anzeigen

@ -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;
}

Datei anzeigen

@ -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;
}

Datei anzeigen

@ -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) {

Datei anzeigen

@ -98,7 +98,7 @@ public interface ServerPreConnectEvent extends ResultedEvent<ServerPreConnectEve
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
if (!(o instanceof ServerResult)) {
return false;
}
ServerResult that = (ServerResult) o;

Datei anzeigen

@ -60,7 +60,7 @@ public enum ProtocolVersion implements Ordered<ProtocolVersion> {
private final int protocol;
private final int snapshotProtocol;
private final String[] names;
private final ImmutableList<String> names;
/**
* Represents the lowest supported version.
@ -127,7 +127,7 @@ public enum ProtocolVersion implements Ordered<ProtocolVersion> {
}
this.protocol = protocol;
this.names = names;
this.names = ImmutableList.copyOf(names);
}
/**
@ -146,7 +146,7 @@ public enum ProtocolVersion implements Ordered<ProtocolVersion> {
* @return the version name
*/
public String versionIntroducedIn() {
return names[0];
return names.get(0);
}
/**
@ -156,7 +156,7 @@ public enum ProtocolVersion implements Ordered<ProtocolVersion> {
* @return the version name
*/
public String mostRecentSupportedVersion() {
return names[names.length - 1];
return names.get(names.size() - 1);
}
/**

Datei anzeigen

@ -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.

Datei anzeigen

@ -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);

Datei anzeigen

@ -33,14 +33,14 @@ public final class QueryResponse {
private final int maxPlayers;
private final String proxyHost;
private final int proxyPort;
private final ImmutableCollection<String> players;
private final ImmutableList<String> players;
private final String proxyVersion;
private final ImmutableCollection<PluginInformation> plugins;
private final ImmutableList<PluginInformation> plugins;
@VisibleForTesting
QueryResponse(String hostname, String gameVersion, String map, int onlinePlayers,
int maxPlayers, String proxyHost, int proxyPort, ImmutableCollection<String> players,
String proxyVersion, ImmutableCollection<PluginInformation> plugins) {
int maxPlayers, String proxyHost, int proxyPort, ImmutableList<String> players,
String proxyVersion, ImmutableList<PluginInformation> plugins) {
this.hostname = hostname;
this.gameVersion = gameVersion;
this.map = map;

Datei anzeigen

@ -150,7 +150,7 @@ public final class ServerPing {
private final List<SamplePlayer> samplePlayers = new ArrayList<>();
private String modType = "FML";
private final List<ModInfo.Mod> mods = new ArrayList<>();
private Component description;
private @Nullable Component description;
private @Nullable Favicon favicon;
private boolean nullOutPlayers;
private boolean nullOutModinfo;

Datei anzeigen

@ -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'
}
}
}
}

17
gradle/errorprone.gradle Normale Datei
Datei anzeigen

@ -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")
}
}

Datei anzeigen

@ -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

Datei anzeigen

@ -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<T> implements Supplier<T> {
@ -56,7 +57,7 @@ public final class NativeCodeLoader<T> implements Supplier<T> {
private final Runnable setup;
private final String name;
private final Supplier<T> object;
private T constructed;
private @MonotonicNonNull T constructed;
Variant(BooleanSupplier possiblyAvailable, Runnable setup, String name, T object) {
this(possiblyAvailable, setup, name, () -> object);

Datei anzeigen

@ -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}"

Datei anzeigen

@ -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('.');

Datei anzeigen

@ -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<Path> 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

Datei anzeigen

@ -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);

Datei anzeigen

@ -592,18 +592,10 @@ public class VelocityConfiguration implements ProxyConfig {
}
}
private ForcedHosts(Map<String, List<String>> forcedHosts) {
this.forcedHosts = forcedHosts;
}
private Map<String, List<String>> getForcedHosts() {
return forcedHosts;
}
private void setForcedHosts(Map<String, List<String>> forcedHosts) {
this.forcedHosts = forcedHosts;
}
@Override
public String toString() {
return "ForcedHosts{"

Datei anzeigen

@ -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

Datei anzeigen

@ -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<CommandSource> rootNode = commands.getRootNode();
if (server.configuration().isAnnounceProxyCommands()) {
// Inject commands from the proxy.
RootCommandNode<CommandSource> dispatcherRootNode =
(RootCommandNode<CommandSource>)
filterNode(server.commandManager().getDispatcher().getRoot());
assert dispatcherRootNode != null : "Filtering root node returned null.";
RootCommandNode<CommandSource> dispatcherRootNode = filterRootNode(server.commandManager()
.getDispatcher().getRoot());
Collection<CommandNode<CommandSource>> proxyNodes = dispatcherRootNode.getChildren();
for (CommandNode<CommandSource> node : proxyNodes) {
CommandNode<CommandSource> 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<CommandSource> filterRootNode(CommandNode<CommandSource> source) {
RootCommandNode<CommandSource> dest = new RootCommandNode<>();
for (CommandNode<CommandSource> sourceChild : source.getChildren()) {
CommandNode<CommandSource> 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<CommandSource> filterNode(CommandNode<CommandSource> source) {
CommandNode<CommandSource> 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<CommandSource> filterNode(CommandNode<CommandSource> 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<CommandSource, ?> destChildBuilder = source.createBuilder();
destChildBuilder.requires((commandSource) -> true);
if (destChildBuilder.getRedirect() != null) {
destChildBuilder.redirect(filterNode(destChildBuilder.getRedirect()));
}
dest = destChildBuilder.build();
}
ArgumentBuilder<CommandSource, ?> destChildBuilder = source.createBuilder();
destChildBuilder.requires((commandSource) -> true);
if (destChildBuilder.getRedirect() != null) {
destChildBuilder.redirect(filterNode(destChildBuilder.getRedirect()));
}
CommandNode<CommandSource> dest = destChildBuilder.build();
for (CommandNode<CommandSource> sourceChild : source.getChildren()) {
CommandNode<CommandSource> destChild = filterNode(sourceChild);
if (destChild == null) {

Datei anzeigen

@ -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);

Datei anzeigen

@ -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('%');

Datei anzeigen

@ -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;

Datei anzeigen

@ -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

Datei anzeigen

@ -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());
}

Datei anzeigen

@ -228,9 +228,4 @@ public class StatusSessionHandler implements MinecraftSessionHandler {
// what even is going on?
connection.close(true);
}
private enum State {
AWAITING_REQUEST,
RECEIVED_REQUEST
}
}

Datei anzeigen

@ -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;
}

Datei anzeigen

@ -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
+ '}';
}
}

Datei anzeigen

@ -118,4 +118,9 @@ public final class DimensionRegistry {
}
return mappings.build();
}
@Override
public String toString() {
return levelNames.toString();
}
}

Datei anzeigen

@ -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;
}

Datei anzeigen

@ -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<UntargetedEventHandler> untargetedHandlerType =
LambdaType.of(UntargetedEventHandler.class);
private static final LambdaType<UntargetedEventHandler.Void> untargetedVoidHandlerType =
LambdaType.of(UntargetedEventHandler.Void.class);
private static final LambdaType<VoidHandler> untargetedVoidHandlerType =
LambdaType.of(VoidHandler.class);
private static final Comparator<HandlerRegistration> handlerComparator =
Comparator.comparingInt(o -> o.order);
@ -77,7 +79,7 @@ public class VelocityEventManager implements EventManager {
private final PluginManager pluginManager;
private final Multimap<Class<?>, HandlerRegistration> handlersByType = HashMultimap.create();
private final LoadingCache<Class<?>, @Nullable HandlersCache> handlersCache =
private final LoadingCache<Class<?>, HandlersCache> handlersCache =
Caffeine.newBuilder().build(this::bakeHandlers);
private final LoadingCache<Method, UntargetedEventHandler> 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<Object> 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(

Datei anzeigen

@ -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);
}

Datei anzeigen

@ -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<? extends ServerSocketChannel> serverSocketChannelFactory;
final ChannelFactory<? extends SocketChannel> socketChannelFactory;
final ChannelFactory<? extends DatagramChannel> datagramChannelFactory;
final ChannelFactory<? extends ServerDomainSocketChannel> domainServerSocketChannelFactory;
final ChannelFactory<? extends DomainSocketChannel> domainSocketChannelFactory;
final @Nullable ChannelFactory<? extends ServerDomainSocketChannel> domainServerSocketChannelFactory;
final @Nullable ChannelFactory<? extends DomainSocketChannel> domainSocketChannelFactory;
final BiFunction<String, Type, EventLoopGroup> eventLoopGroupFactory;
TransportType(final String name,
final ChannelFactory<? extends ServerSocketChannel> serverSocketChannelFactory,
final ChannelFactory<? extends SocketChannel> socketChannelFactory,
final ChannelFactory<? extends DatagramChannel> datagramChannelFactory,
final ChannelFactory<? extends ServerDomainSocketChannel> domainServerSocketChannelFactory,
final ChannelFactory<? extends DomainSocketChannel> domainSocketChannelFactory,
@Nullable final ChannelFactory<? extends ServerDomainSocketChannel> domainServerSocketChannelFactory,
@Nullable final ChannelFactory<? extends DomainSocketChannel> domainSocketChannelFactory,
final BiFunction<String, Type, EventLoopGroup> eventLoopGroupFactory) {
this.name = name;
this.serverSocketChannelFactory = serverSocketChannelFactory;

Datei anzeigen

@ -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<S extends AbstractPluginMessag
};
}
protected final @Nullable String channel;
protected final String channel;
protected AbstractPluginMessagePacket(String channel,
@MonotonicNonNull ByteBuf backing) {
protected AbstractPluginMessagePacket(String channel, @MonotonicNonNull ByteBuf backing) {
super(backing);
this.channel = channel;
this.channel = Preconditions.checkNotNull(channel, "channel");
}
public String getChannel() {
if (channel == null) {
throw new IllegalStateException("Channel is not specified.");
}
return channel;
}

Datei anzeigen

@ -23,7 +23,7 @@ import io.netty.buffer.ByteBuf;
public interface Packet {
@Deprecated
default void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion protocolVersion) {
default void decode(ByteBuf buf, ProtocolVersion protocolVersion) {
throw new UnsupportedOperationException();
}

Datei anzeigen

@ -46,7 +46,7 @@ public interface PacketReader<P extends Packet> {
static <P extends Packet> PacketReader<P> method(final Supplier<P> factory) {
return (buf, version) -> {
final P packet = factory.get();
packet.decode(buf, null, version);
packet.decode(buf, version);
return packet;
};
}

Datei anzeigen

@ -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++) {

Datei anzeigen

@ -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) {

Datei anzeigen

@ -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<ClientboundChatPacket> DECODER = PacketReader.method(ClientboundChatPacket::new);
public static final PacketWriter<ClientboundChatPacket> ENCODER = PacketWriter.deprecatedEncode();
public static final PacketReader<ClientboundChatPacket> DECODER = PacketReader.unsupported();
public static final PacketWriter<ClientboundChatPacket> 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)

Datei anzeigen

@ -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)) {

Datei anzeigen

@ -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<ClientboundJoinGamePacket> DECODER = PacketReader.method(ClientboundJoinGamePacket::new);
public static final PacketWriter<ClientboundJoinGamePacket> 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;

Datei anzeigen

@ -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;

Datei anzeigen

@ -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<GameProfile.Property> 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;
}

Datei anzeigen

@ -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<ClientboundRespawnPacket> DECODER = PacketReader.method(ClientboundRespawnPacket::new);
public static final PacketWriter<ClientboundRespawnPacket> 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) {

Datei anzeigen

@ -35,20 +35,12 @@ public class ClientboundStatusResponsePacket implements Packet {
public static final PacketWriter<ClientboundStatusResponsePacket> 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);

Datei anzeigen

@ -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;
}

Datei anzeigen

@ -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);

Datei anzeigen

@ -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);
}

Datei anzeigen

@ -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());
}

Datei anzeigen

@ -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);

Datei anzeigen

@ -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;

Datei anzeigen

@ -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<? extends Packet> lookupPacket(int id) {
for (Entry<Class<?>> entry : this.classesById.object2IntEntrySet()) {
for (Object2IntMap.Entry<Class<?>> entry : this.classesById.object2IntEntrySet()) {
if (entry.getIntValue() == id) {
return (Class<? extends Packet>) entry.getKey();
}

Datei anzeigen

@ -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");
}

Datei anzeigen

@ -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<ProtocolVersion, ProtocolRegistry> versions;
private final Map<ProtocolVersion, InternalRegistryMap> versions;
PacketRegistry(PacketDirection direction) {
this.direction = direction;
Map<ProtocolVersion, ProtocolRegistry> mutableVersions = new EnumMap<>(ProtocolVersion.class);
Map<ProtocolVersion, InternalRegistryMap> 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<ProtocolVersion, ProtocolRegistry> entry : this.versions
InternalRegistryMap last = this.versions.get(MINIMUM_VERSION);
if (last == null) {
return;
}
for (Map.Entry<ProtocolVersion, InternalRegistryMap> 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<PacketReader<? extends Packet>> packetIdToReader =
new IntObjectHashMap<>(16, 0.5f);
final Object2IntMap<Class<? extends Packet>> packetClassToId =
new Object2IntOpenHashMap<>(16, 0.5f);
final Map<Class<? extends Packet>, PacketWriter<? extends Packet>> packetClassToWriter =
new HashMap<>(16, 0.5f);
private final ProtocolVersion version;
final IntObjectMap<PacketReader<? extends Packet>> packetIdToReader =
new IntObjectHashMap<>(16, 0.5f);
final Object2IntMap<Class<? extends Packet>> packetClassToId =
new Object2IntOpenHashMap<>(16, 0.5f);
final Map<Class<? extends Packet>, PacketWriter<? extends Packet>> 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<? extends Packet> 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 <P extends Packet> 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<? extends Packet> lookupPacket(int id) {
for (Object2IntMap.Entry<Class<? extends Packet>> 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<? extends Packet> 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 <P extends Packet> 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<? extends Packet> lookupPacket(int id) {
for (Object2IntMap.Entry<Class<? extends Packet>> entry : this.packetClassToId
.object2IntEntrySet()) {
if (entry.getIntValue() == id) {
return entry.getKey();
}
}
return null;
}
}

Datei anzeigen

@ -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<String, List<InetAddress>> cache;
private AddressResolverGroup<InetSocketAddress> resolverGroup;
private @MonotonicNonNull AddressResolverGroup<InetSocketAddress> resolverGroup;
/**
* Creates a new instance of {@code SeparatePoolInetNameResolver}.

Datei anzeigen

@ -60,7 +60,7 @@ public class VelocityPluginManager implements PluginManager {
private static final Logger logger = LogManager.getLogger(VelocityPluginManager.class);
private final Map<String, PluginContainer> plugins = new LinkedHashMap<>();
private final Map<Object, PluginContainer> pluginInstances = new IdentityHashMap<>();
private final IdentityHashMap<Object, PluginContainer> pluginInstances = new IdentityHashMap<>();
private final VelocityServer server;
public VelocityPluginManager(VelocityServer server) {

Datei anzeigen

@ -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");
}
}
}

Datei anzeigen

@ -39,7 +39,7 @@ public class VelocityPluginDescription implements PluginDescription {
private final @Nullable String url;
private final List<String> authors;
private final Map<String, PluginDependency> 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<String> authors, Collection<PluginDependency> dependencies, Path source) {
@Nullable List<String> authors, Collection<PluginDependency> dependencies,
@Nullable Path source) {
this.id = checkNotNull(id, "id");
this.name = Strings.emptyToNull(name);
this.version = Strings.emptyToNull(version);

Datei anzeigen

@ -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<SerializedPluginDescription> 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

Datei anzeigen

@ -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<String> authors, Collection<PluginDependency> dependencies, Path source,
Class<?> mainClass) {
@Nullable List<String> authors, Collection<PluginDependency> dependencies,
@Nullable Path source, Class<?> mainClass) {
super(id, name, version, description, url, authors, dependencies, source);
this.mainClass = checkNotNull(mainClass);
}

Datei anzeigen

@ -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;

Datei anzeigen

@ -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<UUID, ConnectedPlayer> 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<ServerPing> 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<ServerPing> pingFuture = new CompletableFuture<>();
server.createBootstrap(loop, serverInfo.address())
.handler(new ChannelInitializer<Channel>() {
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())

Datei anzeigen

@ -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())

Datei anzeigen

@ -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;
}

Datei anzeigen

@ -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"))) {

Datei anzeigen

@ -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<String> 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;
}

Datei anzeigen

@ -274,7 +274,7 @@ public class AdventureBossBarManager implements BossBar.Listener {
private byte serializeFlags(Set<Flag> 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;
}

Datei anzeigen

@ -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)

Datei anzeigen

@ -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'