From e455995c02bce8e5af851f0012f7471df14ee38e Mon Sep 17 00:00:00 2001 From: Prospector Date: Wed, 10 Feb 2021 18:54:34 -0800 Subject: [PATCH] Re-port the refactor from 1.16 (except I actually included the files this time) Took 2 minutes --- .github/workflows/check_build.yml | 42 ++ .github/workflows/release.yml | 62 +++ logs/latest.log | 0 .../com/terraformersmc/modmenu/ModMenu.java | 126 +++++ .../modmenu/ModMenuModMenuCompat.java | 23 + .../modmenu/api/ConfigScreenFactory.java | 8 + .../modmenu/api/ModMenuApi.java | 61 +++ .../modmenu/config/ModMenuConfig.java | 117 +++++ .../modmenu/config/ModMenuConfigManager.java | 126 +++++ .../config/option/BooleanConfigOption.java | 59 +++ .../config/option/ConfigOptionStorage.java | 60 +++ .../config/option/EnumConfigOption.java | 61 +++ .../config/option/OptionConvertable.java | 7 + .../config/option/StringSetConfigOption.java | 34 ++ .../modmenu/event/ModMenuEventHandler.java | 115 ++++ .../modmenu/gui/ModMenuOptionsScreen.java | 53 ++ .../modmenu/gui/ModsScreen.java | 494 ++++++++++++++++++ .../gui/widget/DescriptionListWidget.java | 318 +++++++++++ .../modmenu/gui/widget/ModListWidget.java | 316 +++++++++++ .../gui/widget/ModMenuButtonWidget.java | 13 + .../widget/ModMenuTexturedButtonWidget.java | 72 +++ .../gui/widget/entries/ChildEntry.java | 31 ++ .../gui/widget/entries/IndependentEntry.java | 11 + .../gui/widget/entries/ModListEntry.java | 108 ++++ .../gui/widget/entries/ParentEntry.java | 116 ++++ .../mixin/MixinEntryListWidgetEntries.java | 21 + .../modmenu/mixin/MixinTitleScreen.java | 38 ++ .../modmenu/util/DrawingUtil.java | 58 ++ .../modmenu/util/ModMenuApiMarker.java | 4 + .../modmenu/util/OptionalUtil.java | 9 + .../modmenu/util/TranslationUtil.java | 58 ++ .../terraformersmc/modmenu/util/mod/Mod.java | 99 ++++ .../modmenu/util/mod/ModBadgeRenderer.java | 61 +++ .../modmenu/util/mod/ModIconHandler.java | 62 +++ .../modmenu/util/mod/ModSearch.java | 58 ++ .../util/mod/fabric/CustomValueUtil.java | 77 +++ .../util/mod/fabric/FabricDummyParentMod.java | 129 +++++ .../modmenu/util/mod/fabric/FabricMod.java | 342 ++++++++++++ .../resources/assets/modmenu/java_icon.png | Bin 0 -> 1453 bytes .../resources/assets/modmenu/lang/ca_es.json | 91 ++++ .../resources/assets/modmenu/lang/en_pt.json | 38 ++ .../resources/assets/modmenu/lang/en_ud.json | 40 ++ .../resources/assets/modmenu/lang/en_ws.json | 3 + .../resources/assets/modmenu/lang/fa_ir.json | 39 ++ .../resources/assets/modmenu/lang/lol_us.json | 3 + .../resources/assets/modmenu/lang/szl.json | 3 + .../assets/modmenu/minecraft_icon.png | Bin 0 -> 1749 bytes .../modmenu/textures/gui/mods_button.png | Bin 0 -> 951 bytes .../modmenu/textures/gui/mods_button_alt.png | Bin 0 -> 4342 bytes .../modmenu/textures/gui/mods_button_alt3.png | Bin 0 -> 1161 bytes .../resources/assets/modmenu/unknown_icon.png | Bin 0 -> 137 bytes .../assets/modmenu/unknown_parent.png | Bin 0 -> 122 bytes .../modmenu/textures/gui/configure_button.png | Bin 0 -> 4658 bytes .../modmenu/textures/gui/filters_button.png | Bin 0 -> 4575 bytes .../modmenu/textures/gui/mods_button.png | Bin 0 -> 2736 bytes .../modmenu/textures/gui/parent_mod.png | Bin 0 -> 2297 bytes 56 files changed, 3666 insertions(+) create mode 100644 .github/workflows/check_build.yml create mode 100644 .github/workflows/release.yml create mode 100644 logs/latest.log create mode 100644 src/main/java/com/terraformersmc/modmenu/ModMenu.java create mode 100644 src/main/java/com/terraformersmc/modmenu/ModMenuModMenuCompat.java create mode 100644 src/main/java/com/terraformersmc/modmenu/api/ConfigScreenFactory.java create mode 100644 src/main/java/com/terraformersmc/modmenu/api/ModMenuApi.java create mode 100644 src/main/java/com/terraformersmc/modmenu/config/ModMenuConfig.java create mode 100644 src/main/java/com/terraformersmc/modmenu/config/ModMenuConfigManager.java create mode 100644 src/main/java/com/terraformersmc/modmenu/config/option/BooleanConfigOption.java create mode 100644 src/main/java/com/terraformersmc/modmenu/config/option/ConfigOptionStorage.java create mode 100644 src/main/java/com/terraformersmc/modmenu/config/option/EnumConfigOption.java create mode 100644 src/main/java/com/terraformersmc/modmenu/config/option/OptionConvertable.java create mode 100644 src/main/java/com/terraformersmc/modmenu/config/option/StringSetConfigOption.java create mode 100644 src/main/java/com/terraformersmc/modmenu/event/ModMenuEventHandler.java create mode 100644 src/main/java/com/terraformersmc/modmenu/gui/ModMenuOptionsScreen.java create mode 100644 src/main/java/com/terraformersmc/modmenu/gui/ModsScreen.java create mode 100644 src/main/java/com/terraformersmc/modmenu/gui/widget/DescriptionListWidget.java create mode 100644 src/main/java/com/terraformersmc/modmenu/gui/widget/ModListWidget.java create mode 100644 src/main/java/com/terraformersmc/modmenu/gui/widget/ModMenuButtonWidget.java create mode 100644 src/main/java/com/terraformersmc/modmenu/gui/widget/ModMenuTexturedButtonWidget.java create mode 100644 src/main/java/com/terraformersmc/modmenu/gui/widget/entries/ChildEntry.java create mode 100644 src/main/java/com/terraformersmc/modmenu/gui/widget/entries/IndependentEntry.java create mode 100644 src/main/java/com/terraformersmc/modmenu/gui/widget/entries/ModListEntry.java create mode 100644 src/main/java/com/terraformersmc/modmenu/gui/widget/entries/ParentEntry.java create mode 100644 src/main/java/com/terraformersmc/modmenu/mixin/MixinEntryListWidgetEntries.java create mode 100644 src/main/java/com/terraformersmc/modmenu/mixin/MixinTitleScreen.java create mode 100644 src/main/java/com/terraformersmc/modmenu/util/DrawingUtil.java create mode 100644 src/main/java/com/terraformersmc/modmenu/util/ModMenuApiMarker.java create mode 100644 src/main/java/com/terraformersmc/modmenu/util/OptionalUtil.java create mode 100644 src/main/java/com/terraformersmc/modmenu/util/TranslationUtil.java create mode 100644 src/main/java/com/terraformersmc/modmenu/util/mod/Mod.java create mode 100644 src/main/java/com/terraformersmc/modmenu/util/mod/ModBadgeRenderer.java create mode 100644 src/main/java/com/terraformersmc/modmenu/util/mod/ModIconHandler.java create mode 100644 src/main/java/com/terraformersmc/modmenu/util/mod/ModSearch.java create mode 100644 src/main/java/com/terraformersmc/modmenu/util/mod/fabric/CustomValueUtil.java create mode 100644 src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricDummyParentMod.java create mode 100644 src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricMod.java create mode 100644 src/main/resources/assets/modmenu/java_icon.png create mode 100644 src/main/resources/assets/modmenu/lang/ca_es.json create mode 100644 src/main/resources/assets/modmenu/lang/en_pt.json create mode 100644 src/main/resources/assets/modmenu/lang/en_ud.json create mode 100644 src/main/resources/assets/modmenu/lang/en_ws.json create mode 100644 src/main/resources/assets/modmenu/lang/fa_ir.json create mode 100644 src/main/resources/assets/modmenu/lang/lol_us.json create mode 100644 src/main/resources/assets/modmenu/lang/szl.json create mode 100644 src/main/resources/assets/modmenu/minecraft_icon.png create mode 100644 src/main/resources/assets/modmenu/textures/gui/mods_button.png create mode 100644 src/main/resources/assets/modmenu/textures/gui/mods_button_alt.png create mode 100644 src/main/resources/assets/modmenu/textures/gui/mods_button_alt3.png create mode 100644 src/main/resources/assets/modmenu/unknown_icon.png create mode 100644 src/main/resources/assets/modmenu/unknown_parent.png create mode 100644 src/main/resources/programmer_art/assets/modmenu/textures/gui/configure_button.png create mode 100644 src/main/resources/programmer_art/assets/modmenu/textures/gui/filters_button.png create mode 100644 src/main/resources/programmer_art/assets/modmenu/textures/gui/mods_button.png create mode 100644 src/main/resources/programmer_art/assets/modmenu/textures/gui/parent_mod.png diff --git a/.github/workflows/check_build.yml b/.github/workflows/check_build.yml new file mode 100644 index 000000000..d956e8c0f --- /dev/null +++ b/.github/workflows/check_build.yml @@ -0,0 +1,42 @@ +# Automatically build the project and run any configured tests for every push +# and submitted pull request. This can help catch issues that only occur on +# certain platforms or Java versions, and provides a first line of defence +# against bad commits. + +name: Check Build +on: [push, pull_request] + +jobs: + build: + strategy: + matrix: + # Use these Java versions + java: [ + 1.8, # Minimum + 11, # LTS + 15 # Latest + ] + os: [ubuntu-20.04] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Validate Gradle wrapper + uses: gradle/wrapper-validation-action@v1 + - name: Setup JDK ${{ matrix.java }} + uses: actions/setup-java@v1 + with: + java-version: ${{ matrix.java }} + - name: Make Gradle wrapper executable + if: ${{ runner.os != 'Windows' }} + run: chmod +x ./gradlew + - name: Build + run: ./gradlew build --stacktrace --parallel + - name: Capture build artifacts + if: ${{ runner.os == 'Linux' && matrix.java == '11' }} # Only upload artifacts built from LTS java on one OS + uses: actions/upload-artifact@v2 + with: + name: Artifacts + path: build/libs/ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..36b3aeac2 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,62 @@ +name: Release +on: + workflow_dispatch: + inputs: + previousVersion: + description: 'Previous Version (Do not include v prefix, must be same as the last version tag! Example: 1.4.1)' + required: true + version: + description: 'Version (Do not include v prefix! Example: 1.4.2)' + required: true +jobs: + release: + strategy: + matrix: + # Use these Java versions + java: [11] + # and run on both Linux and Windows + os: [ubuntu-20.04] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Create version tag + uses: actions/github-script@v3 + with: + github-token: ${{ github.token }} + script: | + github.git.createRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: "refs/tags/v${{ github.event.inputs.version }}", + sha: context.sha + }) + - name: Fetch tags + run: git fetch --tags + - name: Validate Gradle wrapper + uses: gradle/wrapper-validation-action@v1 + - name: Setup JDK ${{ matrix.java }} + uses: actions/setup-java@v1 + with: + java-version: ${{ matrix.java }} + - name: Make Gradle wrapper executable + if: ${{ runner.os != 'Windows' }} + run: chmod +x ./gradlew + - name: Build + run: ./gradlew generateChangelog build publish curseforge github publishModrinth --stacktrace --parallel -PlastTag="v${{ github.event.inputs.previousVersion }}" -PcurrentTag="v${{ github.event.inputs.version }}" + env: + MAVEN_URL: ${{ secrets.MAVEN_URL }} + MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} + CURSEFORGE_TOKEN: ${{ secrets.CURSEFORGE_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GH_API_KEY }} + MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} + DISCORD_ANNOUNCEMENT_WEBHOOK: ${{ secrets.DISCORD_ANNOUNCEMENT_WEBHOOK }} + - name: Capture build artifacts + if: ${{ runner.os == 'Linux' && matrix.java == '11' }} # Only upload artifacts built from LTS java on one OS + uses: actions/upload-artifact@v2 + with: + name: Artifacts + path: build/libs/ diff --git a/logs/latest.log b/logs/latest.log new file mode 100644 index 000000000..e69de29bb diff --git a/src/main/java/com/terraformersmc/modmenu/ModMenu.java b/src/main/java/com/terraformersmc/modmenu/ModMenu.java new file mode 100644 index 000000000..3476cd329 --- /dev/null +++ b/src/main/java/com/terraformersmc/modmenu/ModMenu.java @@ -0,0 +1,126 @@ +package com.terraformersmc.modmenu; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.LinkedListMultimap; +import com.google.gson.FieldNamingPolicy; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.terraformersmc.modmenu.api.ConfigScreenFactory; +import com.terraformersmc.modmenu.api.ModMenuApi; +import com.terraformersmc.modmenu.config.ModMenuConfig; +import com.terraformersmc.modmenu.config.ModMenuConfigManager; +import com.terraformersmc.modmenu.event.ModMenuEventHandler; +import com.terraformersmc.modmenu.util.ModMenuApiMarker; +import com.terraformersmc.modmenu.util.mod.Mod; +import com.terraformersmc.modmenu.util.mod.fabric.FabricDummyParentMod; +import com.terraformersmc.modmenu.util.mod.fabric.FabricMod; +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; + +import java.text.NumberFormat; +import java.util.HashMap; +import java.util.Map; + +public class ModMenu implements ClientModInitializer { + public static final String MOD_ID = "modmenu"; + public static final Gson GSON = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).setPrettyPrinting().create(); + + public static final Map MODS = new HashMap<>(); + public static final Map ROOT_MODS = new HashMap<>(); + public static final LinkedListMultimap PARENT_MAP = LinkedListMultimap.create(); + + private static ImmutableMap> configScreenFactories = ImmutableMap.of(); + + private static int cachedDisplayedModCount = -1; + + public static Screen getConfigScreen(String modid, Screen menuScreen) { + ConfigScreenFactory factory = configScreenFactories.get(modid); + return factory != null ? factory.create(menuScreen) : null; + } + + @Override + public void onInitializeClient() { + ModMenuConfigManager.initializeConfig(); + Map> factories = new HashMap<>(); + FabricLoader.getInstance().getEntrypointContainers("modmenu", ModMenuApiMarker.class).forEach(entrypoint -> { + ModMenuApiMarker marker = entrypoint.getEntrypoint(); + if (marker instanceof ModMenuApi) { + /* Current API */ + ModMenuApi api = (ModMenuApi) marker; + factories.put(entrypoint.getProvider().getMetadata().getId(), api.getModConfigScreenFactory()); + api.getProvidedConfigScreenFactories().forEach(factories::putIfAbsent); + } else if (marker instanceof io.github.prospector.modmenu.api.ModMenuApi) { + /* Legacy API */ + io.github.prospector.modmenu.api.ModMenuApi api = (io.github.prospector.modmenu.api.ModMenuApi) entrypoint.getEntrypoint(); + factories.put(entrypoint.getProvider().getMetadata().getId(), screen -> api.getModConfigScreenFactory().create(screen)); + api.getProvidedConfigScreenFactories().forEach((id, legacyFactory) -> factories.put(id, legacyFactory::create)); + } else { + throw new RuntimeException(entrypoint.getProvider().getMetadata().getId() + " is providing an invalid ModMenuApi implementation"); + } + }); + configScreenFactories = new ImmutableMap.Builder>().putAll(factories).build(); + + + // Fill mods map + for (ModContainer modContainer : FabricLoader.getInstance().getAllMods()) { + if (!ModMenuConfig.HIDDEN_MODS.getValue().contains(modContainer.getMetadata().getId())) { + FabricMod mod = new FabricMod(modContainer); + MODS.put(mod.getId(), mod); + } + } + + Map dummyParents = new HashMap<>(); + + // Initialize parent map + for (Mod mod : MODS.values()) { + String parentId = mod.getParent(); + if (parentId != null) { + Mod parent = MODS.getOrDefault(parentId, dummyParents.get(parentId)); + if (parent == null) { + if (mod instanceof FabricMod) { + parent = new FabricDummyParentMod((FabricMod) mod, parentId); + dummyParents.put(parentId, parent); + } + } + PARENT_MAP.put(parent, mod); + } else { + ROOT_MODS.put(mod.getId(), mod); + } + } + MODS.putAll(dummyParents); + ModMenuEventHandler.register(); + } + + public static void clearModCountCache() { + cachedDisplayedModCount = -1; + } + + public static String getDisplayedModCount() { + if (cachedDisplayedModCount == -1) { + // listen, if you have >= 2^32 mods then that's on you + cachedDisplayedModCount = Math.toIntExact(MODS.values().stream().filter(mod -> + (ModMenuConfig.COUNT_CHILDREN.getValue() || mod.getParent() == null) && + (ModMenuConfig.COUNT_LIBRARIES.getValue() || !mod.getBadges().contains(Mod.Badge.LIBRARY)) && + (ModMenuConfig.COUNT_HIDDEN_MODS.getValue() || !ModMenuConfig.HIDDEN_MODS.getValue().contains(mod.getId())) + ).count()); + } + return NumberFormat.getInstance().format(cachedDisplayedModCount); + } + + public static Text createModsButtonText() { + TranslatableText modsText = new TranslatableText("modmenu.title"); + if (ModMenuConfig.MOD_COUNT_LOCATION.getValue().isOnModsButton() && ModMenuConfig.MODS_BUTTON_STYLE.getValue() != ModMenuConfig.ModsButtonStyle.ICON) { + if (ModMenuConfig.MODS_BUTTON_STYLE.getValue() == ModMenuConfig.ModsButtonStyle.SHRINK) { + modsText.append(new LiteralText(" ")).append(new TranslatableText("modmenu.loaded.short", ModMenu.getDisplayedModCount())); + } else { + modsText.append(new LiteralText(" ")).append(new TranslatableText("modmenu.loaded", ModMenu.getDisplayedModCount())); + } + } + return modsText; + } +} diff --git a/src/main/java/com/terraformersmc/modmenu/ModMenuModMenuCompat.java b/src/main/java/com/terraformersmc/modmenu/ModMenuModMenuCompat.java new file mode 100644 index 000000000..99c8cacf0 --- /dev/null +++ b/src/main/java/com/terraformersmc/modmenu/ModMenuModMenuCompat.java @@ -0,0 +1,23 @@ +package com.terraformersmc.modmenu; + +import com.google.common.collect.ImmutableMap; +import com.terraformersmc.modmenu.api.ConfigScreenFactory; +import com.terraformersmc.modmenu.api.ModMenuApi; +import com.terraformersmc.modmenu.gui.ModMenuOptionsScreen; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.option.OptionsScreen; + +import java.util.Map; + +public class ModMenuModMenuCompat implements ModMenuApi { + + @Override + public ConfigScreenFactory getModConfigScreenFactory() { + return ModMenuOptionsScreen::new; + } + + @Override + public Map> getProvidedConfigScreenFactories() { + return ImmutableMap.of("minecraft", parent -> new OptionsScreen(parent, MinecraftClient.getInstance().options)); + } +} diff --git a/src/main/java/com/terraformersmc/modmenu/api/ConfigScreenFactory.java b/src/main/java/com/terraformersmc/modmenu/api/ConfigScreenFactory.java new file mode 100644 index 000000000..7de8e6164 --- /dev/null +++ b/src/main/java/com/terraformersmc/modmenu/api/ConfigScreenFactory.java @@ -0,0 +1,8 @@ +package com.terraformersmc.modmenu.api; + +import net.minecraft.client.gui.screen.Screen; + +@FunctionalInterface +public interface ConfigScreenFactory extends io.github.prospector.modmenu.api.ConfigScreenFactory { + S create(Screen parent); +} diff --git a/src/main/java/com/terraformersmc/modmenu/api/ModMenuApi.java b/src/main/java/com/terraformersmc/modmenu/api/ModMenuApi.java new file mode 100644 index 000000000..27fa22ba9 --- /dev/null +++ b/src/main/java/com/terraformersmc/modmenu/api/ModMenuApi.java @@ -0,0 +1,61 @@ +package com.terraformersmc.modmenu.api; + +import com.google.common.collect.ImmutableMap; +import com.terraformersmc.modmenu.ModMenu; +import com.terraformersmc.modmenu.gui.ModsScreen; +import com.terraformersmc.modmenu.util.ModMenuApiMarker; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; + +import java.util.Map; + +public interface ModMenuApi extends ModMenuApiMarker { + + /** + * Used for creating a {@link Screen} instance of the Mod Menu + * "Mods" screen + * + * @param previous The screen before opening + * @return A "Mods" Screen + */ + static Screen createModsScreen(Screen previous) { + return new ModsScreen(previous); + } + + /** + * Used for creating a {@link Text} just like what would appear + * on a Mod Menu Mods button + * + * @return The text that would be displayed on a Mods button + */ + static Text createModsButtonText() { + return ModMenu.createModsButtonText(); + } + + /** + * Used to construct a new config screen instance when your mod's + * configuration button is selected on the mod menu screen. The + * screen instance parameter is the active mod menu screen. + * + * @return A factory for constructing config screen instances. + */ + default ConfigScreenFactory getModConfigScreenFactory() { + return screen -> null; + } + + /** + * Used to provide config screen factories for other mods. This takes second + * priority to a mod's own config screen factory provider. For example, if + * mod `xyz` supplies a config screen factory, mod `abc` providing a config + * screen to `xyz` will be pointless, as the one provided by `xyz` will be + * used. + *

