diff --git a/WindSpigot-Server/pom.xml b/WindSpigot-Server/pom.xml index 68bcfcf7..38626b83 100644 --- a/WindSpigot-Server/pom.xml +++ b/WindSpigot-Server/pom.xml @@ -155,13 +155,17 @@ 3.21.0 - - - - net.kyori - adventure-key - 4.10.1 - + + net.kyori + adventure-key + 4.10.1 + + + + org.javassist + javassist + 3.29.2-GA + diff --git a/WindSpigot-Server/src/main/java/com/windpvp/windspigot/commons/PluginUtils.java b/WindSpigot-Server/src/main/java/com/windpvp/windspigot/commons/PluginUtils.java index 30859f84..d33a04fa 100644 --- a/WindSpigot-Server/src/main/java/com/windpvp/windspigot/commons/PluginUtils.java +++ b/WindSpigot-Server/src/main/java/com/windpvp/windspigot/commons/PluginUtils.java @@ -1,13 +1,28 @@ package com.windpvp.windspigot.commons; + import org.bukkit.plugin.Plugin; -/** - * @author Elierrr - */ public class PluginUtils { + public static int getCitizensBuild(Plugin plugin) { + if (plugin == null || plugin.getDescription() == null) { + return 2396; + } + return parseCitizensBuild(plugin.getDescription().getVersion()); + } + + public static int parseCitizensBuild(String version) { try { - return Integer.parseInt(plugin.getDescription().getVersion().split("\\(build ")[1].replace(")", "")); + if (version == null) { + return 2396; + } + if (version.contains("(build ")) { + return Integer.parseInt(version.split("\\(build ")[1].replace(")", "").trim()); + } + if (version.startsWith("2.0.25") || version.startsWith("2.0.26") || version.startsWith("2.0.27")) { + return 1000; + } + return 2396; } catch (Throwable ignored) { return 2396; } diff --git a/WindSpigot-Server/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/WindSpigot-Server/src/main/java/org/bukkit/craftbukkit/CraftServer.java index d96c817f..ba2eb89e 100644 --- a/WindSpigot-Server/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/WindSpigot-Server/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -169,6 +169,10 @@ import net.minecraft.server.WorldSettings; import net.minecraft.server.WorldType; import xyz.sculas.nacho.malware.AntiMalware; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; +import javassist.LoaderClassPath; public final class CraftServer implements Server { private static final Player[] EMPTY_PLAYER_ARRAY = new Player[0]; @@ -371,19 +375,30 @@ public void loadPlugins() { } // Nacho end - // Nacho start - Add notice for older Citizens versions + // WindSpigot start - GamingOP69 - Auto-patch older Citizens EmptyChannel for Netty 4.1 compatibility else if (plugin.getDescription().getFullName().contains("Citizens")) { if (PluginUtils.getCitizensBuild(plugin) < 2396) { - logger.warning("Please update to Citizens 2.0.28 #7 or higher!\n" - + "Previously, there was a fix for older versions, but that has been removed.\n" - + "So, if you want Citizens to work, please update!\n" - + "You can download the latest version with this link: " - + "https://ci.citizensnpcs.co/job/Citizens2/\n" - + "Sleeping for 10s so this message can be read."); - Thread.sleep(10000); + try { + ClassPool pool = ClassPool.getDefault(); + pool.insertClassPath(new LoaderClassPath(plugin.getClass().getClassLoader())); + pool.importPackage("io.netty.channel.ChannelMetadata"); + + CtClass emptyChannel = pool.get("net.citizensnpcs.nms.v1_8_R3.network.EmptyChannel"); + if (emptyChannel.isFrozen()) { + emptyChannel.defrost(); + } + + CtMethod metaData = emptyChannel.getDeclaredMethods("metadata")[0]; + metaData.setBody("{ return new ChannelMetadata(true); }"); + + emptyChannel.toClass(plugin.getClass().getClassLoader(), plugin.getClass().getProtectionDomain()); + logger.info("Successfully patched Citizens EmptyChannel for Netty 4.1 compatibility!"); + } catch (Throwable t) { + logger.warning("Could not automatically patch Citizens: " + t.getMessage()); + } } } - // Nacho end + // WindSpigot end - GamingOP69 plugin.getLogger().info(String.format("Loading %s", plugin.getDescription().getFullName())); plugin.onLoad(); diff --git a/WindSpigot-Server/src/test/java/com/windpvp/windspigot/citizens/CitizensVersionDetectionTest.java b/WindSpigot-Server/src/test/java/com/windpvp/windspigot/citizens/CitizensVersionDetectionTest.java new file mode 100644 index 00000000..31bfe815 --- /dev/null +++ b/WindSpigot-Server/src/test/java/com/windpvp/windspigot/citizens/CitizensVersionDetectionTest.java @@ -0,0 +1,38 @@ +package com.windpvp.windspigot.citizens; + +import com.windpvp.windspigot.commons.PluginUtils; +import org.junit.Assert; +import org.junit.Test; + +public class CitizensVersionDetectionTest { + + @Test + public void testOlderBuildDetected() { + int build = PluginUtils.parseCitizensBuild("2.0.25-SNAPSHOT (build 1770)"); + Assert.assertEquals(1770, build); + Assert.assertTrue("Older build 1770 must be less than 2396", build < 2396); + } + + @Test + public void testLegacyVersionWithoutBuildDetected() { + int build25 = PluginUtils.parseCitizensBuild("2.0.25"); + Assert.assertTrue("2.0.25 must trigger older build detection", build25 < 2396); + + int build26 = PluginUtils.parseCitizensBuild("2.0.26-SNAPSHOT"); + Assert.assertTrue("2.0.26 must trigger older build detection", build26 < 2396); + } + + @Test + public void testNewerBuildDetected() { + int build = PluginUtils.parseCitizensBuild("2.0.28-SNAPSHOT (build 2400)"); + Assert.assertEquals(2400, build); + Assert.assertTrue("Newer build 2400 must be >= 2396", build >= 2396); + } + + @Test + public void testFallbackOnNullOrUnknownVersion() { + Assert.assertEquals(2396, PluginUtils.parseCitizensBuild(null)); + Assert.assertEquals(2396, PluginUtils.parseCitizensBuild("unknown-version")); + Assert.assertEquals(2396, PluginUtils.getCitizensBuild(null)); + } +}