Skip to content

Commit 9435618

Browse files
authored
Preliminary Folia support (#763)
* Initial work for Folia support * More Folia work * Task - add isCancelled and get id * SecRunTaskLater - add folia options * EffTaskStop - remove support for all tasks - Stopping all tasks will also stop internal tasks SkBee is running, OOPS! * SecWhileRunnable - add folia option * Config - add setting to allow using Paper schedulers * FoliaScheduler - prevent 0 delay * Task sections - update docs, fix a bug, change pattern for run task later * CondIsOwnedByRegion - add condition to check regions * SecRunTaskLater - fix expression location * build.gradle - use Paper's javadocs * Tasks - update javadocs * TaskUtils - strip SkBee stuff out and use generic plugin - this allows other plugins to use these classes easily * Section pattern cleanup * Tasks - remove block as its not really needed - Skript will convert * RegionUtils - add region utils * Repackage scheduler * Util - better Folia check * TaskUtils - repackage
1 parent 96edb2f commit 9435618

32 files changed

+728
-116
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ publishing {
117117
javadoc {
118118
destinationDir = file("${projectDir}/build/javadoc")
119119
options {
120-
links('https://hub.spigotmc.org/javadocs/spigot/')
120+
links('https://jd.papermc.io/paper/1.21.4/')
121121
links('https://docs.skriptlang.org/javadocs/')
122122
links('https://tr7zw.github.io/Item-NBT-API/v2-api/')
123123
links('https://jd.advntr.dev/api/4.14.0/')

src/main/java/com/shanebeestudios/skbee/AddonLoader.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,10 @@ private void loadScoreboardElements() {
215215
Util.logLoading("&7To use SkBee Scoreboards, please remove the addon which has registered Scoreboard already.");
216216
return;
217217
}
218+
if (Util.IS_RUNNING_FOLIA) {
219+
Util.logLoading("&5Scoreboard Elements &cdisabled &7(&eCurrently not supported on Folia&7)");
220+
return;
221+
}
218222
try {
219223
this.addon.loadClasses("com.shanebeestudios.skbee.elements.scoreboard");
220224
Util.logLoading("&5Scoreboard Elements &asuccessfully loaded");
@@ -332,6 +336,10 @@ private void loadWorldCreatorElements() {
332336
Util.logLoading("&5World Creator Elements &cdisabled via config");
333337
return;
334338
}
339+
if (Util.IS_RUNNING_FOLIA) {
340+
Util.logLoading("&5World Creator Elements &cdisabled &7(&eCurrently not supported on Folia&7)");
341+
return;
342+
}
335343
try {
336344
this.plugin.beeWorldConfig = new BeeWorldConfig(this.plugin);
337345
this.addon.loadClasses("com.shanebeestudios.skbee.elements.worldcreator");
@@ -350,6 +358,10 @@ private void loadChunkGenElements() {
350358
Util.logLoading("&5Chunk Generator &cdisabled via World Creator config");
351359
return;
352360
}
361+
if (Util.IS_RUNNING_FOLIA) {
362+
Util.logLoading("&5Chunk Generator Elements &cdisabled &7(&eCurrently not supported on Folia&7)");
363+
return;
364+
}
353365
try {
354366
this.addon.loadClasses("com.shanebeestudios.skbee.elements.generator");
355367
Util.logLoading("&5Chunk Generator Elements &asuccessfully loaded");

src/main/java/com/shanebeestudios/skbee/SkBee.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,18 @@
33
import ch.njol.skript.Skript;
44
import ch.njol.skript.test.runner.TestMode;
55
import com.shanebeestudios.skbee.api.bound.Bound;
6+
import com.shanebeestudios.skbee.api.bound.BoundConfig;
67
import com.shanebeestudios.skbee.api.command.SkBeeInfo;
8+
import com.shanebeestudios.skbee.api.region.TaskUtils;
79
import com.shanebeestudios.skbee.api.structure.StructureManager;
810
import com.shanebeestudios.skbee.api.util.UpdateChecker;
911
import com.shanebeestudios.skbee.api.util.Util;
1012
import com.shanebeestudios.skbee.api.wrapper.LazyLocation;
11-
import com.shanebeestudios.skbee.api.bound.BoundConfig;
1213
import com.shanebeestudios.skbee.config.Config;
13-
import com.shanebeestudios.skbee.elements.other.sections.SecRunTaskLater;
1414
import com.shanebeestudios.skbee.elements.worldcreator.objects.BeeWorldConfig;
1515
import com.shanebeestudios.vf.api.VirtualFurnaceAPI;
1616
import org.bstats.bukkit.Metrics;
1717
import org.bstats.charts.SimplePie;
18-
import org.bukkit.Bukkit;
1918
import org.bukkit.configuration.serialization.ConfigurationSerialization;
2019
import org.bukkit.plugin.java.JavaPlugin;
2120

@@ -57,6 +56,7 @@ public void onEnable() {
5756
long start = System.currentTimeMillis();
5857
instance = this;
5958
this.config = new Config(this);
59+
TaskUtils.initialize(this, Util.IS_RUNNING_FOLIA || this.config.settings_use_paper_schedulers);
6060
this.addonLoader = new AddonLoader(this);
6161
// Check if SkriptAddon can actually load
6262
this.properlyEnabled = addonLoader.canLoadPlugin();
@@ -101,7 +101,7 @@ private void loadMetrics() { //6719
101101
public void onDisable() {
102102
if (this.properlyEnabled) {
103103
// Cancel tasks on stop to prevent async issues
104-
Bukkit.getScheduler().cancelTasks(this);
104+
TaskUtils.cancelTasks();
105105
}
106106
if (this.virtualFurnaceAPI != null) {
107107
this.virtualFurnaceAPI.disableAPI();

src/main/java/com/shanebeestudios/skbee/api/bound/BoundConfig.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
import ch.njol.skript.Skript;
44
import ch.njol.skript.test.runner.TestMode;
55
import com.shanebeestudios.skbee.SkBee;
6-
import org.bukkit.Bukkit;
6+
import com.shanebeestudios.skbee.api.region.scheduler.Scheduler;
7+
import com.shanebeestudios.skbee.api.region.TaskUtils;
78
import org.bukkit.Location;
89
import org.bukkit.World;
910
import org.bukkit.configuration.ConfigurationSection;
1011
import org.bukkit.configuration.file.FileConfiguration;
1112
import org.bukkit.configuration.file.YamlConfiguration;
1213
import org.bukkit.event.Listener;
13-
import org.bukkit.scheduler.BukkitScheduler;
1414
import org.jetbrains.annotations.NotNull;
1515
import org.jetbrains.annotations.Nullable;
1616

@@ -63,13 +63,12 @@ public BoundConfig(SkBee plugin) {
6363
}
6464
this.boundPostponing.print();
6565
// Only start save timer if not in test mode
66-
if (!TestMode.ENABLED) startSaveTimer(plugin);
66+
if (!TestMode.ENABLED) startSaveTimer();
6767
}
6868

69-
private void startSaveTimer(SkBee plugin) {
70-
BukkitScheduler scheduler = Bukkit.getScheduler();
71-
72-
scheduler.runTaskTimer(plugin, () -> {
69+
private void startSaveTimer() {
70+
Scheduler<?> globalScheduler = TaskUtils.getGlobalScheduler();
71+
globalScheduler.runTaskTimer(() -> {
7372
// Skip saving if maps are empty
7473
if (this.scheduledToSave.isEmpty() && this.scheduledToRemove.isEmpty()) return;
7574

@@ -82,7 +81,7 @@ private void startSaveTimer(SkBee plugin) {
8281
this.scheduledToSave.clear();
8382

8483
// Async save yaml to file
85-
scheduler.runTaskAsynchronously(plugin, this::saveConfig);
84+
globalScheduler.runTaskAsync(this::saveConfig);
8685
}, 6000, 6000); // Every 5 minutes
8786
}
8887

src/main/java/com/shanebeestudios/skbee/api/fastboard/FastBoardBase.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.shanebeestudios.skbee.api.fastboard;
22

33
import com.shanebeestudios.skbee.SkBee;
4+
import com.shanebeestudios.skbee.api.util.Util;
45
import org.bukkit.Bukkit;
56
import org.bukkit.entity.Player;
67
import org.bukkit.scoreboard.Scoreboard;
@@ -10,7 +11,8 @@
1011
public abstract class FastBoardBase<T, B> {
1112

1213
protected static final boolean REVERSE = SkBee.getPlugin().getPluginConfig().SETTINGS_FASTBOARD_LINES;
13-
private static final Scoreboard DUMMY_BOARD = Bukkit.getScoreboardManager().getNewScoreboard();
14+
// Folia has currently removed vanilla scoreboards
15+
private static final Scoreboard DUMMY_BOARD = Util.IS_RUNNING_FOLIA ? null : Bukkit.getScoreboardManager().getNewScoreboard();
1416

1517
protected final Player player;
1618
protected fr.mrmicky.fastboard.FastBoardBase<B> fastBoard;
@@ -49,10 +51,12 @@ public void hide() {
4951
if (this.fastBoard == null) return;
5052
this.fastBoard.delete();
5153
this.fastBoard = null;
52-
// This force resends the vanilla scoreboard to the client
53-
Scoreboard previous = this.player.getScoreboard();
54-
this.player.setScoreboard(DUMMY_BOARD);
55-
this.player.setScoreboard(previous);
54+
if (DUMMY_BOARD != null) {
55+
// This force resends the vanilla scoreboard to the client
56+
Scoreboard previous = this.player.getScoreboard();
57+
this.player.setScoreboard(DUMMY_BOARD);
58+
this.player.setScoreboard(previous);
59+
}
5660
}
5761

5862
public abstract void show();

src/main/java/com/shanebeestudios/skbee/api/fastboard/FastBoardManager.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.shanebeestudios.skbee.api.fastboard;
22

33
import com.shanebeestudios.skbee.SkBee;
4+
import com.shanebeestudios.skbee.api.region.TaskUtils;
45
import org.bukkit.Bukkit;
56
import org.bukkit.entity.Player;
67
import org.bukkit.event.EventHandler;
@@ -17,7 +18,6 @@ public class FastBoardManager implements Listener {
1718
public static final boolean HAS_ADVENTURE = SkBee.getPlugin().getAddonLoader().isTextComponentEnabled();
1819

1920
private static final Map<UUID, FastBoardBase<?, ?>> BOARDS = new HashMap<>();
20-
private static final SkBee PLUGIN = SkBee.getPlugin();
2121

2222
@Nullable
2323
public static FastBoardBase<?, ?> getBoard(Player player) {
@@ -49,7 +49,7 @@ public FastBoardManager() {
4949
@EventHandler
5050
private void onQuit(PlayerQuitEvent event) {
5151
UUID uuid = event.getPlayer().getUniqueId();
52-
Bukkit.getScheduler().runTaskLater(PLUGIN, () -> removeBoard(uuid), 1);
52+
TaskUtils.getEntityScheduler(event.getPlayer()).runTaskLater(() -> removeBoard(uuid), 1);
5353
}
5454

5555
}

src/main/java/com/shanebeestudios/skbee/api/listener/BoundBorderListener.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.shanebeestudios.skbee.api.event.bound.BoundEnterEvent;
77
import com.shanebeestudios.skbee.api.event.bound.BoundExitEvent;
88
import com.shanebeestudios.skbee.api.bound.BoundConfig;
9+
import com.shanebeestudios.skbee.api.region.TaskUtils;
910
import com.shanebeestudios.skbee.config.Config;
1011
import org.bukkit.Bukkit;
1112
import org.bukkit.Location;
@@ -107,7 +108,7 @@ private void onEnterBed(PlayerBedEnterEvent event) {
107108
private void onExitBed(PlayerBedLeaveEvent event) {
108109
Player player = event.getPlayer();
109110
Location from = event.getBed().getLocation();
110-
Bukkit.getScheduler().runTaskLater(plugin, () -> {
111+
TaskUtils.getEntityScheduler(player).runTaskLater(() -> {
111112
// Find player's new location after leaving bed
112113
// have to add a delay as this isn't determinded in the event
113114
Location to = player.getLocation();
@@ -136,7 +137,7 @@ private void onMount(EntityMountEvent event) {
136137
private void onDismount(EntityDismountEvent event) {
137138
if (event.getEntity() instanceof Player player) {
138139
Location from = event.getDismounted().getLocation().clone();
139-
Bukkit.getScheduler().runTaskLater(plugin, () -> {
140+
TaskUtils.getEntityScheduler(player).runTaskLater(() -> {
140141
Location to = player.getLocation();
141142
if (preventBoundMovement(player, from, to)) {
142143
from.setYaw(player.getLocation().getYaw());
@@ -166,7 +167,7 @@ private void onVehicleEnter(VehicleEnterEvent event) {
166167
private void onVehicleExit(VehicleExitEvent event) {
167168
Location from = event.getVehicle().getLocation().clone();
168169
if (event.getExited() instanceof Player player) {
169-
Bukkit.getScheduler().runTaskLater(plugin, () -> {
170+
TaskUtils.getEntityScheduler(player).runTaskLater(() -> {
170171
Location to = player.getLocation();
171172
if (preventBoundMovement(player, from, to)) {
172173
from.setYaw(player.getLocation().getYaw());
@@ -201,9 +202,10 @@ private void onVehicleMove(VehicleMoveEvent event) {
201202
if (config.BOUND_EVENTS_VEHICLE_DESTROY) pluginManager.registerEvents(new Listener() {
202203
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
203204
private void onVehicleDestroy(VehicleDestroyEvent event) {
204-
Location from = event.getVehicle().getLocation().clone();
205-
Bukkit.getScheduler().runTaskLater(plugin, () -> {
206-
for (Entity passenger : event.getVehicle().getPassengers()) {
205+
Vehicle vehicle = event.getVehicle();
206+
Location from = vehicle.getLocation().clone();
207+
TaskUtils.getEntityScheduler(vehicle).runTaskLater(() -> {
208+
for (Entity passenger : vehicle.getPassengers()) {
207209
Location to = passenger.getLocation();
208210
if (passenger instanceof Player player) {
209211
if (preventBoundMovement(player, from, to)) {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.shanebeestudios.skbee.api.region;
2+
3+
import com.shanebeestudios.skbee.api.util.Util;
4+
import org.bukkit.Bukkit;
5+
import org.bukkit.Location;
6+
import org.bukkit.World;
7+
import org.bukkit.block.Block;
8+
import org.bukkit.entity.Entity;
9+
10+
/**
11+
* Utility methods for Folia's threaded regions
12+
*/
13+
public class RegionUtils {
14+
15+
/**
16+
* Check if an object is owned by the curent region
17+
* <p>Currently accepts Block/Location/Entity.
18+
* If not running Folia this will just return true</p>
19+
*
20+
* @param object Object to check
21+
* @return Whether object is running in the current region
22+
*/
23+
public static boolean isOwnedByCurrentRegion(Object object) {
24+
if (!Util.IS_RUNNING_FOLIA) return true;
25+
26+
if (object instanceof Block block) return Bukkit.isOwnedByCurrentRegion(block);
27+
else if (object instanceof Entity entity) return Bukkit.isOwnedByCurrentRegion(entity);
28+
else if (object instanceof Location location) return Bukkit.isOwnedByCurrentRegion(location);
29+
return true;
30+
}
31+
32+
/**
33+
* Check if a chunk location is owned by a current region
34+
* <p>If not running Folia this will just return true</p>
35+
*
36+
* @param world World of chunk
37+
* @param chunkX Chunk X of chunk
38+
* @param chunkZ Chunk Z of chunk
39+
* @return Whether chunk is running in the current region
40+
*/
41+
public static boolean isOwnedByCurrentRegion(World world, int chunkX, int chunkZ) {
42+
if (!Util.IS_RUNNING_FOLIA) return true;
43+
return Bukkit.isOwnedByCurrentRegion(world, chunkX, chunkZ);
44+
}
45+
46+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package com.shanebeestudios.skbee.api.region;
2+
3+
import com.shanebeestudios.skbee.api.region.scheduler.FoliaScheduler;
4+
import com.shanebeestudios.skbee.api.region.scheduler.Scheduler;
5+
import com.shanebeestudios.skbee.api.region.scheduler.SpigotScheduler;
6+
import org.bukkit.Bukkit;
7+
import org.bukkit.Location;
8+
import org.bukkit.entity.Entity;
9+
import org.bukkit.plugin.Plugin;
10+
import org.jetbrains.annotations.NotNull;
11+
12+
/**
13+
* Utility class for creating {@link Scheduler Schedulers}
14+
* <p>Intialize before use, {@link #initialize(Plugin, boolean)}</p>
15+
* <p>If initialized with `useFoliaSchedulers=true`, will return a {@link FoliaScheduler}
16+
* else will return a {@link SpigotScheduler}</p>
17+
*/
18+
public class TaskUtils {
19+
20+
private static Plugin plugin;
21+
private static boolean useFoliaSchedulers;
22+
23+
/**
24+
* Initialize schedulers
25+
*
26+
* @param plugin Plugin to reference for tasks
27+
* @param useFoliaSchedulers Whether to use Paper/Folia schedulers else Bukkit schedulers
28+
*/
29+
public static void initialize(@NotNull Plugin plugin, boolean useFoliaSchedulers) {
30+
if (TaskUtils.plugin != null) {
31+
throw new IllegalStateException("TaskUtils already initialized!");
32+
}
33+
TaskUtils.plugin = plugin;
34+
TaskUtils.useFoliaSchedulers = useFoliaSchedulers;
35+
}
36+
37+
/**
38+
* Get the plugin that these schedulers will use
39+
*
40+
* @return Plugin for schedulers
41+
*/
42+
public static Plugin getPlugin() {
43+
pluginCheck();
44+
return plugin;
45+
}
46+
47+
/**
48+
* Get a global scheduler
49+
* <p>This is used for global World/Server tasks which don't require regions</p>
50+
* <p>If running Spigot or Paper (with Paper schedulers disabled) this will use a normal Bukkit Scheduler</p>
51+
*
52+
* @return Global scheduler
53+
*/
54+
public static Scheduler<?> getGlobalScheduler() {
55+
pluginCheck();
56+
if (useFoliaSchedulers) return FoliaScheduler.getGlobalScheduler();
57+
return new SpigotScheduler();
58+
}
59+
60+
/**
61+
* Get a regional scheduler based on a location
62+
* <p>This is used for scheduling tasks at a specific location</p>
63+
* <p>If running Spigot or Paper (with Paper schedulers disabled) this will use a normal Bukkit Scheduler</p>
64+
*
65+
* @param location Location to grab region from
66+
* @return Region scheduler
67+
*/
68+
public static Scheduler<?> getRegionalScheduler(Location location) {
69+
pluginCheck();
70+
if (useFoliaSchedulers) return FoliaScheduler.getRegionalScheduler(location);
71+
return new SpigotScheduler();
72+
}
73+
74+
/**
75+
* Get an entity scheduler
76+
* <p>This is used for scheduling tasks linked to an entity
77+
* The tasks will move with the entity to whatever region they're in</p>
78+
* <p>If running Spigot or Paper (with Paper schedulers disabled) this will use a normal Bukkit Scheduler</p>
79+
*
80+
* @param entity Entity to attach scheduler to
81+
* @return Entity scheduler
82+
*/
83+
public static Scheduler<?> getEntityScheduler(Entity entity) {
84+
pluginCheck();
85+
if (useFoliaSchedulers) return FoliaScheduler.getEntityScheduler(entity);
86+
return new SpigotScheduler();
87+
}
88+
89+
/**
90+
* Cancel all currently running tasks
91+
*/
92+
public static void cancelTasks() {
93+
pluginCheck();
94+
if (useFoliaSchedulers) {
95+
Bukkit.getGlobalRegionScheduler().cancelTasks(plugin);
96+
Bukkit.getAsyncScheduler().cancelTasks(plugin);
97+
} else {
98+
Bukkit.getScheduler().cancelTasks(plugin);
99+
}
100+
}
101+
102+
private static void pluginCheck() {
103+
if (plugin == null) {
104+
throw new IllegalStateException("TaskUtils has not been initialized!");
105+
}
106+
}
107+
108+
}

0 commit comments

Comments
 (0)