diff --git a/src/main/java/dynamic_fps/impl/GraphicsState.java b/src/main/java/dynamic_fps/impl/GraphicsState.java index 3f749711..2b1e748e 100644 --- a/src/main/java/dynamic_fps/impl/GraphicsState.java +++ b/src/main/java/dynamic_fps/impl/GraphicsState.java @@ -29,7 +29,7 @@ public enum GraphicsState { public static final Codec CODEC = new PrimitiveCodec() { @Override public T write(DynamicOps ops, GraphicsState value) { - return ops.createString(value.toString().toLowerCase(Locale.ROOT)); + return ops.createString(value.toString()); } @Override @@ -43,4 +43,9 @@ public DataResult read(DynamicOps ops, T input) { } } }; + + @Override + public String toString() { + return super.toString().toLowerCase(Locale.ROOT); + } } diff --git a/src/main/java/dynamic_fps/impl/compat/ClothConfig.java b/src/main/java/dynamic_fps/impl/compat/ClothConfig.java index c83a53fc..fc726278 100644 --- a/src/main/java/dynamic_fps/impl/compat/ClothConfig.java +++ b/src/main/java/dynamic_fps/impl/compat/ClothConfig.java @@ -2,10 +2,14 @@ import me.shedaniel.clothconfig2.api.ConfigBuilder; import me.shedaniel.clothconfig2.api.ConfigEntryBuilder; +import net.minecraft.ChatFormatting; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; import static dynamic_fps.impl.util.Localization.localized; +import java.util.Optional; + import dynamic_fps.impl.DynamicFPSMod; import dynamic_fps.impl.GraphicsState; import dynamic_fps.impl.PowerState; @@ -13,12 +17,12 @@ public final class ClothConfig { public static Screen genConfigScreen(Screen parent) { - ConfigBuilder builder = ConfigBuilder.create() + var builder = ConfigBuilder.create() .setParentScreen(parent) .setTitle(localized("config", "title")) .setSavingRunnable(DynamicFPSMod.modConfig::save); - ConfigEntryBuilder entryBuilder = builder.entryBuilder(); + var entryBuilder = builder.entryBuilder(); for (var state : PowerState.values()) { if (!state.configurable) { @@ -28,52 +32,115 @@ public static Screen genConfigScreen(Screen parent) { var config = DynamicFPSMod.modConfig.get(state); var standard = DynamicFPSConfig.getDefaultConfig(state); - builder.getOrCreateCategory( - localized("config", "category." + state.toString().toLowerCase())) - .addEntry( - entryBuilder - .startTextDescription( - localized("config", "frame_rate_target_description")).build()) - .addEntry(entryBuilder - .startIntSlider( - localized("config", "frame_rate_target"), - config.frameRateTarget(), - -1, 60) - .setDefaultValue(standard.frameRateTarget()) - .setSaveConsumer(config::setFrameRateTarget) - .build()) - .addEntry(entryBuilder - .startIntSlider( - localized("config", "volume_multiplier"), - (int) (config.volumeMultiplier() * 100), - 0, 100) - .setDefaultValue((int) (standard.volumeMultiplier() * 100)) - .setSaveConsumer(value -> config.setVolumeMultiplier(value / 100f)) - .build()) - .addEntry(entryBuilder - .startEnumSelector( - localized("config", "graphics_state"), - GraphicsState.class, - config.graphicsState()) - .setDefaultValue(standard.graphicsState()) - .setSaveConsumer(config::setGraphicsState) - .build()) - .addEntry(entryBuilder - .startBooleanToggle( - localized("config", "show_toasts"), - config.showToasts()) - .setDefaultValue(standard.showToasts()) - .setSaveConsumer(config::setShowToasts) - .build()) - .addEntry(entryBuilder - .startBooleanToggle( - localized("config", "run_garbage_collector"), - config.runGarbageCollector()) - .setDefaultValue(standard.runGarbageCollector()) - .setSaveConsumer(config::setRunGarbageCollector) - .build()); + var category = builder.getOrCreateCategory( + localized("config", "category." + state.toString().toLowerCase()) + ); + + category.addEntry( + entryBuilder.startIntSlider( + localized("config", "frame_rate_target"), + fromConfigFpsTarget(config.frameRateTarget()), + 0, 61 + ) + .setDefaultValue(fromConfigFpsTarget(standard.frameRateTarget())) + .setSaveConsumer(value -> config.setFrameRateTarget(toConfigFpsTarget(value))) + .setTextGetter(ClothConfig::fpsTargetMessage) + .build() + ); + + category.addEntry( + entryBuilder.startIntSlider( + localized("config", "volume_multiplier"), + (int) (config.volumeMultiplier() * 100), + 0, 100 + ) + .setDefaultValue((int) (standard.volumeMultiplier() * 100)) + .setSaveConsumer(value -> config.setVolumeMultiplier(value / 100f)) + .setTextGetter(ClothConfig::volumeMultiplierMessage) + .build() + ); + + category.addEntry( + entryBuilder.startEnumSelector( + localized("config", "graphics_state"), + GraphicsState.class, + config.graphicsState() + ) + .setDefaultValue(standard.graphicsState()) + .setSaveConsumer(config::setGraphicsState) + .setEnumNameProvider(ClothConfig::graphicsStateMessage) + .setTooltipSupplier(ClothConfig::graphicsStateTooltip) + .build() + ); + + category.addEntry( + entryBuilder.startBooleanToggle( + localized("config", "show_toasts"), + config.showToasts() + ) + .setDefaultValue(standard.showToasts()) + .setSaveConsumer(config::setShowToasts) + .setTooltip(localized("config", "show_toasts_tooltip")) + .build() + ); + + category.addEntry( + entryBuilder.startBooleanToggle( + localized("config", "run_garbage_collector"), + config.runGarbageCollector() + ) + .setDefaultValue(standard.runGarbageCollector()) + .setSaveConsumer(config::setRunGarbageCollector) + .setTooltip(localized("config", "run_garbage_collector_tooltip")) + .build() + ); } return builder.build(); } + + // Convert magic -1 number to 61 (and reverse) + // So the "unlocked" FPS value is on the right + private static int toConfigFpsTarget(int value) { + return value == 61 ? -1 : value; + } + + private static int fromConfigFpsTarget(int value) { + return value == -1 ? 61 : value; + } + + private static Component fpsTargetMessage(int value) { + if (toConfigFpsTarget(value) != -1) { + return Component.translatable("options.framerate", value); + } else { + return Component.translatable("options.framerateLimit.max"); + } + } + + private static Component volumeMultiplierMessage(int value) { + return Component.literal(Integer.toString(value) + "%"); + } + + private static Component graphicsStateMessage(Enum graphicsState) { + String key; + + if (graphicsState.equals(GraphicsState.DEFAULT)) { + key = "options.gamma.default"; + } else if (graphicsState.equals(GraphicsState.MINIMAL)) { + key = "options.particles.minimal"; + } else { + key = "options.particles.decreased"; + } + + return Component.translatable(key); + // return localized("config", "graphics_state_" + graphicsState.toString()); + } + + private static Optional graphicsStateTooltip(GraphicsState graphicsState) { + if (!graphicsState.equals(GraphicsState.MINIMAL)) { + return Optional.empty(); + } + + return Optional.of(new Component[]{ localized("config", "graphics_state_minimal_tooltip").withStyle(ChatFormatting.RED) }); + } } diff --git a/src/main/java/dynamic_fps/impl/util/Localization.java b/src/main/java/dynamic_fps/impl/util/Localization.java index 7d47bb1d..93fc0d1b 100644 --- a/src/main/java/dynamic_fps/impl/util/Localization.java +++ b/src/main/java/dynamic_fps/impl/util/Localization.java @@ -2,6 +2,7 @@ import dynamic_fps.impl.DynamicFPSMod; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; public final class Localization { /** e.g. keyString("title", "config") -> "title.dynamic_fps.config") */ @@ -9,7 +10,7 @@ public static String translationKey(String domain, String path) { return domain + "." + DynamicFPSMod.MOD_ID + "." + path; } - public static Component localized(String domain, String path, Object... args) { + public static MutableComponent localized(String domain, String path, Object... args) { return Component.translatable(translationKey(domain, path), args); } diff --git a/src/main/resources/assets/dynamic_fps/lang/de_at.json b/src/main/resources/assets/dynamic_fps/lang/de_at.json index 669392ba..27f1c84e 100644 --- a/src/main/resources/assets/dynamic_fps/lang/de_at.json +++ b/src/main/resources/assets/dynamic_fps/lang/de_at.json @@ -6,11 +6,19 @@ "config.dynamic_fps.category.invisible": "Unsichtbar", "config.dynamic_fps.frame_rate_target": "Zielbildrate", - "config.dynamic_fps.frame_rate_target_description": "Setze die Zielbildrate auf -1, um die Bildrate nicht zu reduzieren.", "config.dynamic_fps.volume_multiplier": "Lautstärke", + "config.dynamic_fps.graphics_state": "Grafikoptionen", + "config.dynamic_fps.graphics_state_default": "Standard", + "config.dynamic_fps.graphics_state_reduced": "Reduziert", + "config.dynamic_fps.graphics_state_minimal": "Minimal", + "config.dynamic_fps.graphics_state_minimal_tooltip": "Minimale Grafik bewirkt, dass die Welt neu lädt!", + "config.dynamic_fps.show_toasts": "Toasts Anzeigen", + "config.dynamic_fps.show_toasts_tooltip": "Toast Benachrichtigungen weiterhin anzeigen oder verzögern", + "config.dynamic_fps.run_garbage_collector": "GC auslösen", + "config.dynamic_fps.run_garbage_collector_tooltip": "Ungenutzen Arbeitsspeicher frei machen, wenn dieser Status aktiviert wird", "key.dynamic_fps.toggle_forced": "Unfokussierten Modus forcieren (Toggle)", "key.dynamic_fps.toggle_disabled": "Dynamic FPS deaktivieren (Toggle)", diff --git a/src/main/resources/assets/dynamic_fps/lang/de_ch.json b/src/main/resources/assets/dynamic_fps/lang/de_ch.json index 669392ba..27f1c84e 100644 --- a/src/main/resources/assets/dynamic_fps/lang/de_ch.json +++ b/src/main/resources/assets/dynamic_fps/lang/de_ch.json @@ -6,11 +6,19 @@ "config.dynamic_fps.category.invisible": "Unsichtbar", "config.dynamic_fps.frame_rate_target": "Zielbildrate", - "config.dynamic_fps.frame_rate_target_description": "Setze die Zielbildrate auf -1, um die Bildrate nicht zu reduzieren.", "config.dynamic_fps.volume_multiplier": "Lautstärke", + "config.dynamic_fps.graphics_state": "Grafikoptionen", + "config.dynamic_fps.graphics_state_default": "Standard", + "config.dynamic_fps.graphics_state_reduced": "Reduziert", + "config.dynamic_fps.graphics_state_minimal": "Minimal", + "config.dynamic_fps.graphics_state_minimal_tooltip": "Minimale Grafik bewirkt, dass die Welt neu lädt!", + "config.dynamic_fps.show_toasts": "Toasts Anzeigen", + "config.dynamic_fps.show_toasts_tooltip": "Toast Benachrichtigungen weiterhin anzeigen oder verzögern", + "config.dynamic_fps.run_garbage_collector": "GC auslösen", + "config.dynamic_fps.run_garbage_collector_tooltip": "Ungenutzen Arbeitsspeicher frei machen, wenn dieser Status aktiviert wird", "key.dynamic_fps.toggle_forced": "Unfokussierten Modus forcieren (Toggle)", "key.dynamic_fps.toggle_disabled": "Dynamic FPS deaktivieren (Toggle)", diff --git a/src/main/resources/assets/dynamic_fps/lang/de_de.json b/src/main/resources/assets/dynamic_fps/lang/de_de.json index 669392ba..27f1c84e 100644 --- a/src/main/resources/assets/dynamic_fps/lang/de_de.json +++ b/src/main/resources/assets/dynamic_fps/lang/de_de.json @@ -6,11 +6,19 @@ "config.dynamic_fps.category.invisible": "Unsichtbar", "config.dynamic_fps.frame_rate_target": "Zielbildrate", - "config.dynamic_fps.frame_rate_target_description": "Setze die Zielbildrate auf -1, um die Bildrate nicht zu reduzieren.", "config.dynamic_fps.volume_multiplier": "Lautstärke", + "config.dynamic_fps.graphics_state": "Grafikoptionen", + "config.dynamic_fps.graphics_state_default": "Standard", + "config.dynamic_fps.graphics_state_reduced": "Reduziert", + "config.dynamic_fps.graphics_state_minimal": "Minimal", + "config.dynamic_fps.graphics_state_minimal_tooltip": "Minimale Grafik bewirkt, dass die Welt neu lädt!", + "config.dynamic_fps.show_toasts": "Toasts Anzeigen", + "config.dynamic_fps.show_toasts_tooltip": "Toast Benachrichtigungen weiterhin anzeigen oder verzögern", + "config.dynamic_fps.run_garbage_collector": "GC auslösen", + "config.dynamic_fps.run_garbage_collector_tooltip": "Ungenutzen Arbeitsspeicher frei machen, wenn dieser Status aktiviert wird", "key.dynamic_fps.toggle_forced": "Unfokussierten Modus forcieren (Toggle)", "key.dynamic_fps.toggle_disabled": "Dynamic FPS deaktivieren (Toggle)", diff --git a/src/main/resources/assets/dynamic_fps/lang/en_us.json b/src/main/resources/assets/dynamic_fps/lang/en_us.json index 20a81af4..19694d7a 100644 --- a/src/main/resources/assets/dynamic_fps/lang/en_us.json +++ b/src/main/resources/assets/dynamic_fps/lang/en_us.json @@ -6,11 +6,19 @@ "config.dynamic_fps.category.invisible": "Invisible", "config.dynamic_fps.frame_rate_target": "Frame Rate Target", - "config.dynamic_fps.frame_rate_target_description": "Set Frame Rate Target to -1 to disable reducing FPS.", "config.dynamic_fps.volume_multiplier": "Volume Multiplier", + "config.dynamic_fps.graphics_state": "Graphics Options", + "config.dynamic_fps.graphics_state_default": "Default", + "config.dynamic_fps.graphics_state_reduced": "Reduced", + "config.dynamic_fps.graphics_state_minimal": "Minimal", + "config.dynamic_fps.graphics_state_minimal_tooltip": "Minimal graphics cause the world to reload!", + "config.dynamic_fps.show_toasts": "Show Toasts", + "config.dynamic_fps.show_toasts_tooltip": "Whether to keep displaying or delay toast notifications", + "config.dynamic_fps.run_garbage_collector": "Invoke Garbage Collector", + "config.dynamic_fps.run_garbage_collector_tooltip": "Free up unused memory when switching to this status", "key.dynamic_fps.toggle_forced": "Force Unfocused Mode (Toggle)", "key.dynamic_fps.toggle_disabled": "Disable Dynamic FPS (Toggle)",