Fix protocol detection on 1.19.4 Spigot

Fixes #3241
This commit is contained in:
Nassim Jahnke 2023-03-15 10:08:49 +01:00
parent a828c43f99
commit b1524642aa
No known key found for this signature in database
GPG Key ID: 6BE3B555EBC5982B
7 changed files with 62 additions and 31 deletions

View File

@ -104,23 +104,22 @@ public interface ViaPlatform<T> {
PlatformTask runSync(Runnable runnable); PlatformTask runSync(Runnable runnable);
/** /**
* Run a task Sync after a interval * Runs a synchronous task after a delay in ticks.
* This must be only used after plugin enable.
* *
* @param runnable The task to run * @param runnable task to run
* @param ticks The interval to run it after * @param delay delay in ticks to run it after
* @return The Task ID * @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 runnable task to run
* @param ticks The interval to run it at * @param period period in ticks to run at
* @return The Task ID * @return created task
*/ */
PlatformTask runRepeatingSync(Runnable runnable, long ticks); PlatformTask runRepeatingSync(Runnable runnable, long period);
/** /**
* Get the online players * Get the online players

View File

@ -171,13 +171,13 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform<Player>
} }
@Override @Override
public PlatformTask runSync(Runnable runnable, long ticks) { public PlatformTask runSync(Runnable runnable, long delay) {
return new BukkitViaTask(getServer().getScheduler().runTaskLater(this, runnable, ticks)); return new BukkitViaTask(getServer().getScheduler().runTaskLater(this, runnable, delay));
} }
@Override @Override
public PlatformTask runRepeatingSync(Runnable runnable, long ticks) { public PlatformTask runRepeatingSync(Runnable runnable, long period) {
return new BukkitViaTask(getServer().getScheduler().runTaskTimer(this, runnable, 0, ticks)); return new BukkitViaTask(getServer().getScheduler().runTaskTimer(this, runnable, 0, period));
} }
@Override @Override

View File

@ -17,6 +17,7 @@
*/ */
package com.viaversion.viaversion.bukkit.platform; package com.viaversion.viaversion.bukkit.platform;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.bukkit.handlers.BukkitChannelInitializer; import com.viaversion.viaversion.bukkit.handlers.BukkitChannelInitializer;
import com.viaversion.viaversion.bukkit.util.NMSUtil; import com.viaversion.viaversion.bukkit.util.NMSUtil;
import com.viaversion.viaversion.platform.LegacyViaInjector; import com.viaversion.viaversion.platform.LegacyViaInjector;
@ -35,6 +36,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public class BukkitViaInjector extends LegacyViaInjector { public class BukkitViaInjector extends LegacyViaInjector {
private static final boolean HAS_SHARED_CONSTANTS = PaperViaInjector.hasClass("net.minecraft.SharedConstants") && PaperViaInjector.hasClass("net.minecraft.WorldVersion");
@Override @Override
public void inject() throws ReflectiveOperationException { public void inject() throws ReflectiveOperationException {
if (PaperViaInjector.PAPER_INJECTION_METHOD) { if (PaperViaInjector.PAPER_INJECTION_METHOD) {
@ -62,10 +65,37 @@ public class BukkitViaInjector extends LegacyViaInjector {
return Bukkit.getUnsafe().getProtocolVersion(); 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 // Grab a static instance of the server
Class<?> serverClazz = NMSUtil.nms("MinecraftServer", "net.minecraft.server.MinecraftServer"); Class<?> serverClazz = NMSUtil.nms("MinecraftServer", "net.minecraft.server.MinecraftServer");
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer"); 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 // Grab the ping class and find the field to access it
Class<?> pingClazz = NMSUtil.nms( Class<?> pingClazz = NMSUtil.nms(
@ -80,6 +110,7 @@ public class BukkitViaInjector extends LegacyViaInjector {
break; break;
} }
} }
Preconditions.checkNotNull(ping, "Failed to get server ping");
// Now get the ServerData inside ServerPing // Now get the ServerData inside ServerPing
Class<?> serverDataClass = NMSUtil.nms( Class<?> serverDataClass = NMSUtil.nms(
@ -94,6 +125,7 @@ public class BukkitViaInjector extends LegacyViaInjector {
break; break;
} }
} }
Preconditions.checkNotNull(serverData, "Failed to get server data");
// Get protocol version field // Get protocol version field
for (Field field : serverDataClass.getDeclaredFields()) { for (Field field : serverDataClass.getDeclaredFields()) {
@ -155,7 +187,7 @@ public class BukkitViaInjector extends LegacyViaInjector {
@Override @Override
public boolean lateProtocolVersionSetting() { public boolean lateProtocolVersionSetting() {
return !PaperViaInjector.PAPER_PROTOCOL_METHOD; return !PaperViaInjector.PAPER_PROTOCOL_METHOD && !HAS_SHARED_CONSTANTS;
} }
public boolean isBinded() { public boolean isBinded() {

View File

@ -126,13 +126,13 @@ public class BungeePlugin extends Plugin implements ViaServerProxyPlatform<Proxi
} }
@Override @Override
public PlatformTask runSync(Runnable runnable, long ticks) { public PlatformTask runSync(Runnable runnable, long delay) {
return new BungeeViaTask(getProxy().getScheduler().schedule(this, runnable, ticks * 50, TimeUnit.MILLISECONDS)); return new BungeeViaTask(getProxy().getScheduler().schedule(this, runnable, delay * 50, TimeUnit.MILLISECONDS));
} }
@Override @Override
public PlatformTask runRepeatingSync(Runnable runnable, long ticks) { public PlatformTask runRepeatingSync(Runnable runnable, long period) {
return runRepeatingAsync(runnable, ticks); return runRepeatingAsync(runnable, period);
} }
@Override @Override

View File

@ -71,12 +71,12 @@ public final class TestPlatform implements ViaPlatform {
} }
@Override @Override
public PlatformTask runSync(Runnable runnable, long ticks) { public PlatformTask runSync(Runnable runnable, long delay) {
return null; return null;
} }
@Override @Override
public PlatformTask runRepeatingSync(Runnable runnable, long ticks) { public PlatformTask runRepeatingSync(Runnable runnable, long period) {
return null; return null;
} }

View File

@ -153,14 +153,14 @@ public class SpongePlugin implements ViaPlatform<Player> {
} }
@Override @Override
public PlatformTask runSync(Runnable runnable, long ticks) { public PlatformTask runSync(Runnable runnable, long delay) {
final Task task = Task.builder().plugin(container).execute(runnable).delay(Ticks.of(ticks)).build(); final Task task = Task.builder().plugin(container).execute(runnable).delay(Ticks.of(delay)).build();
return new SpongeViaTask(game.server().scheduler().submit(task)); return new SpongeViaTask(game.server().scheduler().submit(task));
} }
@Override @Override
public PlatformTask runRepeatingSync(Runnable runnable, long ticks) { public PlatformTask runRepeatingSync(Runnable runnable, long period) {
final Task task = Task.builder().plugin(container).execute(runnable).interval(Ticks.of(ticks)).build(); final Task task = Task.builder().plugin(container).execute(runnable).interval(Ticks.of(period)).build();
return new SpongeViaTask(game.server().scheduler().submit(task)); return new SpongeViaTask(game.server().scheduler().submit(task));
} }

View File

@ -155,17 +155,17 @@ public class VelocityPlugin implements ViaServerProxyPlatform<Player> {
} }
@Override @Override
public PlatformTask runSync(Runnable runnable, long ticks) { public PlatformTask runSync(Runnable runnable, long delay) {
return new VelocityViaTask( return new VelocityViaTask(
PROXY.getScheduler() PROXY.getScheduler()
.buildTask(this, runnable) .buildTask(this, runnable)
.delay(ticks * 50, TimeUnit.MILLISECONDS).schedule() .delay(delay * 50, TimeUnit.MILLISECONDS).schedule()
); );
} }
@Override @Override
public PlatformTask runRepeatingSync(Runnable runnable, long ticks) { public PlatformTask runRepeatingSync(Runnable runnable, long period) {
return runRepeatingAsync(runnable, ticks); return runRepeatingAsync(runnable, period);
} }
@Override @Override