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:
Ursprung
c496d912ea
Commit
3c41211163
35
annotation-processor/build.gradle
Normale Datei
35
annotation-processor/build.gradle
Normale Datei
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
@ -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;
|
@ -0,0 +1 @@
|
||||
com.velocitypowered.annotationprocessor.PluginAnnotationProcessor
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
com.velocitypowered.api.plugin.ap.PluginAnnotationProcessor
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
14
build.gradle
14
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'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
17
gradle/errorprone.gradle
Normale Datei
17
gradle/errorprone.gradle
Normale Datei
@ -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")
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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}"
|
||||
|
@ -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('.');
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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{"
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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('%');
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -228,9 +228,4 @@ public class StatusSessionHandler implements MinecraftSessionHandler {
|
||||
// what even is going on?
|
||||
connection.close(true);
|
||||
}
|
||||
|
||||
private enum State {
|
||||
AWAITING_REQUEST,
|
||||
RECEIVED_REQUEST
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
@ -118,4 +118,9 @@ public final class DimensionRegistry {
|
||||
}
|
||||
return mappings.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return levelNames.toString();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -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++) {
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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}.
|
||||
|
@ -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) {
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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())
|
||||
|
@ -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())
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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"))) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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'
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren