ScriptsLab
WikiDownloadsSourcesSupport
ScriptsLab
DocumentationDownloadsGitHubDiscord

© 2026 ScriptsLab

Back to src/main/java/com/scriptslab/core/scheduler
J

TaskSchedulerImpl.java

Java · 196 lines · 5.8 KB

src/main/java/com/scriptslab/core/scheduler/TaskSchedulerImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
package com.scriptslab.core.scheduler;

import com.scriptslab.api.scheduler.ScheduledTask;
import com.scriptslab.api.scheduler.TaskScheduler;

import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;

import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;

/**
 * Implementation of TaskScheduler wrapping BukkitScheduler.
 * Thread-safe.
 */
public final class TaskSchedulerImpl implements TaskScheduler {
    
    private final Plugin plugin;
    private final BukkitScheduler scheduler;
    private final Map<Integer, ScheduledTaskImpl> tasks;
    private final AtomicInteger taskCounter;
    
    public TaskSchedulerImpl(Plugin plugin) {
        this.plugin = plugin;
        this.scheduler = Bukkit.getScheduler();
        this.tasks = new ConcurrentHashMap<>();
        this.taskCounter = new AtomicInteger(0);
    }
    
    @Override
    public ScheduledTask runTask(Runnable task) {
        BukkitTask bukkitTask = scheduler.runTask(plugin, task);
        return wrapTask(bukkitTask, task, true);
    }
    
    @Override
    public ScheduledTask runTaskAsync(Runnable task) {
        BukkitTask bukkitTask = scheduler.runTaskAsynchronously(plugin, task);
        return wrapTask(bukkitTask, task, false);
    }
    
    @Override
    public ScheduledTask runTaskLater(Runnable task, long delay, TimeUnit unit) {
        long ticks = toTicks(delay, unit);
        BukkitTask bukkitTask = scheduler.runTaskLater(plugin, task, ticks);
        return wrapTask(bukkitTask, task, true);
    }
    
    @Override
    public ScheduledTask runTaskLaterAsync(Runnable task, long delay, TimeUnit unit) {
        long ticks = toTicks(delay, unit);
        BukkitTask bukkitTask = scheduler.runTaskLaterAsynchronously(plugin, task, ticks);
        return wrapTask(bukkitTask, task, false);
    }
    
    @Override
    public ScheduledTask runTaskTimer(Runnable task, long delay, long period, TimeUnit unit) {
        long delayTicks = toTicks(delay, unit);
        long periodTicks = toTicks(period, unit);
        BukkitTask bukkitTask = scheduler.runTaskTimer(plugin, task, delayTicks, periodTicks);
        return wrapTask(bukkitTask, task, true);
    }
    
    @Override
    public ScheduledTask runTaskTimerAsync(Runnable task, long delay, long period, TimeUnit unit) {
        long delayTicks = toTicks(delay, unit);
        long periodTicks = toTicks(period, unit);
        BukkitTask bukkitTask = scheduler.runTaskTimerAsynchronously(plugin, task, delayTicks, periodTicks);
        return wrapTask(bukkitTask, task, false);
    }
    
    @Override
    public <T> CompletableFuture<T> supply(Supplier<T> task) {
        CompletableFuture<T> future = new CompletableFuture<>();
        runTask(() -> {
            try {
                future.complete(task.get());
            } catch (Exception e) {
                future.completeExceptionally(e);
            }
        });
        return future;
    }
    
    @Override
    public <T> CompletableFuture<T> supplyAsync(Supplier<T> task) {
        CompletableFuture<T> future = new CompletableFuture<>();
        runTaskAsync(() -> {
            try {
                future.complete(task.get());
            } catch (Exception e) {
                future.completeExceptionally(e);
            }
        });
        return future;
    }
    
    @Override
    public void cancelTasks(Object owner) {
        tasks.values().removeIf(task -> {
            if (task.getOwner() == owner) {
                task.cancel();
                return true;
            }
            return false;
        });
    }
    
    @Override
    public void cancelAllTasks() {
        tasks.values().forEach(ScheduledTask::cancel);
        tasks.clear();
    }
    
    @Override
    public int getActiveTaskCount() {
        return (int) tasks.values().stream()
                .filter(task -> !task.isCancelled())
                .count();
    }
    
    /**
     * Converts time to Minecraft ticks (20 ticks = 1 second).
     */
    private long toTicks(long time, TimeUnit unit) {
        long millis = unit.toMillis(time);
        return millis / 50; // 1 tick = 50ms
    }
    
    /**
     * Wraps a BukkitTask into our ScheduledTask.
     */
    private ScheduledTask wrapTask(BukkitTask bukkitTask, Runnable task, boolean sync) {
        int id = taskCounter.incrementAndGet();
        ScheduledTaskImpl scheduledTask = new ScheduledTaskImpl(
                id, bukkitTask, task, sync);
        tasks.put(id, scheduledTask);
        return scheduledTask;
    }
    
    /**
     * Internal task implementation.
     */
    private class ScheduledTaskImpl implements ScheduledTask {
        
        private final int taskId;
        private final BukkitTask bukkitTask;
        private final Object owner;
        private final boolean sync;
        
        ScheduledTaskImpl(int taskId, BukkitTask bukkitTask, Object owner, boolean sync) {
            this.taskId = taskId;
            this.bukkitTask = bukkitTask;
            this.owner = owner;
            this.sync = sync;
        }
        
        @Override
        public int getTaskId() {
            return taskId;
        }
        
        @Override
        public boolean isCancelled() {
            return bukkitTask.isCancelled();
        }
        
        @Override
        public void cancel() {
            bukkitTask.cancel();
            tasks.remove(taskId);
        }
        
        @Override
        public boolean isRunning() {
            return !isCancelled();
        }
        
        @Override
        public boolean isSync() {
            return sync;
        }
        
        @Override
        public Object getOwner() {
            return owner;
        }
    }
}