From 6d46e3311cf4eec9088d4dedfd95bd93eac72e4a Mon Sep 17 00:00:00 2001 From: ceze88 Date: Wed, 17 May 2023 12:57:40 +0200 Subject: [PATCH] Add folia support --- .../core/compatibility/ServerVersion.java | 15 ++ Core/pom.xml | 26 ++- .../java/com/songoda/core/SongodaCore.java | 30 ++-- .../java/com/songoda/core/SongodaPlugin.java | 3 +- .../core/database/DataManagerAbstract.java | 5 +- .../java/com/songoda/core/gui/GuiManager.java | 9 +- .../com/songoda/core/input/ChatPrompt.java | 10 +- .../core/lootables/loot/DropUtils.java | 5 +- .../main/java/com/songoda/core/nms/Nms.java | 12 +- .../java/com/songoda/core/utils/Metrics.java | 3 +- .../java/com/songoda/core/world/SWorld.java | 10 ++ Folia/pom.xml | 49 ++++++ .../main/java/com/songoda/SchedulerTask.java | 24 +++ .../main/java/com/songoda/SchedulerUtils.java | 155 ++++++++++++++++++ NMS/NMS-API/pom.xml | 7 + .../com/songoda/core/nms/world/SWorld.java | 8 + .../nms/v1_19_R2/NmsImplementationsImpl.java | 56 +++++++ .../v1_19_R2/world/NmsWorldBorderImpl.java | 35 ++++ NMS/NMS-v1_19_R3/pom.xml | 14 ++ .../nms/v1_19_R3/NmsImplementationsImpl.java | 56 +++++++ .../v1_19_R3/world/NmsWorldBorderImpl.java | 35 ++++ .../core/nms/v1_19_R3/world/SSpawnerImpl.java | 3 +- .../core/nms/v1_19_R3/world/SWorldImpl.java | 28 ++++ NMS/NMS/pom.xml | 6 + pom.xml | 1 + 25 files changed, 573 insertions(+), 32 deletions(-) create mode 100644 Folia/pom.xml create mode 100644 Folia/src/main/java/com/songoda/SchedulerTask.java create mode 100644 Folia/src/main/java/com/songoda/SchedulerUtils.java create mode 100644 NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/NmsImplementationsImpl.java create mode 100644 NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/NmsWorldBorderImpl.java create mode 100644 NMS/NMS-v1_19_R3/src/main/java/com/songoda/core/nms/v1_19_R3/NmsImplementationsImpl.java create mode 100644 NMS/NMS-v1_19_R3/src/main/java/com/songoda/core/nms/v1_19_R3/world/NmsWorldBorderImpl.java diff --git a/Compatibility/src/main/java/com/songoda/core/compatibility/ServerVersion.java b/Compatibility/src/main/java/com/songoda/core/compatibility/ServerVersion.java index 763eeef3..37316473 100644 --- a/Compatibility/src/main/java/com/songoda/core/compatibility/ServerVersion.java +++ b/Compatibility/src/main/java/com/songoda/core/compatibility/ServerVersion.java @@ -11,7 +11,10 @@ public enum ServerVersion { private final static ServerVersion serverVersion; private final static boolean isMocked; + private final static boolean isFolia; + static { + boolean isFolia1; if (Bukkit.getServer() != null) { String srvPackage = Bukkit.getServer().getClass().getPackage().getName(); isMocked = srvPackage.equals("be.seeseemelk.mockbukkit"); @@ -29,9 +32,21 @@ public enum ServerVersion { isMocked = false; } + try { + Class.forName("io.papermc.paper.threadedregions.RegionizedServer"); + isFolia1 = true; + } catch (ClassNotFoundException e) { + isFolia1 = false; + } + isFolia = isFolia1; + serverVersion = getVersion(); } + public static boolean isFolia() { + return isFolia; + } + private static ServerVersion getVersion() { for (ServerVersion version : values()) { if (serverPackageVersion.toUpperCase().startsWith(version.name())) { diff --git a/Core/pom.xml b/Core/pom.xml index b56f1db4..855967af 100644 --- a/Core/pom.xml +++ b/Core/pom.xml @@ -84,6 +84,7 @@ org.apache.commons:commons-lang3 org.apache.commons:commons-text org.yaml:snakeyaml + io.papermc:paperlib @@ -109,8 +110,8 @@ - org.yaml.snakeyaml - com.songoda.core.third_party.org.yaml.snakeyaml + io.papermc.lib + com.songoda.core.third_party.io.papermc.lib @@ -142,6 +143,13 @@ + + dev.folia + folia-api + 1.19.4-R0.1-SNAPSHOT + provided + + org.spigotmc spigot @@ -149,6 +157,13 @@ provided + + io.papermc + paperlib + 1.0.7 + compile + + ${project.groupId} SongodaCore-Compatibility @@ -156,6 +171,13 @@ compile + + ${project.groupId} + Folia + ${project.version} + compile + + ${project.groupId} SongodaCore-NMS diff --git a/Core/src/main/java/com/songoda/core/SongodaCore.java b/Core/src/main/java/com/songoda/core/SongodaCore.java index 81025e23..10636c2b 100644 --- a/Core/src/main/java/com/songoda/core/SongodaCore.java +++ b/Core/src/main/java/com/songoda/core/SongodaCore.java @@ -1,5 +1,7 @@ package com.songoda.core; +import com.songoda.SchedulerTask; +import com.songoda.SchedulerUtils; import com.songoda.core.commands.CommandManager; import com.songoda.core.compatibility.ClientVersion; import com.songoda.core.compatibility.CompatibleMaterial; @@ -198,15 +200,14 @@ public class SongodaCore { Bukkit.getPluginManager().registerEvents(shadingListener, piggybackedPlugin); // we aggressively want to own this command - tasks.add(Bukkit.getScheduler().runTaskLaterAsynchronously(piggybackedPlugin, () -> - CommandManager.registerCommandDynamically(piggybackedPlugin, "songoda", commandManager, commandManager), - 10 * 60)); - tasks.add(Bukkit.getScheduler().runTaskLaterAsynchronously(piggybackedPlugin, () -> - CommandManager.registerCommandDynamically(piggybackedPlugin, "songoda", commandManager, commandManager), - 20 * 60)); - tasks.add(Bukkit.getScheduler().runTaskLaterAsynchronously(piggybackedPlugin, () -> - CommandManager.registerCommandDynamically(piggybackedPlugin, "songoda", commandManager, commandManager), - 20 * 60 * 2)); + tasks.add(SchedulerUtils.runTaskLater(piggybackedPlugin, () -> + CommandManager.registerCommandDynamically(piggybackedPlugin, "songoda", commandManager, commandManager), 10 * 60)); + + tasks.add(SchedulerUtils.runTaskLater(piggybackedPlugin, () -> + CommandManager.registerCommandDynamically(piggybackedPlugin, "songoda", commandManager, commandManager), 20 * 60)); + + tasks.add(SchedulerUtils.runTaskLater(piggybackedPlugin, () -> + CommandManager.registerCommandDynamically(piggybackedPlugin, "songoda", commandManager, commandManager), 20 * 60 * 2)); } /** @@ -216,7 +217,7 @@ public class SongodaCore { Bukkit.getServicesManager().unregister(SongodaCore.class, INSTANCE); tasks.stream().filter(Objects::nonNull) - .forEach(task -> Bukkit.getScheduler().cancelTask(task.getTaskId())); + .forEach(SchedulerUtils::cancelTask); HandlerList.unregisterAll(loginListener); if (!hasShading()) { @@ -228,7 +229,7 @@ public class SongodaCore { loginListener = null; } - private ArrayList tasks = new ArrayList<>(); + private ArrayList tasks = new ArrayList<>(); private void register(JavaPlugin plugin, int pluginID, String icon, String libraryVersion) { logger.info(getPrefix() + "Hooked " + plugin.getName() + "."); @@ -237,7 +238,7 @@ public class SongodaCore { // don't forget to check for language pack updates ;) info.addModule(new LocaleModule()); registeredPlugins.add(info); - tasks.add(Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, () -> update(info), 60L)); + tasks.add(SchedulerUtils.runTaskLaterAsynchronously(plugin, () -> update(info), 60L)); } /** @@ -416,9 +417,10 @@ public class SongodaCore { // check for updates! ;) for (PluginInfo plugin : getPlugins()) { - if (plugin.getNotification() != null && plugin.getJavaPlugin().isEnabled()) - Bukkit.getScheduler().runTaskLaterAsynchronously(plugin.getJavaPlugin(), () -> + if (plugin.getNotification() != null && plugin.getJavaPlugin().isEnabled()) { + SchedulerUtils.runTaskLaterAsynchronously(plugin.getJavaPlugin(), () -> player.sendMessage("[" + plugin.getJavaPlugin().getName() + "] " + plugin.getNotification()), 10L); + } } } diff --git a/Core/src/main/java/com/songoda/core/SongodaPlugin.java b/Core/src/main/java/com/songoda/core/SongodaPlugin.java index 41937b30..90ce9b6d 100644 --- a/Core/src/main/java/com/songoda/core/SongodaPlugin.java +++ b/Core/src/main/java/com/songoda/core/SongodaPlugin.java @@ -1,5 +1,6 @@ package com.songoda.core; +import com.songoda.SchedulerUtils; import com.songoda.core.configuration.Config; import com.songoda.core.database.DataManagerAbstract; import com.songoda.core.locale.Locale; @@ -136,7 +137,7 @@ public abstract class SongodaPlugin extends JavaPlugin { } // Load Data. - Bukkit.getScheduler().runTaskLater(this, this::onDataLoad, this.dataLoadDelay); + SchedulerUtils.runTaskLater(this, this::onDataLoad, this.dataLoadDelay); if (this.emergencyStop) { console.sendMessage(ChatColor.RED + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); diff --git a/Core/src/main/java/com/songoda/core/database/DataManagerAbstract.java b/Core/src/main/java/com/songoda/core/database/DataManagerAbstract.java index 78435c7d..ac28d912 100644 --- a/Core/src/main/java/com/songoda/core/database/DataManagerAbstract.java +++ b/Core/src/main/java/com/songoda/core/database/DataManagerAbstract.java @@ -1,5 +1,6 @@ package com.songoda.core.database; +import com.songoda.SchedulerUtils; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; @@ -81,7 +82,7 @@ public class DataManagerAbstract { */ @Deprecated public void async(Runnable runnable) { - Bukkit.getScheduler().runTaskAsynchronously(this.plugin, runnable); + SchedulerUtils.runTaskAsynchronously(plugin, runnable); } /** @@ -100,7 +101,7 @@ public class DataManagerAbstract { * @param runnable task to run on the next server tick */ public void sync(Runnable runnable) { - Bukkit.getScheduler().runTask(this.plugin, runnable); + SchedulerUtils.runTask(plugin, runnable); } public void runAsync(Runnable runnable) { 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 66256a50..8d5fcdb2 100644 --- a/Core/src/main/java/com/songoda/core/gui/GuiManager.java +++ b/Core/src/main/java/com/songoda/core/gui/GuiManager.java @@ -1,5 +1,6 @@ package com.songoda.core.gui; +import com.songoda.SchedulerUtils; import com.songoda.core.compatibility.ClientVersion; import com.songoda.core.compatibility.CompatibleMaterial; import com.songoda.core.compatibility.ServerVersion; @@ -102,7 +103,7 @@ public class GuiManager { return; } - Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + SchedulerUtils.runTaskAsynchronously(plugin, () -> { Gui openInv = openInventories.get(player); if (openInv != null) { @@ -111,7 +112,7 @@ public class GuiManager { Inventory inv = gui.getOrCreateInventory(this); - Bukkit.getScheduler().runTask(plugin, () -> { + SchedulerUtils.runTask(plugin, () -> { player.openInventory(inv); gui.onOpen(this, player); @@ -136,7 +137,7 @@ public class GuiManager { popup.add(); popup.grant(player); - Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, () -> { + SchedulerUtils.runTaskLaterAsynchronously(plugin, () -> { popup.revoke(player); popup.remove(); }, 70); @@ -280,7 +281,7 @@ public class GuiManager { if (manager.shutdown) { gui.onClose(manager, player); } else { - Bukkit.getScheduler().runTaskLater(manager.plugin, () -> gui.onClose(manager, player), 1); + SchedulerUtils.runEntityTask(manager.plugin, player, () -> gui.onClose(manager, player), 1); } 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 ca9add4b..a58dfb25 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,7 @@ package com.songoda.core.input; +import com.songoda.SchedulerTask; +import com.songoda.SchedulerUtils; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -20,7 +22,7 @@ public class ChatPrompt implements Listener { private final Plugin plugin; private final ChatConfirmHandler handler; - private int taskId; + private SchedulerTask taskId; private OnClose onClose = null; private OnCancel onCancel = null; private Listener listener; @@ -67,7 +69,7 @@ public class ChatPrompt implements Listener { } public ChatPrompt setTimeOut(Player player, long ticks) { - taskId = Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, () -> { + taskId = SchedulerUtils.scheduleSyncDelayedTask(plugin, () -> { if (onClose != null) { plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> onClose.onClose(), 0L); @@ -108,7 +110,7 @@ public class ChatPrompt implements Listener { } HandlerList.unregisterAll(listener); - Bukkit.getScheduler().cancelTask(taskId); + SchedulerUtils.cancelTask(taskId); } @EventHandler(priority = EventPriority.LOWEST) @@ -132,7 +134,7 @@ public class ChatPrompt implements Listener { } HandlerList.unregisterAll(listener); - Bukkit.getScheduler().cancelTask(taskId); + SchedulerUtils.cancelTask(taskId); } }; 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 4d57b8fe..19b38b8e 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,6 +1,7 @@ package com.songoda.core.lootables.loot; import com.bgsoftware.wildstacker.api.objects.StackedItem; +import com.songoda.SchedulerUtils; import com.songoda.core.SongodaCore; import com.songoda.ultimatestacker.UltimateStacker; import com.songoda.ultimatestacker.settings.Settings; @@ -87,7 +88,7 @@ public class DropUtils { } stack.setamount(newAmount); } - Bukkit.getScheduler().runTask(UltimateStacker.getInstance(), () -> { + SchedulerUtils.runLocationTask(UltimateStacker.getInstance(), event.getEntity().getLocation(), () -> { for (StackedItem stack : stacks) { UltimateStacker.spawnStackedItem(stack.getItem(), stack.getAmount(), event.getEntity().getLocation()); } @@ -98,7 +99,7 @@ public class DropUtils { } private static void runCommands(LivingEntity entity, List commands) { - Bukkit.getScheduler().runTask(SongodaCore.getHijackedPlugin(), () -> { + SchedulerUtils.runTask(SongodaCore.getHijackedPlugin(), () -> { for (String command : commands) { if (entity.getKiller() != null) { command = command.replace("%player%", entity.getKiller().getName() diff --git a/Core/src/main/java/com/songoda/core/nms/Nms.java b/Core/src/main/java/com/songoda/core/nms/Nms.java index 7b01821e..60824e05 100644 --- a/Core/src/main/java/com/songoda/core/nms/Nms.java +++ b/Core/src/main/java/com/songoda/core/nms/Nms.java @@ -1,6 +1,7 @@ package com.songoda.core.nms; import com.songoda.core.compatibility.ServerVersion; +import com.songoda.core.nms.v1_19_R3.NmsImplementationsImpl; public class Nms { protected static NmsImplementations impl; @@ -11,8 +12,17 @@ public class Nms { public static NmsImplementations getImplementations() throws UnsupportedServerVersionException { if (impl == null) { try { + if (ServerVersion.isFolia()) { + impl = new NmsImplementationsImpl(); + return impl; + } + switch (ServerVersion.getServerVersionString()) { + case "v1_19_R2": + impl = new com.songoda.core.nms.v1_19_R2.NmsImplementationsImpl(); + break; + } impl = (NmsImplementations) Class.forName("com.songoda.core.nms." + ServerVersion.getServerVersionString() + ".NmsImplementationsImpl").getConstructors()[0].newInstance(); - } catch (ReflectiveOperationException ex) { + } catch (Exception ex) { throw new UnsupportedServerVersionException(ex); } } 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 36aa7dca..32098d3b 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,6 @@ package com.songoda.core.utils; +import com.songoda.SchedulerUtils; import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; @@ -188,7 +189,7 @@ public class Metrics { } // 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, () -> 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 ac70ccff..125863ba 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 @@ package com.songoda.core.world; 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 class SWorld { return 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 world; } diff --git a/Folia/pom.xml b/Folia/pom.xml new file mode 100644 index 00000000..f6d8f446 --- /dev/null +++ b/Folia/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + com.songoda + SongodaCore-Modules + 2.6.22 + + + Folia + + + 17 + 17 + UTF-8 + + + + + papermc + https://repo.papermc.io/repository/maven-public/ + + + + + + ${project.groupId} + SongodaCore-Compatibility + ${project.version} + compile + + + + 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/src/main/java/com/songoda/SchedulerTask.java b/Folia/src/main/java/com/songoda/SchedulerTask.java new file mode 100644 index 00000000..c2bc40c5 --- /dev/null +++ b/Folia/src/main/java/com/songoda/SchedulerTask.java @@ -0,0 +1,24 @@ +package com.songoda; + +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; + +public class SchedulerTask { + + private final Object task; + + public SchedulerTask(Object task) { + this.task = task; + } + + public Object getTask() { + return task; + } + + public ScheduledTask getAsFoliaTask() { + return (ScheduledTask) task; + } + + public int getAsBukkitTaskId() { + return (int) task; + } +} diff --git a/Folia/src/main/java/com/songoda/SchedulerUtils.java b/Folia/src/main/java/com/songoda/SchedulerUtils.java new file mode 100644 index 00000000..f5e27253 --- /dev/null +++ b/Folia/src/main/java/com/songoda/SchedulerUtils.java @@ -0,0 +1,155 @@ +package com.songoda; + +import com.songoda.core.compatibility.ServerVersion; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.TimeUnit; + +public class SchedulerUtils { + + + /** + * Run a task on an entity or fallback for Bukkit#runTask + */ + public static SchedulerTask runEntityTask(@NotNull Plugin plugin, @NotNull Entity entity, @NotNull Runnable runnable) { + if (ServerVersion.isFolia()) { + return new SchedulerTask(runEntityTask(plugin, entity, runnable, 1)); + } + return new SchedulerTask(Bukkit.getScheduler().runTask(plugin, runnable)); + } + + public static SchedulerTask runEntityTask(@NotNull Plugin plugin, @NotNull Entity entity, @NotNull Runnable runnable, long delay) { + if (ServerVersion.isFolia()) { + return new SchedulerTask(entity.getScheduler().runDelayed(plugin, scheduledTask -> runnable.run(), null, delay)); + } + return new SchedulerTask(Bukkit.getScheduler().runTask(plugin, runnable)); + } + + //location task + + public static SchedulerTask runLocationTask(@NotNull Plugin plugin, @NotNull Location location, @NotNull Runnable runnable) { + if (ServerVersion.isFolia()) { + return new SchedulerTask(runLocationTask(plugin, location, runnable, 1)); + } + return new SchedulerTask(Bukkit.getScheduler().runTask(plugin, runnable)); + } + + public static SchedulerTask runEntityTask(@NotNull Plugin plugin, @NotNull Entity entity, @NotNull Runnable runnable, long delay, long period) { + if (ServerVersion.isFolia()) { + return new SchedulerTask(entity.getScheduler().runAtFixedRate(plugin, scheduledTask -> runnable.run(), null, delay, period)); + } + return new SchedulerTask(Bukkit.getScheduler().runTask(plugin, runnable)); + } + + /** + * Run a task on a location or fallback for Bukkit#runTask + * Delay is in ticks + */ + public static SchedulerTask runLocationTask(@NotNull Plugin plugin, @NotNull Location location, @NotNull Runnable runnable, long delay) { + if (ServerVersion.isFolia()) { + return new SchedulerTask(plugin.getServer().getRegionScheduler().runDelayed(plugin, location, scheduledTask -> runnable.run(), delay)); + } + return new SchedulerTask(Bukkit.getScheduler().runTask(plugin, runnable)); + } + + public static SchedulerTask runLocationTask(@NotNull Plugin plugin, @NotNull Location location, @NotNull Runnable runnable, long delay, long period) { + if (ServerVersion.isFolia()) { + return new SchedulerTask(plugin.getServer().getRegionScheduler().runAtFixedRate(plugin, location, scheduledTask -> runnable.run(), delay, period)); + } + return new SchedulerTask(Bukkit.getScheduler().runTask(plugin, runnable)); + } + + public static SchedulerTask runTask(@NotNull Plugin plugin, @NotNull Runnable runnable) { + if (ServerVersion.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 Runnable runnable) { + if (ServerVersion.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 Runnable runnable, long delay) { + if (ServerVersion.isFolia()) { + return new SchedulerTask(plugin.getServer().getGlobalRegionScheduler().runDelayed(plugin, scheduledTask -> runnable.run(), delay)); + } + return new SchedulerTask(Bukkit.getScheduler().runTaskLater(plugin, runnable, delay)); + } + + public static SchedulerTask runTaskLaterAsynchronously(@NotNull Plugin plugin, @NotNull Runnable runnable, long delay) { + if (ServerVersion.isFolia()) { + return new SchedulerTask(plugin.getServer().getAsyncScheduler().runDelayed(plugin, scheduledTask -> runnable.run(), delay, TimeUnit.MILLISECONDS)); + } + return new SchedulerTask(Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, runnable, delay)); + } + + public static SchedulerTask scheduleSyncDelayedTask(@NotNull Plugin plugin, @NotNull Runnable runnable, long delay) { + if (ServerVersion.isFolia()) { + return new SchedulerTask(plugin.getServer().getGlobalRegionScheduler().runDelayed(plugin, scheduledTask -> runnable.run(), delay)); + } + return new SchedulerTask(Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, runnable, delay)); + } + + public static SchedulerTask scheduleSyncRepeatingTask(@NotNull Plugin plugin, @NotNull Runnable runnable, long delay, long period) { + if (ServerVersion.isFolia()) { + return new SchedulerTask(plugin.getServer().getGlobalRegionScheduler().runAtFixedRate(plugin, scheduledTask -> runnable.run(), delay, period)); + } + return new SchedulerTask(Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, runnable, delay, period)); + } + + public static SchedulerTask runTaskTimer(@NotNull Plugin plugin, @NotNull Runnable runnable, long delay, long period) { + if (ServerVersion.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 Runnable runnable, long delay, long period) { + if (ServerVersion.isFolia()) { + return new SchedulerTask(plugin.getServer().getAsyncScheduler().runAtFixedRate(plugin, scheduledTask -> runnable.run(), delay, period, TimeUnit.MILLISECONDS)); + } + return new SchedulerTask(Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, delay, period)); + } + + public static void cancelTask(SchedulerTask task) { + if (ServerVersion.isFolia()) { + task.getAsFoliaTask().cancel(); + } else { + Bukkit.getScheduler().cancelTask(task.getAsBukkitTaskId()); + } + } + + public static void cancelAllTasks(Plugin plugin) { + if (ServerVersion.isFolia()) { + Bukkit.getAsyncScheduler().cancelTasks(plugin); + Bukkit.getGlobalRegionScheduler().cancelTasks(plugin); + } else { + Bukkit.getScheduler().cancelTasks(plugin); + } + } + + public static boolean isCurrentlyRunning(SchedulerTask task) { + if (ServerVersion.isFolia()) { + return task.getAsFoliaTask().getExecutionState() == ScheduledTask.ExecutionState.RUNNING; + } else { + return Bukkit.getScheduler().isCurrentlyRunning(task.getAsBukkitTaskId()); + } + } + + public static boolean isQueued(SchedulerTask task) { + if (ServerVersion.isFolia()) { + return task.getAsFoliaTask().getExecutionState() == ScheduledTask.ExecutionState.RUNNING; + } else { + return Bukkit.getScheduler().isQueued(task.getAsBukkitTaskId()); + } + } +} diff --git a/NMS/NMS-API/pom.xml b/NMS/NMS-API/pom.xml index b1be3987..dca76d92 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_R2/src/main/java/com/songoda/core/nms/v1_19_R2/NmsImplementationsImpl.java b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/NmsImplementationsImpl.java new file mode 100644 index 00000000..147f32ef --- /dev/null +++ b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/NmsImplementationsImpl.java @@ -0,0 +1,56 @@ +package com.songoda.core.nms.v1_19_R2; + +import com.songoda.core.nms.NmsImplementations; +import com.songoda.core.nms.anvil.AnvilCore; +import com.songoda.core.nms.entity.NMSPlayer; +import com.songoda.core.nms.nbt.NBTCore; +import com.songoda.core.nms.v1_19_R2.entity.NMSPlayerImpl; +import com.songoda.core.nms.v1_19_R2.nbt.NBTCoreImpl; +import com.songoda.core.nms.v1_19_R2.world.NmsWorldBorderImpl; +import com.songoda.core.nms.v1_19_R2.world.WorldCoreImpl; +import com.songoda.core.nms.world.NmsWorldBorder; +import com.songoda.core.nms.world.WorldCore; +import org.bukkit.craftbukkit.v1_19_R2.util.CraftMagicNumbers; +import org.jetbrains.annotations.NotNull; + +@SuppressWarnings("unused") +public class NmsImplementationsImpl implements NmsImplementations { + private final NMSPlayer player; + private final WorldCore world; + private final NmsWorldBorder worldBorder; + private final AnvilCore anvil; + private final NBTCore nbt; + + public NmsImplementationsImpl() { + this.player = new NMSPlayerImpl(); + this.world = new WorldCoreImpl(); + this.worldBorder = new NmsWorldBorderImpl(); + this.anvil = new com.songoda.core.nms.v1_19_R2.anvil.AnvilCore(); + this.nbt = new NBTCoreImpl(); + } + + @Override + public @NotNull NMSPlayer getPlayer() { + return this.player; + } + + @Override + public @NotNull WorldCore getWorld() { + return this.world; + } + + @Override + public @NotNull NmsWorldBorder getWorldBorder() { + return this.worldBorder; + } + + @Override + public @NotNull AnvilCore getAnvil() { + return this.anvil; + } + + @Override + public @NotNull NBTCore getNbt() { + return this.nbt; + } +} diff --git a/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/NmsWorldBorderImpl.java b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/NmsWorldBorderImpl.java new file mode 100644 index 00000000..3dd9ee44 --- /dev/null +++ b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/NmsWorldBorderImpl.java @@ -0,0 +1,35 @@ +package com.songoda.core.nms.v1_19_R2.world; + +import com.songoda.core.nms.world.NmsWorldBorder; +import net.minecraft.network.protocol.game.ClientboundInitializeBorderPacket; +import net.minecraft.world.level.border.WorldBorder; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; +import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public class NmsWorldBorderImpl implements NmsWorldBorder { + @Override + public void send(Player player, BorderColor color, double size, @NotNull Location center) { + Objects.requireNonNull(center.getWorld()); + + WorldBorder worldBorder = new WorldBorder(); + worldBorder.world = ((CraftWorld) center.getWorld()).getHandle(); + + worldBorder.setCenter(center.getX(), center.getZ()); + worldBorder.setSize(size); + worldBorder.setWarningTime(0); + worldBorder.setWarningBlocks(0); + + if (color == BorderColor.GREEN) { + worldBorder.lerpSizeBetween(size - 0.1D, size, Long.MAX_VALUE); + } else if (color == BorderColor.RED) { + worldBorder.lerpSizeBetween(size, size - 1.0D, Long.MAX_VALUE); + } + + ((CraftPlayer) player).getHandle().connection.send(new ClientboundInitializeBorderPacket(worldBorder)); + } +} diff --git a/NMS/NMS-v1_19_R3/pom.xml b/NMS/NMS-v1_19_R3/pom.xml index 09883d3e..7a157eeb 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.7 + provided + diff --git a/NMS/NMS-v1_19_R3/src/main/java/com/songoda/core/nms/v1_19_R3/NmsImplementationsImpl.java b/NMS/NMS-v1_19_R3/src/main/java/com/songoda/core/nms/v1_19_R3/NmsImplementationsImpl.java new file mode 100644 index 00000000..efab9107 --- /dev/null +++ b/NMS/NMS-v1_19_R3/src/main/java/com/songoda/core/nms/v1_19_R3/NmsImplementationsImpl.java @@ -0,0 +1,56 @@ +package com.songoda.core.nms.v1_19_R3; + +import com.songoda.core.nms.NmsImplementations; +import com.songoda.core.nms.anvil.AnvilCore; +import com.songoda.core.nms.entity.NMSPlayer; +import com.songoda.core.nms.nbt.NBTCore; +import com.songoda.core.nms.v1_19_R3.entity.NMSPlayerImpl; +import com.songoda.core.nms.v1_19_R3.nbt.NBTCoreImpl; +import com.songoda.core.nms.v1_19_R3.world.NmsWorldBorderImpl; +import com.songoda.core.nms.v1_19_R3.world.WorldCoreImpl; +import com.songoda.core.nms.world.NmsWorldBorder; +import com.songoda.core.nms.world.WorldCore; +import org.bukkit.craftbukkit.v1_19_R3.util.CraftMagicNumbers; +import org.jetbrains.annotations.NotNull; + +@SuppressWarnings("unused") +public class NmsImplementationsImpl implements NmsImplementations { + private final NMSPlayer player; + private final WorldCore world; + private final NmsWorldBorder worldBorder; + private final AnvilCore anvil; + private final NBTCore nbt; + + public NmsImplementationsImpl() { + this.player = new NMSPlayerImpl(); + this.world = new WorldCoreImpl(); + this.worldBorder = new NmsWorldBorderImpl(); + this.anvil = new com.songoda.core.nms.v1_19_R3.anvil.AnvilCore(); + this.nbt = new NBTCoreImpl(); + } + + @Override + public @NotNull NMSPlayer getPlayer() { + return this.player; + } + + @Override + public @NotNull WorldCore getWorld() { + return this.world; + } + + @Override + public @NotNull NmsWorldBorder getWorldBorder() { + return this.worldBorder; + } + + @Override + public @NotNull AnvilCore getAnvil() { + return this.anvil; + } + + @Override + public @NotNull NBTCore getNbt() { + return this.nbt; + } +} diff --git a/NMS/NMS-v1_19_R3/src/main/java/com/songoda/core/nms/v1_19_R3/world/NmsWorldBorderImpl.java b/NMS/NMS-v1_19_R3/src/main/java/com/songoda/core/nms/v1_19_R3/world/NmsWorldBorderImpl.java new file mode 100644 index 00000000..bb53f96c --- /dev/null +++ b/NMS/NMS-v1_19_R3/src/main/java/com/songoda/core/nms/v1_19_R3/world/NmsWorldBorderImpl.java @@ -0,0 +1,35 @@ +package com.songoda.core.nms.v1_19_R3.world; + +import com.songoda.core.nms.world.NmsWorldBorder; +import net.minecraft.network.protocol.game.ClientboundInitializeBorderPacket; +import net.minecraft.world.level.border.WorldBorder; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_19_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public class NmsWorldBorderImpl implements NmsWorldBorder { + @Override + public void send(Player player, BorderColor color, double size, @NotNull Location center) { + Objects.requireNonNull(center.getWorld()); + + WorldBorder worldBorder = new WorldBorder(); + worldBorder.world = ((CraftWorld) center.getWorld()).getHandle(); + + worldBorder.setCenter(center.getX(), center.getZ()); + worldBorder.setSize(size); + worldBorder.setWarningTime(0); + worldBorder.setWarningBlocks(0); + + if (color == BorderColor.GREEN) { + worldBorder.lerpSizeBetween(size - 0.1D, size, Long.MAX_VALUE); + } else if (color == BorderColor.RED) { + worldBorder.lerpSizeBetween(size, size - 1.0D, Long.MAX_VALUE); + } + + ((CraftPlayer) player).getHandle().connection.send(new ClientboundInitializeBorderPacket(worldBorder)); + } +} 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 b4722d8e..16ba1c5d 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 @@ -4,6 +4,7 @@ import com.songoda.core.compatibility.CompatibleMaterial; import com.songoda.core.compatibility.CompatibleParticleHandler; import com.songoda.core.nms.world.SSpawner; import com.songoda.core.nms.world.SpawnedEntity; +import io.papermc.lib.PaperLib; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; @@ -92,7 +93,7 @@ public class SSpawnerImpl implements SSpawner { 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..c5a5727a 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,28 @@ package com.songoda.core.nms.v1_19_R3.world; +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 +57,24 @@ public class SWorldImpl implements SWorld { levelChunk.setBlockState(new BlockPos(x & 0xF, y, z & 0xF), blockState, true); } + + @Override + public Map> getRegionizedEntities() { + if (!ServerVersion.isFolia()) { + 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/NMS/NMS/pom.xml b/NMS/NMS/pom.xml index 38514e89..eff98e7f 100644 --- a/NMS/NMS/pom.xml +++ b/NMS/NMS/pom.xml @@ -141,5 +141,11 @@ ${project.groupId} compile + + ${project.version} + SongodaCore-NMS-v1_19_R3 + ${project.groupId} + compile + diff --git a/pom.xml b/pom.xml index de44f20f..172ab59c 100644 --- a/pom.xml +++ b/pom.xml @@ -48,6 +48,7 @@ NMS/NMS-v1_19_R1 NMS/NMS-v1_19_R2 NMS/NMS-v1_19_R3 + Folia