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 extends Player> 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 extends Player> 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");
- }
-
- }
-
}