From b1524642aa4ac6feb10b3ede0b7566f65328f21a Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Wed, 15 Mar 2023 10:08:49 +0100 Subject: [PATCH] Fix protocol detection on 1.19.4 Spigot Fixes #3241 --- .../viaversion/api/platform/ViaPlatform.java | 21 ++++++----- .../viaversion/ViaVersionPlugin.java | 8 ++--- .../bukkit/platform/BukkitViaInjector.java | 36 +++++++++++++++++-- .../viaversion/viaversion/BungeePlugin.java | 8 ++--- .../viaversion/common/dummy/TestPlatform.java | 4 +-- .../viaversion/viaversion/SpongePlugin.java | 8 ++--- .../viaversion/viaversion/VelocityPlugin.java | 8 ++--- 7 files changed, 62 insertions(+), 31 deletions(-) diff --git a/api/src/main/java/com/viaversion/viaversion/api/platform/ViaPlatform.java b/api/src/main/java/com/viaversion/viaversion/api/platform/ViaPlatform.java index 7e5b0ca90..22ee5c98b 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/platform/ViaPlatform.java +++ b/api/src/main/java/com/viaversion/viaversion/api/platform/ViaPlatform.java @@ -104,23 +104,22 @@ public interface ViaPlatform { PlatformTask runSync(Runnable runnable); /** - * Run a task Sync after a interval - * This must be only used after plugin enable. + * Runs a synchronous task after a delay in ticks. * - * @param runnable The task to run - * @param ticks The interval to run it after - * @return The Task ID + * @param runnable task to run + * @param delay delay in ticks to run it after + * @return created task */ - PlatformTask runSync(Runnable runnable, long ticks); + PlatformTask runSync(Runnable runnable, long delay); /** - * Run a task at a repeating interval. + * Runs a synchronous task at a repeating interval. * - * @param runnable The task to run - * @param ticks The interval to run it at - * @return The Task ID + * @param runnable task to run + * @param period period in ticks to run at + * @return created task */ - PlatformTask runRepeatingSync(Runnable runnable, long ticks); + PlatformTask runRepeatingSync(Runnable runnable, long period); /** * Get the online players diff --git a/bukkit/src/main/java/com/viaversion/viaversion/ViaVersionPlugin.java b/bukkit/src/main/java/com/viaversion/viaversion/ViaVersionPlugin.java index 126292f58..11f4fde1c 100644 --- a/bukkit/src/main/java/com/viaversion/viaversion/ViaVersionPlugin.java +++ b/bukkit/src/main/java/com/viaversion/viaversion/ViaVersionPlugin.java @@ -171,13 +171,13 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform } @Override - public PlatformTask runSync(Runnable runnable, long ticks) { - return new BukkitViaTask(getServer().getScheduler().runTaskLater(this, runnable, ticks)); + public PlatformTask runSync(Runnable runnable, long delay) { + return new BukkitViaTask(getServer().getScheduler().runTaskLater(this, runnable, delay)); } @Override - public PlatformTask runRepeatingSync(Runnable runnable, long ticks) { - return new BukkitViaTask(getServer().getScheduler().runTaskTimer(this, runnable, 0, ticks)); + public PlatformTask runRepeatingSync(Runnable runnable, long period) { + return new BukkitViaTask(getServer().getScheduler().runTaskTimer(this, runnable, 0, period)); } @Override diff --git a/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/BukkitViaInjector.java b/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/BukkitViaInjector.java index 0085aadea..e3e0690d9 100644 --- a/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/BukkitViaInjector.java +++ b/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/BukkitViaInjector.java @@ -17,6 +17,7 @@ */ package com.viaversion.viaversion.bukkit.platform; +import com.google.common.base.Preconditions; import com.viaversion.viaversion.bukkit.handlers.BukkitChannelInitializer; import com.viaversion.viaversion.bukkit.util.NMSUtil; import com.viaversion.viaversion.platform.LegacyViaInjector; @@ -35,6 +36,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; public class BukkitViaInjector extends LegacyViaInjector { + private static final boolean HAS_SHARED_CONSTANTS = PaperViaInjector.hasClass("net.minecraft.SharedConstants") && PaperViaInjector.hasClass("net.minecraft.WorldVersion"); + @Override public void inject() throws ReflectiveOperationException { if (PaperViaInjector.PAPER_INJECTION_METHOD) { @@ -62,10 +65,37 @@ public class BukkitViaInjector extends LegacyViaInjector { return Bukkit.getUnsafe().getProtocolVersion(); } - // Time to go on a journey! The protocol version is hidden inside an int in ServerPing.ServerData + return HAS_SHARED_CONSTANTS ? cursedProtocolDetection() : veryCursedProtocolDetection(); + } + + private int cursedProtocolDetection() throws ReflectiveOperationException { + // Get the version from SharedConstants.getWorldVersion().getProtocolVersion() + Class sharedConstantsClass = Class.forName("net.minecraft.SharedConstants"); + Class worldVersionClass = Class.forName("net.minecraft.WorldVersion"); + Method getWorldVersionMethod = null; + for (Method method : sharedConstantsClass.getDeclaredMethods()) { + if (method.getReturnType() == worldVersionClass && method.getParameterTypes().length == 0) { + getWorldVersionMethod = method; + break; + } + } + Preconditions.checkNotNull(getWorldVersionMethod, "Failed to get world version method"); + + Object worldVersion = getWorldVersionMethod.invoke(null); + for (Method method : worldVersionClass.getDeclaredMethods()) { + if (method.getReturnType() == int.class && method.getParameterTypes().length == 0) { + return (int) method.invoke(worldVersion); + } + } + throw new IllegalAccessException("Failed to find protocol version method in WorldVersion"); + } + + private int veryCursedProtocolDetection() throws ReflectiveOperationException { + // Time to go on a journey! The protocol version is hidden inside an int in ServerPing.ServerData, that is only set once the server has ticked once // Grab a static instance of the server Class serverClazz = NMSUtil.nms("MinecraftServer", "net.minecraft.server.MinecraftServer"); Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer"); + Preconditions.checkNotNull(server, "Failed to get server instance"); // Grab the ping class and find the field to access it Class pingClazz = NMSUtil.nms( @@ -80,6 +110,7 @@ public class BukkitViaInjector extends LegacyViaInjector { break; } } + Preconditions.checkNotNull(ping, "Failed to get server ping"); // Now get the ServerData inside ServerPing Class serverDataClass = NMSUtil.nms( @@ -94,6 +125,7 @@ public class BukkitViaInjector extends LegacyViaInjector { break; } } + Preconditions.checkNotNull(serverData, "Failed to get server data"); // Get protocol version field for (Field field : serverDataClass.getDeclaredFields()) { @@ -155,7 +187,7 @@ public class BukkitViaInjector extends LegacyViaInjector { @Override public boolean lateProtocolVersionSetting() { - return !PaperViaInjector.PAPER_PROTOCOL_METHOD; + return !PaperViaInjector.PAPER_PROTOCOL_METHOD && !HAS_SHARED_CONSTANTS; } public boolean isBinded() { diff --git a/bungee/src/main/java/com/viaversion/viaversion/BungeePlugin.java b/bungee/src/main/java/com/viaversion/viaversion/BungeePlugin.java index 5e37de30a..a474f4189 100644 --- a/bungee/src/main/java/com/viaversion/viaversion/BungeePlugin.java +++ b/bungee/src/main/java/com/viaversion/viaversion/BungeePlugin.java @@ -126,13 +126,13 @@ public class BungeePlugin extends Plugin implements ViaServerProxyPlatform { } @Override - public PlatformTask runSync(Runnable runnable, long ticks) { - final Task task = Task.builder().plugin(container).execute(runnable).delay(Ticks.of(ticks)).build(); + public PlatformTask runSync(Runnable runnable, long delay) { + final Task task = Task.builder().plugin(container).execute(runnable).delay(Ticks.of(delay)).build(); return new SpongeViaTask(game.server().scheduler().submit(task)); } @Override - public PlatformTask runRepeatingSync(Runnable runnable, long ticks) { - final Task task = Task.builder().plugin(container).execute(runnable).interval(Ticks.of(ticks)).build(); + public PlatformTask runRepeatingSync(Runnable runnable, long period) { + final Task task = Task.builder().plugin(container).execute(runnable).interval(Ticks.of(period)).build(); return new SpongeViaTask(game.server().scheduler().submit(task)); } diff --git a/velocity/src/main/java/com/viaversion/viaversion/VelocityPlugin.java b/velocity/src/main/java/com/viaversion/viaversion/VelocityPlugin.java index 7d796afc4..c6ae351b6 100644 --- a/velocity/src/main/java/com/viaversion/viaversion/VelocityPlugin.java +++ b/velocity/src/main/java/com/viaversion/viaversion/VelocityPlugin.java @@ -155,17 +155,17 @@ public class VelocityPlugin implements ViaServerProxyPlatform { } @Override - public PlatformTask runSync(Runnable runnable, long ticks) { + public PlatformTask runSync(Runnable runnable, long delay) { return new VelocityViaTask( PROXY.getScheduler() .buildTask(this, runnable) - .delay(ticks * 50, TimeUnit.MILLISECONDS).schedule() + .delay(delay * 50, TimeUnit.MILLISECONDS).schedule() ); } @Override - public PlatformTask runRepeatingSync(Runnable runnable, long ticks) { - return runRepeatingAsync(runnable, ticks); + public PlatformTask runRepeatingSync(Runnable runnable, long period) { + return runRepeatingAsync(runnable, period); } @Override