From a46f43d19aeaf5870f9331d7dbc0f204fff243cc Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Mon, 13 Jun 2022 15:29:45 -0400
Subject: [PATCH] Fix Velocity modern forwarding with 1.19
Fixes https://github.com/GeyserMC/Geyser/issues/3039, #321
---
.../floodgate/util/ReflectionUtils.java | 29 +++++++++++
.../geysermc/floodgate/util/ClassNames.java | 48 ++++++++++++++++---
.../geysermc/floodgate/util/ProxyUtils.java | 5 +-
3 files changed, 72 insertions(+), 10 deletions(-)
diff --git a/core/src/main/java/org/geysermc/floodgate/util/ReflectionUtils.java b/core/src/main/java/org/geysermc/floodgate/util/ReflectionUtils.java
index 13d16d8a..80352d87 100644
--- a/core/src/main/java/org/geysermc/floodgate/util/ReflectionUtils.java
+++ b/core/src/main/java/org/geysermc/floodgate/util/ReflectionUtils.java
@@ -255,6 +255,25 @@ public final class ReflectionUtils {
}
}
+ /**
+ * Get the value of a boolean field. This method first makes the field accessible and then gets
+ * the value.
This method will return false instead of throwing an exception, but it'll log
+ * the stacktrace to the console.
+ *
+ * @param instance the instance to get the value from
+ * @param field the field to get the value from
+ * @return the value when succeeded, otherwise null
+ */
+ public static boolean getBooleanValue(Object instance, Field field) {
+ makeAccessible(field);
+ try {
+ return field.getBoolean(instance);
+ } catch (IllegalArgumentException | IllegalAccessException exception) {
+ exception.printStackTrace();
+ return false;
+ }
+ }
+
/**
* Get the value of the given field by finding the field and then get the value of it.
*
@@ -300,6 +319,16 @@ public final class ReflectionUtils {
return getCastedValue(null, field);
}
+ public static boolean castedStaticBooleanValue(Field field) {
+ makeAccessible(field);
+ try {
+ return field.getBoolean(null);
+ } catch (IllegalArgumentException | IllegalAccessException exception) {
+ exception.printStackTrace();
+ return false;
+ }
+ }
+
/**
* Set the value of a field. This method make the field accessible and then sets the value.
* This method doesn't throw an exception when failed, but it'll log the error to the console.
diff --git a/spigot/src/main/java/org/geysermc/floodgate/util/ClassNames.java b/spigot/src/main/java/org/geysermc/floodgate/util/ClassNames.java
index 4d0908e7..22c7d688 100644
--- a/spigot/src/main/java/org/geysermc/floodgate/util/ClassNames.java
+++ b/spigot/src/main/java/org/geysermc/floodgate/util/ClassNames.java
@@ -25,10 +25,15 @@
package org.geysermc.floodgate.util;
+import static org.geysermc.floodgate.util.ReflectionUtils.castedStaticBooleanValue;
+import static org.geysermc.floodgate.util.ReflectionUtils.getBooleanValue;
import static org.geysermc.floodgate.util.ReflectionUtils.getClassOrFallback;
+import static org.geysermc.floodgate.util.ReflectionUtils.getClassSilently;
import static org.geysermc.floodgate.util.ReflectionUtils.getField;
import static org.geysermc.floodgate.util.ReflectionUtils.getFieldOfType;
import static org.geysermc.floodgate.util.ReflectionUtils.getMethod;
+import static org.geysermc.floodgate.util.ReflectionUtils.getValue;
+import static org.geysermc.floodgate.util.ReflectionUtils.invoke;
import com.google.common.base.Preconditions;
import com.mojang.authlib.GameProfile;
@@ -37,6 +42,8 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.SocketAddress;
+import java.util.function.BooleanSupplier;
+import javax.annotation.CheckForNull;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -61,7 +68,7 @@ public class ClassNames {
public static final Field PACKET_LISTENER;
@Nullable public static final Field PAPER_DISABLE_USERNAME_VALIDATION;
- @Nullable public static final Field PAPER_VELOCITY_SUPPORT;
+ @Nullable public static final BooleanSupplier PAPER_VELOCITY_SUPPORT;
public static final Method GET_PROFILE_METHOD;
public static final Method LOGIN_DISCONNECT;
@@ -182,14 +189,41 @@ public class ClassNames {
BUNGEE = getField(spigotConfig, "bungee");
checkNotNull(BUNGEE, "Bungee field");
- Class> paperConfig = ReflectionUtils.getClassSilently(
- "com.destroystokyo.paper.PaperConfig");
+ Class> paperConfigNew = getClassSilently(
+ "io.papermc.paper.configuration.GlobalConfiguration");
+ if (paperConfigNew != null) {
+ // 1.19 and later
+ Method paperConfigGet = checkNotNull(getMethod(paperConfigNew, "get"),
+ "GlobalConfiguration get");
+ Field paperConfigProxies = checkNotNull(getField(paperConfigNew, "proxies"),
+ "Proxies field");
+ Field paperConfigVelocity = checkNotNull(
+ getField(paperConfigProxies.getType(), "velocity"),
+ "velocity field");
+ Field paperVelocityEnabled = checkNotNull(
+ getField(paperConfigVelocity.getType(), "enabled"),
+ "Velocity enabled field");
+ PAPER_VELOCITY_SUPPORT = () -> {
+ Object paperConfigInstance = invoke(null, paperConfigGet);
+ Object proxiesInstance = getValue(paperConfigInstance, paperConfigProxies);
+ Object velocityInstance = getValue(proxiesInstance, paperConfigVelocity);
+ return getBooleanValue(velocityInstance, paperVelocityEnabled);
+ };
+ } else {
+ // Pre-1.19
+ Class> paperConfig = getClassSilently(
+ "com.destroystokyo.paper.PaperConfig");
- PAPER_VELOCITY_SUPPORT =
- paperConfig == null ? null : getField(paperConfig, "velocitySupport");
+ if (paperConfig != null) {
+ Field velocitySupport = getField(paperConfig, "velocitySupport");
+ PAPER_VELOCITY_SUPPORT = () -> castedStaticBooleanValue(velocitySupport);
+ } else {
+ PAPER_VELOCITY_SUPPORT = null;
+ }
+ }
}
- private static void checkNotNull(Object toCheck, String objectName) {
- Preconditions.checkNotNull(toCheck, objectName + " cannot be null");
+ private static T checkNotNull(@CheckForNull T toCheck, @CheckForNull String objectName) {
+ return Preconditions.checkNotNull(toCheck, objectName + " cannot be null");
}
}
diff --git a/spigot/src/main/java/org/geysermc/floodgate/util/ProxyUtils.java b/spigot/src/main/java/org/geysermc/floodgate/util/ProxyUtils.java
index 9d982850..d9d7791d 100644
--- a/spigot/src/main/java/org/geysermc/floodgate/util/ProxyUtils.java
+++ b/spigot/src/main/java/org/geysermc/floodgate/util/ProxyUtils.java
@@ -25,7 +25,6 @@
package org.geysermc.floodgate.util;
-@SuppressWarnings("ConstantConditions")
public final class ProxyUtils {
public static boolean isProxyData() {
@@ -33,7 +32,7 @@ public final class ProxyUtils {
}
private static boolean isBungeeData() {
- return ReflectionUtils.castedStaticValue(ClassNames.BUNGEE);
+ return ReflectionUtils.castedStaticBooleanValue(ClassNames.BUNGEE);
}
private static boolean isVelocitySupport() {
@@ -41,6 +40,6 @@ public final class ProxyUtils {
return false;
}
- return ReflectionUtils.castedStaticValue(ClassNames.PAPER_VELOCITY_SUPPORT);
+ return ClassNames.PAPER_VELOCITY_SUPPORT.getAsBoolean();
}
}
\ No newline at end of file