diff --git a/Compatibility/pom.xml b/Compatibility/pom.xml
index fe7fd0e4..e0d48009 100644
--- a/Compatibility/pom.xml
+++ b/Compatibility/pom.xml
@@ -32,6 +32,13 @@
provided
+
+ ${project.groupId}
+ Folia-Compatibility
+ ${project.version}
+ compile
+
+
com.viaversion
viaversion-api
diff --git a/Compatibility/src/main/java/com/songoda/core/compatibility/ClientVersion.java b/Compatibility/src/main/java/com/songoda/core/compatibility/ClientVersion.java
index 743b7de4..30ea7ccc 100644
--- a/Compatibility/src/main/java/com/songoda/core/compatibility/ClientVersion.java
+++ b/Compatibility/src/main/java/com/songoda/core/compatibility/ClientVersion.java
@@ -1,7 +1,8 @@
package com.songoda.core.compatibility;
+import com.songoda.core.compatibility.folia.SchedulerRunnable;
+import com.songoda.core.compatibility.folia.SchedulerUtils;
import com.viaversion.viaversion.api.Via;
-import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
@@ -37,10 +38,13 @@ public static ServerVersion getClientVersion(Player player) {
*/
@Deprecated
public static void onLoginProtocol(Player p, JavaPlugin plugin) {
- Bukkit.getScheduler().runTaskLater(plugin, () -> {
- if (p.isOnline()) {
- final int version = protocolsupport.api.ProtocolSupportAPI.getProtocolVersion(p).getId();
- players.put(p.getUniqueId(), protocolToVersion(version));
+ SchedulerUtils.runTaskLater(plugin, new SchedulerRunnable() {
+ @Override
+ public void run() {
+ if (p.isOnline()) {
+ final int version = protocolsupport.api.ProtocolSupportAPI.getProtocolVersion(p).getId();
+ players.put(p.getUniqueId(), protocolToVersion(version));
+ }
}
}, 20);
}
@@ -50,10 +54,13 @@ public static void onLoginProtocol(Player p, JavaPlugin plugin) {
*/
@Deprecated
public static void onLoginVia(Player p, JavaPlugin plugin) {
- Bukkit.getScheduler().runTaskLater(plugin, () -> {
- if (p.isOnline()) {
- final int version = Via.getAPI().getPlayerVersion(p.getUniqueId());
- players.put(p.getUniqueId(), protocolToVersion(version));
+ SchedulerUtils.runTaskLater(plugin, new SchedulerRunnable() {
+ @Override
+ public void run() {
+ if (p.isOnline()) {
+ final int version = Via.getAPI().getPlayerVersion(p.getUniqueId());
+ players.put(p.getUniqueId(), protocolToVersion(version));
+ }
}
}, 20);
}
diff --git a/Compatibility/src/main/java/com/songoda/core/compatibility/ServerProject.java b/Compatibility/src/main/java/com/songoda/core/compatibility/ServerProject.java
index eb3e35c3..87b79e4d 100644
--- a/Compatibility/src/main/java/com/songoda/core/compatibility/ServerProject.java
+++ b/Compatibility/src/main/java/com/songoda/core/compatibility/ServerProject.java
@@ -4,7 +4,7 @@
import org.bukkit.Bukkit;
public enum ServerProject {
- UNKNOWN, CRAFTBUKKIT, SPIGOT, PAPER, TACO, GLOWSTONE, MOCK_BUKKIT;
+ UNKNOWN, CRAFTBUKKIT, SPIGOT, PAPER, FOLIA, TACO, GLOWSTONE, MOCK_BUKKIT;
private static final ServerProject serverProject = checkProject();
private static ServerProject checkProject() {
@@ -38,6 +38,12 @@ private static ServerProject checkProject() {
} catch (ClassNotFoundException ignore) {
}
+ try {
+ Class.forName("io.papermc.paper.threadedregions.RegionizedServer");
+ return FOLIA;
+ } catch (ClassNotFoundException ignored) {
+ }
+
// spigot is the fork that pretty much all builds are based on anymore
try {
Class.forName("org.spigotmc.SpigotConfig");
diff --git a/Core/pom.xml b/Core/pom.xml
index 42d46488..1b0f729b 100644
--- a/Core/pom.xml
+++ b/Core/pom.xml
@@ -97,6 +97,8 @@
com.github.GeorgeV220:LibraryLoader
org.ow2.asm:asm
org.ow2.asm:asm-commons
+
+ io.papermc:paperlib
@@ -165,6 +167,11 @@
org.objectweb.asm
com.songoda.core.third_party.org.objectweb.asm
+
+
+ io.papermc.lib
+ com.craftaro.third_party.io.papermc.lib
+
@@ -208,7 +215,21 @@
provided
+
+ dev.folia
+ folia-api
+ 1.19.4-R0.1-SNAPSHOT
+ provided
+
+
+
+ io.papermc
+ paperlib
+ 1.0.8
+ compile
+
+
${project.groupId}
SongodaCore-Compatibility
@@ -370,13 +391,6 @@
compile
-
- org.ow2.asm
- asm-commons
- 9.2
- compile
-
-
com.zaxxer
diff --git a/Core/src/main/java/com/songoda/core/SongodaCore.java b/Core/src/main/java/com/songoda/core/SongodaCore.java
index 38e8d95c..68a5fe47 100644
--- a/Core/src/main/java/com/songoda/core/SongodaCore.java
+++ b/Core/src/main/java/com/songoda/core/SongodaCore.java
@@ -1,5 +1,8 @@
package com.songoda.core;
+import com.songoda.core.compatibility.folia.SchedulerRunnable;
+import com.songoda.core.compatibility.folia.SchedulerTask;
+import com.songoda.core.compatibility.folia.SchedulerUtils;
import com.songoda.core.commands.CommandManager;
import com.songoda.core.compatibility.ClientVersion;
import com.songoda.core.core.PluginInfo;
@@ -7,6 +10,7 @@
import com.songoda.core.core.SongodaCoreDiagCommand;
import com.cryptomorin.xseries.XMaterial;
import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
@@ -16,15 +20,16 @@
import org.bukkit.event.server.PluginEnableEvent;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin;
-import org.bukkit.scheduler.BukkitTask;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.UUID;
import java.util.logging.Level;
public class SongodaCore {
@@ -181,15 +186,26 @@ private void init() {
Bukkit.getPluginManager().registerEvents(this.shadingListener, this.piggybackedPlugin);
// we aggressively want to own this command
- this.tasks.add(Bukkit.getScheduler().runTaskLaterAsynchronously(this.piggybackedPlugin, () ->
- CommandManager.registerCommandDynamically(this.piggybackedPlugin, "songoda", this.commandManager, this.commandManager),
- 10 * 60));
- this.tasks.add(Bukkit.getScheduler().runTaskLaterAsynchronously(this.piggybackedPlugin, () ->
- CommandManager.registerCommandDynamically(this.piggybackedPlugin, "songoda", this.commandManager, this.commandManager),
- 20 * 60));
- this.tasks.add(Bukkit.getScheduler().runTaskLaterAsynchronously(this.piggybackedPlugin, () ->
- CommandManager.registerCommandDynamically(this.piggybackedPlugin, "songoda", this.commandManager, this.commandManager),
- 20 * 60 * 2));
+ tasks.add(SchedulerUtils.runTaskLater(piggybackedPlugin, new SchedulerRunnable() {
+ @Override
+ public void run() {
+ CommandManager.registerCommandDynamically(piggybackedPlugin, "songoda", commandManager, commandManager);
+ }
+ }, 10 * 60));
+
+ tasks.add(SchedulerUtils.runTaskLater(piggybackedPlugin, new SchedulerRunnable() {
+ @Override
+ public void run() {
+ CommandManager.registerCommandDynamically(piggybackedPlugin, "songoda", commandManager, commandManager);
+ }
+ }, 20 * 60));
+
+ tasks.add(SchedulerUtils.runTaskLater(piggybackedPlugin, new SchedulerRunnable() {
+ @Override
+ public void run() {
+ CommandManager.registerCommandDynamically(piggybackedPlugin, "songoda", commandManager, commandManager);
+ }
+ }, 20 * 60 * 2));
}
/**
@@ -198,8 +214,8 @@ private void init() {
private void destroy() {
Bukkit.getServicesManager().unregister(SongodaCore.class, INSTANCE);
- this.tasks.stream().filter(Objects::nonNull)
- .forEach(task -> Bukkit.getScheduler().cancelTask(task.getTaskId()));
+ tasks.stream().filter(Objects::nonNull)
+ .forEach(SchedulerUtils::cancelTask);
HandlerList.unregisterAll(this.loginListener);
if (!hasShading()) {
@@ -211,7 +227,7 @@ private void destroy() {
this.loginListener = null;
}
- private final ArrayList tasks = new ArrayList<>();
+ private final ArrayList tasks = new ArrayList<>();
private void register(JavaPlugin plugin, int pluginID, String icon, String libraryVersion) {
getLogger().info(getPrefix() + "Hooked " + plugin.getName() + ".");
@@ -338,6 +354,23 @@ void onEnable(PluginEnableEvent event) {
}
private class EventListener implements Listener {
+ final HashMap lastCheck = new HashMap<>();
+
+ @EventHandler
+ void onLogin(PlayerLoginEvent event) {
+ final Player player = event.getPlayer();
+
+ // don't spam players with update checks
+ long now = System.currentTimeMillis();
+ Long last = this.lastCheck.get(player.getUniqueId());
+
+ if (last != null && now - 10000 < last) {
+ return;
+ }
+
+ this.lastCheck.put(player.getUniqueId(), now);
+ }
+
@EventHandler
void onDisable(PluginDisableEvent event) {
// don't track disabled plugins
diff --git a/Core/src/main/java/com/songoda/core/SongodaPlugin.java b/Core/src/main/java/com/songoda/core/SongodaPlugin.java
index 46eafbd4..58eb981f 100644
--- a/Core/src/main/java/com/songoda/core/SongodaPlugin.java
+++ b/Core/src/main/java/com/songoda/core/SongodaPlugin.java
@@ -1,5 +1,7 @@
package com.songoda.core;
+import com.songoda.core.compatibility.folia.SchedulerRunnable;
+import com.songoda.core.compatibility.folia.SchedulerUtils;
import com.songoda.core.configuration.Config;
import com.songoda.core.database.DataManager;
import com.songoda.core.database.DataMigration;
@@ -11,7 +13,6 @@
import com.songoda.core.locale.Locale;
import com.songoda.core.utils.Metrics;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
-import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@@ -117,7 +118,8 @@ public final void onLoad() {
dependencies.add(new Dependency("https://repo.songoda.com/repository/third-party/", "com;cryptomorin", "XSeries", "13.7.0", false,
new Relocation("com;cryptomorin;xseries", "com;songoda;third_party;com;cryptomorin;xseries")) // Custom relocation if the package names not match with the groupId
);
-
+ dependencies.add(new Dependency("https://papermc.io/repo/repository/maven-public/", "io;papermc", "paperlib", "1.0.8"));
+
//Load plugin dependencies
new DependencyLoader(this).loadDependencies(dependencies);
@@ -154,7 +156,12 @@ public final void onEnable() {
}
// Load Data.
- Bukkit.getScheduler().runTaskLater(this, this::onDataLoad, this.dataLoadDelay);
+ SchedulerUtils.runTaskLater(this, new SchedulerRunnable() {
+ @Override
+ public void run() {
+ onDataLoad();
+ }
+ }, this.dataLoadDelay);
if (this.emergencyStop) {
console.sendMessage(ChatColor.RED + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
diff --git a/Core/src/main/java/com/songoda/core/gui/GuiManager.java b/Core/src/main/java/com/songoda/core/gui/GuiManager.java
index 2dc84f1b..61f6719b 100644
--- a/Core/src/main/java/com/songoda/core/gui/GuiManager.java
+++ b/Core/src/main/java/com/songoda/core/gui/GuiManager.java
@@ -3,6 +3,8 @@
import com.songoda.core.compatibility.ClientVersion;
import com.songoda.core.compatibility.ServerVersion;
import com.cryptomorin.xseries.XMaterial;
+import com.songoda.core.compatibility.folia.SchedulerRunnable;
+import com.songoda.core.compatibility.folia.SchedulerUtils;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@@ -102,23 +104,29 @@ public void showGUI(Player player, Gui gui) {
return;
}
- Bukkit.getScheduler().runTaskAsynchronously(this.plugin, () -> {
- Gui openInv = this.openInventories.get(player);
+ SchedulerUtils.runTaskAsynchronously(plugin, new SchedulerRunnable() {
+ @Override
+ public void run() {
+ Gui openInv = openInventories.get(player);
- if (openInv != null) {
- openInv.open = false;
- }
+ if (openInv != null) {
+ openInv.open = false;
+ }
- Inventory inv = gui.getOrCreateInventory(this);
+ Inventory inv = gui.getOrCreateInventory(GuiManager.this);
- Bukkit.getScheduler().runTask(this.plugin, () -> {
- player.openInventory(inv);
- gui.onOpen(this, player);
+ SchedulerUtils.runTask(plugin, new SchedulerRunnable() {
+ @Override
+ public void run() {
+ player.openInventory(inv);
+ gui.onOpen(GuiManager.this, player);
- synchronized (this.lock) {
- this.openInventories.put(player, gui);
- }
- });
+ synchronized (GuiManager.this.lock) {
+ GuiManager.this.openInventories.put(player, gui);
+ }
+ }
+ });
+ }
});
}
@@ -136,9 +144,12 @@ public void showPopup(Player player, String message, XMaterial icon, BackgroundT
popup.add();
popup.grant(player);
- Bukkit.getScheduler().runTaskLaterAsynchronously(this.plugin, () -> {
- popup.revoke(player);
- popup.remove();
+ SchedulerUtils.runTaskLaterAsynchronously(plugin, new SchedulerRunnable() {
+ @Override
+ public void run() {
+ popup.revoke(player);
+ popup.remove();
+ }
}, 70);
return;
@@ -285,7 +296,12 @@ void onCloseGUI(InventoryCloseEvent event) {
if (this.manager.shutdown) {
gui.onClose(this.manager, player);
} else {
- Bukkit.getScheduler().runTaskLater(this.manager.plugin, () -> gui.onClose(this.manager, player), 1);
+ SchedulerUtils.runEntityTaskLater(manager.plugin, player, new SchedulerRunnable() {
+ @Override
+ public void run() {
+ gui.onClose(manager, player);
+ }
+ }, 1);
}
this.manager.openInventories.remove(player);
diff --git a/Core/src/main/java/com/songoda/core/input/ChatPrompt.java b/Core/src/main/java/com/songoda/core/input/ChatPrompt.java
index 302f6fd0..850c1e2f 100644
--- a/Core/src/main/java/com/songoda/core/input/ChatPrompt.java
+++ b/Core/src/main/java/com/songoda/core/input/ChatPrompt.java
@@ -1,5 +1,8 @@
package com.songoda.core.input;
+import com.songoda.core.compatibility.folia.SchedulerRunnable;
+import com.songoda.core.compatibility.folia.SchedulerTask;
+import com.songoda.core.compatibility.folia.SchedulerUtils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -20,7 +23,7 @@ public class ChatPrompt implements Listener {
private final Plugin plugin;
private final ChatConfirmHandler handler;
- private int taskId;
+ private SchedulerTask task;
private OnClose onClose = null;
private OnCancel onCancel = null;
private Listener listener;
@@ -67,14 +70,21 @@ public ChatPrompt setOnCancel(OnCancel onCancel) {
}
public ChatPrompt setTimeOut(Player player, long ticks) {
- this.taskId = Bukkit.getScheduler().scheduleSyncDelayedTask(this.plugin, () -> {
- if (this.onClose != null) {
- this.plugin.getServer().getScheduler().scheduleSyncDelayedTask(this.plugin, () ->
- this.onClose.onClose(), 0L);
- }
+ task = SchedulerUtils.scheduleSyncDelayedTask(plugin, new SchedulerRunnable() {
+ @Override
+ public void run() {
+ if (onClose != null) {
+ SchedulerUtils.scheduleSyncDelayedTask(plugin, new SchedulerRunnable() {
+ @Override
+ public void run() {
+ onClose.onClose();
+ }
+ }, 0L);
+ }
- HandlerList.unregisterAll(this.listener);
- player.sendMessage("Your action has timed out.");
+ HandlerList.unregisterAll(listener);
+ player.sendMessage("Your action has timed out.");
+ }
}, ticks);
return this;
@@ -103,12 +113,17 @@ public void onChat(AsyncPlayerChatEvent event) {
plugin.getLogger().log(Level.SEVERE, "Failed to process chat prompt", t);
}
- if (ChatPrompt.this.onClose != null) {
- plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> ChatPrompt.this.onClose.onClose(), 0L);
+ if (onClose != null) {
+ SchedulerUtils.scheduleSyncDelayedTask(plugin, new SchedulerRunnable() {
+ @Override
+ public void run() {
+ onClose.onClose();
+ }
+ }, 0L);
}
- HandlerList.unregisterAll(ChatPrompt.this.listener);
- Bukkit.getScheduler().cancelTask(ChatPrompt.this.taskId);
+ HandlerList.unregisterAll(listener);
+ SchedulerUtils.cancelTask(task);
}
@EventHandler(priority = EventPriority.LOWEST)
@@ -125,14 +140,24 @@ public void onCancel(PlayerCommandPreprocessEvent event) {
event.setCancelled(true);
}
- if (ChatPrompt.this.onCancel != null) {
- plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> ChatPrompt.this.onCancel.onCancel(), 0L);
- } else if (ChatPrompt.this.onClose != null) {
- plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> ChatPrompt.this.onClose.onClose(), 0L);
+ if (onCancel != null) {
+ SchedulerUtils.scheduleSyncDelayedTask(plugin, new SchedulerRunnable() {
+ @Override
+ public void run() {
+ onCancel.onCancel();
+ }
+ }, 0L);
+ } else if (onClose != null) {
+ SchedulerUtils.scheduleSyncDelayedTask(plugin, new SchedulerRunnable() {
+ @Override
+ public void run() {
+ onClose.onClose();
+ }
+ }, 0L);
}
- HandlerList.unregisterAll(ChatPrompt.this.listener);
- Bukkit.getScheduler().cancelTask(ChatPrompt.this.taskId);
+ HandlerList.unregisterAll(listener);
+ SchedulerUtils.cancelTask(task);
}
};
diff --git a/Core/src/main/java/com/songoda/core/lootables/loot/DropUtils.java b/Core/src/main/java/com/songoda/core/lootables/loot/DropUtils.java
index e392cc06..e13bca2b 100644
--- a/Core/src/main/java/com/songoda/core/lootables/loot/DropUtils.java
+++ b/Core/src/main/java/com/songoda/core/lootables/loot/DropUtils.java
@@ -1,5 +1,7 @@
package com.songoda.core.lootables.loot;
+import com.songoda.core.compatibility.folia.SchedulerRunnable;
+import com.songoda.core.compatibility.folia.SchedulerUtils;
import com.songoda.core.SongodaCore;
import com.songoda.ultimatestacker.api.UltimateStackerApi;
import org.bukkit.Bukkit;
@@ -89,26 +91,34 @@ private static void dropItems(List items, EntityDeathEvent event) {
}
stack.setAmount(newAmount.intValue());
}
- for (StackedItem stack : stacks) {
- UltimateStackerApi.getStackedItemManager().createStack(stack.getItemToDrop(), event.getEntity().getLocation(), stack.getAmount(), event.getEntity());
- }
+ SchedulerUtils.runLocationTask(SongodaCore.getHijackedPlugin(), event.getEntity().getLocation(), new SchedulerRunnable() {
+ @Override
+ public void run() {
+ for (StackedItem stack : stacks) {
+ UltimateStackerApi.getStackedItemManager().createStack(stack.getItemToDrop(), event.getEntity().getLocation(), stack.getAmount());
+ }
+ }
+ });
return;
}
event.getDrops().addAll(items);
}
private static void runCommands(LivingEntity entity, List commands) {
- Bukkit.getScheduler().runTask(SongodaCore.getHijackedPlugin(), () -> {
- for (String command : commands) {
- if (entity.getKiller() != null) {
- command = command.replace("%player%", entity.getKiller().getName()
- .replace("%x%", String.valueOf((int) entity.getLocation().getX()))
- .replace("%y%", String.valueOf((int) entity.getLocation().getY()))
- .replace("%z%", String.valueOf((int) entity.getLocation().getZ())));
- }
-
- if (!command.contains("%player%")) {
- Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
+ SchedulerUtils.runTask(SongodaCore.getHijackedPlugin(), new SchedulerRunnable() {
+ @Override
+ public void run() {
+ for (String command : commands) {
+ if (entity.getKiller() != null) {
+ command = command.replace("%player%", entity.getKiller().getName()
+ .replace("%x%", String.valueOf((int) entity.getLocation().getX()))
+ .replace("%y%", String.valueOf((int) entity.getLocation().getY()))
+ .replace("%z%", String.valueOf((int) entity.getLocation().getZ())));
+ }
+
+ if (!command.contains("%player%")) {
+ Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
+ }
}
}
});
diff --git a/Core/src/main/java/com/songoda/core/utils/Metrics.java b/Core/src/main/java/com/songoda/core/utils/Metrics.java
index 21d3716f..68422845 100644
--- a/Core/src/main/java/com/songoda/core/utils/Metrics.java
+++ b/Core/src/main/java/com/songoda/core/utils/Metrics.java
@@ -1,5 +1,7 @@
package com.songoda.core.utils;
+import com.songoda.core.compatibility.folia.SchedulerRunnable;
+import com.songoda.core.compatibility.folia.SchedulerUtils;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
@@ -191,7 +193,12 @@ public void run() {
}
// Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
// Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
- Bukkit.getScheduler().runTask(plugin, () -> submitData());
+ SchedulerUtils.runTask(plugin, new SchedulerRunnable() {
+ @Override
+ public void run() {
+ submitData();
+ }
+ });
}
}, 1000 * 60 * 5, 1000 * 60 * 30);
// Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
diff --git a/Core/src/main/java/com/songoda/core/world/SWorld.java b/Core/src/main/java/com/songoda/core/world/SWorld.java
index ed790cc8..ba317412 100644
--- a/Core/src/main/java/com/songoda/core/world/SWorld.java
+++ b/Core/src/main/java/com/songoda/core/world/SWorld.java
@@ -2,12 +2,14 @@
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.core.nms.Nms;
+import io.papermc.paper.threadedregions.scheduler.EntityScheduler;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import java.util.List;
+import java.util.Map;
public class SWorld {
protected final com.songoda.core.nms.world.SWorld sWorld;
@@ -35,6 +37,14 @@ public List getLivingEntities() {
return this.sWorld.getLivingEntities();
}
+ /**
+ * For folia servers
+ * @return EntityScheduler and a list of entities belongs to it
+ */
+ public Map> getRegionizedEntities() {
+ return sWorld.getRegionizedEntities();
+ }
+
public World getWorld() {
return this.world;
}
diff --git a/Folia-Compatibility/.gitignore b/Folia-Compatibility/.gitignore
new file mode 100644
index 00000000..4788b4b4
--- /dev/null
+++ b/Folia-Compatibility/.gitignore
@@ -0,0 +1,113 @@
+# User-specific stuff
+.idea/
+
+*.iml
+*.ipr
+*.iws
+
+# IntelliJ
+out/
+
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+*~
+
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
+
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+target/
+
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+pom.xml.next
+
+release.properties
+dependency-reduced-pom.xml
+buildNumber.properties
+.mvn/timing.properties
+.mvn/wrapper/maven-wrapper.jar
+.flattened-pom.xml
+
+# Common working directory
+run/
diff --git a/Folia-Compatibility/pom.xml b/Folia-Compatibility/pom.xml
new file mode 100644
index 00000000..1e3458aa
--- /dev/null
+++ b/Folia-Compatibility/pom.xml
@@ -0,0 +1,85 @@
+
+
+ 4.0.0
+
+ com.songoda
+ SongodaCore-Modules
+ 4.0.0-SNAPSHOT
+ ../pom.xml
+
+
+ Folia-Compatibility
+
+ Folia-Compatibility
+
+
+ 1.8
+ UTF-8
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.15.0
+
+ ${java.version}
+ ${java.version}
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.2.4
+
+
+ package
+
+ shade
+
+
+
+
+
+
+
+ src/main/resources
+ true
+
+
+
+
+
+
+ papermc
+ https://repo.papermc.io/repository/maven-public/
+
+
+
+
+
+
+ io.papermc
+ paperlib
+ 1.0.8
+ provided
+
+
+
+ dev.folia
+ folia-api
+ 1.19.4-R0.1-SNAPSHOT
+ provided
+
+
+
+ io.papermc.paper
+ paper-api
+ 1.19.4-R0.1-SNAPSHOT
+ provided
+
+
+
diff --git a/Folia-Compatibility/src/main/java/com/songoda/core/compatibility/folia/SchedulerRunnable.java b/Folia-Compatibility/src/main/java/com/songoda/core/compatibility/folia/SchedulerRunnable.java
new file mode 100644
index 00000000..23a02857
--- /dev/null
+++ b/Folia-Compatibility/src/main/java/com/songoda/core/compatibility/folia/SchedulerRunnable.java
@@ -0,0 +1,19 @@
+package com.songoda.core.compatibility.folia;
+
+public abstract class SchedulerRunnable implements Runnable {
+
+ private SchedulerTask task;
+
+ @Override
+ public void run() {
+
+ }
+
+ public void cancel() {
+ SchedulerUtils.cancelTask(task);
+ }
+
+ void setTask(SchedulerTask task) {
+ this.task = task;
+ }
+}
diff --git a/Folia-Compatibility/src/main/java/com/songoda/core/compatibility/folia/SchedulerTask.java b/Folia-Compatibility/src/main/java/com/songoda/core/compatibility/folia/SchedulerTask.java
new file mode 100644
index 00000000..c7439da2
--- /dev/null
+++ b/Folia-Compatibility/src/main/java/com/songoda/core/compatibility/folia/SchedulerTask.java
@@ -0,0 +1,41 @@
+package com.songoda.core.compatibility.folia;
+
+import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
+import org.bukkit.scheduler.BukkitTask;
+
+public class SchedulerTask {
+
+ private final Object task;
+
+ public SchedulerTask(Object task) {
+ if (task == null) throw new IllegalArgumentException("Task cannot be null");
+ switch (task.getClass().getSimpleName()) {
+ case "BukkitTask":
+ case "SchedulerTask":
+ case "AsyncScheduledTask":
+ case "EntityScheduledTask":
+ case "GlobalScheduledTask":
+ case "LocationScheduledTask":
+ this.task = task;
+ break;
+ default:
+ throw new IllegalArgumentException("Task: " + task.getClass().getSimpleName() + " is not a BukkitTask or ScheduledTask");
+ }
+ }
+
+ public Object getTask() {
+ return task;
+ }
+
+ public ScheduledTask getAsFoliaTask() {
+ return (ScheduledTask) task;
+ }
+
+ public BukkitTask getAsBukkitTask() {
+ return (BukkitTask) task;
+ }
+
+ public int getAsBukkitTaskId() {
+ return getAsBukkitTask().getTaskId();
+ }
+}
diff --git a/Folia-Compatibility/src/main/java/com/songoda/core/compatibility/folia/SchedulerUtils.java b/Folia-Compatibility/src/main/java/com/songoda/core/compatibility/folia/SchedulerUtils.java
new file mode 100644
index 00000000..1ce9f5d4
--- /dev/null
+++ b/Folia-Compatibility/src/main/java/com/songoda/core/compatibility/folia/SchedulerUtils.java
@@ -0,0 +1,348 @@
+package com.songoda.core.compatibility.folia;
+
+import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.block.Block;
+import org.bukkit.entity.Entity;
+import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Run a task on Folia Scheduler or fallback for Bukkit Scheduler
+ * Delay is in ticks
+ */
+public class SchedulerUtils {
+
+ // Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, delay, period);
+
+ //TODO: Add methods for simple Runnable
+
+ private static boolean isFolia;
+
+ public static boolean isFolia() {
+ return isFolia;
+ }
+
+ public static boolean isOwnedByCurrentRegion(Location location) {
+ return Bukkit.isOwnedByCurrentRegion(location);
+ }
+
+ public static boolean isOwnedByCurrentRegion(Block block) {
+ return Bukkit.isOwnedByCurrentRegion(block);
+ }
+
+ public static boolean isOwnedByCurrentRegion(Entity entity) {
+ return Bukkit.isOwnedByCurrentRegion(entity);
+ }
+
+ static {
+ try {
+ Class.forName("io.papermc.paper.threadedregions.RegionizedServer");
+ isFolia = true;
+ } catch (ClassNotFoundException e) {
+ isFolia = false;
+ }
+ }
+
+ //Entity
+ public static SchedulerTask runEntityTask(@NotNull Plugin plugin, @NotNull Entity entity, @NotNull SchedulerRunnable runnable) {
+ if (isFolia) {
+ SchedulerTask task = new SchedulerTask(entity.getScheduler().run(plugin, scheduledTask -> runnable.run(), null));
+ runnable.setTask(task);
+ return task;
+ }
+ SchedulerTask task = new SchedulerTask(Bukkit.getScheduler().runTask(plugin, runnable));
+ runnable.setTask(task);
+ return task;
+ }
+
+ public static SchedulerTask runEntityTask(@NotNull Plugin plugin, @NotNull Entity entity, @NotNull Runnable runnable) {
+ if (isFolia) {
+ return new SchedulerTask(entity.getScheduler().run(plugin, scheduledTask -> runnable.run(), null));
+ }
+ return new SchedulerTask(Bukkit.getScheduler().runTask(plugin, runnable));
+ }
+
+ public static SchedulerTask runEntityTaskLater(@NotNull Plugin plugin, @NotNull Entity entity, @NotNull SchedulerRunnable runnable, long delay) {
+ if (isFolia) {
+ SchedulerTask task = new SchedulerTask(entity.getScheduler().runDelayed(plugin, scheduledTask -> runnable.run(), null, correctDelay(delay)));
+ runnable.setTask(task);
+ return task;
+ }
+ SchedulerTask task = new SchedulerTask(Bukkit.getScheduler().runTask(plugin, runnable));
+ runnable.setTask(task);
+ return task;
+ }
+
+ public static SchedulerTask runEntityTaskLater(@NotNull Plugin plugin, @NotNull Entity entity, @NotNull Runnable runnable, long delay) {
+ if (isFolia) {
+ return new SchedulerTask(entity.getScheduler().runDelayed(plugin, scheduledTask -> runnable.run(), null, correctDelay(delay)));
+ }
+ return new SchedulerTask(Bukkit.getScheduler().runTaskLater(plugin, runnable, delay));
+ }
+
+ public static SchedulerTask runEntityTaskTimer(@NotNull Plugin plugin, @NotNull Entity entity, @NotNull SchedulerRunnable runnable, long delay, long period) {
+ if (isFolia) {
+ SchedulerTask task = new SchedulerTask(entity.getScheduler().runAtFixedRate(plugin, scheduledTask -> runnable.run(), null, correctDelay(delay), correctDelay(period)));
+ runnable.setTask(task);
+ return task;
+ }
+ SchedulerTask task = new SchedulerTask(Bukkit.getScheduler().runTask(plugin, runnable));
+ runnable.setTask(task);
+ return task;
+ }
+
+ public static SchedulerTask runEntityTaskTimer(@NotNull Plugin plugin, @NotNull Entity entity, @NotNull Runnable runnable, long delay, long period) {
+ if (isFolia) {
+ return new SchedulerTask(entity.getScheduler().runAtFixedRate(plugin, scheduledTask -> runnable.run(), null, correctDelay(delay), correctDelay(period)));
+ }
+ return new SchedulerTask(Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, period));
+ }
+
+ //Location
+ public static SchedulerTask runLocationTask(@NotNull Plugin plugin, @NotNull Location location, @NotNull SchedulerRunnable runnable) {
+ if (isFolia) {
+ SchedulerTask task = new SchedulerTask(plugin.getServer().getRegionScheduler().run(plugin, location, scheduledTask -> {
+ runnable.run();
+ }));
+ runnable.setTask(task);
+ return task;
+ }
+ SchedulerTask task = new SchedulerTask(Bukkit.getScheduler().runTask(plugin, runnable));
+ runnable.setTask(task);
+ return task;
+ }
+
+ public static SchedulerTask runLocationTask(@NotNull Plugin plugin, @NotNull Location location, @NotNull Runnable runnable) {
+ if (isFolia) {
+ return new SchedulerTask(plugin.getServer().getRegionScheduler().run(plugin, location, scheduledTask -> runnable.run()));
+ }
+ return new SchedulerTask(Bukkit.getScheduler().runTask(plugin, runnable));
+ }
+
+ public static SchedulerTask runLocationTaskLater(@NotNull Plugin plugin, @NotNull Location location, @NotNull SchedulerRunnable runnable, long delay) {
+ if (isFolia) {
+ SchedulerTask task = new SchedulerTask(plugin.getServer().getRegionScheduler().runDelayed(plugin, location, scheduledTask -> runnable.run(), correctDelay(delay)));
+ runnable.setTask(task);
+ return task;
+ }
+ SchedulerTask task = new SchedulerTask(Bukkit.getScheduler().runTaskLater(plugin, runnable, delay));
+ runnable.setTask(task);
+ return task;
+ }
+
+ public static SchedulerTask runLocationTaskLater(@NotNull Plugin plugin, @NotNull Location location, @NotNull Runnable runnable, long delay) {
+ if (isFolia) {
+ return new SchedulerTask(plugin.getServer().getRegionScheduler().runDelayed(plugin, location, scheduledTask -> runnable.run(), correctDelay(delay)));
+ }
+ return new SchedulerTask(Bukkit.getScheduler().runTaskLater(plugin, runnable, delay));
+ }
+
+ public static SchedulerTask runLocationTaskTimer(@NotNull Plugin plugin, @NotNull Location location, @NotNull SchedulerRunnable runnable, long delay, long period) {
+ if (isFolia) {
+ SchedulerTask task = new SchedulerTask(plugin.getServer().getRegionScheduler().runAtFixedRate(plugin, location, scheduledTask -> runnable.run(), correctDelay(delay), correctDelay(period)));
+ runnable.setTask(task);
+ return task;
+ }
+ SchedulerTask task = new SchedulerTask(Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, period));
+ runnable.setTask(task);
+ return task;
+ }
+
+ public static SchedulerTask runLocationTaskTimer(@NotNull Plugin plugin, @NotNull Location location, @NotNull Runnable runnable, long delay, long period) {
+ if (isFolia) {
+ return new SchedulerTask(plugin.getServer().getRegionScheduler().runAtFixedRate(plugin, location, scheduledTask -> runnable.run(), correctDelay(delay), correctDelay(period)));
+ }
+ return new SchedulerTask(Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, period));
+ }
+
+ //Default
+ public static SchedulerTask runTask(@NotNull Plugin plugin, @NotNull SchedulerRunnable runnable) {
+ if (isFolia) {
+ SchedulerTask task = new SchedulerTask(plugin.getServer().getGlobalRegionScheduler().run(plugin, scheduledTask -> runnable.run()));
+ runnable.setTask(task);
+ return task;
+ }
+ SchedulerTask task = new SchedulerTask(Bukkit.getScheduler().runTask(plugin, runnable));
+ runnable.setTask(task);
+ return task;
+ }
+
+ public static SchedulerTask runTask(@NotNull Plugin plugin, @NotNull Runnable runnable) {
+ if (isFolia) {
+ return new SchedulerTask(plugin.getServer().getGlobalRegionScheduler().run(plugin, scheduledTask -> runnable.run()));
+ }
+ return new SchedulerTask(Bukkit.getScheduler().runTask(plugin, runnable));
+ }
+
+ public static SchedulerTask runTaskAsynchronously(@NotNull Plugin plugin, @NotNull SchedulerRunnable runnable) {
+ if (isFolia) {
+ SchedulerTask task = new SchedulerTask(plugin.getServer().getAsyncScheduler().runNow(plugin, scheduledTask -> runnable.run()));
+ runnable.setTask(task);
+ return task;
+ }
+ SchedulerTask task = new SchedulerTask(Bukkit.getScheduler().runTaskAsynchronously(plugin, runnable));
+ runnable.setTask(task);
+ return task;
+ }
+
+ public static SchedulerTask runTaskAsynchronously(@NotNull Plugin plugin, @NotNull Runnable runnable) {
+ if (isFolia) {
+ return new SchedulerTask(plugin.getServer().getAsyncScheduler().runNow(plugin, scheduledTask -> runnable.run()));
+ }
+ return new SchedulerTask(Bukkit.getScheduler().runTaskAsynchronously(plugin, runnable));
+ }
+
+ public static SchedulerTask runTaskLater(@NotNull Plugin plugin, @NotNull SchedulerRunnable runnable, long delay) {
+ if (isFolia) {
+ SchedulerTask task = new SchedulerTask(plugin.getServer().getGlobalRegionScheduler().runDelayed(plugin, scheduledTask -> runnable.run(), correctDelay(delay)));
+ runnable.setTask(task);
+ return task;
+ }
+ SchedulerTask task = new SchedulerTask(Bukkit.getScheduler().runTaskLater(plugin, runnable, delay));
+ runnable.setTask(task);
+ return task;
+ }
+
+ public static SchedulerTask runTaskLater(@NotNull Plugin plugin, @NotNull Runnable runnable, long delay) {
+ if (isFolia) {
+ return new SchedulerTask(plugin.getServer().getGlobalRegionScheduler().runDelayed(plugin, scheduledTask -> runnable.run(), correctDelay(delay)));
+ }
+ return new SchedulerTask(Bukkit.getScheduler().runTaskLater(plugin, runnable, delay));
+ }
+
+ public static SchedulerTask runTaskLaterAsynchronously(@NotNull Plugin plugin, @NotNull SchedulerRunnable runnable, long delay) {
+ if (isFolia) {
+ SchedulerTask task = new SchedulerTask(plugin.getServer().getAsyncScheduler().runDelayed(plugin, scheduledTask -> runnable.run(), correctDelay(delay), TimeUnit.MILLISECONDS));
+ runnable.setTask(task);
+ return task;
+ }
+ SchedulerTask task = new SchedulerTask(Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, runnable, delay));
+ runnable.setTask(task);
+ return task;
+ }
+
+ public static SchedulerTask runTaskLaterAsynchronously(@NotNull Plugin plugin, @NotNull Runnable runnable, long delay) {
+ if (isFolia) {
+ return new SchedulerTask(plugin.getServer().getAsyncScheduler().runDelayed(plugin, scheduledTask -> runnable.run(), correctDelay(delay), TimeUnit.MILLISECONDS));
+ }
+ return new SchedulerTask(Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, runnable, delay));
+ }
+
+ public static SchedulerTask scheduleSyncDelayedTask(@NotNull Plugin plugin, @NotNull SchedulerRunnable runnable, long delay) {
+ if (isFolia) {
+ SchedulerTask task = new SchedulerTask(plugin.getServer().getGlobalRegionScheduler().runDelayed(plugin, scheduledTask -> runnable.run(), correctDelay(delay)));
+ runnable.setTask(task);
+ return task;
+ }
+ SchedulerTask task = new SchedulerTask(Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, runnable, delay));
+ runnable.setTask(task);
+ return task;
+ }
+
+ public static SchedulerTask scheduleSyncDelayedTask(@NotNull Plugin plugin, @NotNull Runnable runnable, long delay) {
+ if (isFolia) {
+ return new SchedulerTask(plugin.getServer().getGlobalRegionScheduler().runDelayed(plugin, scheduledTask -> runnable.run(), correctDelay(delay)));
+ }
+ return new SchedulerTask(Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, runnable, delay));
+ }
+
+ public static SchedulerTask scheduleSyncRepeatingTask(@NotNull Plugin plugin, @NotNull SchedulerRunnable runnable, long delay, long period) {
+ if (isFolia) {
+ SchedulerTask task = new SchedulerTask(plugin.getServer().getGlobalRegionScheduler().runAtFixedRate(plugin, scheduledTask -> runnable.run(), correctDelay(delay), correctDelay(period)));
+ runnable.setTask(task);
+ return task;
+ }
+ SchedulerTask task = new SchedulerTask(Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, runnable, delay, period));
+ runnable.setTask(task);
+ return task;
+ }
+
+ public static SchedulerTask scheduleSyncRepeatingTask(@NotNull Plugin plugin, @NotNull Runnable runnable, long delay, long period) {
+ if (isFolia) {
+ return new SchedulerTask(plugin.getServer().getGlobalRegionScheduler().runAtFixedRate(plugin, scheduledTask -> runnable.run(), correctDelay(delay), correctDelay(period)));
+ }
+ return new SchedulerTask(Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, runnable, delay, period));
+ }
+
+ public static SchedulerTask runTaskTimer(@NotNull Plugin plugin, @NotNull SchedulerRunnable runnable, long delay, long period) {
+ if (isFolia) {
+ SchedulerTask task = new SchedulerTask(plugin.getServer().getGlobalRegionScheduler().runAtFixedRate(plugin, scheduledTask -> runnable.run(), correctDelay(delay), correctDelay(period)));
+ runnable.setTask(task);
+ return task;
+ }
+ //return new SchedulerTask(Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, period));
+ SchedulerTask task = new SchedulerTask(Bukkit.getScheduler().runTaskTimer(plugin, runnable, correctDelay(delay), period));
+ runnable.setTask(task);
+ return task;
+ }
+
+ public static SchedulerTask runTaskTimer(@NotNull Plugin plugin, @NotNull Runnable runnable, long delay, long period) {
+ if (isFolia) {
+ return new SchedulerTask(plugin.getServer().getGlobalRegionScheduler().runAtFixedRate(plugin, scheduledTask -> runnable.run(), delay, period));
+ }
+ return new SchedulerTask(Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, period));
+ }
+
+ public static SchedulerTask runTaskTimerAsynchronously(@NotNull Plugin plugin, @NotNull SchedulerRunnable runnable, long delay, long period) {
+ if (isFolia) {
+ SchedulerTask task = new SchedulerTask(plugin.getServer().getAsyncScheduler().runAtFixedRate(plugin, scheduledTask -> runnable.run(), correctDelay(delay), correctDelay(period), TimeUnit.MILLISECONDS));
+ runnable.setTask(task);
+ return task;
+ }
+ SchedulerTask task = new SchedulerTask(Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, delay, period));
+ runnable.setTask(task);
+ return task;
+ }
+
+ public static SchedulerTask runTaskTimerAsynchronously(@NotNull Plugin plugin, @NotNull Runnable runnable, long delay, long period) {
+ if (isFolia) {
+ return new SchedulerTask(plugin.getServer().getAsyncScheduler().runAtFixedRate(plugin, scheduledTask -> runnable.run(), correctDelay(delay), correctDelay(period), TimeUnit.MILLISECONDS));
+ }
+ return new SchedulerTask(Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, delay, period));
+ }
+
+ public static void cancelTask(SchedulerTask task) {
+ if (task == null) return;
+ if (isFolia) {
+ task.getAsFoliaTask().cancel();
+ } else {
+ Bukkit.getScheduler().cancelTask(task.getAsBukkitTaskId());
+ }
+ }
+
+ public static void cancelAllTasks(Plugin plugin) {
+ if (isFolia) {
+ Bukkit.getAsyncScheduler().cancelTasks(plugin);
+ Bukkit.getGlobalRegionScheduler().cancelTasks(plugin);
+ } else {
+ Bukkit.getScheduler().cancelTasks(plugin);
+ }
+ }
+
+ public static boolean isCurrentlyRunning(SchedulerTask task) {
+ if (isFolia) {
+ return task.getAsFoliaTask().getExecutionState() == ScheduledTask.ExecutionState.RUNNING;
+ } else {
+ return Bukkit.getScheduler().isCurrentlyRunning(task.getAsBukkitTaskId());
+ }
+ }
+
+ public static boolean isQueued(SchedulerTask task) {
+ if (isFolia) {
+ return task.getAsFoliaTask().getExecutionState() == ScheduledTask.ExecutionState.RUNNING;
+ } else {
+ return Bukkit.getScheduler().isQueued(task.getAsBukkitTaskId());
+ }
+ }
+
+ private static long correctDelay(long delay) {
+ if (isFolia && delay <= 0) {
+ return 1;
+ }
+ return delay;
+ }
+}
diff --git a/NMS/NMS-API/pom.xml b/NMS/NMS-API/pom.xml
index 998913d0..a21b7edd 100644
--- a/NMS/NMS-API/pom.xml
+++ b/NMS/NMS-API/pom.xml
@@ -13,6 +13,13 @@
SongodaCore-NMS-API
+
+ dev.folia
+ folia-api
+ 1.19.4-R0.1-SNAPSHOT
+ provided
+
+
org.spigotmc
diff --git a/NMS/NMS-API/src/main/java/com/songoda/core/nms/world/SWorld.java b/NMS/NMS-API/src/main/java/com/songoda/core/nms/world/SWorld.java
index 6f2dd16b..71bacf39 100644
--- a/NMS/NMS-API/src/main/java/com/songoda/core/nms/world/SWorld.java
+++ b/NMS/NMS-API/src/main/java/com/songoda/core/nms/world/SWorld.java
@@ -1,9 +1,13 @@
package com.songoda.core.nms.world;
+import io.papermc.paper.threadedregions.scheduler.EntityScheduler;
+import org.bukkit.Location;
import org.bukkit.Material;
+import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import java.util.List;
+import java.util.Map;
public interface SWorld {
List getLivingEntities();
@@ -17,4 +21,8 @@ public interface SWorld {
// TODO: Check if FabledSkyBlock *really* needs this method and if it can be removed.
// Would make thinks less complicated and I kinda cannot imagine it being *that* much faster to be worth it?
void setBlockFast(int x, int y, int z, Material material);
+
+ default Map> getRegionizedEntities() {
+ throw new UnsupportedOperationException("This server version does not support threaded regions. Not a Folia server.");
+ }
}
diff --git a/NMS/NMS-v1_19_R3/pom.xml b/NMS/NMS-v1_19_R3/pom.xml
index b16a9838..df2dc7f6 100644
--- a/NMS/NMS-v1_19_R3/pom.xml
+++ b/NMS/NMS-v1_19_R3/pom.xml
@@ -62,6 +62,13 @@
+
+ dev.folia
+ folia-api
+ 1.19.4-R0.1-SNAPSHOT
+ provided
+
+
org.spigotmc
@@ -84,5 +91,12 @@
${project.version}
provided
+
+
+ io.papermc
+ paperlib
+ 1.0.8
+ provided
+
diff --git a/NMS/NMS-v1_19_R3/src/main/java/com/songoda/core/nms/v1_19_R3/world/SSpawnerImpl.java b/NMS/NMS-v1_19_R3/src/main/java/com/songoda/core/nms/v1_19_R3/world/SSpawnerImpl.java
index 78eaa0cc..c182f374 100644
--- a/NMS/NMS-v1_19_R3/src/main/java/com/songoda/core/nms/v1_19_R3/world/SSpawnerImpl.java
+++ b/NMS/NMS-v1_19_R3/src/main/java/com/songoda/core/nms/v1_19_R3/world/SSpawnerImpl.java
@@ -5,6 +5,7 @@
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SpawnedEntity;
import com.cryptomorin.xseries.XMaterial;
+import io.papermc.lib.PaperLib;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
@@ -93,7 +94,7 @@ public LivingEntity spawnEntity(EntityType type, String particleType, SpawnedEnt
world.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.SPAWNER);
spot.setYaw(random.nextFloat() * 360.0F);
- craftEntity.teleport(spot);
+ PaperLib.teleportAsync(craftEntity, spot);
return craftEntity;
}
diff --git a/NMS/NMS-v1_19_R3/src/main/java/com/songoda/core/nms/v1_19_R3/world/SWorldImpl.java b/NMS/NMS-v1_19_R3/src/main/java/com/songoda/core/nms/v1_19_R3/world/SWorldImpl.java
index fa941282..bfa361ae 100644
--- a/NMS/NMS-v1_19_R3/src/main/java/com/songoda/core/nms/v1_19_R3/world/SWorldImpl.java
+++ b/NMS/NMS-v1_19_R3/src/main/java/com/songoda/core/nms/v1_19_R3/world/SWorldImpl.java
@@ -1,20 +1,29 @@
package com.songoda.core.nms.v1_19_R3.world;
+import com.songoda.core.compatibility.ServerProject;
+import com.songoda.core.compatibility.ServerVersion;
import com.songoda.core.nms.world.SWorld;
+import io.papermc.paper.threadedregions.scheduler.EntityScheduler;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.entity.LevelEntityGetter;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData;
import org.bukkit.entity.LivingEntity;
+import java.lang.reflect.Field;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
public class SWorldImpl implements SWorld {
private final World world;
@@ -49,4 +58,24 @@ public void setBlockFast(int x, int y, int z, Material material) {
levelChunk.setBlockState(new BlockPos(x & 0xF, y, z & 0xF), blockState, true);
}
+
+ @Override
+ public Map> getRegionizedEntities() {
+ if (!ServerProject.isServer(ServerProject.FOLIA)) {
+ SWorld.super.getRegionizedEntities();
+ }
+ Map> result = new HashMap<>();
+
+ for (LivingEntity entity : getLivingEntities()) {
+ EntityScheduler scheduler = entity.getScheduler();
+
+ if (!result.containsKey(scheduler)) {
+ result.computeIfAbsent(scheduler, k -> new ArrayList<>(List.of(entity)));
+ }
+
+ result.get(scheduler).add(entity);
+ }
+
+ return result;
+ }
}
diff --git a/pom.xml b/pom.xml
index 6fc7c99a..8e68d6ac 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,6 +23,7 @@
Core
Compatibility
+ Folia-Compatibility
NMS/NMS
NMS/NMS-API