+ * This method is NOT meant to be used to add a config screen factory to + * your own mod. + * + * @return a map of mod ids to screen factories. + */ + default Map> getProvidedConfigScreenFactories() { + return ImmutableMap.of(); + } +} diff --git a/src/main/java/com/terraformersmc/modmenu/config/ModMenuConfig.java b/src/main/java/com/terraformersmc/modmenu/config/ModMenuConfig.java new file mode 100644 index 000000000..892acc63b --- /dev/null +++ b/src/main/java/com/terraformersmc/modmenu/config/ModMenuConfig.java @@ -0,0 +1,117 @@ +package com.terraformersmc.modmenu.config; + +import com.google.gson.annotations.SerializedName; +import com.terraformersmc.modmenu.config.option.BooleanConfigOption; +import com.terraformersmc.modmenu.config.option.EnumConfigOption; +import com.terraformersmc.modmenu.config.option.OptionConvertable; +import com.terraformersmc.modmenu.config.option.StringSetConfigOption; +import com.terraformersmc.modmenu.util.mod.Mod; +import net.minecraft.client.option.Option; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Locale; + +public class ModMenuConfig { + public static final EnumConfigOption SORTING = new EnumConfigOption<>("sorting", Sorting.ASCENDING); + public static final BooleanConfigOption COUNT_LIBRARIES = new BooleanConfigOption("count_libraries", true); + public static final BooleanConfigOption COMPACT_LIST = new BooleanConfigOption("compact_list", false); + public static final BooleanConfigOption COUNT_CHILDREN = new BooleanConfigOption("count_children", true); + public static final EnumConfigOption MODS_BUTTON_STYLE = new EnumConfigOption<>("mods_button_style", ModsButtonStyle.CLASSIC); + public static final BooleanConfigOption COUNT_HIDDEN_MODS = new BooleanConfigOption("count_hidden_mods", true); + public static final EnumConfigOption MOD_COUNT_LOCATION = new EnumConfigOption<>("mod_count_location", ModCountLocation.TITLE_SCREEN); + public static final BooleanConfigOption HIDE_MOD_LINKS = new BooleanConfigOption("hide_mod_links", false); + public static final BooleanConfigOption SHOW_LIBRARIES = new BooleanConfigOption("show_libraries", false); + public static final BooleanConfigOption HIDE_MOD_LICENSE = new BooleanConfigOption("hide_mod_license", false); + public static final BooleanConfigOption HIDE_BADGES = new BooleanConfigOption("hide_badges", false); + public static final BooleanConfigOption HIDE_MOD_CREDITS = new BooleanConfigOption("hide_mod_credits", false); + public static final BooleanConfigOption EASTER_EGGS = new BooleanConfigOption("easter_eggs", true); + public static final BooleanConfigOption MODIFY_TITLE_SCREEN = new BooleanConfigOption("modify_title_screen", true); + public static final BooleanConfigOption MODIFY_GAME_MENU = new BooleanConfigOption("modify_game_menu", true); + public static final BooleanConfigOption HIDE_CONFIG_BUTTONS = new BooleanConfigOption("hide_config_buttons", false); + public static final StringSetConfigOption HIDDEN_MODS = new StringSetConfigOption("hidden_mods", new HashSet<>()); + + public static Option[] asOptions() { + ArrayList