diff --git a/platforms/common/src/main/java/dynamic_fps/impl/DynamicFPSMod.java b/platforms/common/src/main/java/dynamic_fps/impl/DynamicFPSMod.java index 8a1afbc9..6f56951a 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/DynamicFPSMod.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/DynamicFPSMod.java @@ -15,6 +15,7 @@ import dynamic_fps.impl.util.Logging; import dynamic_fps.impl.feature.state.OptionHolder; import dynamic_fps.impl.util.ResourceLocations; +import dynamic_fps.impl.util.Threads; import dynamic_fps.impl.util.Version; import dynamic_fps.impl.feature.volume.SmoothVolumeHandler; import dynamic_fps.impl.util.duck.DuckLoadingOverlay; @@ -198,11 +199,20 @@ public static void onBatteryStatusChanged(State before, State after) { // Internal logic private static void doInit() { - // NOTE: Init battery tracker first here - // Since the idle handler queries it for info - BatteryTracker.init(); - IdleHandler.init(); SmoothVolumeHandler.init(); + + if (!BatteryTracker.isFeatureEnabled()) { + IdleHandler.init(); + } else { + // Run battery tracker init on its own thread to ensure + // The initial library download doesn't block rendering + Threads.create("init", () -> { + BatteryTracker.init(); + // The idle handler must be initialized later, + // Since it queries whether there are batteries available + Threads.runOnMainThread(IdleHandler::init); + }); + } } private static void showNotification(String titleTranslationKey, String iconPath) { @@ -263,7 +273,7 @@ private static void checkForStateChanges() { checkForStateChanges0(); } else { // Schedule check for the beginning of the next frame - minecraft.schedule(DynamicFPSMod::checkForStateChanges0); + Threads.runOnMainThread(DynamicFPSMod::checkForStateChanges0); } } diff --git a/platforms/common/src/main/java/dynamic_fps/impl/compat/GLFW.java b/platforms/common/src/main/java/dynamic_fps/impl/compat/GLFW.java index 0f8e765f..3278b15a 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/compat/GLFW.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/compat/GLFW.java @@ -1,6 +1,7 @@ package dynamic_fps.impl.compat; import dynamic_fps.impl.DynamicFPSMod; +import dynamic_fps.impl.util.Threads; import dynamic_fps.impl.util.Version; import net.minecraft.client.Minecraft; @@ -32,7 +33,7 @@ public static void applyWorkaround() { // Agrees that the window is focused. The mod is // A little too fast for this, so we schedule it // For the next client tick (before next frame). - minecraft.schedule(minecraft.mouseHandler::grabMouse); + Threads.runOnMainThread(minecraft.mouseHandler::grabMouse); } } diff --git a/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/BatteryTracker.java b/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/BatteryTracker.java index f6bf2014..2e5da1c0 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/BatteryTracker.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/BatteryTracker.java @@ -4,12 +4,12 @@ import dynamic_fps.impl.config.DynamicFPSConfig; import dynamic_fps.impl.service.Platform; import dynamic_fps.impl.util.Logging; +import dynamic_fps.impl.util.Threads; import net.lostluma.battery.api.Battery; import net.lostluma.battery.api.Manager; import net.lostluma.battery.api.State; import net.lostluma.battery.api.exception.LibraryLoadError; import net.lostluma.battery.api.util.LibraryUtil; -import net.minecraft.client.Minecraft; import org.jetbrains.annotations.Nullable; import java.io.IOException; @@ -29,7 +29,6 @@ public class BatteryTracker { private static @Nullable Manager manager = null; private static Collection batteries = Collections.emptyList(); - private static final Minecraft minecraft = Minecraft.getInstance(); private static final Duration updateInterval = Duration.of(15, ChronoUnit.SECONDS); public static int charge() { @@ -57,7 +56,7 @@ public static boolean hasBatteries() { } public static void init() { - if (manager != null || !DynamicFPSConfig.INSTANCE.batteryTracker().enabled()) { + if (manager != null || !isFeatureEnabled()) { return; } @@ -72,10 +71,14 @@ public static void init() { } } else { manager = temp; // Keep around to allow updating batteries - Thread.ofVirtual().name("refresh-battery").start(BatteryTracker::updateBatteries); + Threads.create("refresh-battery", BatteryTracker::updateBatteries); } } + public static boolean isFeatureEnabled() { + return DynamicFPSConfig.INSTANCE.batteryTracker().enabled(); + } + private static State mergeStates(State a, State b) { if (a == b) { return a; @@ -105,7 +108,7 @@ private static void updateState() { changed = true; int current = charge; - minecraft.schedule(() -> DynamicFPSMod.onBatteryChargeChanged(current, newCharge)); + Threads.runOnMainThread(() -> DynamicFPSMod.onBatteryChargeChanged(current, newCharge)); } if (readInitialData && status != newStatus) { @@ -113,7 +116,7 @@ private static void updateState() { State current = status; State updated = newStatus; - minecraft.schedule(() -> DynamicFPSMod.onBatteryStatusChanged(current, updated)); + Threads.runOnMainThread(() -> DynamicFPSMod.onBatteryStatusChanged(current, updated)); } charge = newCharge; @@ -177,7 +180,7 @@ private static Manager createManager() { path = "no_library"; } - ErrorToast.queueToast(localized("toast", path)); + Threads.runOnMainThread(() -> ErrorToast.queueToast(localized("toast", path))); } return result; diff --git a/platforms/common/src/main/java/dynamic_fps/impl/util/Threads.java b/platforms/common/src/main/java/dynamic_fps/impl/util/Threads.java new file mode 100644 index 00000000..fd84c2cb --- /dev/null +++ b/platforms/common/src/main/java/dynamic_fps/impl/util/Threads.java @@ -0,0 +1,21 @@ +package dynamic_fps.impl.util; + +import net.minecraft.client.Minecraft; + +public class Threads { + /** + * Schedule a task on the main thread. + */ + public static void runOnMainThread(Runnable runnable) { + Minecraft.getInstance().schedule(runnable); + } + + /** + * Create a thread and immediately start it. + */ + public static Thread create(String name, Runnable runnable) { + Thread thread = new Thread(runnable, "dynamic-fps-" + name); + thread.start(); + return thread; + } +}