Compare commits

...

11 Commits

Author SHA1 Message Date
Motschen
2db6b33d30 Bump version 2023-03-09 21:11:02 +01:00
Motschen
c881db8be4 Fix <Ctrl>+<Number> keybinds not working for tabs 2023-03-09 21:10:01 +01:00
Motschen
79eb8936ff Update the example config 2023-03-09 20:37:44 +01:00
Motschen
920fb797e1 Minor improvements 2023-03-09 19:50:28 +01:00
Motschen
cacd3516c1 Port to 1.19.4, Add tab support & Large code cleanup 2023-03-08 21:27:41 +01:00
Martin Prokoph
b5052ff324 Merge pull request #24 from Amirhan-Taipovjan-Greatest-I/patch-1
Tatar Translation for MidnightLib
2023-03-08 16:43:38 +01:00
Martin Prokoph
8acc9baa5a Merge pull request #22 from Calvineries/patch-1
Create fr_fr.json
2023-03-08 16:43:27 +01:00
Amirhan-Taipovjan-Greatest-I
ecda37dd13 Tatar Translation for MidnightLib 2023-02-26 09:44:44 +03:00
Motschen
1009dd9e84 Fix #23 2023-02-15 12:12:18 +01:00
Calvineries
9bfa593d4d Create fr_fr.json 2023-01-22 13:11:42 +01:00
Motschen
1ef835a015 Re-enable Quilt and Forge support 2022-12-14 18:22:32 +01:00
15 changed files with 168 additions and 79 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;
@@ -12,21 +13,22 @@ import java.util.List;
public class MidnightConfigExample extends MidnightConfig { 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(category = "text") 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(category = "text", 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 @Comment(category = "text") public static Comment spacer1; // Comments containing the word "spacer" will just appear as a blank line
@Entry public static double world = 1.4D; // Example for a double option @Entry(category = "text") public static boolean showInfo = true; // Example for a boolean option
@Entry public static boolean showInfo = true; // Example for a boolean option @Entry(category = "text") public static String name = "Hello World!"; // Example for a string option, which is in a category!
@Entry public static String name = "Hello World!"; // Example for a string option @Entry(category = "text") public static TestEnum testEnum = TestEnum.FABRIC; // Example for an enum option
@Entry 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 = "text", 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 +51,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-rc1+build.2: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,21 @@ 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 -> {}, a -> {});
public Tab prevTab;
public TabNavigationWidget tabNavigation;
public ButtonWidget done;
// Real Time config update // // Real Time config update //
@Override @Override
public void tick() { public void tick() {
super.tick(); super.tick();
if (prevTab != null && prevTab != tabManager.getCurrentTab()) {
prevTab = tabManager.getCurrentTab();
this.list.clear();
fillList();
list.setScrollAmount(0);
}
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) {}
} }
@@ -231,20 +243,50 @@ public abstract class MidnightConfig {
} catch (IllegalAccessException ignored) {} } catch (IllegalAccessException ignored) {}
} }
} }
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
if (this.tabNavigation.trySwitchTabsWithKey(keyCode)) return true;
return super.keyPressed(keyCode, scanCode, modifiers);
}
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);
}
}
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());
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)) {
try { try {
@@ -258,48 +300,52 @@ public abstract class MidnightConfig {
this.list = new MidnightConfigListWidget(this.client, this.width, this.height, 32, this.height - 32, 25); 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); if (this.client != null && this.client.world != null) this.list.setRenderBackground(false);
this.addSelectableChild(this.list); this.addSelectableChild(this.list);
fillList();
}
public void fillList() {
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 +356,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 +397,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 +457,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 += hoveredVOffset * 2;
} else if (this.isSelected()) {
i += hoveredVOffset;
}
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

@@ -0,0 +1,17 @@
{
"midnightlib.overview.title":"Vue d'ensemble de MidnightConfig",
"midnightlib.midnightconfig.title":"Configuration de MidnightLib",
"midnightlib.midnightconfig.midnightlib_description":"§nMidnightLib",
"midnightlib.midnightconfig.config_screen_list":"Activer la liste de l'écran de configuration",
"midnightlib.midnightconfig.enum.ConfigButton.TRUE":"§aOui",
"midnightlib.midnightconfig.enum.ConfigButton.FALSE":"§cNon",
"midnightlib.midnightconfig.enum.ConfigButton.MODMENU":"§bModMenu",
"midnightlib.midnightconfig.background_texture":"Texture d'arrière-plan de l'écran de configuration",
"midnightlib.midnightconfig.midnighthats_description":"§nMidnightHats",
"midnightlib.midnightconfig.special_hats":"Activer les chapeaux de fan",
"midnightlib.modrinth":"Modrinth",
"midnightlib.curseforge":"CurseForge",
"midnightlib.wiki":"Wiki",
"modmenu.descriptionTranslation.midnightlib": "Bibliothèque commune pour les mods de la Team MidnightDust.\nFournit une API de configuration, une intégration automatique avec d'autres mods, des utilitaires courants et des cosmétiques.",
"modmenu.summaryTranslation.midnightlib": "Bibliothèque commune pour les mods de la Team MidnightDust."
}

View File

@@ -0,0 +1,17 @@
{
"midnightlib.overview.title":"MidnightConfig күзәтү",
"midnightlib.midnightconfig.title":"MidnightLib көйләүләре",
"midnightlib.midnightconfig.midnightlib_description":"§nMidnightLib",
"midnightlib.midnightconfig.config_screen_list":"Көйләүләр экранының исемлеген кушу",
"midnightlib.midnightconfig.enum.ConfigButton.TRUE":"§aӘйе",
"midnightlib.midnightconfig.enum.ConfigButton.FALSE":"§cЮк",
"midnightlib.midnightconfig.enum.ConfigButton.MODMENU":"§bModMenu",
"midnightlib.midnightconfig.background_texture":"Көйләүләр экранының фонының текстурасы",
"midnightlib.midnightconfig.midnighthats_description":"§nMidnightHats",
"midnightlib.midnightconfig.special_hats":"Ярдәмченең эшләпәсен кушу",
"midnightlib.modrinth":"Modrinth",
"midnightlib.curseforge":"CurseForge",
"midnightlib.wiki":"Вики",
"modmenu.descriptionTranslation.midnightlib": "MidnightDust төркеменең модлары өчен гомуми китапханә.\nКөйләүләр API-ын, башка модлар белән автоматик интеграцияне, гомуми хезмәти программаларны һәм бизәнүләрне тәэмин ителә.",
"modmenu.summaryTranslation.midnightlib": "MidnightDust төркеменең модлары өчен гомуми китапханә."
}

View File

@@ -11,8 +11,6 @@ loom {
dependencies { dependencies {
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}" modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}"
// Remove the next line if you don't want to depend on the API
modApi "dev.architectury:architectury-fabric:${rootProject.architectury_version}"
modImplementation ("com.terraformersmc:modmenu:${rootProject.mod_menu_version}") modImplementation ("com.terraformersmc:modmenu:${rootProject.mod_menu_version}")
compileClasspath(project(path: ":common", configuration: "namedElements")) { transitive false } compileClasspath(project(path: ":common", configuration: "namedElements")) { transitive false }

View File

@@ -30,6 +30,11 @@
"eu.midnightdust.lib.config.AutoModMenu" "eu.midnightdust.lib.config.AutoModMenu"
] ]
}, },
"depends": {
"fabric-models-v0": "*",
"fabric-resource-loader-v0": "*",
"minecraft": ">=1.19.4-rc.1"
},
"mixins": [ "mixins": [
"midnightlib.mixins.json" "midnightlib.mixins.json"

View File

@@ -25,9 +25,7 @@ public class MidnightLibClientEvents {
@SubscribeEvent @SubscribeEvent
public void onPostInit(FMLLoadCompleteEvent event) { public void onPostInit(FMLLoadCompleteEvent event) {
ModList.get().applyForEachModContainer(modContainer -> { ModList.get().applyForEachModContainer(modContainer -> {
System.out.println(modContainer.getModId() + " yes");
if (MidnightConfig.configClass.containsKey(modContainer.getModId())) { if (MidnightConfig.configClass.containsKey(modContainer.getModId())) {
modContainer.registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> modContainer.registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () ->
new ConfigScreenHandler.ConfigScreenFactory((client, parent) -> MidnightConfig.getScreen(parent, modContainer.getModId()))); new ConfigScreenHandler.ConfigScreenFactory((client, parent) -> MidnightConfig.getScreen(parent, modContainer.getModId())));
} }

View File

@@ -2,7 +2,9 @@ package eu.midnightdust.forge;
import eu.midnightdust.core.MidnightLibClient; import eu.midnightdust.core.MidnightLibClient;
import eu.midnightdust.core.MidnightLibServer; import eu.midnightdust.core.MidnightLibServer;
import eu.midnightdust.lib.config.MidnightConfig;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.ConfigScreenHandler;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.IExtensionPoint; import net.minecraftforge.fml.IExtensionPoint;
@@ -16,8 +18,8 @@ public class MidnightLibForge {
ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(() -> NetworkConstants.IGNORESERVERONLY, (remote, server) -> true)); ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(() -> NetworkConstants.IGNORESERVERONLY, (remote, server) -> true));
DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> MidnightLibClient::onInitializeClient); DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> MidnightLibClient::onInitializeClient);
DistExecutor.safeRunWhenOn(Dist.DEDICATED_SERVER, () -> MidnightLibServer::onInitializeServer); DistExecutor.safeRunWhenOn(Dist.DEDICATED_SERVER, () -> MidnightLibServer::onInitializeServer);
//ModLoadingContext.get().registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> ModLoadingContext.get().registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () ->
// new ConfigScreenHandler.ConfigScreenFactory((client, parent) -> MidnightConfig.getScreen(parent, "midnightlib"))); new ConfigScreenHandler.ConfigScreenFactory((client, parent) -> MidnightConfig.getScreen(parent, "midnightlib")));
MinecraftForge.EVENT_BUS.register(new MidnightLibClientEvents()); MinecraftForge.EVENT_BUS.register(new MidnightLibClientEvents());
MinecraftForge.EVENT_BUS.register(new MidnightLibServerEvents()); MinecraftForge.EVENT_BUS.register(new MidnightLibServerEvents());
} }

View File

@@ -23,6 +23,6 @@ public class PlatformFunctionsImpl {
return ModList.get().isLoaded(modid); return ModList.get().isLoaded(modid);
} }
public static void registerCommand(LiteralArgumentBuilder<ServerCommandSource> command) { public static void registerCommand(LiteralArgumentBuilder<ServerCommandSource> command) {
// Ignored here, see MidnightLibEvents#registerCommands // Ignored here, see MidnightLibServerEvents#registerCommands
} }
} }

