|
1 | | -From ab1fe38a111dfdfa4bcb01e9dfa7292c199daeed Mon Sep 17 00:00:00 2001 |
| 1 | +From a93aa52d858b0465fe9b71109dfe310f8b689d88 Mon Sep 17 00:00:00 2001 |
2 | 2 | From: Bierque Euphyllia <bierque.euphyllia@gmail.com> |
3 | | -Date: Mon, 9 Feb 2026 00:20:18 +0100 |
4 | | -Subject: [PATCH 03/14] Replace BukkitRunnable to FoliaRunnable |
| 3 | +Date: Sun, 26 Apr 2026 12:56:15 +0200 |
| 4 | +Subject: [PATCH 03/13] Replace BukkitRunnable to FoliaRunnable |
5 | 5 |
|
6 | 6 | --- |
7 | | - .../essentials/api/FoliaRunnable.java | 271 ++++++++++++++++++ |
8 | | - .../commands/Commandessentials.java | 5 +- |
9 | | - 2 files changed, 274 insertions(+), 2 deletions(-) |
10 | | - create mode 100644 Essentials/src/main/java/com/earth2me/essentials/api/FoliaRunnable.java |
| 7 | + .../earth2me/essentials/commands/essentials/NyanCommand.java | 5 +++-- |
| 8 | + 1 file changed, 3 insertions(+), 2 deletions(-) |
11 | 9 |
|
12 | | -diff --git a/Essentials/src/main/java/com/earth2me/essentials/api/FoliaRunnable.java b/Essentials/src/main/java/com/earth2me/essentials/api/FoliaRunnable.java |
13 | | -new file mode 100644 |
14 | | -index 000000000..cc2ec820e |
15 | | ---- /dev/null |
16 | | -+++ b/Essentials/src/main/java/com/earth2me/essentials/api/FoliaRunnable.java |
17 | | -@@ -0,0 +1,271 @@ |
18 | | -+package com.earth2me.essentials.api; |
19 | | -+ |
20 | | -+import io.papermc.paper.threadedregions.scheduler.AsyncScheduler; |
21 | | -+import io.papermc.paper.threadedregions.scheduler.EntityScheduler; |
22 | | -+import io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler; |
23 | | -+import io.papermc.paper.threadedregions.scheduler.RegionScheduler; |
24 | | -+import io.papermc.paper.threadedregions.scheduler.ScheduledTask; |
25 | | -+import org.bukkit.Location; |
26 | | -+import org.bukkit.World; |
27 | | -+import org.bukkit.plugin.Plugin; |
28 | | -+import org.jetbrains.annotations.NotNull; |
29 | | -+import org.jetbrains.annotations.Nullable; |
30 | | -+import java.util.concurrent.TimeUnit; |
31 | | -+ |
32 | | -+/** |
33 | | -+ * A runnable class with both Paper and Folia Support. |
34 | | -+ * |
35 | | -+ * @author Euphyllia |
36 | | -+ * @version 1.9 |
37 | | -+ * @since 1.0 |
38 | | -+ */ |
39 | | -+public abstract class FoliaRunnable implements Runnable { |
40 | | -+ |
41 | | -+ private ScheduledTask task; |
42 | | -+ private @Nullable AsyncScheduler asyncScheduler; |
43 | | -+ private @Nullable TimeUnit timeUnit; |
44 | | -+ private @Nullable EntityScheduler entityScheduler; |
45 | | -+ private @Nullable Runnable entityRetired; |
46 | | -+ private @Nullable GlobalRegionScheduler globalRegionScheduler; |
47 | | -+ private @Nullable RegionScheduler regionScheduler; |
48 | | -+ private World world; |
49 | | -+ private int chunkX; |
50 | | -+ private int chunkZ; |
51 | | -+ |
52 | | -+ /** |
53 | | -+ * A constructor to build an {@link AsyncScheduler} with a {@link TimeUnit}. |
54 | | -+ * |
55 | | -+ * @param scheduler the {@link AsyncScheduler} |
56 | | -+ * @param timeUnit the {@link TimeUnit} |
57 | | -+ * @since 1.0 |
58 | | -+ */ |
59 | | -+ public FoliaRunnable(@NotNull final AsyncScheduler scheduler, @Nullable final TimeUnit timeUnit) { |
60 | | -+ this.asyncScheduler = scheduler; |
61 | | -+ this.timeUnit = timeUnit; |
62 | | -+ } |
63 | | -+ |
64 | | -+ /** |
65 | | -+ * A constructor to build an entity scheduler. |
66 | | -+ * |
67 | | -+ * @param scheduler the {@link EntityScheduler} |
68 | | -+ * @param retired the {@link Runnable} |
69 | | -+ * @since 1.0 |
70 | | -+ */ |
71 | | -+ public FoliaRunnable(@NotNull final EntityScheduler scheduler, @Nullable final Runnable retired) { |
72 | | -+ this.entityScheduler = scheduler; |
73 | | -+ this.entityRetired = retired; |
74 | | -+ } |
75 | | -+ |
76 | | -+ /** |
77 | | -+ * A constructor for the {@link GlobalRegionScheduler}. |
78 | | -+ * |
79 | | -+ * @param scheduler the {@link GlobalRegionScheduler} |
80 | | -+ * @since 1.0 |
81 | | -+ */ |
82 | | -+ public FoliaRunnable(@NotNull final GlobalRegionScheduler scheduler) { |
83 | | -+ this.globalRegionScheduler = scheduler; |
84 | | -+ } |
85 | | -+ |
86 | | -+ /** |
87 | | -+ * A constructor that builds a {@link Runnable} for the {@link Location}'s region. |
88 | | -+ * |
89 | | -+ * @param scheduler the {@link RegionScheduler} for the {@link Location} |
90 | | -+ * @param location the {@link Location} |
91 | | -+ * @since 1.0 |
92 | | -+ */ |
93 | | -+ public FoliaRunnable(@NotNull final RegionScheduler scheduler, @NotNull final Location location) { |
94 | | -+ this(scheduler, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4); |
95 | | -+ } |
96 | | -+ |
97 | | -+ /** |
98 | | -+ * A constructor that builds a {@link Runnable} for the world region. |
99 | | -+ * |
100 | | -+ * @param scheduler the {@link RegionScheduler} for the world |
101 | | -+ * @param world the {@link World} |
102 | | -+ * @param chunkX the chunk's {@link Integer} |
103 | | -+ * @param chunkZ the chunk's {@link Integer} |
104 | | -+ * @since 1.0 |
105 | | -+ */ |
106 | | -+ public FoliaRunnable(@NotNull final RegionScheduler scheduler, @NotNull final World world, final int chunkX, final int chunkZ) { |
107 | | -+ this.regionScheduler = scheduler; |
108 | | -+ this.world = world; |
109 | | -+ this.chunkX = chunkX; |
110 | | -+ this.chunkZ = chunkZ; |
111 | | -+ } |
112 | | -+ |
113 | | -+ /** |
114 | | -+ * Checks if the task is cancelled or not. |
115 | | -+ * |
116 | | -+ * @return true or false |
117 | | -+ * @throws IllegalStateException throws this exception if unable to check |
118 | | -+ * @since 1.0 |
119 | | -+ */ |
120 | | -+ public final boolean isCancelled() throws IllegalStateException { |
121 | | -+ checkScheduled(); |
122 | | -+ |
123 | | -+ return this.task.isCancelled(); |
124 | | -+ } |
125 | | -+ |
126 | | -+ /** |
127 | | -+ * Cancels a task. |
128 | | -+ * |
129 | | -+ * @throws IllegalStateException throws this exception if unable to cancel |
130 | | -+ * @since 1.0 |
131 | | -+ */ |
132 | | -+ public void cancel() throws IllegalStateException { |
133 | | -+ this.task.cancel(); |
134 | | -+ } |
135 | | -+ |
136 | | -+ /** |
137 | | -+ * Runs a task immediately supporting Folia/Paper. |
138 | | -+ * |
139 | | -+ * @param plugin the {@link Plugin} |
140 | | -+ * @return true if the task was successfully executed. |
141 | | -+ * @throws IllegalArgumentException throws this exception if it fails |
142 | | -+ * @throws IllegalStateException throws this exception if it is unstable |
143 | | -+ * @since 1.5.6 |
144 | | -+ */ |
145 | | -+ public final boolean execute(@NotNull final Plugin plugin) throws IllegalArgumentException, IllegalStateException { |
146 | | -+ checkNotYetScheduled(); |
147 | | -+ |
148 | | -+ if (this.globalRegionScheduler != null) { |
149 | | -+ this.globalRegionScheduler.execute(plugin, this); |
150 | | -+ } else if (this.entityScheduler != null) { |
151 | | -+ return this.entityScheduler.execute(plugin, this, this.entityRetired, 1L); |
152 | | -+ } else if (this.regionScheduler != null) { |
153 | | -+ this.regionScheduler.execute(plugin, this.world, this.chunkX, this.chunkZ, this); |
154 | | -+ } else if (this.asyncScheduler != null) { |
155 | | -+ this.asyncScheduler.runNow(plugin, scheduledTask -> this.run()); |
156 | | -+ } else { |
157 | | -+ throw new UnsupportedOperationException("The task type is not supported."); |
158 | | -+ } |
159 | | -+ |
160 | | -+ return true; |
161 | | -+ } |
162 | | -+ |
163 | | -+ /** |
164 | | -+ * Runs a task on the next tick supporting Folia/Paper. |
165 | | -+ * |
166 | | -+ * @param plugin the {@link Plugin} |
167 | | -+ * @return a scheduled task |
168 | | -+ * @throws IllegalArgumentException throws this exception if it fails |
169 | | -+ * @throws IllegalStateException throws this exception if it is unstable |
170 | | -+ * @since 1.0 |
171 | | -+ */ |
172 | | -+ public @NotNull final ScheduledTask run(@NotNull final Plugin plugin) throws IllegalArgumentException, IllegalStateException { |
173 | | -+ checkNotYetScheduled(); |
174 | | -+ |
175 | | -+ if (this.globalRegionScheduler != null) { |
176 | | -+ return setupTask(this.globalRegionScheduler.run(plugin, scheduledTask -> this.run())); |
177 | | -+ } else if (this.entityScheduler != null) { |
178 | | -+ return setupTask(this.entityScheduler.run(plugin, scheduledTask -> this.run(), this.entityRetired)); |
179 | | -+ } else if (this.regionScheduler != null) { |
180 | | -+ return setupTask(this.regionScheduler.run(plugin, this.world, this.chunkX, this.chunkZ, scheduledTask -> this.run())); |
181 | | -+ } else if (this.asyncScheduler != null) { |
182 | | -+ return setupTask(this.asyncScheduler.runDelayed(plugin, scheduledTask -> this.run(), 50, TimeUnit.MILLISECONDS)); |
183 | | -+ } else { |
184 | | -+ throw new UnsupportedOperationException("The task type is not supported."); |
185 | | -+ } |
186 | | -+ } |
187 | | -+ |
188 | | -+ /** |
189 | | -+ * Schedules this to run after the specified number of server ticks. |
190 | | -+ * |
191 | | -+ * @param plugin the reference to the {@link Plugin} scheduling task |
192 | | -+ * @param delay the ticks to wait before running the task |
193 | | -+ * @return a ScheduledTask that contains the id number |
194 | | -+ * @throws IllegalArgumentException if plugin is null |
195 | | -+ * @throws IllegalStateException if this was already scheduled |
196 | | -+ * @since 1.0 |
197 | | -+ */ |
198 | | -+ public @NotNull final ScheduledTask runDelayed(@NotNull final Plugin plugin, long delay) throws IllegalArgumentException, IllegalStateException { |
199 | | -+ checkNotYetScheduled(); |
200 | | -+ |
201 | | -+ delay = Math.max(1, delay); |
202 | | -+ |
203 | | -+ if (this.globalRegionScheduler != null) { |
204 | | -+ return setupTask(this.globalRegionScheduler.runDelayed(plugin, scheduledTask -> this.run(), delay)); |
205 | | -+ } else if (this.entityScheduler != null) { |
206 | | -+ return setupTask(this.entityScheduler.runDelayed(plugin, scheduledTask -> this.run(), this.entityRetired, delay)); |
207 | | -+ } else if (this.regionScheduler != null) { |
208 | | -+ return setupTask(this.regionScheduler.runDelayed(plugin, this.world, this.chunkX, this.chunkZ, scheduledTask -> this.run(), delay)); |
209 | | -+ } else if (this.asyncScheduler != null && this.timeUnit != null) { |
210 | | -+ return setupTask(this.asyncScheduler.runDelayed(plugin, scheduledTask -> this.run(), delay, this.timeUnit)); |
211 | | -+ } else { |
212 | | -+ throw new UnsupportedOperationException("The task type is not supported."); |
213 | | -+ } |
214 | | -+ } |
215 | | -+ |
216 | | -+ /** |
217 | | -+ * Schedules this to repeatedly run until cancelled, starting after the |
218 | | -+ * specified number of server ticks. |
219 | | -+ * |
220 | | -+ * @param plugin the reference to the {@link Plugin} scheduling task |
221 | | -+ * @param delay the ticks to wait before running the task |
222 | | -+ * @param period the ticks to wait between runs |
223 | | -+ * @return a ScheduledTask that contains the id number |
224 | | -+ * @throws IllegalArgumentException if plugin is null |
225 | | -+ * @throws IllegalStateException if this was already scheduled |
226 | | -+ * @since 1.0 |
227 | | -+ */ |
228 | | -+ public @NotNull final ScheduledTask runAtFixedRate(@NotNull final Plugin plugin, long delay, long period) throws IllegalArgumentException, IllegalStateException { |
229 | | -+ checkNotYetScheduled(); |
230 | | -+ |
231 | | -+ delay = Math.max(1, delay); |
232 | | -+ period = Math.max(1, period); |
233 | | -+ |
234 | | -+ if (this.globalRegionScheduler != null) { |
235 | | -+ return setupTask(this.globalRegionScheduler.runAtFixedRate(plugin, scheduledTask -> this.run(), delay, period)); |
236 | | -+ } else if (this.entityScheduler != null) { |
237 | | -+ return setupTask(this.entityScheduler.runAtFixedRate(plugin, scheduledTask -> this.run(), this.entityRetired, delay, period)); |
238 | | -+ } else if (this.regionScheduler != null) { |
239 | | -+ return setupTask(this.regionScheduler.runAtFixedRate(plugin, this.world, this.chunkX, this.chunkZ, scheduledTask -> this.run(), delay, period)); |
240 | | -+ } else if (this.asyncScheduler != null && this.timeUnit != null) { |
241 | | -+ return setupTask(this.asyncScheduler.runAtFixedRate(plugin, scheduledTask -> this.run(), delay, period, this.timeUnit)); |
242 | | -+ } else { |
243 | | -+ throw new UnsupportedOperationException("The task type is not supported."); |
244 | | -+ } |
245 | | -+ } |
246 | | -+ |
247 | | -+ /** |
248 | | -+ * Gets the task id for this runnable. |
249 | | -+ * |
250 | | -+ * @return the task id that this runnable was scheduled as |
251 | | -+ * @throws IllegalStateException if task was not scheduled yet |
252 | | -+ * @since 1.0 |
253 | | -+ */ |
254 | | -+ public final int getTaskId() throws IllegalStateException { |
255 | | -+ checkScheduled(); |
256 | | -+ |
257 | | -+ return this.task.hashCode(); |
258 | | -+ } |
259 | | -+ |
260 | | -+ /** |
261 | | -+ * Checks scheduled and throws a state exception if null i.e. not scheduled. |
262 | | -+ * |
263 | | -+ * @since 1.0 |
264 | | -+ */ |
265 | | -+ private void checkScheduled() { |
266 | | -+ if (this.task == null) throw new IllegalStateException("Not scheduled yet"); |
267 | | -+ } |
268 | | -+ |
269 | | -+ /** |
270 | | -+ * Checks if scheduled and throws an illegal state exception if not null i.e. already scheduled. |
271 | | -+ * |
272 | | -+ * @since 1.0 |
273 | | -+ */ |
274 | | -+ private void checkNotYetScheduled() { |
275 | | -+ if (this.task != null) throw new IllegalStateException("Already scheduled as " + task.hashCode()); |
276 | | -+ } |
277 | | -+ |
278 | | -+ /** |
279 | | -+ * Sets up the {@link ScheduledTask}. |
280 | | -+ * |
281 | | -+ * @param task the {@link ScheduledTask} to schedule |
282 | | -+ * @return the {@link ScheduledTask} |
283 | | -+ * @since 1.0 |
284 | | -+ */ |
285 | | -+ private @NotNull ScheduledTask setupTask(@NotNull final ScheduledTask task) { |
286 | | -+ return this.task = task; |
287 | | -+ } |
288 | | -+} |
289 | | -\ No newline at end of file |
290 | | -diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandessentials.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandessentials.java |
291 | | -index 1eeb6d20b..1efae5e9c 100644 |
292 | | ---- a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandessentials.java |
293 | | -+++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandessentials.java |
294 | | -@@ -509,7 +509,7 @@ public class Commandessentials extends EssentialsCommand { |
| 10 | +diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/essentials/NyanCommand.java b/Essentials/src/main/java/com/earth2me/essentials/commands/essentials/NyanCommand.java |
| 11 | +index 9e42fc503..172b6c331 100644 |
| 12 | +--- a/Essentials/src/main/java/com/earth2me/essentials/commands/essentials/NyanCommand.java |
| 13 | ++++ b/Essentials/src/main/java/com/earth2me/essentials/commands/essentials/NyanCommand.java |
| 14 | +@@ -29,10 +29,10 @@ public class NyanCommand extends EssentialsTreeNode { |
295 | 15 | } |
296 | 16 |
|
297 | 17 | currentTune = new TuneRunnable(NYAN_TUNE, NOTE_HARP, ess::getOnlinePlayers); |
298 | 18 | - currentTune.runTaskTimer(ess, 20, 2); |
299 | 19 | + currentTune.runAtFixedRate(ess, 20, 2); // Euphyllia |
300 | 20 | } |
301 | 21 |
|
302 | | - // Cow farts. |
303 | | -@@ -904,7 +904,7 @@ public class Commandessentials extends EssentialsCommand { |
304 | | - return Collections.emptyList(); |
305 | | - } |
306 | | - |
307 | 22 | - private static class TuneRunnable extends BukkitRunnable { |
308 | | -+ private static class TuneRunnable extends com.earth2me.essentials.api.FoliaRunnable { // Euphyllia |
| 23 | ++ private static class TuneRunnable extends com.earth2me.essentials.api.FoliaRunnable { // Euphyllia |
309 | 24 | private static final Map<String, Float> noteMap = ImmutableMap.<String, Float>builder() |
310 | | - .put("1F#", 0.5f) |
311 | | - .put("1G", 0.53f) |
312 | | -@@ -938,6 +938,7 @@ public class Commandessentials extends EssentialsCommand { |
| 25 | + .put("1F#", 0.5f) |
| 26 | + .put("1G", 0.53f) |
| 27 | +@@ -66,6 +66,7 @@ public class NyanCommand extends EssentialsTreeNode { |
313 | 28 | private int i = 0; |
314 | 29 |
|
315 | 30 | TuneRunnable(final String tuneStr, final Sound sound, final Supplier<Collection<Player>> players) { |
|
0 commit comments