11package gg .nextforge .scheduler ;
22
33import lombok .Getter ;
4- import org .bukkit .Bukkit ;
5- import org .bukkit .plugin .Plugin ;
6- import org .bukkit .scheduler .BukkitTask ;
74
8- import java .util .Collection ;
95import java .util .Map ;
10- import java .util .concurrent .ConcurrentHashMap ;
6+ import java .util .concurrent .* ;
117import java .util .concurrent .atomic .AtomicInteger ;
128
139/**
14- * A wrapper around Bukkit's scheduler to simplify task management.
15- * <p>
16- * Features:
17- * - Static access for convenience (e.g., CoreScheduler.runLater())
18- * - Automatic task cleanup
19- * - Cancel tokens for better task control
20- * - Avoids manual tracking of task IDs
10+ * A standalone, thread-safe scheduler implementation.
11+ * No Bukkit dependencies, suitable for general Java use.
2112 */
2213public class CoreScheduler {
2314
24- private static CoreScheduler instance ; // Singleton instance of CoreScheduler
25- private final Plugin plugin ; // Plugin instance for scheduling tasks
15+ private static CoreScheduler instance ;
16+
2617 @ Getter
27- private static final Map <Integer , ScheduledTask > activeTasks = new ConcurrentHashMap <>(); // Active tasks map
28- private final AtomicInteger taskCounter = new AtomicInteger (0 ); // Counter for task IDs
29-
30- /**
31- * Constructs a CoreScheduler instance.
32- *
33- * @param plugin The plugin instance.
34- */
35- public CoreScheduler (Plugin plugin ) {
36- this .plugin = plugin ;
18+ private static final Map <Integer , ScheduledTask > activeTasks = new ConcurrentHashMap <>();
19+
20+ private final ScheduledExecutorService executorService ;
21+ private final AtomicInteger taskCounter = new AtomicInteger (0 );
22+
23+ public CoreScheduler () {
24+ this .executorService = Executors .newScheduledThreadPool (Runtime .getRuntime ().availableProcessors ());
3725 instance = this ;
3826 }
3927
40- /**
41- * Runs a task on the next tick.
42- *
43- * @param task The task to run.
44- * @return A ScheduledTask representing the scheduled task.
45- */
4628 public static ScheduledTask run (Runnable task ) {
47- return instance .runTask (task );
29+ return instance .schedule (task , 0 , false , false );
4830 }
4931
50- // Static convenience methods for scheduling tasks
51-
52- /**
53- * Runs a task after a specified delay.
54- *
55- * @param task The task to run.
56- * @param delay The delay in ticks (20 ticks = 1 second).
57- * @return A ScheduledTask representing the scheduled task.
58- */
59- public static ScheduledTask runLater (Runnable task , long delay ) {
60- return instance .runTaskLater (task , delay );
32+ public static ScheduledTask runLater (Runnable task , long delayTicks ) {
33+ return instance .schedule (task , delayTicks , false , false );
6134 }
6235
63- /**
64- * Runs a task repeatedly with a specified delay and interval.
65- *
66- * @param task The task to run.
67- * @param delay The initial delay in ticks.
68- * @param period The interval between executions in ticks.
69- * @return A ScheduledTask representing the scheduled task.
70- */
71- public static ScheduledTask runTimer (Runnable task , long delay , long period ) {
72- return instance .runTaskTimer (task , delay , period );
36+ public static ScheduledTask runTimer (Runnable task , long delayTicks , long periodTicks ) {
37+ return instance .scheduleRepeating (task , delayTicks , periodTicks , false );
7338 }
7439
75- /**
76- * Runs a task asynchronously.
77- *
78- * @param task The task to run.
79- * @return A ScheduledTask representing the scheduled task.
80- */
8140 public static ScheduledTask runAsync (Runnable task ) {
82- return instance .runTaskAsync (task );
41+ return instance .schedule (task , 0 , true , false );
8342 }
8443
85- /**
86- * Runs a task asynchronously after a specified delay.
87- *
88- * @param task The task to run.
89- * @param delay The delay in ticks.
90- * @return A ScheduledTask representing the scheduled task.
91- */
92- public static ScheduledTask runAsyncLater (Runnable task , long delay ) {
93- return instance .runTaskAsyncLater (task , delay );
44+ public static ScheduledTask runAsyncLater (Runnable task , long delayTicks ) {
45+ return instance .schedule (task , delayTicks , true , false );
9446 }
9547
96- /**
97- * Runs a task asynchronously and repeatedly.
98- *
99- * @param task The task to run.
100- * @param delay The initial delay in ticks.
101- * @param period The interval between executions in ticks.
102- * @return A ScheduledTask representing the scheduled task.
103- */
104- public static ScheduledTask runAsyncTimer (Runnable task , long delay , long period ) {
105- return instance .runTaskAsyncTimer (task , delay , period );
48+ public static ScheduledTask runAsyncTimer (Runnable task , long delayTicks , long periodTicks ) {
49+ return instance .scheduleRepeating (task , delayTicks , periodTicks , true );
10650 }
10751
108- /**
109- * Cleans up all active tasks.
110- * Should be called when the plugin is disabled.
111- */
11252 public void shutdown () {
11353 activeTasks .values ().forEach (ScheduledTask ::cancel );
11454 activeTasks .clear ();
55+ executorService .shutdownNow ();
11556 }
11657
117- // Instance methods for scheduling tasks
118-
119- private ScheduledTask runTask (Runnable task ) {
120- int id = taskCounter .incrementAndGet ();
121- ScheduledTask scheduled = new ScheduledTask (id );
122-
123- BukkitTask bukkitTask = Bukkit .getScheduler ().runTask (plugin , () -> {
124- try {
125- task .run ();
126- } finally {
127- activeTasks .remove (id );
128- }
129- });
130-
131- scheduled .setBukkitTask (bukkitTask );
132- activeTasks .put (id , scheduled );
133- return scheduled ;
134- }
135-
136- private ScheduledTask runTaskLater (Runnable task , long delay ) {
137- int id = taskCounter .incrementAndGet ();
138- ScheduledTask scheduled = new ScheduledTask (id );
139-
140- BukkitTask bukkitTask = Bukkit .getScheduler ().runTaskLater (plugin , () -> {
141- try {
142- task .run ();
143- } finally {
144- activeTasks .remove (id );
145- }
146- }, delay );
147-
148- scheduled .setBukkitTask (bukkitTask );
149- activeTasks .put (id , scheduled );
150- return scheduled ;
151- }
152-
153- private ScheduledTask runTaskTimer (Runnable task , long delay , long period ) {
154- int id = taskCounter .incrementAndGet ();
155- ScheduledTask scheduled = new ScheduledTask (id );
156-
157- BukkitTask bukkitTask = Bukkit .getScheduler ().runTaskTimer (plugin , task , delay , period );
158-
159- scheduled .setBukkitTask (bukkitTask );
160- activeTasks .put (id , scheduled );
161- return scheduled ;
162- }
163-
164- private ScheduledTask runTaskAsync (Runnable task ) {
165- int id = taskCounter .incrementAndGet ();
166- ScheduledTask scheduled = new ScheduledTask (id );
167-
168- BukkitTask bukkitTask = Bukkit .getScheduler ().runTaskAsynchronously (plugin , () -> {
169- try {
170- task .run ();
171- } finally {
172- activeTasks .remove (id );
173- }
174- });
175-
176- scheduled .setBukkitTask (bukkitTask );
177- activeTasks .put (id , scheduled );
178- return scheduled ;
179- }
180-
181- private ScheduledTask runTaskAsyncLater (Runnable task , long delay ) {
58+ private ScheduledTask schedule (Runnable task , long delayTicks , boolean async , boolean repeating ) {
18259 int id = taskCounter .incrementAndGet ();
183- ScheduledTask scheduled = new ScheduledTask (id );
60+ ScheduledTask scheduledTask = new ScheduledTask (id );
61+ long delayMillis = ticksToMillis (delayTicks );
18462
185- BukkitTask bukkitTask = Bukkit . getScheduler (). runTaskLaterAsynchronously ( plugin , () -> {
63+ ScheduledFuture <?> future = executorService . schedule ( () -> {
18664 try {
18765 task .run ();
18866 } finally {
189- activeTasks .remove (id );
67+ if (!repeating ) {
68+ activeTasks .remove (id );
69+ }
19070 }
191- }, delay );
71+ }, delayMillis , TimeUnit . MILLISECONDS );
19272
193- scheduled . setBukkitTask ( bukkitTask );
194- activeTasks .put (id , scheduled );
195- return scheduled ;
73+ scheduledTask . setFuture ( future );
74+ activeTasks .put (id , scheduledTask );
75+ return scheduledTask ;
19676 }
19777
198- private ScheduledTask runTaskAsyncTimer (Runnable task , long delay , long period ) {
78+ private ScheduledTask scheduleRepeating (Runnable task , long delayTicks , long periodTicks , boolean async ) {
19979 int id = taskCounter .incrementAndGet ();
200- ScheduledTask scheduled = new ScheduledTask (id );
80+ ScheduledTask scheduledTask = new ScheduledTask (id );
81+ long delayMillis = ticksToMillis (delayTicks );
82+ long periodMillis = ticksToMillis (periodTicks );
20183
202- BukkitTask bukkitTask = Bukkit .getScheduler ().runTaskTimerAsynchronously (
203- plugin , task , delay , period
204- );
84+ ScheduledFuture <?> future = executorService .scheduleAtFixedRate (task , delayMillis , periodMillis , TimeUnit .MILLISECONDS );
20585
206- scheduled . setBukkitTask ( bukkitTask );
207- activeTasks .put (id , scheduled );
208- return scheduled ;
86+ scheduledTask . setFuture ( future );
87+ activeTasks .put (id , scheduledTask );
88+ return scheduledTask ;
20989 }
21090
211- /**
212- * Runs a task on the main thread.
213- * Useful for accessing Bukkit API from asynchronous tasks.
214- *
215- * @param task The task to run.
216- */
217- public void runSync (Runnable task ) {
218- Bukkit .getScheduler ().runTask (plugin , task );
91+ private long ticksToMillis (long ticks ) {
92+ return ticks * 50L ; // 20 ticks = 1 second
21993 }
220- }
94+ }
0 commit comments