Port to 1.19.4, Add tab support & Large code cleanup

This commit is contained in:
Motschen
2023-03-08 21:27:41 +01:00
parent b5052ff324
commit cacd3516c1
8 changed files with 111 additions and 66 deletions

View File

@@ -1,5 +1,6 @@
package eu.midnightdust.core.config; package eu.midnightdust.core.config;
import com.google.common.collect.Lists;
import eu.midnightdust.lib.config.MidnightConfig; import eu.midnightdust.lib.config.MidnightConfig;
import java.util.List; import java.util.List;
@@ -14,19 +15,19 @@ public class MidnightConfigExample extends MidnightConfig {
@Comment public static Comment text1; // Comments are rendered like an option without a button and are excluded from the config file @Comment public static Comment text1; // Comments are rendered like an option without a button and are excluded from the config file
@Comment(centered = true) public static Comment text2; // Centered comments are the same as normal ones - just centered! @Comment(centered = true) public static Comment text2; // Centered comments are the same as normal ones - just centered!
@Entry public static int fabric = 16777215; // Example for an int option
@Entry public static double world = 1.4D; // Example for a double option
@Entry public static boolean showInfo = true; // Example for a boolean option @Entry public static boolean showInfo = true; // Example for a boolean option
@Entry public static String name = "Hello World!"; // Example for a string option @Entry(category = "text") public static String name = "Hello World!"; // Example for a string option, which is in a category!
@Entry public static TestEnum testEnum = TestEnum.FABRIC; // Example for an enum option @Entry(category = "text") public static TestEnum testEnum = TestEnum.FABRIC; // Example for an enum option
public enum TestEnum { // Enums allow the user to cycle through predefined options public enum TestEnum { // Enums allow the user to cycle through predefined options
QUILT, FABRIC, FORGE QUILT, FABRIC, FORGE
} }
@Entry(min=69,max=420) public static int hello = 420; // - The entered number has to be larger than 69 and smaller than 420 @Entry(category = "numbers") public static int fabric = 16777215; // Example for an int option
@Entry(width = 7, min = 7, isColor = true, name = "I am a color!") public static String titleColor = "#ffffff"; // The isColor property adds a preview box for a hexadecimal color @Entry(category = "numbers") public static double world = 1.4D; // Example for a double option
@Entry(name = "I am an array list!") public static List<String> arrayList = List.of("String1", "String2"); // Array String Lists are also supported @Entry(category = "numbers", min=69,max=420) public static int hello = 420; // - The entered number has to be larger than 69 and smaller than 420
@Entry(name = "I am an int slider.",isSlider = true, min = 0, max = 100) public static int intSlider = 35; // Int fields can also be displayed as a Slider @Entry(category = "text", width = 7, min = 7, isColor = true, name = "I am a color!") public static String titleColor = "#ffffff"; // The isColor property adds a preview box for a hexadecimal color
@Entry(name = "I am a float slider!", isSlider = true, min = 0f, max = 1f, precision = 1000) public static float floatSlider = 0.24f; // And so can floats! Precision defines the amount of decimal places @Entry(category = "sliders", name = "I am an array list!") public static List<String> arrayList = Lists.newArrayList("String1", "String2"); // Array String Lists are also supported
@Entry(category = "sliders", name = "I am an int slider.",isSlider = true, min = 0, max = 100) public static int intSlider = 35; // Int fields can also be displayed as a Slider
@Entry(category = "sliders", name = "I am a float slider!", isSlider = true, min = 0f, max = 1f, precision = 1000) public static float floatSlider = 0.24f; // And so can floats! Precision defines the amount of decimal places
// The name field can be used to specify a custom translation string or plain text // The name field can be used to specify a custom translation string or plain text
public static int imposter = 16777215; // - Entries without an @Entry or @Comment annotation are ignored public static int imposter = 16777215; // - Entries without an @Entry or @Comment annotation are ignored
@@ -49,11 +50,13 @@ public class MidnightConfigExample extends MidnightConfig {
"modid.midnightconfig.testEnum":"I am an enum!", "modid.midnightconfig.testEnum":"I am an enum!",
"modid.midnightconfig.enum.TestEnum.FORGE":"Slow", "modid.midnightconfig.enum.TestEnum.FORGE":"Slow",
"modid.midnightconfig.enum.TestEnum.FABRIC":"Fancy", "modid.midnightconfig.enum.TestEnum.FABRIC":"Fancy",
"modid.midnightconfig.enum.TestEnum.QUILT":"Fabulous" "modid.midnightconfig.enum.TestEnum.QUILT":"Fabulous",
"modid.midnightconfig.category.numbers": "Numbers",
"modid.midnightconfig.category.text": "Text",
"modid.midnightconfig.category.sliders": "Sliders"
} }
To initialize the config you have to call "MidnightConfig.init("modid", MidnightConfigExample.class)" in your ModInitializer To initialize the config you have to call "MidnightConfig.init("modid", MidnightConfigExample.class)" in your ModInitializer
To get an instance of the config screen you have to call "MidnightConfig.getScreen(parent, "modid");" To get an instance of the config screen you have to call "MidnightConfig.getScreen(parent, "modid");"
If you don't use the whole library and therefore not the automatic ModMenu integration, the code in your ModMenu integration class would look something like this: If you don't use the whole library and therefore not the automatic ModMenu integration, the code in your ModMenu integration class would look something like this:
@Override @Override
public ConfigScreenFactory<?> getModConfigScreenFactory() { public ConfigScreenFactory<?> getModConfigScreenFactory() {

View File

@@ -15,7 +15,7 @@ subprojects {
// The following line declares the mojmap mappings, you may use other mappings as well // The following line declares the mojmap mappings, you may use other mappings as well
//mappings loom.officialMojangMappings() //mappings loom.officialMojangMappings()
// The following line declares the yarn mappings you may select this one as well. // The following line declares the yarn mappings you may select this one as well.
mappings "net.fabricmc:yarn:1.19.3+build.3:v2" mappings "net.fabricmc:yarn:${rootProject.yarn_mappings}:v2"
} }
} }

