From 6305db8aec0fd7a2b0d30e69a247e9c04d50c94f Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:07:57 +0200 Subject: [PATCH 01/26] Use folia api against paper api --- Bukkit/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bukkit/build.gradle.kts b/Bukkit/build.gradle.kts index 4b89438f56..a5983bb1f0 100644 --- a/Bukkit/build.gradle.kts +++ b/Bukkit/build.gradle.kts @@ -24,7 +24,7 @@ dependencies { implementation("org.bstats:bstats-bukkit") // Paper - compileOnly("io.papermc.paper:paper-api") + compileOnly("dev.folia:folia-api:1.19.4-R0.1-SNAPSHOT") implementation("io.papermc:paperlib") // Plugins From 1ddeec6f156f3c1038d11e19a459b4d64c119e03 Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:08:11 +0200 Subject: [PATCH 02/26] Implement run paper for folia --- build.gradle.kts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index 083d2b82f4..f8489a63ab 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,6 +15,8 @@ plugins { eclipse idea + + id("xyz.jpenilla.run-paper") version "2.0.2-SNAPSHOT" } group = "com.plotsquared" @@ -218,3 +220,14 @@ nexusPublishing { tasks.getByName("jar") { enabled = false } + +tasks { + register("runFolia") { + downloadsApiService.set(xyz.jpenilla.runtask.service.DownloadsAPIService.folia(project)) + minecraftVersion("1.19.4") + group = "run paper" + runDirectory.set(file("run-folia")) + pluginJars(*project(":PlotSquared-Bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } + .toTypedArray()) + } +} From f5c606f573d32b060e98beee7178bb206574c71e Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:08:52 +0200 Subject: [PATCH 03/26] Add folia support class --- .../plotsquared/bukkit/util/FoliaSupport.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/FoliaSupport.java diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/FoliaSupport.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/FoliaSupport.java new file mode 100644 index 0000000000..fc9d019f7d --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/FoliaSupport.java @@ -0,0 +1,39 @@ +package com.plotsquared.bukkit.util; + +public final class FoliaSupport { + private FoliaSupport() { + + } + + private static final boolean IS_FOLIA; + + private static final Class TICK_THREAD_CLASS; + static { + boolean isFolia = false; + try { + // Assume API is present + Class.forName("io.papermc.paper.threadedregions.scheduler.EntityScheduler"); + isFolia = true; + } catch (Exception ignored) { + + } + IS_FOLIA = isFolia; + Class tickThreadClass = String.class; // thread will never be instance of String + if (IS_FOLIA) { + try { + tickThreadClass = Class.forName("io.papermc.paper.util.TickThread"); + } catch (ClassNotFoundException e) { + throw new AssertionError(e); + } + } + TICK_THREAD_CLASS = tickThreadClass; + } + + public static boolean isFolia() { + return IS_FOLIA; + } + + public static boolean isTickThread() { + return TICK_THREAD_CLASS.isInstance(Thread.currentThread()); + } +} From 6727d850fc3098a37e895519ab22724d9df139d8 Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:09:12 +0200 Subject: [PATCH 04/26] Add specialized folia task manager --- .../bukkit/util/task/FoliaTaskManager.java | 201 ++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java new file mode 100644 index 0000000000..1c0ae0cbcd --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java @@ -0,0 +1,201 @@ +package com.plotsquared.bukkit.util.task; + +import com.google.inject.Singleton; +import com.plotsquared.bukkit.BukkitPlatform; +import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.util.task.PlotSquaredTask; +import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.util.Location; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Method; +import java.util.concurrent.Callable; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import static java.lang.invoke.MethodHandles.dropReturn; +import static java.lang.invoke.MethodHandles.explicitCastArguments; +import static java.lang.invoke.MethodHandles.filterArguments; +import static java.lang.invoke.MethodHandles.insertArguments; +import static java.lang.invoke.MethodType.methodType; + +/** + * Bukkit implementation of {@link TaskManager} using + * by {@link org.bukkit.scheduler.BukkitScheduler} and {@link BukkitPlotSquaredTask} + */ +@Singleton +public class FoliaTaskManager extends TaskManager { + + private final BukkitPlatform bukkitMain; + private final TaskTime.TimeConverter timeConverter; + + private final ScheduledExecutorService backgroundExecutor = Executors.newSingleThreadScheduledExecutor(); + + public FoliaTaskManager(final BukkitPlatform bukkitMain, final TaskTime.TimeConverter timeConverter) { + this.bukkitMain = bukkitMain; + this.timeConverter = timeConverter; + } + + @Override + public T sync(final @NonNull Callable function, final int timeout) throws Exception { + return backgroundExecutor.schedule(function, timeout, TimeUnit.MILLISECONDS).get(); + } + + @Override + public Future callMethodSync(final @NonNull Callable method) { + return backgroundExecutor.submit(method); + } + + @Override + public PlotSquaredTask taskRepeat(@NonNull final Runnable runnable, @NonNull final TaskTime taskTime) { + var time = switch (taskTime.getUnit()) { + case TICKS -> timeConverter.ticksToMs(taskTime.getTime()); + case MILLISECONDS -> taskTime.getTime(); + }; + backgroundExecutor.scheduleAtFixedRate(runnable, 0, time, TimeUnit.MILLISECONDS); + return PlotSquaredTask.nullTask(); + } + + @Override + public PlotSquaredTask taskRepeatAsync(@NonNull final Runnable runnable, @NonNull final TaskTime taskTime) { + var time = switch (taskTime.getUnit()) { + case TICKS -> timeConverter.ticksToMs(taskTime.getTime()); + case MILLISECONDS -> taskTime.getTime(); + }; + Bukkit.getAsyncScheduler().runAtFixedRate(bukkitMain, scheduledTask -> runnable.run(), 0, time, TimeUnit.MILLISECONDS); + return PlotSquaredTask.nullTask(); + } + + @Override + public void taskAsync(@NonNull final Runnable runnable) { + Bukkit.getAsyncScheduler().runNow(bukkitMain, scheduledTask -> runnable.run()); + } + + @Override + public void task(@NonNull final Runnable runnable) { + backgroundExecutor.submit(runnable); + } + + @Override + public void taskLater(@NonNull final Runnable runnable, @NonNull final TaskTime taskTime) { + var time = switch (taskTime.getUnit()) { + case TICKS -> timeConverter.ticksToMs(taskTime.getTime()); + case MILLISECONDS -> taskTime.getTime(); + }; + backgroundExecutor.scheduleWithFixedDelay(runnable, 0, time, TimeUnit.MILLISECONDS); + } + + @Override + public void taskLaterAsync(@NonNull final Runnable runnable, @NonNull final TaskTime taskTime) { + var time = switch (taskTime.getUnit()) { + case TICKS -> timeConverter.ticksToMs(taskTime.getTime()); + case MILLISECONDS -> taskTime.getTime(); + }; + Bukkit.getAsyncScheduler().runDelayed(this.bukkitMain, scheduledTask -> runnable.run(), time, TimeUnit.MILLISECONDS); + } + + private static class SchedulerAdapter { + + private static final MethodHandle EXECUTE_FOR_LOCATION; + private static final MethodHandle EXECUTE_FOR_PLAYER; + private static final Runnable THROW_IF_RETIRED = () -> throwRetired(); + + private static final MethodType LOCATION_EXECUTE_TYPE = methodType( + void.class, + Plugin.class, + org.bukkit.Location.class, + Runnable.class + ); + + private static final MethodType ENTITY_EXECUTE_TYPE = methodType( + boolean.class, + Plugin.class, + Runnable.class, + Runnable.class, + long.class + ); + + static { + final Plugin pluginInstance = ((Plugin) PlotSquared.get()); + final MethodHandles.Lookup lookup = MethodHandles.lookup(); + + MethodHandle executeForLocation; + + MethodHandle executeForPlayer; + try { + Class regionisedSchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.FoliaRegionScheduler"); + final Method method = Bukkit.class.getDeclaredMethod("getRegionScheduler"); + executeForLocation = lookup.findVirtual( + regionisedSchedulerClass, + "execute", + LOCATION_EXECUTE_TYPE + ); + executeForLocation = executeForLocation.bindTo(method.invoke(null)); + executeForLocation = executeForLocation.bindTo(pluginInstance); + + Class entitySchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.EntityScheduler"); + executeForPlayer = lookup.findVirtual( + entitySchedulerClass, + "execute", + ENTITY_EXECUTE_TYPE + ); + // (ES, P, R, R, L)Z (ES, R, R, L)Z + executeForPlayer = insertArguments(executeForPlayer, 1, pluginInstance); + // (ES, R1, R2, L)Z -> (ES, R1)Z + executeForPlayer = insertArguments(executeForPlayer, 2, THROW_IF_RETIRED, 0); + // (ES, R1)Z -> (ES, R1)V + executeForPlayer = dropReturn(executeForPlayer); + MethodHandle getScheduler = lookup.findVirtual( + org.bukkit.entity.Entity.class, + "getScheduler", + methodType(entitySchedulerClass) + ); + // (ES, R1)V -> (E, R1)V + executeForPlayer = filterArguments(executeForPlayer, 0, getScheduler); + MethodType finalType = methodType(void.class, org.bukkit.entity.Player.class, Runnable.class); + // (ES, R1)V -> (P, R1)V + executeForPlayer = explicitCastArguments(executeForPlayer, finalType); + } catch (Throwable throwable) { + throw new AssertionError(throwable); + } + EXECUTE_FOR_LOCATION = executeForLocation; + EXECUTE_FOR_PLAYER = executeForPlayer; + } + + static void executeForLocation(Location location, Runnable task) { + try { + EXECUTE_FOR_LOCATION.invokeExact(BukkitAdapter.adapt(location), task); + } catch (Error | RuntimeException e) { + throw e; + } catch (Throwable other) { + throw new RuntimeException(other); + } + } + static void executeForEntity(Player player, Runnable task) { + try { + EXECUTE_FOR_PLAYER.invokeExact(BukkitAdapter.adapt(player), task); + } catch (Error | RuntimeException e) { + throw e; + } catch (Throwable other) { + throw new RuntimeException(other); + } + } + + private static void throwRetired() { + throw new RuntimeException("Player retired"); + } + + } + +} From c6bab2a463cbdf46507d7ea6e8ee6ce1128535b0 Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:09:21 +0200 Subject: [PATCH 05/26] Enable folia support --- Bukkit/src/main/resources/plugin.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/Bukkit/src/main/resources/plugin.yml b/Bukkit/src/main/resources/plugin.yml index 10a9ae0192..a59406a694 100644 --- a/Bukkit/src/main/resources/plugin.yml +++ b/Bukkit/src/main/resources/plugin.yml @@ -420,3 +420,4 @@ permissions: plots.done: true plots.continue: true plots.middle: true +folia-supported: true From accce8971fa02df7adfaacd41eb03a147a5e1dbe Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:09:33 +0200 Subject: [PATCH 06/26] Add snapshot support for run paper --- settings.gradle.kts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/settings.gradle.kts b/settings.gradle.kts index c35882d558..f7db267686 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,3 +6,12 @@ project(":Core").name = "PlotSquared-Core" project(":Bukkit").name = "PlotSquared-Bukkit" enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") +pluginManagement { + repositories { + gradlePluginPortal() + maven { + name = "jmp repository" + url = uri("https://repo.jpenilla.xyz/snapshots") + } + } +} From dcb11e16d64f51cdbecb26461de2066ae0aadcca Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:09:50 +0200 Subject: [PATCH 07/26] Implement folia support --- .../plotsquared/bukkit/BukkitPlatform.java | 108 ++++++------------ 1 file changed, 33 insertions(+), 75 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java index 2b05b97429..7c33eb3e1a 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java @@ -18,57 +18,28 @@ */ package com.plotsquared.bukkit; -import com.google.inject.Guice; -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.Singleton; -import com.google.inject.Stage; -import com.google.inject.TypeLiteral; +import com.google.inject.*; import com.plotsquared.bukkit.generator.BukkitPlotGenerator; import com.plotsquared.bukkit.inject.BackupModule; import com.plotsquared.bukkit.inject.BukkitModule; import com.plotsquared.bukkit.inject.PermissionModule; import com.plotsquared.bukkit.inject.WorldManagerModule; -import com.plotsquared.bukkit.listener.BlockEventListener; -import com.plotsquared.bukkit.listener.BlockEventListener117; -import com.plotsquared.bukkit.listener.ChunkListener; -import com.plotsquared.bukkit.listener.EntityEventListener; -import com.plotsquared.bukkit.listener.EntitySpawnListener; -import com.plotsquared.bukkit.listener.PaperListener; -import com.plotsquared.bukkit.listener.PlayerEventListener; -import com.plotsquared.bukkit.listener.ProjectileEventListener; -import com.plotsquared.bukkit.listener.ServerListener; -import com.plotsquared.bukkit.listener.SingleWorldListener; -import com.plotsquared.bukkit.listener.SpigotListener; -import com.plotsquared.bukkit.listener.WorldEvents; +import com.plotsquared.bukkit.listener.*; import com.plotsquared.bukkit.placeholder.PAPIPlaceholders; import com.plotsquared.bukkit.placeholder.PlaceholderFormatter; import com.plotsquared.bukkit.player.BukkitPlayer; import com.plotsquared.bukkit.player.BukkitPlayerManager; -import com.plotsquared.bukkit.util.BukkitUtil; -import com.plotsquared.bukkit.util.BukkitWorld; -import com.plotsquared.bukkit.util.SetGenCB; -import com.plotsquared.bukkit.util.TranslationUpdateManager; -import com.plotsquared.bukkit.util.UpdateUtility; +import com.plotsquared.bukkit.util.*; import com.plotsquared.bukkit.util.task.BukkitTaskManager; +import com.plotsquared.bukkit.util.task.FoliaTaskManager; import com.plotsquared.bukkit.util.task.PaperTimeConverter; import com.plotsquared.bukkit.util.task.SpigotTimeConverter; -import com.plotsquared.bukkit.uuid.EssentialsUUIDService; -import com.plotsquared.bukkit.uuid.LuckPermsUUIDService; -import com.plotsquared.bukkit.uuid.OfflinePlayerUUIDService; -import com.plotsquared.bukkit.uuid.PaperUUIDService; -import com.plotsquared.bukkit.uuid.SQLiteUUIDService; -import com.plotsquared.bukkit.uuid.SquirrelIdUUIDService; +import com.plotsquared.bukkit.uuid.*; import com.plotsquared.core.PlotPlatform; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.backup.BackupManager; import com.plotsquared.core.components.ComponentPresetManager; -import com.plotsquared.core.configuration.ConfigurationNode; -import com.plotsquared.core.configuration.ConfigurationSection; -import com.plotsquared.core.configuration.ConfigurationUtil; -import com.plotsquared.core.configuration.Settings; -import com.plotsquared.core.configuration.Storage; +import com.plotsquared.core.configuration.*; import com.plotsquared.core.configuration.caption.ChatFormatter; import com.plotsquared.core.configuration.file.YamlConfiguration; import com.plotsquared.core.database.DBFunc; @@ -77,20 +48,12 @@ import com.plotsquared.core.generator.GeneratorWrapper; import com.plotsquared.core.generator.IndependentPlotGenerator; import com.plotsquared.core.generator.SingleWorldGenerator; -import com.plotsquared.core.inject.annotations.BackgroundPipeline; -import com.plotsquared.core.inject.annotations.DefaultGenerator; -import com.plotsquared.core.inject.annotations.ImpromptuPipeline; -import com.plotsquared.core.inject.annotations.WorldConfig; -import com.plotsquared.core.inject.annotations.WorldFile; +import com.plotsquared.core.inject.annotations.*; import com.plotsquared.core.inject.modules.PlotSquaredModule; import com.plotsquared.core.listener.PlotListener; import com.plotsquared.core.listener.WESubscriber; import com.plotsquared.core.player.PlotPlayer; -import com.plotsquared.core.plot.Plot; -import com.plotsquared.core.plot.PlotArea; -import com.plotsquared.core.plot.PlotAreaTerrainType; -import com.plotsquared.core.plot.PlotAreaType; -import com.plotsquared.core.plot.PlotId; +import com.plotsquared.core.plot.*; import com.plotsquared.core.plot.comment.CommentManager; import com.plotsquared.core.plot.flag.implementations.ServerPlotFlag; import com.plotsquared.core.plot.world.PlotAreaManager; @@ -98,14 +61,7 @@ import com.plotsquared.core.plot.world.SinglePlotAreaManager; import com.plotsquared.core.setup.PlotAreaBuilder; import com.plotsquared.core.setup.SettingsNodesWrapper; -import com.plotsquared.core.util.EventDispatcher; -import com.plotsquared.core.util.FileUtils; -import com.plotsquared.core.util.PlatformWorldManager; -import com.plotsquared.core.util.PlayerManager; -import com.plotsquared.core.util.PremiumVerification; -import com.plotsquared.core.util.ReflectionUtils; -import com.plotsquared.core.util.SetupUtils; -import com.plotsquared.core.util.WorldUtil; +import com.plotsquared.core.util.*; import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.task.TaskTime; import com.plotsquared.core.uuid.CacheUUIDService; @@ -143,27 +99,13 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Queue; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import static com.plotsquared.core.util.PremiumVerification.getDownloadID; -import static com.plotsquared.core.util.PremiumVerification.getResourceID; -import static com.plotsquared.core.util.PremiumVerification.getUserID; +import static com.plotsquared.core.util.PremiumVerification.*; import static com.plotsquared.core.util.ReflectionUtils.getRefClass; @SuppressWarnings("unused") @@ -264,7 +206,12 @@ public void onEnable() { // Stuff that needs to be created before the PlotSquared instance PlotPlayer.registerConverter(Player.class, BukkitUtil::adapt); - TaskManager.setPlatformImplementation(new BukkitTaskManager(this, timeConverter)); + if (FoliaSupport.isFolia()) { + TaskManager.setPlatformImplementation(new FoliaTaskManager(this, timeConverter)); + } else { + TaskManager.setPlatformImplementation(new BukkitTaskManager(this, timeConverter)); + } + final PlotSquared plotSquared = new PlotSquared(this, "Bukkit"); @@ -558,9 +505,7 @@ public void onEnable() { e.printStackTrace(); } } - - // Clean up potential memory leak - Bukkit.getScheduler().runTaskTimer(this, () -> { + Runnable cleanUp = () -> { try { for (final PlotPlayer player : this.playerManager().getPlayers()) { if (player.getPlatformPlayer() == null || !player.getPlatformPlayer().isOnline()) { @@ -570,7 +515,15 @@ public void onEnable() { } catch (final Exception e) { getLogger().warning("Failed to clean up players: " + e.getMessage()); } - }, 100L, 100L); + }; + if (FoliaSupport.isFolia()) { + Bukkit.getGlobalRegionScheduler().runAtFixedRate(this, scheduledTask -> { + cleanUp.run(); + }, 100, 100); + } else { + // Clean up potential memory leak + Bukkit.getScheduler().runTaskTimer(this, cleanUp, 100L, 100L); + } // Check if we are in a safe environment ServerLib.checkUnsafeForks(); @@ -728,7 +681,12 @@ private void startUuidCaching( @Override public void onDisable() { PlotSquared.get().disable(); - Bukkit.getScheduler().cancelTasks(this); + if (FoliaSupport.isFolia()) { + Bukkit.getAsyncScheduler().cancelTasks(this); + Bukkit.getGlobalRegionScheduler().cancelTasks(this); + } else { + Bukkit.getScheduler().cancelTasks(this); + } } @Override From 19cde4011c861fada10bd7ca2b0ee735b9758342 Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:10:23 +0200 Subject: [PATCH 08/26] Extend git ignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index b0ccc3fffb..309092131f 100644 --- a/.gitignore +++ b/.gitignore @@ -137,3 +137,6 @@ docs/ build/ .DS_Store +### Run Paper +run-folia/ +run/ From 0e0b4e2d9904c3aa10031e4ec24910eb0e670eb1 Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:32:42 +0200 Subject: [PATCH 09/26] Exclude 1.20 biome for 1.19 --- .../com/plotsquared/bukkit/generator/BukkitPlotGenerator.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java index 767bcd3751..05ad8f6335 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java @@ -436,6 +436,9 @@ private final class BukkitPlotBiomeProvider extends BiomeProvider { static { ArrayList biomes = new ArrayList<>(List.of(Biome.values())); biomes.remove(Biome.CUSTOM); + if (PlotSquared.platform().serverVersion()[1] <= 19) { + biomes.remove(Biome.CHERRY_GROVE); + } BIOMES = List.copyOf(biomes); } From c31aea7c7698230a0db6aeb57c785ec63d3c9b8d Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:33:04 +0200 Subject: [PATCH 10/26] Check if world creation folia api --- .../bukkit/managers/BukkitWorldManager.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java index 7397d7b5c4..3e8f032160 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java @@ -19,6 +19,7 @@ package com.plotsquared.bukkit.managers; import com.google.inject.Singleton; +import com.plotsquared.bukkit.util.FoliaSupport; import com.plotsquared.core.configuration.file.YamlConfiguration; import com.plotsquared.core.util.PlatformWorldManager; import org.bukkit.Bukkit; @@ -48,13 +49,16 @@ public void initialize() { @Override public @Nullable World handleWorldCreation(@NonNull String worldName, @Nullable String generator) { this.setGenerator(worldName, generator); - final WorldCreator wc = new WorldCreator(worldName); - wc.environment(World.Environment.NORMAL); - if (generator != null) { - wc.generator(generator); - wc.type(WorldType.FLAT); + if (!FoliaSupport.isFolia()) { + final WorldCreator wc = new WorldCreator(worldName); + wc.environment(World.Environment.NORMAL); + if (generator != null) { + wc.generator(generator); + wc.type(WorldType.FLAT); + } + return Bukkit.createWorld(wc); } - return Bukkit.createWorld(wc); + return null; } protected void setGenerator(final @Nullable String worldName, final @Nullable String generator) { From 129859ef2435cca4d9314a030e7f516aecf68149 Mon Sep 17 00:00:00 2001 From: TheMeinerLP Date: Mon, 5 Jun 2023 20:56:49 +0200 Subject: [PATCH 11/26] Fix command processing for folia servers --- .../util/task/FoliaPlotSquaredTask.java | 61 +++++++++++++++++++ .../bukkit/util/task/FoliaTaskManager.java | 37 +++++------ 2 files changed, 81 insertions(+), 17 deletions(-) create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaPlotSquaredTask.java diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaPlotSquaredTask.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaPlotSquaredTask.java new file mode 100644 index 0000000000..6a44df8278 --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaPlotSquaredTask.java @@ -0,0 +1,61 @@ +package com.plotsquared.bukkit.util.task; + +import com.plotsquared.core.util.task.PlotSquaredTask; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.TimeUnit; + +public final class FoliaPlotSquaredTask implements PlotSquaredTask { + + @NonNull + private final Runnable runnable; + @NotNull + private final JavaPlugin javaPlugin; + + private ScheduledTask task; + + public FoliaPlotSquaredTask(final @NonNull Runnable runnable, final JavaPlugin javaPlugin) { + this.runnable = runnable; + this.javaPlugin = javaPlugin; + } + + @Override + public void runTask() { + this.task = Bukkit.getGlobalRegionScheduler().run(javaPlugin, scheduledTask -> this.runnable.run()); + } + + public void runTaskLater(long delay) { + this.task = Bukkit.getGlobalRegionScheduler().runDelayed(javaPlugin, scheduledTask -> this.runnable.run(), delay); + } + + public void runTaskLaterAsynchronously(long delay) { + this.task = Bukkit.getAsyncScheduler().runDelayed(javaPlugin, scheduledTask -> this.runnable.run(), delay, TimeUnit.MILLISECONDS); + } + + public void runTaskAsynchronously() { + this.task = Bukkit.getAsyncScheduler().runNow(javaPlugin, scheduledTask -> this.runnable.run()); + } + + public void runTaskTimerAsynchronously(long delay, long period) { + this.task = Bukkit.getAsyncScheduler().runAtFixedRate(javaPlugin, scheduledTask -> this.runnable.run(), delay, period, TimeUnit.MILLISECONDS); + } + + public void runTaskTimer(long delay, long period) { + this.task = Bukkit.getGlobalRegionScheduler().runAtFixedRate(javaPlugin, scheduledTask -> this.runnable.run(), delay, period); + } + + @Override + public boolean isCancelled() { + return this.task.isCancelled(); + } + + @Override + public void cancel() { + this.task.cancel(); + } + +} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java index 1c0ae0cbcd..cd98307946 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java @@ -49,7 +49,10 @@ public FoliaTaskManager(final BukkitPlatform bukkitMain, final TaskTime.TimeConv @Override public T sync(final @NonNull Callable function, final int timeout) throws Exception { - return backgroundExecutor.schedule(function, timeout, TimeUnit.MILLISECONDS).get(); + if (PlotSquared.get().isMainThread(Thread.currentThread())) { + return function.call(); + } + return this.callMethodSync(function).get(timeout, TimeUnit.MILLISECONDS); } @Override @@ -59,12 +62,10 @@ public Future callMethodSync(final @NonNull Callable method) { @Override public PlotSquaredTask taskRepeat(@NonNull final Runnable runnable, @NonNull final TaskTime taskTime) { - var time = switch (taskTime.getUnit()) { - case TICKS -> timeConverter.ticksToMs(taskTime.getTime()); - case MILLISECONDS -> taskTime.getTime(); - }; - backgroundExecutor.scheduleAtFixedRate(runnable, 0, time, TimeUnit.MILLISECONDS); - return PlotSquaredTask.nullTask(); + final long ticks = this.timeConverter.toTicks(taskTime); + final FoliaPlotSquaredTask foliaPlotSquaredTask = new FoliaPlotSquaredTask(runnable, this.bukkitMain); + foliaPlotSquaredTask.runTaskTimer(ticks, ticks); + return foliaPlotSquaredTask; } @Override @@ -73,27 +74,29 @@ public PlotSquaredTask taskRepeatAsync(@NonNull final Runnable runnable, @NonNul case TICKS -> timeConverter.ticksToMs(taskTime.getTime()); case MILLISECONDS -> taskTime.getTime(); }; - Bukkit.getAsyncScheduler().runAtFixedRate(bukkitMain, scheduledTask -> runnable.run(), 0, time, TimeUnit.MILLISECONDS); - return PlotSquaredTask.nullTask(); + final FoliaPlotSquaredTask foliaPlotSquaredTask = new FoliaPlotSquaredTask(runnable, this.bukkitMain); + foliaPlotSquaredTask.runTaskTimerAsynchronously(time, time); + return foliaPlotSquaredTask; } @Override public void taskAsync(@NonNull final Runnable runnable) { - Bukkit.getAsyncScheduler().runNow(bukkitMain, scheduledTask -> runnable.run()); + if (this.bukkitMain.isEnabled()) { + new FoliaPlotSquaredTask(runnable, this.bukkitMain).runTaskAsynchronously(); + } else { + runnable.run(); + } + } @Override public void task(@NonNull final Runnable runnable) { - backgroundExecutor.submit(runnable); + new FoliaPlotSquaredTask(runnable, this.bukkitMain).runTask(); } @Override public void taskLater(@NonNull final Runnable runnable, @NonNull final TaskTime taskTime) { - var time = switch (taskTime.getUnit()) { - case TICKS -> timeConverter.ticksToMs(taskTime.getTime()); - case MILLISECONDS -> taskTime.getTime(); - }; - backgroundExecutor.scheduleWithFixedDelay(runnable, 0, time, TimeUnit.MILLISECONDS); + new FoliaPlotSquaredTask(runnable, this.bukkitMain).runTaskLater(this.timeConverter.toTicks(taskTime)); } @Override @@ -102,7 +105,7 @@ public void taskLaterAsync(@NonNull final Runnable runnable, @NonNull final Task case TICKS -> timeConverter.ticksToMs(taskTime.getTime()); case MILLISECONDS -> taskTime.getTime(); }; - Bukkit.getAsyncScheduler().runDelayed(this.bukkitMain, scheduledTask -> runnable.run(), time, TimeUnit.MILLISECONDS); + new FoliaPlotSquaredTask(runnable, this.bukkitMain).runTaskLaterAsynchronously(time); } private static class SchedulerAdapter { From fe475803859e4ad2a45f7f37b99eef7bedccbe25 Mon Sep 17 00:00:00 2001 From: TheMeinerLP Date: Mon, 5 Jun 2023 21:21:12 +0200 Subject: [PATCH 12/26] Fix chunk coordinator for folia --- .../bukkit/queue/BukkitChunkCoordinator.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java index fc3ce73703..d0a2bcd2dc 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java @@ -21,6 +21,7 @@ import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import com.plotsquared.bukkit.BukkitPlatform; +import com.plotsquared.bukkit.util.FoliaSupport; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.queue.ChunkCoordinator; import com.plotsquared.core.queue.subscriber.ProgressSubscriber; @@ -160,6 +161,7 @@ public void run() { } Chunk chunk = this.availableChunks.poll(); + if (chunk == null) { if (this.availableChunks.isEmpty()) { if (this.requestedChunks.isEmpty() && loadingChunks.get() == 0) { @@ -175,7 +177,20 @@ public void run() { do { final long start = System.currentTimeMillis(); try { - this.chunkConsumer.accept(BlockVector2.at(chunk.getX(), chunk.getZ())); + if (FoliaSupport.isFolia()) { + var tempChunk = chunk; + Bukkit.getRegionScheduler().run( + this.plugin, + this.bukkitWorld, + chunk.getX(), + chunk.getZ(), + scheduledTask -> { + this.chunkConsumer.accept(BlockVector2.at(tempChunk.getX(), tempChunk.getZ())); + } + ); + } else { + this.chunkConsumer.accept(BlockVector2.at(chunk.getX(), chunk.getZ())); + } } catch (final Throwable throwable) { this.throwableConsumer.accept(throwable); } @@ -188,6 +203,8 @@ public void run() { iterationTime[0] = iterationTime[1]; iterationTime[1] = end - start; } while (iterationTime[0] + iterationTime[1] < this.maxIterationTime * 2 && (chunk = availableChunks.poll()) != null); + + if (processedChunks < this.batchSize) { // Adjust batch size based on the amount of processed chunks per tick this.batchSize = processedChunks; From 654c48e2f96ee42f54053c9486878cfea08983b2 Mon Sep 17 00:00:00 2001 From: TheMeinerLP Date: Mon, 5 Jun 2023 21:32:05 +0200 Subject: [PATCH 13/26] Remove unused code --- .../bukkit/util/task/FoliaTaskManager.java | 93 ------------------- 1 file changed, 93 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java index cd98307946..77a61c76c6 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java @@ -108,97 +108,4 @@ public void taskLaterAsync(@NonNull final Runnable runnable, @NonNull final Task new FoliaPlotSquaredTask(runnable, this.bukkitMain).runTaskLaterAsynchronously(time); } - private static class SchedulerAdapter { - - private static final MethodHandle EXECUTE_FOR_LOCATION; - private static final MethodHandle EXECUTE_FOR_PLAYER; - private static final Runnable THROW_IF_RETIRED = () -> throwRetired(); - - private static final MethodType LOCATION_EXECUTE_TYPE = methodType( - void.class, - Plugin.class, - org.bukkit.Location.class, - Runnable.class - ); - - private static final MethodType ENTITY_EXECUTE_TYPE = methodType( - boolean.class, - Plugin.class, - Runnable.class, - Runnable.class, - long.class - ); - - static { - final Plugin pluginInstance = ((Plugin) PlotSquared.get()); - final MethodHandles.Lookup lookup = MethodHandles.lookup(); - - MethodHandle executeForLocation; - - MethodHandle executeForPlayer; - try { - Class regionisedSchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.FoliaRegionScheduler"); - final Method method = Bukkit.class.getDeclaredMethod("getRegionScheduler"); - executeForLocation = lookup.findVirtual( - regionisedSchedulerClass, - "execute", - LOCATION_EXECUTE_TYPE - ); - executeForLocation = executeForLocation.bindTo(method.invoke(null)); - executeForLocation = executeForLocation.bindTo(pluginInstance); - - Class entitySchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.EntityScheduler"); - executeForPlayer = lookup.findVirtual( - entitySchedulerClass, - "execute", - ENTITY_EXECUTE_TYPE - ); - // (ES, P, R, R, L)Z (ES, R, R, L)Z - executeForPlayer = insertArguments(executeForPlayer, 1, pluginInstance); - // (ES, R1, R2, L)Z -> (ES, R1)Z - executeForPlayer = insertArguments(executeForPlayer, 2, THROW_IF_RETIRED, 0); - // (ES, R1)Z -> (ES, R1)V - executeForPlayer = dropReturn(executeForPlayer); - MethodHandle getScheduler = lookup.findVirtual( - org.bukkit.entity.Entity.class, - "getScheduler", - methodType(entitySchedulerClass) - ); - // (ES, R1)V -> (E, R1)V - executeForPlayer = filterArguments(executeForPlayer, 0, getScheduler); - MethodType finalType = methodType(void.class, org.bukkit.entity.Player.class, Runnable.class); - // (ES, R1)V -> (P, R1)V - executeForPlayer = explicitCastArguments(executeForPlayer, finalType); - } catch (Throwable throwable) { - throw new AssertionError(throwable); - } - EXECUTE_FOR_LOCATION = executeForLocation; - EXECUTE_FOR_PLAYER = executeForPlayer; - } - - static void executeForLocation(Location location, Runnable task) { - try { - EXECUTE_FOR_LOCATION.invokeExact(BukkitAdapter.adapt(location), task); - } catch (Error | RuntimeException e) { - throw e; - } catch (Throwable other) { - throw new RuntimeException(other); - } - } - static void executeForEntity(Player player, Runnable task) { - try { - EXECUTE_FOR_PLAYER.invokeExact(BukkitAdapter.adapt(player), task); - } catch (Error | RuntimeException e) { - throw e; - } catch (Throwable other) { - throw new RuntimeException(other); - } - } - - private static void throwRetired() { - throw new RuntimeException("Player retired"); - } - - } - } From 3138d672acab5e7e3ee7675b896194170f1445b3 Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:07:57 +0200 Subject: [PATCH 14/26] Use folia api against paper api --- Bukkit/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bukkit/build.gradle.kts b/Bukkit/build.gradle.kts index 33d2335144..dc623d39a5 100644 --- a/Bukkit/build.gradle.kts +++ b/Bukkit/build.gradle.kts @@ -24,7 +24,7 @@ dependencies { implementation("org.bstats:bstats-bukkit") // Paper - compileOnly("io.papermc.paper:paper-api") + compileOnly("dev.folia:folia-api:1.19.4-R0.1-SNAPSHOT") implementation("io.papermc:paperlib") // Plugins From c09d842a6453ac8a289706a1b0df759431055bea Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:08:11 +0200 Subject: [PATCH 15/26] Implement run paper for folia --- build.gradle.kts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index b7963f49af..7992da98a4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -234,4 +234,12 @@ tasks { runDirectory.set(file("run-$it")) } } + register("runFolia") { + downloadsApiService.set(xyz.jpenilla.runtask.service.DownloadsAPIService.folia(project)) + minecraftVersion("1.19.4") + group = "run paper" + runDirectory.set(file("run-folia")) + pluginJars(*project(":PlotSquared-Bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } + .toTypedArray()) + } } From 402805d31e088e08707333872e9d7f92a50fe76b Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:08:52 +0200 Subject: [PATCH 16/26] Add folia support class --- .../plotsquared/bukkit/util/FoliaSupport.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/FoliaSupport.java diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/FoliaSupport.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/FoliaSupport.java new file mode 100644 index 0000000000..fc9d019f7d --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/FoliaSupport.java @@ -0,0 +1,39 @@ +package com.plotsquared.bukkit.util; + +public final class FoliaSupport { + private FoliaSupport() { + + } + + private static final boolean IS_FOLIA; + + private static final Class TICK_THREAD_CLASS; + static { + boolean isFolia = false; + try { + // Assume API is present + Class.forName("io.papermc.paper.threadedregions.scheduler.EntityScheduler"); + isFolia = true; + } catch (Exception ignored) { + + } + IS_FOLIA = isFolia; + Class tickThreadClass = String.class; // thread will never be instance of String + if (IS_FOLIA) { + try { + tickThreadClass = Class.forName("io.papermc.paper.util.TickThread"); + } catch (ClassNotFoundException e) { + throw new AssertionError(e); + } + } + TICK_THREAD_CLASS = tickThreadClass; + } + + public static boolean isFolia() { + return IS_FOLIA; + } + + public static boolean isTickThread() { + return TICK_THREAD_CLASS.isInstance(Thread.currentThread()); + } +} From e104e0f024e4b84a4ff87182c8ffc989655fe33c Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:09:12 +0200 Subject: [PATCH 17/26] Add specialized folia task manager --- .../bukkit/util/task/FoliaTaskManager.java | 201 ++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java new file mode 100644 index 0000000000..1c0ae0cbcd --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java @@ -0,0 +1,201 @@ +package com.plotsquared.bukkit.util.task; + +import com.google.inject.Singleton; +import com.plotsquared.bukkit.BukkitPlatform; +import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.util.task.PlotSquaredTask; +import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.util.Location; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Method; +import java.util.concurrent.Callable; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import static java.lang.invoke.MethodHandles.dropReturn; +import static java.lang.invoke.MethodHandles.explicitCastArguments; +import static java.lang.invoke.MethodHandles.filterArguments; +import static java.lang.invoke.MethodHandles.insertArguments; +import static java.lang.invoke.MethodType.methodType; + +/** + * Bukkit implementation of {@link TaskManager} using + * by {@link org.bukkit.scheduler.BukkitScheduler} and {@link BukkitPlotSquaredTask} + */ +@Singleton +public class FoliaTaskManager extends TaskManager { + + private final BukkitPlatform bukkitMain; + private final TaskTime.TimeConverter timeConverter; + + private final ScheduledExecutorService backgroundExecutor = Executors.newSingleThreadScheduledExecutor(); + + public FoliaTaskManager(final BukkitPlatform bukkitMain, final TaskTime.TimeConverter timeConverter) { + this.bukkitMain = bukkitMain; + this.timeConverter = timeConverter; + } + + @Override + public T sync(final @NonNull Callable function, final int timeout) throws Exception { + return backgroundExecutor.schedule(function, timeout, TimeUnit.MILLISECONDS).get(); + } + + @Override + public Future callMethodSync(final @NonNull Callable method) { + return backgroundExecutor.submit(method); + } + + @Override + public PlotSquaredTask taskRepeat(@NonNull final Runnable runnable, @NonNull final TaskTime taskTime) { + var time = switch (taskTime.getUnit()) { + case TICKS -> timeConverter.ticksToMs(taskTime.getTime()); + case MILLISECONDS -> taskTime.getTime(); + }; + backgroundExecutor.scheduleAtFixedRate(runnable, 0, time, TimeUnit.MILLISECONDS); + return PlotSquaredTask.nullTask(); + } + + @Override + public PlotSquaredTask taskRepeatAsync(@NonNull final Runnable runnable, @NonNull final TaskTime taskTime) { + var time = switch (taskTime.getUnit()) { + case TICKS -> timeConverter.ticksToMs(taskTime.getTime()); + case MILLISECONDS -> taskTime.getTime(); + }; + Bukkit.getAsyncScheduler().runAtFixedRate(bukkitMain, scheduledTask -> runnable.run(), 0, time, TimeUnit.MILLISECONDS); + return PlotSquaredTask.nullTask(); + } + + @Override + public void taskAsync(@NonNull final Runnable runnable) { + Bukkit.getAsyncScheduler().runNow(bukkitMain, scheduledTask -> runnable.run()); + } + + @Override + public void task(@NonNull final Runnable runnable) { + backgroundExecutor.submit(runnable); + } + + @Override + public void taskLater(@NonNull final Runnable runnable, @NonNull final TaskTime taskTime) { + var time = switch (taskTime.getUnit()) { + case TICKS -> timeConverter.ticksToMs(taskTime.getTime()); + case MILLISECONDS -> taskTime.getTime(); + }; + backgroundExecutor.scheduleWithFixedDelay(runnable, 0, time, TimeUnit.MILLISECONDS); + } + + @Override + public void taskLaterAsync(@NonNull final Runnable runnable, @NonNull final TaskTime taskTime) { + var time = switch (taskTime.getUnit()) { + case TICKS -> timeConverter.ticksToMs(taskTime.getTime()); + case MILLISECONDS -> taskTime.getTime(); + }; + Bukkit.getAsyncScheduler().runDelayed(this.bukkitMain, scheduledTask -> runnable.run(), time, TimeUnit.MILLISECONDS); + } + + private static class SchedulerAdapter { + + private static final MethodHandle EXECUTE_FOR_LOCATION; + private static final MethodHandle EXECUTE_FOR_PLAYER; + private static final Runnable THROW_IF_RETIRED = () -> throwRetired(); + + private static final MethodType LOCATION_EXECUTE_TYPE = methodType( + void.class, + Plugin.class, + org.bukkit.Location.class, + Runnable.class + ); + + private static final MethodType ENTITY_EXECUTE_TYPE = methodType( + boolean.class, + Plugin.class, + Runnable.class, + Runnable.class, + long.class + ); + + static { + final Plugin pluginInstance = ((Plugin) PlotSquared.get()); + final MethodHandles.Lookup lookup = MethodHandles.lookup(); + + MethodHandle executeForLocation; + + MethodHandle executeForPlayer; + try { + Class regionisedSchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.FoliaRegionScheduler"); + final Method method = Bukkit.class.getDeclaredMethod("getRegionScheduler"); + executeForLocation = lookup.findVirtual( + regionisedSchedulerClass, + "execute", + LOCATION_EXECUTE_TYPE + ); + executeForLocation = executeForLocation.bindTo(method.invoke(null)); + executeForLocation = executeForLocation.bindTo(pluginInstance); + + Class entitySchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.EntityScheduler"); + executeForPlayer = lookup.findVirtual( + entitySchedulerClass, + "execute", + ENTITY_EXECUTE_TYPE + ); + // (ES, P, R, R, L)Z (ES, R, R, L)Z + executeForPlayer = insertArguments(executeForPlayer, 1, pluginInstance); + // (ES, R1, R2, L)Z -> (ES, R1)Z + executeForPlayer = insertArguments(executeForPlayer, 2, THROW_IF_RETIRED, 0); + // (ES, R1)Z -> (ES, R1)V + executeForPlayer = dropReturn(executeForPlayer); + MethodHandle getScheduler = lookup.findVirtual( + org.bukkit.entity.Entity.class, + "getScheduler", + methodType(entitySchedulerClass) + ); + // (ES, R1)V -> (E, R1)V + executeForPlayer = filterArguments(executeForPlayer, 0, getScheduler); + MethodType finalType = methodType(void.class, org.bukkit.entity.Player.class, Runnable.class); + // (ES, R1)V -> (P, R1)V + executeForPlayer = explicitCastArguments(executeForPlayer, finalType); + } catch (Throwable throwable) { + throw new AssertionError(throwable); + } + EXECUTE_FOR_LOCATION = executeForLocation; + EXECUTE_FOR_PLAYER = executeForPlayer; + } + + static void executeForLocation(Location location, Runnable task) { + try { + EXECUTE_FOR_LOCATION.invokeExact(BukkitAdapter.adapt(location), task); + } catch (Error | RuntimeException e) { + throw e; + } catch (Throwable other) { + throw new RuntimeException(other); + } + } + static void executeForEntity(Player player, Runnable task) { + try { + EXECUTE_FOR_PLAYER.invokeExact(BukkitAdapter.adapt(player), task); + } catch (Error | RuntimeException e) { + throw e; + } catch (Throwable other) { + throw new RuntimeException(other); + } + } + + private static void throwRetired() { + throw new RuntimeException("Player retired"); + } + + } + +} From 1fa9d0cb302b6572dedd6d3e18569c17d947a539 Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:09:21 +0200 Subject: [PATCH 18/26] Enable folia support --- Bukkit/src/main/resources/plugin.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/Bukkit/src/main/resources/plugin.yml b/Bukkit/src/main/resources/plugin.yml index 10a9ae0192..a59406a694 100644 --- a/Bukkit/src/main/resources/plugin.yml +++ b/Bukkit/src/main/resources/plugin.yml @@ -420,3 +420,4 @@ permissions: plots.done: true plots.continue: true plots.middle: true +folia-supported: true From 43d71fe64be7ce71dbe02f2ea3cb09a24b08a941 Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:09:33 +0200 Subject: [PATCH 19/26] Add snapshot support for run paper --- settings.gradle.kts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/settings.gradle.kts b/settings.gradle.kts index c35882d558..f7db267686 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,3 +6,12 @@ project(":Core").name = "PlotSquared-Core" project(":Bukkit").name = "PlotSquared-Bukkit" enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") +pluginManagement { + repositories { + gradlePluginPortal() + maven { + name = "jmp repository" + url = uri("https://repo.jpenilla.xyz/snapshots") + } + } +} From 086138bbcd717cb5ab03926166b2bd45bdd8cff2 Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:09:50 +0200 Subject: [PATCH 20/26] Implement folia support --- .../plotsquared/bukkit/BukkitPlatform.java | 108 ++++++------------ 1 file changed, 33 insertions(+), 75 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java index 2b05b97429..7c33eb3e1a 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java @@ -18,57 +18,28 @@ */ package com.plotsquared.bukkit; -import com.google.inject.Guice; -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.Singleton; -import com.google.inject.Stage; -import com.google.inject.TypeLiteral; +import com.google.inject.*; import com.plotsquared.bukkit.generator.BukkitPlotGenerator; import com.plotsquared.bukkit.inject.BackupModule; import com.plotsquared.bukkit.inject.BukkitModule; import com.plotsquared.bukkit.inject.PermissionModule; import com.plotsquared.bukkit.inject.WorldManagerModule; -import com.plotsquared.bukkit.listener.BlockEventListener; -import com.plotsquared.bukkit.listener.BlockEventListener117; -import com.plotsquared.bukkit.listener.ChunkListener; -import com.plotsquared.bukkit.listener.EntityEventListener; -import com.plotsquared.bukkit.listener.EntitySpawnListener; -import com.plotsquared.bukkit.listener.PaperListener; -import com.plotsquared.bukkit.listener.PlayerEventListener; -import com.plotsquared.bukkit.listener.ProjectileEventListener; -import com.plotsquared.bukkit.listener.ServerListener; -import com.plotsquared.bukkit.listener.SingleWorldListener; -import com.plotsquared.bukkit.listener.SpigotListener; -import com.plotsquared.bukkit.listener.WorldEvents; +import com.plotsquared.bukkit.listener.*; import com.plotsquared.bukkit.placeholder.PAPIPlaceholders; import com.plotsquared.bukkit.placeholder.PlaceholderFormatter; import com.plotsquared.bukkit.player.BukkitPlayer; import com.plotsquared.bukkit.player.BukkitPlayerManager; -import com.plotsquared.bukkit.util.BukkitUtil; -import com.plotsquared.bukkit.util.BukkitWorld; -import com.plotsquared.bukkit.util.SetGenCB; -import com.plotsquared.bukkit.util.TranslationUpdateManager; -import com.plotsquared.bukkit.util.UpdateUtility; +import com.plotsquared.bukkit.util.*; import com.plotsquared.bukkit.util.task.BukkitTaskManager; +import com.plotsquared.bukkit.util.task.FoliaTaskManager; import com.plotsquared.bukkit.util.task.PaperTimeConverter; import com.plotsquared.bukkit.util.task.SpigotTimeConverter; -import com.plotsquared.bukkit.uuid.EssentialsUUIDService; -import com.plotsquared.bukkit.uuid.LuckPermsUUIDService; -import com.plotsquared.bukkit.uuid.OfflinePlayerUUIDService; -import com.plotsquared.bukkit.uuid.PaperUUIDService; -import com.plotsquared.bukkit.uuid.SQLiteUUIDService; -import com.plotsquared.bukkit.uuid.SquirrelIdUUIDService; +import com.plotsquared.bukkit.uuid.*; import com.plotsquared.core.PlotPlatform; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.backup.BackupManager; import com.plotsquared.core.components.ComponentPresetManager; -import com.plotsquared.core.configuration.ConfigurationNode; -import com.plotsquared.core.configuration.ConfigurationSection; -import com.plotsquared.core.configuration.ConfigurationUtil; -import com.plotsquared.core.configuration.Settings; -import com.plotsquared.core.configuration.Storage; +import com.plotsquared.core.configuration.*; import com.plotsquared.core.configuration.caption.ChatFormatter; import com.plotsquared.core.configuration.file.YamlConfiguration; import com.plotsquared.core.database.DBFunc; @@ -77,20 +48,12 @@ import com.plotsquared.core.generator.GeneratorWrapper; import com.plotsquared.core.generator.IndependentPlotGenerator; import com.plotsquared.core.generator.SingleWorldGenerator; -import com.plotsquared.core.inject.annotations.BackgroundPipeline; -import com.plotsquared.core.inject.annotations.DefaultGenerator; -import com.plotsquared.core.inject.annotations.ImpromptuPipeline; -import com.plotsquared.core.inject.annotations.WorldConfig; -import com.plotsquared.core.inject.annotations.WorldFile; +import com.plotsquared.core.inject.annotations.*; import com.plotsquared.core.inject.modules.PlotSquaredModule; import com.plotsquared.core.listener.PlotListener; import com.plotsquared.core.listener.WESubscriber; import com.plotsquared.core.player.PlotPlayer; -import com.plotsquared.core.plot.Plot; -import com.plotsquared.core.plot.PlotArea; -import com.plotsquared.core.plot.PlotAreaTerrainType; -import com.plotsquared.core.plot.PlotAreaType; -import com.plotsquared.core.plot.PlotId; +import com.plotsquared.core.plot.*; import com.plotsquared.core.plot.comment.CommentManager; import com.plotsquared.core.plot.flag.implementations.ServerPlotFlag; import com.plotsquared.core.plot.world.PlotAreaManager; @@ -98,14 +61,7 @@ import com.plotsquared.core.plot.world.SinglePlotAreaManager; import com.plotsquared.core.setup.PlotAreaBuilder; import com.plotsquared.core.setup.SettingsNodesWrapper; -import com.plotsquared.core.util.EventDispatcher; -import com.plotsquared.core.util.FileUtils; -import com.plotsquared.core.util.PlatformWorldManager; -import com.plotsquared.core.util.PlayerManager; -import com.plotsquared.core.util.PremiumVerification; -import com.plotsquared.core.util.ReflectionUtils; -import com.plotsquared.core.util.SetupUtils; -import com.plotsquared.core.util.WorldUtil; +import com.plotsquared.core.util.*; import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.task.TaskTime; import com.plotsquared.core.uuid.CacheUUIDService; @@ -143,27 +99,13 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Queue; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import static com.plotsquared.core.util.PremiumVerification.getDownloadID; -import static com.plotsquared.core.util.PremiumVerification.getResourceID; -import static com.plotsquared.core.util.PremiumVerification.getUserID; +import static com.plotsquared.core.util.PremiumVerification.*; import static com.plotsquared.core.util.ReflectionUtils.getRefClass; @SuppressWarnings("unused") @@ -264,7 +206,12 @@ public void onEnable() { // Stuff that needs to be created before the PlotSquared instance PlotPlayer.registerConverter(Player.class, BukkitUtil::adapt); - TaskManager.setPlatformImplementation(new BukkitTaskManager(this, timeConverter)); + if (FoliaSupport.isFolia()) { + TaskManager.setPlatformImplementation(new FoliaTaskManager(this, timeConverter)); + } else { + TaskManager.setPlatformImplementation(new BukkitTaskManager(this, timeConverter)); + } + final PlotSquared plotSquared = new PlotSquared(this, "Bukkit"); @@ -558,9 +505,7 @@ public void onEnable() { e.printStackTrace(); } } - - // Clean up potential memory leak - Bukkit.getScheduler().runTaskTimer(this, () -> { + Runnable cleanUp = () -> { try { for (final PlotPlayer player : this.playerManager().getPlayers()) { if (player.getPlatformPlayer() == null || !player.getPlatformPlayer().isOnline()) { @@ -570,7 +515,15 @@ public void onEnable() { } catch (final Exception e) { getLogger().warning("Failed to clean up players: " + e.getMessage()); } - }, 100L, 100L); + }; + if (FoliaSupport.isFolia()) { + Bukkit.getGlobalRegionScheduler().runAtFixedRate(this, scheduledTask -> { + cleanUp.run(); + }, 100, 100); + } else { + // Clean up potential memory leak + Bukkit.getScheduler().runTaskTimer(this, cleanUp, 100L, 100L); + } // Check if we are in a safe environment ServerLib.checkUnsafeForks(); @@ -728,7 +681,12 @@ private void startUuidCaching( @Override public void onDisable() { PlotSquared.get().disable(); - Bukkit.getScheduler().cancelTasks(this); + if (FoliaSupport.isFolia()) { + Bukkit.getAsyncScheduler().cancelTasks(this); + Bukkit.getGlobalRegionScheduler().cancelTasks(this); + } else { + Bukkit.getScheduler().cancelTasks(this); + } } @Override From b72001ce599a2219d7b2f4b043b4011082296994 Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:10:23 +0200 Subject: [PATCH 21/26] Extend git ignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 0b17ea5b10..f977e2edf7 100644 --- a/.gitignore +++ b/.gitignore @@ -137,6 +137,9 @@ docs/ build/ .DS_Store +### Run Paper +run-folia/ +run/ # Ignore run folders run-[0-0].[0-9]/ run-[0-0].[0-9].[0-9]/ From 963a92131996b38061d48bd1a9577585cce8a66a Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:32:42 +0200 Subject: [PATCH 22/26] Exclude 1.20 biome for 1.19 --- .../com/plotsquared/bukkit/generator/BukkitPlotGenerator.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java index 767bcd3751..05ad8f6335 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java @@ -436,6 +436,9 @@ private final class BukkitPlotBiomeProvider extends BiomeProvider { static { ArrayList biomes = new ArrayList<>(List.of(Biome.values())); biomes.remove(Biome.CUSTOM); + if (PlotSquared.platform().serverVersion()[1] <= 19) { + biomes.remove(Biome.CHERRY_GROVE); + } BIOMES = List.copyOf(biomes); } From aba3a921e80038115a1270e25a4290c5adf5995a Mon Sep 17 00:00:00 2001 From: Phillipp Glanz Date: Wed, 5 Apr 2023 13:33:04 +0200 Subject: [PATCH 23/26] Check if world creation folia api --- .../bukkit/managers/BukkitWorldManager.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java index 7397d7b5c4..3e8f032160 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java @@ -19,6 +19,7 @@ package com.plotsquared.bukkit.managers; import com.google.inject.Singleton; +import com.plotsquared.bukkit.util.FoliaSupport; import com.plotsquared.core.configuration.file.YamlConfiguration; import com.plotsquared.core.util.PlatformWorldManager; import org.bukkit.Bukkit; @@ -48,13 +49,16 @@ public void initialize() { @Override public @Nullable World handleWorldCreation(@NonNull String worldName, @Nullable String generator) { this.setGenerator(worldName, generator); - final WorldCreator wc = new WorldCreator(worldName); - wc.environment(World.Environment.NORMAL); - if (generator != null) { - wc.generator(generator); - wc.type(WorldType.FLAT); + if (!FoliaSupport.isFolia()) { + final WorldCreator wc = new WorldCreator(worldName); + wc.environment(World.Environment.NORMAL); + if (generator != null) { + wc.generator(generator); + wc.type(WorldType.FLAT); + } + return Bukkit.createWorld(wc); } - return Bukkit.createWorld(wc); + return null; } protected void setGenerator(final @Nullable String worldName, final @Nullable String generator) { From 75361b9c29a39b57b4bfe3ebf6405eaf30917e34 Mon Sep 17 00:00:00 2001 From: TheMeinerLP Date: Mon, 5 Jun 2023 20:56:49 +0200 Subject: [PATCH 24/26] Fix command processing for folia servers --- .../util/task/FoliaPlotSquaredTask.java | 61 +++++++++++++++++++ .../bukkit/util/task/FoliaTaskManager.java | 37 +++++------ 2 files changed, 81 insertions(+), 17 deletions(-) create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaPlotSquaredTask.java diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaPlotSquaredTask.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaPlotSquaredTask.java new file mode 100644 index 0000000000..6a44df8278 --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaPlotSquaredTask.java @@ -0,0 +1,61 @@ +package com.plotsquared.bukkit.util.task; + +import com.plotsquared.core.util.task.PlotSquaredTask; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.TimeUnit; + +public final class FoliaPlotSquaredTask implements PlotSquaredTask { + + @NonNull + private final Runnable runnable; + @NotNull + private final JavaPlugin javaPlugin; + + private ScheduledTask task; + + public FoliaPlotSquaredTask(final @NonNull Runnable runnable, final JavaPlugin javaPlugin) { + this.runnable = runnable; + this.javaPlugin = javaPlugin; + } + + @Override + public void runTask() { + this.task = Bukkit.getGlobalRegionScheduler().run(javaPlugin, scheduledTask -> this.runnable.run()); + } + + public void runTaskLater(long delay) { + this.task = Bukkit.getGlobalRegionScheduler().runDelayed(javaPlugin, scheduledTask -> this.runnable.run(), delay); + } + + public void runTaskLaterAsynchronously(long delay) { + this.task = Bukkit.getAsyncScheduler().runDelayed(javaPlugin, scheduledTask -> this.runnable.run(), delay, TimeUnit.MILLISECONDS); + } + + public void runTaskAsynchronously() { + this.task = Bukkit.getAsyncScheduler().runNow(javaPlugin, scheduledTask -> this.runnable.run()); + } + + public void runTaskTimerAsynchronously(long delay, long period) { + this.task = Bukkit.getAsyncScheduler().runAtFixedRate(javaPlugin, scheduledTask -> this.runnable.run(), delay, period, TimeUnit.MILLISECONDS); + } + + public void runTaskTimer(long delay, long period) { + this.task = Bukkit.getGlobalRegionScheduler().runAtFixedRate(javaPlugin, scheduledTask -> this.runnable.run(), delay, period); + } + + @Override + public boolean isCancelled() { + return this.task.isCancelled(); + } + + @Override + public void cancel() { + this.task.cancel(); + } + +} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java index 1c0ae0cbcd..cd98307946 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java @@ -49,7 +49,10 @@ public FoliaTaskManager(final BukkitPlatform bukkitMain, final TaskTime.TimeConv @Override public T sync(final @NonNull Callable function, final int timeout) throws Exception { - return backgroundExecutor.schedule(function, timeout, TimeUnit.MILLISECONDS).get(); + if (PlotSquared.get().isMainThread(Thread.currentThread())) { + return function.call(); + } + return this.callMethodSync(function).get(timeout, TimeUnit.MILLISECONDS); } @Override @@ -59,12 +62,10 @@ public Future callMethodSync(final @NonNull Callable method) { @Override public PlotSquaredTask taskRepeat(@NonNull final Runnable runnable, @NonNull final TaskTime taskTime) { - var time = switch (taskTime.getUnit()) { - case TICKS -> timeConverter.ticksToMs(taskTime.getTime()); - case MILLISECONDS -> taskTime.getTime(); - }; - backgroundExecutor.scheduleAtFixedRate(runnable, 0, time, TimeUnit.MILLISECONDS); - return PlotSquaredTask.nullTask(); + final long ticks = this.timeConverter.toTicks(taskTime); + final FoliaPlotSquaredTask foliaPlotSquaredTask = new FoliaPlotSquaredTask(runnable, this.bukkitMain); + foliaPlotSquaredTask.runTaskTimer(ticks, ticks); + return foliaPlotSquaredTask; } @Override @@ -73,27 +74,29 @@ public PlotSquaredTask taskRepeatAsync(@NonNull final Runnable runnable, @NonNul case TICKS -> timeConverter.ticksToMs(taskTime.getTime()); case MILLISECONDS -> taskTime.getTime(); }; - Bukkit.getAsyncScheduler().runAtFixedRate(bukkitMain, scheduledTask -> runnable.run(), 0, time, TimeUnit.MILLISECONDS); - return PlotSquaredTask.nullTask(); + final FoliaPlotSquaredTask foliaPlotSquaredTask = new FoliaPlotSquaredTask(runnable, this.bukkitMain); + foliaPlotSquaredTask.runTaskTimerAsynchronously(time, time); + return foliaPlotSquaredTask; } @Override public void taskAsync(@NonNull final Runnable runnable) { - Bukkit.getAsyncScheduler().runNow(bukkitMain, scheduledTask -> runnable.run()); + if (this.bukkitMain.isEnabled()) { + new FoliaPlotSquaredTask(runnable, this.bukkitMain).runTaskAsynchronously(); + } else { + runnable.run(); + } + } @Override public void task(@NonNull final Runnable runnable) { - backgroundExecutor.submit(runnable); + new FoliaPlotSquaredTask(runnable, this.bukkitMain).runTask(); } @Override public void taskLater(@NonNull final Runnable runnable, @NonNull final TaskTime taskTime) { - var time = switch (taskTime.getUnit()) { - case TICKS -> timeConverter.ticksToMs(taskTime.getTime()); - case MILLISECONDS -> taskTime.getTime(); - }; - backgroundExecutor.scheduleWithFixedDelay(runnable, 0, time, TimeUnit.MILLISECONDS); + new FoliaPlotSquaredTask(runnable, this.bukkitMain).runTaskLater(this.timeConverter.toTicks(taskTime)); } @Override @@ -102,7 +105,7 @@ public void taskLaterAsync(@NonNull final Runnable runnable, @NonNull final Task case TICKS -> timeConverter.ticksToMs(taskTime.getTime()); case MILLISECONDS -> taskTime.getTime(); }; - Bukkit.getAsyncScheduler().runDelayed(this.bukkitMain, scheduledTask -> runnable.run(), time, TimeUnit.MILLISECONDS); + new FoliaPlotSquaredTask(runnable, this.bukkitMain).runTaskLaterAsynchronously(time); } private static class SchedulerAdapter { From 15d802784e274d9c8c5d3c6af59df259a0e060d7 Mon Sep 17 00:00:00 2001 From: TheMeinerLP Date: Mon, 5 Jun 2023 21:21:12 +0200 Subject: [PATCH 25/26] Fix chunk coordinator for folia --- .../bukkit/queue/BukkitChunkCoordinator.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java index fc3ce73703..d0a2bcd2dc 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java @@ -21,6 +21,7 @@ import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import com.plotsquared.bukkit.BukkitPlatform; +import com.plotsquared.bukkit.util.FoliaSupport; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.queue.ChunkCoordinator; import com.plotsquared.core.queue.subscriber.ProgressSubscriber; @@ -160,6 +161,7 @@ public void run() { } Chunk chunk = this.availableChunks.poll(); + if (chunk == null) { if (this.availableChunks.isEmpty()) { if (this.requestedChunks.isEmpty() && loadingChunks.get() == 0) { @@ -175,7 +177,20 @@ public void run() { do { final long start = System.currentTimeMillis(); try { - this.chunkConsumer.accept(BlockVector2.at(chunk.getX(), chunk.getZ())); + if (FoliaSupport.isFolia()) { + var tempChunk = chunk; + Bukkit.getRegionScheduler().run( + this.plugin, + this.bukkitWorld, + chunk.getX(), + chunk.getZ(), + scheduledTask -> { + this.chunkConsumer.accept(BlockVector2.at(tempChunk.getX(), tempChunk.getZ())); + } + ); + } else { + this.chunkConsumer.accept(BlockVector2.at(chunk.getX(), chunk.getZ())); + } } catch (final Throwable throwable) { this.throwableConsumer.accept(throwable); } @@ -188,6 +203,8 @@ public void run() { iterationTime[0] = iterationTime[1]; iterationTime[1] = end - start; } while (iterationTime[0] + iterationTime[1] < this.maxIterationTime * 2 && (chunk = availableChunks.poll()) != null); + + if (processedChunks < this.batchSize) { // Adjust batch size based on the amount of processed chunks per tick this.batchSize = processedChunks; From 1e691f5961f479098d9e300f6325965fabb5df37 Mon Sep 17 00:00:00 2001 From: TheMeinerLP Date: Mon, 5 Jun 2023 21:32:05 +0200 Subject: [PATCH 26/26] Remove unused code --- .../bukkit/util/task/FoliaTaskManager.java | 93 ------------------- 1 file changed, 93 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java index cd98307946..77a61c76c6 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/task/FoliaTaskManager.java @@ -108,97 +108,4 @@ public void taskLaterAsync(@NonNull final Runnable runnable, @NonNull final Task new FoliaPlotSquaredTask(runnable, this.bukkitMain).runTaskLaterAsynchronously(time); } - private static class SchedulerAdapter { - - private static final MethodHandle EXECUTE_FOR_LOCATION; - private static final MethodHandle EXECUTE_FOR_PLAYER; - private static final Runnable THROW_IF_RETIRED = () -> throwRetired(); - - private static final MethodType LOCATION_EXECUTE_TYPE = methodType( - void.class, - Plugin.class, - org.bukkit.Location.class, - Runnable.class - ); - - private static final MethodType ENTITY_EXECUTE_TYPE = methodType( - boolean.class, - Plugin.class, - Runnable.class, - Runnable.class, - long.class - ); - - static { - final Plugin pluginInstance = ((Plugin) PlotSquared.get()); - final MethodHandles.Lookup lookup = MethodHandles.lookup(); - - MethodHandle executeForLocation; - - MethodHandle executeForPlayer; - try { - Class regionisedSchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.FoliaRegionScheduler"); - final Method method = Bukkit.class.getDeclaredMethod("getRegionScheduler"); - executeForLocation = lookup.findVirtual( - regionisedSchedulerClass, - "execute", - LOCATION_EXECUTE_TYPE - ); - executeForLocation = executeForLocation.bindTo(method.invoke(null)); - executeForLocation = executeForLocation.bindTo(pluginInstance); - - Class entitySchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.EntityScheduler"); - executeForPlayer = lookup.findVirtual( - entitySchedulerClass, - "execute", - ENTITY_EXECUTE_TYPE - ); - // (ES, P, R, R, L)Z (ES, R, R, L)Z - executeForPlayer = insertArguments(executeForPlayer, 1, pluginInstance); - // (ES, R1, R2, L)Z -> (ES, R1)Z - executeForPlayer = insertArguments(executeForPlayer, 2, THROW_IF_RETIRED, 0); - // (ES, R1)Z -> (ES, R1)V - executeForPlayer = dropReturn(executeForPlayer); - MethodHandle getScheduler = lookup.findVirtual( - org.bukkit.entity.Entity.class, - "getScheduler", - methodType(entitySchedulerClass) - ); - // (ES, R1)V -> (E, R1)V - executeForPlayer = filterArguments(executeForPlayer, 0, getScheduler); - MethodType finalType = methodType(void.class, org.bukkit.entity.Player.class, Runnable.class); - // (ES, R1)V -> (P, R1)V - executeForPlayer = explicitCastArguments(executeForPlayer, finalType); - } catch (Throwable throwable) { - throw new AssertionError(throwable); - } - EXECUTE_FOR_LOCATION = executeForLocation; - EXECUTE_FOR_PLAYER = executeForPlayer; - } - - static void executeForLocation(Location location, Runnable task) { - try { - EXECUTE_FOR_LOCATION.invokeExact(BukkitAdapter.adapt(location), task); - } catch (Error | RuntimeException e) { - throw e; - } catch (Throwable other) { - throw new RuntimeException(other); - } - } - static void executeForEntity(Player player, Runnable task) { - try { - EXECUTE_FOR_PLAYER.invokeExact(BukkitAdapter.adapt(player), task); - } catch (Error | RuntimeException e) { - throw e; - } catch (Throwable other) { - throw new RuntimeException(other); - } - } - - private static void throwRetired() { - throw new RuntimeException("Player retired"); - } - - } - }