11package nl .rutgerkok .blocklocker .impl ;
22
3- import java .lang .reflect .InvocationTargetException ;
4- import java .lang .reflect .Method ;
5- import java .util .Objects ;
6- import java .util .concurrent .TimeUnit ;
7- import java .util .function .Consumer ;
8-
9- import org .bukkit .Location ;
10- import org .bukkit .Server ;
11- import org .bukkit .World ;
123import org .bukkit .block .Block ;
134import org .bukkit .plugin .Plugin ;
145import org .bukkit .scheduler .BukkitTask ;
156
7+ import java .util .Objects ;
8+ import java .util .concurrent .TimeUnit ;
9+ import java .util .function .Consumer ;
10+
1611/**
17- * Horrible reflection code to access the Folia scheduler if we're on Folia.
18- *
19- * <p>
20- * I guess the "best" solution would be to create a submodule that can access
21- * Folia code. However, that complicates the project setup. I guess at some
22- * point Paper will offer a better solution, so that you don't need two code
23- * paths.
24- *
25- * <p>
26- * Some Java purists will say that you should separate this class into three: an
27- * interface, and two implementations (Folia and Bukkit). However, since the
28- * reflection code is quite unreadable, I think it's better to keep the
29- * reference Bukkit code close by.
12+ * Code to support both the standard schedulers of Bukkit, and Folia's scheduler.
3013 */
3114final class SchedulerSupport {
3215
33- private static Method getRegionScheduler ;
34- private static Method getGlobalRegionScheduler ;
35- private static Method getAsyncScheduler ;
36-
37- private static Class <?> globalRegionScheduler ;
38- private static Class <?> regionScheduler ;
39- private static Class <?> asyncScheduler ;
40-
41- private static Method runDelayedOnGlobal ;
42- private static Method runDelayedOnRegion ;
43- private static Method runOnRegion ;
44- private static Method runAtFixedRateAsync ;
16+ private static boolean folia ;
4517
4618 static {
4719 try {
48- getRegionScheduler = Server .class .getMethod ("getRegionScheduler" );
49- getGlobalRegionScheduler = Server .class .getMethod ("getGlobalRegionScheduler" );
50- getAsyncScheduler = Server .class .getMethod ("getAsyncScheduler" );
51-
52- globalRegionScheduler = getGlobalRegionScheduler .getReturnType ();
53- regionScheduler = getRegionScheduler .getReturnType ();
54- asyncScheduler = getAsyncScheduler .getReturnType ();
55-
56- runDelayedOnGlobal = globalRegionScheduler
57- .getMethod ("runDelayed" , Plugin .class , Consumer .class , long .class );
58- runDelayedOnRegion = regionScheduler
59- .getMethod ("runDelayed" , Plugin .class , World .class , int .class , int .class , Consumer .class , long .class );
60- runOnRegion = regionScheduler
61- .getMethod ("run" , Plugin .class , Location .class , Consumer .class );
62- runAtFixedRateAsync = asyncScheduler
63- .getMethod ("runAtFixedRate" , Plugin .class , Consumer .class , long .class , long .class , TimeUnit .class );
20+ Class .forName ("io.papermc.paper.threadedregions.RegionizedServer" );
6421 folia = true ;
65- } catch (NoSuchMethodException e ) {
22+ } catch (ClassNotFoundException e ) {
6623 folia = false ;
6724 }
6825 }
6926
70- private static boolean folia ;
71-
72- /**
73- * Used to invoke a parameterless instance method.
74- *
75- * @param on
76- * The instance.
77- * @param name
78- * Name of the method.
79- * @return Return value of the method (null for void methods).
80- */
81- private static Object invoke (Object on , String name ) {
82- try {
83- return on .getClass ().getMethod (name ).invoke (on );
84- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
85- | SecurityException e ) {
86- throw new RuntimeException ("Cannot invoke instance." + name + "()" , e );
87- }
88- }
89-
9027 private final Plugin plugin ;
9128
9229 SchedulerSupport (Plugin plugin ) {
@@ -95,92 +32,65 @@ private static Object invoke(Object on, String name) {
9532
9633 public void runLater (Block block , Runnable runnable ) {
9734 if (folia ) {
98- try {
99- Object regionScheduler = getRegionScheduler .invoke (plugin .getServer ());
100- Consumer <?> consumer = task -> {
101- runnable .run ();
102- };
103- runOnRegion .invoke (regionScheduler , this .plugin , block .getLocation (), consumer );
104- } catch (IllegalAccessException | InvocationTargetException e ) {
105- throw new RuntimeException (e );
106- }
35+ plugin .getServer ().getRegionScheduler ().run (plugin , block .getLocation (), task -> {
36+ runnable .run ();
37+ });
10738 } else {
10839 plugin .getServer ().getScheduler ().runTask (plugin , runnable );
10940 }
11041 }
11142
11243 public void runLater (Block block , Runnable runnable , int ticks ) {
11344 if (folia ) {
114- try {
115- Object regionScheduler = getRegionScheduler .invoke (plugin .getServer ());
116- Consumer <?> consumer = task -> {
117- runnable .run ();
118- };
119- runDelayedOnRegion .invoke (regionScheduler , plugin , block
120- .getWorld (), block .getX () >> 4 , block .getZ () >> 4 , consumer , ticks );
121- } catch (IllegalAccessException | InvocationTargetException e ) {
122- throw new RuntimeException (e );
123- }
45+ plugin .getServer ().getRegionScheduler ().runDelayed (plugin , block .getLocation (), task -> {
46+ runnable .run ();
47+ }, ticks );
12448 } else {
12549 plugin .getServer ().getScheduler ().runTaskLater (plugin , runnable , ticks );
12650 }
12751 }
12852
12953 void runLaterGlobally (Runnable runnable , int ticks ) {
13054 if (folia ) {
131- try {
132- Object globalRegionScheduler = getGlobalRegionScheduler .invoke (plugin .getServer ());
133- Consumer <?> consumer = task -> {
134- runnable .run ();
135- };
136- runDelayedOnGlobal .invoke (globalRegionScheduler , plugin , consumer , ticks );
137- } catch (IllegalAccessException | InvocationTargetException e ) {
138- throw new RuntimeException (e );
139- }
55+ plugin .getServer ().getGlobalRegionScheduler ().runDelayed (plugin , task -> {
56+ runnable .run ();
57+ }, ticks );
14058 } else {
14159 plugin .getServer ().getScheduler ().runTaskLater (plugin , runnable , ticks );
14260 }
14361 }
14462
14563 void runTimerAsync (Consumer <BukkitTask > task , long checkInterval ) {
14664 if (folia ) {
147- try {
148- Object asyncScheduler = getAsyncScheduler .invoke (plugin .getServer ());
149-
150- Consumer <?> consumer = foliaTask -> {
151- task .accept (new BukkitTask () {
152-
153- @ Override
154- public void cancel () {
155- invoke (foliaTask , "cancel" );
156- }
157-
158- @ Override
159- public Plugin getOwner () {
160- return (Plugin ) invoke (foliaTask , "getOwningPlugin" );
161- }
162-
163- @ Override
164- public int getTaskId () {
165- throw new UnsupportedOperationException ();
166- }
167-
168- @ Override
169- public boolean isCancelled () {
170- return (Boolean ) invoke (foliaTask , "isCancelled" );
171- }
172-
173- @ Override
174- public boolean isSync () {
175- return false ;
176- }
177- });
178- };
179- runAtFixedRateAsync
180- .invoke (asyncScheduler , plugin , consumer , 1 , checkInterval * 50 , TimeUnit .MILLISECONDS );
181- } catch (IllegalAccessException | InvocationTargetException e ) {
182- throw new RuntimeException (e );
183- }
65+ plugin .getServer ().getAsyncScheduler ().runAtFixedRate (plugin , foliaTask -> {
66+ task .accept (new BukkitTask () {
67+
68+ @ Override
69+ public void cancel () {
70+ foliaTask .cancel ();
71+ }
72+
73+ @ Override
74+ public Plugin getOwner () {
75+ return foliaTask .getOwningPlugin ();
76+ }
77+
78+ @ Override
79+ public int getTaskId () {
80+ throw new UnsupportedOperationException ();
81+ }
82+
83+ @ Override
84+ public boolean isCancelled () {
85+ return foliaTask .isCancelled ();
86+ }
87+
88+ @ Override
89+ public boolean isSync () {
90+ return false ;
91+ }
92+ });
93+ }, 1 , checkInterval * 50 , TimeUnit .MILLISECONDS );
18494 } else {
18595 BukkitTask [] bukkitTask = new BukkitTask [1 ];
18696 bukkitTask [0 ] = plugin .getServer ().getScheduler ().runTaskTimerAsynchronously (plugin , () -> {
0 commit comments