Route hybrid schedulers

- Select Bukkit scheduling only when the bound platform identifies as Bukkit.
- Route hybrid Youer hosts through the modded scheduler despite Bukkit classes on the classpath.
- Add regression coverage for Bukkit and NeoForge platform identities.
This commit is contained in:
Brian Neumann-Fopiano
2026-08-28 16:29:58 -04:00
parent ecec18509c
commit 95d8523d1d
2 changed files with 70 additions and 9 deletions
@@ -121,7 +121,7 @@ public class J {
} }
public static void aBukkit(Runnable a) { public static void aBukkit(Runnable a) {
if (!BUKKIT_PRESENT) { if (!usesBukkitScheduler()) {
if (IrisPlatforms.isBound()) { if (IrisPlatforms.isBound()) {
IrisPlatforms.get().scheduler().async(a); IrisPlatforms.get().scheduler().async(a);
} }
@@ -186,7 +186,7 @@ public class J {
} }
public static boolean isFolia() { public static boolean isFolia() {
return BUKKIT_PRESENT && FoliaScheduler.isFolia(Bukkit.getServer()); return usesBukkitScheduler() && FoliaScheduler.isFolia(Bukkit.getServer());
} }
public static boolean isPrimaryThread() { public static boolean isPrimaryThread() {
@@ -345,7 +345,7 @@ public class J {
return false; return false;
} }
if (!BUKKIT_PRESENT) { if (!usesBukkitScheduler()) {
if (!IrisPlatforms.isBound()) { if (!IrisPlatforms.isBound()) {
return false; return false;
} }
@@ -416,7 +416,7 @@ public class J {
public static void cancelPluginTasks() { public static void cancelPluginTasks() {
cancelTrackedRepeatingTasks(); cancelTrackedRepeatingTasks();
if (!BukkitPlatform.hasPlugin()) { if (!usesBukkitScheduler() || !BukkitPlatform.hasPlugin()) {
return; return;
} }
@@ -442,7 +442,7 @@ public class J {
} }
public static void s(Runnable r) { public static void s(Runnable r) {
if (!BUKKIT_PRESENT) { if (!usesBukkitScheduler()) {
if (IrisPlatforms.isBound()) { if (IrisPlatforms.isBound()) {
IrisPlatforms.get().scheduler().global(r); IrisPlatforms.get().scheduler().global(r);
} }
@@ -566,7 +566,7 @@ public class J {
} }
public static void s(Runnable r, int delay) { public static void s(Runnable r, int delay) {
if (!BUKKIT_PRESENT) { if (!usesBukkitScheduler()) {
if (IrisPlatforms.isBound()) { if (IrisPlatforms.isBound()) {
IrisPlatforms.get().scheduler().laterGlobal(r, delay); IrisPlatforms.get().scheduler().laterGlobal(r, delay);
} }
@@ -667,7 +667,7 @@ public class J {
} }
public static void a(Runnable r, int delay) { public static void a(Runnable r, int delay) {
if (!BUKKIT_PRESENT) { if (!usesBukkitScheduler()) {
if (IrisPlatforms.isBound()) { if (IrisPlatforms.isBound()) {
if (delay <= 0) { if (delay <= 0) {
IrisPlatforms.get().scheduler().async(r); IrisPlatforms.get().scheduler().async(r);
@@ -772,11 +772,17 @@ public class J {
} }
private static boolean isPluginEnabled() { private static boolean isPluginEnabled() {
return BUKKIT_PRESENT && BukkitPlatform.hasPlugin() && Bukkit.getPluginManager().isPluginEnabled(BukkitPlatform.plugin()); return usesBukkitScheduler() && BukkitPlatform.hasPlugin() && Bukkit.getPluginManager().isPluginEnabled(BukkitPlatform.plugin());
} }
private static boolean canSchedule() { private static boolean canSchedule() {
return BUKKIT_PRESENT ? isPluginEnabled() : IrisPlatforms.isBound(); return usesBukkitScheduler() ? isPluginEnabled() : IrisPlatforms.isBound();
}
static boolean usesBukkitScheduler() {
return BUKKIT_PRESENT
&& IrisPlatforms.isBound()
&& "bukkit".equalsIgnoreCase(IrisPlatforms.get().platformName());
} }
private static long ticksToMilliseconds(int ticks) { private static long ticksToMilliseconds(int ticks) {
@@ -0,0 +1,55 @@
package art.arcane.iris.util.common.scheduling;
import art.arcane.iris.spi.IrisPlatform;
import art.arcane.iris.spi.IrisPlatforms;
import art.arcane.iris.spi.PlatformScheduler;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class JHybridPlatformTest {
@Before
public void clearPlatform() {
IrisPlatforms.unbind();
}
@After
public void cleanup() {
J.cancelTrackedRepeatingTasks();
IrisPlatforms.unbind();
}
@Test
public void boundBukkitIdentitySelectsBukkitScheduler() {
IrisPlatform platform = mock(IrisPlatform.class);
when(platform.platformName()).thenReturn("bukkit");
IrisPlatforms.bind(platform);
assertTrue(J.usesBukkitScheduler());
}
@Test
public void hybridHostRepeaterUsesBoundModdedScheduler() {
IrisPlatform platform = mock(IrisPlatform.class);
PlatformScheduler scheduler = mock(PlatformScheduler.class);
when(platform.platformName()).thenReturn("neoforge");
when(platform.scheduler()).thenReturn(scheduler);
IrisPlatforms.bind(platform);
assertFalse(J.usesBukkitScheduler());
int taskId = J.ar(() -> {
}, 1);
assertNotEquals(-1, taskId);
verify(scheduler).laterGlobal(any(Runnable.class), eq(1));
}
}