From c4aca598d1cea118a514f4c3f6b6fbd7cdc2ee77 Mon Sep 17 00:00:00 2001 From: LostLuma Date: Fri, 20 Sep 2024 10:27:52 +0200 Subject: [PATCH] Minecraft 1.19.3 backport --- .../main/kotlin/dynamic_fps.java.gradle.kts | 4 +- gradle.properties | 8 +- gradle/libs.versions.toml | 12 +-- .../java/dynamic_fps/impl/DynamicFPSMod.java | 17 ++-- .../dynamic_fps/impl/compat/ClothConfig.java | 7 +- .../java/dynamic_fps/impl/compat/GLFW.java | 2 +- .../option/BatteryIndicatorPlacement.java | 16 +-- .../impl/config/option/IdleCondition.java | 1 - .../impl/feature/battery/BaseToast.java | 48 ++++----- .../impl/feature/battery/BatteryToast.java | 5 +- .../impl/feature/battery/BatteryTracker.java | 8 +- .../impl/feature/battery/ErrorToast.java | 2 +- .../impl/feature/state/OptionHolder.java | 2 +- .../mixin/FramerateLimitTrackerMixin.java | 99 ------------------- .../impl/mixin/MinecraftMixin.java | 30 +++++- .../dynamic_fps/impl/mixin/ScreenMixin.java | 50 ++++++++++ .../impl/mixin/StatsScreenMixin.java | 17 ++++ ...gerMixin.java => ToastComponentMixin.java} | 10 +- .../dynamic_fps/impl/mixin/WindowMixin.java | 28 ++++++ .../dynamic_fps/impl/service/ModCompat.java | 13 +++ .../impl/util/FallbackConfigScreen.java | 15 +-- .../impl/util/HudInfoRenderer.java | 30 +++--- .../impl/util/ModCompatHelper.java | 40 ++++++++ .../impl/util/ResourceLocations.java | 2 +- .../impl/util/VariableStepTransformer.java | 14 ++- .../impl/util/duck/DuckScreen.java | 11 +++ .../dynamic_fps/data/default_config.json | 2 +- .../resources/dynamic_fps-common.mixins.json | 6 +- .../fabric/src/main/resources/fabric.mod.json | 42 +++++++- .../impl/forge/DynamicFPSForgeMod.java | 16 +-- .../impl/forge/mixin/GuiMixin.java | 21 ---- .../impl/forge/service/ForgeModCompat.java | 40 +++++++- .../src/main/resources/META-INF/mods.toml | 2 +- .../main/resources/dynamic_fps.mixins.json | 4 +- .../impl/neoforge/DynamicFPSNeoForgeMod.java | 8 +- .../neoforge/service/NeoForgeModCompat.java | 16 +++ .../neoforge/service/NeoForgePlatform.java | 4 +- .../{neoforge.mods.toml => mods.toml} | 2 +- .../quilt/src/main/resources/quilt.mod.json | 40 +++++++- .../impl/textile/mixin/GuiMixin.java | 14 ++- .../textile/service/TextileModCompat.java | 41 ++++++++ settings.gradle.kts | 2 +- 42 files changed, 500 insertions(+), 251 deletions(-) delete mode 100644 platforms/common/src/main/java/dynamic_fps/impl/mixin/FramerateLimitTrackerMixin.java create mode 100644 platforms/common/src/main/java/dynamic_fps/impl/mixin/ScreenMixin.java create mode 100644 platforms/common/src/main/java/dynamic_fps/impl/mixin/StatsScreenMixin.java rename platforms/common/src/main/java/dynamic_fps/impl/mixin/{ToastManagerMixin.java => ToastComponentMixin.java} (58%) create mode 100644 platforms/common/src/main/java/dynamic_fps/impl/mixin/WindowMixin.java create mode 100644 platforms/common/src/main/java/dynamic_fps/impl/util/ModCompatHelper.java create mode 100644 platforms/common/src/main/java/dynamic_fps/impl/util/duck/DuckScreen.java delete mode 100644 platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/mixin/GuiMixin.java rename platforms/neoforge/src/main/resources/META-INF/{neoforge.mods.toml => mods.toml} (97%) diff --git a/build-logic/src/main/kotlin/dynamic_fps.java.gradle.kts b/build-logic/src/main/kotlin/dynamic_fps.java.gradle.kts index 10e67fe4..1acb9758 100644 --- a/build-logic/src/main/kotlin/dynamic_fps.java.gradle.kts +++ b/build-logic/src/main/kotlin/dynamic_fps.java.gradle.kts @@ -6,7 +6,7 @@ java { withSourcesJar() toolchain { - languageVersion = JavaLanguageVersion.of(21) + languageVersion = JavaLanguageVersion.of(17) } } @@ -14,6 +14,6 @@ tasks.withType { options.encoding = "UTF-8" javaCompiler = javaToolchains.compilerFor { - languageVersion = JavaLanguageVersion.of(21) + languageVersion = JavaLanguageVersion.of(17) } } diff --git a/gradle.properties b/gradle.properties index a33c2168..ecd1e3fb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,9 +10,9 @@ maven_group = juliand665 archives_name = dynamic-fps # File naming version -minecraft_version = 1.21.2 +minecraft_version = 1.19.3 # Version for publishing -minecraft_version_min = 1.21.2 -minecraft_version_max = 1.21.2 +minecraft_version_min = 1.19.3 +minecraft_version_max = 1.19.3 -enabled_platforms=fabric,forge,neoforge,quilt +enabled_platforms=fabric,forge,quilt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3fe0d4cb..a421fb07 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,14 +1,14 @@ [versions] -minecraft = "1.21.3" +minecraft = "1.19.3" # Platform libraries fabric_loader = "0.15.10" -fabric_api = "0.102.2+1.21.2" +fabric_api = "0.76.1+1.19.3" -forge = "1.21.3-53.0.7" +forge = "1.19.3-44.1.23" -neoforge = "21.3.0-beta" +neoforge = "20.4.237" quilt_loader = "0.25.0" @@ -18,8 +18,8 @@ battery = "1.3.0" # Modding libraries -modmenu = "11.0.0-beta.1" -cloth_config = "15.0.127" +modmenu = "5.1.0" +cloth_config = "9.1.104" mixinextras = "0.3.5" 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..ba62b7a3 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/DynamicFPSMod.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/DynamicFPSMod.java @@ -10,16 +10,13 @@ import dynamic_fps.impl.feature.battery.BatteryToast; import dynamic_fps.impl.feature.battery.BatteryTracker; import dynamic_fps.impl.feature.state.IdleHandler; -import dynamic_fps.impl.util.BatteryUtil; -import dynamic_fps.impl.util.FallbackConfigScreen; -import dynamic_fps.impl.util.Logging; +import dynamic_fps.impl.util.*; import dynamic_fps.impl.feature.state.OptionHolder; -import dynamic_fps.impl.util.ResourceLocations; -import dynamic_fps.impl.util.Version; import dynamic_fps.impl.feature.volume.SmoothVolumeHandler; import dynamic_fps.impl.util.duck.DuckLoadingOverlay; import dynamic_fps.impl.feature.state.WindowObserver; import dynamic_fps.impl.service.Platform; +import dynamic_fps.impl.util.duck.DuckScreen; import net.lostluma.battery.api.State; import net.minecraft.Util; import net.minecraft.client.Minecraft; @@ -178,7 +175,7 @@ public static GraphicsState graphicsState() { } public static boolean shouldShowLevels() { - return isDisabled() || !isLevelCoveredByOverlay(); + return isDisabled() || !(isLevelCoveredByScreen() || isLevelCoveredByOverlay()); } public static void onBatteryChargeChanged(int before, int after) { @@ -200,11 +197,17 @@ public static void onBatteryStatusChanged(State before, State after) { private static void doInit() { // NOTE: Init battery tracker first here // Since the idle handler queries it for info + ModCompatHelper.init(); + BatteryTracker.init(); IdleHandler.init(); SmoothVolumeHandler.init(); } + private static boolean isLevelCoveredByScreen() { + return minecraft.screen != null && ((DuckScreen) minecraft.screen).dynamic_fps$rendersBackground(); + } + private static void showNotification(String titleTranslationKey, String iconPath) { if (!DynamicFPSConfig.INSTANCE.batteryTracker().notifications()) { return; @@ -263,7 +266,7 @@ private static void checkForStateChanges() { checkForStateChanges0(); } else { // Schedule check for the beginning of the next frame - minecraft.schedule(DynamicFPSMod::checkForStateChanges0); + minecraft.tell(DynamicFPSMod::checkForStateChanges0); } } diff --git a/platforms/common/src/main/java/dynamic_fps/impl/compat/ClothConfig.java b/platforms/common/src/main/java/dynamic_fps/impl/compat/ClothConfig.java index 130314ca..13871faf 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/compat/ClothConfig.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/compat/ClothConfig.java @@ -17,7 +17,6 @@ import me.shedaniel.clothconfig2.impl.builders.SubCategoryBuilder; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.screens.Screen; -import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundSource; @@ -64,7 +63,7 @@ public static Screen genConfigScreen(Screen parent) { ); general.addEntry( - entryBuilder.startTextDescription(CommonComponents.SPACE).build() + entryBuilder.startTextDescription(Component.literal(" ")).build() ); general.addEntry( @@ -94,7 +93,7 @@ public static Screen genConfigScreen(Screen parent) { ); general.addEntry( - entryBuilder.startTextDescription(CommonComponents.SPACE).build() + entryBuilder.startTextDescription(Component.literal(" ")).build() ); VariableStepTransformer volumeTransformer = getVolumeStepTransformer(); @@ -126,7 +125,7 @@ public static Screen genConfigScreen(Screen parent) { ); general.addEntry( - entryBuilder.startTextDescription(CommonComponents.SPACE).build() + entryBuilder.startTextDescription(Component.literal(" ")).build() ); BatteryTrackerConfig batteryTracker = config.batteryTracker(); 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 0c3bb626..67f1f5e7 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 @@ -31,7 +31,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); + minecraft.tell(minecraft.mouseHandler::grabMouse); } } diff --git a/platforms/common/src/main/java/dynamic_fps/impl/config/option/BatteryIndicatorPlacement.java b/platforms/common/src/main/java/dynamic_fps/impl/config/option/BatteryIndicatorPlacement.java index be6234a5..3158092a 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/config/option/BatteryIndicatorPlacement.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/config/option/BatteryIndicatorPlacement.java @@ -1,15 +1,15 @@ package dynamic_fps.impl.config.option; -import net.minecraft.client.gui.GuiGraphics; +import com.mojang.blaze3d.platform.Window; /** * Screen corner to render the battery indicator in. */ public enum BatteryIndicatorPlacement { - TOP_LEFT(graphics -> new int[] {4, 4}), - TOP_RIGHT(graphics -> new int[] {graphics.guiWidth() - 47, 4}), - BOTTOM_LEFT(graphics -> new int[] {4, graphics.guiHeight() - 20}), - BOTTOM_RIGHT(graphics -> new int[] {graphics.guiWidth() - 47, graphics.guiHeight() - 20}); + TOP_LEFT(window -> new int[] {4, 4}), + TOP_RIGHT(window -> new int[] {window.getGuiScaledWidth() - 47, 4}), + BOTTOM_LEFT(window -> new int[] {4, window.getGuiScaledHeight() - 20}), + BOTTOM_RIGHT(window -> new int[] {window.getGuiScaledWidth() - 47, window.getGuiScaledHeight() - 20}); private final DynamicPlacement placement; @@ -17,12 +17,12 @@ public enum BatteryIndicatorPlacement { this.placement = placement; } - public int[] get(GuiGraphics graphics) { - return this.placement.get(graphics); + public int[] get(Window window) { + return this.placement.get(window); } @FunctionalInterface private interface DynamicPlacement { - int[] get(GuiGraphics graphics); + int[] get(Window window); } } diff --git a/platforms/common/src/main/java/dynamic_fps/impl/config/option/IdleCondition.java b/platforms/common/src/main/java/dynamic_fps/impl/config/option/IdleCondition.java index eec4ac24..cc96914f 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/config/option/IdleCondition.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/config/option/IdleCondition.java @@ -2,6 +2,5 @@ public enum IdleCondition { NONE, - VANILLA, ON_BATTERY; } diff --git a/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/BaseToast.java b/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/BaseToast.java index a37d9e1e..6df8851e 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/BaseToast.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/BaseToast.java @@ -1,12 +1,12 @@ package dynamic_fps.impl.feature.battery; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; import dynamic_fps.impl.util.ResourceLocations; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiComponent; import net.minecraft.client.gui.components.toasts.Toast; -import net.minecraft.client.gui.components.toasts.ToastManager; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.gui.components.toasts.ToastComponent; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.NotNull; @@ -14,12 +14,13 @@ public class BaseToast implements Toast { private long firstRender; - private Visibility visibility; protected Component title; protected Component description; protected @Nullable ResourceLocation icon; + private static final Minecraft MINECRAFT = Minecraft.getInstance(); + private static final ResourceLocation MOD_ICON = ResourceLocations.of("dynamic_fps", "textures/battery/toast/background_icon.png"); private static final ResourceLocation BACKGROUND_IMAGE = ResourceLocations.of("dynamic_fps", "textures/battery/toast/background.png"); @@ -28,47 +29,34 @@ protected BaseToast(Component title, Component description, @Nullable ResourceLo this.description = description; this.icon = icon; - - this.visibility = Visibility.SHOW; } @Override - public @NotNull Visibility getWantedVisibility() { - return this.visibility; - } - - @Override - public void update(ToastManager toastManager, long currentTime) { - if (this.firstRender == 0) { - return; - } - - if (currentTime - this.firstRender >= 5000.0 * toastManager.getNotificationDisplayTimeMultiplier()) { - this.visibility = Visibility.HIDE; - } - } - - @Override - public void render(GuiGraphics graphics, Font font, long currentTime) { + public @NotNull Visibility render(PoseStack poseStack, ToastComponent toastComponent, long currentTime) { if (this.firstRender == 0) { this.onFirstRender(); this.firstRender = currentTime; } - // type, resource, x, y, ?, ?, width, height, width, height - graphics.blit(RenderType::guiTextured, BACKGROUND_IMAGE, 0, 0, 0.0f, 0, this.width(), this.height(), this.width(), this.height()); + RenderSystem.setShaderTexture(0, BACKGROUND_IMAGE); + // resource, x, y, z, ?, ?, width, height, width, height + GuiComponent.blit(poseStack, 0, 0, 0.0f, 0.0f, this.width(), this.height(), this.width(), this.height()); int x = 8; if (this.icon != null) { x += 22; - graphics.blit(RenderType::guiTextured, MOD_ICON, 2, 2, 0.0f, 0, 8, 8, 8, 8); - graphics.blit(RenderType::guiTextured, this.icon, 8, 8, 0.0f, 0, 16, 16, 16, 16); + RenderSystem.setShaderTexture(0, MOD_ICON); + GuiComponent.blit(poseStack, 2, 2, 0.0f, 0.0f, 8, 8, 8, 8); + RenderSystem.setShaderTexture(0, this.icon); + GuiComponent.blit(poseStack, 8, 8, 0.0f, 0.0f, 16, 16, 16, 16); } - graphics.drawString(Minecraft.getInstance().font, this.title, x, 7, 0x5f3315, false); - graphics.drawString(Minecraft.getInstance().font, this.description, x, 18, -16777216, false); + MINECRAFT.font.draw(poseStack, this.title, x, 7, 0x5f3315); + MINECRAFT.font.draw(poseStack, this.description, x, 17, -16777216); + + return currentTime - this.firstRender >= 5000.0 ? Toast.Visibility.HIDE : Toast.Visibility.SHOW; } public void onFirstRender() {} diff --git a/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/BatteryToast.java b/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/BatteryToast.java index 4d2427cf..591c0876 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/BatteryToast.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/BatteryToast.java @@ -1,6 +1,7 @@ package dynamic_fps.impl.feature.battery; import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; @@ -10,7 +11,7 @@ public class BatteryToast extends BaseToast { private static BatteryToast queuedToast; private BatteryToast(Component title, ResourceLocation icon) { - super(title, Component.empty(), icon); + super(title, CommonComponents.EMPTY, icon); } /** @@ -23,7 +24,7 @@ public static void queueToast(Component title, ResourceLocation icon) { queuedToast.icon = icon; } else { queuedToast = new BatteryToast(title, icon); - Minecraft.getInstance().getToastManager().addToast(queuedToast); + Minecraft.getInstance().getToasts().addToast(queuedToast); } } 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..df6bf05b 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 @@ -72,7 +72,7 @@ public static void init() { } } else { manager = temp; // Keep around to allow updating batteries - Thread.ofVirtual().name("refresh-battery").start(BatteryTracker::updateBatteries); + new Thread(BatteryTracker::updateBatteries, "refresh-battery").start(); } } @@ -105,7 +105,7 @@ private static void updateState() { changed = true; int current = charge; - minecraft.schedule(() -> DynamicFPSMod.onBatteryChargeChanged(current, newCharge)); + minecraft.tell(() -> DynamicFPSMod.onBatteryChargeChanged(current, newCharge)); } if (readInitialData && status != newStatus) { @@ -113,7 +113,7 @@ private static void updateState() { State current = status; State updated = newStatus; - minecraft.schedule(() -> DynamicFPSMod.onBatteryStatusChanged(current, updated)); + minecraft.tell(() -> DynamicFPSMod.onBatteryStatusChanged(current, updated)); } charge = newCharge; @@ -141,7 +141,7 @@ private static void updateBatteries() { updateState(); try { - Thread.sleep(updateInterval); + Thread.sleep(updateInterval.toMillis()); } catch (InterruptedException e) { active = false; Thread.currentThread().interrupt(); diff --git a/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/ErrorToast.java b/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/ErrorToast.java index a827e2a2..1767e394 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/ErrorToast.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/ErrorToast.java @@ -17,6 +17,6 @@ private ErrorToast(Component description) { */ public static void queueToast(Component description) { ErrorToast toast = new ErrorToast(description); - Minecraft.getInstance().getToastManager().addToast(toast); + Minecraft.getInstance().getToasts().addToast(toast); } } diff --git a/platforms/common/src/main/java/dynamic_fps/impl/feature/state/OptionHolder.java b/platforms/common/src/main/java/dynamic_fps/impl/feature/state/OptionHolder.java index b4e4501a..e9e1130a 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/feature/state/OptionHolder.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/feature/state/OptionHolder.java @@ -4,7 +4,7 @@ import net.minecraft.client.CloudStatus; import net.minecraft.client.GraphicsStatus; import net.minecraft.client.Options; -import net.minecraft.server.level.ParticleStatus; +import net.minecraft.client.ParticleStatus; /* * Helper for saving, overriding, and re-applying vanilla options. diff --git a/platforms/common/src/main/java/dynamic_fps/impl/mixin/FramerateLimitTrackerMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/FramerateLimitTrackerMixin.java deleted file mode 100644 index c0cb1077..00000000 --- a/platforms/common/src/main/java/dynamic_fps/impl/mixin/FramerateLimitTrackerMixin.java +++ /dev/null @@ -1,99 +0,0 @@ -package dynamic_fps.impl.mixin; - -import com.mojang.blaze3d.platform.FramerateLimitTracker; -import dynamic_fps.impl.Constants; -import dynamic_fps.impl.DynamicFPSMod; -import dynamic_fps.impl.PowerState; -import dynamic_fps.impl.config.DynamicFPSConfig; -import dynamic_fps.impl.config.option.IdleCondition; -import net.minecraft.client.Minecraft; -import net.minecraft.client.Options; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(FramerateLimitTracker.class) -public class FramerateLimitTrackerMixin { - @Shadow - @Final - private Options options; - - @Shadow - @Final - private Minecraft minecraft; - - @Shadow - private int framerateLimit; - - @Inject(method = "getFramerateLimit", at = @At("HEAD"), cancellable = true) - private void getFramerateLimit(CallbackInfoReturnable callbackInfo) { - PowerState state = DynamicFPSMod.powerState(); - - if (state != PowerState.FOCUSED) { - // Instruct Minecraft to render a minimum of 15 FPS - // Going lower here makes resuming again feel sluggish - callbackInfo.setReturnValue(Math.max(this.getFramerateTarget(), 15)); - } else { - IdleCondition condition = DynamicFPSConfig.INSTANCE.idle().condition(); - - // Bypass all the vanilla idle checking code - // Note: If Dynamic FPS thinks the user is idle the power state would be different above - if (condition != IdleCondition.VANILLA) { - // Since we're bypassing the idle checking code we also need to set the menu FPS here as it's bundled now - if (isInLevel() || !DynamicFPSConfig.INSTANCE.uncapMenuFrameRate()) { - callbackInfo.setReturnValue(this.framerateLimit); - } else { - callbackInfo.setReturnValue(this.getMenuFramerateLimit()); - } - } - } - } - - /** - * Conditionally bypasses the main menu frame rate limit while using the vanilla idle code. - *

