diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 23bbe8f..0553687 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -1,30 +1,18 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
+
+
+
@@ -34,4 +22,13 @@
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
index 67b357d..ba0f5d5 100644
--- a/.idea/encodings.xml
+++ b/.idea/encodings.xml
@@ -3,8 +3,18 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index e973167..bf5484c 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -4,8 +4,11 @@
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index c827f29..463b28c 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,8 @@ TaskChain then executes your task pipe line, switching thread context where need
- [[GUIDE: Using in your Bukkit Plugins](https://github.com/aikar/TaskChain/wiki/implementing-bukkit)]
- Sponge Minecraft Servers
- [[GUIDE: Using in your Sponge Plugins](https://github.com/aikar/TaskChain/wiki/implementing-sponge)]
+ - Folia Servers
+ - Same methods employed by BukkitTaskChainFactory but instead use FoliaTaskChainFactory
### Planned
- Forge Minecraft Servers [[#2](https://github.com/aikar/TaskChain/issues/2)]
diff --git a/bukkit/src/main/java/co/aikar/taskchain/BukkitTaskChainFactory.java b/bukkit/src/main/java/co/aikar/taskchain/BukkitTaskChainFactory.java
index 77fdfad..3293db6 100644
--- a/bukkit/src/main/java/co/aikar/taskchain/BukkitTaskChainFactory.java
+++ b/bukkit/src/main/java/co/aikar/taskchain/BukkitTaskChainFactory.java
@@ -31,7 +31,6 @@
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.plugin.Plugin;
-import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@SuppressWarnings({"WeakerAccess", "unused"})
diff --git a/folia/pom.xml b/folia/pom.xml
new file mode 100644
index 0000000..963c703
--- /dev/null
+++ b/folia/pom.xml
@@ -0,0 +1,60 @@
+
+
+
+
+ 4.0.0
+
+ co.aikar
+ taskchain-parent
+ 3.7.3-SNAPSHOT
+ ../pom.xml
+
+
+ taskchain-folia
+ 3.7.3-SNAPSHOT
+ jar
+ TaskChain (Folia)
+
+
+
+ papermc
+ https://repo.papermc.io/repository/maven-public/
+
+
+
+
+
+ co.aikar
+ taskchain-core
+ 3.7.3-SNAPSHOT
+
+
+ dev.folia
+ folia-api
+ 1.20.1-R0.1-SNAPSHOT
+ provided
+
+
+
diff --git a/folia/src/main/java/co/aikar/taskchain/FoliaTaskChainFactory.java b/folia/src/main/java/co/aikar/taskchain/FoliaTaskChainFactory.java
new file mode 100644
index 0000000..8d3f1eb
--- /dev/null
+++ b/folia/src/main/java/co/aikar/taskchain/FoliaTaskChainFactory.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2016-2024 Daniel Ennis (Aikar) - MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package co.aikar.taskchain;
+
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.server.PluginDisableEvent;
+import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.concurrent.TimeUnit;
+
+@SuppressWarnings({"WeakerAccess", "unused"})
+public class FoliaTaskChainFactory extends TaskChainFactory {
+
+ private FoliaTaskChainFactory(Plugin plugin, AsyncQueue asyncQueue) {
+ super(new FoliaGameInterface(plugin, asyncQueue));
+ }
+
+ @Contract("_ -> new")
+ public static @NotNull TaskChainFactory create(Plugin plugin) {
+ return new FoliaTaskChainFactory(plugin, new TaskChainAsyncQueue());
+ }
+
+ @SuppressWarnings("PublicInnerClass")
+ private static class FoliaGameInterface implements GameInterface {
+ private final Plugin plugin;
+ private final AsyncQueue asyncQueue;
+
+ FoliaGameInterface(Plugin plugin, AsyncQueue asyncQueue) {
+ this.plugin = plugin;
+ this.asyncQueue = asyncQueue;
+ }
+
+ @Override
+ public AsyncQueue getAsyncQueue() {
+ return this.asyncQueue;
+ }
+
+ @Override
+ public boolean isMainThread() {
+ return Bukkit.isPrimaryThread();
+ }
+
+ @Override
+ public void postToMain(Runnable run) {
+ if (plugin.isEnabled()) {
+ Bukkit.getGlobalRegionScheduler().execute(plugin, run);
+ } else {
+ run.run();
+ }
+ }
+
+ @Override
+ public void scheduleTask(int ticks, Runnable run) {
+ if (plugin.isEnabled()) {
+ Bukkit.getGlobalRegionScheduler().runDelayed(plugin, task ->
+ Bukkit.getGlobalRegionScheduler().execute(plugin, run), ticks);
+ } else {
+ run.run();
+ }
+ }
+
+ @Override
+ public void registerShutdownHandler(TaskChainFactory factory) {
+ Bukkit.getPluginManager().registerEvents(new Listener() {
+ @EventHandler
+ public void onPluginDisable(PluginDisableEvent event) {
+ if (event.getPlugin().equals(plugin)) {
+ factory.shutdown(60, TimeUnit.SECONDS);
+ }
+ }
+ }, plugin);
+ }
+ }
+
+ public static final TaskChainAbortAction MESSAGE = new TaskChainAbortAction() {
+ @Override
+ public void onAbort(TaskChain> chain, @NotNull Player player, String message) {
+ player.sendMessage(message);
+ }
+ };
+
+ public static final TaskChainAbortAction COLOR_MESSAGE = new TaskChainAbortAction() {
+ @Override
+ public void onAbort(TaskChain> chain, @NotNull Player player, String message) {
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', message));
+ }
+ };
+}
diff --git a/pom.xml b/pom.xml
index 875fa83..2f62a03 100644
--- a/pom.xml
+++ b/pom.xml
@@ -91,5 +91,6 @@
core
bukkit
sponge
+ folia
diff --git a/sponge/pom.xml b/sponge/pom.xml
index 8f5539f..6df034d 100644
--- a/sponge/pom.xml
+++ b/sponge/pom.xml
@@ -40,7 +40,7 @@
sponge-maven-repo
Sponge maven repo
- http://repo.spongepowered.org/maven
+ https://repo.spongepowered.org/maven
true