View File

@@ -1,19 +1,18 @@
org.gradle.jvmargs=-Xmx4096M org.gradle.jvmargs=-Xmx4096M
minecraft_version=1.19.3-rc1 minecraft_version=1.19.4-pre4
yarn_mappings=1.19.4-pre4+build.1
enabled_platforms=fabric enabled_platforms=fabric
archives_base_name=midnightlib archives_base_name=midnightlib
mod_version=1.1.0 mod_version=1.2.1
maven_group=eu.midnightdust maven_group=eu.midnightdust
architectury_version=6.2.43 fabric_loader_version=0.14.17
fabric_api_version=0.75.3+1.19.4
fabric_loader_version=0.14.11 forge_version=1.19.3-44.0.18
fabric_api_version=0.68.1+1.19.3
forge_version=1.19.2-43.0.8 quilt_loader_version=0.18.1-beta.75
quilt_fabric_api_version=5.0.0-beta.2+0.68.1-1.19.3
quilt_loader_version=0.18.1-beta.9 mod_menu_version = 5.0.2
quilt_fabric_api_version=4.0.0-beta.7+0.59.0-1.19.2
mod_menu_version = 5.0.0-alpha.4

View File

@@ -5,7 +5,7 @@ import eu.midnightdust.lib.util.PlatformFunctions;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import org.quiltmc.loader.api.QuiltLoader; import org.quiltmc.loader.api.QuiltLoader;
import org.quiltmc.loader.impl.QuiltLoaderImpl; import org.quiltmc.loader.api.minecraft.MinecraftQuiltLoader;
import org.quiltmc.qsl.command.api.CommandRegistrationCallback; import org.quiltmc.qsl.command.api.CommandRegistrationCallback;
import java.nio.file.Path; import java.nio.file.Path;
@@ -18,7 +18,7 @@ public class PlatformFunctionsImpl {
return QuiltLoader.getConfigDir(); return QuiltLoader.getConfigDir();
} }
public static boolean isClientEnv() { public static boolean isClientEnv() {
return QuiltLoaderImpl.INSTANCE.getEnvironmentType() == EnvType.CLIENT; return MinecraftQuiltLoader.getEnvironmentType() == EnvType.CLIENT;
} }
public static boolean isModLoaded(String modid) { public static boolean isModLoaded(String modid) {
return QuiltLoader.isModLoaded(modid); return QuiltLoader.isModLoaded(modid);