From 3c0e30bff78a73a547017957732f3f1438f3b369 Mon Sep 17 00:00:00 2001 From: Tim203 Date: Fri, 31 Mar 2023 13:14:37 -0400 Subject: [PATCH] Folia support Co-Authored-By: Camotoy <20743703+Camotoy@users.noreply.github.com> --- build-logic/src/main/kotlin/Versions.kt | 2 +- settings.gradle.kts | 10 +--- spigot/build.gradle.kts | 15 +++++- .../module/SpigotPlatformModule.java | 2 +- .../pluginmessage/SpigotSkinApplier.java | 11 ++-- .../geysermc/floodgate/util/ClassNames.java | 6 +++ .../floodgate/util/SpigotCommandUtil.java | 10 ++-- .../util/SpigotVersionSpecificMethods.java | 53 ++++++++++++++----- spigot/src/main/resources/plugin.yml | 3 +- 9 files changed, 73 insertions(+), 39 deletions(-) diff --git a/build-logic/src/main/kotlin/Versions.kt b/build-logic/src/main/kotlin/Versions.kt index b501b9e2..a7d5d0ff 100644 --- a/build-logic/src/main/kotlin/Versions.kt +++ b/build-logic/src/main/kotlin/Versions.kt @@ -28,7 +28,7 @@ object Versions { const val cumulusVersion = "1.1.1" const val eventsVersion = "1.0-SNAPSHOT" const val configUtilsVersion = "1.0-SNAPSHOT" - const val spigotVersion = "1.13-R0.1-SNAPSHOT" + const val spigotVersion = "1.19.4-R0.1-SNAPSHOT" const val fastutilVersion = "8.5.3" const val guiceVersion = "5.1.0" const val nettyVersion = "4.1.49.Final" diff --git a/settings.gradle.kts b/settings.gradle.kts index 30992cbc..eee1e4e4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -4,7 +4,7 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { -// mavenLocal() + mavenLocal() // Geyser, Cumulus etc. maven("https://repo.opencollab.dev/maven-releases") { @@ -21,13 +21,7 @@ dependencyResolutionManagement { // maven("https://repo.papermc.io/repository/maven-snapshots") { // mavenContent { snapshotsOnly() } // } - maven("https://repo.papermc.io/repository/maven-public") { - content { - includeGroupByRegex( - "(io\\.papermc\\..*|com\\.destroystokyo\\..*|com\\.velocitypowered)" - ) - } - } + maven("https://repo.papermc.io/repository/maven-public") // Spigot maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots") { mavenContent { snapshotsOnly() } diff --git a/spigot/build.gradle.kts b/spigot/build.gradle.kts index 8bd8b9c0..2a819ac0 100644 --- a/spigot/build.gradle.kts +++ b/spigot/build.gradle.kts @@ -2,12 +2,26 @@ var authlibVersion = "1.5.21" var guavaVersion = "21.0" var gsonVersion = "2.8.5" +indra { + javaVersions { + // For Folia + target(8) + minimumToolchain(17) + } +} + dependencies { api(projects.core) implementation("cloud.commandframework", "cloud-bukkit", Versions.cloudVersion) // hack to make pre 1.12 work implementation("com.google.guava", "guava", guavaVersion) + + compileOnlyApi("dev.folia", "folia-api", Versions.spigotVersion) { + attributes { + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) + } + } } relocate("com.google.inject") @@ -21,7 +35,6 @@ relocate("com.google.guava") relocate("it.unimi") // these dependencies are already present on the platform -provided("com.destroystokyo.paper", "paper-api", Versions.spigotVersion) provided("com.mojang", "authlib", authlibVersion) provided("io.netty", "netty-transport", Versions.nettyVersion) provided("io.netty", "netty-codec", Versions.nettyVersion) diff --git a/spigot/src/main/java/org/geysermc/floodgate/module/SpigotPlatformModule.java b/spigot/src/main/java/org/geysermc/floodgate/module/SpigotPlatformModule.java index 0649280e..1c03dc95 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/module/SpigotPlatformModule.java +++ b/spigot/src/main/java/org/geysermc/floodgate/module/SpigotPlatformModule.java @@ -86,7 +86,7 @@ public final class SpigotPlatformModule extends AbstractModule { SpigotVersionSpecificMethods versionSpecificMethods, LanguageManager languageManager) { return new SpigotCommandUtil( - languageManager, plugin.getServer(), api, versionSpecificMethods, plugin); + languageManager, plugin.getServer(), api, versionSpecificMethods); } @Provides diff --git a/spigot/src/main/java/org/geysermc/floodgate/pluginmessage/SpigotSkinApplier.java b/spigot/src/main/java/org/geysermc/floodgate/pluginmessage/SpigotSkinApplier.java index fa599f40..4caa6f00 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/pluginmessage/SpigotSkinApplier.java +++ b/spigot/src/main/java/org/geysermc/floodgate/pluginmessage/SpigotSkinApplier.java @@ -33,7 +33,6 @@ import com.mojang.authlib.properties.PropertyMap; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.checkerframework.checker.nullness.qual.NonNull; -import org.geysermc.floodgate.SpigotPlugin; import org.geysermc.floodgate.api.event.skin.SkinApplyEvent; import org.geysermc.floodgate.api.event.skin.SkinApplyEvent.SkinData; import org.geysermc.floodgate.api.player.FloodgatePlayer; @@ -48,7 +47,6 @@ import org.geysermc.floodgate.util.SpigotVersionSpecificMethods; @Singleton public final class SpigotSkinApplier implements SkinApplier { @Inject private SpigotVersionSpecificMethods versionSpecificMethods; - @Inject private SpigotPlugin plugin; @Inject private EventBus eventBus; @Override @@ -62,8 +60,7 @@ public final class SpigotSkinApplier implements SkinApplier { // player is probably not logged in yet if (player == null) { if (firstTry) { - Bukkit.getScheduler().runTaskLater( - plugin, + versionSpecificMethods.schedule( () -> applySkin0(floodgatePlayer, skinData, false), 10 * 20 ); @@ -94,12 +91,10 @@ public final class SpigotSkinApplier implements SkinApplier { replaceSkin(properties, event.newSkin()); - // By running as a task, we don't run into async issues - plugin.getServer().getScheduler().runTask(plugin, () -> { + versionSpecificMethods.maybeSchedule(() -> { for (Player p : Bukkit.getOnlinePlayers()) { if (!p.equals(player) && p.canSee(player)) { - versionSpecificMethods.hidePlayer(p, player); - versionSpecificMethods.showPlayer(p, player); + versionSpecificMethods.hideAndShowPlayer(p, player); } } }); 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 1ca5105a..d4ec2b16 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/util/ClassNames.java +++ b/spigot/src/main/java/org/geysermc/floodgate/util/ClassNames.java @@ -78,6 +78,8 @@ public class ClassNames { public static final Field BUNGEE; + public static final boolean IS_FOLIA; + static { String version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; SPIGOT_MAPPING_PREFIX = "net.minecraft.server." + version; @@ -223,6 +225,10 @@ public class ClassNames { PAPER_VELOCITY_SUPPORT = null; } } + + IS_FOLIA = ReflectionUtils.getClass( + "io.papermc.paper.threadedregions.scheduler.EntityScheduler" + ) != null; } private static T checkNotNull(@CheckForNull T toCheck, @CheckForNull String objectName) { diff --git a/spigot/src/main/java/org/geysermc/floodgate/util/SpigotCommandUtil.java b/spigot/src/main/java/org/geysermc/floodgate/util/SpigotCommandUtil.java index da3d65bc..4950309d 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/util/SpigotCommandUtil.java +++ b/spigot/src/main/java/org/geysermc/floodgate/util/SpigotCommandUtil.java @@ -27,11 +27,9 @@ package org.geysermc.floodgate.util; import java.util.Collection; import java.util.UUID; -import org.bukkit.Bukkit; import org.bukkit.Server; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.bukkit.plugin.java.JavaPlugin; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.floodgate.api.FloodgateApi; import org.geysermc.floodgate.platform.command.CommandUtil; @@ -42,19 +40,17 @@ import org.geysermc.floodgate.player.UserAudience.PlayerAudience; public final class SpigotCommandUtil extends CommandUtil { private final Server server; private final SpigotVersionSpecificMethods versionSpecificMethods; - private final JavaPlugin plugin; private UserAudience console; public SpigotCommandUtil( LanguageManager manager, Server server, FloodgateApi api, - SpigotVersionSpecificMethods versionSpecificMethods, - JavaPlugin plugin) { + SpigotVersionSpecificMethods versionSpecificMethods + ) { super(manager, api); this.server = server; this.versionSpecificMethods = versionSpecificMethods; - this.plugin = plugin; } @Override @@ -120,7 +116,7 @@ public final class SpigotCommandUtil extends CommandUtil { public void kickPlayer(Object player, String message) { // can also be console if (player instanceof Player) { - Bukkit.getScheduler().runTask(plugin, () -> ((Player) player).kickPlayer(message)); + versionSpecificMethods.schedule(() -> ((Player) player).kickPlayer(message), 0); } } diff --git a/spigot/src/main/java/org/geysermc/floodgate/util/SpigotVersionSpecificMethods.java b/spigot/src/main/java/org/geysermc/floodgate/util/SpigotVersionSpecificMethods.java index f8e67616..e0dfcb2d 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/util/SpigotVersionSpecificMethods.java +++ b/spigot/src/main/java/org/geysermc/floodgate/util/SpigotVersionSpecificMethods.java @@ -25,16 +25,21 @@ package org.geysermc.floodgate.util; +import java.lang.reflect.Method; +import java.util.concurrent.TimeUnit; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.geysermc.floodgate.SpigotPlugin; public final class SpigotVersionSpecificMethods { - private static final boolean NEW_GET_LOCALE; + private static final Method GET_SPIGOT; + private static final Method OLD_GET_LOCALE; private static final boolean NEW_VISIBILITY; static { - NEW_GET_LOCALE = ReflectionUtils.getMethod(Player.class, "getLocale") != null; + GET_SPIGOT = ReflectionUtils.getMethod(Player.class, "spigot"); + OLD_GET_LOCALE = ReflectionUtils.getMethod(Player.Spigot.class, "getLocale"); + NEW_VISIBILITY = null != ReflectionUtils.getMethod( Player.class, "hidePlayer", Plugin.class, Player.class @@ -48,27 +53,51 @@ public final class SpigotVersionSpecificMethods { } public String getLocale(Player player) { - if (NEW_GET_LOCALE) { + if (OLD_GET_LOCALE == null) { return player.getLocale(); } - return player.spigot().getLocale(); + Object spigot = ReflectionUtils.invoke(player, GET_SPIGOT); + return ReflectionUtils.castedInvoke(spigot, OLD_GET_LOCALE); + } + + public void hideAndShowPlayer(Player on, Player target) { + // In Folia we don't have to schedule this as there is no concept of a single main thread. + // Instead, we have to schedule the task per player. + if (ClassNames.IS_FOLIA) { + on.getScheduler().execute(plugin, () -> hideAndShowPlayer0(on, target), null, 0); + return; + } + hideAndShowPlayer0(on, target); + } + + public void schedule(Runnable runnable, long delay) { + if (ClassNames.IS_FOLIA) { + plugin.getServer().getAsyncScheduler().runDelayed( + plugin, $ -> runnable.run(), delay * 50, TimeUnit.MILLISECONDS + ); + return; + } + plugin.getServer().getScheduler().runTaskLater(plugin, runnable, delay); } @SuppressWarnings("deprecation") - public void hidePlayer(Player hideFor, Player playerToHide) { + private void hideAndShowPlayer0(Player source, Player target) { if (NEW_VISIBILITY) { - hideFor.hidePlayer(plugin, playerToHide); + source.hidePlayer(plugin, target); + source.showPlayer(plugin, target); return; } - hideFor.hidePlayer(playerToHide); + source.hidePlayer(target); + source.showPlayer(target); } - @SuppressWarnings("deprecation") - public void showPlayer(Player showFor, Player playerToShow) { - if (NEW_VISIBILITY) { - showFor.showPlayer(plugin, playerToShow); + public void maybeSchedule(Runnable runnable) { + // In Folia we don't have to schedule this as there is no concept of a single main thread. + // Instead, we have to schedule the task per player. + if (ClassNames.IS_FOLIA) { + runnable.run(); return; } - showFor.showPlayer(playerToShow); + plugin.getServer().getScheduler().runTask(plugin, runnable); } } diff --git a/spigot/src/main/resources/plugin.yml b/spigot/src/main/resources/plugin.yml index c9a5d232..0c9fe9f1 100644 --- a/spigot/src/main/resources/plugin.yml +++ b/spigot/src/main/resources/plugin.yml @@ -4,4 +4,5 @@ version: ${version} author: ${author} website: ${url} main: org.geysermc.floodgate.SpigotPlugin -api-version: 1.13 \ No newline at end of file +api-version: 1.13 +folia-supported: true \ No newline at end of file