├── .github
└── workflows
│ └── maven.yml
├── .gitignore
├── LICENSE.md
├── README.md
├── pom.xml
└── src
└── main
└── java
└── com
└── github
└── Anon8281
└── universalScheduler
├── UniversalRunnable.java
├── UniversalScheduler.java
├── bukkitScheduler
├── BukkitScheduledTask.java
└── BukkitScheduler.java
├── foliaScheduler
├── FoliaScheduledTask.java
└── FoliaScheduler.java
├── paperScheduler
└── PaperScheduler.java
├── scheduling
├── schedulers
│ └── TaskScheduler.java
└── tasks
│ └── MyScheduledTask.java
└── utils
└── JavaUtil.java
/.github/workflows/maven.yml:
--------------------------------------------------------------------------------
1 | name: Maven Compile
2 | on: [ push, pull_request ]
3 | jobs:
4 | build:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - uses: actions/checkout@v2
8 | - name: Set up OpenJDK 8
9 | uses: actions/setup-java@v2
10 | with:
11 | distribution: 'adopt'
12 | java-version: '17'
13 | - name: Compile with Maven
14 | env:
15 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
16 | run: mvn -B package --file pom.xml
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # User-specific stuff
2 | .idea/
3 |
4 | *.iml
5 | *.ipr
6 | *.iws
7 |
8 | # IntelliJ
9 | out/
10 |
11 | # Compiled class file
12 | *.class
13 |
14 | # Log file
15 | *.log
16 |
17 | # BlueJ files
18 | *.ctxt
19 |
20 | # Package Files #
21 | *.jar
22 | *.war
23 | *.nar
24 | *.ear
25 | *.zip
26 | *.tar.gz
27 | *.rar
28 |
29 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
30 | hs_err_pid*
31 |
32 | *~
33 |
34 | # temporary files which can be created if a process still has a handle open of a deleted file
35 | .fuse_hidden*
36 |
37 | # KDE directory preferences
38 | .directory
39 |
40 | # Linux trash folder which might appear on any partition or disk
41 | .Trash-*
42 |
43 | # .nfs files are created when an open file is removed but is still being accessed
44 | .nfs*
45 |
46 | # General
47 | .DS_Store
48 | .AppleDouble
49 | .LSOverride
50 |
51 | # Icon must end with two \r
52 | Icon
53 |
54 | # Thumbnails
55 | ._*
56 |
57 | # Files that might appear in the root of a volume
58 | .DocumentRevisions-V100
59 | .fseventsd
60 | .Spotlight-V100
61 | .TemporaryItems
62 | .Trashes
63 | .VolumeIcon.icns
64 | .com.apple.timemachine.donotpresent
65 |
66 | # Directories potentially created on remote AFP share
67 | .AppleDB
68 | .AppleDesktop
69 | Network Trash Folder
70 | Temporary Items
71 | .apdisk
72 |
73 | # Windows thumbnail cache files
74 | Thumbs.db
75 | Thumbs.db:encryptable
76 | ehthumbs.db
77 | ehthumbs_vista.db
78 |
79 | # Dump file
80 | *.stackdump
81 |
82 | # Folder config file
83 | [Dd]esktop.ini
84 |
85 | # Recycle Bin used on file shares
86 | $RECYCLE.BIN/
87 |
88 | # Windows Installer files
89 | *.cab
90 | *.msi
91 | *.msix
92 | *.msm
93 | *.msp
94 |
95 | # Windows shortcuts
96 | *.lnk
97 |
98 | target/
99 |
100 | pom.xml.tag
101 | pom.xml.releaseBackup
102 | pom.xml.versionsBackup
103 | pom.xml.next
104 |
105 | release.properties
106 | dependency-reduced-pom.xml
107 | buildNumber.properties
108 | .mvn/timing.properties
109 | .mvn/wrapper/maven-wrapper.jar
110 | .flattened-pom.xml
111 |
112 | # Common working directory
113 | run/
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Sevastjan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Universal Scheduler [](https://jitpack.io/#Anon8281/UniversalScheduler)
2 |
3 | Is a lib for java minecraft plugins to simplify Folia support implementation
4 | > Just for your information: Folia doesn't support any of `Bukkit.getScheduler().*` and `Bukkit.getServer().getScheduler().*`
5 | > scheduling methods
6 |
7 | ### Java version: 8 or above
8 |
9 | ### Supported:
10 |
11 | - Folia
12 | - Paper
13 | - Spigot
14 |
15 | ## Plugins using UniversalScheduler
16 |
17 | | **Name** | **Link** |
18 | |:----------------------------:|:-------------------------------------------------------------:|
19 | | Brewery (Fork) | [GitHub](https://github.com/Anon8281/Brewery) |
20 | | InventoryRollbackPlus (Fork) | [GitHub](https://github.com/Anon8281/Inventory-Rollback-Plus) |
21 | | CraftBook (Fork) | [GitHub](https://github.com/Anon8281/CraftBook) |
22 | | PlaceholderAPI (Fork) | [GitHub](https://github.com/Anon8281/PlaceholderAPI) |
23 | | ImageOnMap (Fork) | [GitHub](https://github.com/Anon8281/ImageOnMap) |
24 | | BigDoors (Fork) | [GitHub](https://github.com/Anon8281/BigDoors) |
25 | | WorldGuardExtraFlags (Fork) | [GitHub](https://github.com/Anon8281/WorldGuardExtraFlags) |
26 | | HorseTpWithMe (Fork) | [GitHub](https://github.com/Anon8281/HorseTpWithMe) |
27 | | BetterTridents (Fork) | [GitHub](https://github.com/Anon8281/BetterTridents) |
28 | | HolographicDisplays (Fork) | [GitHub](https://github.com/Anon8281/HolographicDisplays) |
29 | | Lucko helper (Fork) | [GitHub](https://github.com/Anon8281/helper) |
30 | | HexNicks | [GitHub](https://github.com/MajekDev/HexNicks) |
31 | | WorldEdit (Unstable Fork) | [GitHub](https://github.com/Anon8281/WorldEdit) |
32 | | SuperVanish (Fork) | [GitHub](https://github.com/ewof/SuperVanish/tree/folia) |
33 | | TownyWaypoints (Fork) | [GitHub](https://github.com/ewof/TownyWaypoints) |
34 |
35 | ## How to use scheduler?
36 |
37 | 1. To your plugin Main add:
38 |
39 | ```java
40 | private static TaskScheduler scheduler;
41 | ```
42 |
43 | ```java
44 | @Override
45 | public void onEnable() {
46 | //if your already have onEnable() just add next line to it
47 | scheduler = UniversalScheduler.getScheduler(this);
48 | }
49 | ```
50 |
51 | ```java
52 | public static TaskScheduler getScheduler() {
53 | return scheduler;
54 | }
55 | ```
56 |
57 | 2. Call it just like
58 |
59 | ```java
60 | Main.getScheduler().runTaskLater(() -> { //Main there is your plugin Main
61 | Bukkit.broadcastMessage("Wow, it was scheduled");
62 | });
63 | ```
64 |
65 | 3. If you need to get the scheduled task for some reason
66 |
67 | ```java
68 | MyScheduledTask task = Main.getScheduler().runTaskLater(() -> { //Main there is your plugin Main
69 | Bukkit.broadcastMessage("Wow, it was scheduled");
70 | }, 10L);
71 | ```
72 |
73 | ### Maven information
74 |
75 | ```xml
76 |
46 | * Schedules this in the Bukkit scheduler to run asynchronously. 47 | * 48 | * @param plugin the reference to the plugin scheduling task 49 | * @return {@link MyScheduledTask} 50 | * @throws IllegalArgumentException if plugin is null 51 | * @throws IllegalStateException if this was already scheduled 52 | * @see TaskScheduler#runTaskAsynchronously(Runnable) 53 | */ 54 | 55 | public synchronized MyScheduledTask runTaskAsynchronously(Plugin plugin) throws IllegalArgumentException, IllegalStateException { 56 | checkNotYetScheduled(); 57 | return setupTask(UniversalScheduler.getScheduler(plugin).runTaskAsynchronously(this)); 58 | } 59 | 60 | /** 61 | * Schedules this to run after the specified number of server ticks. 62 | * 63 | * @param plugin the reference to the plugin scheduling task 64 | * @param delay the ticks to wait before running the task 65 | * @return {@link MyScheduledTask} 66 | * @throws IllegalArgumentException if plugin is null 67 | * @throws IllegalStateException if this was already scheduled 68 | * @see TaskScheduler#runTaskLater(Runnable, long) 69 | */ 70 | 71 | public synchronized MyScheduledTask runTaskLater(Plugin plugin, long delay) throws IllegalArgumentException, IllegalStateException { 72 | checkNotYetScheduled(); 73 | return setupTask(UniversalScheduler.getScheduler(plugin).runTaskLater(this, delay)); 74 | } 75 | 76 | /** 77 | * Asynchronous tasks should never access any API in Bukkit. Great care 78 | * should be taken to assure the thread-safety of asynchronous tasks. 79 | *
80 | * Schedules this to run asynchronously after the specified number of 81 | * server ticks. 82 | * 83 | * @param plugin the reference to the plugin scheduling task 84 | * @param delay the ticks to wait before running the task 85 | * @return {@link MyScheduledTask} 86 | * @throws IllegalArgumentException if plugin is null 87 | * @throws IllegalStateException if this was already scheduled 88 | * @see TaskScheduler#runTaskLaterAsynchronously(Runnable, long) 89 | */ 90 | 91 | public synchronized MyScheduledTask runTaskLaterAsynchronously(Plugin plugin, long delay) throws IllegalArgumentException, IllegalStateException { 92 | checkNotYetScheduled(); 93 | return setupTask(UniversalScheduler.getScheduler(plugin).runTaskLaterAsynchronously(this, delay)); 94 | } 95 | 96 | /** 97 | * Schedules this to repeatedly run until cancelled, starting after the 98 | * specified number of server ticks. 99 | * 100 | * @param plugin the reference to the plugin scheduling task 101 | * @param delay the ticks to wait before running the task 102 | * @param period the ticks to wait between runs 103 | * @return {@link MyScheduledTask} 104 | * @throws IllegalArgumentException if plugin is null 105 | * @throws IllegalStateException if this was already scheduled 106 | * @see TaskScheduler#runTaskTimer(Runnable, long, long) 107 | */ 108 | 109 | public synchronized MyScheduledTask runTaskTimer(Plugin plugin, long delay, long period) throws IllegalArgumentException, IllegalStateException { 110 | checkNotYetScheduled(); 111 | return setupTask(UniversalScheduler.getScheduler(plugin).runTaskTimer(this, delay, period)); 112 | } 113 | 114 | /** 115 | * Asynchronous tasks should never access any API in Bukkit. Great care 116 | * should be taken to assure the thread-safety of asynchronous tasks. 117 | *
118 | * Schedules this to repeatedly run asynchronously until cancelled,
119 | * starting after the specified number of server ticks.
120 | *
121 | * @param plugin the reference to the plugin scheduling task
122 | * @param delay the ticks to wait before running the task for the first
123 | * time
124 | * @param period the ticks to wait between runs
125 | * @return {@link MyScheduledTask}
126 | * @throws IllegalArgumentException if plugin is null
127 | * @throws IllegalStateException if this was already scheduled
128 | * @see TaskScheduler#runTaskTimerAsynchronously(Runnable, long, long)
129 | */
130 |
131 | public synchronized MyScheduledTask runTaskTimerAsynchronously(Plugin plugin, long delay, long period) throws IllegalArgumentException, IllegalStateException {
132 | checkNotYetScheduled();
133 | return setupTask(UniversalScheduler.getScheduler(plugin).runTaskTimerAsynchronously(this, delay, period));
134 | }
135 |
136 | private void checkScheduled() {
137 | if (task == null) {
138 | throw new IllegalStateException("Not scheduled yet");
139 | }
140 | }
141 |
142 | private void checkNotYetScheduled() {
143 | if (task != null) {
144 | throw new IllegalStateException("Already scheduled");
145 | }
146 | }
147 |
148 |
149 | private MyScheduledTask setupTask(final MyScheduledTask task) {
150 | this.task = task;
151 | return task;
152 | }
153 |
154 |
155 | }
156 |
--------------------------------------------------------------------------------
/src/main/java/com/github/Anon8281/universalScheduler/UniversalScheduler.java:
--------------------------------------------------------------------------------
1 | package com.github.Anon8281.universalScheduler;
2 |
3 | import com.github.Anon8281.universalScheduler.bukkitScheduler.BukkitScheduler;
4 | import com.github.Anon8281.universalScheduler.foliaScheduler.FoliaScheduler;
5 | import com.github.Anon8281.universalScheduler.paperScheduler.PaperScheduler;
6 | import com.github.Anon8281.universalScheduler.scheduling.schedulers.TaskScheduler;
7 | import com.github.Anon8281.universalScheduler.utils.JavaUtil;
8 | import org.bukkit.plugin.Plugin;
9 |
10 | public class UniversalScheduler {
11 | public static final boolean isFolia = JavaUtil.classExists("io.papermc.paper.threadedregions.RegionizedServer");
12 | public static final boolean isExpandedSchedulingAvailable = JavaUtil.classExists("io.papermc.paper.threadedregions.scheduler.ScheduledTask");
13 |
14 | public static TaskScheduler getScheduler(Plugin plugin) {
15 | return isFolia ? new FoliaScheduler(plugin) : (isExpandedSchedulingAvailable ? new PaperScheduler(plugin) : new BukkitScheduler(plugin));
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/github/Anon8281/universalScheduler/bukkitScheduler/BukkitScheduledTask.java:
--------------------------------------------------------------------------------
1 | package com.github.Anon8281.universalScheduler.bukkitScheduler;
2 |
3 | import com.github.Anon8281.universalScheduler.scheduling.tasks.MyScheduledTask;
4 | import org.bukkit.Bukkit;
5 | import org.bukkit.plugin.Plugin;
6 | import org.bukkit.scheduler.BukkitTask;
7 |
8 | public class BukkitScheduledTask implements MyScheduledTask {
9 |
10 | BukkitTask task;
11 |
12 | boolean isRepeating;
13 |
14 | public BukkitScheduledTask(final BukkitTask task) {
15 | this.task = task;
16 | this.isRepeating = false;
17 | }
18 |
19 | public BukkitScheduledTask(final BukkitTask task, boolean isRepeating) {
20 | this.task = task;
21 | this.isRepeating = isRepeating;
22 | }
23 |
24 | @Override
25 | public void cancel() {
26 | task.cancel();
27 | }
28 |
29 | @Override
30 | public boolean isCancelled() {
31 | return task.isCancelled();
32 | }
33 |
34 | @Override
35 | public Plugin getOwningPlugin() {
36 | return task.getOwner();
37 | }
38 |
39 | @Override
40 | public boolean isCurrentlyRunning() {
41 | return Bukkit.getServer().getScheduler().isCurrentlyRunning(this.task.getTaskId()); //There's no other way. Fuck bukkit
42 | }
43 |
44 | @Override
45 | public boolean isRepeatingTask() {
46 | return isRepeating;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/com/github/Anon8281/universalScheduler/bukkitScheduler/BukkitScheduler.java:
--------------------------------------------------------------------------------
1 | package com.github.Anon8281.universalScheduler.bukkitScheduler;
2 |
3 | import com.github.Anon8281.universalScheduler.scheduling.schedulers.TaskScheduler;
4 | import com.github.Anon8281.universalScheduler.scheduling.tasks.MyScheduledTask;
5 | import org.bukkit.Bukkit;
6 | import org.bukkit.Location;
7 | import org.bukkit.entity.Entity;
8 | import org.bukkit.plugin.Plugin;
9 |
10 | public class BukkitScheduler implements TaskScheduler {
11 | final Plugin plugin;
12 |
13 | public BukkitScheduler(Plugin plugin) {
14 | this.plugin = plugin;
15 | }
16 |
17 | @Override
18 | public boolean isGlobalThread() {
19 | return Bukkit.getServer().isPrimaryThread();
20 | }
21 |
22 | @Override
23 | public boolean isEntityThread(Entity entity) {
24 | return Bukkit.getServer().isPrimaryThread();
25 | }
26 |
27 | @Override
28 | public boolean isRegionThread(Location location) {
29 | return Bukkit.getServer().isPrimaryThread();
30 | }
31 |
32 | @Override
33 | public MyScheduledTask runTask(Runnable runnable) {
34 | return new BukkitScheduledTask(Bukkit.getScheduler().runTask(plugin, runnable));
35 | }
36 |
37 | @Override
38 | public MyScheduledTask runTaskLater(Runnable runnable, long delay) {
39 | return new BukkitScheduledTask(Bukkit.getScheduler().runTaskLater(plugin, runnable, delay));
40 | }
41 |
42 | @Override
43 | public MyScheduledTask runTaskTimer(Runnable runnable, long delay, long period) {
44 | return new BukkitScheduledTask(Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, period));
45 | }
46 |
47 | @Override
48 | public MyScheduledTask runTaskAsynchronously(Runnable runnable) {
49 | return new BukkitScheduledTask(Bukkit.getScheduler().runTaskAsynchronously(plugin, runnable));
50 | }
51 |
52 | @Override
53 | public MyScheduledTask runTaskLaterAsynchronously(Runnable runnable, long delay) {
54 | return new BukkitScheduledTask(Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, runnable, delay));
55 | }
56 |
57 | @Override
58 | public MyScheduledTask runTaskTimerAsynchronously(Runnable runnable, long delay, long period) {
59 | return new BukkitScheduledTask(Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, delay, period));
60 | }
61 |
62 | //Useless? Or...
63 | public MyScheduledTask runTask(Plugin plugin, Runnable runnable) {
64 | return new BukkitScheduledTask(Bukkit.getScheduler().runTask(plugin, runnable));
65 | }
66 |
67 | @Override
68 | public MyScheduledTask runTaskLater(Plugin plugin, Runnable runnable, long delay) {
69 | return new BukkitScheduledTask(Bukkit.getScheduler().runTaskLater(plugin, runnable, delay));
70 | }
71 |
72 | @Override
73 | public MyScheduledTask runTaskTimer(Plugin plugin, Runnable runnable, long delay, long period) {
74 | return new BukkitScheduledTask(Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, period));
75 | }
76 |
77 | @Override
78 | public MyScheduledTask runTaskAsynchronously(Plugin plugin, Runnable runnable) {
79 | return new BukkitScheduledTask(Bukkit.getScheduler().runTaskAsynchronously(plugin, runnable));
80 | }
81 |
82 | @Override
83 | public MyScheduledTask runTaskLaterAsynchronously(Plugin plugin, Runnable runnable, long delay) {
84 | return new BukkitScheduledTask(Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, runnable, delay));
85 | }
86 |
87 | @Override
88 | public MyScheduledTask runTaskTimerAsynchronously(Plugin plugin, Runnable runnable, long delay, long period) {
89 | return new BukkitScheduledTask(Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, delay, period));
90 | }
91 |
92 | @Override
93 | public void execute(Runnable runnable) {
94 | Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, runnable);
95 | }
96 |
97 | @Override
98 | public void cancelTasks() {
99 | Bukkit.getScheduler().cancelTasks(plugin);
100 | }
101 |
102 | @Override
103 | public void cancelTasks(Plugin plugin) {
104 | Bukkit.getScheduler().cancelTasks(plugin);
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/main/java/com/github/Anon8281/universalScheduler/foliaScheduler/FoliaScheduledTask.java:
--------------------------------------------------------------------------------
1 | package com.github.Anon8281.universalScheduler.foliaScheduler;
2 |
3 | import com.github.Anon8281.universalScheduler.scheduling.tasks.MyScheduledTask;
4 | import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
5 | import org.bukkit.plugin.Plugin;
6 |
7 | public class FoliaScheduledTask implements MyScheduledTask {
8 | private final ScheduledTask task;
9 |
10 | public FoliaScheduledTask(final ScheduledTask task) {
11 | this.task = task;
12 | }
13 |
14 | public void cancel() {
15 | this.task.cancel();
16 | }
17 |
18 | public boolean isCancelled() {
19 | return this.task.isCancelled();
20 | }
21 |
22 | public Plugin getOwningPlugin() {
23 | return this.task.getOwningPlugin();
24 | }
25 |
26 | public boolean isCurrentlyRunning() {
27 | final ScheduledTask.ExecutionState state = this.task.getExecutionState();
28 | return state == ScheduledTask.ExecutionState.RUNNING || state == ScheduledTask.ExecutionState.CANCELLED_RUNNING;
29 | }
30 |
31 | public boolean isRepeatingTask() {
32 | return this.task.isRepeatingTask();
33 | }
34 | }
--------------------------------------------------------------------------------
/src/main/java/com/github/Anon8281/universalScheduler/foliaScheduler/FoliaScheduler.java:
--------------------------------------------------------------------------------
1 | package com.github.Anon8281.universalScheduler.foliaScheduler;
2 |
3 | import com.github.Anon8281.universalScheduler.scheduling.schedulers.TaskScheduler;
4 | import com.github.Anon8281.universalScheduler.scheduling.tasks.MyScheduledTask;
5 | import io.papermc.paper.threadedregions.scheduler.AsyncScheduler;
6 | import io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler;
7 | import io.papermc.paper.threadedregions.scheduler.RegionScheduler;
8 | import org.bukkit.Bukkit;
9 | import org.bukkit.Location;
10 | import org.bukkit.entity.Entity;
11 | import org.bukkit.plugin.Plugin;
12 |
13 | import java.util.concurrent.TimeUnit;
14 |
15 | public class FoliaScheduler implements TaskScheduler {
16 |
17 | final Plugin plugin;
18 |
19 | public FoliaScheduler(Plugin plugin) {
20 | this.plugin = plugin;
21 | }
22 |
23 | private final RegionScheduler regionScheduler = Bukkit.getServer().getRegionScheduler();
24 | private final GlobalRegionScheduler globalRegionScheduler = Bukkit.getServer().getGlobalRegionScheduler();
25 | private final AsyncScheduler asyncScheduler = Bukkit.getServer().getAsyncScheduler();
26 |
27 | @Override
28 | public boolean isGlobalThread() {
29 | return Bukkit.getServer().isGlobalTickThread();
30 | }
31 |
32 | @Override
33 | public boolean isTickThread() {
34 | return Bukkit.getServer().isPrimaryThread(); // The Paper implementation checks whether this is a tick thread, this method exists to avoid confusion.
35 | }
36 |
37 | @Override
38 | public boolean isEntityThread(Entity entity) {
39 | return Bukkit.getServer().isOwnedByCurrentRegion(entity);
40 | }
41 |
42 | @Override
43 | public boolean isRegionThread(Location location) {
44 | return Bukkit.getServer().isOwnedByCurrentRegion(location);
45 | }
46 |
47 | @Override
48 | public MyScheduledTask runTask(Runnable runnable) {
49 | return new FoliaScheduledTask(globalRegionScheduler.run(plugin, task -> runnable.run()));
50 | }
51 |
52 | @Override
53 | public MyScheduledTask runTaskLater(Runnable runnable, long delay) {
54 | //Folia exception: Delay ticks may not be <= 0
55 | if (delay <= 0) {
56 | return runTask(runnable);
57 | }
58 | return new FoliaScheduledTask(globalRegionScheduler.runDelayed(plugin, task -> runnable.run(), delay));
59 | }
60 |
61 | @Override
62 | public MyScheduledTask runTaskTimer(Runnable runnable, long delay, long period) {
63 | //Folia exception: Delay ticks may not be <= 0
64 | delay = getOneIfNotPositive(delay);
65 | return new FoliaScheduledTask(globalRegionScheduler.runAtFixedRate(plugin, task -> runnable.run(), delay, period));
66 | }
67 |
68 | @Override
69 | public MyScheduledTask runTask(Plugin plugin, Runnable runnable) {
70 | return new FoliaScheduledTask(globalRegionScheduler.run(plugin, task -> runnable.run()));
71 | }
72 |
73 | @Override
74 | public MyScheduledTask runTaskLater(Plugin plugin, Runnable runnable, long delay) {
75 | //Folia exception: Delay ticks may not be <= 0
76 | if (delay <= 0) {
77 | return runTask(plugin, runnable);
78 | }
79 | return new FoliaScheduledTask(globalRegionScheduler.runDelayed(plugin, task -> runnable.run(), delay));
80 | }
81 |
82 | @Override
83 | public MyScheduledTask runTaskTimer(Plugin plugin, Runnable runnable, long delay, long period) {
84 | //Folia exception: Delay ticks may not be <= 0
85 | delay = getOneIfNotPositive(delay);
86 | return new FoliaScheduledTask(globalRegionScheduler.runAtFixedRate(plugin, task -> runnable.run(), delay, period));
87 | }
88 |
89 | @Override
90 | public MyScheduledTask runTask(Location location, Runnable runnable) {
91 | return new FoliaScheduledTask(regionScheduler.run(plugin, location, task -> runnable.run()));
92 | }
93 |
94 | @Override
95 | public MyScheduledTask runTaskLater(Location location, Runnable runnable, long delay) {
96 | //Folia exception: Delay ticks may not be <= 0
97 | if (delay <= 0) {
98 | return runTask(runnable);
99 | }
100 | return new FoliaScheduledTask(regionScheduler.runDelayed(plugin, location, task -> runnable.run(), delay));
101 | }
102 |
103 | @Override
104 | public MyScheduledTask runTaskTimer(Location location, Runnable runnable, long delay, long period) {
105 | //Folia exception: Delay ticks may not be <= 0
106 | delay = getOneIfNotPositive(delay);
107 | return new FoliaScheduledTask(regionScheduler.runAtFixedRate(plugin, location, task -> runnable.run(), delay, period));
108 | }
109 |
110 | @Override
111 | public MyScheduledTask runTask(Entity entity, Runnable runnable) {
112 | return new FoliaScheduledTask(entity.getScheduler().run(plugin, task -> runnable.run(), null));
113 | }
114 |
115 | @Override
116 | public MyScheduledTask runTaskLater(Entity entity, Runnable runnable, long delay) {
117 | //Folia exception: Delay ticks may not be <= 0
118 | if (delay <= 0) {
119 | return runTask(entity, runnable);
120 | }
121 | return new FoliaScheduledTask(entity.getScheduler().runDelayed(plugin, task -> runnable.run(), null, delay));
122 | }
123 |
124 | @Override
125 | public MyScheduledTask runTaskTimer(Entity entity, Runnable runnable, long delay, long period) {
126 | //Folia exception: Delay ticks may not be <= 0
127 | delay = getOneIfNotPositive(delay);
128 | return new FoliaScheduledTask(entity.getScheduler().runAtFixedRate(plugin, task -> runnable.run(), null, delay, period));
129 | }
130 |
131 | @Override
132 | public MyScheduledTask runTaskAsynchronously(Runnable runnable) {
133 | return new FoliaScheduledTask(asyncScheduler.runNow(plugin, task -> runnable.run()));
134 | }
135 |
136 | @Override
137 | public MyScheduledTask runTaskLaterAsynchronously(Runnable runnable, long delay) {
138 | //Folia exception: Delay ticks may not be <= 0
139 | delay = getOneIfNotPositive(delay);
140 | return new FoliaScheduledTask(asyncScheduler.runDelayed(plugin, task -> runnable.run(), delay * 50L, TimeUnit.MILLISECONDS));
141 | }
142 |
143 | @Override
144 | public MyScheduledTask runTaskTimerAsynchronously(Runnable runnable, long delay, long period) {
145 | return new FoliaScheduledTask(asyncScheduler.runAtFixedRate(plugin, task -> runnable.run(), delay * 50, period * 50, TimeUnit.MILLISECONDS));
146 | }
147 |
148 | @Override
149 | public MyScheduledTask runTaskAsynchronously(Plugin plugin, Runnable runnable) {
150 | return new FoliaScheduledTask(asyncScheduler.runNow(plugin, task -> runnable.run()));
151 | }
152 |
153 | @Override
154 | public MyScheduledTask runTaskLaterAsynchronously(Plugin plugin, Runnable runnable, long delay) {
155 | //Folia exception: Delay ticks may not be <= 0
156 | delay = getOneIfNotPositive(delay);
157 | return new FoliaScheduledTask(asyncScheduler.runDelayed(plugin, task -> runnable.run(), delay * 50L, TimeUnit.MILLISECONDS));
158 | }
159 |
160 | @Override
161 | public MyScheduledTask runTaskTimerAsynchronously(Plugin plugin, Runnable runnable, long delay, long period) {
162 | //Folia exception: Delay ticks may not be <= 0
163 | delay = getOneIfNotPositive(delay);
164 | return new FoliaScheduledTask(asyncScheduler.runAtFixedRate(plugin, task -> runnable.run(), delay * 50, period * 50, TimeUnit.MILLISECONDS));
165 | }
166 |
167 | @Override
168 | public void execute(Runnable runnable) {
169 | globalRegionScheduler.execute(plugin, runnable);
170 | }
171 |
172 | @Override
173 | public void execute(Location location, Runnable runnable) {
174 | regionScheduler.execute(plugin, location, runnable);
175 | }
176 |
177 | @Override
178 | public void execute(Entity entity, Runnable runnable) {
179 | entity.getScheduler().execute(plugin, runnable, null, 1L);
180 | }
181 |
182 | @Override
183 | public void cancelTasks() {
184 | globalRegionScheduler.cancelTasks(plugin);
185 | asyncScheduler.cancelTasks(plugin);
186 | }
187 |
188 | @Override
189 | public void cancelTasks(Plugin plugin) {
190 | globalRegionScheduler.cancelTasks(plugin);
191 | asyncScheduler.cancelTasks(plugin);
192 | }
193 |
194 | private long getOneIfNotPositive(long x) {
195 | return x <= 0 ? 1L : x;
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/src/main/java/com/github/Anon8281/universalScheduler/paperScheduler/PaperScheduler.java:
--------------------------------------------------------------------------------
1 | package com.github.Anon8281.universalScheduler.paperScheduler;
2 |
3 | import com.github.Anon8281.universalScheduler.foliaScheduler.FoliaScheduler;
4 | import org.bukkit.Bukkit;
5 | import org.bukkit.plugin.Plugin;
6 |
7 | //Thanks to Towny
8 | public class PaperScheduler extends FoliaScheduler {
9 | public PaperScheduler(Plugin plugin) {
10 | super(plugin);
11 | }
12 |
13 | @Override
14 | public boolean isGlobalThread() {
15 | // isGlobalThread does not exist on paper, match the bukkit task scheduler's behaviour.
16 | return Bukkit.getServer().isPrimaryThread();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/github/Anon8281/universalScheduler/scheduling/schedulers/TaskScheduler.java:
--------------------------------------------------------------------------------
1 | package com.github.Anon8281.universalScheduler.scheduling.schedulers;
2 |
3 | import com.github.Anon8281.universalScheduler.scheduling.tasks.MyScheduledTask;
4 | import org.bukkit.Bukkit;
5 | import org.bukkit.Location;
6 | import org.bukkit.entity.Entity;
7 | import org.bukkit.plugin.Plugin;
8 |
9 | import java.util.concurrent.Callable;
10 | import java.util.concurrent.CompletableFuture;
11 | import java.util.concurrent.Future;
12 |
13 | public interface TaskScheduler {
14 |
15 | /**
16 | * Folia: Returns whether the current thread is ticking the global region
17 | * Paper & Bukkit: Returns {@link org.bukkit.Server#isPrimaryThread}
18 | */
19 | boolean isGlobalThread();
20 |
21 | /**
22 | * @return {@link org.bukkit.Server#isPrimaryThread}
23 | */
24 | default boolean isTickThread() {
25 | return Bukkit.getServer().isPrimaryThread();
26 | }
27 |
28 | /**
29 | * Folia & Paper: Returns whether the current thread is ticking a region and that the region
30 | * being ticked owns the specified entity. Note that this function is the only appropriate method of
31 | * checking for ownership of an entity, as retrieving the entity's location is undefined unless the
32 | * entity is owned by the current region
33 | *
34 | * Bukkit: returns {@link org.bukkit.Server#isPrimaryThread} 35 | * 36 | * @param entity Specified entity 37 | */ 38 | boolean isEntityThread(Entity entity); 39 | 40 | /** 41 | * Folia & Paper: Returns whether the current thread is ticking a region and that the region 42 | * being ticked owns the chunk at the specified world and block position as included in the specified location 43 | *
44 | * Bukkit: returns {@link org.bukkit.Server#isPrimaryThread}
45 | *
46 | * @param location Specified location, must have a non-null world.
47 | */
48 | boolean isRegionThread(Location location);
49 |
50 | /**
51 | * Schedules a task to be executed on the next tick
52 | * Folia & Paper: ...on the global region
53 | * Bukkit: ...on the main thread
54 | *
55 | * @param runnable The task to execute
56 | */
57 | MyScheduledTask runTask(Runnable runnable);
58 |
59 | /**
60 | * Schedules a task to be executed after the specified delay in ticks
61 | * Folia & Paper: ...on the global region
62 | * Bukkit: ...on the main thread
63 | *
64 | * @param runnable The task to execute
65 | * @param delay The delay, in ticks
66 | */
67 | MyScheduledTask runTaskLater(Runnable runnable, long delay);
68 |
69 | /**
70 | * Schedules a repeating task to be executed after the initial delay with the specified period
71 | * Folia & Paper: ...on the global region
72 | * Bukkit: ...on the main thread
73 | *
74 | * @param runnable The task to execute
75 | * @param delay The initial delay, in ticks.
76 | * @param period The period, in ticks.
77 | */
78 | MyScheduledTask runTaskTimer(Runnable runnable, long delay, long period);
79 |
80 | /**
81 | * Deprecated: use {@link #runTask(Runnable)}
82 | */
83 | @Deprecated
84 | default MyScheduledTask runTask(Plugin plugin, Runnable runnable) {
85 | return runTask(runnable);
86 | }
87 |
88 | /**
89 | * Deprecated: use {@link #runTaskLater(Runnable, long)}
90 | */
91 | @Deprecated
92 | default MyScheduledTask runTaskLater(Plugin plugin, Runnable runnable, long delay) {
93 | return runTaskLater(runnable, delay);
94 | }
95 |
96 | /**
97 | * Deprecated: use {@link #runTaskTimer(Runnable, long, long)}
98 | */
99 | @Deprecated
100 | default MyScheduledTask runTaskTimer(Plugin plugin, Runnable runnable, long delay, long period) {
101 | return runTaskTimer(runnable, delay, period);
102 | }
103 |
104 | /**
105 | * Folia & Paper: Schedules a task to be executed on the region which owns the location on the next tick
106 | *
107 | * Bukkit: same as {@link #runTask(Runnable)} 108 | * 109 | * @param location The location which the region executing should own 110 | * @param runnable The task to execute 111 | */ 112 | default MyScheduledTask runTask(Location location, Runnable runnable) { 113 | return runTask(runnable); 114 | } 115 | 116 | /** 117 | * Folia & Paper: Schedules a task to be executed on the region which owns the location after the 118 | * specified delay in ticks 119 | *
120 | * Bukkit: same as {@link #runTaskLater(Runnable, long)} 121 | * 122 | * @param location The location which the region executing should own 123 | * @param runnable The task to execute 124 | * @param delay The delay, in ticks. 125 | */ 126 | default MyScheduledTask runTaskLater(Location location, Runnable runnable, long delay) { 127 | return runTaskLater(runnable, delay); 128 | } 129 | 130 | /** 131 | * Folia & Paper: Schedules a repeating task to be executed on the region which owns the location 132 | * after the initial delay with the specified period 133 | *
134 | * Bukkit: same as {@link #runTaskTimer(Runnable, long, long)} 135 | * 136 | * @param location The location which the region executing should own 137 | * @param runnable The task to execute 138 | * @param delay The initial delay, in ticks. 139 | * @param period The period, in ticks. 140 | */ 141 | default MyScheduledTask runTaskTimer(Location location, Runnable runnable, long delay, long period) { 142 | return runTaskTimer(runnable, delay, period); 143 | } 144 | 145 | /** 146 | * Deprecated: use {@link #runTaskLater(Runnable, long)} 147 | */ 148 | @Deprecated 149 | default MyScheduledTask scheduleSyncDelayedTask(Runnable runnable, long delay) { 150 | return runTaskLater(runnable, delay); 151 | } 152 | 153 | /** 154 | * Deprecated: use {@link #execute(Runnable)} or {@link #runTask(Runnable)} 155 | */ 156 | @Deprecated 157 | default MyScheduledTask scheduleSyncDelayedTask(Runnable runnable) { 158 | return runTask(runnable); 159 | } 160 | 161 | /** 162 | * Deprecated: use {@link #runTaskTimer(Runnable, long, long)} 163 | */ 164 | @Deprecated 165 | default MyScheduledTask scheduleSyncRepeatingTask(Runnable runnable, long delay, long period) { 166 | return runTaskTimer(runnable, delay, period); 167 | } 168 | 169 | /** 170 | * Folia & Paper: Schedules a task to be executed on the region which owns the location 171 | * of given entity on the next tick 172 | *
173 | * Bukkit: same as {@link #runTask(Runnable)} 174 | * 175 | * @param entity The entity whose location the region executing should own 176 | * @param runnable The task to execute 177 | */ 178 | default MyScheduledTask runTask(Entity entity, Runnable runnable) { 179 | return runTask(runnable); 180 | } 181 | 182 | /** 183 | * Folia & Paper: Schedules a task to be executed on the region which owns the location 184 | * of given entity after the specified delay in ticks 185 | *
186 | * Bukkit: same as {@link #runTaskLater(Runnable, long)} 187 | * 188 | * @param entity The entity whose location the region executing should own 189 | * @param runnable The task to execute 190 | * @param delay The delay, in ticks. 191 | */ 192 | default MyScheduledTask runTaskLater(Entity entity, Runnable runnable, long delay) { 193 | return runTaskLater(runnable, delay); 194 | } 195 | 196 | /** 197 | * Folia & Paper: Schedules a repeating task to be executed on the region which owns the 198 | * location of given entity after the initial delay with the specified period 199 | *
200 | * Bukkit: same as {@link #runTaskTimer(Runnable, long, long)} 201 | * 202 | * @param entity The entity whose location the region executing should own 203 | * @param runnable The task to execute 204 | * @param delay The initial delay, in ticks. 205 | * @param period The period, in ticks. 206 | */ 207 | default MyScheduledTask runTaskTimer(Entity entity, Runnable runnable, long delay, long period) { 208 | return runTaskTimer(runnable, delay, period); 209 | } 210 | 211 | /** 212 | * Schedules the specified task to be executed asynchronously immediately 213 | * 214 | * @param runnable The task to execute 215 | * @return The {@link MyScheduledTask} that represents the scheduled task 216 | */ 217 | MyScheduledTask runTaskAsynchronously(Runnable runnable); 218 | 219 | /** 220 | * Schedules the specified task to be executed asynchronously after the time delay has passed 221 | * 222 | * @param runnable The task to execute 223 | * @param delay The time delay to pass before the task should be executed 224 | * @return The {@link MyScheduledTask} that represents the scheduled task 225 | */ 226 | MyScheduledTask runTaskLaterAsynchronously(Runnable runnable, long delay); 227 | 228 | /** 229 | * Schedules the specified task to be executed asynchronously after the initial delay has passed, 230 | * and then periodically executed with the specified period 231 | * 232 | * @param runnable The task to execute 233 | * @param delay The time delay to pass before the first execution of the task, in ticks 234 | * @param period The time between task executions after the first execution of the task, in ticks 235 | * @return The {@link MyScheduledTask} that represents the scheduled task 236 | */ 237 | MyScheduledTask runTaskTimerAsynchronously(Runnable runnable, long delay, long period); 238 | 239 | /** 240 | * Deprecated: use {@link #runTaskAsynchronously(Runnable)} 241 | */ 242 | @Deprecated 243 | default MyScheduledTask runTaskAsynchronously(Plugin plugin, Runnable runnable) { 244 | return runTaskAsynchronously(runnable); 245 | } 246 | 247 | /** 248 | * Deprecated: use {@link #runTaskLaterAsynchronously(Runnable, long)} 249 | */ 250 | @Deprecated 251 | default MyScheduledTask runTaskLaterAsynchronously(Plugin plugin, Runnable runnable, long delay) { 252 | return runTaskLaterAsynchronously(runnable, delay); 253 | } 254 | 255 | /** 256 | * Deprecated: use {@link #runTaskTimerAsynchronously(Runnable, long, long)} 257 | */ 258 | @Deprecated 259 | default MyScheduledTask runTaskTimerAsynchronously(Plugin plugin, Runnable runnable, long delay, long period) { 260 | return runTaskTimerAsynchronously(runnable, delay, period); 261 | } 262 | 263 | /** 264 | * Calls a method on the main thread and returns a Future object. This task will be executed 265 | * by the main(Bukkit)/global(Folia&Paper) server thread. 266 | *
267 | * Note: The Future.get() methods must NOT be called from the main thread. 268 | *
269 | * Note2: There is at least an average of 10ms latency until the isDone() method returns true.
270 | *
271 | * @param task Task to be executed
272 | */
273 | default