From 95d8523d1d7270cfc7460df7a0b66d49458ef1b3 Mon Sep 17 00:00:00 2001 From: Brian Neumann-Fopiano Date: Fri, 28 Aug 2026 16:29:58 -0400 Subject: [PATCH] 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. --- .../arcane/iris/util/common/scheduling/J.java | 24 +++++--- .../scheduling/JHybridPlatformTest.java | 55 +++++++++++++++++++ 2 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 core/src/test/java/art/arcane/iris/util/common/scheduling/JHybridPlatformTest.java diff --git a/core/src/main/java/art/arcane/iris/util/common/scheduling/J.java b/core/src/main/java/art/arcane/iris/util/common/scheduling/J.java index f811bfc5d..dd2cee405 100644 --- a/core/src/main/java/art/arcane/iris/util/common/scheduling/J.java +++ b/core/src/main/java/art/arcane/iris/util/common/scheduling/J.java @@ -121,7 +121,7 @@ public class J { } public static void aBukkit(Runnable a) { - if (!BUKKIT_PRESENT) { + if (!usesBukkitScheduler()) { if (IrisPlatforms.isBound()) { IrisPlatforms.get().scheduler().async(a); } @@ -186,7 +186,7 @@ public class J { } public static boolean isFolia() { - return BUKKIT_PRESENT && FoliaScheduler.isFolia(Bukkit.getServer()); + return usesBukkitScheduler() && FoliaScheduler.isFolia(Bukkit.getServer()); } public static boolean isPrimaryThread() { @@ -345,7 +345,7 @@ public class J { return false; } - if (!BUKKIT_PRESENT) { + if (!usesBukkitScheduler()) { if (!IrisPlatforms.isBound()) { return false; } @@ -416,7 +416,7 @@ public class J { public static void cancelPluginTasks() { cancelTrackedRepeatingTasks(); - if (!BukkitPlatform.hasPlugin()) { + if (!usesBukkitScheduler() || !BukkitPlatform.hasPlugin()) { return; } @@ -442,7 +442,7 @@ public class J { } public static void s(Runnable r) { - if (!BUKKIT_PRESENT) { + if (!usesBukkitScheduler()) { if (IrisPlatforms.isBound()) { IrisPlatforms.get().scheduler().global(r); } @@ -566,7 +566,7 @@ public class J { } public static void s(Runnable r, int delay) { - if (!BUKKIT_PRESENT) { + if (!usesBukkitScheduler()) { if (IrisPlatforms.isBound()) { IrisPlatforms.get().scheduler().laterGlobal(r, delay); } @@ -667,7 +667,7 @@ public class J { } public static void a(Runnable r, int delay) { - if (!BUKKIT_PRESENT) { + if (!usesBukkitScheduler()) { if (IrisPlatforms.isBound()) { if (delay <= 0) { IrisPlatforms.get().scheduler().async(r); @@ -772,11 +772,17 @@ public class J { } 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() { - 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) { diff --git a/core/src/test/java/art/arcane/iris/util/common/scheduling/JHybridPlatformTest.java b/core/src/test/java/art/arcane/iris/util/common/scheduling/JHybridPlatformTest.java new file mode 100644 index 000000000..6d97dfe0d --- /dev/null +++ b/core/src/test/java/art/arcane/iris/util/common/scheduling/JHybridPlatformTest.java @@ -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)); + } +}