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