Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions build.forge.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
12 changes: 11 additions & 1 deletion src/main/java/net/marios271/cat_vision/config/ConfigData.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -22,6 +22,16 @@ public class ConfigData {

public boolean has_nv = false;

public void resetToDefaults() {
ConfigData defaults = new ConfigData();
remember_nv = defaults.remember_nv;
auto_nv = defaults.auto_nv;
blindness_immunity = defaults.blindness_immunity;
nausea_immunity = defaults.nausea_immunity;
darkness_immunity = defaults.darkness_immunity;
copyFrom(defaults);
}

public void save() {
try (FileWriter writer = new FileWriter(file)) {
GSON.toJson(this, writer);
Expand Down
232 changes: 144 additions & 88 deletions src/main/java/net/marios271/cat_vision/config/ConfigScreen.java
Original file line number Diff line number Diff line change
@@ -1,106 +1,162 @@
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;
//? < 1.19 {
/*import net.minecraft.network.chat.TranslatableComponent;
*///?} >= 1.19 {
import net.minecraft.network.chat.Component;
//?}
//? < 1.19 {
/*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 {
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")
//?}
);

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();

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());

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(
//? < 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(
//? < 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());
private static final String PREFIX = "text.cat_vision.config.";

public static Screen create(Screen parent, ConfigData config) {
ConfigBuilder builder = ConfigBuilder.create()
.setParentScreen(parent)
.setTitle(text(PREFIX + "title"));

ConfigCategory category = builder.getOrCreateCategory(text(PREFIX + "category"));
ConfigEntryBuilder entryBuilder = builder.entryBuilder();

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(text(PREFIX + "option.auto_nv"), config.auto_nv)
.setDefaultValue(true)
.setSaveConsumer(v -> config.auto_nv = 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);
for (AbstractConfigListEntry entry : curveEntries(entryBuilder, config))
category.addEntry(entry);

return builder.build();
}
boolean[] reset = new boolean[1];
category.addEntry(entryBuilder.startBooleanToggle(text(PREFIX + "option.reset"), false)
.setDefaultValue(false)
.setTooltip(
text(PREFIX + "tooltip.reset.1"),
text(PREFIX + "tooltip.reset.2")
)
.setSaveConsumer(v -> reset[0] = v)
.build());

builder.setSavingRunnable(() -> {
if (reset[0])
config.resetToDefaults();
config.save();
});

return builder.build();
}

private static List<AbstractConfigListEntry> curveEntries(ConfigEntryBuilder entryBuilder, VisionSettings settings) {
List<AbstractConfigListEntry> 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<Integer, Component> 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);
*///?} >= 1.19 {
return Component.translatable(key);
//?}
}

private static Component literal(String value) {
//? < 1.19 {
/*return new TextComponent(value);
*///?} >= 1.19 {
return Component.literal(value);
//?}
}
}
33 changes: 33 additions & 0 deletions src/main/java/net/marios271/cat_vision/config/VisionSettings.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
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 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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();

Expand Down
44 changes: 44 additions & 0 deletions src/main/java/net/marios271/cat_vision/handler/VisionHandler.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
Loading