View File

@@ -14,7 +14,6 @@ public class MidnightLibClient {
public static void onInitializeClient() { public static void onInitializeClient() {
MidnightConfig.init("midnightlib", MidnightLibConfig.class); MidnightConfig.init("midnightlib", MidnightLibConfig.class);
hiddenMods.add("puzzle");
if (MidnightLibConfig.special_hats) HatLoader.init(); if (MidnightLibConfig.special_hats) HatLoader.init();
} }

View File

@@ -46,7 +46,7 @@ public class MidnightConfigOverviewScreen extends Screen {
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
this.renderBackground(matrices); this.renderBackground(matrices);
this.list.render(matrices, mouseX, mouseY, delta); this.list.render(matrices, mouseX, mouseY, delta);
drawCenteredText(matrices, textRenderer, title, width / 2, 15, 0xFFFFFF); drawCenteredTextWithShadow(matrices, textRenderer, title, width / 2, 15, 0xFFFFFF);
super.render(matrices, mouseX, mouseY, delta); super.render(matrices, mouseX, mouseY, delta);
} }
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)

View File

@@ -13,6 +13,9 @@ import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.client.gui.Element; import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.Selectable; import net.minecraft.client.gui.Selectable;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.tab.GridScreenTab;
import net.minecraft.client.gui.tab.Tab;
import net.minecraft.client.gui.tab.TabManager;
import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.tooltip.Tooltip;
import net.minecraft.client.gui.widget.*; import net.minecraft.client.gui.widget.*;
import net.minecraft.client.resource.language.I18n; import net.minecraft.client.resource.language.I18n;
@@ -56,9 +59,8 @@ public abstract class MidnightConfig {
Field field; Field field;
Object widget; Object widget;
int width; int width;
int max;
boolean centered; boolean centered;
Map.Entry<TextFieldWidget,Text> error; Text error;
Object defaultValue; Object defaultValue;
Object value; Object value;
String tempValue; String tempValue;
@@ -67,6 +69,7 @@ public abstract class MidnightConfig {
Text name; Text name;
int index; int index;
ClickableWidget colorButton; ClickableWidget colorButton;
Tab tab;
} }
public static final Map<String,Class<?>> configClass = new HashMap<>(); public static final Map<String,Class<?>> configClass = new HashMap<>();
@@ -113,7 +116,6 @@ public abstract class MidnightConfig {
else if (type == float.class) textField(info, Float::parseFloat, DECIMAL_ONLY, (float) e.min(), (float) e.max(), false); else if (type == float.class) textField(info, Float::parseFloat, DECIMAL_ONLY, (float) e.min(), (float) e.max(), false);
else if (type == double.class) textField(info, Double::parseDouble, DECIMAL_ONLY, e.min(), e.max(), false); else if (type == double.class) textField(info, Double::parseDouble, DECIMAL_ONLY, e.min(), e.max(), false);
else if (type == String.class || type == List.class) { else if (type == String.class || type == List.class) {
info.max = e.max() == Double.MAX_VALUE ? Integer.MAX_VALUE : (int) e.max();
textField(info, String::length, null, Math.min(e.min(), 0), Math.max(e.max(), 1), true); textField(info, String::length, null, Math.min(e.min(), 0), Math.max(e.max(), 1), true);
} else if (type == boolean.class) { } else if (type == boolean.class) {
Function<Object, Text> func = value -> Text.translatable((Boolean) value ? "gui.yes" : "gui.no").formatted((Boolean) value ? Formatting.GREEN : Formatting.RED); Function<Object, Text> func = value -> Text.translatable((Boolean) value ? "gui.yes" : "gui.no").formatted((Boolean) value ? Formatting.GREEN : Formatting.RED);
@@ -146,9 +148,9 @@ public abstract class MidnightConfig {
if (!(isNumber && s.isEmpty()) && !s.equals("-") && !s.equals(".")) { if (!(isNumber && s.isEmpty()) && !s.equals("-") && !s.equals(".")) {
try { value = f.apply(s); } catch(NumberFormatException e){ return false; } try { value = f.apply(s); } catch(NumberFormatException e){ return false; }
inLimits = value.doubleValue() >= min && value.doubleValue() <= max; inLimits = value.doubleValue() >= min && value.doubleValue() <= max;
info.error = inLimits? null : new AbstractMap.SimpleEntry<>(t, Text.literal(value.doubleValue() < min ? info.error = inLimits? null : Text.literal(value.doubleValue() < min ?
"§cMinimum " + (isNumber? "value" : "length") + (cast? " is " + (int)min : " is " + min) : "§cMinimum " + (isNumber? "value" : "length") + (cast? " is " + (int)min : " is " + min) :
"§cMaximum " + (isNumber? "value" : "length") + (cast? " is " + (int)max : " is " + max))); "§cMaximum " + (isNumber? "value" : "length") + (cast? " is " + (int)max : " is " + max)).formatted(Formatting.RED);
} }
info.tempValue = s; info.tempValue = s;
@@ -200,11 +202,19 @@ public abstract class MidnightConfig {
public final String modid; public final String modid;
public MidnightConfigListWidget list; public MidnightConfigListWidget list;
public boolean reload = false; public boolean reload = false;
public TabManager tabManager = new TabManager(a -> refresh(), a -> refresh());
public Tab prevTab;
// Real Time config update // // Real Time config update //
@Override @Override
public void tick() { public void tick() {
super.tick(); super.tick();
tabManager.tick();
if (prevTab != null && prevTab != tabManager.getCurrentTab()) {
prevTab = tabManager.getCurrentTab();
this.list.clear();
fillList();
}
for (EntryInfo info : entries) { for (EntryInfo info : entries) {
try {info.field.set(null, info.value);} catch (IllegalAccessException ignored) {} try {info.field.set(null, info.value);} catch (IllegalAccessException ignored) {}
} }
@@ -232,18 +242,50 @@ public abstract class MidnightConfig {
} }
} }
public Tooltip getTooltip(EntryInfo info) { public Tooltip getTooltip(EntryInfo info) {
return Tooltip.of(I18n.hasTranslation(translationPrefix+info.field.getName()+".tooltip") ? Text.translatable(translationPrefix+info.field.getName()+".tooltip") : Text.empty()); return Tooltip.of(info.error != null ? info.error : I18n.hasTranslation(translationPrefix+info.field.getName()+".tooltip") ? Text.translatable(translationPrefix+info.field.getName()+".tooltip") : Text.empty());
}
public void refresh() {
double scrollAmount = list.getScrollAmount();
list.clear();
fillList();
list.setScrollAmount(scrollAmount);
} }
@Override @Override
public void init() { public void init() {
super.init(); super.init();
if (!reload) loadValues(); loadValues();
Map<String, Tab> tabs = new HashMap<>();
for (EntryInfo e : entries) {
if (e.id.equals(modid)) {
String tabId = e.field.isAnnotationPresent(Entry.class) ? e.field.getAnnotation(Entry.class).category() : e.field.getAnnotation(Comment.class).category();
String name = translationPrefix + "category." + tabId;
if (!I18n.hasTranslation(name) && tabId.equals("default"))
name = translationPrefix + "title";
Tab tab = new GridScreenTab(Text.translatable(name));
if (!tabs.containsKey(name)) {
e.tab = tab;
tabs.put(name, tab);
} else e.tab = tabs.get(name);
}
}
TabNavigationWidget tabNavigation = TabNavigationWidget.builder(tabManager, this.width).tabs(tabs.values().toArray(new Tab[0])).build();
if (tabs.size() > 1) this.addDrawableChild(tabNavigation);
if (!reload) tabNavigation.selectTab(0, false);
tabNavigation.init();
prevTab = tabManager.getCurrentTab();
this.addDrawableChild(ButtonWidget.builder(ScreenTexts.CANCEL, button -> { this.addDrawableChild(ButtonWidget.builder(ScreenTexts.CANCEL, button -> {
loadValues(); loadValues();
Objects.requireNonNull(client).setScreen(parent); Objects.requireNonNull(client).setScreen(parent);
}).dimensions(this.width / 2 - 154, this.height - 28, 150, 20).build()); }).dimensions(this.width / 2 - 154, this.height - 28, 150, 20).build());
this.list = new MidnightConfigListWidget(this.client, this.width, this.height, 32, this.height - 32, 25);
if (this.client != null && this.client.world != null) this.list.setRenderBackground(false);
this.addSelectableChild(this.list);
this.fillList();
}
public void fillList() {
ButtonWidget done = this.addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, (button) -> { ButtonWidget done = this.addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, (button) -> {
for (EntryInfo info : entries) for (EntryInfo info : entries)
if (info.id.equals(modid)) { if (info.id.equals(modid)) {
@@ -254,52 +296,48 @@ public abstract class MidnightConfig {
write(modid); write(modid);
Objects.requireNonNull(client).setScreen(parent); Objects.requireNonNull(client).setScreen(parent);
}).dimensions(this.width / 2 + 4, this.height - 28, 150, 20).build()); }).dimensions(this.width / 2 + 4, this.height - 28, 150, 20).build());
this.list = new MidnightConfigListWidget(this.client, this.width, this.height, 32, this.height - 32, 25);
if (this.client != null && this.client.world != null) this.list.setRenderBackground(false);
this.addSelectableChild(this.list);
for (EntryInfo info : entries) { for (EntryInfo info : entries) {
if (info.id.equals(modid)) { if (info.id.equals(modid) && (info.tab == null || info.tab == tabManager.getCurrentTab())) {
Text name = Objects.requireNonNullElseGet(info.name, () -> Text.translatable(translationPrefix + info.field.getName())); Text name = Objects.requireNonNullElseGet(info.name, () -> Text.translatable(translationPrefix + info.field.getName()));
ButtonWidget resetButton = ButtonWidget.builder(Text.literal("Reset").formatted(Formatting.RED), (button -> { ButtonWidget resetButton = ButtonWidget.builder(Text.literal("Reset").formatted(Formatting.RED), (button -> {
info.value = info.defaultValue; info.value = info.defaultValue;
info.tempValue = info.defaultValue.toString(); info.tempValue = info.defaultValue.toString();
info.index = 0; info.index = 0;
double scrollAmount = list.getScrollAmount(); this.refresh();
this.reload = true;
Objects.requireNonNull(client).setScreen(this);
list.setScrollAmount(scrollAmount);
})).dimensions(width - 205, 0, 40, 20).build(); })).dimensions(width - 205, 0, 40, 20).build();
if (info.widget instanceof Map.Entry) { if (info.widget instanceof Map.Entry) {
Map.Entry<ButtonWidget.PressAction, Function<Object, Text>> widget = (Map.Entry<ButtonWidget.PressAction, Function<Object, Text>>) info.widget; Map.Entry<ButtonWidget.PressAction, Function<Object, Text>> widget = (Map.Entry<ButtonWidget.PressAction, Function<Object, Text>>) info.widget;
if (info.field.getType().isEnum()) widget.setValue(value -> Text.translatable(translationPrefix + "enum." + info.field.getType().getSimpleName() + "." + info.value.toString())); if (info.field.getType().isEnum())
this.list.addButton(List.of(ButtonWidget.builder(widget.getValue().apply(info.value), widget.getKey()).dimensions(width - 160, 0,150, 20).tooltip(getTooltip(info)).build(),resetButton), name, info); widget.setValue(value -> Text.translatable(translationPrefix + "enum." + info.field.getType().getSimpleName() + "." + info.value.toString()));
this.list.addButton(List.of(ButtonWidget.builder(widget.getValue().apply(info.value), widget.getKey()).dimensions(width - 160, 0, 150, 20).tooltip(getTooltip(info)).build(), resetButton), name, info);
} else if (info.field.getType() == List.class) { } else if (info.field.getType() == List.class) {
if (!reload) info.index = 0; if (!reload) info.index = 0;
TextFieldWidget widget = new TextFieldWidget(textRenderer, width - 160, 0, 150, 20, Text.empty()); TextFieldWidget widget = new TextFieldWidget(textRenderer, width - 160, 0, 150, 20, Text.empty());
widget.setMaxLength(info.width); widget.setMaxLength(info.width);
if (info.index < ((List<String>)info.value).size()) widget.setText((String.valueOf(((List<String>)info.value).get(info.index)))); if (info.index < ((List<String>) info.value).size())
widget.setText((String.valueOf(((List<String>) info.value).get(info.index))));
Predicate<String> processor = ((BiFunction<TextFieldWidget, ButtonWidget, Predicate<String>>) info.widget).apply(widget, done); Predicate<String> processor = ((BiFunction<TextFieldWidget, ButtonWidget, Predicate<String>>) info.widget).apply(widget, done);
widget.setTextPredicate(processor); widget.setTextPredicate(processor);
resetButton.setWidth(20); resetButton.setWidth(20);
resetButton.setMessage(Text.literal("R").formatted(Formatting.RED)); resetButton.setMessage(Text.literal("R").formatted(Formatting.RED));
ButtonWidget cycleButton = ButtonWidget.builder(Text.literal(String.valueOf(info.index)).formatted(Formatting.GOLD), (button -> { ButtonWidget cycleButton = ButtonWidget.builder(Text.literal(String.valueOf(info.index)).formatted(Formatting.GOLD), (button -> {
((List<String>)info.value).remove(""); if (((List<?>) info.value).contains("")) ((List<String>) info.value).remove("");
double scrollAmount = list.getScrollAmount();
this.reload = true;
info.index = info.index + 1; info.index = info.index + 1;
if (info.index > ((List<String>)info.value).size()) info.index = 0; if (info.index > ((List<String>) info.value).size()) info.index = 0;
Objects.requireNonNull(client).setScreen(this); this.reload = true;
list.setScrollAmount(scrollAmount); refresh();
this.reload = false;
})).dimensions(width - 185, 0, 20, 20).build(); })).dimensions(width - 185, 0, 20, 20).build();
widget.setTooltip(getTooltip(info)); widget.setTooltip(getTooltip(info));
this.list.addButton(List.of(widget, resetButton, cycleButton), name, info); this.list.addButton(List.of(widget, resetButton, cycleButton), name, info);
} else if (info.widget != null) { } else if (info.widget != null) {
ClickableWidget widget; ClickableWidget widget;
Entry e = info.field.getAnnotation(Entry.class); Entry e = info.field.getAnnotation(Entry.class);
if (e.isSlider()) widget = new MidnightSliderWidget(width - 160, 0, 150, 20, Text.of(info.tempValue), (Double.parseDouble(info.tempValue)-e.min()) / (e.max() - e.min()), info); if (e.isSlider())
else widget = new TextFieldWidget(textRenderer, width - 160, 0, 150, 20, null, Text.of(info.tempValue)); widget = new MidnightSliderWidget(width - 160, 0, 150, 20, Text.of(info.tempValue), (Double.parseDouble(info.tempValue) - e.min()) / (e.max() - e.min()), info);
else
widget = new TextFieldWidget(textRenderer, width - 160, 0, 150, 20, null, Text.of(info.tempValue));
if (widget instanceof TextFieldWidget textField) { if (widget instanceof TextFieldWidget textField) {
textField.setMaxLength(info.width); textField.setMaxLength(info.width);
textField.setText(info.tempValue); textField.setText(info.tempValue);
@@ -310,26 +348,29 @@ public abstract class MidnightConfig {
if (e.isColor()) { if (e.isColor()) {
resetButton.setWidth(20); resetButton.setWidth(20);
resetButton.setMessage(Text.literal("R").formatted(Formatting.RED)); resetButton.setMessage(Text.literal("R").formatted(Formatting.RED));
ButtonWidget colorButton = ButtonWidget.builder(Text.literal(""), (button -> {})).dimensions(width - 185, 0, 20, 20).build(); ButtonWidget colorButton = ButtonWidget.builder(Text.literal(""), (button -> {
try {colorButton.setMessage(Text.literal("").setStyle(Style.EMPTY.withColor(Color.decode(info.tempValue).getRGB())));} catch (Exception ignored) {} })).dimensions(width - 185, 0, 20, 20).build();
try {
colorButton.setMessage(Text.literal("").setStyle(Style.EMPTY.withColor(Color.decode(info.tempValue).getRGB())));
} catch (Exception ignored) {
}
info.colorButton = colorButton; info.colorButton = colorButton;
colorButton.active = false; colorButton.active = false;
this.list.addButton(List.of(widget, resetButton, colorButton), name, info); this.list.addButton(List.of(widget, resetButton, colorButton), name, info);
} } else this.list.addButton(List.of(widget, resetButton), name, info);
else this.list.addButton(List.of(widget, resetButton), name, info);
} else { } else {
this.list.addButton(List.of(),name, info); this.list.addButton(List.of(), name, info);
} }
} }
updateResetButtons(); updateResetButtons();
} }
} }
@Override @Override
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
this.renderBackground(matrices); this.renderBackground(matrices);
this.list.render(matrices, mouseX, mouseY, delta); this.list.render(matrices, mouseX, mouseY, delta);
drawCenteredText(matrices, textRenderer, title, width / 2, 15, 0xFFFFFF);
drawCenteredTextWithShadow(matrices, textRenderer, title, width / 2, 15, 0xFFFFFF);
super.render(matrices,mouseX,mouseY,delta); super.render(matrices,mouseX,mouseY,delta);
} }
} }
@@ -348,16 +389,11 @@ public abstract class MidnightConfig {
public void addButton(List<ClickableWidget> buttons, Text text, EntryInfo info) { public void addButton(List<ClickableWidget> buttons, Text text, EntryInfo info) {
this.addEntry(new ButtonEntry(buttons, text, info)); this.addEntry(new ButtonEntry(buttons, text, info));
} }
public void clear() {
this.clearEntries();
}
@Override @Override
public int getRowWidth() { return 10000; } public int getRowWidth() { return 10000; }
public Optional<ClickableWidget> getHoveredButton(double mouseX, double mouseY) {
for (ButtonEntry buttonEntry : this.children()) {
if (!buttonEntry.buttons.isEmpty() && buttonEntry.buttons.get(0).isMouseOver(mouseX, mouseY)) {
return Optional.of(buttonEntry.buttons.get(0));
}
}
return Optional.empty();
}
} }
public static class ButtonEntry extends ElementListWidget.Entry<ButtonEntry> { public static class ButtonEntry extends ElementListWidget.Entry<ButtonEntry> {
private static final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; private static final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
@@ -413,12 +449,14 @@ public abstract class MidnightConfig {
boolean isColor() default false; boolean isColor() default false;
boolean isSlider() default false; boolean isSlider() default false;
int precision() default 100; int precision() default 100;
String category() default "default";
} }
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Client {} @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Client {}
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Server {} @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Server {}
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Hidden {} @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Hidden {}
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Comment { @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Comment {
boolean centered() default false; boolean centered() default false;
String category() default "default";
} }
public static class HiddenAnnotationExclusionStrategy implements ExclusionStrategy { public static class HiddenAnnotationExclusionStrategy implements ExclusionStrategy {

View File

@@ -27,15 +27,19 @@ public class TexturedOverlayButtonWidget extends TexturedButtonWidget {
@Override @Override
public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float delta) { public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float delta) {
int i = 66;
if (!this.isNarratable()) {
i += 40;
} else if (this.isHovered()) {
i += 20;
}
RenderSystem.setShader(GameRenderer::getPositionTexProgram); RenderSystem.setShader(GameRenderer::getPositionTexProgram);
RenderSystem.setShaderTexture(0, WIDGETS_TEXTURE); RenderSystem.setShaderTexture(0, WIDGETS_TEXTURE);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha);
int i = this.getYImage(this.isHovered());
RenderSystem.enableBlend(); RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc(); RenderSystem.defaultBlendFunc();
RenderSystem.enableDepthTest(); RenderSystem.enableDepthTest();
this.drawTexture(matrices, this.getX(), this.getY(), 0, 46 + i * 20, this.width / 2, this.height); drawNineSlicedTexture(matrices, this.getX(), this.getY(), this.width, this.height, 4, 200, 20, 0, i);
this.drawTexture(matrices, this.getX() + this.width / 2, this.getY(), 200 - this.width / 2, 46 + i * 20, this.width / 2, this.height);
super.renderButton(matrices, mouseX, mouseY, delta); super.renderButton(matrices, mouseX, mouseY, delta);
} }

View File

@@ -1,14 +1,15 @@
org.gradle.jvmargs=-Xmx4096M org.gradle.jvmargs=-Xmx4096M
minecraft_version=1.19.3 minecraft_version=1.19.4-pre4
enabled_platforms=quilt,fabric,forge yarn_mappings=1.19.4-pre4+build.1
enabled_platforms=fabric
archives_base_name=midnightlib archives_base_name=midnightlib
mod_version=1.1.0 mod_version=1.2.0
maven_group=eu.midnightdust maven_group=eu.midnightdust
fabric_loader_version=0.14.11 fabric_loader_version=0.14.17
fabric_api_version=0.68.1+1.19.3 fabric_api_version=0.75.3+1.19.4
forge_version=1.19.3-44.0.18 forge_version=1.19.3-44.0.18

View File

@@ -10,7 +10,7 @@ pluginManagement {
include("common") include("common")
include("fabric-like") include("fabric-like")
include("fabric") include("fabric")
include("quilt") //include("quilt")
include("forge") //include("forge")
rootProject.name = "midnightlib" rootProject.name = "midnightlib"