diff --git a/src/main/java/dsns/betterhud/ModMenu.java b/src/main/java/dsns/betterhud/ModMenu.java index 70400af..aad4ac4 100644 --- a/src/main/java/dsns/betterhud/ModMenu.java +++ b/src/main/java/dsns/betterhud/ModMenu.java @@ -3,17 +3,31 @@ import com.terraformersmc.modmenu.api.ConfigScreenFactory; import com.terraformersmc.modmenu.api.ModMenuApi; import dsns.betterhud.util.BaseMod; +import dsns.betterhud.util.ModSettings; import dsns.betterhud.util.Setting; -import java.util.Arrays; +import java.util.LinkedHashMap; import java.util.Map; import me.shedaniel.clothconfig2.api.ConfigBuilder; import me.shedaniel.clothconfig2.api.ConfigCategory; import me.shedaniel.clothconfig2.api.ConfigEntryBuilder; +import me.shedaniel.clothconfig2.api.Requirement; +import me.shedaniel.clothconfig2.gui.entries.BooleanListEntry; +import me.shedaniel.clothconfig2.impl.builders.SubCategoryBuilder; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.network.chat.Component; public class ModMenu implements ModMenuApi { + private static final Map ORIENTATION_LABELS; + + static { + ORIENTATION_LABELS = new LinkedHashMap<>(); + ORIENTATION_LABELS.put("top-left", "Top Left"); + ORIENTATION_LABELS.put("top-right", "Top Right"); + ORIENTATION_LABELS.put("bottom-left", "Bottom Left"); + ORIENTATION_LABELS.put("bottom-right", "Bottom Right"); + } + @Override public ConfigScreenFactory getModConfigScreenFactory() { if (!FabricLoader.getInstance().isModLoaded("cloth-config2")) { @@ -24,7 +38,6 @@ public ConfigScreenFactory getModConfigScreenFactory() { .setParentScreen(parent) .setTitle(Component.literal("BetterHUD Settings")); - // same as builder.setSavingRunnable(() -> Config.serialize()); builder.setSavingRunnable(Config::serialize); ConfigEntryBuilder entryBuilder = builder.entryBuilder(); @@ -33,97 +46,210 @@ public ConfigScreenFactory getModConfigScreenFactory() { ConfigCategory category = builder.getOrCreateCategory( Component.literal(mod.getModID()) ); - - for (Map.Entry entry : mod - .getModSettings() - .getSettings() - .entrySet()) { - String key = entry.getKey(); - Setting setting = entry.getValue(); - - if (setting.getType().equals("boolean")) { - category.addEntry( - entryBuilder - .startBooleanToggle( - Component.literal(key), - setting.getBooleanValue() - ) - .setDefaultValue( - Boolean.valueOf(setting.getDefaultValue()) - ) - .setSaveConsumer(value -> - setting.setValue(String.valueOf(value)) - ) - .build() - ); - } else if (setting.getType().equals("string")) { - category.addEntry( - entryBuilder - .startStringDropdownMenu( - Component.literal(key), - setting.getStringValue() - ) - .setSelections( - Arrays.asList(setting.getPossibleValues()) - ) - .setDefaultValue(setting.getDefaultValue()) - .setSaveConsumer(value -> - setting.setValue(value) - ) - .build() - ); - } else if (setting.getType().equals("integer")) { - category.addEntry( - entryBuilder - .startIntField( - Component.literal(key), - setting.getIntValue() - ) - .setDefaultValue( - Integer.parseInt(setting.getDefaultValue()) - ) - .setSaveConsumer(value -> - setting.setValue(String.valueOf(value)) - ) - .build() - ); - } else if (setting.getType().equals("double")) { - category.addEntry( - entryBuilder - .startDoubleField( - Component.literal(key), - setting.getDoubleValue() - ) - .setDefaultValue( - Double.parseDouble( - setting.getDefaultValue() - ) - ) - .setSaveConsumer(value -> - setting.setValue(String.valueOf(value)) - ) - .build() - ); - } else if (setting.getType().equals("color")) { - category.addEntry( - entryBuilder - .startAlphaColorField( - Component.literal(key), - setting.getColorValue() - ) - .setDefaultValue( - Integer.parseInt(setting.getDefaultValue()) - ) - .setSaveConsumer(value -> - setting.setValue(String.valueOf(value)) - ) - .build() - ); - } - } + buildModCategory(category, entryBuilder, mod); } return builder.build(); }; } + + private void buildModCategory( + ConfigCategory category, + ConfigEntryBuilder entryBuilder, + BaseMod mod + ) { + ModSettings settings = mod.getModSettings(); + String name = mod.getModID(); + + Setting enabled = settings.getSetting("Enabled"); + BooleanListEntry enabledEntry = entryBuilder + .startBooleanToggle( + Component.literal("Enable " + name), + enabled.getBooleanValue() + ) + .setDefaultValue(Boolean.parseBoolean(enabled.getDefaultValue())) + .setTooltip( + Component.literal( + "Show the " + name + " module on the HUD." + ) + ) + .setYesNoTextSupplier(value -> + Component.literal(value ? "Enabled" : "Disabled") + ) + .setSaveConsumer(value -> + enabled.setValue(String.valueOf(value)) + ) + .build(); + category.addEntry(enabledEntry); + + Setting customPosition = settings.getSetting("Custom Position"); + BooleanListEntry customPositionEntry = entryBuilder + .startBooleanToggle( + Component.literal("Use Custom Position"), + customPosition.getBooleanValue() + ) + .setDefaultValue( + Boolean.parseBoolean(customPosition.getDefaultValue()) + ) + .setTooltip( + Component.literal( + "Override the screen anchor and place this module at an exact location." + ) + ) + .setSaveConsumer(value -> + customPosition.setValue(String.valueOf(value)) + ) + .build(); + + SubCategoryBuilder positionGroup = entryBuilder + .startSubCategory(Component.literal("Position")) + .setExpanded(true) + .setTooltip( + Component.literal( + "Where the module is drawn on the screen." + ) + ); + + Setting orientation = settings.getSetting("Orientation"); + positionGroup.add( + entryBuilder + .startSelector( + Component.literal("Anchor"), + orientation.getPossibleValues(), + orientation.getStringValue() + ) + .setDefaultValue(orientation.getDefaultValue()) + .setNameProvider(value -> + Component.literal(prettyOrientation(value)) + ) + .setTooltip( + Component.literal( + "Which corner of the screen the module is anchored to." + ) + ) + .setRequirement(Requirement.isFalse(customPositionEntry)) + .setSaveConsumer(value -> orientation.setValue(value)) + .build() + ); + + positionGroup.add(customPositionEntry); + + Setting customX = settings.getSetting("Custom X"); + positionGroup.add( + entryBuilder + .startIntSlider( + Component.literal("Custom X"), + customX.getIntValue(), + parseBound(customX, 0, 0), + parseBound(customX, 1, 100) + ) + .setDefaultValue(Integer.parseInt(customX.getDefaultValue())) + .setTextGetter(value -> Component.literal(value + "%")) + .setTooltip( + Component.literal( + "Horizontal position as a percentage of screen width (0% = left edge, 100% = right edge)." + ) + ) + .setRequirement(Requirement.isTrue(customPositionEntry)) + .setSaveConsumer(value -> + customX.setValue(String.valueOf(value)) + ) + .build() + ); + + Setting customY = settings.getSetting("Custom Y"); + positionGroup.add( + entryBuilder + .startIntSlider( + Component.literal("Custom Y"), + customY.getIntValue(), + parseBound(customY, 0, 0), + parseBound(customY, 1, 100) + ) + .setDefaultValue(Integer.parseInt(customY.getDefaultValue())) + .setTextGetter(value -> Component.literal(value + "%")) + .setTooltip( + Component.literal( + "Vertical position as a percentage of screen height (0% = top edge, 100% = bottom edge)." + ) + ) + .setRequirement(Requirement.isTrue(customPositionEntry)) + .setSaveConsumer(value -> + customY.setValue(String.valueOf(value)) + ) + .build() + ); + + category.addEntry(positionGroup.build()); + + SubCategoryBuilder appearanceGroup = entryBuilder + .startSubCategory(Component.literal("Appearance")) + .setExpanded(false) + .setTooltip( + Component.literal( + "Colors used to draw the module." + ) + ); + + Setting textColor = settings.getSetting("Text Color"); + appearanceGroup.add( + entryBuilder + .startAlphaColorField( + Component.literal("Text Color"), + textColor.getColorValue() + ) + .setDefaultValue( + Integer.parseInt(textColor.getDefaultValue()) + ) + .setTooltip( + Component.literal( + "Color of the displayed text (with alpha)." + ) + ) + .setSaveConsumer(value -> + textColor.setValue(String.valueOf(value)) + ) + .build() + ); + + Setting backgroundColor = settings.getSetting("Background Color"); + appearanceGroup.add( + entryBuilder + .startAlphaColorField( + Component.literal("Background Color"), + backgroundColor.getColorValue() + ) + .setDefaultValue( + Integer.parseInt(backgroundColor.getDefaultValue()) + ) + .setTooltip( + Component.literal( + "Color of the rectangle drawn behind the text. Set alpha to 0 for no background." + ) + ) + .setSaveConsumer(value -> + backgroundColor.setValue(String.valueOf(value)) + ) + .build() + ); + + category.addEntry(appearanceGroup.build()); + } + + private static String prettyOrientation(String raw) { + String pretty = ORIENTATION_LABELS.get(raw); + return pretty != null ? pretty : raw; + } + + private static int parseBound(Setting setting, int index, int fallback) { + String[] possible = setting.getPossibleValues(); + if (possible == null || possible.length <= index) { + return fallback; + } + try { + return Integer.parseInt(possible[index]); + } catch (NumberFormatException e) { + return fallback; + } + } }