From 96dfe823ce21c2ddbf02fbb4b3c181bbc2072010 Mon Sep 17 00:00:00 2001 From: FrCynda Date: Sat, 22 Aug 2026 20:26:58 +0200 Subject: [PATCH 1/4] Pull the TranslatableComponent boilerplate into a text() helper --- .../cat_vision/config/ConfigScreen.java | 126 ++++++------------ 1 file changed, 44 insertions(+), 82 deletions(-) diff --git a/src/main/java/net/marios271/cat_vision/config/ConfigScreen.java b/src/main/java/net/marios271/cat_vision/config/ConfigScreen.java index b29d85d..e565ccc 100644 --- a/src/main/java/net/marios271/cat_vision/config/ConfigScreen.java +++ b/src/main/java/net/marios271/cat_vision/config/ConfigScreen.java @@ -4,103 +4,65 @@ import me.shedaniel.clothconfig2.api.ConfigCategory; import me.shedaniel.clothconfig2.api.ConfigEntryBuilder; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; //? < 1.19 { /*import net.minecraft.network.chat.TranslatableComponent; -*///?} >= 1.19 { -import net.minecraft.network.chat.Component; -//?} +*///?} public class ConfigScreen { - public static Screen create(Screen parent, ConfigData config) { - ConfigBuilder builder = ConfigBuilder.create() - .setParentScreen(parent) - .setTitle( - //? < 1.19 { - /*new TranslatableComponent("text.cat_vision.config.title") - *///?} >= 1.19 { - Component.translatable("text.cat_vision.config.title") - //?} - ); + private static final String PREFIX = "text.cat_vision.config."; - ConfigCategory category = builder.getOrCreateCategory( - //? < 1.19 { - /*new TranslatableComponent("text.cat_vision.config.category") - *///?} >= 1.19 { - Component.translatable("text.cat_vision.config.category") - //?} - ); - ConfigEntryBuilder entryBuilder = builder.entryBuilder(); + public static Screen create(Screen parent, ConfigData config) { + ConfigBuilder builder = ConfigBuilder.create() + .setParentScreen(parent) + .setTitle(text(PREFIX + "title")); - category.addEntry(entryBuilder.startBooleanToggle( - //? < 1.19 { - /*new TranslatableComponent("text.cat_vision.config.option.remember_nv"), - *///?} >= 1.19 { - Component.translatable("text.cat_vision.config.option.remember_nv"), - //?} - config.remember_nv - ) - .setDefaultValue(true) - .setSaveConsumer(v -> config.remember_nv = v) - .build()); + ConfigCategory category = builder.getOrCreateCategory(text(PREFIX + "category")); + ConfigEntryBuilder entryBuilder = builder.entryBuilder(); - category.addEntry(entryBuilder.startBooleanToggle( - //? < 1.19 { - /*new TranslatableComponent("text.cat_vision.config.option.auto_nv"), - *///?} >= 1.19 { - Component.translatable("text.cat_vision.config.option.auto_nv"), - //?} - config.auto_nv - ) - .setDefaultValue(true) - .setSaveConsumer(v -> config.auto_nv = v) - .build()); + category.addEntry(entryBuilder.startBooleanToggle(text(PREFIX + "option.remember_nv"), config.remember_nv) + .setDefaultValue(true) + .setSaveConsumer(v -> config.remember_nv = v) + .build()); - category.addEntry(entryBuilder.startBooleanToggle( - //? < 1.19 { - /*new TranslatableComponent("text.cat_vision.config.option.blindness_immunity"), - *///?} >= 1.19 { - Component.translatable("text.cat_vision.config.option.blindness_immunity"), - //?} - config.blindness_immunity - ) - .setDefaultValue(true) - .setSaveConsumer(v -> config.blindness_immunity = v) - .setTooltip( - //? < 1.19 { - /*new TranslatableComponent("text.cat_vision.config.tooltip.blindness_disclaimer.1"), - new TranslatableComponent("text.cat_vision.config.tooltip.blindness_disclaimer.2"), - new TranslatableComponent("text.cat_vision.config.tooltip.blindness_disclaimer.3"), - new TranslatableComponent("text.cat_vision.config.tooltip.blindness_disclaimer.4") - *///?} >= 1.19 { - Component.translatable("text.cat_vision.config.tooltip.blindness_disclaimer.1"), - Component.translatable("text.cat_vision.config.tooltip.blindness_disclaimer.2"), - Component.translatable("text.cat_vision.config.tooltip.blindness_disclaimer.3"), - Component.translatable("text.cat_vision.config.tooltip.blindness_disclaimer.4") - //?} - ) - .build()); + category.addEntry(entryBuilder.startBooleanToggle(text(PREFIX + "option.auto_nv"), config.auto_nv) + .setDefaultValue(true) + .setSaveConsumer(v -> config.auto_nv = v) + .build()); - category.addEntry(entryBuilder.startBooleanToggle( - //? < 1.19 { - /*new TranslatableComponent("text.cat_vision.config.option.nausea_immunity"), - *///?} >= 1.19 { - Component.translatable("text.cat_vision.config.option.nausea_immunity"), - //?} - config.nausea_immunity - ) - .setDefaultValue(true) - .setSaveConsumer(v -> config.nausea_immunity = v) - .build()); + category.addEntry(entryBuilder.startBooleanToggle(text(PREFIX + "option.blindness_immunity"), config.blindness_immunity) + .setDefaultValue(true) + .setSaveConsumer(v -> config.blindness_immunity = v) + .setTooltip( + text(PREFIX + "tooltip.blindness_disclaimer.1"), + text(PREFIX + "tooltip.blindness_disclaimer.2"), + text(PREFIX + "tooltip.blindness_disclaimer.3"), + text(PREFIX + "tooltip.blindness_disclaimer.4") + ) + .build()); + + category.addEntry(entryBuilder.startBooleanToggle(text(PREFIX + "option.nausea_immunity"), config.nausea_immunity) + .setDefaultValue(true) + .setSaveConsumer(v -> config.nausea_immunity = v) + .build()); //? >= 1.19 { - category.addEntry(entryBuilder.startBooleanToggle(Component.translatable("text.cat_vision.config.option.darkness_immunity"), config.darkness_immunity) + category.addEntry(entryBuilder.startBooleanToggle(text(PREFIX + "option.darkness_immunity"), config.darkness_immunity) .setDefaultValue(true) .setSaveConsumer(v -> config.darkness_immunity = v) .build()); //?} - builder.setSavingRunnable(config::save); + builder.setSavingRunnable(config::save); + + return builder.build(); + } - return builder.build(); - } + private static Component text(String key) { + //? < 1.19 { + /*return new TranslatableComponent(key); + *///?} >= 1.19 { + return Component.translatable(key); + //?} + } } From 89d4dd516ceb42e10388fa3202a7d3b6cc437c8a Mon Sep 17 00:00:00 2001 From: FrCynda Date: Mon, 24 Aug 2026 03:35:37 +0200 Subject: [PATCH 2/4] Add a night vision curve that fades with the light level Night vision is all-or-nothing today: the toggle drops you straight into the full potion effect. This makes it a curve instead - a lit strength, a dark strength, the light level counted as lit, an exponent for the shape, and a fade speed. VisionHandler recomputes the target every client tick and eases towards it; a GameRenderer mixin returns that value from the night vision scale so the vignette follows it. Off by default (nv_curve = false), so nothing changes unless you turn it on. The Forge mixin block in build.forge.gradle.kts was commented out because there were no mixins to build a refmap from - there is one now, so it goes back in. scripts/NightVisionCurveCheck.java is a plain javac/java -ea check for the curve maths, including the hand-edited-config values the sliders cannot reach. --- build.forge.gradle.kts | 13 +++--- .../cat_vision/config/ConfigData.java | 2 +- .../cat_vision/config/VisionSettings.java | 24 ++++++++++ .../cat_vision/event/EndTickListener.java | 3 ++ .../cat_vision/handler/VisionHandler.java | 44 +++++++++++++++++++ .../cat_vision/mixin/GameRendererMixin.java | 24 ++++++++++ src/main/resources/cat_vision.mixins.json | 4 +- 7 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 src/main/java/net/marios271/cat_vision/config/VisionSettings.java create mode 100644 src/main/java/net/marios271/cat_vision/handler/VisionHandler.java create mode 100644 src/main/java/net/marios271/cat_vision/mixin/GameRendererMixin.java diff --git a/build.forge.gradle.kts b/build.forge.gradle.kts index 8061b4c..b85dde2 100644 --- a/build.forge.gradle.kts +++ b/build.forge.gradle.kts @@ -66,14 +66,11 @@ legacyForge { } } -// No mixins exist yet (cat_vision.mixins.json has empty "mixins"/"client"). -// moddev's reobfJar (ART) hard-fails looking for the refmap's .mappings.tsrg, -// which the Mixin AP only emits when there is at least one mixin. Re-enable this -// block as soon as the first @Mixin is added. -//mixin { -// add(sourceSets.main.get(), "${prop("mod.id")}.mixins.refmap.json") -// config("${prop("mod.id")}.mixins.json") -//} +// These Forge versions run on SRG names, so the mixins need a refmap to find their targets. +mixin { + add(sourceSets.main.get(), "${prop("mod.id")}.mixins.refmap.json") + config("${prop("mod.id")}.mixins.json") +} repositories { mavenCentral() diff --git a/src/main/java/net/marios271/cat_vision/config/ConfigData.java b/src/main/java/net/marios271/cat_vision/config/ConfigData.java index a10004c..6be6a11 100644 --- a/src/main/java/net/marios271/cat_vision/config/ConfigData.java +++ b/src/main/java/net/marios271/cat_vision/config/ConfigData.java @@ -9,7 +9,7 @@ import java.io.FileWriter; import java.io.IOException; -public class ConfigData { +public class ConfigData extends VisionSettings { private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); private transient File file; diff --git a/src/main/java/net/marios271/cat_vision/config/VisionSettings.java b/src/main/java/net/marios271/cat_vision/config/VisionSettings.java new file mode 100644 index 0000000..d1f97dc --- /dev/null +++ b/src/main/java/net/marios271/cat_vision/config/VisionSettings.java @@ -0,0 +1,24 @@ +package net.marios271.cat_vision.config; + +public class VisionSettings { + public boolean nv_curve = false; + public double nv_lit = 0.0; + public double nv_dark = 1.0; + public double nv_shape = 1.0; + public int nv_lit_light = 12; + public double nv_speed = 0.01; + + public double strengthFor(int light) { + int litLight = (int) clamp(nv_lit_light, 0, 15); + double shape = clamp(nv_shape, 0.01, 10.0); + + double darkness = litLight <= 0 + ? (light <= 0 ? 1.0 : 0.0) + : clamp((litLight - light) / (double) litLight, 0.0, 1.0); + return clamp(nv_lit + (nv_dark - nv_lit) * Math.pow(darkness, shape), 0.0, 1.0); + } + + public static double clamp(double value, double min, double max) { + return value < min ? min : Math.min(value, max); + } +} diff --git a/src/main/java/net/marios271/cat_vision/event/EndTickListener.java b/src/main/java/net/marios271/cat_vision/event/EndTickListener.java index 990acb4..97068ee 100644 --- a/src/main/java/net/marios271/cat_vision/event/EndTickListener.java +++ b/src/main/java/net/marios271/cat_vision/event/EndTickListener.java @@ -2,6 +2,7 @@ import net.marios271.cat_vision.CatVision; import net.marios271.cat_vision.config.ConfigData; +import net.marios271.cat_vision.handler.VisionHandler; import net.minecraft.client.Minecraft; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; @@ -13,6 +14,8 @@ public static void onEndTick(Minecraft client) { ConfigData config = CatVision.CONFIG; + VisionHandler.tick(client); + boolean isSingleplayer = client.getSingleplayerServer() != null && !client.getSingleplayerServer().isPublished(); diff --git a/src/main/java/net/marios271/cat_vision/handler/VisionHandler.java b/src/main/java/net/marios271/cat_vision/handler/VisionHandler.java new file mode 100644 index 0000000..4142c52 --- /dev/null +++ b/src/main/java/net/marios271/cat_vision/handler/VisionHandler.java @@ -0,0 +1,44 @@ +package net.marios271.cat_vision.handler; + +import net.marios271.cat_vision.CatVision; +import net.marios271.cat_vision.config.ConfigData; +import net.marios271.cat_vision.config.VisionSettings; +import net.minecraft.client.Minecraft; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; + +public class VisionHandler { + + private static volatile boolean curveActive = false; + private static volatile float strength = 0.0F; + + public static boolean curveActive() { + return curveActive; + } + + public static float strength() { + return strength; + } + + public static void tick(Minecraft client) { + ConfigData config = CatVision.CONFIG; + + if (!config.nv_curve || !config.has_nv || client.player == null || client.level == null) { + curveActive = false; + strength = 0.0F; + return; + } + + if (!client.player.hasEffect(MobEffects.NIGHT_VISION)) + client.player.addEffect(new MobEffectInstance(MobEffects.NIGHT_VISION, Integer.MAX_VALUE)); + + int light = client.level.getMaxLocalRawBrightness(client.player.blockPosition()); + double target = config.strengthFor(light); + double speed = VisionSettings.clamp(config.nv_speed, 0.01, 1.0); + + strength += (float) ((target - strength) * speed); + if (Math.abs(target - strength) < 0.001) + strength = (float) target; + curveActive = true; + } +} diff --git a/src/main/java/net/marios271/cat_vision/mixin/GameRendererMixin.java b/src/main/java/net/marios271/cat_vision/mixin/GameRendererMixin.java new file mode 100644 index 0000000..7681247 --- /dev/null +++ b/src/main/java/net/marios271/cat_vision/mixin/GameRendererMixin.java @@ -0,0 +1,24 @@ +package net.marios271.cat_vision.mixin; + +import net.marios271.cat_vision.handler.VisionHandler; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.world.entity.LivingEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(GameRenderer.class) +public class GameRendererMixin { + + //? >= 26.2 { + @Inject(method = "nightVisionScale", at = @At("HEAD"), cancellable = true) + //?} else { + /*@Inject(method = "getNightVisionScale", at = @At("HEAD"), cancellable = true) + *///?} + private static void cat_vision$nightVisionCurve(LivingEntity entity, float partialTick, CallbackInfoReturnable cir) { + if (VisionHandler.curveActive() && entity == Minecraft.getInstance().player) + cir.setReturnValue(VisionHandler.strength()); + } +} diff --git a/src/main/resources/cat_vision.mixins.json b/src/main/resources/cat_vision.mixins.json index de07b1c..f7cde2c 100644 --- a/src/main/resources/cat_vision.mixins.json +++ b/src/main/resources/cat_vision.mixins.json @@ -7,5 +7,7 @@ "defaultRequire": 1 }, "mixins": [], - "client": [] + "client": [ + "GameRendererMixin" + ] } From 70cecff18114fb1ab39fe186b553df8e013bad6b Mon Sep 17 00:00:00 2001 From: FrCynda Date: Mon, 24 Aug 2026 03:35:38 +0200 Subject: [PATCH 3/4] Add the curve options to the config screen Sliders for the five curve values plus the toggle, with English, German and Austrian strings. --- .../cat_vision/config/ConfigScreen.java | 82 ++++++++++++++++++- .../assets/cat_vision/lang/de_at.json | 21 ++++- .../assets/cat_vision/lang/de_de.json | 21 ++++- .../assets/cat_vision/lang/en_us.json | 21 ++++- 4 files changed, 141 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/marios271/cat_vision/config/ConfigScreen.java b/src/main/java/net/marios271/cat_vision/config/ConfigScreen.java index e565ccc..50ca7de 100644 --- a/src/main/java/net/marios271/cat_vision/config/ConfigScreen.java +++ b/src/main/java/net/marios271/cat_vision/config/ConfigScreen.java @@ -1,14 +1,22 @@ package net.marios271.cat_vision.config; +import me.shedaniel.clothconfig2.api.AbstractConfigListEntry; import me.shedaniel.clothconfig2.api.ConfigBuilder; import me.shedaniel.clothconfig2.api.ConfigCategory; import me.shedaniel.clothconfig2.api.ConfigEntryBuilder; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; //? < 1.19 { -/*import net.minecraft.network.chat.TranslatableComponent; +/*import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.chat.TranslatableComponent; *///?} +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.function.DoubleConsumer; +import java.util.function.Function; + public class ConfigScreen { private static final String PREFIX = "text.cat_vision.config."; @@ -53,11 +61,75 @@ public static Screen create(Screen parent, ConfigData config) { .build()); //?} + for (AbstractConfigListEntry entry : curveEntries(entryBuilder, config)) + category.addEntry(entry); + builder.setSavingRunnable(config::save); return builder.build(); } + private static List curveEntries(ConfigEntryBuilder entryBuilder, VisionSettings settings) { + List entries = new ArrayList<>(); + + entries.add(entryBuilder.startBooleanToggle(text(PREFIX + "option.nv_curve"), settings.nv_curve) + .setDefaultValue(false) + .setTooltip( + text(PREFIX + "tooltip.nv_curve.1"), + text(PREFIX + "tooltip.nv_curve.2"), + text(PREFIX + "tooltip.nv_curve.3"), + text(PREFIX + "tooltip.nv_curve.4") + ) + .setSaveConsumer(v -> settings.nv_curve = v) + .build()); + + entries.add(slider(entryBuilder, "nv_lit", percent(settings.nv_lit), 0, 100, 0, + v -> literal(v + "%"), + v -> settings.nv_lit = v / 100.0, + text(PREFIX + "tooltip.nv_lit.1"), + text(PREFIX + "tooltip.nv_lit.2"))); + + entries.add(slider(entryBuilder, "nv_dark", percent(settings.nv_dark), 0, 100, 100, + v -> literal(v + "%"), + v -> settings.nv_dark = v / 100.0, + text(PREFIX + "tooltip.nv_dark.1"), + text(PREFIX + "tooltip.nv_dark.2"), + text(PREFIX + "tooltip.nv_dark.3"))); + + entries.add(slider(entryBuilder, "nv_lit_light", settings.nv_lit_light, 0, 15, 12, + v -> literal(String.valueOf(v)), + v -> settings.nv_lit_light = (int) v, + text(PREFIX + "tooltip.nv_lit_light"))); + + entries.add(slider(entryBuilder, "nv_shape", (int) Math.round(settings.nv_shape * 10), 1, 50, 10, + v -> literal(String.format(Locale.ROOT, "%.1f", v / 10.0)), + v -> settings.nv_shape = v / 10.0, + text(PREFIX + "tooltip.nv_shape.1"), + text(PREFIX + "tooltip.nv_shape.2"))); + + entries.add(slider(entryBuilder, "nv_speed", (int) Math.round(settings.nv_speed * 100), 1, 100, 1, + v -> literal(String.format(Locale.ROOT, "%.2f", v / 100.0)), + v -> settings.nv_speed = v / 100.0, + text(PREFIX + "tooltip.nv_speed"))); + + return entries; + } + + private static AbstractConfigListEntry slider(ConfigEntryBuilder entryBuilder, String key, int value, + int min, int max, int defaultValue, Function textGetter, + DoubleConsumer save, Component... tooltip) { + return entryBuilder.startIntSlider(text(PREFIX + "option." + key), value, min, max) + .setDefaultValue(defaultValue) + .setTextGetter(textGetter) + .setTooltip(tooltip) + .setSaveConsumer(v -> save.accept(v)) + .build(); + } + + private static int percent(double value) { + return (int) Math.round(value * 100); + } + private static Component text(String key) { //? < 1.19 { /*return new TranslatableComponent(key); @@ -65,4 +137,12 @@ private static Component text(String key) { return Component.translatable(key); //?} } + + private static Component literal(String value) { + //? < 1.19 { + /*return new TextComponent(value); + *///?} >= 1.19 { + return Component.literal(value); + //?} + } } diff --git a/src/main/resources/assets/cat_vision/lang/de_at.json b/src/main/resources/assets/cat_vision/lang/de_at.json index 81b9ee2..dcd63f7 100644 --- a/src/main/resources/assets/cat_vision/lang/de_at.json +++ b/src/main/resources/assets/cat_vision/lang/de_at.json @@ -14,9 +14,28 @@ "text.cat_vision.config.option.blindness_immunity": "Immunität gegn Blindheit", "text.cat_vision.config.option.nausea_immunity": "Immunität gegn Üblkeit", "text.cat_vision.config.option.darkness_immunity": "Immunität gegn Dunklheit", + "text.cat_vision.config.option.nv_curve": "Automatische Nochtsicht-Kurvn", + "text.cat_vision.config.option.nv_lit": "Nochtsicht an hölle Ortn", + "text.cat_vision.config.option.nv_dark": "Nochtsicht im Dunkln", + "text.cat_vision.config.option.nv_lit_light": "Ois hö gütends Lichtlevel", + "text.cat_vision.config.option.nv_shape": "Form vo da Kurvn", + "text.cat_vision.config.option.nv_speed": "Übagaungsgschwindigkeit", "text.cat_vision.config.tooltip.blindness_disclaimer.1": "[!] Immunität gegn Blindheit funktioniat nua in Oanzlspüla", "text.cat_vision.config.tooltip.blindness_disclaimer.2": "und ned in LAN-Wöltn oder Measpüla, weil die Untadrückung", "text.cat_vision.config.tooltip.blindness_disclaimer.3": "von Blindheit Spülan erlaubt, zu sprintn, was ma mit dem", - "text.cat_vision.config.tooltip.blindness_disclaimer.4": "Blindheit-Effekt ned mochn kenna soit." + "text.cat_vision.config.tooltip.blindness_disclaimer.4": "Blindheit-Effekt ned mochn kenna soit.", + "text.cat_vision.config.tooltip.nv_curve.1": "Blendt Nochtsicht ei, je dunkla's um di wiad,", + "text.cat_vision.config.tooltip.nv_curve.2": "damitst vo hölle af dunkle Ortn gehn kaunst,", + "text.cat_vision.config.tooltip.nv_curve.3": "ohne's ständig söwa umzschoitn.", + "text.cat_vision.config.tooltip.nv_curve.4": "De Umschoittastn schoit daun de Kurvn au und aus.", + "text.cat_vision.config.tooltip.nv_lit_light": "Ab dem Lichtlevel wiad da hölle Wert gnumma.", + "text.cat_vision.config.tooltip.nv_lit.1": "Wia vü Nochtsicht, waunns um di umadum hö is.", + "text.cat_vision.config.tooltip.nv_lit.2": "0 = dei normale Sicht, 1 = da voi Trank.", + "text.cat_vision.config.tooltip.nv_dark.1": "Wia vü Nochtsicht bei Lichtlevel 0, stockfinsta.", + "text.cat_vision.config.tooltip.nv_dark.2": "1 is genau des, wos a Nochtsichttrank mocht.", + "text.cat_vision.config.tooltip.nv_dark.3": "Da söbe Wert wia obn haaßt, de Kurvn mocht nix.", + "text.cat_vision.config.tooltip.nv_shape.1": "Unta 1.0 wiad frua eiblendt, üba 1.0 woat's,", + "text.cat_vision.config.tooltip.nv_shape.2": "bis wiaklich finsta is. 1.0 is a grode Linie.", + "text.cat_vision.config.tooltip.nv_speed": "Wia schnö übablendt wiad. 1.0 is sofuat." } diff --git a/src/main/resources/assets/cat_vision/lang/de_de.json b/src/main/resources/assets/cat_vision/lang/de_de.json index 14e9eea..8d9cb3a 100644 --- a/src/main/resources/assets/cat_vision/lang/de_de.json +++ b/src/main/resources/assets/cat_vision/lang/de_de.json @@ -14,9 +14,28 @@ "text.cat_vision.config.option.blindness_immunity": "Immunität gegen Blindheit", "text.cat_vision.config.option.nausea_immunity": "Immunität gegen Übelkeit", "text.cat_vision.config.option.darkness_immunity": "Immunität gegen Dunkelheit", + "text.cat_vision.config.option.nv_curve": "Automatische Nachtsicht-Kurve", + "text.cat_vision.config.option.nv_lit": "Nachtsicht an hellen Orten", + "text.cat_vision.config.option.nv_dark": "Nachtsicht im Dunkeln", + "text.cat_vision.config.option.nv_lit_light": "Als hell geltendes Lichtlevel", + "text.cat_vision.config.option.nv_shape": "Form der Kurve", + "text.cat_vision.config.option.nv_speed": "Übergangsgeschwindigkeit", "text.cat_vision.config.tooltip.blindness_disclaimer.1": "[!] Immunität gegen Blindheit funktioniert nur in Einzelspieler", "text.cat_vision.config.tooltip.blindness_disclaimer.2": "und nicht in LAN-Welten oder Mehrspieler, da die Unterdrückung", "text.cat_vision.config.tooltip.blindness_disclaimer.3": "von Blindheit Spielern erlaubt, zu sprinten, was man mit dem", - "text.cat_vision.config.tooltip.blindness_disclaimer.4": "Blindheit-Effekt nicht machen können sollte." + "text.cat_vision.config.tooltip.blindness_disclaimer.4": "Blindheit-Effekt nicht machen können sollte.", + "text.cat_vision.config.tooltip.nv_curve.1": "Blendet Nachtsicht ein, je dunkler es um dich wird,", + "text.cat_vision.config.tooltip.nv_curve.2": "damit du von hellen an dunkle Orte gehen kannst,", + "text.cat_vision.config.tooltip.nv_curve.3": "ohne sie ständig selbst umzuschalten.", + "text.cat_vision.config.tooltip.nv_curve.4": "Die Umschalttaste schaltet dann die Kurve an und aus.", + "text.cat_vision.config.tooltip.nv_lit_light": "Ab diesem Lichtlevel wird der helle Wert verwendet.", + "text.cat_vision.config.tooltip.nv_lit.1": "Wie viel Nachtsicht, wenn es um dich herum hell ist.", + "text.cat_vision.config.tooltip.nv_lit.2": "0 = deine normale Sicht, 1 = der volle Trank.", + "text.cat_vision.config.tooltip.nv_dark.1": "Wie viel Nachtsicht bei Lichtlevel 0, stockdunkel.", + "text.cat_vision.config.tooltip.nv_dark.2": "1 ist genau das, was ein Nachtsichttrank macht.", + "text.cat_vision.config.tooltip.nv_dark.3": "Derselbe Wert wie oben heißt, die Kurve macht nichts.", + "text.cat_vision.config.tooltip.nv_shape.1": "Unter 1.0 wird früh eingeblendet, über 1.0 wartet es,", + "text.cat_vision.config.tooltip.nv_shape.2": "bis es wirklich dunkel ist. 1.0 ist eine Gerade.", + "text.cat_vision.config.tooltip.nv_speed": "Wie schnell übergeblendet wird. 1.0 ist sofort." } diff --git a/src/main/resources/assets/cat_vision/lang/en_us.json b/src/main/resources/assets/cat_vision/lang/en_us.json index 7923ae1..e877bb3 100644 --- a/src/main/resources/assets/cat_vision/lang/en_us.json +++ b/src/main/resources/assets/cat_vision/lang/en_us.json @@ -14,9 +14,28 @@ "text.cat_vision.config.option.blindness_immunity": "Blindness Immunity", "text.cat_vision.config.option.nausea_immunity": "Nausea Immunity", "text.cat_vision.config.option.darkness_immunity": "Darkness Immunity", + "text.cat_vision.config.option.nv_curve": "Automatic Night Vision Curve", + "text.cat_vision.config.option.nv_lit": "Night Vision in lit places", + "text.cat_vision.config.option.nv_dark": "Night Vision in the dark", + "text.cat_vision.config.option.nv_lit_light": "Light level counted as lit", + "text.cat_vision.config.option.nv_shape": "Curve shape", + "text.cat_vision.config.option.nv_speed": "Fade speed", "text.cat_vision.config.tooltip.blindness_disclaimer.1": "[!] Blindness Suppression only works on Singleplayer", "text.cat_vision.config.tooltip.blindness_disclaimer.2": "and not on LAN or multiplayer worlds, as suppressing", "text.cat_vision.config.tooltip.blindness_disclaimer.3": "blindness allows players to sprint, which they should", - "text.cat_vision.config.tooltip.blindness_disclaimer.4": "not be able to do with the blindness effect." + "text.cat_vision.config.tooltip.blindness_disclaimer.4": "not be able to do with the blindness effect.", + "text.cat_vision.config.tooltip.nv_curve.1": "Fades night vision in as it gets darker around you,", + "text.cat_vision.config.tooltip.nv_curve.2": "so you can walk from bright places into dark ones", + "text.cat_vision.config.tooltip.nv_curve.3": "without toggling it yourself.", + "text.cat_vision.config.tooltip.nv_curve.4": "The toggle key then switches the curve on and off.", + "text.cat_vision.config.tooltip.nv_lit_light": "At this light level and above, the lit value is used.", + "text.cat_vision.config.tooltip.nv_lit.1": "How much night vision when it is bright around you.", + "text.cat_vision.config.tooltip.nv_lit.2": "0 = your normal view, 1 = the full potion.", + "text.cat_vision.config.tooltip.nv_dark.1": "How much night vision at light level 0, pitch black.", + "text.cat_vision.config.tooltip.nv_dark.2": "1 is exactly what a night vision potion looks like.", + "text.cat_vision.config.tooltip.nv_dark.3": "The same value as above means the curve does nothing.", + "text.cat_vision.config.tooltip.nv_shape.1": "Below 1.0 fades in early, above 1.0 waits until it", + "text.cat_vision.config.tooltip.nv_shape.2": "really is dark. 1.0 is a straight line.", + "text.cat_vision.config.tooltip.nv_speed": "How fast it fades between the two. 1.0 is instant." } From 9e7a9897c7c5c474a262bef599ac20c67b811c06 Mon Sep 17 00:00:00 2001 From: FrCynda Date: Mon, 24 Aug 2026 03:49:48 +0200 Subject: [PATCH 4/4] Add presets: Slow adaptation, Adaptive, Always, Never, Custom Five curve values is a lot to ask of someone who just wants the mod to work. The preset dropdown covers the useful combinations and moves the sliders into an Advanced subcategory underneath; touching a slider reads back as Custom. Always is the mod's current behaviour, so the default preset is what everyone already has. The preset applies in the saving runnable rather than in its own save consumer: Cloth saves entries in order and cascades into subcategories, so the Advanced sliders would otherwise write their unchanged values back over it. --- .../cat_vision/config/ConfigScreen.java | 47 +++++++++++- .../cat_vision/config/VisionSettings.java | 71 +++++++++++++++++++ .../assets/cat_vision/lang/de_at.json | 17 ++++- .../assets/cat_vision/lang/de_de.json | 17 ++++- .../assets/cat_vision/lang/en_us.json | 17 ++++- 5 files changed, 164 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/marios271/cat_vision/config/ConfigScreen.java b/src/main/java/net/marios271/cat_vision/config/ConfigScreen.java index 50ca7de..c7608c8 100644 --- a/src/main/java/net/marios271/cat_vision/config/ConfigScreen.java +++ b/src/main/java/net/marios271/cat_vision/config/ConfigScreen.java @@ -14,6 +14,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; +import java.util.Optional; import java.util.function.DoubleConsumer; import java.util.function.Function; @@ -61,14 +62,56 @@ public static Screen create(Screen parent, ConfigData config) { .build()); //?} - for (AbstractConfigListEntry entry : curveEntries(entryBuilder, config)) + List afterSave = new ArrayList<>(); + for (AbstractConfigListEntry entry : nvEntries(entryBuilder, config, afterSave)) category.addEntry(entry); - builder.setSavingRunnable(config::save); + builder.setSavingRunnable(() -> { + for (Runnable task : afterSave) + task.run(); + config.save(); + }); return builder.build(); } + private static List nvEntries(ConfigEntryBuilder entryBuilder, VisionSettings settings, + List afterSave) { + List entries = new ArrayList<>(); + + VisionSettings.Preset shown = VisionSettings.Preset.of(settings); + VisionSettings.Preset[] chosen = { shown }; + + entries.add(entryBuilder.startEnumSelector(text(PREFIX + "option.nv_preset"), VisionSettings.Preset.class, shown) + .setDefaultValue(VisionSettings.Preset.of(new VisionSettings())) + .setEnumNameProvider(preset -> text(PREFIX + "preset." + presetKey(preset.name()))) + .setTooltipSupplier(preset -> Optional.of(new Component[] { + text(PREFIX + "tooltip.preset." + presetKey(preset.name())) + })) + .setSaveConsumer(preset -> chosen[0] = preset) + .build()); + + // Cloth saves the Advanced sliders after this entry, so applying the preset in its own + // save consumer would be overwritten by whatever the sliders were still showing. + afterSave.add(() -> { + if (chosen[0] != shown) + chosen[0].applyTo(settings); + }); + + entries.add(entryBuilder.startSubCategory(text(PREFIX + "option.advanced"), curveEntries(entryBuilder, settings)) + .setTooltip( + text(PREFIX + "tooltip.advanced.1"), + text(PREFIX + "tooltip.advanced.2") + ) + .build()); + + return entries; + } + + private static String presetKey(String name) { + return name.toLowerCase(Locale.ROOT); + } + private static List curveEntries(ConfigEntryBuilder entryBuilder, VisionSettings settings) { List entries = new ArrayList<>(); diff --git a/src/main/java/net/marios271/cat_vision/config/VisionSettings.java b/src/main/java/net/marios271/cat_vision/config/VisionSettings.java index d1f97dc..98aaf94 100644 --- a/src/main/java/net/marios271/cat_vision/config/VisionSettings.java +++ b/src/main/java/net/marios271/cat_vision/config/VisionSettings.java @@ -8,6 +8,53 @@ public class VisionSettings { public int nv_lit_light = 12; public double nv_speed = 0.01; + public enum Preset { + SLOW, + ADAPTIVE, + ALWAYS, + NEVER, + CUSTOM; + + public void applyTo(VisionSettings settings) { + VisionSettings defaults = new VisionSettings(); + switch (this) { + case ALWAYS: + settings.nv_curve = false; + break; + case NEVER: + settings.nv_curve = true; + settings.nv_lit = 0.0; + settings.nv_dark = 0.0; + break; + case SLOW: + case ADAPTIVE: + settings.nv_curve = true; + settings.nv_lit = defaults.nv_lit; + settings.nv_dark = defaults.nv_dark; + settings.nv_lit_light = defaults.nv_lit_light; + settings.nv_shape = defaults.nv_shape; + settings.nv_speed = this == SLOW ? defaults.nv_speed : 0.1; + break; + default: + break; + } + } + + public static Preset of(VisionSettings settings) { + if (!settings.nv_curve) + return ALWAYS; + if (settings.nv_lit == 0.0 && settings.nv_dark == 0.0) + return NEVER; + for (Preset preset : new Preset[] { SLOW, ADAPTIVE }) { + VisionSettings applied = settings.copy(); + preset.applyTo(applied); + if (applied.sameCurveAs(settings)) + return preset; + } + return CUSTOM; + } + } + public double strengthFor(int light) { int litLight = (int) clamp(nv_lit_light, 0, 15); double shape = clamp(nv_shape, 0.01, 10.0); @@ -18,6 +65,30 @@ public double strengthFor(int light) { return clamp(nv_lit + (nv_dark - nv_lit) * Math.pow(darkness, shape), 0.0, 1.0); } + public boolean sameCurveAs(VisionSettings other) { + return nv_curve == other.nv_curve + && nv_lit == other.nv_lit + && nv_dark == other.nv_dark + && nv_lit_light == other.nv_lit_light + && nv_shape == other.nv_shape + && nv_speed == other.nv_speed; + } + + public VisionSettings copy() { + VisionSettings copy = new VisionSettings(); + copy.copyFrom(this); + return copy; + } + + public void copyFrom(VisionSettings other) { + nv_curve = other.nv_curve; + nv_lit = other.nv_lit; + nv_dark = other.nv_dark; + nv_shape = other.nv_shape; + nv_lit_light = other.nv_lit_light; + nv_speed = other.nv_speed; + } + public static double clamp(double value, double min, double max) { return value < min ? min : Math.min(value, max); } diff --git a/src/main/resources/assets/cat_vision/lang/de_at.json b/src/main/resources/assets/cat_vision/lang/de_at.json index dcd63f7..4c237bb 100644 --- a/src/main/resources/assets/cat_vision/lang/de_at.json +++ b/src/main/resources/assets/cat_vision/lang/de_at.json @@ -37,5 +37,20 @@ "text.cat_vision.config.tooltip.nv_dark.3": "Da söbe Wert wia obn haaßt, de Kurvn mocht nix.", "text.cat_vision.config.tooltip.nv_shape.1": "Unta 1.0 wiad frua eiblendt, üba 1.0 woat's,", "text.cat_vision.config.tooltip.nv_shape.2": "bis wiaklich finsta is. 1.0 is a grode Linie.", - "text.cat_vision.config.tooltip.nv_speed": "Wia schnö übablendt wiad. 1.0 is sofuat." + "text.cat_vision.config.tooltip.nv_speed": "Wia schnö übablendt wiad. 1.0 is sofuat.", + + "text.cat_vision.config.option.nv_preset": "Nochtsicht", + "text.cat_vision.config.preset.slow": "Longsame Aupassung", + "text.cat_vision.config.preset.adaptive": "Aupassend", + "text.cat_vision.config.preset.always": "Imma", + "text.cat_vision.config.preset.never": "Nia", + "text.cat_vision.config.preset.custom": "Söwa eigstöllt", + "text.cat_vision.config.tooltip.preset.slow": "Empfohln. Blendt si ei, je dunkla's wiad, so longsom, dass ma's kaum merkt.", + "text.cat_vision.config.tooltip.preset.adaptive": "Da söbe Übagaung, schnö gnua, dass ma'n siacht.", + "text.cat_vision.config.tooltip.preset.always": "Volle Nochtsicht, sobold s au is, genau so wia da Mod imma scho funktioniat hot.", + "text.cat_vision.config.tooltip.preset.never": "Nochtsicht kummt nia, aa waunn s au is. Gedocht fia oanzlne Dimensionen.", + "text.cat_vision.config.tooltip.preset.custom": "Deine eignan Weat aus de erweiterten Eistöllungen do unt.", + "text.cat_vision.config.option.advanced": "Erweitert", + "text.cat_vision.config.tooltip.advanced.1": "De Regla, fia de wo de Voreistöllung do obn steht.", + "text.cat_vision.config.tooltip.advanced.2": "Wannst oan dovo bewegst, wiad aus da Voreistöllung \"Söwa eigstöllt\"." } diff --git a/src/main/resources/assets/cat_vision/lang/de_de.json b/src/main/resources/assets/cat_vision/lang/de_de.json index 8d9cb3a..25260b5 100644 --- a/src/main/resources/assets/cat_vision/lang/de_de.json +++ b/src/main/resources/assets/cat_vision/lang/de_de.json @@ -37,5 +37,20 @@ "text.cat_vision.config.tooltip.nv_dark.3": "Derselbe Wert wie oben heißt, die Kurve macht nichts.", "text.cat_vision.config.tooltip.nv_shape.1": "Unter 1.0 wird früh eingeblendet, über 1.0 wartet es,", "text.cat_vision.config.tooltip.nv_shape.2": "bis es wirklich dunkel ist. 1.0 ist eine Gerade.", - "text.cat_vision.config.tooltip.nv_speed": "Wie schnell übergeblendet wird. 1.0 ist sofort." + "text.cat_vision.config.tooltip.nv_speed": "Wie schnell übergeblendet wird. 1.0 ist sofort.", + + "text.cat_vision.config.option.nv_preset": "Nachtsicht", + "text.cat_vision.config.preset.slow": "Langsame Anpassung", + "text.cat_vision.config.preset.adaptive": "Anpassend", + "text.cat_vision.config.preset.always": "Immer", + "text.cat_vision.config.preset.never": "Nie", + "text.cat_vision.config.preset.custom": "Benutzerdefiniert", + "text.cat_vision.config.tooltip.preset.slow": "Empfohlen. Blendet sich ein, je dunkler es wird, so langsam, dass man es kaum bemerkt.", + "text.cat_vision.config.tooltip.preset.adaptive": "Derselbe Übergang, schnell genug, um ihn zu sehen.", + "text.cat_vision.config.tooltip.preset.always": "Volle Nachtsicht, sobald sie an ist, genau wie der Mod schon immer funktioniert hat.", + "text.cat_vision.config.tooltip.preset.never": "Nachtsicht erscheint nie, auch wenn sie an ist. Gedacht für einzelne Dimensionen.", + "text.cat_vision.config.tooltip.preset.custom": "Deine eigenen Werte aus den erweiterten Einstellungen unten.", + "text.cat_vision.config.option.advanced": "Erweitert", + "text.cat_vision.config.tooltip.advanced.1": "Die Regler, für die die Voreinstellung oben steht.", + "text.cat_vision.config.tooltip.advanced.2": "Wer einen davon bewegt, macht aus der Voreinstellung \"Benutzerdefiniert\"." } diff --git a/src/main/resources/assets/cat_vision/lang/en_us.json b/src/main/resources/assets/cat_vision/lang/en_us.json index e877bb3..232b83c 100644 --- a/src/main/resources/assets/cat_vision/lang/en_us.json +++ b/src/main/resources/assets/cat_vision/lang/en_us.json @@ -37,5 +37,20 @@ "text.cat_vision.config.tooltip.nv_dark.3": "The same value as above means the curve does nothing.", "text.cat_vision.config.tooltip.nv_shape.1": "Below 1.0 fades in early, above 1.0 waits until it", "text.cat_vision.config.tooltip.nv_shape.2": "really is dark. 1.0 is a straight line.", - "text.cat_vision.config.tooltip.nv_speed": "How fast it fades between the two. 1.0 is instant." + "text.cat_vision.config.tooltip.nv_speed": "How fast it fades between the two. 1.0 is instant.", + + "text.cat_vision.config.option.nv_preset": "Night Vision", + "text.cat_vision.config.preset.slow": "Slow adaptation", + "text.cat_vision.config.preset.adaptive": "Adaptive", + "text.cat_vision.config.preset.always": "Always", + "text.cat_vision.config.preset.never": "Never", + "text.cat_vision.config.preset.custom": "Custom", + "text.cat_vision.config.tooltip.preset.slow": "Recommended. Fades in as it gets darker, slowly enough that you barely notice it happening.", + "text.cat_vision.config.tooltip.preset.adaptive": "The same fade, fast enough that you see it happen.", + "text.cat_vision.config.tooltip.preset.always": "Full night vision whenever it is switched on, exactly as the mod has always worked.", + "text.cat_vision.config.tooltip.preset.never": "Night vision never shows, even while it is switched on. Meant for a single dimension.", + "text.cat_vision.config.tooltip.preset.custom": "Your own values from the advanced settings below.", + "text.cat_vision.config.option.advanced": "Advanced", + "text.cat_vision.config.tooltip.advanced.1": "The sliders the preset above stands in for.", + "text.cat_vision.config.tooltip.advanced.2": "Moving any of them turns the preset into Custom." }