From fcce4b467670c170592bb53e5512a9dbd713cc28 Mon Sep 17 00:00:00 2001 From: LostLuma Date: Mon, 24 Jun 2024 21:35:27 +0200 Subject: [PATCH] Minecraft 1.18.0 backport --- .../main/kotlin/dynamic_fps.java.gradle.kts | 4 +- gradle.properties | 8 +-- gradle/libs.versions.toml | 12 ++--- .../java/dynamic_fps/impl/DynamicFPSMod.java | 12 ++++- .../dynamic_fps/impl/compat/ClothConfig.java | 20 +++---- .../option/BatteryIndicatorPlacement.java | 16 +++--- .../impl/feature/battery/BatteryToast.java | 21 +++++--- .../impl/feature/battery/BatteryTracker.java | 4 +- .../impl/feature/state/OptionHolder.java | 41 +++++++------- .../impl/mixin/GameRendererMixin.java | 3 ++ .../impl/mixin/MinecraftMixin.java | 2 +- .../dynamic_fps/impl/mixin/ScreenMixin.java | 50 ++++++++++++++++++ .../impl/mixin/StatsScreenMixin.java | 17 ++++++ .../impl/mixin/ToastComponentMixin.java | 14 +++-- .../dynamic_fps/impl/service/ModCompat.java | 13 +++++ .../impl/util/FallbackConfigScreen.java | 24 +++++---- .../impl/util/HudInfoRenderer.java | 29 +++++----- .../dynamic_fps/impl/util/Localization.java | 3 +- .../java/dynamic_fps/impl/util/Logging.java | 6 +-- .../impl/util/ModCompatHelper.java | 40 ++++++++++++++ .../impl/util/ResourceLocations.java | 2 +- .../impl/util/VariableStepTransformer.java | 14 ++++- .../impl/util/duck/DuckScreen.java | 11 ++++ .../resources/dynamic_fps-common.mixins.json | 2 + platforms/fabric/build.gradle | 8 +-- .../fabric/src/main/resources/fabric.mod.json | 46 +++++++++++++++- platforms/forge/build.gradle | 10 ++-- .../impl/forge/DynamicFPSForgeMod.java | 20 +++---- .../impl/forge/mixin/GameRendererMixin.java | 39 ++++++++++++++ .../impl/forge/mixin/GuiMixin.java | 20 +++++++ .../impl/forge/service/ForgeModCompat.java | 40 +++++++++++++- .../impl/forge/service/ForgePlatform.java | 16 +++++- .../src/main/resources/META-INF/mods.toml | 4 +- .../main/resources/dynamic_fps.mixins.json | 5 +- .../forge/src/main/resources/dynamic_fps.png | Bin 0 -> 6871 bytes platforms/neoforge/build.gradle | 8 +-- platforms/neoforge/gradle.properties | 2 + .../impl/neoforge/DynamicFPSNeoForgeMod.java | 9 ++-- .../neoforge/service/NeoForgeModCompat.java | 16 ++++++ .../neoforge/service/NeoForgePlatform.java | 4 +- .../{neoforge.mods.toml => mods.toml} | 2 +- platforms/quilt/build.gradle | 8 +-- .../quilt/src/main/resources/quilt.mod.json | 42 ++++++++++++++- .../impl/textile/mixin/GameRendererMixin.java | 23 ++++++++ .../impl/textile/mixin/GuiMixin.java | 14 +++-- .../textile/service/TextileModCompat.java | 41 ++++++++++++++ .../resources/dynamic_fps-textile.mixins.json | 1 + settings.gradle.kts | 4 +- 48 files changed, 594 insertions(+), 156 deletions(-) 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 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 create mode 100644 platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/mixin/GameRendererMixin.java create mode 100644 platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/mixin/GuiMixin.java create mode 100644 platforms/forge/src/main/resources/dynamic_fps.png rename platforms/neoforge/src/main/resources/META-INF/{neoforge.mods.toml => mods.toml} (98%) create mode 100644 platforms/textile/src/main/java/net/lostluma/dynamic_fps/impl/textile/mixin/GameRendererMixin.java 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 b09ac9ee..57725949 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.0 +minecraft_version = 1.18.0 # Version for publishing -minecraft_version_min = 1.21 -minecraft_version_max = 1.21 +minecraft_version_min = 1.18 +minecraft_version_max = 1.18.2 -enabled_platforms=fabric,neoforge,quilt +enabled_platforms=fabric,forge,quilt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 31be607d..547b9016 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,14 +1,14 @@ [versions] -minecraft = "1.21" +minecraft = "1.18.2" # Platform libraries fabric_loader = "0.15.10" -fabric_api = "0.100.1+1.21" +fabric_api = "0.77.0+1.18.2" -forge = "1.20.4-49.0.30" +forge = "1.18.2-40.2.17" -neoforge = "21.0.0-beta" +neoforge = "20.4.237" quilt_loader = "0.25.0" @@ -18,8 +18,8 @@ battery = "1.1.0" # Modding libraries -modmenu = "11.0.0-beta.1" -cloth_config = "15.0.127" +modmenu = "3.2.5" +cloth_config = "6.2.57" 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 76ce8a60..b85a8f8e 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/DynamicFPSMod.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/DynamicFPSMod.java @@ -14,12 +14,14 @@ import dynamic_fps.impl.util.FallbackConfigScreen; import dynamic_fps.impl.util.Logging; import dynamic_fps.impl.feature.state.OptionHolder; +import dynamic_fps.impl.util.ModCompatHelper; 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; @@ -174,7 +176,7 @@ public static boolean shouldShowToasts() { } public static boolean shouldShowLevels() { - return isDisabled() || !isLevelCoveredByOverlay(); + return isDisabled() || !(isLevelCoveredByScreen() || isLevelCoveredByOverlay()); } public static void onBatteryChargeChanged(int before, int after) { @@ -196,11 +198,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; @@ -243,7 +251,7 @@ public static void handleStateChange(PowerState previous, PowerState current) { } // The FOCUSED config doesn't have the user's actual vsync preference sadly ... - boolean enableVsync = current != PowerState.FOCUSED ? config.enableVsync() : minecraft.options.enableVsync().get(); + boolean enableVsync = current != PowerState.FOCUSED ? config.enableVsync() : minecraft.options.enableVsync; if (enableVsync != before.enableVsync()) { minecraft.getWindow().updateVsync(enableVsync); 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 48eea474..0bc12ae4 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 @@ -19,6 +19,8 @@ import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.sounds.SoundSource; import java.util.Locale; @@ -64,7 +66,7 @@ public static Screen genConfigScreen(Screen parent) { ); general.addEntry( - entryBuilder.startTextDescription(CommonComponents.SPACE).build() + entryBuilder.startTextDescription(new TextComponent(" ")).build() ); general.addEntry( @@ -93,7 +95,7 @@ public static Screen genConfigScreen(Screen parent) { ); general.addEntry( - entryBuilder.startTextDescription(CommonComponents.SPACE).build() + entryBuilder.startTextDescription(new TextComponent(" ")).build() ); VariableStepTransformer volumeTransformer = getVolumeStepTransformer(); @@ -125,7 +127,7 @@ public static Screen genConfigScreen(Screen parent) { ); general.addEntry( - entryBuilder.startTextDescription(CommonComponents.SPACE).build() + entryBuilder.startTextDescription(new TextComponent(" ")).build() ); BatteryTrackerConfig batteryTracker = config.batteryTracker(); @@ -219,7 +221,7 @@ public static Screen genConfigScreen(Screen parent) { category.addEntry( entryBuilder.startBooleanToggle( - Component.translatable("options.vsync"), + new TranslatableComponent("options.vsync"), instance.enableVsync() ) .setDefaultValue(standard.enableVsync()) @@ -239,7 +241,7 @@ public static Screen genConfigScreen(Screen parent) { volumes.add( entryBuilder.startIntSlider( - Component.translatable("soundCategory." + name), + new TranslatableComponent("soundCategory." + name), (int) (instance.rawVolumeMultiplier(source) * 100), 0, 100 ) @@ -335,7 +337,7 @@ private static Component volumeTransitionMessage(int step) { int value = getVolumeStepTransformer().toValue(step); if (value <= 300) { - return Component.literal(value + "%"); + return new TranslatableComponent(value + "%"); } else { return localized("config", "volume_transition_speed_instant"); } @@ -357,14 +359,14 @@ private static Component fpsTargetMessage(int step) { int fps = getFpsTransformer().toValue(step); if (fps != Constants.NO_FRAME_RATE_LIMIT) { - return Component.translatable("options.framerate", fps); + return new TranslatableComponent("options.framerate", fps); } else { - return Component.translatable("options.framerateLimit.max"); + return new TranslatableComponent("options.framerateLimit.max"); } } private static Component volumeMultiplierMessage(int value) { - return Component.literal(Integer.toString(value) + "%"); + return new TranslatableComponent(Integer.toString(value) + "%"); } public static Component IdleConditionMessage(Enum state) { 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/feature/battery/BatteryToast.java b/platforms/common/src/main/java/dynamic_fps/impl/feature/battery/BatteryToast.java index 93ee1c16..cdef4fa2 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,8 +1,10 @@ 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.GuiGraphics; +import net.minecraft.client.gui.GuiComponent; import net.minecraft.client.gui.components.toasts.Toast; import net.minecraft.client.gui.components.toasts.ToastComponent; import net.minecraft.network.chat.Component; @@ -43,7 +45,7 @@ public static void queueToast(Component title, ResourceLocation icon) { } @Override - public @NotNull Visibility render(GuiGraphics graphics, ToastComponent toastComponent, long currentTime) { + public @NotNull Visibility render(PoseStack poseStack, ToastComponent toastComponent, long currentTime) { if (this.firstRender == 0) { if (this == queuedToast) { queuedToast = null; @@ -54,15 +56,18 @@ public static void queueToast(Component title, ResourceLocation icon) { this.description = localized("toast", "battery_charge", BatteryTracker.charge()); } + RenderSystem.setShaderTexture(0, BACKGROUND_IMAGE); // resource, x, y, z, ?, ?, width, height, width, height - graphics.blit(BACKGROUND_IMAGE, 0, 0, 0, 0.0f, 0.0f, this.width(), this.height(), this.width(), this.height()); + GuiComponent.blit(poseStack, 0, 0, 0, 0.0f, 0.0f, this.width(), this.height(), this.width(), this.height()); - graphics.blit(MOD_ICON, 2, 2, 0, 0.0f, 0.0f, 8, 8, 8, 8); - graphics.blit(this.icon, 8, 8, 0, 0.0f, 0.0f, 16, 16, 16, 16); + RenderSystem.setShaderTexture(0, MOD_ICON); + GuiComponent.blit(poseStack, 2, 2, 0, 0.0f, 0.0f, 8, 8, 8, 8); + RenderSystem.setShaderTexture(0, this.icon); + GuiComponent.blit(poseStack, 8, 8, 0, 0.0f, 0.0f, 16, 16, 16, 16); - graphics.drawString(toastComponent.getMinecraft().font, this.title, 30, 7, 0x5f3315, false); - graphics.drawString(toastComponent.getMinecraft().font, this.description, 30, 18, -16777216, false); + GuiComponent.drawString(poseStack, toastComponent.getMinecraft().font, this.title, 30, 7, 0x5f3315); + GuiComponent.drawString(poseStack, toastComponent.getMinecraft().font, this.description, 30, 18, -16777216); - return currentTime - this.firstRender >= 5000.0 * toastComponent.getNotificationDisplayTimeMultiplier() ? Toast.Visibility.HIDE : Toast.Visibility.SHOW; + return currentTime - this.firstRender >= 5000.0 ? Toast.Visibility.HIDE : Toast.Visibility.SHOW; } } 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 483a6d5a..62b15d27 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 @@ -58,7 +58,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(); } } @@ -127,7 +127,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/state/OptionHolder.java b/platforms/common/src/main/java/dynamic_fps/impl/feature/state/OptionHolder.java index e9e1130a..38c657b5 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 @@ -1,6 +1,7 @@ package dynamic_fps.impl.feature.state; import dynamic_fps.impl.config.option.GraphicsState; +import net.minecraft.client.AmbientOcclusionStatus; import net.minecraft.client.CloudStatus; import net.minecraft.client.GraphicsStatus; import net.minecraft.client.Options; @@ -14,10 +15,10 @@ public class OptionHolder { private static CloudStatus cloudStatus; private static GraphicsStatus graphicsStatus; - private static boolean ambientOcclusion; + private static AmbientOcclusionStatus ambientOcclusion; private static ParticleStatus particlesStatus; private static boolean entityShadows; - private static double entityDistance; + private static float entityDistance; /* * Create an in-memory copy of current vanilla graphics options. @@ -25,12 +26,12 @@ public class OptionHolder { * This MUST be called while graphics options have not been changed yet. */ public static void copyOptions(Options options) { - cloudStatus = options.getCloudsType(); - graphicsStatus = options.graphicsMode().get(); - ambientOcclusion = options.ambientOcclusion().get(); - particlesStatus = options.particles().get(); - entityShadows = options.entityShadows().get(); - entityDistance = options.entityDistanceScaling().get(); + cloudStatus = options.renderClouds; + graphicsStatus = options.graphicsMode; + ambientOcclusion = options.ambientOcclusion; + particlesStatus = options.particles; + entityShadows = options.entityShadows; + entityDistance = options.entityDistanceScaling; } /* @@ -38,21 +39,21 @@ public static void copyOptions(Options options) { */ public static void applyOptions(Options options, GraphicsState state) { if (state == GraphicsState.DEFAULT) { - options.cloudStatus().set(cloudStatus); - options.graphicsMode().set(graphicsStatus); - options.ambientOcclusion().set(ambientOcclusion); - options.particles().set(particlesStatus); - options.entityShadows().set(entityShadows); - options.entityDistanceScaling().set(entityDistance); + options.renderClouds = cloudStatus; + options.graphicsMode = graphicsStatus; + options.ambientOcclusion = ambientOcclusion; + options.particles = particlesStatus; + options.entityShadows = entityShadows; + options.entityDistanceScaling = entityDistance; } else { // state == GraphicsState.REDUCED - options.cloudStatus().set(CloudStatus.OFF); - options.particles().set(ParticleStatus.MINIMAL); - options.entityShadows().set(false); - options.entityDistanceScaling().set(0.5); + options.renderClouds = CloudStatus.OFF; + options.particles = ParticleStatus.MINIMAL; + options.entityShadows = false; + options.entityDistanceScaling = 0.5f; if (state == GraphicsState.MINIMAL) { - options.graphicsMode().set(GraphicsStatus.FAST); - options.ambientOcclusion().set(false); + options.graphicsMode = GraphicsStatus.FAST; + options.ambientOcclusion = AmbientOcclusionStatus.OFF; } } } diff --git a/platforms/common/src/main/java/dynamic_fps/impl/mixin/GameRendererMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/GameRendererMixin.java index 43c2b9cc..7f5d8593 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/mixin/GameRendererMixin.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/mixin/GameRendererMixin.java @@ -19,6 +19,8 @@ public class GameRendererMixin { * Note: Inject after the pause on lost focus check, * This allows the feature to work even at zero FPS. */ + /* + Moved to individual platform impl due to old Forge versions ... @ModifyExpressionValue( method = "render", at = @At( @@ -30,6 +32,7 @@ public class GameRendererMixin { private boolean skipRendering(boolean original) { return original || !DynamicFPSMod.checkForRender(); } + */ /** * Cancels rendering the world if it is determined to currently not be visible. 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 9afc56f0..f1bfb219 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 @@ -54,7 +54,7 @@ private void getFramerateLimit(CallbackInfoReturnable callbackInfo) { callbackInfo.setReturnValue(limit); } } else if (DynamicFPSConfig.INSTANCE.uncapMenuFrameRate()) { - if (this.options.enableVsync().get()) { + if (this.options.enableVsync) { // VSync will regulate to a non-infinite value callbackInfo.setReturnValue(Constants.NO_FRAME_RATE_LIMIT); } else { 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/ToastComponentMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/ToastComponentMixin.java index 52368925..03f2694b 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/mixin/ToastComponentMixin.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/mixin/ToastComponentMixin.java @@ -1,19 +1,23 @@ package dynamic_fps.impl.mixin; +import java.util.Deque; + 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 org.spongepowered.asm.mixin.injection.Redirect; import dynamic_fps.impl.DynamicFPSMod; +import net.minecraft.client.gui.components.toasts.Toast; import net.minecraft.client.gui.components.toasts.ToastComponent; @Mixin(ToastComponent.class) public class ToastComponentMixin { - @Inject(method = "freeSlots", at = @At("HEAD"), cancellable = true) - private void hasFreeSlots(CallbackInfoReturnable callbackInfo) { + @Redirect(method = "render", at = @At(value = "INVOKE", target = "Ljava/util/Deque;isEmpty()Z")) + private boolean onQueueIsEmpty(Deque queued) { if (!DynamicFPSMod.shouldShowToasts()) { - callbackInfo.setReturnValue(0); + return true; + } else { + return queued.isEmpty(); } } } 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..1a47054a 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,20 +1,21 @@ 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; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TranslatableComponent; public class FallbackConfigScreen extends Screen { private final Screen parent; - private static final Component WARNING_0 = Component.translatable("config.dynamic_fps.warn_cloth_config.0"); - private static final Component WARNING_1 = Component.translatable("config.dynamic_fps.warn_cloth_config.1"); + private static final Component WARNING_0 = new TranslatableComponent("config.dynamic_fps.warn_cloth_config.0"); + private static final Component WARNING_1 = new TranslatableComponent("config.dynamic_fps.warn_cloth_config.1"); public FallbackConfigScreen(Screen parent) { - super(Component.translatable("config.dynamic_fps.title")); + super(new TranslatableComponent("config.dynamic_fps.title")); this.parent = parent; } @@ -27,19 +28,20 @@ protected void init() { int y = this.height - height - 5; this.addRenderableWidget( - Button.builder(CommonComponents.GUI_BACK, button -> this.onClose()).bounds(x, y, width, height).build() + new Button(x, y, width, height, CommonComponents.GUI_BACK, button -> this.onClose()) ); } @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 35e472db..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,10 +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.gui.GuiComponent; import net.minecraft.network.chat.Component; import static dynamic_fps.impl.util.Localization.localized; @@ -16,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; } @@ -54,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(icon, position[0], position[1], 0, 0.0f, 0.0f, 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/Localization.java b/platforms/common/src/main/java/dynamic_fps/impl/util/Localization.java index bd3d95e0..1476a5dd 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/util/Localization.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/util/Localization.java @@ -3,6 +3,7 @@ import dynamic_fps.impl.Constants; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.TranslatableComponent; public final class Localization { /** e.g. keyString("title", "config") -> "title.dynamic_fps.config") */ @@ -11,7 +12,7 @@ public static String translationKey(String domain, String path) { } public static MutableComponent localized(String domain, String path, Object... args) { - return Component.translatable(translationKey(domain, path), args); + return new TranslatableComponent(translationKey(domain, path), args); } private Localization() {} diff --git a/platforms/common/src/main/java/dynamic_fps/impl/util/Logging.java b/platforms/common/src/main/java/dynamic_fps/impl/util/Logging.java index f510adfb..a0911c62 100644 --- a/platforms/common/src/main/java/dynamic_fps/impl/util/Logging.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/util/Logging.java @@ -1,11 +1,11 @@ package dynamic_fps.impl.util; import dynamic_fps.impl.Constants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; public class Logging { - private static final Logger logger = LoggerFactory.getLogger(Constants.MOD_ID); + private static final Logger logger = LogManager.getLogger(Constants.MOD_ID); public static Logger getLogger() { return logger; 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/dynamic_fps-common.mixins.json b/platforms/common/src/main/resources/dynamic_fps-common.mixins.json index b1453d3f..473d39e9 100644 --- a/platforms/common/src/main/resources/dynamic_fps-common.mixins.json +++ b/platforms/common/src/main/resources/dynamic_fps-common.mixins.json @@ -8,7 +8,9 @@ "GuiMixin", "LoadingOverlayMixin", "MinecraftMixin", + "ScreenMixin", "SoundEngineMixin", + "StatsScreenMixin", "ToastComponentMixin", "WindowMixin", "bugfix.BlockableEventLoopMixin" diff --git a/platforms/fabric/build.gradle b/platforms/fabric/build.gradle index 79505109..c8f4be2f 100644 --- a/platforms/fabric/build.gradle +++ b/platforms/fabric/build.gradle @@ -87,13 +87,11 @@ publishMods { accessToken = providers.environmentVariable("CURSEFORGE_SECRET") projectId = "335493" - /* minecraftVersionRange { start = project.property("minecraft_version_min").toString() end = project.property("minecraft_version_max").toString() } - */ - minecraftVersions.add(project.property("minecraft_version_min").toString()) + // minecraftVersions.add(project.property("minecraft_version_min").toString()) clientRequired = true serverRequired = false @@ -106,13 +104,11 @@ publishMods { accessToken = providers.environmentVariable("MODRINTH_SECRET") projectId = "LQ3K71Q1" - /* minecraftVersionRange { start = project.property("minecraft_version_min").toString() end = project.property("minecraft_version_max").toString() } - */ - minecraftVersions.add(project.property("minecraft_version_min").toString()) + // minecraftVersions.add(project.property("minecraft_version_min").toString()) requires("fabric-api") optional("cloth-config", "modmenu") diff --git a/platforms/fabric/src/main/resources/fabric.mod.json b/platforms/fabric/src/main/resources/fabric.mod.json index 4d0ecdcb..1c720f85 100644 --- a/platforms/fabric/src/main/resources/fabric.mod.json +++ b/platforms/fabric/src/main/resources/fabric.mod.json @@ -70,7 +70,11 @@ }, "depends": { "fabricloader": ">=0.15.10", - "minecraft": ">=1.21.0-alpha.24.20.a", + "minecraft": [ + "=1.18.0", + "=1.18.1", + "=1.18.2" + ], "mixinextras": ">=0.3.2", "fabric-resource-loader-v0": "*", "fabric-lifecycle-events-v1": "*" @@ -88,5 +92,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/build.gradle b/platforms/forge/build.gradle index b7e66a3e..2754737c 100644 --- a/platforms/forge/build.gradle +++ b/platforms/forge/build.gradle @@ -41,6 +41,8 @@ dependencies { include(libs.mixinextras.forge) implementation(libs.mixinextras.forge) + include(libs.battery) + common(project(path: ":platforms:common", configuration: "namedElements")) { transitive false } shadowCommon(project(path: ":platforms:common", configuration: "transformProductionForge")) { transitive = false } } @@ -86,13 +88,11 @@ publishMods { accessToken = providers.environmentVariable("CURSEFORGE_SECRET") projectId = "335493" - /* minecraftVersionRange { start = project.property("minecraft_version_min").toString() end = project.property("minecraft_version_max").toString() } - */ - minecraftVersions.add(project.property("minecraft_version_min").toString()) + // minecraftVersions.add(project.property("minecraft_version_min").toString()) clientRequired = true serverRequired = false @@ -104,13 +104,11 @@ publishMods { accessToken = providers.environmentVariable("MODRINTH_SECRET") projectId = "LQ3K71Q1" - /* minecraftVersionRange { start = project.property("minecraft_version_min").toString() end = project.property("minecraft_version_max").toString() } - */ - minecraftVersions.add(project.property("minecraft_version_min").toString()) + // minecraftVersions.add(project.property("minecraft_version_min").toString()) optional("cloth-config") } 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 f6f3e938..918d9c4c 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,15 +3,14 @@ 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.client.ClientRegistry; +import net.minecraftforge.client.ConfigGuiHandler; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.TickEvent; import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.loading.FMLLoader; @@ -30,25 +29,20 @@ public DynamicFPSForgeMod() { DynamicFPSMod.init(); ModLoadingContext.get().registerExtensionPoint( - ConfigScreenHandler.ConfigScreenFactory.class, - () -> new ConfigScreenHandler.ConfigScreenFactory( + ConfigGuiHandler.ConfigGuiFactory.class, + () -> new ConfigGuiHandler.ConfigGuiFactory( (minecraft, screen) -> DynamicFPSMod.getConfigScreen(screen) ) ); MinecraftForge.EVENT_BUS.addListener(this::onClientTick); - MinecraftForge.EVENT_BUS.addListener(this::renderGuiOverlay); FMLJavaModLoadingContext.get().getModEventBus().addListener(this::registerKeyMappings); } - public void renderGuiOverlay(RenderGuiOverlayEvent event) { - HudInfoRenderer.renderInfo(event.getGuiGraphics()); - } - - public void registerKeyMappings(RegisterKeyMappingsEvent event) { + public void registerKeyMappings(FMLClientSetupEvent event) { for (KeyMappingHandler handler : KeyMappingHandler.getHandlers()) { - event.register(handler.keyMapping()); + ClientRegistry.registerKeyBinding(handler.keyMapping()); } } diff --git a/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/mixin/GameRendererMixin.java b/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/mixin/GameRendererMixin.java new file mode 100644 index 00000000..3422af32 --- /dev/null +++ b/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/mixin/GameRendererMixin.java @@ -0,0 +1,39 @@ +package net.lostluma.dynamic_fps.impl.forge.mixin; + +import dynamic_fps.impl.DynamicFPSMod; +import net.minecraft.Util; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GameRenderer; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(GameRenderer.class) +public class GameRendererMixin { + @Shadow + @Final + private Minecraft minecraft; + + @Shadow + private long lastActiveTime; + + // Duplicate of common mixin w/o mixinextras and injected earlier + // Since the original just does not activate at all on Forge ...? + // We have to add the pause on lost focus feature ourselves sadly + @Inject(method = "render", at = @At("HEAD"), cancellable = true) + private void skipRendering(CallbackInfo callbackInfo) { + if (!DynamicFPSMod.checkForRender()) { + callbackInfo.cancel(); + + // Copy of vanilla code + if (this.minecraft.isWindowActive() || !this.minecraft.options.pauseOnLostFocus || this.minecraft.options.touchscreen && this.minecraft.mouseHandler.isRightPressed()) { + this.lastActiveTime = Util.getMillis(); + } else if (Util.getMillis() - this.lastActiveTime > 500L) { + this.minecraft.pauseGame(false); + } + } + } +} 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 new file mode 100644 index 00000000..b4d7305f --- /dev/null +++ b/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/mixin/GuiMixin.java @@ -0,0 +1,20 @@ +package net.lostluma.dynamic_fps.impl.forge.mixin; + +import com.mojang.blaze3d.vertex.PoseStack; +import dynamic_fps.impl.util.HudInfoRenderer; +import net.minecraftforge.client.gui.ForgeIngameGui; +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(ForgeIngameGui.class) +public class GuiMixin { + /** + * Render info on whether Dynamic FPS is disabled or always reducing the user's FPS. + */ + @Inject(method = "render", at = @At("HEAD")) + private void renderSavingIndicator(PoseStack poseStack, float partialTick, CallbackInfo ci) { + HudInfoRenderer.renderInfo(poseStack); + } +} 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/java/net/lostluma/dynamic_fps/impl/forge/service/ForgePlatform.java b/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/service/ForgePlatform.java index 74a7af9e..13be8a2b 100644 --- a/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/service/ForgePlatform.java +++ b/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/service/ForgePlatform.java @@ -2,6 +2,7 @@ import dynamic_fps.impl.Constants; import dynamic_fps.impl.service.Platform; +import dynamic_fps.impl.util.Version; import net.lostluma.dynamic_fps.impl.forge.DynamicFPSForgeMod; import net.minecraftforge.fml.ModContainer; import net.minecraftforge.fml.ModList; @@ -41,9 +42,20 @@ public boolean isModLoaded(String modId) { } @Override - public Optional getModVersion(String modId) { + public Optional getModVersion(String modId) { Optional optional = ModList.get().getModContainerById(modId); - return optional.map(modContainer -> modContainer.getModInfo().getVersion().toString()); + + if (optional.isEmpty()) { + return Optional.empty(); + } + + String raw = optional.get().getModInfo().getVersion().toString(); + + try { + return Optional.of(Version.of(raw)); + } catch (Version.VersionParseException e) { + throw new RuntimeException(e); + } } @Override diff --git a/platforms/forge/src/main/resources/META-INF/mods.toml b/platforms/forge/src/main/resources/META-INF/mods.toml index 11b8f613..96012e9b 100644 --- a/platforms/forge/src/main/resources/META-INF/mods.toml +++ b/platforms/forge/src/main/resources/META-INF/mods.toml @@ -10,7 +10,7 @@ version = "${version}" displayName = "Dynamic FPS" authors = "juliand665 & LostLuma" description = "Reduce resource usage while Minecraft is in the background or idle." -logoFile = "assets/dynamic_fps/textures/icon.png" +logoFile = "dynamic_fps.png" displayTest = "IGNORE_ALL_VERSION" credits = """ Thanks to: @@ -85,7 +85,7 @@ file="META-INF/accesstransformer.cfg" [[dependencies.dynamic_fps]] modId = "minecraft" mandatory = true -versionRange = "[1.20.0,1.20.4]" +versionRange = "[1.18.0,1.18.2]" 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 a5227ad4..7e14ebb3 100644 --- a/platforms/forge/src/main/resources/dynamic_fps.mixins.json +++ b/platforms/forge/src/main/resources/dynamic_fps.mixins.json @@ -2,7 +2,10 @@ "required": true, "package": "net.lostluma.dynamic_fps.impl.forge.mixin", "minVersion": "0.8", - "client": [], + "client": [ + "GameRendererMixin", + "GuiMixin" + ], "mixins": [], "server": [], "injectors": { diff --git a/platforms/forge/src/main/resources/dynamic_fps.png b/platforms/forge/src/main/resources/dynamic_fps.png new file mode 100644 index 0000000000000000000000000000000000000000..f282051920dd8187815d2c7347e9db3d1766fc9a GIT binary patch literal 6871 zcmV;|8Ytz7P)nLekmD8#tY-boY)MC zSWbKbnM5X&DZ*qjQEY}wV{;Rzl{ufJIvBeX z@cDzA;9#Rhje?uNLdJRUv_Pk*jeh|ipIS4%U9rQPT2TtaIak*T( zZ@u-_E5zd{XN zMS2uOF{<=eCNoZ*I@J|~ky{Mk3pL==ek6Yg8E8Hf4D|+iFTM2A^}K1wq!_3Is`O8u zJo%+y>G%KE3tsIf^5=7X;ujc)PJ=ml@??AZUV4mG0af|~)7QYG{Yw5Oq%rB%elL%{ z8vVco{C?|OZ@nd|fa(RJz4UhqmVVa@4dBvh!X2_k$nyEeYeCyO9Ae>sA^Xk%S!`opp7>C2LiPp#x8z~{m&IMHIPfJU?f|9ry zgn#Z9IJEj?z4GX!D8`Zv%A@mzW-we{FvEure~Q+sPFkX?3aHb*j6;VGH3p#<+u(Sm zHSAg=vZ09bSVT$RoGoCov$F^ATD+!e2LH!M&;1lKwSD{c59|3EW%v5ATcATgMHi^X!K)oNV^!oT_etdF;ZRckJ6VG?D< zb@UzmcmbHLTep52X)_q+tt1=AQN4=3aH^1Loc!F}+)*G5hX>ZTd!STn9kNVoC0lWx z$D!!%wFnGtrscGDW+csEn75Kiq(#I8o{xNOMOO9d)vw9P$r%B{@CD$gJ%JM07A0Cc zVOyceoIDnmzSbRvKLA4S)Tz@${E|pM8H}(;i5E$)%;&)917P?VIiiz6^FL3kwP?}e7OE`M0q7o& zXZOU36CV&&EGdG=i~<6^zz%DzsVLGqlU+DUWBGF@lh3S}7tvZ{G8nJddp0dCEuy!C zQt~ZiwFwg@JRYFt5(2UQ{;aI5Os)hGJZ2Pu(Js`y}V|h-V?~aOVIR>u>Q(9U&hi+Bjw={g|m;M&r@Gajh8Bd??D-7rr|ZhHk(x3}2l(b?*AB z&7jorTgd8d+qS(=59l@!Wz80a?qB%9C@{3X`|Gd2zBQuP&}swp1DmV$4=W{A8q41q zAkVX*InVl2V2&L-*2<(A40keFh0LM~G8Y7|mHYU)_x5hj2E!F1f-?t2jy4G94y@oH zDGoNj&SZ^}hKqv#H+VQXIr;K1&7j=%r;urzHf{P6gzoks|Gjac`|}3lacP?sV4P0p zc9Sy)ML4pxA;{MLVDB7&Bwvy+eztAfzN@FT?cK9&+qUo4wrv|@n{T`vqbIMvnEqlb z@~UfQ;)SE~;uq;2H#!A!@ZiDep@%{E zi1Vp`(V|7K<_+ZAf4eA{r>PsgO8UEc1!6CzzGaw4&rxd4N&z)y6|`jqfUQ7mIc*hJ zJ*uX4ZMHy~o0~U#9tIz-|LNy_1bZ^M6n#AfEmC{mD(`IAU03S_l9rbCnPI-$h*D!# zOSM@eH3qB__^<(U(13Yr=BUvFThFOquu~xRL9S!Lf(5V94}*cLXbJm2Y5drJXOC(v z%k8C^0%>SyScxB;VH`R|sWR)N+5)X?`c7;EZHM)U(FRWMT47IDW}`sz^Yg#sc^Cwb zbnheB-|1ex&wbC2>*c8JyWT0)hLx!m2;$gMcWMoa(aKKHrT<6oHg956(w zFk7X*z^H?9b-Lx#x!oca@2O|yWK62)2B~=055d%1%GUkCs>~T)vtc_jeWg+ zH&NI0lZ%3N+`VyK#z<#ovq12!AwCBTL(0u|DK|ST&}18J<`@gW{0`uqas6Mp{1j2% zGoJB`7bcHypOoZjmgm_A#Z9Q`Oly+zd)TYipmw;qvOpkpb#;r?ub9veK$J4GTguF? zB(QfX-_7q-c_+>~MJeM}myg^dy-l6GEb?W%;K>*3nU?47-Me=da{avtsa|+Y&AK}W za9zxYU-y*@{Nc(R#&bZFQnOb;iP>lM9-$8#Fz553;p-m4JZD?P`Qa1V!j-AooH)6zympSJFp}!7BDK-bB#Ow!BYz|s| z0Kj&9#sF<-vY$449lg(Lr{=yx(p7LvAe|kZ<)8Z0r|z-$5XajWzd;boy(y)m4y$>DKIBxfD_O} z`8p1c(^qj{eTsSaoRpI3=cRb!xxiXO_p82=#ZM+(8RCOrlst1*^37?>82}r&wy=hH zV(e#}F={st-1&@q*L8E$8uk@WxhRmnzP`5P+svm7@*o%`*PNF;a}G$ZxghYV8P~8D zFNltZz)YfZ!<>^c*4xr8kpKSozh+1mP~s23MbY5J%`ul;bPZw}ozt`2TyXwya(Z^_ zrJFow_|yhk9rSV*b5wcGKE=fmByl{|$#s z@rKYKl4a5)%UnwW8_-VoYr+_NbWF|Dewc8b-Xp2{Q8_=Abd+}w;-7{Cl4-Ie(_~mO z1vWH53_j2~#@Vam^mVOwuG3FH!cT~Z{Jx^vm6QthW24#4m5Q7aE*R}Lj-j^d~oU3x$ z*0s#3*-mZMADZ}yp{?RfOJ<6%EsORZxh|1)*G8xZdZ z4knjPm0UK}MBsxiPv#yP);YY@L-ucdVz9ila z2*@QSn2csC#* z7fgeYi>BVS34Pksq1s@Lr#9F_+Y?Vo%gHW*rl3l`-&u@=WB z%}z|uYGe;V4P*2PXHYAg8A=1)TeY}dAoz4qyc-aZbLNKJ4zzX9z9@kls@oH4BePMbCWTchJTNA1|{R^OpdJJ?ID^FaGU+S5I)(tEpK zAoj-bJLBDe6mrUR%4yRf1G=3WG5WBny*8lDeqX&_%NKKJ5YBOXT-=V6yV z2BeS^rcY9F()5O69ulkx)F-@kjQRV*uvYs8ze?~+s`kV$u1+DxO}`vBBGljnYzs7F z8uo;9M20hmeL5HPskwJ>FVk##od5-BKVj_W;_g*D$B*=qp>r zoEe^46$gyD@nfTf9~Vp9fB*e2k4M5DIdq@M!TUuHTMc_aEBk)>w9x~bJ~it+^OVn7 z?o7fs_XW77p2K>;T6bSpWxB{yBBW zh5tWB-;8$yJhE@3h|6Bf{t>hRY-$Z_bRIJp3-|kT{&mCn_glDB_;Iln@krPsdq#=u z9{v9?PMg||`}4%jg?s$-gEJJV_jT#}!Xx2}xEm1P2`JeyRs`&{>>A@@V_+;aVVx5X z+MEN;b)XSbTCE9m+&7yxaqGe1g%UavjlGFro#Ap*8r%&9Nn$MWh$g_qp z=3Se%TkF_Powa*fB_0W4xd}K@krP!%Vvozn=JypbT(dGOVW08 z)L=P%##}Iiw!a2>&hWmp;%oVNBPB z!F=80U(a8o=P*v+-^={v_3=p9EB~1%^4}!?aZ#~<&$s?ue_r=1U-w`Rv_ki(^^~vY z>2W7}?gd+eDyn|C_TM#hPZj9RNR z;>6XtH}k!$?w7Cda?UpZVs4}Q9$J>;Q8CX+drVGfI8jPoFDTle_Xzicg4DK!T+~7jcx9*VuF-_1t z${~;j+QOl(dFqeXpcI|_oJrwopJ9%HcBs!BZ#$Re0U$qg=+FxWA0Xx0En|RNM*}8v zqYY*&=-0UVSSOvU;1~*r<`rIRYY)O5%?CdkzIiNglY_~qZgL!bF`k`t<2Y!Zk5MP$ zHB=9f$R(FPTIpE1ob{AvmKB+)wu*8#4zPXI!+O$=q>V2;B49a1;m2klfm)n{RS%&Z3=DgWlh z7hin(|NT0kWfIWp(L$&_nLfgNBAF*pKXWusIoh}OMcFKM3aP(qTXY@p|92U%<87J( z80uAozw*d`EL)-zXUWuW7;YG)x7E`eG+T zOckBBaVdpsC)l7of;Kq>?dW(kkI*qnUB;M0%+Glvh;<|tp{=BK1jZR(-#w)Nms#J=ZF#K{gv`w1G6%{}w5!k9L z$3Q=IlU3wO+z@aHiA6Y(nB<8~UmztmXAZcpz|K#9`qP)Y6LN}8uuZgw=_lHcNuGT2 z$n+r$7B^`10k;zv?Et zvahdi_O4yKe(g?BFCy*r*MV1G1wQx?Y;Z4(4_|%t)jzIXyY{p8;^D^F{^TDZYlMIH zzk5#nLBU`Au_YxX7rPhh47c{#1K%>l3=dIB|pfa zB)?R6M9`1;3>+O<|hc!FdJv}|Q`iE5?<0m7lmj&Vi^_>V)L(jz zw})iA??2uT-}*NL(--Qw12PjD0mH-wlhkPogsVC6Sc;pdCAs6HV@N~$Nac!8@(J-L za^`#&*uD#FaO;EBbLY;zF<2iQ#@k1^{oLPUKLP!Ei<5a-$8IR>_$UeOo3$dG z1b0#^@T*n8d+-0{vhe<9`65oi~NKh;&HGC?X2FS`Wh#U9Xs|S zcgeZMKI0hZE06W}0i`#`=ZL<{s8(QfOB`bi%?9zAPAPiGrC<9Plj zM;&$AZMWU_b+_pJy}Ju}kHw#S5onyJ#~L47W@H;+7~!SC4v4zgM3Sq%RL+PrkDy(6 zon-C8c_R#|^N@;5e%H5v`=0_n9QaleKb3sjeMRj>_wn>?J9g~&QEzW=&Mn-E-7V?o zIy*bBF_>;Xiy6nbmSefWZ78031(^9GIX^NM^<{>20EXf1M8r;T)ITEN6R{kX+SdrP z<4DzJ|B1e+rxCADXe@mUno~R-`1v|u=d1X;+pbrEU*85)%+@i)bw%bIUBEXw19*F= zN1ziLC+LsY=~C$tsr_}&QG{cpFFIb~Nj%6)jZu68`Xcp(BYjHFglRzIGGOMevIeGp|E&GC`4W*>&bbrdaLzqJZk6nGO|CrDnfLFK_wV!U@8qblzwEbo)d}C5 z^I6UK9p`!9H_kdU_LjqsiQ7Nwp6J}W=gDZfmo|V)&{rBUXnn1tJM@V)a0l1V`#BQS zI2Y#7Ug6d6B;EqG31{}LS^w?KTj;0#+#|jp5xFOLw*UtCHAjA6PCZsjSPpk^z#zHe zyq`Xu!T02K2S2a&$FpKU&u(soYVGqG@%f6#z0QfRx(ky3(;tQ6nNgl^Bz%_sFJH@N z!DBXf;CrdRlb2r1o5*us@NPGd@5G)>F17M;K5(7++Q%#6{kJmmKoKK~Vdxxdd+&R- z^j;486J_&=^DvkJgj{6V^XK*dNDU?ycFw3a%)9se##-my-nr(!wZ6$U!S|{s9(EeN zhc)V}-eG%uyVld2g5-Z|&*X)vXD*=UILtgTv&7N4Mvjm7gq@=g_c!}C=^Ur;y0zK~ zn!eu%2Faz@jeweWS(m>2?L~jPf4A2C`?Vgz@50F)7f6rJJ>olZ`zektd5%RF)?Sca zwAu&bQ6R5!7lwFvWcJpzq+Yi9Vg9NGz@#ru{;Mh-0!vSn@11jdXJqw?+HA6>^B}fx1%3x9sOMEu;2)g*Pinq)Dj1p z7aybfQFmI`@3fEW@oYV$Iqr7%-v&#ked--sADumuOFMmscI*9tc5A0=zW{0m5BaSs RG-v<-002ovPDHLkV1jdx=ym`A literal 0 HcmV?d00001 diff --git a/platforms/neoforge/build.gradle b/platforms/neoforge/build.gradle index fce0c47e..f6ba30c8 100644 --- a/platforms/neoforge/build.gradle +++ b/platforms/neoforge/build.gradle @@ -91,13 +91,11 @@ publishMods { accessToken = providers.environmentVariable("CURSEFORGE_SECRET") projectId = "335493" - /* minecraftVersionRange { start = project.property("minecraft_version_min").toString() end = project.property("minecraft_version_max").toString() } - */ - minecraftVersions.add(project.property("minecraft_version_min").toString()) + // minecraftVersions.add(project.property("minecraft_version_min").toString()) clientRequired = true serverRequired = false @@ -109,13 +107,11 @@ publishMods { accessToken = providers.environmentVariable("MODRINTH_SECRET") projectId = "LQ3K71Q1" - /* minecraftVersionRange { start = project.property("minecraft_version_min").toString() end = project.property("minecraft_version_max").toString() } - */ - minecraftVersions.add(project.property("minecraft_version_min").toString()) + // minecraftVersions.add(project.property("minecraft_version_min").toString()) optional("cloth-config") } diff --git a/platforms/neoforge/gradle.properties b/platforms/neoforge/gradle.properties index 97b48a86..29baa81d 100644 --- a/platforms/neoforge/gradle.properties +++ b/platforms/neoforge/gradle.properties @@ -1,2 +1,4 @@ loom.platform=neoforge supported_platforms=neoforge + +minecraft_version_min = 1.20.2 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..024f28ca 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 @@ -2,15 +2,16 @@ import dynamic_fps.impl.Constants; import dynamic_fps.impl.DynamicFPSMod; +import dynamic_fps.impl.compat.ClothConfig; import dynamic_fps.impl.util.HudInfoRenderer; import dynamic_fps.impl.util.KeyMappingHandler; import net.neoforged.bus.api.IEventBus; 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 +24,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) -> ClothConfig.genConfigScreen(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 98% rename from platforms/neoforge/src/main/resources/META-INF/neoforge.mods.toml rename to platforms/neoforge/src/main/resources/META-INF/mods.toml index 04dedd3d..37337481 100644 --- a/platforms/neoforge/src/main/resources/META-INF/neoforge.mods.toml +++ b/platforms/neoforge/src/main/resources/META-INF/mods.toml @@ -85,7 +85,7 @@ file="META-INF/accesstransformer.cfg" [[dependencies.dynamic_fps]] modId = "minecraft" mandatory = true -versionRange = "[1.21.0,)" +versionRange = "[1.20.2,1.20.4]" ordering = "NONE" side = "CLIENT" diff --git a/platforms/quilt/build.gradle b/platforms/quilt/build.gradle index 418984ed..114a5c81 100644 --- a/platforms/quilt/build.gradle +++ b/platforms/quilt/build.gradle @@ -88,13 +88,11 @@ publishMods { accessToken = providers.environmentVariable("CURSEFORGE_SECRET") projectId = "335493" - /* minecraftVersionRange { start = project.property("minecraft_version_min").toString() end = project.property("minecraft_version_max").toString() } - */ - minecraftVersions.add(project.property("minecraft_version_min").toString()) + // minecraftVersions.add(project.property("minecraft_version_min").toString()) clientRequired = true serverRequired = false @@ -107,13 +105,11 @@ publishMods { accessToken = providers.environmentVariable("MODRINTH_SECRET") projectId = "LQ3K71Q1" - /* minecraftVersionRange { start = project.property("minecraft_version_min").toString() end = project.property("minecraft_version_max").toString() } - */ - minecraftVersions.add(project.property("minecraft_version_min").toString()) + // minecraftVersions.add(project.property("minecraft_version_min").toString()) requires("qsl") optional("cloth-config", "modmenu") diff --git a/platforms/quilt/src/main/resources/quilt.mod.json b/platforms/quilt/src/main/resources/quilt.mod.json index 3d458889..6bd7fde0 100644 --- a/platforms/quilt/src/main/resources/quilt.mod.json +++ b/platforms/quilt/src/main/resources/quilt.mod.json @@ -81,7 +81,9 @@ }, { "id": "minecraft", - "versions": ">=1.21.0-alpha.24.20.a" + "versions": { + "all": [">=1.18.0", "<=1.18.2"] + } }, { "id": "mixinextras", @@ -115,5 +117,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/GameRendererMixin.java b/platforms/textile/src/main/java/net/lostluma/dynamic_fps/impl/textile/mixin/GameRendererMixin.java new file mode 100644 index 00000000..120e1202 --- /dev/null +++ b/platforms/textile/src/main/java/net/lostluma/dynamic_fps/impl/textile/mixin/GameRendererMixin.java @@ -0,0 +1,23 @@ +package net.lostluma.dynamic_fps.impl.textile.mixin; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import dynamic_fps.impl.DynamicFPSMod; +import net.minecraft.client.renderer.GameRenderer; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(GameRenderer.class) +public class GameRendererMixin { + @ModifyExpressionValue( + method = "render", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/client/Minecraft;noRender:Z", + opcode = Opcodes.GETFIELD + ) + ) + private boolean skipRendering(boolean original) { + return original || !DynamicFPSMod.checkForRender(); + } +} 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/platforms/textile/src/main/resources/dynamic_fps-textile.mixins.json b/platforms/textile/src/main/resources/dynamic_fps-textile.mixins.json index 28e3ecc0..3c6ddb9c 100644 --- a/platforms/textile/src/main/resources/dynamic_fps-textile.mixins.json +++ b/platforms/textile/src/main/resources/dynamic_fps-textile.mixins.json @@ -3,6 +3,7 @@ "package": "net.lostluma.dynamic_fps.impl.textile.mixin", "minVersion": "0.8", "client": [ + "GameRendererMixin", "GuiMixin", "OptionsMixin" ], diff --git a/settings.gradle.kts b/settings.gradle.kts index 7489080b..cb576658 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,7 +17,7 @@ includeBuild("build-logic") include(":platforms:common") include(":platforms:fabric") -// include(":platforms:forge") -include(":platforms:neoforge") +include(":platforms:forge") +// include(":platforms:neoforge") include(":platforms:quilt") include(":platforms:textile")