Skip to content

Commit

Permalink
Add option to disable the menu FPS limit
Browse files Browse the repository at this point in the history
  • Loading branch information
LostLuma committed Feb 6, 2024
1 parent e31e648 commit 96fb7c9
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 12 deletions.
4 changes: 4 additions & 0 deletions src/main/java/dynamic_fps/impl/DynamicFPSMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ public static int targetFrameRate() {
return config.frameRateTarget();
}

public static boolean uncapMenuFrameRate() {
return modConfig.uncapMenuFrameRate();
}

public static float volumeMultiplier(SoundSource source) {
return config.volumeMultiplier(source);
}
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/dynamic_fps/impl/compat/ClothConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ public static Screen genConfigScreen(Screen parent) {
.build()
);

general.addEntry(
entryBuilder.startBooleanToggle(
localized("config", "uncap_menu_frame_rate"),
DynamicFPSMod.modConfig.uncapMenuFrameRate()
)
.setDefaultValue(false)
.setSaveConsumer(DynamicFPSMod.modConfig::setUncapMenuFrameRate)
.setTooltip(localized("config", "uncap_menu_frame_rate_tooltip"))
.build()
);

for (PowerState state : PowerState.values()) {
if (!state.configurable) {
continue;
Expand Down
14 changes: 13 additions & 1 deletion src/main/java/dynamic_fps/impl/config/DynamicFPSConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@

public final class DynamicFPSConfig {
private int idleTime; // Seconds
private boolean uncapMenuFrameRate;

@SerializedName("states")
private final Map<PowerState, Config> configs;

DynamicFPSConfig(int abandonTime, Map<PowerState, Config> configs) {
DynamicFPSConfig(int abandonTime, boolean uncapMenuFrameRate, Map<PowerState, Config> configs) {
this.idleTime = abandonTime;
this.uncapMenuFrameRate = uncapMenuFrameRate;

this.configs = new EnumMap<>(configs);

for (PowerState state : PowerState.values()) {
Expand All @@ -38,6 +42,14 @@ public void setIdleTime(int value) {
this.idleTime = value;
}

public boolean uncapMenuFrameRate() {
return this.uncapMenuFrameRate;
}

public void setUncapMenuFrameRate(boolean value) {
this.uncapMenuFrameRate = value;
}

private Map<PowerState, Config> configs() {
return this.configs;
}
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/dynamic_fps/impl/config/Serialization.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public static DynamicFPSConfig load() {
try {
data = Files.readAllBytes(CONFIG_FILE);
} catch (NoSuchFileException e) {
DynamicFPSConfig config = new DynamicFPSConfig(0, new EnumMap<>(PowerState.class));
DynamicFPSConfig config = new DynamicFPSConfig(0, false, new EnumMap<>(PowerState.class));
config.save();
return config;
} catch (IOException e) {
Expand All @@ -84,6 +84,7 @@ private static void upgradeConfig(JsonObject root) {
addIdleTime(root);
upgradeVolumeMultiplier(root);
addAbandonedConfig(root);
addUncapMenuFrameRate(root);
}

private static void addIdleTime(JsonObject root) {
Expand Down Expand Up @@ -144,6 +145,13 @@ private static void addAbandonedConfig(JsonObject root) {
states.add("abandoned", GSON.toJsonTree(Config.getDefault(PowerState.ABANDONED)));
}

private static void addUncapMenuFrameRate(JsonObject root) {
// Add uncap_menu_frame_rate field if it's missing
if (!root.has("uncap_menu_frame_rate")) {
root.addProperty("uncap_menu_frame_rate", false);
}
}

private static @Nullable JsonObject getStatesAsObject(JsonObject root) {
if (!root.has("states")) {
return null;
Expand Down
49 changes: 39 additions & 10 deletions src/main/java/dynamic_fps/impl/mixin/MinecraftMixin.java
Original file line number Diff line number Diff line change
@@ -1,32 +1,61 @@
package dynamic_fps.impl.mixin;

import com.mojang.blaze3d.platform.Window;
import dynamic_fps.impl.DynamicFPSMod;
import dynamic_fps.impl.PowerState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.Options;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import com.mojang.blaze3d.platform.Window;

import dynamic_fps.impl.DynamicFPSMod;
import net.minecraft.client.Minecraft;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(Minecraft.class)
public class MinecraftMixin {
@Shadow
@Final
private Window window;

@Shadow
@Final
public Options options;

// Minecraft considers limits >=260 as infinite
private static final int NO_FRAME_RATE_LIMIT = 260;

@Inject(method = "<init>", at = @At("TAIL"))
private void onInit(CallbackInfo callbackInfo) {
DynamicFPSMod.setWindow(this.window.window);
}

/*
@Inject(method = "setScreen", at = @At("TAIL"))
private void onSetScreen(CallbackInfo callbackInfo) {
DynamicFPSMod.onStatusChanged();
/**
* Conditionally bypasses the main menu frame rate limit.
*
* This is done in two cases:
* - The window is active, and the user wants to uncap the frame rate
* - The window is inactive, and the current FPS limit should be lower
*/
@Inject(method = "getFramerateLimit", at = @At(value = "CONSTANT", args = "intValue=60"), cancellable = true)
private void getFramerateLimit(CallbackInfoReturnable<Integer> callbackInfo) {
int limit = this.window.getFramerateLimit();

if (DynamicFPSMod.powerState() != PowerState.FOCUSED) {
// Limit may be 260 (uncapped)
if (limit < 60) {
callbackInfo.setReturnValue(limit);
}
} else if (DynamicFPSMod.uncapMenuFrameRate()) {
if (this.options.enableVsync().get()) {
// VSync will regulate to a non-infinite value
callbackInfo.setReturnValue(NO_FRAME_RATE_LIMIT);
} else {
// Even though the option "uncaps" the frame rate the max is 250 FPS
// Since otherwise this will just cause coil whine for no real benefit.
callbackInfo.setReturnValue(Math.min(limit, NO_FRAME_RATE_LIMIT - 10));
}
}
}
*/
}
3 changes: 3 additions & 0 deletions src/main/resources/assets/dynamic_fps/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
"config.dynamic_fps.idle_time": "Idle time",
"config.dynamic_fps.idle_time_tooltip": "Minutes without input until Dynamic FPS activates the Idle state while the game is focused.",

"config.dynamic_fps.uncap_menu_frame_rate": "Uncap Menu FPS",
"config.dynamic_fps.uncap_menu_frame_rate_tooltip": "Remove the 60 FPS limit in the main menu.",

"config.dynamic_fps.frame_rate_target": "Frame Rate Target",
"config.dynamic_fps.volume_multiplier": "Volume Multiplier",

Expand Down

0 comments on commit 96fb7c9

Please sign in to comment.