diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperPingPassthrough.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperPingPassthrough.java index 60d5dee55..84a12b4ad 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperPingPassthrough.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperPingPassthrough.java @@ -37,6 +37,7 @@ import org.geysermc.geyser.ping.GeyserPingInfo; import org.geysermc.geyser.ping.IGeyserPingPassthrough; import java.lang.reflect.Constructor; +import java.lang.reflect.Method; import java.net.InetSocketAddress; /** @@ -44,7 +45,10 @@ import java.net.InetSocketAddress; * applied. */ public final class GeyserPaperPingPassthrough implements IGeyserPingPassthrough { - private static final Constructor OLD_CONSTRUCTOR = ReflectedNames.getOldPaperPingConstructor(); + private static final Constructor EVENT_CONSTRUCTOR = ReflectedNames.paperServerListPingEventConstructor(); + // https://jd.papermc.io/paper/1.19.2/com/destroystokyo/paper/event/server/PaperServerListPingEvent.html + private static final boolean CHAT_PREVIEWS = EVENT_CONSTRUCTOR.getParameters()[2].getType() == boolean.class; + private static final Method MOTD_COMPONENT_GETTER = ReflectedNames.motdGetter(); private final GeyserSpigotLogger logger; @@ -57,18 +61,15 @@ public final class GeyserPaperPingPassthrough implements IGeyserPingPassthrough @Override public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) { try { - // We'd rather *not* use deprecations here, but unfortunately any Adventure class would be relocated at - // runtime because we still have to shade in our own Adventure class. For now. PaperServerListPingEvent event; - if (OLD_CONSTRUCTOR != null) { - // 1.19, removed in 1.19.4 - event = OLD_CONSTRUCTOR.newInstance(new GeyserStatusClient(inetSocketAddress), - Bukkit.getMotd(), Bukkit.getOnlinePlayers().size(), - Bukkit.getMaxPlayers(), Bukkit.getVersion(), GameProtocol.getJavaProtocolVersion(), null); + if (CHAT_PREVIEWS) { + event = EVENT_CONSTRUCTOR.newInstance(new GeyserStatusClient(inetSocketAddress), + MOTD_COMPONENT_GETTER.invoke(null), false, Bukkit.getOnlinePlayers().size(), + Bukkit.getMaxPlayers(), Bukkit.getVersion(), GameProtocol.getJavaProtocolVersion(), null); } else { - event = new PaperServerListPingEvent(new GeyserStatusClient(inetSocketAddress), - Bukkit.getMotd(), Bukkit.getOnlinePlayers().size(), - Bukkit.getMaxPlayers(), Bukkit.getVersion(), GameProtocol.getJavaProtocolVersion(), null); + event = EVENT_CONSTRUCTOR.newInstance(new GeyserStatusClient(inetSocketAddress), + MOTD_COMPONENT_GETTER.invoke(null), Bukkit.getOnlinePlayers().size(), + Bukkit.getMaxPlayers(), Bukkit.getVersion(), GameProtocol.getJavaProtocolVersion(), null); } Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) { diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/ReflectedNames.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/ReflectedNames.java index 275fec657..5429850de 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/ReflectedNames.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/ReflectedNames.java @@ -26,12 +26,12 @@ package org.geysermc.geyser.platform.spigot; import com.destroystokyo.paper.event.server.PaperServerListPingEvent; -import com.destroystokyo.paper.network.StatusClient; +import org.bukkit.Bukkit; import org.bukkit.event.server.ServerListPingEvent; -import org.bukkit.util.CachedServerIcon; import org.checkerframework.checker.nullness.qual.Nullable; import java.lang.reflect.Constructor; +import java.lang.reflect.Method; import java.net.InetAddress; /** @@ -42,8 +42,9 @@ public final class ReflectedNames { static boolean checkPaperPingEvent() { try { Class.forName("com.destroystokyo.paper.event.server.PaperServerListPingEvent"); + paperServerListPingEventConstructor(); return true; - } catch (ClassNotFoundException e) { + } catch (Throwable ignored) { return false; } } @@ -52,18 +53,27 @@ public final class ReflectedNames { return getConstructor(ServerListPingEvent.class, InetAddress.class, String.class, boolean.class, int.class, int.class) != null; } - static @Nullable Constructor getOldPaperPingConstructor() { - if (getConstructor(PaperServerListPingEvent.class, StatusClient.class, String.class, int.class, - int.class, String.class, int.class, CachedServerIcon.class) != null) { - // @NotNull StatusClient client, @NotNull String motd, int numPlayers, int maxPlayers, - // @NotNull String version, int protocolVersion, @Nullable CachedServerIcon favicon - // New constructor is present - return null; + // Ugly workaround that's necessary due to relocation of adventure components + static Method motdGetter() { + try { + return Bukkit.class.getMethod("motd"); + } catch (Throwable e) { + throw new RuntimeException("Could not find component motd method! Please report this issue.", e); } - // @NotNull StatusClient client, @NotNull String motd, boolean shouldSendChatPreviews, int numPlayers, int maxPlayers, - // @NotNull String version, int protocolVersion, @Nullable CachedServerIcon favicon - return getConstructor(PaperServerListPingEvent.class, StatusClient.class, String.class, boolean.class, int.class, int.class, - String.class, int.class, CachedServerIcon.class); + } + + @SuppressWarnings("unchecked") + static Constructor paperServerListPingEventConstructor() { + var constructors = PaperServerListPingEvent.class.getConstructors(); + for (var constructor : constructors) { + // We want to get the constructor with the adventure component motd, but without referencing the + // component class as that's relocated + if (constructor.getParameters()[1].getType() != String.class) { + return (Constructor) constructor; + } + } + + throw new IllegalStateException("Could not find component motd method!"); } /**