- * This is done in two cases: - * - The window is active, and the user wants to uncap the frame rate - * - The window is inactive, and the current FPS limit should be lower - */ - @Inject(method = "getFramerateLimit", at = @At(value = "CONSTANT", args = "intValue=60"), cancellable = true) - private void getMenuFramerateLimit(CallbackInfoReturnable callbackInfo) { - int limit = this.getFramerateTarget(); - - if (DynamicFPSMod.powerState() != PowerState.FOCUSED) { - // Vanilla returns 60 here - // Only overwrite if our current limit is lower - if (limit < 60) { - callbackInfo.setReturnValue(limit); - } - } else if (DynamicFPSConfig.INSTANCE.uncapMenuFrameRate()) { - callbackInfo.setReturnValue(this.getMenuFramerateLimit()); - } - } - - @Unique - private int getFramerateTarget() { - return DynamicFPSMod.targetFrameRate(); - } - - @Unique - private int getMenuFramerateLimit() { - if (this.options.enableVsync().get()) { - // VSync will regulate to a non-infinite value - return Constants.NO_FRAME_RATE_LIMIT; - } else { - // Even though the option "uncaps" the frame rate the limit is 250 FPS. - // Since otherwise this will just cause coil whine with no real benefit - return Math.min(this.framerateLimit, Constants.NO_FRAME_RATE_LIMIT - 10); - } - } - - @Unique - private boolean isInLevel() { - return this.minecraft.level != null || this.minecraft.screen == null && this.minecraft.getOverlay() == null; - } -} diff --git a/platforms/common/src/main/java/dynamic_fps/impl/mixin/MinecraftMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/MinecraftMixin.java index d0ada68b..51392611 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/mixin/MinecraftMixin.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/mixin/MinecraftMixin.java @@ -20,7 +20,7 @@ public class MinecraftMixin { @Shadow @Final - private Window window; + private Window window; @Shadow @Final @@ -36,4 +36,32 @@ private void setScreen(CallbackInfo callbackInfo) { IdleHandler.onActivity(); } + /** + * Conditionally bypasses the main menu frame rate limit. + * + * This is done in two cases: + * - The window is active, and the user wants to uncap the frame rate + * - The window is inactive, and the current FPS limit should be lower + */ + @Inject(method = "getFramerateLimit", at = @At(value = "CONSTANT", args = "intValue=60"), cancellable = true) + private void getFramerateLimit(CallbackInfoReturnable callbackInfo) { + int limit = this.window.getFramerateLimit(); + + if (DynamicFPSMod.powerState() != PowerState.FOCUSED) { + // Vanilla returns 60 here + // Only overwrite if our current limit is lower + if (limit < 60) { + callbackInfo.setReturnValue(limit); + } + } else if (DynamicFPSConfig.INSTANCE.uncapMenuFrameRate()) { + if (this.options.enableVsync().get()) { + // VSync will regulate to a non-infinite value + callbackInfo.setReturnValue(Constants.NO_FRAME_RATE_LIMIT); + } else { + // Even though the option "uncaps" the frame rate the limit is 250 FPS. + // Since otherwise this will just cause coil whine with no real benefit + callbackInfo.setReturnValue(Math.min(limit, Constants.NO_FRAME_RATE_LIMIT - 10)); + } + } + } } diff --git a/platforms/common/src/main/java/dynamic_fps/impl/mixin/ScreenMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/ScreenMixin.java new file mode 100644 index 00000000..7f39e351 --- /dev/null +++ b/platforms/common/src/main/java/dynamic_fps/impl/mixin/ScreenMixin.java @@ -0,0 +1,50 @@ +package dynamic_fps.impl.mixin; + +import dynamic_fps.impl.service.ModCompat; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import dynamic_fps.impl.util.duck.DuckScreen; +import net.minecraft.client.gui.screens.Screen; + +@Mixin(Screen.class) +public class ScreenMixin implements DuckScreen { + @Unique + private boolean dynamic_fps$canOptimize = false; + + @Unique + private boolean dynamic_fps$hasOptedOut = false; + + @Override + public boolean dynamic_fps$rendersBackground() { + return dynamic_fps$canOptimize; + } + + @Override + public void dynamic_fps$setRendersBackground() { + this.dynamic_fps$canOptimize = true; + } + + @Inject(method = "init", at = @At("HEAD")) + private void onInit(CallbackInfo callbackInfo) { + String name = this.getClass().getName(); + + this.dynamic_fps$hasOptedOut = ModCompat.getInstance().isScreenOptedOut(name); + + // Allow other mods to opt out on behalf of vanilla screens + // That Dynamic FPS forced to opt in via its own mod metadata. + if (!this.dynamic_fps$hasOptedOut) { + this.dynamic_fps$canOptimize = ModCompat.getInstance().isScreenOptedIn(name); + } + } + + @Inject(method = "renderDirtBackground", at = @At("HEAD")) + private void onRenderDirtBackground(CallbackInfo callbackInfo) { + if (!this.dynamic_fps$hasOptedOut) { + this.dynamic_fps$canOptimize = true; // Signal to apply optimizations on next frame + } + } +} diff --git a/platforms/common/src/main/java/dynamic_fps/impl/mixin/StatsScreenMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/StatsScreenMixin.java new file mode 100644 index 00000000..92b1b5ac --- /dev/null +++ b/platforms/common/src/main/java/dynamic_fps/impl/mixin/StatsScreenMixin.java @@ -0,0 +1,17 @@ +package dynamic_fps.impl.mixin; + +import dynamic_fps.impl.util.duck.DuckScreen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.gui.screens.achievement.StatsScreen; + +@Mixin(StatsScreen.class) +public class StatsScreenMixin { + @Inject(method = "onStatsUpdated", at = @At("HEAD")) + private void onStatsUpdated(CallbackInfo callbackInfo) { + ((DuckScreen) this).dynamic_fps$setRendersBackground(); + } +} diff --git a/platforms/common/src/main/java/dynamic_fps/impl/mixin/ToastManagerMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/ToastComponentMixin.java similarity index 58% rename from platforms/common/src/main/java/dynamic_fps/impl/mixin/ToastManagerMixin.java rename to platforms/common/src/main/java/dynamic_fps/impl/mixin/ToastComponentMixin.java index 7a3eaf4c..52368925 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/mixin/ToastManagerMixin.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/mixin/ToastComponentMixin.java @@ -1,17 +1,17 @@ package dynamic_fps.impl.mixin; -import net.minecraft.client.gui.components.toasts.ToastManager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import dynamic_fps.impl.DynamicFPSMod; +import net.minecraft.client.gui.components.toasts.ToastComponent; -@Mixin(ToastManager.class) -public class ToastManagerMixin { - @Inject(method = "freeSlotCount", at = @At("HEAD"), cancellable = true) - private void freeSlotCount(CallbackInfoReturnable callbackInfo) { +@Mixin(ToastComponent.class) +public class ToastComponentMixin { + @Inject(method = "freeSlots", at = @At("HEAD"), cancellable = true) + private void hasFreeSlots(CallbackInfoReturnable callbackInfo) { if (!DynamicFPSMod.shouldShowToasts()) { callbackInfo.setReturnValue(0); } diff --git a/platforms/common/src/main/java/dynamic_fps/impl/mixin/WindowMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/WindowMixin.java new file mode 100644 index 00000000..6dfcfd9f --- /dev/null +++ b/platforms/common/src/main/java/dynamic_fps/impl/mixin/WindowMixin.java @@ -0,0 +1,28 @@ +package dynamic_fps.impl.mixin; + +import dynamic_fps.impl.PowerState; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import com.mojang.blaze3d.platform.Window; + +import dynamic_fps.impl.DynamicFPSMod; + +@Mixin(Window.class) +public class WindowMixin { + /** + * Sets a frame rate limit while we're cancelling some or all rendering. + */ + @Inject(method = "getFramerateLimit", at = @At("RETURN"), cancellable = true) + private void onGetFramerateLimit(CallbackInfoReturnable callbackInfo) { + PowerState state = DynamicFPSMod.powerState(); + + if (state != PowerState.FOCUSED) { + // Instruct Minecraft to render a minimum of 15 FPS + // Going lower here makes resuming again feel sluggish + callbackInfo.setReturnValue(Math.max(DynamicFPSMod.targetFrameRate(), 15)); + } + } +} diff --git a/platforms/common/src/main/java/dynamic_fps/impl/service/ModCompat.java b/platforms/common/src/main/java/dynamic_fps/impl/service/ModCompat.java index dea57fdf..bbfdbc53 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/service/ModCompat.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/service/ModCompat.java @@ -1,10 +1,23 @@ package dynamic_fps.impl.service; +import java.util.Set; + public interface ModCompat { boolean isDisabled(); boolean disableOverlayOptimization(); + Set getOptedInScreens(); + Set getOptedOutScreens(); + + default boolean isScreenOptedIn(String className) { + return getOptedInScreens().contains(className); + } + + default boolean isScreenOptedOut(String className) { + return getOptedOutScreens().contains(className); + } + static ModCompat getInstance() { return Services.MOD_COMPAT; } diff --git a/platforms/common/src/main/java/dynamic_fps/impl/util/FallbackConfigScreen.java b/platforms/common/src/main/java/dynamic_fps/impl/util/FallbackConfigScreen.java index 99f5532b..eee14038 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/util/FallbackConfigScreen.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/util/FallbackConfigScreen.java @@ -1,7 +1,7 @@ package dynamic_fps.impl.util; +import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.CommonComponents; @@ -32,14 +32,15 @@ protected void init() { } @Override - public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTicks) { - super.render(guiGraphics, mouseX, mouseY, partialTicks); + public void render(PoseStack poseStack, int mouseX, int mouseY, float partialTicks) { + this.renderDirtBackground(0); + super.render(poseStack, mouseX, mouseY, partialTicks); - int width = guiGraphics.guiWidth() / 2; - int height = guiGraphics.guiHeight() / 3; + int width = this.width / 2; + int height = this.height / 3; - guiGraphics.drawCenteredString(this.font, WARNING_0.getVisualOrderText(), width, height, 0xFFFFFF); - guiGraphics.drawCenteredString(this.font, WARNING_1.getVisualOrderText(), width, height + 10, 0xFFFFFF); + drawCenteredString(poseStack, this.font, WARNING_0.getVisualOrderText(), width, height, 0xFFFFFF); + drawCenteredString(poseStack, this.font, WARNING_1.getVisualOrderText(), width, height + 10, 0xFFFFFF); } @Override diff --git a/platforms/common/src/main/java/dynamic_fps/impl/util/HudInfoRenderer.java b/platforms/common/src/main/java/dynamic_fps/impl/util/HudInfoRenderer.java index e6f91e18..470d5737 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/util/HudInfoRenderer.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/util/HudInfoRenderer.java @@ -1,11 +1,12 @@ package dynamic_fps.impl.util; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; import dynamic_fps.impl.config.BatteryTrackerConfig; import dynamic_fps.impl.config.DynamicFPSConfig; import dynamic_fps.impl.feature.battery.BatteryTracker; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.gui.GuiComponent; import net.minecraft.network.chat.Component; import static dynamic_fps.impl.util.Localization.localized; @@ -17,30 +18,30 @@ public final class HudInfoRenderer { private static final Minecraft minecraft = Minecraft.getInstance(); - public static void renderInfo(GuiGraphics guiGraphics) { + public static void renderInfo(PoseStack poseStack) { if (minecraft.options.hideGui || minecraft.screen != null) { return; } if (DynamicFPSConfig.INSTANCE.batteryTracker().enabled()) { - drawBatteryOverlay(guiGraphics); + drawBatteryOverlay(poseStack); } if (DynamicFPSMod.disabledByUser()) { - drawCenteredText(guiGraphics, localized("gui", "hud.disabled")); + drawCenteredText(poseStack, localized("gui", "hud.disabled")); } else if (DynamicFPSMod.isForcingLowFPS()) { - drawCenteredText(guiGraphics, localized("gui", "hud.reducing")); + drawCenteredText(poseStack, localized("gui", "hud.reducing")); } } - private static void drawCenteredText(GuiGraphics guiGraphics, Component component) { - int width = guiGraphics.guiWidth() / 2; + private static void drawCenteredText(PoseStack poseStack, Component component) { + int width = minecraft.getWindow().getGuiScaledWidth() / 2; - guiGraphics.drawCenteredString(minecraft.font, component, width, 32, 0xFFFFFF); + GuiComponent.drawCenteredString(poseStack, minecraft.font, component, width, 32, 0xFFFFFF); } - private static void drawBatteryOverlay(GuiGraphics graphics) { - if (minecraft.getDebugOverlay().showDebugScreen() || !BatteryTracker.hasBatteries()) { + private static void drawBatteryOverlay(PoseStack poseStack) { + if (minecraft.options.renderDebug || !BatteryTracker.hasBatteries()) { return; } @@ -55,11 +56,12 @@ private static void drawBatteryOverlay(GuiGraphics graphics) { ResourceLocation icon = ResourceLocations.of("dynamic_fps", "textures/battery/icon/" + type + "_" + index + ".png"); // pair of coordinates - int[] position = config.placement().get(graphics); + int[] position = config.placement().get(minecraft.getWindow()); + RenderSystem.setShaderTexture(0, icon); // resource, x, y, z, ?, ?, width, height, width, height - graphics.blit(RenderType::guiTextured, icon, position[0], position[1], 0.0f, 0, 16, 16, 16, 16); + GuiComponent.blit(poseStack, position[0], position[1], 0, 0.0f, 0.0f, 16, 16, 16, 16); // font, text, x, y, text color - graphics.drawString(minecraft.font, BatteryTracker.charge() + "%", position[0] + 20, position[1] + 4, 0xFFFFFF); + GuiComponent.drawString(poseStack, minecraft.font, BatteryTracker.charge() + "%", position[0] + 20, position[1] + 4, 0xFFFFFF); } } diff --git a/platforms/common/src/main/java/dynamic_fps/impl/util/ModCompatHelper.java b/platforms/common/src/main/java/dynamic_fps/impl/util/ModCompatHelper.java new file mode 100644 index 00000000..7e629913 --- /dev/null +++ b/platforms/common/src/main/java/dynamic_fps/impl/util/ModCompatHelper.java @@ -0,0 +1,40 @@ +package dynamic_fps.impl.util; + +import dynamic_fps.impl.service.ModCompat; +import dynamic_fps.impl.service.Platform; + +import java.util.Optional; + +public class ModCompatHelper { + public static void init() { + fixFastloadSoftLock(); + } + + /** + * Fix softlock in combination with Fastload <=3.4.0 due to our screen / loading overlay optimization. + * + * See the issue report for more info. + */ + private static void fixFastloadSoftLock() { + Optional optional = Platform.getInstance().getModVersion("fastload"); + + if (optional.isEmpty()) { + return; + } + + Version other; + + try { + other = Version.of("3.4.0"); + } catch (Version.VersionParseException e) { + throw new RuntimeException(e); + } + + // If a version below 3.4.0 is present opt their custom world loading screen out of our optimization + if (optional.get().compareTo(other) <= 0) { + ModCompat.getInstance().getOptedOutScreens().add( + "io.github.bumblesoftware.fastload.client.BuildingTerrainScreen" + ); + } + } +} diff --git a/platforms/common/src/main/java/dynamic_fps/impl/util/ResourceLocations.java b/platforms/common/src/main/java/dynamic_fps/impl/util/ResourceLocations.java index 45e40b8d..c9f0ab50 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/util/ResourceLocations.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/util/ResourceLocations.java @@ -4,6 +4,6 @@ public class ResourceLocations { public static ResourceLocation of(String namespace, String path) { - return ResourceLocation.fromNamespaceAndPath(namespace, path); + return new ResourceLocation(namespace, path); } } diff --git a/platforms/common/src/main/java/dynamic_fps/impl/util/VariableStepTransformer.java b/platforms/common/src/main/java/dynamic_fps/impl/util/VariableStepTransformer.java index 93bef45f..dc94e8bc 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/util/VariableStepTransformer.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/util/VariableStepTransformer.java @@ -1,6 +1,7 @@ package dynamic_fps.impl.util; import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -13,9 +14,11 @@ public class VariableStepTransformer { private boolean unsorted; private final List steps; + private final List reversedSteps; public VariableStepTransformer() { this.steps = new ArrayList<>(); + this.reversedSteps = new ArrayList<>(); } /** @@ -27,6 +30,7 @@ public VariableStepTransformer() { public void addStep(int change, int max) { this.unsorted = true; this.steps.add(new Step(change, max)); + this.reversedSteps.add(new Step(change, max)); } /** @@ -42,7 +46,7 @@ public int toStep(int value) { int currentChange = 0; int currentValue = value; - for (Step pair : this.steps.reversed()) { + for (Step pair : this.reversedSteps) { if (currentValue > pair.max && currentChange != 0) { step += Math.floorDiv(currentValue - pair.max, currentChange); currentValue = pair.max; @@ -86,6 +90,14 @@ public int compare(Step self, Step other) { return Integer.compare(self.max, other.max); } }); + + this.reversedSteps.sort(new Comparator() { + @Override + public int compare(Step self, Step other) { + return Integer.compare(self.max, other.max); + } + }); + Collections.reverse(this.reversedSteps); } private record Step(int change, int max) {} diff --git a/platforms/common/src/main/java/dynamic_fps/impl/util/duck/DuckScreen.java b/platforms/common/src/main/java/dynamic_fps/impl/util/duck/DuckScreen.java new file mode 100644 index 00000000..fe72fe3d --- /dev/null +++ b/platforms/common/src/main/java/dynamic_fps/impl/util/duck/DuckScreen.java @@ -0,0 +1,11 @@ +package dynamic_fps.impl.util.duck; + +public interface DuckScreen { + default boolean dynamic_fps$rendersBackground() { + throw new RuntimeException("No implementation for dynamic_fps$rendersBackground was found."); + } + + default void dynamic_fps$setRendersBackground() { + throw new RuntimeException("No implementation for dynamic_fps$rendersBackground was found."); + } +} diff --git a/platforms/common/src/main/resources/assets/dynamic_fps/data/default_config.json b/platforms/common/src/main/resources/assets/dynamic_fps/data/default_config.json index 36ccd02d..0f1f9798 100644 --- a/platforms/common/src/main/resources/assets/dynamic_fps/data/default_config.json +++ b/platforms/common/src/main/resources/assets/dynamic_fps/data/default_config.json @@ -3,7 +3,7 @@ "uncap_menu_frame_rate": false, "idle": { "timeout": 300, - "condition": "vanilla" + "condition": "on_battery" }, "battery_tracker": { "enabled": false, diff --git a/platforms/common/src/main/resources/dynamic_fps-common.mixins.json b/platforms/common/src/main/resources/dynamic_fps-common.mixins.json index f930e0a4..913c8808 100644 --- a/platforms/common/src/main/resources/dynamic_fps-common.mixins.json +++ b/platforms/common/src/main/resources/dynamic_fps-common.mixins.json @@ -4,14 +4,16 @@ "minVersion": "0.8", "client": [ "DebugScreenOverlayMixin", - "FramerateLimitTrackerMixin", "GameRendererMixin", "GuiMixin", "LoadingOverlayMixin", "MinecraftMixin", "OptionsMixin", + "ScreenMixin", "SoundEngineMixin", - "ToastManagerMixin", + "StatsScreenMixin", + "ToastComponentMixin", + "WindowMixin", "bugfix.BlockableEventLoopMixin" ], "mixins": [], diff --git a/platforms/fabric/src/main/resources/fabric.mod.json b/platforms/fabric/src/main/resources/fabric.mod.json index 47e5e59b..4e98b40a 100644 --- a/platforms/fabric/src/main/resources/fabric.mod.json +++ b/platforms/fabric/src/main/resources/fabric.mod.json @@ -70,7 +70,7 @@ }, "depends": { "fabricloader": ">=0.15.10", - "minecraft": ">=1.21.2", + "minecraft": "=1.19.3", "mixinextras": ">=0.3.2", "fabric-resource-loader-v0": "*", "fabric-lifecycle-events-v1": "*" @@ -88,5 +88,43 @@ "dynamic_fps-common.mixins.json", "dynamic_fps-textile.mixins.json" ], - "accessWidener": "dynamic_fps.accesswidener" + "accessWidener": "dynamic_fps.accesswidener", + "custom": { + "dynamic_fps": { + "optimized_screens": { + "enabled": [ + "net.minecraft.class_4189", + "net.minecraft.class_404", + "net.minecraft.class_426", + "net.minecraft.class_4288", + "net.minecraft.class_6777", + "net.minecraft.class_443", + "net.minecraft.class_446", + "net.minecraft.class_445", + "net.minecraft.class_6599" + ], + "disabled": [ + "net.minecraft.class_434" + ], + "_comment": { + "_0": "Mojang mapping names of the enabled / disabled screens.", + "_1": "Sorted by fully qualified name. Translation not needed for mod screens.", + "enabled": { + "net.minecraft.class_4189": "net.minecraft.client.gui.screens.AccessibilityOptionsScreen", + "net.minecraft.class_404": "net.minecraft.client.gui.screens.ChatOptionsScreen", + "net.minecraft.class_426": "net.minecraft.client.gui.screens.LanguageSelectScreen", + "net.minecraft.class_4288": "net.minecraft.client.gui.screens.MouseSettingsScreen", + "net.minecraft.class_6777": "net.minecraft.client.gui.screens.OnlineOptionsScreen", + "net.minecraft.class_443": "net.minecraft.client.gui.screens.SoundOptionsScreen", + "net.minecraft.class_446": "net.minecraft.client.gui.screens.VideoSettingsScreen", + "net.minecraft.class_445": "net.minecraft.client.gui.screens.WinScreen", + "net.minecraft.class_6599": "net.minecraft.client.gui.screens.controls.KeyBindsScreen" + }, + "disabled": { + "net.minecraft.class_434": "net.minecraft.client.gui.screens.ReceivingLevelScreen" + } + } + } + } + } } diff --git a/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/DynamicFPSForgeMod.java b/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/DynamicFPSForgeMod.java index db9c02bf..17979516 100644 --- a/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/DynamicFPSForgeMod.java +++ b/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/DynamicFPSForgeMod.java @@ -3,9 +3,11 @@ import dynamic_fps.impl.Constants; import dynamic_fps.impl.DynamicFPSMod; import dynamic_fps.impl.service.Platform; +import dynamic_fps.impl.util.HudInfoRenderer; import dynamic_fps.impl.util.KeyMappingHandler; import net.minecraftforge.client.ConfigScreenHandler; import net.minecraftforge.client.event.RegisterKeyMappingsEvent; +import net.minecraftforge.client.event.RenderGuiOverlayEvent; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.TickEvent; import net.minecraftforge.fml.ModLoadingContext; @@ -20,14 +22,14 @@ public class DynamicFPSForgeMod { private static final List TICK_EVENT_LISTENERS = new ArrayList<>(); - public DynamicFPSForgeMod(FMLJavaModLoadingContext context) { + public DynamicFPSForgeMod() { if (FMLLoader.getDist().isDedicatedServer()) { return; } DynamicFPSMod.init(); - context.registerExtensionPoint( + ModLoadingContext.get().registerExtensionPoint( ConfigScreenHandler.ConfigScreenFactory.class, () -> new ConfigScreenHandler.ConfigScreenFactory( (minecraft, screen) -> DynamicFPSMod.getConfigScreen(screen) @@ -35,16 +37,14 @@ public DynamicFPSForgeMod(FMLJavaModLoadingContext context) { ); MinecraftForge.EVENT_BUS.addListener(this::onClientTick); - // MinecraftForge.EVENT_BUS.addListener(this::renderGuiOverlay); + MinecraftForge.EVENT_BUS.addListener(this::renderGuiOverlay); - context.getModEventBus().addListener(this::registerKeyMappings); - } + FMLJavaModLoadingContext.get().getModEventBus().addListener(this::registerKeyMappings); + } - /* public void renderGuiOverlay(RenderGuiOverlayEvent event) { - HudInfoRenderer.renderInfo(event.getGuiGraphics()); + HudInfoRenderer.renderInfo(event.getPoseStack()); } - */ public void registerKeyMappings(RegisterKeyMappingsEvent event) { for (KeyMappingHandler handler : KeyMappingHandler.getHandlers()) { diff --git a/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/mixin/GuiMixin.java b/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/mixin/GuiMixin.java deleted file mode 100644 index 67ae3396..00000000 --- a/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/mixin/GuiMixin.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.lostluma.dynamic_fps.impl.forge.mixin; - -import com.llamalad7.mixinextras.sugar.Local; -import dynamic_fps.impl.util.HudInfoRenderer; -import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.GuiGraphics; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(Gui.class) -public class GuiMixin { - /** - * Render info on whether Dynamic FPS is disabled or always reducing the user's FPS. - */ - @Inject(method = "renderSavingIndicator", at = @At("HEAD")) - private void renderSavingIndicator(CallbackInfo callbackInfo, @Local(argsOnly = true) GuiGraphics guiGraphics) { - HudInfoRenderer.renderInfo(guiGraphics); - } -} diff --git a/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/service/ForgeModCompat.java b/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/service/ForgeModCompat.java index 4f47fadb..814c28eb 100644 --- a/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/service/ForgeModCompat.java +++ b/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/service/ForgeModCompat.java @@ -1,9 +1,23 @@ package net.lostluma.dynamic_fps.impl.forge.service; +import com.electronwill.nightconfig.core.CommentedConfig; import dynamic_fps.impl.service.ModCompat; +import net.minecraft.client.gui.screens.ReceivingLevelScreen; import net.minecraftforge.fml.ModList; +import net.minecraftforge.forgespi.language.IModInfo; + +import java.util.HashSet; +import java.util.Set; public class ForgeModCompat implements ModCompat { + private static boolean disableOverlayOptimization = false; + private static final Set optedOutScreens = new HashSet<>(); + + static { + optedOutScreens.add(ReceivingLevelScreen.class.getCanonicalName()); + ModList.get().getMods().forEach(ForgeModCompat::parseModMetadata); + } + @Override public boolean isDisabled() { return false; @@ -11,6 +25,30 @@ public boolean isDisabled() { @Override public boolean disableOverlayOptimization() { - return ModList.get().isLoaded("rrls"); + return disableOverlayOptimization || ModList.get().isLoaded("rrls"); + } + + @Override + public Set getOptedInScreens() { + return Set.of(); + } + + @Override + public Set getOptedOutScreens() { + return optedOutScreens; + } + + private static void parseModMetadata(IModInfo modInfo) { + Object config = modInfo.getModProperties().get("dynamic_fps"); + + if (config == null) { + return; + } + + Boolean value = ((CommentedConfig) config).get("optimized_overlay"); + + if (value != null && !value) { + disableOverlayOptimization = true; + } } } diff --git a/platforms/forge/src/main/resources/META-INF/mods.toml b/platforms/forge/src/main/resources/META-INF/mods.toml index 6b3a1eda..65c3e81b 100644 --- a/platforms/forge/src/main/resources/META-INF/mods.toml +++ b/platforms/forge/src/main/resources/META-INF/mods.toml @@ -85,6 +85,6 @@ file="META-INF/accesstransformer.cfg" [[dependencies.dynamic_fps]] modId = "minecraft" mandatory = true -versionRange = "[1.21.2,)" +versionRange = "[1.19.3]" ordering = "NONE" side = "CLIENT" diff --git a/platforms/forge/src/main/resources/dynamic_fps.mixins.json b/platforms/forge/src/main/resources/dynamic_fps.mixins.json index 6d185a3e..68796ed4 100644 --- a/platforms/forge/src/main/resources/dynamic_fps.mixins.json +++ b/platforms/forge/src/main/resources/dynamic_fps.mixins.json @@ -2,9 +2,7 @@ "required": true, "package": "net.lostluma.dynamic_fps.impl.forge.mixin", "minVersion": "0.8", - "client": [ - "GuiMixin" - ], + "client": [], "mixins": [], "server": [], "injectors": { diff --git a/platforms/neoforge/src/main/java/net/lostluma/dynamic_fps/impl/neoforge/DynamicFPSNeoForgeMod.java b/platforms/neoforge/src/main/java/net/lostluma/dynamic_fps/impl/neoforge/DynamicFPSNeoForgeMod.java index 3f1cb0d5..e0832aa8 100644 --- a/platforms/neoforge/src/main/java/net/lostluma/dynamic_fps/impl/neoforge/DynamicFPSNeoForgeMod.java +++ b/platforms/neoforge/src/main/java/net/lostluma/dynamic_fps/impl/neoforge/DynamicFPSNeoForgeMod.java @@ -8,9 +8,9 @@ import net.neoforged.fml.ModLoadingContext; import net.neoforged.fml.common.Mod; import net.neoforged.fml.loading.FMLLoader; +import net.neoforged.neoforge.client.ConfigScreenHandler; import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent; import net.neoforged.neoforge.client.event.RenderGuiEvent; -import net.neoforged.neoforge.client.gui.IConfigScreenFactory; import net.neoforged.neoforge.common.NeoForge; @Mod(Constants.MOD_ID) @@ -23,8 +23,10 @@ public DynamicFPSNeoForgeMod(IEventBus modEventBus) { DynamicFPSMod.init(); ModLoadingContext.get().registerExtensionPoint( - IConfigScreenFactory.class, - () -> (minecraft, screen) -> DynamicFPSMod.getConfigScreen(screen) + ConfigScreenHandler.ConfigScreenFactory.class, + () -> new ConfigScreenHandler.ConfigScreenFactory( + (minecraft, screen) -> DynamicFPSMod.getConfigScreen(screen) + ) ); modEventBus.addListener(this::registerKeyMappings); diff --git a/platforms/neoforge/src/main/java/net/lostluma/dynamic_fps/impl/neoforge/service/NeoForgeModCompat.java b/platforms/neoforge/src/main/java/net/lostluma/dynamic_fps/impl/neoforge/service/NeoForgeModCompat.java index 7496aa3a..62735115 100644 --- a/platforms/neoforge/src/main/java/net/lostluma/dynamic_fps/impl/neoforge/service/NeoForgeModCompat.java +++ b/platforms/neoforge/src/main/java/net/lostluma/dynamic_fps/impl/neoforge/service/NeoForgeModCompat.java @@ -2,13 +2,19 @@ import com.electronwill.nightconfig.core.CommentedConfig; import dynamic_fps.impl.service.ModCompat; +import net.minecraft.client.gui.screens.ReceivingLevelScreen; import net.neoforged.fml.ModList; import net.neoforged.neoforgespi.language.IModInfo; +import java.util.HashSet; +import java.util.Set; + public class NeoForgeModCompat implements ModCompat { private static boolean disableOverlayOptimization = false; + private static final Set optedOutScreens = new HashSet<>(); static { + optedOutScreens.add(ReceivingLevelScreen.class.getCanonicalName()); ModList.get().getMods().forEach(NeoForgeModCompat::parseModMetadata); } @@ -22,6 +28,16 @@ public boolean disableOverlayOptimization() { return disableOverlayOptimization || ModList.get().isLoaded("rrls"); } + @Override + public Set getOptedInScreens() { + return Set.of(); + } + + @Override + public Set getOptedOutScreens() { + return optedOutScreens; + } + private static void parseModMetadata(IModInfo modInfo) { Object config = modInfo.getModProperties().get("dynamic_fps"); diff --git a/platforms/neoforge/src/main/java/net/lostluma/dynamic_fps/impl/neoforge/service/NeoForgePlatform.java b/platforms/neoforge/src/main/java/net/lostluma/dynamic_fps/impl/neoforge/service/NeoForgePlatform.java index 08f5b43e..fd4eef6c 100644 --- a/platforms/neoforge/src/main/java/net/lostluma/dynamic_fps/impl/neoforge/service/NeoForgePlatform.java +++ b/platforms/neoforge/src/main/java/net/lostluma/dynamic_fps/impl/neoforge/service/NeoForgePlatform.java @@ -7,8 +7,8 @@ import net.neoforged.fml.ModList; import net.neoforged.fml.loading.FMLLoader; import net.neoforged.fml.loading.FMLPaths; -import net.neoforged.neoforge.client.event.ClientTickEvent; import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.event.TickEvent; import java.io.IOException; import java.nio.file.Files; @@ -61,7 +61,7 @@ public Optional getModVersion(String modId) { @Override public void registerStartTickEvent(StartTickEvent event) { - NeoForge.EVENT_BUS.addListener(ClientTickEvent.Pre.class, (unused) -> event.onStartTick()); + NeoForge.EVENT_BUS.addListener(TickEvent.ClientTickEvent.class, (unused) -> event.onStartTick()); } private Path ensureDir(Path path) { diff --git a/platforms/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/platforms/neoforge/src/main/resources/META-INF/mods.toml similarity index 97% rename from platforms/neoforge/src/main/resources/META-INF/neoforge.mods.toml rename to platforms/neoforge/src/main/resources/META-INF/mods.toml index 5daef2be..892d4df4 100644 --- a/platforms/neoforge/src/main/resources/META-INF/neoforge.mods.toml +++ b/platforms/neoforge/src/main/resources/META-INF/mods.toml @@ -85,6 +85,6 @@ file="META-INF/accesstransformer.cfg" [[dependencies.dynamic_fps]] modId = "minecraft" mandatory = true -versionRange = "[1.21.2,)" +versionRange = "[1.20.2,1.20.4]" ordering = "NONE" side = "CLIENT" diff --git a/platforms/quilt/src/main/resources/quilt.mod.json b/platforms/quilt/src/main/resources/quilt.mod.json index 7ad45af2..1a01a492 100644 --- a/platforms/quilt/src/main/resources/quilt.mod.json +++ b/platforms/quilt/src/main/resources/quilt.mod.json @@ -81,7 +81,7 @@ }, { "id": "minecraft", - "versions": ">=1.21.2" + "versions": "=1.19.3" }, { "id": "mixinextras", @@ -115,5 +115,41 @@ "dynamic_fps-common.mixins.json", "dynamic_fps-textile.mixins.json" ], - "access_widener": "dynamic_fps.accesswidener" + "access_widener": "dynamic_fps.accesswidener", + "dynamic_fps": { + "optimized_screens": { + "enabled": [ + "net.minecraft.class_4189", + "net.minecraft.class_404", + "net.minecraft.class_426", + "net.minecraft.class_4288", + "net.minecraft.class_6777", + "net.minecraft.class_443", + "net.minecraft.class_446", + "net.minecraft.class_445", + "net.minecraft.class_6599" + ], + "disabled": [ + "net.minecraft.class_434" + ], + "_comment": { + "_0": "Mojang mapping names of the enabled / disabled screens.", + "_1": "Sorted by fully qualified name. Translation not needed for mod screens.", + "enabled": { + "net.minecraft.class_4189": "net.minecraft.client.gui.screens.AccessibilityOptionsScreen", + "net.minecraft.class_404": "net.minecraft.client.gui.screens.ChatOptionsScreen", + "net.minecraft.class_426": "net.minecraft.client.gui.screens.LanguageSelectScreen", + "net.minecraft.class_4288": "net.minecraft.client.gui.screens.MouseSettingsScreen", + "net.minecraft.class_6777": "net.minecraft.client.gui.screens.OnlineOptionsScreen", + "net.minecraft.class_443": "net.minecraft.client.gui.screens.SoundOptionsScreen", + "net.minecraft.class_446": "net.minecraft.client.gui.screens.VideoSettingsScreen", + "net.minecraft.class_445": "net.minecraft.client.gui.screens.WinScreen", + "net.minecraft.class_6599": "net.minecraft.client.gui.screens.controls.KeyBindsScreen" + }, + "disabled": { + "net.minecraft.class_434": "net.minecraft.client.gui.screens.ReceivingLevelScreen" + } + } + } + } } diff --git a/platforms/textile/src/main/java/net/lostluma/dynamic_fps/impl/textile/mixin/GuiMixin.java b/platforms/textile/src/main/java/net/lostluma/dynamic_fps/impl/textile/mixin/GuiMixin.java index 31bcb2a5..a8c170b6 100644 --- a/platforms/textile/src/main/java/net/lostluma/dynamic_fps/impl/textile/mixin/GuiMixin.java +++ b/platforms/textile/src/main/java/net/lostluma/dynamic_fps/impl/textile/mixin/GuiMixin.java @@ -1,9 +1,9 @@ package net.lostluma.dynamic_fps.impl.textile.mixin; import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.blaze3d.vertex.PoseStack; import dynamic_fps.impl.util.HudInfoRenderer; import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.GuiGraphics; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -14,8 +14,14 @@ public class GuiMixin { /** * Render info on whether Dynamic FPS is disabled or always reducing the user's FPS. */ - @Inject(method = "renderSavingIndicator", at = @At("HEAD")) - private void renderSavingIndicator(CallbackInfo callbackInfo, @Local(argsOnly = true) GuiGraphics guiGraphics) { - HudInfoRenderer.renderInfo(guiGraphics); + @Inject( + method = "render", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/gui/Gui;renderSavingIndicator(Lcom/mojang/blaze3d/vertex/PoseStack;)V" + ) + ) + private void renderSavingIndicator(CallbackInfo callbackInfo, @Local(argsOnly = true) PoseStack poseStack) { + HudInfoRenderer.renderInfo(poseStack); } } diff --git a/platforms/textile/src/main/java/net/lostluma/dynamic_fps/impl/textile/service/TextileModCompat.java b/platforms/textile/src/main/java/net/lostluma/dynamic_fps/impl/textile/service/TextileModCompat.java index 58e699bc..e4396623 100644 --- a/platforms/textile/src/main/java/net/lostluma/dynamic_fps/impl/textile/service/TextileModCompat.java +++ b/platforms/textile/src/main/java/net/lostluma/dynamic_fps/impl/textile/service/TextileModCompat.java @@ -2,15 +2,22 @@ import dynamic_fps.impl.service.ModCompat; import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.MappingResolver; import net.fabricmc.loader.api.ModContainer; import net.fabricmc.loader.api.metadata.CustomValue; import net.fabricmc.loader.api.metadata.ModMetadata; import net.lostluma.dynamic_fps.impl.textile.compat.FREX; import org.jetbrains.annotations.Nullable; +import java.util.HashSet; +import java.util.Set; + public class TextileModCompat implements ModCompat { private static boolean disableOverlayOptimization = false; + private static final Set optedInScreens = new HashSet<>(); + private static final Set optedOutScreens = new HashSet<>(); + static { FabricLoader.getInstance().getAllMods().forEach(TextileModCompat::parseModMetadata); } @@ -25,6 +32,16 @@ public boolean disableOverlayOptimization() { return disableOverlayOptimization; } + @Override + public Set getOptedInScreens() { + return optedInScreens; + } + + @Override + public Set getOptedOutScreens() { + return optedOutScreens; + } + private static void parseModMetadata(ModContainer mod) { CustomValue.CvObject root; ModMetadata data = mod.getMetadata(); @@ -36,6 +53,9 @@ private static void parseModMetadata(ModContainer mod) { } parseOverlayOverride(root.get("optimized_overlay")); + + parseScreenOverrides(root.get("optimized_screens"), "enabled", optedInScreens); + parseScreenOverrides(root.get("optimized_screens"), "disabled", optedOutScreens); } private static void parseOverlayOverride(@Nullable CustomValue value) { @@ -43,4 +63,25 @@ private static void parseOverlayOverride(@Nullable CustomValue value) { disableOverlayOptimization = true; } } + + private static void parseScreenOverrides(@Nullable CustomValue parent, String type, Set set) { + if (parent == null || parent.getType() != CustomValue.CvType.OBJECT) { + return; + } + + CustomValue values = parent.getAsObject().get(type); + + if (values == null || values.getType() != CustomValue.CvType.ARRAY) { + return; + } + + MappingResolver resolver = FabricLoader.getInstance().getMappingResolver(); + + values.getAsArray().forEach(value -> { + if (value.getType() == CustomValue.CvType.STRING) { + // Translate from intermediary to runtime names for vanilla screens + set.add(resolver.mapClassName("intermediary", value.getAsString())); + } + }); + } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 34562df9..cb576658 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -18,6 +18,6 @@ includeBuild("build-logic") include(":platforms:common") include(":platforms:fabric") include(":platforms:forge") -include(":platforms:neoforge") +// include(":platforms:neoforge") include(":platforms:quilt") include(":platforms:textile")