Skip to content

Commit

Permalink
add way to reduce volume when unfocused!
Browse files Browse the repository at this point in the history
  • Loading branch information
juliand665 committed Jan 15, 2022
1 parent 6ef00c1 commit 5c8b1b6
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 47 deletions.
18 changes: 18 additions & 0 deletions src/main/java/dynamicfps/ClothConfigScreenFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@ static Screen genConfig(Screen parent) {
.setSaveConsumer(value -> DynamicFPSMod.config.restoreFPSWhenHovered = value)
.build()
)
.addEntry(entryBuilder
.startIntSlider(
localized("config", "unfocused_volume"),
(int) (DynamicFPSMod.config.unfocusedVolumeMultiplier * 100),
0, 100
)
.setSaveConsumer(value -> DynamicFPSMod.config.unfocusedVolumeMultiplier = value / 100f)
.build()
)
.addEntry(entryBuilder
.startIntSlider(
localized("config", "hidden_volume"),
(int) (DynamicFPSMod.config.hiddenVolumeMultiplier * 100),
0, 100
)
.setSaveConsumer(value -> DynamicFPSMod.config.hiddenVolumeMultiplier = value / 100f)
.build()
)
.addEntry(entryBuilder
.startBooleanToggle(
localized("config", "run_gc_on_unfocus"),
Expand Down
8 changes: 6 additions & 2 deletions src/main/java/dynamicfps/DynamicFPSConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@ public final class DynamicFPSConfig {
public boolean reduceFPSWhenUnfocused = true;
/// The frame rate to target when unfocused (only applies if `enableUnfocusedFPS` is true).
public int unfocusedFPS = 1;
/// Whether or not to uncap FPS when hovered, even if it would otherwise be reduced.
/// Whether to uncap FPS when hovered, even if it would otherwise be reduced.
public boolean restoreFPSWhenHovered = true;
/// Whether or not to trigger a garbage collector run whenever the game is unfocused.
/// Volume multiplier when not focused.
public float unfocusedVolumeMultiplier = 0.25f;
/// Volume multiplier when not visible.
public float hiddenVolumeMultiplier = 0f;
/// Whether to trigger a garbage collector run whenever the game is unfocused.
public boolean runGCOnUnfocus = false;

private DynamicFPSConfig() {}
Expand Down
94 changes: 69 additions & 25 deletions src/main/java/dynamicfps/DynamicFPSMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.util.Window;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.Util;
import org.lwjgl.glfw.GLFW;

Expand Down Expand Up @@ -47,16 +48,27 @@ public void onInitialize() {
FlawlessFrames.onClientInitialization();
}

private static MinecraftClient client;
private static Window window;
private static boolean isFocused, isVisible, isHovered;
private static long lastRender;
/**
Determines whether the game should render anything at this time. If not, blocks for a short time.
@return whether or not the game should be rendered after this.
@return whether the game should be rendered after this.
*/
public static boolean checkForRender() {
if (isDisabled || FlawlessFrames.isActive()) return true;

checkForGC();
if (client == null) {
client = MinecraftClient.getInstance();
window = client.getWindow();
}
isFocused = client.isWindowFocused();
isVisible = GLFW.glfwGetWindowAttrib(window.getHandle(), GLFW.GLFW_VISIBLE) != 0;
isHovered = GLFW.glfwGetWindowAttrib(window.getHandle(), GLFW.GLFW_HOVERED) != 0;

checkForStateChanges();

long currentTime = Util.getMeasuringTimeMs();
long timeSinceLastRender = currentTime - lastRender;
Expand All @@ -67,18 +79,65 @@ public static boolean checkForRender() {
return true;
}

private static boolean hasTriggeredGC = false;
private static void checkForGC() {
if (!config.runGCOnUnfocus) return;
private static boolean wasFocused = true;
private static boolean wasVisible = true;
private static void checkForStateChanges() {
if (isFocused != wasFocused) {
wasFocused = isFocused;
if (isFocused) {
onFocus();
} else {
onUnfocus();
}
}

if (MinecraftClient.getInstance().isWindowFocused()) {
hasTriggeredGC = false;
} else if (!hasTriggeredGC && hasRenderedLastFrame) {
hasTriggeredGC = true;
if (isVisible != wasVisible) {
wasVisible = isVisible;
if (isVisible) {
onAppear();
} else {
onDisappear();
}
}
}

private static void onFocus() {
setVolumeMultiplier(1);
}

private static void onUnfocus() {
if (isVisible) {
setVolumeMultiplier(config.unfocusedVolumeMultiplier);
}

if (config.runGCOnUnfocus) {
System.gc();
}
}

private static void onAppear() {
if (!isFocused) {
setVolumeMultiplier(config.unfocusedVolumeMultiplier);
}
}

private static void onDisappear() {
setVolumeMultiplier(config.hiddenVolumeMultiplier);
}

private static void setVolumeMultiplier(float multiplier) {
// setting the volume to 0 stops all sounds (including music), which we want to avoid if possible.
var clientWillPause = !isFocused && client.options.pauseOnLostFocus && client.currentScreen == null;
// if the client would pause anyway, we don't need to do anything because that will already pause all sounds.
if (multiplier == 0 && clientWillPause) return;

var baseVolume = client.options.getSoundVolume(SoundCategory.MASTER);
client.getSoundManager().updateSoundVolume(
SoundCategory.MASTER,
baseVolume * multiplier
);
}

// we always render one last frame before actually reducing FPS, so the hud text shows up instantly when forcing low fps.
// additionally, this would enable mods which render differently while mc is inactive.
private static boolean hasRenderedLastFrame = false;
Expand Down Expand Up @@ -119,28 +178,13 @@ private static void idle(long waitMillis) {

@Nullable
private static Integer fpsOverride() {
MinecraftClient client = MinecraftClient.getInstance();
Window window = ((WindowHolder) client).getWindow();

boolean isVisible = GLFW.glfwGetWindowAttrib(window.getHandle(), GLFW.GLFW_VISIBLE) != 0;
if (!isVisible) return 0;

if (isForcingLowFPS) return config.unfocusedFPS;

if (config.restoreFPSWhenHovered) {
boolean isHovered = GLFW.glfwGetWindowAttrib(window.getHandle(), GLFW.GLFW_HOVERED) != 0;
if (isHovered) return null;
}

if (config.restoreFPSWhenHovered && isHovered) return null;
if (config.reduceFPSWhenUnfocused && !client.isWindowFocused()) return config.unfocusedFPS;

return null;
}

public interface WindowHolder {
Window getWindow();
}

public interface SplashOverlayAccessor {
boolean isReloadComplete();
}
Expand Down
18 changes: 0 additions & 18 deletions src/main/java/dynamicfps/mixin/MinecraftClientMixin.java

This file was deleted.

2 changes: 2 additions & 0 deletions src/main/resources/assets/dynamicfps/lang/de_de.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"config.dynamicfps.unfocused_fps": "Reduzierte FPS",
"config.dynamicfps.restore_when_hovered": "FPS bei Hover maximieren",
"config.dynamicfps.run_gc_on_unfocus": "GC beim inaktiv Werden auslösen",
"config.dynamicfps.unfocused_volume": "Lautstärke wenn inaktiv (%)",
"config.dynamicfps.hidden_volume": "Lautstärke wenn nicht sichtbar (%)",
"key.dynamicfps.toggle_forced": "Reduzierte FPS forcieren (Toggle)",
"key.dynamicfps.toggle_disabled": "Dynamic FPS deaktivieren (Toggle)",
"gui.dynamicfps.hud.reducing": "Dynamic FPS: tiefe FPS forciert",
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/assets/dynamicfps/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"config.dynamicfps.unfocused_fps": "Unfocused FPS target",
"config.dynamicfps.restore_when_hovered": "Restore FPS when hovered",
"config.dynamicfps.run_gc_on_unfocus": "Run GC on unfocus",
"config.dynamicfps.unfocused_volume": "Volume when unfocused (%)",
"config.dynamicfps.hidden_volume": "Volume when not visible (%)",
"key.dynamicfps.toggle_forced": "Force Reduced FPS (Toggle)",
"key.dynamicfps.toggle_disabled": "Disable Dynamic FPS (Toggle)",
"gui.dynamicfps.hud.reducing": "Dynamic FPS: Forcing Reduced FPS",
Expand Down
3 changes: 1 addition & 2 deletions src/main/resources/dynamicfps.mixins.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
{
"required": true,
"package": "dynamicfps.mixin",
"compatibilityLevel": "JAVA_8",
"compatibilityLevel": "JAVA_17",
"mixins": [
],
"client": [
"GameRendererMixin",
"MinecraftClientMixin",
"SplashOverlayMixin",
"ThreadExecutorMixin"
],
Expand Down

0 comments on commit 5c8b1b6

Please sign in to comment.