diff --git a/.editorconfig b/.editorconfig index f317aa3f..88e22b11 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,15 +4,14 @@ root = true tab_width = 4 charset = utf-8 +indent_size = 4 +indent_style = space + insert_final_newline = true trim_trailing_whitespace = true -[*.{gradle,java,json,toml}] +[*.{gradle,java}] indent_style = tab -[*.{properties,yaml}] -indent_size = 2 -indent_style = space - [*.md] trim_trailing_whitespace = false diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 28a80883..2d7f8466 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -39,5 +39,8 @@ jobs: uses: actions/upload-artifact@v4 with: name: dynamic-fps-artifacts - path: build/libs + path: | + platforms/**/build/libs + !platforms/**/build/libs/*-all.jar + !platforms/**/build/libs/*-transformProduction*.jar if-no-files-found: error diff --git a/build.gradle b/build.gradle index 4e239510..c8c515ac 100644 --- a/build.gradle +++ b/build.gradle @@ -1,86 +1,72 @@ plugins { - id "maven-publish" - alias libs.plugins.fabric.loom + alias libs.plugins.architectury + alias libs.plugins.architectury.loom apply false } -group = project.maven_group -version = "${generateVersion()}+minecraft-${libs.versions.minecraft.get()}" - -base { - archivesName = project.archives_base_name -} - -repositories { - maven { url = "https://maven.shedaniel.me/" } // cloth config - maven { url = "https://maven.terraformersmc.com/releases/" } // modmenu +architectury { + minecraft = libs.versions.minecraft.get() } -dependencies { - minecraft libs.minecraft - mappings loom.officialMojangMappings() +subprojects { + if (project.name == "platforms") { + return + } - modImplementation libs.fabric.api - modImplementation libs.fabric.loader + apply plugin: "dev.architectury.loom" - modApi libs.modmenu - modApi libs.cloth.config -} + loom { + silentMojangMappingsLicense() + } -loom { - accessWidenerPath = file("src/main/resources/dynamic_fps.accesswidener") + dependencies { + minecraft libs.minecraft + mappings loom.officialMojangMappings() + } } -processResources { - inputs.property "version", generateVersion() - - filesMatching("fabric.mod.json") { - expand "version": generateVersion() +allprojects { + if (project.name == "platforms") { + return } -} -java { - withSourcesJar() + apply plugin: "java" + apply plugin: "architectury-plugin" + apply plugin: "maven-publish" - toolchain { - languageVersion = JavaLanguageVersion.of(17) + base { + archivesName = rootProject.archives_base_name } -} -tasks.withType(JavaCompile).configureEach { - it.options.encoding = "UTF-8" + group = rootProject.maven_group - javaCompiler = javaToolchains.compilerFor { - languageVersion = JavaLanguageVersion.of(17) + if (!project.hasProperty("loom.platform")) { + version = rootProject.mod_version + } else { + var platform = project.property("loom.platform") + version = "${rootProject.mod_version}+minecraft-${libs.versions.minecraft.get()}-${platform}" } - it.options.compilerArgs += ["-Xlint:deprecation", "-Xlint:unchecked"] -} - -tasks.withType(org.gradle.jvm.tasks.Jar).configureEach { - it.from(".") { - include("LICENSE") + repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. } -} -// configure the maven publication -publishing { - publications { - mavenJava(MavenPublication) { - from components.java + java { + withSourcesJar() + + toolchain { + languageVersion = JavaLanguageVersion.of(17) } } - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - // Notice: This block does NOT have the same function as the block in the top level. - // The repositories here will be used for publishing your artifact, not for - // retrieving dependencies. - } -} + tasks.withType(JavaCompile).configureEach { + it.options.encoding = "UTF-8" -def generateVersion() { - var version = project.mod_version; - // NOTE: To create a release jar run `./gradlew build -Prelease=true` - return project.hasProperty("release") ? version : version + "-alpha"; + javaCompiler = javaToolchains.compilerFor { + languageVersion = JavaLanguageVersion.of(17) + } + } } diff --git a/gradle.properties b/gradle.properties index 1ab792c8..1eddd27c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,10 @@ -# Gradle +# Gradle Properties org.gradle.parallel = true -org.gradle.jvmargs = -Xmx1G +org.gradle.jvmargs = -Xmx3G # Mod Properties mod_version = 3.3.3 maven_group = juliand665 archives_base_name = dynamic-fps + +enabled_platforms=fabric,forge,neoforge,quilt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7019fd66..d6fea4e4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,22 +1,52 @@ [versions] -minecraft = "1.20" -fabric_loader = "0.15.3" +minecraft = "1.20.4" -modmenu = "7.0.1" -fabric_api = "0.83.0+1.20" +# Platform libraries -cloth_config = "11.0.99" +fabric_loader = "0.15.6" +fabric_api = "0.96.1+1.20.4" + +forge = "1.20.4-49.0.30" + +neoforge = "20.4.160-beta" + +quilt_loader = "0.23.1" +quilt_standard_libraries = "7.0.0-alpha.10+1.20.2" + +# Third-party libraries + +modmenu = "9.0.0" +cloth_config = "13.0.121" + +mixinextras = "0.3.5" [libraries] minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" } + +# Platform libraries + fabric_loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric_loader" } +# fabric_api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric_api" } + +forge = { module = "net.minecraftforge:forge", version.ref = "forge" } + +neoforge = { module = "net.neoforged:neoforge", version.ref = "neoforge" } + +quilt_loader = { module = "org.quiltmc:quilt-loader", version.ref = "quilt_loader" } +qsl_lifecycle_events = { module = "org.quiltmc.qsl.core:lifecycle_events", version.ref = "quilt_standard_libraries" } + +# Third-party libraries modmenu = { module = "com.terraformersmc:modmenu", version.ref = "modmenu" } -fabric_api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric_api" } +cloth_config = { module = "me.shedaniel.cloth:cloth-config", version.ref = "cloth_config" } -cloth_config = { module = "me.shedaniel.cloth:cloth-config-fabric", version.ref = "cloth_config" } +mixinextras_common = { module = "io.github.llamalad7:mixinextras-common", version.ref = "mixinextras" } +mixinextras_forge = { module = "io.github.llamalad7:mixinextras-forge", version.ref = "mixinextras" } [bundles] [plugins] -fabric_loom = { id = "fabric-loom", version = "1.5.7" } +shadow = { id = "com.github.johnrengelman.shadow", version = "8.1.1" } + +architectury = { id = "architectury-plugin", version = "3.4.151" } +architectury_loom = { id = "dev.architectury.loom", version = "1.5.388" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd491..7f93135c 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/platforms/common/build.gradle b/platforms/common/build.gradle new file mode 100644 index 00000000..52c23ba8 --- /dev/null +++ b/platforms/common/build.gradle @@ -0,0 +1,28 @@ +architectury { + common(rootProject.enabled_platforms.split(",")) +} + +loom { + accessWidenerPath = file("src/main/resources/dynamic_fps.accesswidener") +} + +dependencies { + // We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies + // Do NOT use other classes from fabric loader + modImplementation libs.fabric.loader + modImplementation libs.cloth.config +} + +publishing { + publications { + mavenCommon(MavenPublication) { + artifactId = rootProject.archives_base_name + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + } +} diff --git a/src/main/java/dynamic_fps/impl/Constants.java b/platforms/common/src/main/java/dynamic_fps/impl/Constants.java similarity index 100% rename from src/main/java/dynamic_fps/impl/Constants.java rename to platforms/common/src/main/java/dynamic_fps/impl/Constants.java diff --git a/src/main/java/dynamic_fps/impl/DynamicFPSMod.java b/platforms/common/src/main/java/dynamic_fps/impl/DynamicFPSMod.java similarity index 89% rename from src/main/java/dynamic_fps/impl/DynamicFPSMod.java rename to platforms/common/src/main/java/dynamic_fps/impl/DynamicFPSMod.java index ae4e2b07..77c97a85 100644 --- a/src/main/java/dynamic_fps/impl/DynamicFPSMod.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/DynamicFPSMod.java @@ -1,12 +1,14 @@ package dynamic_fps.impl; -import dynamic_fps.impl.compat.FREX; import dynamic_fps.impl.compat.GLFW; import dynamic_fps.impl.config.Config; import dynamic_fps.impl.config.DynamicFPSConfig; +import dynamic_fps.impl.service.ModCompat; import dynamic_fps.impl.util.Logging; -import dynamic_fps.impl.util.ModCompatibility; import dynamic_fps.impl.util.OptionsHolder; +import dynamic_fps.impl.util.duck.DuckScreen; +import dynamic_fps.impl.util.duck.DuckLoadingOverlay; +import dynamic_fps.impl.util.duck.DuckSoundEngine; import dynamic_fps.impl.util.event.InputObserver; import dynamic_fps.impl.util.event.WindowObserver; import dynamic_fps.impl.service.Platform; @@ -23,8 +25,8 @@ public class DynamicFPSMod { public static DynamicFPSConfig modConfig = DynamicFPSConfig.load(); - private static boolean isDisabled = false; private static boolean isForcingLowFPS = false; + private static boolean isDisabled = false; private static final Minecraft minecraft = Minecraft.getInstance(); @@ -42,10 +44,15 @@ public class DynamicFPSMod { // inactive. private static boolean hasRenderedLastFrame = false; - private static final boolean OVERLAY_OPTIMIZATION_ACTIVE = !ModCompatibility.disableOverlayOptimization(); + private static final boolean OVERLAY_OPTIMIZATION_ACTIVE = !ModCompat.getInstance().disableOverlayOptimization(); // Internal "API" for Dynamic FPS itself + public static void init() { + Platform platform = Platform.getInstance(); + Logging.getLogger().info("Dynamic FPS {} active on {}!", platform.modVersion(), platform.getName()); + } + public static boolean isDisabled() { return isDisabled; } @@ -124,11 +131,11 @@ public static boolean shouldShowLevels() { // Internal logic private static boolean isDisabledInternal() { - return isDisabled || FREX.isFlawlessFramesActive(); + return isDisabled || ModCompat.getInstance().isDisabled(); } private static boolean isLevelCoveredByScreen() { - return minecraft.screen != null && minecraft.screen.dynamic_fps$rendersBackground(); + return minecraft.screen != null && ((DuckScreen) minecraft.screen).dynamic_fps$rendersBackground(); } private static boolean isIdle() { @@ -142,7 +149,7 @@ private static boolean isIdle() { } private static boolean isLevelCoveredByOverlay() { - return OVERLAY_OPTIMIZATION_ACTIVE && minecraft.getOverlay() instanceof LoadingOverlay && ((LoadingOverlay)minecraft.getOverlay()).dynamic_fps$isReloadComplete(); + return OVERLAY_OPTIMIZATION_ACTIVE && minecraft.getOverlay() instanceof LoadingOverlay && ((DuckLoadingOverlay)minecraft.getOverlay()).dynamic_fps$isReloadComplete(); } private static void initializeIdleCheck() { @@ -199,7 +206,7 @@ public static void handleStateChange(PowerState previous, PowerState current) { for (SoundSource source : SoundSource.values()) { if (before.volumeMultiplier(source) != config.volumeMultiplier(source)) { - minecraft.getSoundManager().soundEngine.dynamic_fps$updateVolume(source); + ((DuckSoundEngine) minecraft.getSoundManager().soundEngine).dynamic_fps$updateVolume(source); } } diff --git a/src/main/java/dynamic_fps/impl/GraphicsState.java b/platforms/common/src/main/java/dynamic_fps/impl/GraphicsState.java similarity index 100% rename from src/main/java/dynamic_fps/impl/GraphicsState.java rename to platforms/common/src/main/java/dynamic_fps/impl/GraphicsState.java diff --git a/src/main/java/dynamic_fps/impl/PowerState.java b/platforms/common/src/main/java/dynamic_fps/impl/PowerState.java similarity index 100% rename from src/main/java/dynamic_fps/impl/PowerState.java rename to platforms/common/src/main/java/dynamic_fps/impl/PowerState.java diff --git a/src/main/java/dynamic_fps/impl/compat/ClothConfig.java b/platforms/common/src/main/java/dynamic_fps/impl/compat/ClothConfig.java similarity index 99% rename from src/main/java/dynamic_fps/impl/compat/ClothConfig.java rename to platforms/common/src/main/java/dynamic_fps/impl/compat/ClothConfig.java index 4a205d7c..29c4c5b7 100644 --- a/src/main/java/dynamic_fps/impl/compat/ClothConfig.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/compat/ClothConfig.java @@ -1,5 +1,8 @@ package dynamic_fps.impl.compat; +import dynamic_fps.impl.DynamicFPSMod; +import dynamic_fps.impl.GraphicsState; +import dynamic_fps.impl.PowerState; import dynamic_fps.impl.config.Config; import me.shedaniel.clothconfig2.api.ConfigBuilder; import me.shedaniel.clothconfig2.api.ConfigCategory; @@ -10,17 +13,12 @@ import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundSource; -import static dynamic_fps.impl.util.Localization.localized; - import java.util.Locale; import java.util.Optional; -import dynamic_fps.impl.DynamicFPSMod; -import dynamic_fps.impl.GraphicsState; -import dynamic_fps.impl.PowerState; +import static dynamic_fps.impl.util.Localization.localized; public final class ClothConfig { - @SuppressWarnings("unchecked") public static Screen genConfigScreen(Screen parent) { ConfigBuilder builder = ConfigBuilder.create() .setParentScreen(parent) diff --git a/src/main/java/dynamic_fps/impl/compat/GLFW.java b/platforms/common/src/main/java/dynamic_fps/impl/compat/GLFW.java similarity index 100% rename from src/main/java/dynamic_fps/impl/compat/GLFW.java rename to platforms/common/src/main/java/dynamic_fps/impl/compat/GLFW.java diff --git a/src/main/java/dynamic_fps/impl/config/Config.java b/platforms/common/src/main/java/dynamic_fps/impl/config/Config.java similarity index 100% rename from src/main/java/dynamic_fps/impl/config/Config.java rename to platforms/common/src/main/java/dynamic_fps/impl/config/Config.java diff --git a/src/main/java/dynamic_fps/impl/config/DynamicFPSConfig.java b/platforms/common/src/main/java/dynamic_fps/impl/config/DynamicFPSConfig.java similarity index 100% rename from src/main/java/dynamic_fps/impl/config/DynamicFPSConfig.java rename to platforms/common/src/main/java/dynamic_fps/impl/config/DynamicFPSConfig.java diff --git a/src/main/java/dynamic_fps/impl/config/Serialization.java b/platforms/common/src/main/java/dynamic_fps/impl/config/Serialization.java similarity index 100% rename from src/main/java/dynamic_fps/impl/config/Serialization.java rename to platforms/common/src/main/java/dynamic_fps/impl/config/Serialization.java diff --git a/src/main/java/dynamic_fps/impl/mixin/DebugScreenOverlayMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/DebugScreenOverlayMixin.java similarity index 100% rename from src/main/java/dynamic_fps/impl/mixin/DebugScreenOverlayMixin.java rename to platforms/common/src/main/java/dynamic_fps/impl/mixin/DebugScreenOverlayMixin.java diff --git a/src/main/java/dynamic_fps/impl/mixin/GameRendererMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/GameRendererMixin.java similarity index 100% rename from src/main/java/dynamic_fps/impl/mixin/GameRendererMixin.java rename to platforms/common/src/main/java/dynamic_fps/impl/mixin/GameRendererMixin.java diff --git a/platforms/common/src/main/java/dynamic_fps/impl/mixin/GuiMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/GuiMixin.java new file mode 100644 index 00000000..66af3434 --- /dev/null +++ b/platforms/common/src/main/java/dynamic_fps/impl/mixin/GuiMixin.java @@ -0,0 +1,22 @@ +package dynamic_fps.impl.mixin; + +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 dynamic_fps.impl.DynamicFPSMod; +import net.minecraft.client.gui.Gui; + +@Mixin(Gui.class) +public class GuiMixin { + /** + * Cancels rendering the GUI if it is determined to currently not be visible. + */ + @Inject(method = "render", at = @At("HEAD"), cancellable = true) + private void shouldRender(CallbackInfo callbackInfo) { + if (!DynamicFPSMod.shouldShowLevels()) { + callbackInfo.cancel(); + } + } +} diff --git a/src/main/java/dynamic_fps/impl/mixin/LoadingOverlayMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/LoadingOverlayMixin.java similarity index 58% rename from src/main/java/dynamic_fps/impl/mixin/LoadingOverlayMixin.java rename to platforms/common/src/main/java/dynamic_fps/impl/mixin/LoadingOverlayMixin.java index 5b61bd22..a8bf1dd5 100644 --- a/src/main/java/dynamic_fps/impl/mixin/LoadingOverlayMixin.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/mixin/LoadingOverlayMixin.java @@ -5,15 +5,18 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import dynamic_fps.impl.util.duck.DuckSplashOverlay; +import dynamic_fps.impl.util.duck.DuckLoadingOverlay; @Mixin(LoadingOverlay.class) -public class LoadingOverlayMixin implements DuckSplashOverlay { +public class LoadingOverlayMixin implements DuckLoadingOverlay { + /* @Shadow private long fadeOutStart; + */ @Override public boolean dynamic_fps$isReloadComplete() { - return this.fadeOutStart > -1L; + LoadingOverlay self = (LoadingOverlay)(Object) this; + return self.fadeOutStart > -1L; } } diff --git a/src/main/java/dynamic_fps/impl/mixin/MinecraftMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/MinecraftMixin.java similarity index 89% rename from src/main/java/dynamic_fps/impl/mixin/MinecraftMixin.java rename to platforms/common/src/main/java/dynamic_fps/impl/mixin/MinecraftMixin.java index ce385c3d..e314d8d2 100644 --- a/src/main/java/dynamic_fps/impl/mixin/MinecraftMixin.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/mixin/MinecraftMixin.java @@ -15,6 +15,7 @@ @Mixin(Minecraft.class) public class MinecraftMixin { + /* @Shadow @Final private Window window; @@ -22,13 +23,15 @@ public class MinecraftMixin { @Shadow @Final public Options options; + */ // Minecraft considers limits >=260 as infinite private static final int NO_FRAME_RATE_LIMIT = 260; @Inject(method = "", at = @At("TAIL")) private void onInit(CallbackInfo callbackInfo) { - DynamicFPSMod.setWindow(this.window.window); + Minecraft self = (Minecraft)(Object) this; + DynamicFPSMod.setWindow(self.window.window); } /** @@ -40,7 +43,8 @@ private void onInit(CallbackInfo callbackInfo) { */ @Inject(method = "getFramerateLimit", at = @At(value = "CONSTANT", args = "intValue=60"), cancellable = true) private void getFramerateLimit(CallbackInfoReturnable callbackInfo) { - int limit = this.window.getFramerateLimit(); + Minecraft self = (Minecraft)(Object) this; + int limit = self.window.getFramerateLimit(); if (DynamicFPSMod.powerState() != PowerState.FOCUSED) { // Limit may be 260 (uncapped) @@ -48,7 +52,7 @@ private void getFramerateLimit(CallbackInfoReturnable callbackInfo) { callbackInfo.setReturnValue(limit); } } else if (DynamicFPSMod.uncapMenuFrameRate()) { - if (this.options.enableVsync().get()) { + if (self.options.enableVsync().get()) { // VSync will regulate to a non-infinite value callbackInfo.setReturnValue(NO_FRAME_RATE_LIMIT); } else { diff --git a/src/main/java/dynamic_fps/impl/mixin/ScreenMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/ScreenMixin.java similarity index 86% rename from src/main/java/dynamic_fps/impl/mixin/ScreenMixin.java rename to platforms/common/src/main/java/dynamic_fps/impl/mixin/ScreenMixin.java index 939e5eaa..7f39e351 100644 --- a/src/main/java/dynamic_fps/impl/mixin/ScreenMixin.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/mixin/ScreenMixin.java @@ -1,6 +1,6 @@ package dynamic_fps.impl.mixin; -import dynamic_fps.impl.util.ModCompatibility; +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; @@ -32,12 +32,12 @@ public class ScreenMixin implements DuckScreen { private void onInit(CallbackInfo callbackInfo) { String name = this.getClass().getName(); - this.dynamic_fps$hasOptedOut = ModCompatibility.isScreenOptedOut(name); + 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 = ModCompatibility.isScreenOptedIn(name); + this.dynamic_fps$canOptimize = ModCompat.getInstance().isScreenOptedIn(name); } } diff --git a/src/main/java/dynamic_fps/impl/mixin/SoundEngineMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/SoundEngineMixin.java similarity index 91% rename from src/main/java/dynamic_fps/impl/mixin/SoundEngineMixin.java rename to platforms/common/src/main/java/dynamic_fps/impl/mixin/SoundEngineMixin.java index 8a8ea7e0..68110c3c 100644 --- a/src/main/java/dynamic_fps/impl/mixin/SoundEngineMixin.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/mixin/SoundEngineMixin.java @@ -24,6 +24,7 @@ @Mixin(SoundEngine.class) public class SoundEngineMixin implements DuckSoundEngine { + /* @Shadow @Final private Options options; @@ -43,15 +44,18 @@ public class SoundEngineMixin implements DuckSoundEngine { private float calculateVolume(SoundInstance instance) { throw new RuntimeException("Failed to find SoundEngine#calculateVolume."); }; + */ public void dynamic_fps$updateVolume(SoundSource source) { - if (!this.loaded) { + SoundEngine self = (SoundEngine)(Object) this; + + if (!self.loaded) { return; } if (source.equals(SoundSource.MASTER)) { - float volume = this.options.getSoundSourceVolume(source); - this.listener.setGain(this.adjustVolume(volume, source)); + float volume = self.options.getSoundSourceVolume(source); + self.listener.setGain(this.adjustVolume(volume, source)); return; } @@ -60,8 +64,8 @@ private float calculateVolume(SoundInstance instance) { // Also fixes this compat bug: https://github.com/juliand665/Dynamic-FPS/issues/55 boolean isMusic = source.equals(SoundSource.MUSIC) || source.equals(SoundSource.RECORDS); - this.instanceToChannel.forEach((instance, handle) -> { - float volume = this.calculateVolume(instance); + self.instanceToChannel.forEach((instance, handle) -> { + float volume = self.calculateVolume(instance); if (instance.getSource().equals(source)) { handle.execute(channel -> { diff --git a/src/main/java/dynamic_fps/impl/mixin/StatsScreenMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/StatsScreenMixin.java similarity index 81% rename from src/main/java/dynamic_fps/impl/mixin/StatsScreenMixin.java rename to platforms/common/src/main/java/dynamic_fps/impl/mixin/StatsScreenMixin.java index e465ef20..92b1b5ac 100644 --- a/src/main/java/dynamic_fps/impl/mixin/StatsScreenMixin.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/mixin/StatsScreenMixin.java @@ -1,17 +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.Screen; 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) { - ((Screen)(Object)this).dynamic_fps$setRendersBackground(); + ((DuckScreen) this).dynamic_fps$setRendersBackground(); } } diff --git a/src/main/java/dynamic_fps/impl/mixin/ToastComponentMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/ToastComponentMixin.java similarity index 100% rename from src/main/java/dynamic_fps/impl/mixin/ToastComponentMixin.java rename to platforms/common/src/main/java/dynamic_fps/impl/mixin/ToastComponentMixin.java diff --git a/src/main/java/dynamic_fps/impl/mixin/WindowMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/WindowMixin.java similarity index 100% rename from src/main/java/dynamic_fps/impl/mixin/WindowMixin.java rename to platforms/common/src/main/java/dynamic_fps/impl/mixin/WindowMixin.java diff --git a/platforms/common/src/main/java/dynamic_fps/impl/mixin/bugfix/BlockableEventLoopMixin.java b/platforms/common/src/main/java/dynamic_fps/impl/mixin/bugfix/BlockableEventLoopMixin.java new file mode 100644 index 00000000..59a47fcd --- /dev/null +++ b/platforms/common/src/main/java/dynamic_fps/impl/mixin/bugfix/BlockableEventLoopMixin.java @@ -0,0 +1,42 @@ +package dynamic_fps.impl.mixin.bugfix; + +import com.llamalad7.mixinextras.injector.WrapWithCondition; +import org.spongepowered.asm.mixin.Mixin; + +import net.minecraft.util.thread.BlockableEventLoop; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyConstant; + +/** + * @author Julian Dunskus + * @reason The vanilla version of `waitForTasks` is simply broken, taking up way too many resources in the background. + */ +@Mixin(BlockableEventLoop.class) +public final class BlockableEventLoopMixin { + /* + Replaced with other injections due to NeoForge build issue. + + @Overwrite + public void waitForTasks() { + // yield() here is a terrible idea + LockSupport.parkNanos("waiting for tasks", 500_000); // increased wait to 0.5 ms + } + */ + + /** + * Skip the Thread.yield() call. + */ + @WrapWithCondition(method = "waitForTasks", at = @At(value = "INVOKE", target = "Ljava/lang/Thread;yield()V")) + private boolean doThreadYield() { + return false; + } + + /** + * Increase wait time to 0.5 milliseconds. + */ + @ModifyConstant(method = "waitForTasks", constant = @Constant(longValue = 100000L)) + private long incParkNanosTime(long original) { + return 500_000L; + } +} 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 new file mode 100644 index 00000000..97f3c54c --- /dev/null +++ b/platforms/common/src/main/java/dynamic_fps/impl/service/ModCompat.java @@ -0,0 +1,13 @@ +package dynamic_fps.impl.service; + +public interface ModCompat { + boolean isDisabled(); + + boolean disableOverlayOptimization(); + boolean isScreenOptedIn(String className); + boolean isScreenOptedOut(String className); + + static ModCompat getInstance() { + return Services.MOD_COMPAT; + } +} diff --git a/src/main/java/dynamic_fps/impl/service/Platform.java b/platforms/common/src/main/java/dynamic_fps/impl/service/Platform.java similarity index 89% rename from src/main/java/dynamic_fps/impl/service/Platform.java rename to platforms/common/src/main/java/dynamic_fps/impl/service/Platform.java index 40426696..36ab0eb4 100644 --- a/src/main/java/dynamic_fps/impl/service/Platform.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/service/Platform.java @@ -3,18 +3,21 @@ import java.nio.file.Path; public interface Platform { + String getName(); + String modVersion(); + Path getCacheDir(); Path getConfigDir(); boolean isDevelopmentEnvironment(); void registerStartTickEvent(StartTickEvent event); - static Platform getInstance() { - return Services.PLATFORM; - } - @FunctionalInterface interface StartTickEvent { void onStartTick(); } + + static Platform getInstance() { + return Services.PLATFORM; + } } diff --git a/src/main/java/dynamic_fps/impl/service/Services.java b/platforms/common/src/main/java/dynamic_fps/impl/service/Services.java similarity index 88% rename from src/main/java/dynamic_fps/impl/service/Services.java rename to platforms/common/src/main/java/dynamic_fps/impl/service/Services.java index 5dc4593a..2b8e5bc5 100644 --- a/src/main/java/dynamic_fps/impl/service/Services.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/service/Services.java @@ -5,6 +5,7 @@ class Services { static Platform PLATFORM = loadService(Platform.class); + static ModCompat MOD_COMPAT = loadService(ModCompat.class); static T loadService(Class type) { Optional optional = ServiceLoader.load(type).findFirst(); diff --git a/src/main/java/dynamic_fps/impl/util/HudInfoRenderer.java b/platforms/common/src/main/java/dynamic_fps/impl/util/HudInfoRenderer.java similarity index 100% rename from src/main/java/dynamic_fps/impl/util/HudInfoRenderer.java rename to platforms/common/src/main/java/dynamic_fps/impl/util/HudInfoRenderer.java diff --git a/src/main/java/dynamic_fps/impl/util/KeyMappingHandler.java b/platforms/common/src/main/java/dynamic_fps/impl/util/KeyMappingHandler.java similarity index 71% rename from src/main/java/dynamic_fps/impl/util/KeyMappingHandler.java rename to platforms/common/src/main/java/dynamic_fps/impl/util/KeyMappingHandler.java index 87fa7d33..e4321ef5 100644 --- a/src/main/java/dynamic_fps/impl/util/KeyMappingHandler.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/util/KeyMappingHandler.java @@ -29,28 +29,27 @@ public final class KeyMappingHandler { ) }; - public KeyMappingHandler(String translationKey, String category, PressHandler pressHandler) { + private KeyMappingHandler(String translationKey, String category, PressHandler pressHandler) { this.keyMapping = new KeyMapping( translationKey, InputConstants.Type.KEYSYM, InputConstants.UNKNOWN.getValue(), category ); + this.pressHandler = pressHandler; + Platform.getInstance().registerStartTickEvent(this::onStartTick); } - public static KeyMapping[] register(KeyMapping[] existing) { - List mappings = Lists.newArrayList(existing); - - for (KeyMappingHandler handler : KEY_MAPPING_HANDLERS ) { - mappings.add(handler.keyMapping); - Platform.getInstance().registerStartTickEvent(handler::onStartTick); - } + public static KeyMappingHandler[] getHandlers() { + return KEY_MAPPING_HANDLERS; + } - return mappings.toArray(new KeyMapping[0]); + public KeyMapping keyMapping() { + return this.keyMapping; } - public void onStartTick() { + private void onStartTick() { if (this.keyMapping.isDown()) { if (!this.isHoldingKey) { this.pressHandler.handlePress(); @@ -62,7 +61,7 @@ public void onStartTick() { } @FunctionalInterface - public interface PressHandler { + private interface PressHandler { void handlePress(); } } diff --git a/src/main/java/dynamic_fps/impl/util/Localization.java b/platforms/common/src/main/java/dynamic_fps/impl/util/Localization.java similarity index 100% rename from src/main/java/dynamic_fps/impl/util/Localization.java rename to platforms/common/src/main/java/dynamic_fps/impl/util/Localization.java diff --git a/src/main/java/dynamic_fps/impl/util/Logging.java b/platforms/common/src/main/java/dynamic_fps/impl/util/Logging.java similarity index 100% rename from src/main/java/dynamic_fps/impl/util/Logging.java rename to platforms/common/src/main/java/dynamic_fps/impl/util/Logging.java diff --git a/src/main/java/dynamic_fps/impl/util/OptionsHolder.java b/platforms/common/src/main/java/dynamic_fps/impl/util/OptionsHolder.java similarity index 100% rename from src/main/java/dynamic_fps/impl/util/OptionsHolder.java rename to platforms/common/src/main/java/dynamic_fps/impl/util/OptionsHolder.java diff --git a/src/main/java/dynamic_fps/impl/util/duck/DuckSplashOverlay.java b/platforms/common/src/main/java/dynamic_fps/impl/util/duck/DuckLoadingOverlay.java similarity index 83% rename from src/main/java/dynamic_fps/impl/util/duck/DuckSplashOverlay.java rename to platforms/common/src/main/java/dynamic_fps/impl/util/duck/DuckLoadingOverlay.java index bdedb888..8720aee0 100644 --- a/src/main/java/dynamic_fps/impl/util/duck/DuckSplashOverlay.java +++ b/platforms/common/src/main/java/dynamic_fps/impl/util/duck/DuckLoadingOverlay.java @@ -1,6 +1,6 @@ package dynamic_fps.impl.util.duck; -public interface DuckSplashOverlay { +public interface DuckLoadingOverlay { public default boolean dynamic_fps$isReloadComplete() { throw new RuntimeException("No implementation for dynamic_fps$isReloadComplete was found."); } diff --git a/src/main/java/dynamic_fps/impl/util/duck/DuckScreen.java b/platforms/common/src/main/java/dynamic_fps/impl/util/duck/DuckScreen.java similarity index 100% rename from src/main/java/dynamic_fps/impl/util/duck/DuckScreen.java rename to platforms/common/src/main/java/dynamic_fps/impl/util/duck/DuckScreen.java diff --git a/src/main/java/dynamic_fps/impl/util/duck/DuckSoundEngine.java b/platforms/common/src/main/java/dynamic_fps/impl/util/duck/DuckSoundEngine.java similarity index 100% rename from src/main/java/dynamic_fps/impl/util/duck/DuckSoundEngine.java rename to platforms/common/src/main/java/dynamic_fps/impl/util/duck/DuckSoundEngine.java diff --git a/src/main/java/dynamic_fps/impl/util/event/InputObserver.java b/platforms/common/src/main/java/dynamic_fps/impl/util/event/InputObserver.java similarity index 100% rename from src/main/java/dynamic_fps/impl/util/event/InputObserver.java rename to platforms/common/src/main/java/dynamic_fps/impl/util/event/InputObserver.java diff --git a/src/main/java/dynamic_fps/impl/util/event/WindowObserver.java b/platforms/common/src/main/java/dynamic_fps/impl/util/event/WindowObserver.java similarity index 100% rename from src/main/java/dynamic_fps/impl/util/event/WindowObserver.java rename to platforms/common/src/main/java/dynamic_fps/impl/util/event/WindowObserver.java diff --git a/platforms/common/src/main/resources/architectury.common.json b/platforms/common/src/main/resources/architectury.common.json new file mode 100644 index 00000000..498c38bc --- /dev/null +++ b/platforms/common/src/main/resources/architectury.common.json @@ -0,0 +1,3 @@ +{ + "accessWidener": "dynamic_fps.accesswidener" +} diff --git a/src/main/resources/assets/dynamic_fps/icon.png b/platforms/common/src/main/resources/assets/dynamic_fps/icon.png similarity index 100% rename from src/main/resources/assets/dynamic_fps/icon.png rename to platforms/common/src/main/resources/assets/dynamic_fps/icon.png diff --git a/src/main/resources/assets/dynamic_fps/lang/de_at.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/de_at.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/de_at.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/de_at.json diff --git a/src/main/resources/assets/dynamic_fps/lang/de_ch.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/de_ch.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/de_ch.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/de_ch.json diff --git a/src/main/resources/assets/dynamic_fps/lang/de_de.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/de_de.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/de_de.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/de_de.json diff --git a/src/main/resources/assets/dynamic_fps/lang/en_pt.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/en_pt.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/en_pt.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/en_pt.json diff --git a/src/main/resources/assets/dynamic_fps/lang/en_us.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/en_us.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/en_us.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/en_us.json diff --git a/src/main/resources/assets/dynamic_fps/lang/es_ar.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/es_ar.json similarity index 98% rename from src/main/resources/assets/dynamic_fps/lang/es_ar.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/es_ar.json index 73f4a370..ab685073 100644 --- a/src/main/resources/assets/dynamic_fps/lang/es_ar.json +++ b/platforms/common/src/main/resources/assets/dynamic_fps/lang/es_ar.json @@ -1,21 +1,21 @@ -{ - "config.dynamic_fps.title": "Configurar Dynamic FPS", - - "config.dynamic_fps.category.hovered": "Sobre", - "config.dynamic_fps.category.unfocused": "Desenfocado", - "config.dynamic_fps.category.invisible": "Invisible", - - "config.dynamic_fps.frame_rate_target": "Objetivo de Velocidad de Fotogramas", - "config.dynamic_fps.frame_rate_target_description": "Establecer el objetivo de FPS en -1 para desactivar la reducción de FPS.", - "config.dynamic_fps.volume_multiplier": "Multiplicador de Volumen", - "config.dynamic_fps.graphics_state": "Opciones Gráficas", - "config.dynamic_fps.show_toasts": "Mostrar Notificaciones", - "config.dynamic_fps.run_garbage_collector": "Ejecutar el Garbage Collector", - - "key.dynamic_fps.toggle_forced": "Forzar el modo desenfocado (Alternar)", - "key.dynamic_fps.toggle_disabled": "Deshabilitar Dynamic FPS (Alternar)", - "gui.dynamic_fps.hud.reducing": "Dynamic FPS: Forzando FPS reducidos", - "gui.dynamic_fps.hud.disabled": "Dynamic FPS Deshabilitado", - - "modmenu.descriptionTranslation.dynamic_fps": "Ajusta dinámicamente los FPS para que Minecraft no acapare recursos en segundo plano." +{ + "config.dynamic_fps.title": "Configurar Dynamic FPS", + + "config.dynamic_fps.category.hovered": "Sobre", + "config.dynamic_fps.category.unfocused": "Desenfocado", + "config.dynamic_fps.category.invisible": "Invisible", + + "config.dynamic_fps.frame_rate_target": "Objetivo de Velocidad de Fotogramas", + "config.dynamic_fps.frame_rate_target_description": "Establecer el objetivo de FPS en -1 para desactivar la reducción de FPS.", + "config.dynamic_fps.volume_multiplier": "Multiplicador de Volumen", + "config.dynamic_fps.graphics_state": "Opciones Gráficas", + "config.dynamic_fps.show_toasts": "Mostrar Notificaciones", + "config.dynamic_fps.run_garbage_collector": "Ejecutar el Garbage Collector", + + "key.dynamic_fps.toggle_forced": "Forzar el modo desenfocado (Alternar)", + "key.dynamic_fps.toggle_disabled": "Deshabilitar Dynamic FPS (Alternar)", + "gui.dynamic_fps.hud.reducing": "Dynamic FPS: Forzando FPS reducidos", + "gui.dynamic_fps.hud.disabled": "Dynamic FPS Deshabilitado", + + "modmenu.descriptionTranslation.dynamic_fps": "Ajusta dinámicamente los FPS para que Minecraft no acapare recursos en segundo plano." } \ No newline at end of file diff --git a/src/main/resources/assets/dynamic_fps/lang/es_cl.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/es_cl.json similarity index 98% rename from src/main/resources/assets/dynamic_fps/lang/es_cl.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/es_cl.json index 73f4a370..ab685073 100644 --- a/src/main/resources/assets/dynamic_fps/lang/es_cl.json +++ b/platforms/common/src/main/resources/assets/dynamic_fps/lang/es_cl.json @@ -1,21 +1,21 @@ -{ - "config.dynamic_fps.title": "Configurar Dynamic FPS", - - "config.dynamic_fps.category.hovered": "Sobre", - "config.dynamic_fps.category.unfocused": "Desenfocado", - "config.dynamic_fps.category.invisible": "Invisible", - - "config.dynamic_fps.frame_rate_target": "Objetivo de Velocidad de Fotogramas", - "config.dynamic_fps.frame_rate_target_description": "Establecer el objetivo de FPS en -1 para desactivar la reducción de FPS.", - "config.dynamic_fps.volume_multiplier": "Multiplicador de Volumen", - "config.dynamic_fps.graphics_state": "Opciones Gráficas", - "config.dynamic_fps.show_toasts": "Mostrar Notificaciones", - "config.dynamic_fps.run_garbage_collector": "Ejecutar el Garbage Collector", - - "key.dynamic_fps.toggle_forced": "Forzar el modo desenfocado (Alternar)", - "key.dynamic_fps.toggle_disabled": "Deshabilitar Dynamic FPS (Alternar)", - "gui.dynamic_fps.hud.reducing": "Dynamic FPS: Forzando FPS reducidos", - "gui.dynamic_fps.hud.disabled": "Dynamic FPS Deshabilitado", - - "modmenu.descriptionTranslation.dynamic_fps": "Ajusta dinámicamente los FPS para que Minecraft no acapare recursos en segundo plano." +{ + "config.dynamic_fps.title": "Configurar Dynamic FPS", + + "config.dynamic_fps.category.hovered": "Sobre", + "config.dynamic_fps.category.unfocused": "Desenfocado", + "config.dynamic_fps.category.invisible": "Invisible", + + "config.dynamic_fps.frame_rate_target": "Objetivo de Velocidad de Fotogramas", + "config.dynamic_fps.frame_rate_target_description": "Establecer el objetivo de FPS en -1 para desactivar la reducción de FPS.", + "config.dynamic_fps.volume_multiplier": "Multiplicador de Volumen", + "config.dynamic_fps.graphics_state": "Opciones Gráficas", + "config.dynamic_fps.show_toasts": "Mostrar Notificaciones", + "config.dynamic_fps.run_garbage_collector": "Ejecutar el Garbage Collector", + + "key.dynamic_fps.toggle_forced": "Forzar el modo desenfocado (Alternar)", + "key.dynamic_fps.toggle_disabled": "Deshabilitar Dynamic FPS (Alternar)", + "gui.dynamic_fps.hud.reducing": "Dynamic FPS: Forzando FPS reducidos", + "gui.dynamic_fps.hud.disabled": "Dynamic FPS Deshabilitado", + + "modmenu.descriptionTranslation.dynamic_fps": "Ajusta dinámicamente los FPS para que Minecraft no acapare recursos en segundo plano." } \ No newline at end of file diff --git a/src/main/resources/assets/dynamic_fps/lang/es_ec.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/es_ec.json similarity index 98% rename from src/main/resources/assets/dynamic_fps/lang/es_ec.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/es_ec.json index 73f4a370..ab685073 100644 --- a/src/main/resources/assets/dynamic_fps/lang/es_ec.json +++ b/platforms/common/src/main/resources/assets/dynamic_fps/lang/es_ec.json @@ -1,21 +1,21 @@ -{ - "config.dynamic_fps.title": "Configurar Dynamic FPS", - - "config.dynamic_fps.category.hovered": "Sobre", - "config.dynamic_fps.category.unfocused": "Desenfocado", - "config.dynamic_fps.category.invisible": "Invisible", - - "config.dynamic_fps.frame_rate_target": "Objetivo de Velocidad de Fotogramas", - "config.dynamic_fps.frame_rate_target_description": "Establecer el objetivo de FPS en -1 para desactivar la reducción de FPS.", - "config.dynamic_fps.volume_multiplier": "Multiplicador de Volumen", - "config.dynamic_fps.graphics_state": "Opciones Gráficas", - "config.dynamic_fps.show_toasts": "Mostrar Notificaciones", - "config.dynamic_fps.run_garbage_collector": "Ejecutar el Garbage Collector", - - "key.dynamic_fps.toggle_forced": "Forzar el modo desenfocado (Alternar)", - "key.dynamic_fps.toggle_disabled": "Deshabilitar Dynamic FPS (Alternar)", - "gui.dynamic_fps.hud.reducing": "Dynamic FPS: Forzando FPS reducidos", - "gui.dynamic_fps.hud.disabled": "Dynamic FPS Deshabilitado", - - "modmenu.descriptionTranslation.dynamic_fps": "Ajusta dinámicamente los FPS para que Minecraft no acapare recursos en segundo plano." +{ + "config.dynamic_fps.title": "Configurar Dynamic FPS", + + "config.dynamic_fps.category.hovered": "Sobre", + "config.dynamic_fps.category.unfocused": "Desenfocado", + "config.dynamic_fps.category.invisible": "Invisible", + + "config.dynamic_fps.frame_rate_target": "Objetivo de Velocidad de Fotogramas", + "config.dynamic_fps.frame_rate_target_description": "Establecer el objetivo de FPS en -1 para desactivar la reducción de FPS.", + "config.dynamic_fps.volume_multiplier": "Multiplicador de Volumen", + "config.dynamic_fps.graphics_state": "Opciones Gráficas", + "config.dynamic_fps.show_toasts": "Mostrar Notificaciones", + "config.dynamic_fps.run_garbage_collector": "Ejecutar el Garbage Collector", + + "key.dynamic_fps.toggle_forced": "Forzar el modo desenfocado (Alternar)", + "key.dynamic_fps.toggle_disabled": "Deshabilitar Dynamic FPS (Alternar)", + "gui.dynamic_fps.hud.reducing": "Dynamic FPS: Forzando FPS reducidos", + "gui.dynamic_fps.hud.disabled": "Dynamic FPS Deshabilitado", + + "modmenu.descriptionTranslation.dynamic_fps": "Ajusta dinámicamente los FPS para que Minecraft no acapare recursos en segundo plano." } \ No newline at end of file diff --git a/src/main/resources/assets/dynamic_fps/lang/es_es.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/es_es.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/es_es.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/es_es.json diff --git a/src/main/resources/assets/dynamic_fps/lang/es_mx.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/es_mx.json similarity index 98% rename from src/main/resources/assets/dynamic_fps/lang/es_mx.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/es_mx.json index 73f4a370..ab685073 100644 --- a/src/main/resources/assets/dynamic_fps/lang/es_mx.json +++ b/platforms/common/src/main/resources/assets/dynamic_fps/lang/es_mx.json @@ -1,21 +1,21 @@ -{ - "config.dynamic_fps.title": "Configurar Dynamic FPS", - - "config.dynamic_fps.category.hovered": "Sobre", - "config.dynamic_fps.category.unfocused": "Desenfocado", - "config.dynamic_fps.category.invisible": "Invisible", - - "config.dynamic_fps.frame_rate_target": "Objetivo de Velocidad de Fotogramas", - "config.dynamic_fps.frame_rate_target_description": "Establecer el objetivo de FPS en -1 para desactivar la reducción de FPS.", - "config.dynamic_fps.volume_multiplier": "Multiplicador de Volumen", - "config.dynamic_fps.graphics_state": "Opciones Gráficas", - "config.dynamic_fps.show_toasts": "Mostrar Notificaciones", - "config.dynamic_fps.run_garbage_collector": "Ejecutar el Garbage Collector", - - "key.dynamic_fps.toggle_forced": "Forzar el modo desenfocado (Alternar)", - "key.dynamic_fps.toggle_disabled": "Deshabilitar Dynamic FPS (Alternar)", - "gui.dynamic_fps.hud.reducing": "Dynamic FPS: Forzando FPS reducidos", - "gui.dynamic_fps.hud.disabled": "Dynamic FPS Deshabilitado", - - "modmenu.descriptionTranslation.dynamic_fps": "Ajusta dinámicamente los FPS para que Minecraft no acapare recursos en segundo plano." +{ + "config.dynamic_fps.title": "Configurar Dynamic FPS", + + "config.dynamic_fps.category.hovered": "Sobre", + "config.dynamic_fps.category.unfocused": "Desenfocado", + "config.dynamic_fps.category.invisible": "Invisible", + + "config.dynamic_fps.frame_rate_target": "Objetivo de Velocidad de Fotogramas", + "config.dynamic_fps.frame_rate_target_description": "Establecer el objetivo de FPS en -1 para desactivar la reducción de FPS.", + "config.dynamic_fps.volume_multiplier": "Multiplicador de Volumen", + "config.dynamic_fps.graphics_state": "Opciones Gráficas", + "config.dynamic_fps.show_toasts": "Mostrar Notificaciones", + "config.dynamic_fps.run_garbage_collector": "Ejecutar el Garbage Collector", + + "key.dynamic_fps.toggle_forced": "Forzar el modo desenfocado (Alternar)", + "key.dynamic_fps.toggle_disabled": "Deshabilitar Dynamic FPS (Alternar)", + "gui.dynamic_fps.hud.reducing": "Dynamic FPS: Forzando FPS reducidos", + "gui.dynamic_fps.hud.disabled": "Dynamic FPS Deshabilitado", + + "modmenu.descriptionTranslation.dynamic_fps": "Ajusta dinámicamente los FPS para que Minecraft no acapare recursos en segundo plano." } \ No newline at end of file diff --git a/src/main/resources/assets/dynamic_fps/lang/es_uy.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/es_uy.json similarity index 98% rename from src/main/resources/assets/dynamic_fps/lang/es_uy.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/es_uy.json index 73f4a370..ab685073 100644 --- a/src/main/resources/assets/dynamic_fps/lang/es_uy.json +++ b/platforms/common/src/main/resources/assets/dynamic_fps/lang/es_uy.json @@ -1,21 +1,21 @@ -{ - "config.dynamic_fps.title": "Configurar Dynamic FPS", - - "config.dynamic_fps.category.hovered": "Sobre", - "config.dynamic_fps.category.unfocused": "Desenfocado", - "config.dynamic_fps.category.invisible": "Invisible", - - "config.dynamic_fps.frame_rate_target": "Objetivo de Velocidad de Fotogramas", - "config.dynamic_fps.frame_rate_target_description": "Establecer el objetivo de FPS en -1 para desactivar la reducción de FPS.", - "config.dynamic_fps.volume_multiplier": "Multiplicador de Volumen", - "config.dynamic_fps.graphics_state": "Opciones Gráficas", - "config.dynamic_fps.show_toasts": "Mostrar Notificaciones", - "config.dynamic_fps.run_garbage_collector": "Ejecutar el Garbage Collector", - - "key.dynamic_fps.toggle_forced": "Forzar el modo desenfocado (Alternar)", - "key.dynamic_fps.toggle_disabled": "Deshabilitar Dynamic FPS (Alternar)", - "gui.dynamic_fps.hud.reducing": "Dynamic FPS: Forzando FPS reducidos", - "gui.dynamic_fps.hud.disabled": "Dynamic FPS Deshabilitado", - - "modmenu.descriptionTranslation.dynamic_fps": "Ajusta dinámicamente los FPS para que Minecraft no acapare recursos en segundo plano." +{ + "config.dynamic_fps.title": "Configurar Dynamic FPS", + + "config.dynamic_fps.category.hovered": "Sobre", + "config.dynamic_fps.category.unfocused": "Desenfocado", + "config.dynamic_fps.category.invisible": "Invisible", + + "config.dynamic_fps.frame_rate_target": "Objetivo de Velocidad de Fotogramas", + "config.dynamic_fps.frame_rate_target_description": "Establecer el objetivo de FPS en -1 para desactivar la reducción de FPS.", + "config.dynamic_fps.volume_multiplier": "Multiplicador de Volumen", + "config.dynamic_fps.graphics_state": "Opciones Gráficas", + "config.dynamic_fps.show_toasts": "Mostrar Notificaciones", + "config.dynamic_fps.run_garbage_collector": "Ejecutar el Garbage Collector", + + "key.dynamic_fps.toggle_forced": "Forzar el modo desenfocado (Alternar)", + "key.dynamic_fps.toggle_disabled": "Deshabilitar Dynamic FPS (Alternar)", + "gui.dynamic_fps.hud.reducing": "Dynamic FPS: Forzando FPS reducidos", + "gui.dynamic_fps.hud.disabled": "Dynamic FPS Deshabilitado", + + "modmenu.descriptionTranslation.dynamic_fps": "Ajusta dinámicamente los FPS para que Minecraft no acapare recursos en segundo plano." } \ No newline at end of file diff --git a/src/main/resources/assets/dynamic_fps/lang/es_ve.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/es_ve.json similarity index 98% rename from src/main/resources/assets/dynamic_fps/lang/es_ve.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/es_ve.json index 73f4a370..ab685073 100644 --- a/src/main/resources/assets/dynamic_fps/lang/es_ve.json +++ b/platforms/common/src/main/resources/assets/dynamic_fps/lang/es_ve.json @@ -1,21 +1,21 @@ -{ - "config.dynamic_fps.title": "Configurar Dynamic FPS", - - "config.dynamic_fps.category.hovered": "Sobre", - "config.dynamic_fps.category.unfocused": "Desenfocado", - "config.dynamic_fps.category.invisible": "Invisible", - - "config.dynamic_fps.frame_rate_target": "Objetivo de Velocidad de Fotogramas", - "config.dynamic_fps.frame_rate_target_description": "Establecer el objetivo de FPS en -1 para desactivar la reducción de FPS.", - "config.dynamic_fps.volume_multiplier": "Multiplicador de Volumen", - "config.dynamic_fps.graphics_state": "Opciones Gráficas", - "config.dynamic_fps.show_toasts": "Mostrar Notificaciones", - "config.dynamic_fps.run_garbage_collector": "Ejecutar el Garbage Collector", - - "key.dynamic_fps.toggle_forced": "Forzar el modo desenfocado (Alternar)", - "key.dynamic_fps.toggle_disabled": "Deshabilitar Dynamic FPS (Alternar)", - "gui.dynamic_fps.hud.reducing": "Dynamic FPS: Forzando FPS reducidos", - "gui.dynamic_fps.hud.disabled": "Dynamic FPS Deshabilitado", - - "modmenu.descriptionTranslation.dynamic_fps": "Ajusta dinámicamente los FPS para que Minecraft no acapare recursos en segundo plano." +{ + "config.dynamic_fps.title": "Configurar Dynamic FPS", + + "config.dynamic_fps.category.hovered": "Sobre", + "config.dynamic_fps.category.unfocused": "Desenfocado", + "config.dynamic_fps.category.invisible": "Invisible", + + "config.dynamic_fps.frame_rate_target": "Objetivo de Velocidad de Fotogramas", + "config.dynamic_fps.frame_rate_target_description": "Establecer el objetivo de FPS en -1 para desactivar la reducción de FPS.", + "config.dynamic_fps.volume_multiplier": "Multiplicador de Volumen", + "config.dynamic_fps.graphics_state": "Opciones Gráficas", + "config.dynamic_fps.show_toasts": "Mostrar Notificaciones", + "config.dynamic_fps.run_garbage_collector": "Ejecutar el Garbage Collector", + + "key.dynamic_fps.toggle_forced": "Forzar el modo desenfocado (Alternar)", + "key.dynamic_fps.toggle_disabled": "Deshabilitar Dynamic FPS (Alternar)", + "gui.dynamic_fps.hud.reducing": "Dynamic FPS: Forzando FPS reducidos", + "gui.dynamic_fps.hud.disabled": "Dynamic FPS Deshabilitado", + + "modmenu.descriptionTranslation.dynamic_fps": "Ajusta dinámicamente los FPS para que Minecraft no acapare recursos en segundo plano." } \ No newline at end of file diff --git a/src/main/resources/assets/dynamic_fps/lang/et_ee.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/et_ee.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/et_ee.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/et_ee.json diff --git a/src/main/resources/assets/dynamic_fps/lang/fr_ca.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/fr_ca.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/fr_ca.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/fr_ca.json diff --git a/src/main/resources/assets/dynamic_fps/lang/fr_fr.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/fr_fr.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/fr_fr.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/fr_fr.json diff --git a/src/main/resources/assets/dynamic_fps/lang/it_it.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/it_it.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/it_it.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/it_it.json diff --git a/src/main/resources/assets/dynamic_fps/lang/ko_kr.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/ko_kr.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/ko_kr.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/ko_kr.json diff --git a/src/main/resources/assets/dynamic_fps/lang/lol_us.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/lol_us.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/lol_us.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/lol_us.json diff --git a/src/main/resources/assets/dynamic_fps/lang/pl_pl.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/pl_pl.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/pl_pl.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/pl_pl.json diff --git a/src/main/resources/assets/dynamic_fps/lang/pt_br.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/pt_br.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/pt_br.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/pt_br.json diff --git a/src/main/resources/assets/dynamic_fps/lang/pt_pt.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/pt_pt.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/pt_pt.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/pt_pt.json diff --git a/src/main/resources/assets/dynamic_fps/lang/ru_ru.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/ru_ru.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/ru_ru.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/ru_ru.json diff --git a/src/main/resources/assets/dynamic_fps/lang/sv_se.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/sv_se.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/sv_se.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/sv_se.json diff --git a/src/main/resources/assets/dynamic_fps/lang/tr_tr.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/tr_tr.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/tr_tr.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/tr_tr.json diff --git a/src/main/resources/assets/dynamic_fps/lang/uk_ua.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/uk_ua.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/uk_ua.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/uk_ua.json diff --git a/src/main/resources/assets/dynamic_fps/lang/vi_vn.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/vi_vn.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/vi_vn.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/vi_vn.json diff --git a/src/main/resources/assets/dynamic_fps/lang/zh_cn.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/zh_cn.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/zh_cn.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/zh_cn.json diff --git a/src/main/resources/assets/dynamic_fps/lang/zh_hk.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/zh_hk.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/zh_hk.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/zh_hk.json diff --git a/src/main/resources/assets/dynamic_fps/lang/zh_tw.json b/platforms/common/src/main/resources/assets/dynamic_fps/lang/zh_tw.json similarity index 100% rename from src/main/resources/assets/dynamic_fps/lang/zh_tw.json rename to platforms/common/src/main/resources/assets/dynamic_fps/lang/zh_tw.json diff --git a/platforms/common/src/main/resources/dynamic_fps-common.mixins.json b/platforms/common/src/main/resources/dynamic_fps-common.mixins.json new file mode 100644 index 00000000..33486bf4 --- /dev/null +++ b/platforms/common/src/main/resources/dynamic_fps-common.mixins.json @@ -0,0 +1,24 @@ +{ + "required": true, + "package": "dynamic_fps.impl.mixin", + "compatibilityLevel": "JAVA_17", + "minVersion": "0.8", + "client": [ + "DebugScreenOverlayMixin", + "GameRendererMixin", + "GuiMixin", + "LoadingOverlayMixin", + "MinecraftMixin", + "ScreenMixin", + "SoundEngineMixin", + "StatsScreenMixin", + "ToastComponentMixin", + "WindowMixin", + "bugfix.BlockableEventLoopMixin" + ], + "mixins": [], + "server": [], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/platforms/common/src/main/resources/dynamic_fps.accesswidener b/platforms/common/src/main/resources/dynamic_fps.accesswidener new file mode 100644 index 00000000..d152300b --- /dev/null +++ b/platforms/common/src/main/resources/dynamic_fps.accesswidener @@ -0,0 +1,13 @@ +accessWidener v2 named + +accessible field com/mojang/blaze3d/platform/Window window J +accessible field net/minecraft/client/sounds/SoundManager soundEngine Lnet/minecraft/client/sounds/SoundEngine; + +# Temporary fix for the NeoForge build +accessible field net/minecraft/client/gui/screens/LoadingOverlay fadeOutStart J +accessible field net/minecraft/client/Minecraft window Lcom/mojang/blaze3d/platform/Window; +accessible field net/minecraft/client/sounds/SoundEngine options Lnet/minecraft/client/Options; +accessible field net/minecraft/client/sounds/SoundEngine loaded Z +accessible field net/minecraft/client/sounds/SoundEngine listener Lcom/mojang/blaze3d/audio/Listener; +accessible field net/minecraft/client/sounds/SoundEngine instanceToChannel Ljava/util/Map; +accessible method net/minecraft/client/sounds/SoundEngine calculateVolume (Lnet/minecraft/client/resources/sounds/SoundInstance;)F diff --git a/platforms/fabric/build.gradle b/platforms/fabric/build.gradle new file mode 100644 index 00000000..9abd6bab --- /dev/null +++ b/platforms/fabric/build.gradle @@ -0,0 +1,81 @@ +plugins { + alias libs.plugins.shadow +} + +repositories { + maven { url = "https://maven.terraformersmc.com/releases" } // modmenu +} + +architectury { + platformSetupLoomIde() + fabric() +} + +loom { + accessWidenerPath = project(":platforms:common").loom.accessWidenerPath +} + +configurations { + common + shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files. + compileClasspath.extendsFrom common + runtimeClasspath.extendsFrom common + developmentFabric.extendsFrom common +} + +dependencies { + modImplementation(libs.fabric.loader) + + modImplementation(fabricApi.module("fabric-resource-loader-v0", libs.versions.fabric.api.get())) + modImplementation(fabricApi.module("fabric-lifecycle-events-v1", libs.versions.fabric.api.get())) + + modApi(libs.modmenu) + + common(project(path: ":platforms:common", configuration: "namedElements")) { transitive false } + shadowCommon(project(path: ":platforms:common", configuration: "transformProductionFabric")) { transitive false } +} + +processResources { + inputs.property "version", rootProject.mod_version + + filesMatching("fabric.mod.json") { + expand "version": rootProject.mod_version + } +} + +shadowJar { + exclude "architectury.common.json" + configurations = [project.configurations.shadowCommon] +} + +remapJar { + injectAccessWidener = true + input.set shadowJar.archiveFile + dependsOn shadowJar +} + +sourcesJar { + def commonSources = project(":platforms:common").sourcesJar + dependsOn commonSources + from commonSources.archiveFile.map { zipTree(it) } +} + +components.java { + withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { + skip() + } +} + +publishing { + publications { + mavenFabric(MavenPublication) { + artifactId = rootProject.archives_base_name + "-" + project.name + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + } +} diff --git a/platforms/fabric/gradle.properties b/platforms/fabric/gradle.properties new file mode 100644 index 00000000..e846a8f5 --- /dev/null +++ b/platforms/fabric/gradle.properties @@ -0,0 +1 @@ +loom.platform=fabric diff --git a/platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/DynamicFPSFabricMod.java b/platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/DynamicFPSFabricMod.java new file mode 100644 index 00000000..da2b6547 --- /dev/null +++ b/platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/DynamicFPSFabricMod.java @@ -0,0 +1,11 @@ +package net.lostluma.dynamic_fps.impl.fabric; + +import dynamic_fps.impl.DynamicFPSMod; +import net.fabricmc.api.ClientModInitializer; + +public class DynamicFPSFabricMod implements ClientModInitializer { + @Override + public void onInitializeClient() { + DynamicFPSMod.init(); + } +} diff --git a/src/main/java/dynamic_fps/impl/compat/FREX.java b/platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/compat/FREX.java similarity index 96% rename from src/main/java/dynamic_fps/impl/compat/FREX.java rename to platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/compat/FREX.java index a4d1815b..ff17b488 100644 --- a/src/main/java/dynamic_fps/impl/compat/FREX.java +++ b/platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/compat/FREX.java @@ -1,4 +1,4 @@ -package dynamic_fps.impl.compat; +package net.lostluma.dynamic_fps.impl.fabric.compat; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.loader.api.FabricLoader; diff --git a/src/main/java/dynamic_fps/impl/compat/ModMenu.java b/platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/compat/ModMenu.java similarity index 83% rename from src/main/java/dynamic_fps/impl/compat/ModMenu.java rename to platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/compat/ModMenu.java index 65822485..4866f736 100644 --- a/src/main/java/dynamic_fps/impl/compat/ModMenu.java +++ b/platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/compat/ModMenu.java @@ -1,8 +1,9 @@ -package dynamic_fps.impl.compat; +package net.lostluma.dynamic_fps.impl.fabric.compat; import com.terraformersmc.modmenu.api.ConfigScreenFactory; import com.terraformersmc.modmenu.api.ModMenuApi; +import dynamic_fps.impl.compat.ClothConfig; import net.fabricmc.loader.api.FabricLoader; public class ModMenu implements ModMenuApi { diff --git a/src/main/java/dynamic_fps/impl/mixin/GuiMixin.java b/platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/mixin/GuiMixin.java similarity index 69% rename from src/main/java/dynamic_fps/impl/mixin/GuiMixin.java rename to platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/mixin/GuiMixin.java index 7e284411..ab5e81ce 100644 --- a/src/main/java/dynamic_fps/impl/mixin/GuiMixin.java +++ b/platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/mixin/GuiMixin.java @@ -1,28 +1,16 @@ -package dynamic_fps.impl.mixin; +package net.lostluma.dynamic_fps.impl.fabric.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; -import dynamic_fps.impl.DynamicFPSMod; -import net.minecraft.client.gui.Gui; - @Mixin(Gui.class) public class GuiMixin { - /** - * Cancels rendering the GUI if it is determined to currently not be visible. - */ - @Inject(method = "render", at = @At("HEAD"), cancellable = true) - private void shouldRender(CallbackInfo callbackInfo) { - if (!DynamicFPSMod.shouldShowLevels()) { - callbackInfo.cancel(); - } - } - /** * Render info on whether Dynamic FPS is disabled or always reducing the user's FPS. */ diff --git a/platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/mixin/OptionsMixin.java b/platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/mixin/OptionsMixin.java new file mode 100644 index 00000000..a2719038 --- /dev/null +++ b/platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/mixin/OptionsMixin.java @@ -0,0 +1,39 @@ +package net.lostluma.dynamic_fps.impl.fabric.mixin; + +import com.google.common.collect.Lists; +import dynamic_fps.impl.util.KeyMappingHandler; +import net.minecraft.client.KeyMapping; +import net.minecraft.client.Options; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.Pseudo; +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; + +import java.util.List; + +@Mixin(Options.class) +@Pseudo +public class OptionsMixin { + @Shadow + @Final + @Mutable + public KeyMapping[] keyMappings; + + /** + * Add the mod's key mappings to the vanilla options screen. + */ + @Inject(method = "load", at = @At("HEAD")) + private void load(CallbackInfo callbackInfo) { + List mappings = Lists.newArrayList(this.keyMappings); + + for (KeyMappingHandler handler : KeyMappingHandler.getHandlers()) { + mappings.add(handler.keyMapping()); + } + + this.keyMappings = mappings.toArray(new KeyMapping[0]); + } +} diff --git a/src/main/java/dynamic_fps/impl/util/ModCompatibility.java b/platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/service/FabricModCompat.java similarity index 79% rename from src/main/java/dynamic_fps/impl/util/ModCompatibility.java rename to platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/service/FabricModCompat.java index 16e7a31a..81f5d6b5 100644 --- a/src/main/java/dynamic_fps/impl/util/ModCompatibility.java +++ b/platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/service/FabricModCompat.java @@ -1,34 +1,44 @@ -package dynamic_fps.impl.util; +package net.lostluma.dynamic_fps.impl.fabric.service; +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.fabric.compat.FREX; import org.jetbrains.annotations.Nullable; import java.util.HashSet; import java.util.Set; -public class ModCompatibility { +public class FabricModCompat 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(ModCompatibility::parseModMetadata); + FabricLoader.getInstance().getAllMods().forEach(FabricModCompat::parseModMetadata); } - public static boolean disableOverlayOptimization() { + @Override + public boolean isDisabled() { + return FREX.isFlawlessFramesActive(); + } + + @Override + public boolean disableOverlayOptimization() { return disableOverlayOptimization; } - public static boolean isScreenOptedIn(String className) { + @Override + public boolean isScreenOptedIn(String className) { return optedInScreens.contains(className); } - public static boolean isScreenOptedOut(String className) { + @Override + public boolean isScreenOptedOut(String className) { return optedOutScreens.contains(className); } diff --git a/src/main/java/dynamic_fps/impl/service/FabricPlatform.java b/platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/service/FabricPlatform.java similarity index 65% rename from src/main/java/dynamic_fps/impl/service/FabricPlatform.java rename to platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/service/FabricPlatform.java index 233cbc7d..3cd0cfc3 100644 --- a/src/main/java/dynamic_fps/impl/service/FabricPlatform.java +++ b/platforms/fabric/src/main/java/net/lostluma/dynamic_fps/impl/fabric/service/FabricPlatform.java @@ -1,14 +1,33 @@ -package dynamic_fps.impl.service; +package net.lostluma.dynamic_fps.impl.fabric.service; import dynamic_fps.impl.Constants; +import dynamic_fps.impl.service.Platform; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Optional; public class FabricPlatform implements Platform { + @Override + public String getName() { + return "Fabric"; + } + + @Override + public String modVersion() { + Optional optional = FabricLoader.getInstance().getModContainer(Constants.MOD_ID); + + if (optional.isPresent()) { + return optional.get().getMetadata().getVersion().getFriendlyString(); + } else { + throw new RuntimeException("Own mod container is somehow not available!"); + } + } + @Override public Path getCacheDir() { Path base = FabricLoader.getInstance().getGameDir(); diff --git a/platforms/fabric/src/main/resources/META-INF/services/dynamic_fps.impl.service.ModCompat b/platforms/fabric/src/main/resources/META-INF/services/dynamic_fps.impl.service.ModCompat new file mode 100644 index 00000000..e6c39798 --- /dev/null +++ b/platforms/fabric/src/main/resources/META-INF/services/dynamic_fps.impl.service.ModCompat @@ -0,0 +1 @@ +net.lostluma.dynamic_fps.impl.fabric.service.FabricModCompat diff --git a/platforms/fabric/src/main/resources/META-INF/services/dynamic_fps.impl.service.Platform b/platforms/fabric/src/main/resources/META-INF/services/dynamic_fps.impl.service.Platform new file mode 100644 index 00000000..93514d69 --- /dev/null +++ b/platforms/fabric/src/main/resources/META-INF/services/dynamic_fps.impl.service.Platform @@ -0,0 +1 @@ +net.lostluma.dynamic_fps.impl.fabric.service.FabricPlatform diff --git a/platforms/fabric/src/main/resources/dynamic_fps.mixins.json b/platforms/fabric/src/main/resources/dynamic_fps.mixins.json new file mode 100644 index 00000000..f9a16703 --- /dev/null +++ b/platforms/fabric/src/main/resources/dynamic_fps.mixins.json @@ -0,0 +1,15 @@ +{ + "required": true, + "package": "net.lostluma.dynamic_fps.impl.fabric.mixin", + "compatibilityLevel": "JAVA_17", + "minVersion": "0.8", + "client": [ + "GuiMixin", + "OptionsMixin" + ], + "mixins": [], + "server": [], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/platforms/fabric/src/main/resources/fabric.mod.json b/platforms/fabric/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..ee6e2c0a --- /dev/null +++ b/platforms/fabric/src/main/resources/fabric.mod.json @@ -0,0 +1,90 @@ +{ + "schemaVersion": 1, + "id": "dynamic_fps", + "version": "${version}", + "name": "Dynamic FPS", + "description": "Dynamically adjusts FPS so Minecraft doesn't hog resources in the background.", + "authors": [ + "juliand665", + "LostLuma" + ], + "contact": { + "homepage": "https://dapprgames.com/mods", + "issues": "https://github.com/juliand665/Dynamic-FPS/issues", + "sources": "https://github.com/juliand665/Dynamic-FPS" + }, + "license": "MIT", + "icon": "assets/dynamic_fps/icon.png", + "environment": "client", + "entrypoints": { + "client": [ + "net.lostluma.dynamic_fps.impl.fabric.compat.FREX", + "net.lostluma.dynamic_fps.impl.fabric.DynamicFPSFabricMod" + ], + "modmenu": [ + "net.lostluma.dynamic_fps.impl.fabric.compat.ModMenu" + ] + }, + "depends": { + "fabricloader": ">=0.15.0", + "minecraft": ">=1.20.0", + "mixinextras": ">=0.3.2", + "fabric-resource-loader-v0": "*", + "fabric-lifecycle-events-v1": "*" + }, + "conflicts": { + "optifabric": "*", + "smoothmenu": "*" + }, + "recommends": { + "modmenu": "*", + "cloth-config": "*", + "quilt_loader": "*" + }, + "breaks": { + "fastload": "<=3.4.0" + }, + "mixins": [ + "dynamic_fps.mixins.json", + "dynamic_fps-common.mixins.json" + ], + "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 new file mode 100644 index 00000000..c7381cd6 --- /dev/null +++ b/platforms/forge/build.gradle @@ -0,0 +1,87 @@ +plugins { + alias libs.plugins.shadow +} + +architectury { + platformSetupLoomIde() + forge() +} + +loom { + accessWidenerPath = project(":platforms:common").loom.accessWidenerPath + + forge { + convertAccessWideners = true + extraAccessWideners.add loom.accessWidenerPath.get().asFile.name + + mixinConfig "dynamic_fps.mixins.json" + mixinConfig "dynamic_fps-common.mixins.json" + } +} + +configurations { + common + shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files. + compileClasspath.extendsFrom common + runtimeClasspath.extendsFrom common + developmentForge.extendsFrom common +} + +dependencies { + forge libs.forge + + compileOnly(libs.mixinextras.common) + annotationProcessor(libs.mixinextras.common) + + include(libs.mixinextras.forge) + implementation(libs.mixinextras.forge) + + common(project(path: ":platforms:common", configuration: "namedElements")) { transitive false } + shadowCommon(project(path: ":platforms:common", configuration: "transformProductionForge")) { transitive = false } +} + +processResources { + inputs.property "version", rootProject.mod_version + + filesMatching("META-INF/mods.toml") { + expand "version": rootProject.mod_version + } +} + +shadowJar { + exclude "fabric.mod.json" + exclude "architectury.common.json" + + configurations = [project.configurations.shadowCommon] +} + +remapJar { + input.set shadowJar.archiveFile + dependsOn shadowJar +} + +sourcesJar { + def commonSources = project(":platforms:common").sourcesJar + dependsOn commonSources + from commonSources.archiveFile.map { zipTree(it) } +} + +components.java { + withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { + skip() + } +} + +publishing { + publications { + mavenForge(MavenPublication) { + artifactId = rootProject.archives_base_name + "-" + project.name + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + } +} diff --git a/platforms/forge/gradle.properties b/platforms/forge/gradle.properties new file mode 100644 index 00000000..82425854 --- /dev/null +++ b/platforms/forge/gradle.properties @@ -0,0 +1 @@ +loom.platform=forge 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 new file mode 100644 index 00000000..29a4106a --- /dev/null +++ b/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/DynamicFPSForgeMod.java @@ -0,0 +1,65 @@ +package net.lostluma.dynamic_fps.impl.forge; + +import dynamic_fps.impl.Constants; +import dynamic_fps.impl.DynamicFPSMod; +import dynamic_fps.impl.compat.ClothConfig; +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; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.fml.loading.FMLLoader; + +import java.util.ArrayList; +import java.util.List; + +@Mod(Constants.MOD_ID) +public class DynamicFPSForgeMod { + private static final List TICK_EVENT_LISTENERS = new ArrayList<>(); + + public DynamicFPSForgeMod() { + if (FMLLoader.getDist().isDedicatedServer()) { + return; + } + + DynamicFPSMod.init(); + + ModLoadingContext.get().registerExtensionPoint( + ConfigScreenHandler.ConfigScreenFactory.class, + () -> new ConfigScreenHandler.ConfigScreenFactory( + (minecraft, screen) -> ClothConfig.genConfigScreen(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) { + for (KeyMappingHandler handler : KeyMappingHandler.getHandlers()) { + event.register(handler.keyMapping()); + } + } + + public void onClientTick(TickEvent.ClientTickEvent event) { + for (Platform.StartTickEvent listener : TICK_EVENT_LISTENERS) { + listener.onStartTick(); + } + } + + public static void addTickEventListener(Platform.StartTickEvent event) { + TICK_EVENT_LISTENERS.add(event); + } +} 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 new file mode 100644 index 00000000..f3722f7b --- /dev/null +++ b/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/service/ForgeModCompat.java @@ -0,0 +1,27 @@ +package net.lostluma.dynamic_fps.impl.forge.service; + +import dynamic_fps.impl.service.ModCompat; +import net.minecraft.client.gui.screens.ReceivingLevelScreen; +import net.minecraftforge.fml.ModList; + +public class ForgeModCompat implements ModCompat { + @Override + public boolean isDisabled() { + return false; + } + + @Override + public boolean disableOverlayOptimization() { + return ModList.get().isLoaded("rrls"); + } + + @Override + public boolean isScreenOptedIn(String className) { + return false; + } + + @Override + public boolean isScreenOptedOut(String className) { + return ReceivingLevelScreen.class.getCanonicalName().equals(className); + } +} 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 new file mode 100644 index 00000000..70f73858 --- /dev/null +++ b/platforms/forge/src/main/java/net/lostluma/dynamic_fps/impl/forge/service/ForgePlatform.java @@ -0,0 +1,64 @@ +package net.lostluma.dynamic_fps.impl.forge.service; + +import dynamic_fps.impl.Constants; +import dynamic_fps.impl.service.Platform; +import net.lostluma.dynamic_fps.impl.forge.DynamicFPSForgeMod; +import net.minecraftforge.fml.ModContainer; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.loading.FMLLoader; +import net.minecraftforge.fml.loading.FMLPaths; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Optional; + +public class ForgePlatform implements Platform { + + @Override + public String getName() { + return "Forge"; + } + + @Override + public String modVersion() { + Optional optional = ModList.get().getModContainerById(Constants.MOD_ID); + + if (optional.isPresent()) { + return optional.get().getModInfo().getVersion().toString(); + } else { + throw new RuntimeException("Own mod container is somehow not available!"); + } + } + + @Override + public Path getCacheDir() { + Path base = FMLPaths.GAMEDIR.get(); + return this.ensureDir(base.resolve(".cache").resolve(Constants.MOD_ID)); + } + + @Override + public Path getConfigDir() { + return FMLPaths.CONFIGDIR.get(); + } + + @Override + public boolean isDevelopmentEnvironment() { + return !FMLLoader.isProduction(); + } + + @Override + public void registerStartTickEvent(StartTickEvent event) { + DynamicFPSForgeMod.addTickEventListener(event); + } + + private Path ensureDir(Path path) { + try { + Files.createDirectories(path); + } catch (IOException e) { + throw new RuntimeException("Failed to create Dynamic FPS directory.", e); + } + + return path; + } +} diff --git a/platforms/forge/src/main/resources/META-INF/mods.toml b/platforms/forge/src/main/resources/META-INF/mods.toml new file mode 100644 index 00000000..fd16cdc9 --- /dev/null +++ b/platforms/forge/src/main/resources/META-INF/mods.toml @@ -0,0 +1,38 @@ +modLoader = "javafml" +loaderVersion = "[1,)" +license = "MIT" +issueTrackerURL = "https://github.com/juliand665/Dynamic-FPS/issues" + +[[mods]] +modId = "dynamic_fps" +namespace = "net.lostluma" +version = "${version}" +displayName = "Dynamic FPS" +authors = "juliand665 & LostLuma" +description = "Dynamically adjusts FPS so Minecraft doesn't hog resources in the background." +logoFile = "assets/dynamic_fps/icon.png" +displayTest = "IGNORE_ALL_VERSION" +updateJSONURL = "https://api.lostluma.net/updates/dynamic-fps?platform=forge" + +[[mixins]] +config = "dynamic_fps.mixins.json" + +[[mixins]] +config = "dynamic_fps-common.mixins.json" + +[[accessTransformers]] +file="META-INF/accesstransformer.cfg" + +[[dependencies.dynamic_fps]] +modId = "minecraft" +mandatory = true +versionRange = "[1.20.0,)" +ordering = "NONE" +side = "CLIENT" + +[[dependencies.dynamic_fps]] +modId = "cloth_config" +mandatory = true +versionRange = "[1,)" +ordering = "NONE" +side = "CLIENT" diff --git a/platforms/forge/src/main/resources/META-INF/services/dynamic_fps.impl.service.ModCompat b/platforms/forge/src/main/resources/META-INF/services/dynamic_fps.impl.service.ModCompat new file mode 100644 index 00000000..69b053f8 --- /dev/null +++ b/platforms/forge/src/main/resources/META-INF/services/dynamic_fps.impl.service.ModCompat @@ -0,0 +1 @@ +net.lostluma.dynamic_fps.impl.forge.service.ForgeModCompat diff --git a/platforms/forge/src/main/resources/META-INF/services/dynamic_fps.impl.service.Platform b/platforms/forge/src/main/resources/META-INF/services/dynamic_fps.impl.service.Platform new file mode 100644 index 00000000..43ca049e --- /dev/null +++ b/platforms/forge/src/main/resources/META-INF/services/dynamic_fps.impl.service.Platform @@ -0,0 +1 @@ +net.lostluma.dynamic_fps.impl.forge.service.ForgePlatform diff --git a/platforms/forge/src/main/resources/dynamic_fps.mixins.json b/platforms/forge/src/main/resources/dynamic_fps.mixins.json new file mode 100644 index 00000000..36a7f8d0 --- /dev/null +++ b/platforms/forge/src/main/resources/dynamic_fps.mixins.json @@ -0,0 +1,12 @@ +{ + "required": true, + "package": "net.lostluma.dynamic_fps.impl.forge.mixin", + "compatibilityLevel": "JAVA_17", + "minVersion": "0.8", + "client": [], + "mixins": [], + "server": [], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/platforms/forge/src/main/resources/pack.mcmeta b/platforms/forge/src/main/resources/pack.mcmeta new file mode 100644 index 00000000..73c6bc07 --- /dev/null +++ b/platforms/forge/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "Dynamic FPS", + "pack_format": 15 + } +} diff --git a/platforms/neoforge/build.gradle b/platforms/neoforge/build.gradle new file mode 100644 index 00000000..3a4d1a58 --- /dev/null +++ b/platforms/neoforge/build.gradle @@ -0,0 +1,90 @@ +plugins { + alias libs.plugins.shadow +} + +architectury { + platformSetupLoomIde() + neoForge() +} + +loom { + accessWidenerPath = project(":platforms:common").loom.accessWidenerPath +} + +configurations { + common + shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files. + compileClasspath.extendsFrom common + runtimeClasspath.extendsFrom common + developmentForge.extendsFrom common +} + +repositories { + maven { + name = 'NeoForged' + url = 'https://maven.neoforged.net/releases' + } +} + +dependencies { + neoForge libs.neoforge + + common(project(path: ":platforms:common", configuration: "namedElements")) { transitive false } + shadowCommon(project(path: ":platforms:common", configuration: "transformProductionForge")) { transitive = false } +} + +processResources { + inputs.property "version", rootProject.mod_version + + filesMatching("META-INF/mods.toml") { + expand "version": rootProject.mod_version + } +} + +shadowJar { + exclude "fabric.mod.json" + exclude "architectury.common.json" + + exclude "assets/dynamic_fps/icon.png" + + // Sue me + // Fixes crash in prod from our GameRenderer mixin + // Idk anything about NeoForge, if you do explain. + exclude "dynamic-fps-platforms_common-refmap.json" + + configurations = [project.configurations.shadowCommon] +} + +remapJar { + input.set shadowJar.archiveFile + dependsOn shadowJar + + injectAccessWidener.set(true) + atAccessWideners.add("dynamic_fps.accesswidener") +} + +sourcesJar { + def commonSources = project(":platforms:common").sourcesJar + dependsOn commonSources + from commonSources.archiveFile.map { zipTree(it) } +} + +components.java { + withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { + skip() + } +} + +publishing { + publications { + mavenForge(MavenPublication) { + artifactId = rootProject.archives_base_name + "-" + project.name + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + } +} diff --git a/platforms/neoforge/gradle.properties b/platforms/neoforge/gradle.properties new file mode 100644 index 00000000..7da18ea6 --- /dev/null +++ b/platforms/neoforge/gradle.properties @@ -0,0 +1 @@ +loom.platform=neoforge 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 new file mode 100644 index 00000000..7fa09b85 --- /dev/null +++ b/platforms/neoforge/src/main/java/net/lostluma/dynamic_fps/impl/neoforge/DynamicFPSNeoForgeMod.java @@ -0,0 +1,46 @@ +package net.lostluma.dynamic_fps.impl.neoforge; + +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.RenderGuiOverlayEvent; +import net.neoforged.neoforge.common.NeoForge; + +@Mod(Constants.MOD_ID) +public class DynamicFPSNeoForgeMod { + public DynamicFPSNeoForgeMod(IEventBus modEventBus) { + if (FMLLoader.getDist().isDedicatedServer()) { + return; + } + + DynamicFPSMod.init(); + + ModLoadingContext.get().registerExtensionPoint( + ConfigScreenHandler.ConfigScreenFactory.class, + () -> new ConfigScreenHandler.ConfigScreenFactory( + (minecraft, screen) -> ClothConfig.genConfigScreen(screen) + ) + ); + + modEventBus.addListener(this::registerKeyMappings); + NeoForge.EVENT_BUS.addListener(this::renderGuiOverlay); + } + + public void renderGuiOverlay(RenderGuiOverlayEvent.Pre event) { + HudInfoRenderer.renderInfo(event.getGuiGraphics()); + } + + public void registerKeyMappings(RegisterKeyMappingsEvent event) { + for (KeyMappingHandler handler : KeyMappingHandler.getHandlers()) { + event.register(handler.keyMapping()); + } + } +} 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 new file mode 100644 index 00000000..7302daee --- /dev/null +++ b/platforms/neoforge/src/main/java/net/lostluma/dynamic_fps/impl/neoforge/service/NeoForgeModCompat.java @@ -0,0 +1,27 @@ +package net.lostluma.dynamic_fps.impl.neoforge.service; + +import dynamic_fps.impl.service.ModCompat; +import net.minecraft.client.gui.screens.ReceivingLevelScreen; +import net.neoforged.fml.ModList; + +public class NeoForgeModCompat implements ModCompat { + @Override + public boolean isDisabled() { + return false; + } + + @Override + public boolean disableOverlayOptimization() { + return ModList.get().isLoaded("rrls"); + } + + @Override + public boolean isScreenOptedIn(String className) { + return false; + } + + @Override + public boolean isScreenOptedOut(String className) { + return ReceivingLevelScreen.class.getCanonicalName().equals(className); + } +} 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 new file mode 100644 index 00000000..7fa07c97 --- /dev/null +++ b/platforms/neoforge/src/main/java/net/lostluma/dynamic_fps/impl/neoforge/service/NeoForgePlatform.java @@ -0,0 +1,68 @@ +package net.lostluma.dynamic_fps.impl.neoforge.service; + +import dynamic_fps.impl.Constants; +import dynamic_fps.impl.service.Platform; +import net.neoforged.bus.EventBus; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.fml.ModContainer; +import net.neoforged.fml.ModList; +import net.neoforged.fml.loading.FMLLoader; +import net.neoforged.fml.loading.FMLPaths; +import net.neoforged.neoforge.client.ClientHooks; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.common.NeoForgeEventHandler; +import net.neoforged.neoforge.event.TickEvent; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Optional; + +public class NeoForgePlatform implements Platform { + @Override + public String getName() { + return "NeoForge"; + } + + @Override + public String modVersion() { + Optional optional = ModList.get().getModContainerById(Constants.MOD_ID); + + if (optional.isPresent()) { + return optional.get().getModInfo().getVersion().toString(); + } else { + throw new RuntimeException("Own mod container is somehow not available!"); + } + } + + @Override + public Path getCacheDir() { + Path base = FMLPaths.GAMEDIR.get(); + return this.ensureDir(base.resolve(".cache").resolve(Constants.MOD_ID)); + } + + @Override + public Path getConfigDir() { + return FMLPaths.CONFIGDIR.get(); + } + + @Override + public boolean isDevelopmentEnvironment() { + return !FMLLoader.isProduction(); + } + + @Override + public void registerStartTickEvent(StartTickEvent event) { + NeoForge.EVENT_BUS.addListener(TickEvent.ClientTickEvent.class, (unused) -> event.onStartTick()); + } + + private Path ensureDir(Path path) { + try { + Files.createDirectories(path); + } catch (IOException e) { + throw new RuntimeException("Failed to create Dynamic FPS directory.", e); + } + + return path; + } +} diff --git a/platforms/neoforge/src/main/resources/META-INF/mods.toml b/platforms/neoforge/src/main/resources/META-INF/mods.toml new file mode 100644 index 00000000..cf0eb494 --- /dev/null +++ b/platforms/neoforge/src/main/resources/META-INF/mods.toml @@ -0,0 +1,38 @@ +modLoader = "javafml" +loaderVersion = "[1,)" +license = "MIT" +issueTrackerURL = "https://github.com/juliand665/Dynamic-FPS/issues" + +[[mods]] +modId = "dynamic_fps" +namespace = "net.lostluma" +version = "${version}" +displayName = "Dynamic FPS" +authors = "juliand665 & LostLuma" +description = "Dynamically adjusts FPS so Minecraft doesn't hog resources in the background." +logoFile = "dynamic_fps.png" +displayTest = "IGNORE_ALL_VERSION" +updateJSONURL = "https://api.lostluma.net/updates/dynamic-fps?platform=neoforge" + +[[mixins]] +config = "dynamic_fps.mixins.json" + +[[mixins]] +config = "dynamic_fps-common.mixins.json" + +[[accessTransformers]] +file="META-INF/accesstransformer.cfg" + +[[dependencies.dynamic_fps]] +modId = "minecraft" +mandatory = true +versionRange = "[1.20.0,)" +ordering = "NONE" +side = "CLIENT" + +[[dependencies.dynamic_fps]] +modId = "cloth_config" +mandatory = true +versionRange = "[1,)" +ordering = "NONE" +side = "CLIENT" diff --git a/platforms/neoforge/src/main/resources/META-INF/services/dynamic_fps.impl.service.ModCompat b/platforms/neoforge/src/main/resources/META-INF/services/dynamic_fps.impl.service.ModCompat new file mode 100644 index 00000000..a13d7f15 --- /dev/null +++ b/platforms/neoforge/src/main/resources/META-INF/services/dynamic_fps.impl.service.ModCompat @@ -0,0 +1 @@ +net.lostluma.dynamic_fps.impl.neoforge.service.NeoForgeModCompat diff --git a/platforms/neoforge/src/main/resources/META-INF/services/dynamic_fps.impl.service.Platform b/platforms/neoforge/src/main/resources/META-INF/services/dynamic_fps.impl.service.Platform new file mode 100644 index 00000000..75f1b45b --- /dev/null +++ b/platforms/neoforge/src/main/resources/META-INF/services/dynamic_fps.impl.service.Platform @@ -0,0 +1 @@ +net.lostluma.dynamic_fps.impl.neoforge.service.NeoForgePlatform diff --git a/platforms/neoforge/src/main/resources/dynamic_fps.mixins.json b/platforms/neoforge/src/main/resources/dynamic_fps.mixins.json new file mode 100644 index 00000000..a1e30c92 --- /dev/null +++ b/platforms/neoforge/src/main/resources/dynamic_fps.mixins.json @@ -0,0 +1,12 @@ +{ + "required": true, + "package": "net.lostluma.dynamic_fps.impl.neoforge.mixin", + "compatibilityLevel": "JAVA_17", + "minVersion": "0.8", + "client": [], + "mixins": [], + "server": [], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/platforms/neoforge/src/main/resources/dynamic_fps.png b/platforms/neoforge/src/main/resources/dynamic_fps.png new file mode 100644 index 00000000..f2820519 Binary files /dev/null and b/platforms/neoforge/src/main/resources/dynamic_fps.png differ diff --git a/platforms/neoforge/src/main/resources/pack.mcmeta b/platforms/neoforge/src/main/resources/pack.mcmeta new file mode 100644 index 00000000..73c6bc07 --- /dev/null +++ b/platforms/neoforge/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "Dynamic FPS", + "pack_format": 15 + } +} diff --git a/platforms/quilt/build.gradle b/platforms/quilt/build.gradle new file mode 100644 index 00000000..398d59de --- /dev/null +++ b/platforms/quilt/build.gradle @@ -0,0 +1,81 @@ +plugins { + alias libs.plugins.shadow +} + +repositories { + maven { url = "https://maven.terraformersmc.com/releases" } // modmenu + maven { url "https://maven.quiltmc.org/repository/release" } +} + +architectury { + platformSetupLoomIde() + loader("quilt") +} + +loom { + accessWidenerPath = project(":platforms:common").loom.accessWidenerPath +} + +configurations { + common + shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files. + compileClasspath.extendsFrom common + runtimeClasspath.extendsFrom common + developmentQuilt.extendsFrom common +} + +dependencies { + modImplementation(libs.quilt.loader) + modImplementation(libs.qsl.lifecycle.events) + + modApi(libs.modmenu) + + common(project(path: ":platforms:common", configuration: "namedElements")) { transitive false } + shadowCommon(project(path: ":platforms:common", configuration: "transformProductionQuilt")) { transitive false } +} + +processResources { + inputs.property "version", rootProject.mod_version + + filesMatching("quilt.mod.json") { + expand "version": rootProject.mod_version + } +} + +shadowJar { + exclude "architectury.common.json" + + configurations = [project.configurations.shadowCommon] +} + +remapJar { + injectAccessWidener = true + input.set shadowJar.archiveFile + dependsOn shadowJar +} + +sourcesJar { + def commonSources = project(":platforms:common").sourcesJar + dependsOn commonSources + from commonSources.archiveFile.map { zipTree(it) } +} + +components.java { + withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { + skip() + } +} + +publishing { + publications { + mavenQuilt(MavenPublication) { + artifactId = rootProject.archives_base_name + "-" + project.name + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + } +} diff --git a/platforms/quilt/gradle.properties b/platforms/quilt/gradle.properties new file mode 100644 index 00000000..4fb20b83 --- /dev/null +++ b/platforms/quilt/gradle.properties @@ -0,0 +1 @@ +loom.platform=quilt diff --git a/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/DynamicFPSQuiltMod.java b/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/DynamicFPSQuiltMod.java new file mode 100644 index 00000000..84b3cb44 --- /dev/null +++ b/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/DynamicFPSQuiltMod.java @@ -0,0 +1,12 @@ +package net.lostluma.dynamic_fps.impl.quilt; + +import dynamic_fps.impl.DynamicFPSMod; +import org.quiltmc.loader.api.ModContainer; +import org.quiltmc.qsl.base.api.entrypoint.client.ClientModInitializer; + +public class DynamicFPSQuiltMod implements ClientModInitializer { + @Override + public void onInitializeClient(ModContainer mod) { + DynamicFPSMod.init(); + } +} diff --git a/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/compat/FREX.java b/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/compat/FREX.java new file mode 100644 index 00000000..f20ac9f4 --- /dev/null +++ b/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/compat/FREX.java @@ -0,0 +1,51 @@ +package net.lostluma.dynamic_fps.impl.quilt.compat; + +import dynamic_fps.impl.DynamicFPSMod; +import org.quiltmc.loader.api.ModContainer; +import org.quiltmc.loader.api.QuiltLoader; +import org.quiltmc.qsl.base.api.entrypoint.client.ClientModInitializer; + +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; +import java.util.function.Function; + +/** + *

+ * Implements the FREX Flawless Frames API to allow other mods to request all + * frames to be processed until requested to + * go back to normal operation, such as ReplayMod rendering a video. + *

+ * See https://github.com/grondag/frex/pull/9 + */ +public final class FREX implements ClientModInitializer { + private static final Set ACTIVE = ConcurrentHashMap.newKeySet(); + + /** + * Returns whether one or more mods have requested Flawless Frames to be active, + * and therefore frames should not be skipped. + */ + public static boolean isFlawlessFramesActive() { + return !ACTIVE.isEmpty(); + } + + @Override + @SuppressWarnings("unchecked") + public void onInitializeClient(ModContainer mod) { + Function> provider = name -> { + Object token = new Object(); + + return active -> { + if (active) { + ACTIVE.add(token); + } else { + ACTIVE.remove(token); + } + + DynamicFPSMod.onStatusChanged(false); + }; + }; + + QuiltLoader.getEntrypoints("frex_flawless_frames", Consumer.class).forEach(api -> api.accept(provider)); + } +} diff --git a/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/compat/ModMenu.java b/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/compat/ModMenu.java new file mode 100644 index 00000000..e0ceca9a --- /dev/null +++ b/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/compat/ModMenu.java @@ -0,0 +1,19 @@ +package net.lostluma.dynamic_fps.impl.quilt.compat; + +import com.terraformersmc.modmenu.api.ConfigScreenFactory; +import com.terraformersmc.modmenu.api.ModMenuApi; +import dynamic_fps.impl.compat.ClothConfig; +import org.quiltmc.loader.api.QuiltLoader; + +public class ModMenu implements ModMenuApi { + private static final boolean CLOTH_CONFIG = QuiltLoader.isModLoaded("cloth-config2"); + + @Override + public ConfigScreenFactory getModConfigScreenFactory() { + if (!CLOTH_CONFIG) { + return parent -> null; + } else { + return ClothConfig::genConfigScreen; + } + } +} diff --git a/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/mixin/GuiMixin.java b/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/mixin/GuiMixin.java new file mode 100644 index 00000000..0da96cee --- /dev/null +++ b/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/mixin/GuiMixin.java @@ -0,0 +1,27 @@ +package net.lostluma.dynamic_fps.impl.quilt.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 = "render", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/gui/Gui;renderSavingIndicator(Lnet/minecraft/client/gui/GuiGraphics;)V" + ) + ) + private void render(CallbackInfo callbackInfo, @Local GuiGraphics guiGraphics) { + HudInfoRenderer.renderInfo(guiGraphics); + } +} diff --git a/src/main/java/dynamic_fps/impl/mixin/OptionsMixin.java b/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/mixin/OptionsMixin.java similarity index 69% rename from src/main/java/dynamic_fps/impl/mixin/OptionsMixin.java rename to platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/mixin/OptionsMixin.java index d73af116..73ca4b10 100644 --- a/src/main/java/dynamic_fps/impl/mixin/OptionsMixin.java +++ b/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/mixin/OptionsMixin.java @@ -1,5 +1,6 @@ -package dynamic_fps.impl.mixin; +package net.lostluma.dynamic_fps.impl.quilt.mixin; +import com.google.common.collect.Lists; import dynamic_fps.impl.util.KeyMappingHandler; import net.minecraft.client.KeyMapping; import net.minecraft.client.Options; @@ -12,6 +13,8 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.List; + @Mixin(Options.class) @Pseudo public class OptionsMixin { @@ -25,6 +28,12 @@ public class OptionsMixin { */ @Inject(method = "load", at = @At("HEAD")) private void load(CallbackInfo callbackInfo) { - this.keyMappings = KeyMappingHandler.register(this.keyMappings); + List mappings = Lists.newArrayList(this.keyMappings); + + for (KeyMappingHandler handler : KeyMappingHandler.getHandlers()) { + mappings.add(handler.keyMapping()); + } + + this.keyMappings = mappings.toArray(new KeyMapping[0]); } } diff --git a/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/service/QuiltModCompat.java b/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/service/QuiltModCompat.java new file mode 100644 index 00000000..621dcdaa --- /dev/null +++ b/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/service/QuiltModCompat.java @@ -0,0 +1,84 @@ +package net.lostluma.dynamic_fps.impl.quilt.service; + +import dynamic_fps.impl.service.ModCompat; +import net.lostluma.dynamic_fps.impl.quilt.compat.FREX; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.loader.api.LoaderValue; +import org.quiltmc.loader.api.MappingResolver; +import org.quiltmc.loader.api.ModContainer; +import org.quiltmc.loader.api.ModMetadata; +import org.quiltmc.loader.api.QuiltLoader; + +import java.util.HashSet; +import java.util.Set; + +public class QuiltModCompat implements ModCompat { + private static boolean disableOverlayOptimization = false; + + private static final Set optedInScreens = new HashSet<>(); + private static final Set optedOutScreens = new HashSet<>(); + + static { + QuiltLoader.getAllMods().forEach(QuiltModCompat::parseModMetadata); + } + + @Override + public boolean isDisabled() { + return FREX.isFlawlessFramesActive(); + } + + @Override + public boolean disableOverlayOptimization() { + return disableOverlayOptimization; + } + + @Override + public boolean isScreenOptedIn(String className) { + return optedInScreens.contains(className); + } + + @Override + public boolean isScreenOptedOut(String className) { + return optedOutScreens.contains(className); + } + + private static void parseModMetadata(ModContainer mod) { + LoaderValue.LObject root; + ModMetadata data = mod.metadata(); + + try { + root = data.value("dynamic_fps").asObject(); + } catch (ClassCastException | NullPointerException e) { + return; // Object is either missing or is of an invalid type + } + + parseOverlayOverride(root.get("optimized_overlay")); + } + + private static void parseOverlayOverride(@Nullable LoaderValue value) { + if (value != null && value.type() == LoaderValue.LType.BOOLEAN && !value.asBoolean()) { + disableOverlayOptimization = true; + } + } + + private static void parseScreenOverrides(@Nullable LoaderValue parent, String type, Set set) { + if (parent == null || parent.type() != LoaderValue.LType.OBJECT) { + return; + } + + LoaderValue values = parent.asObject().get(type); + + if (values == null || values.type() != LoaderValue.LType.ARRAY) { + return; + } + + MappingResolver resolver = QuiltLoader.getMappingResolver(); + + values.asArray().forEach(value -> { + if (value.type() == LoaderValue.LType.STRING) { + // Translate from intermediary to runtime names for vanilla screens + set.add(resolver.mapClassName("intermediary", value.asString())); + } + }); + } +} diff --git a/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/service/QuiltPlatform.java b/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/service/QuiltPlatform.java new file mode 100644 index 00000000..71cb5a1a --- /dev/null +++ b/platforms/quilt/src/main/java/net/lostluma/dynamic_fps/impl/quilt/service/QuiltPlatform.java @@ -0,0 +1,60 @@ +package net.lostluma.dynamic_fps.impl.quilt.service; + +import dynamic_fps.impl.Constants; +import dynamic_fps.impl.service.Platform; +import org.quiltmc.loader.api.ModContainer; +import org.quiltmc.loader.api.QuiltLoader; +import org.quiltmc.qsl.lifecycle.api.client.event.ClientTickEvents; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Optional; + +public class QuiltPlatform implements Platform { + @Override + public String getName() { + return "Quilt"; + } + + @Override + public String modVersion() { + Optional optional = QuiltLoader.getModContainer(Constants.MOD_ID); + + if (optional.isPresent()) { + return optional.get().metadata().version().toString(); + } else { + throw new RuntimeException("Own mod container is somehow not available!"); + } + } + + @Override + public Path getCacheDir() { + return this.ensureDir(QuiltLoader.getCacheDir().resolve(Constants.MOD_ID)); + } + + @Override + public Path getConfigDir() { + return QuiltLoader.getConfigDir(); + } + + @Override + public boolean isDevelopmentEnvironment() { + return QuiltLoader.isDevelopmentEnvironment(); + } + + @Override + public void registerStartTickEvent(StartTickEvent event) { + ClientTickEvents.START.register((minecraft) -> event.onStartTick()); + } + + private Path ensureDir(Path path) { + try { + Files.createDirectories(path); + } catch (IOException e) { + throw new RuntimeException("Failed to create Dynamic FPS directory.", e); + } + + return path; + } +} diff --git a/platforms/quilt/src/main/resources/META-INF/services/dynamic_fps.impl.service.ModCompat b/platforms/quilt/src/main/resources/META-INF/services/dynamic_fps.impl.service.ModCompat new file mode 100644 index 00000000..2e1b08d8 --- /dev/null +++ b/platforms/quilt/src/main/resources/META-INF/services/dynamic_fps.impl.service.ModCompat @@ -0,0 +1 @@ +net.lostluma.dynamic_fps.impl.quilt.service.QuiltModCompat diff --git a/platforms/quilt/src/main/resources/META-INF/services/dynamic_fps.impl.service.Platform b/platforms/quilt/src/main/resources/META-INF/services/dynamic_fps.impl.service.Platform new file mode 100644 index 00000000..481cc5a3 --- /dev/null +++ b/platforms/quilt/src/main/resources/META-INF/services/dynamic_fps.impl.service.Platform @@ -0,0 +1 @@ +net.lostluma.dynamic_fps.impl.quilt.service.QuiltPlatform diff --git a/platforms/quilt/src/main/resources/dynamic_fps.mixins.json b/platforms/quilt/src/main/resources/dynamic_fps.mixins.json new file mode 100644 index 00000000..603b6b5c --- /dev/null +++ b/platforms/quilt/src/main/resources/dynamic_fps.mixins.json @@ -0,0 +1,15 @@ +{ + "required": true, + "package": "net.lostluma.dynamic_fps.impl.quilt.mixin", + "compatibilityLevel": "JAVA_17", + "minVersion": "0.8", + "client": [ + "GuiMixin", + "OptionsMixin" + ], + "mixins": [], + "server": [], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/platforms/quilt/src/main/resources/quilt.mod.json b/platforms/quilt/src/main/resources/quilt.mod.json new file mode 100644 index 00000000..e9f6eb80 --- /dev/null +++ b/platforms/quilt/src/main/resources/quilt.mod.json @@ -0,0 +1,120 @@ +{ + "schema_version": 1, + "quilt_loader": { + "group": "net.lostluma", + "id": "dynamic_fps", + "version": "${version}", + "metadata": { + "name": "Dynamic FPS", + "description": "Dynamically adjusts FPS so Minecraft doesn't hog resources in the background.", + "contributors": { + "juliand665": "Owner", + "LostLuma": "Owner" + }, + "contact": { + "homepage": "https://dapprgames.com/mods", + "issues": "https://github.com/juliand665/Dynamic-FPS/issues", + "sources": "https://github.com/juliand665/Dynamic-FPS" + }, + "icon": "assets/dynamic_fps/icon.png", + "license": { + "id": "MIT", + "name": "MIT License", + "url": "https://github.com/juliand665/Dynamic-FPS/blob/main/LICENSE" + } + }, + "intermediate_mappings": "net.fabricmc:intermediary", + "entrypoints": { + "client_init": [ + "net.lostluma.dynamic_fps.impl.quilt.compat.FREX", + "net.lostluma.dynamic_fps.impl.quilt.DynamicFPSQuiltMod" + ], + "modmenu": [ + "net.lostluma.dynamic_fps.impl.quilt.compat.ModMenu" + ] + }, + "depends": [ + { + "id": "quilt_loader", + "versions": ">=0.23.1" + }, + { + "id": "minecraft", + "versions": ">=1.20.0" + }, + { + "id": "mixinextras", + "versions": ">=0.3.2" + }, + { + "id": "quilt_resource_loader", + "versions": "*" + }, + { + "id": "quilt_lifecycle_events", + "versions": "*" + }, + { + "id": "modmenu", + "versions": "*", + "optional": true + }, + { + "id": "cloth-config", + "versions": "*", + "optional": true + } + ], + "breaks": [ + { + "id": "fastload", + "versions": "<=3.4.0", + "reason": "Softlock in world loading screen, see https://github.com/BumbleSoftware/Fastload/issues/108" + } + ] + }, + "minecraft": { + "environment": "client" + }, + "mixin": [ + "dynamic_fps.mixins.json", + "dynamic_fps-common.mixins.json" + ], + "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/settings.gradle b/settings.gradle index a7add4a7..46efda2c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,11 +1,16 @@ pluginManagement { repositories { - maven { - name = 'Fabric' - url = 'https://maven.fabricmc.net/' - } - gradlePluginPortal() + maven { url "https://maven.fabricmc.net/" } + maven { url "https://maven.architectury.dev/" } + maven { url "https://maven.minecraftforge.net/" } + gradlePluginPortal() } } rootProject.name = "dynamic-fps" + +include(":platforms:common") +include(":platforms:fabric") +include(":platforms:forge") +include(":platforms:neoforge") +include(":platforms:quilt") diff --git a/src/main/java/dynamic_fps/impl/mixin/bugfix/BlockableEventLoopMixin.java b/src/main/java/dynamic_fps/impl/mixin/bugfix/BlockableEventLoopMixin.java deleted file mode 100644 index ee2fffcc..00000000 --- a/src/main/java/dynamic_fps/impl/mixin/bugfix/BlockableEventLoopMixin.java +++ /dev/null @@ -1,21 +0,0 @@ -package dynamic_fps.impl.mixin.bugfix; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -import net.minecraft.util.thread.BlockableEventLoop; - -import java.util.concurrent.locks.LockSupport; - -@Mixin(BlockableEventLoop.class) -public final class BlockableEventLoopMixin { - /** - * @author Julian Dunskus - * @reason The vanilla version is simply broken, taking up way too many resources in the background. - */ - @Overwrite - public void waitForTasks() { - // yield() here is a terrible idea - LockSupport.parkNanos("waiting for tasks", 500_000); // increased wait to 0.5 ms - } -} diff --git a/src/main/resources/META-INF/services/dynamic_fps.impl.service.Platform b/src/main/resources/META-INF/services/dynamic_fps.impl.service.Platform deleted file mode 100644 index 5e3d3510..00000000 --- a/src/main/resources/META-INF/services/dynamic_fps.impl.service.Platform +++ /dev/null @@ -1 +0,0 @@ -dynamic_fps.impl.service.FabricPlatform diff --git a/src/main/resources/dynamic_fps.accesswidener b/src/main/resources/dynamic_fps.accesswidener deleted file mode 100644 index 0298cddf..00000000 --- a/src/main/resources/dynamic_fps.accesswidener +++ /dev/null @@ -1,4 +0,0 @@ -accessWidener v2 named - -accessible field com/mojang/blaze3d/platform/Window window J -accessible field net/minecraft/client/sounds/SoundManager soundEngine Lnet/minecraft/client/sounds/SoundEngine; diff --git a/src/main/resources/dynamic_fps.mixins.json b/src/main/resources/dynamic_fps.mixins.json deleted file mode 100644 index 45c61bfb..00000000 --- a/src/main/resources/dynamic_fps.mixins.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "required": true, - "package": "dynamic_fps.impl.mixin", - "compatibilityLevel": "JAVA_17", - "mixins": [], - "client": [ - "DebugScreenOverlayMixin", - "GameRendererMixin", - "GuiMixin", - "LoadingOverlayMixin", - "MinecraftMixin", - "OptionsMixin", - "ScreenMixin", - "SoundEngineMixin", - "StatsScreenMixin", - "ToastComponentMixin", - "WindowMixin", - "bugfix.BlockableEventLoopMixin" - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json deleted file mode 100644 index 1b86de3c..00000000 --- a/src/main/resources/fabric.mod.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "schemaVersion": 1, - "id": "dynamic_fps", - "version": "${version}", - - "name": "Dynamic FPS", - "description": "Dynamically adjusts FPS so Minecraft doesn't hog resources in background.", - "authors": [ - "juliand665", - "LostLuma" - ], - "contact": { - "homepage": "https://dapprgames.com/mods/", - "sources": "https://github.com/juliand665/Dynamic-FPS", - "issues": "https://github.com/juliand665/Dynamic-FPS/issues" - }, - - "license": "MIT", - "icon": "assets/dynamic_fps/icon.png", - - "environment": "client", - "entrypoints": { - "client": [ - "dynamic_fps.impl.compat.FREX" - ], - "modmenu": [ - "dynamic_fps.impl.compat.ModMenu" - ] - }, - "mixins": [ - "dynamic_fps.mixins.json" - ], - "accessWidener": "dynamic_fps.accesswidener", - - "depends": { - "minecraft": ">=1.20.0", - "mixinextras": ">=0.3.2", - "fabricloader": ">=0.15.0", - "fabric-resource-loader-v0": "*", - "fabric-lifecycle-events-v1": "*" - }, - - "custom": { - "loom:injected_interfaces": { - "net/minecraft/class_437": ["dynamic_fps/impl/util/duck/DuckScreen"], - "net/minecraft/class_425": ["dynamic_fps/impl/util/duck/DuckSplashOverlay"], - "net/minecraft/class_1140": ["dynamic_fps/impl/util/duck/DuckSoundEngine"] - }, - "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" - } - } - } - } - } -}