From 81af7f3b30fb782b4989bbb1b984bc27dbc6f35a Mon Sep 17 00:00:00 2001 From: 1foxy2 Date: Sun, 11 Oct 2026 10:15:02 +0200 Subject: [PATCH 1/2] Make badges data driven --- .../modmenu/event/ModMenuEventHandler.java | 8 ++ .../modmenu/util/mod/BadgeHolder.java | 21 +++++ .../modmenu/util/mod/BadgeManager.java | 35 ++++++++ .../terraformersmc/modmenu/util/mod/Mod.java | 86 +++++++------------ .../modmenu/util/mod/ModBadgeRenderer.java | 8 +- .../modmenu/util/mod/ModSearch.java | 14 +-- .../util/mod/fabric/CustomValueUtil.java | 28 ++++++ .../util/mod/fabric/FabricDummyParentMod.java | 27 ++++-- .../modmenu/util/mod/fabric/FabricMod.java | 78 +++++++++++------ .../modmenu/util/mod/quilt/QuiltMod.java | 2 +- .../modmenu/badge/clientside_only.json | 8 ++ .../modmenu/modmenu/badge/deprecated.json | 8 ++ .../assets/modmenu/modmenu/badge/library.json | 8 ++ .../modmenu/modmenu/badge/minecraft.json | 7 ++ .../assets/modmenu/modmenu/badge/modpack.json | 8 ++ .../modmenu/badge/patchwork_forge.json | 8 ++ 16 files changed, 248 insertions(+), 106 deletions(-) create mode 100644 src/main/java/com/terraformersmc/modmenu/util/mod/BadgeHolder.java create mode 100644 src/main/java/com/terraformersmc/modmenu/util/mod/BadgeManager.java create mode 100644 src/main/resources/assets/modmenu/modmenu/badge/clientside_only.json create mode 100644 src/main/resources/assets/modmenu/modmenu/badge/deprecated.json create mode 100644 src/main/resources/assets/modmenu/modmenu/badge/library.json create mode 100644 src/main/resources/assets/modmenu/modmenu/badge/minecraft.json create mode 100644 src/main/resources/assets/modmenu/modmenu/badge/modpack.json create mode 100644 src/main/resources/assets/modmenu/modmenu/badge/patchwork_forge.json diff --git a/src/main/java/com/terraformersmc/modmenu/event/ModMenuEventHandler.java b/src/main/java/com/terraformersmc/modmenu/event/ModMenuEventHandler.java index bf7c10832..73ed51a50 100644 --- a/src/main/java/com/terraformersmc/modmenu/event/ModMenuEventHandler.java +++ b/src/main/java/com/terraformersmc/modmenu/event/ModMenuEventHandler.java @@ -7,10 +7,12 @@ import com.terraformersmc.modmenu.gui.ModsScreen; import com.terraformersmc.modmenu.gui.widget.ModMenuButtonWidget; import com.terraformersmc.modmenu.util.UpdateCheckerUtil; +import com.terraformersmc.modmenu.util.mod.BadgeManager; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.keymapping.v1.KeyMappingHelper; import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; import net.fabricmc.fabric.api.client.screen.v1.Screens; +import net.fabricmc.fabric.api.resource.v1.ResourceLoader; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.AbstractWidget; @@ -22,6 +24,7 @@ import net.minecraft.network.chat.ComponentContents; import net.minecraft.network.chat.contents.TranslatableContents; import net.minecraft.resources.Identifier; +import net.minecraft.server.packs.PackType; import java.util.Arrays; import java.util.List; @@ -38,6 +41,11 @@ public static void register() { )); ClientTickEvents.END_CLIENT_TICK.register(ModMenuEventHandler::onClientEndTick); ScreenEvents.AFTER_INIT.register(ModMenuEventHandler::afterScreenInit); + ResourceLoader.get(PackType.CLIENT_RESOURCES).registerReloadListener( + Identifier.fromNamespaceAndPath(ModMenu.MOD_ID, "badge_manager"), + BadgeManager.INSTANCE + ); + } public static void afterScreenInit(Minecraft client, Screen screen, int scaledWidth, int scaledHeight) { diff --git a/src/main/java/com/terraformersmc/modmenu/util/mod/BadgeHolder.java b/src/main/java/com/terraformersmc/modmenu/util/mod/BadgeHolder.java new file mode 100644 index 000000000..228fabdb9 --- /dev/null +++ b/src/main/java/com/terraformersmc/modmenu/util/mod/BadgeHolder.java @@ -0,0 +1,21 @@ +package com.terraformersmc.modmenu.util.mod; + +import net.minecraft.resources.Identifier; + +public record BadgeHolder(Identifier id, Mod.Badge badge) { + + @Override + public boolean equals(final Object obj) { + return this == obj || obj instanceof BadgeHolder holder && this.id == holder.id; + } + + @Override + public int hashCode() { + return this.id.hashCode(); + } + + @Override + public String toString() { + return this.id.toString(); + } +} diff --git a/src/main/java/com/terraformersmc/modmenu/util/mod/BadgeManager.java b/src/main/java/com/terraformersmc/modmenu/util/mod/BadgeManager.java new file mode 100644 index 000000000..56ab4bf7f --- /dev/null +++ b/src/main/java/com/terraformersmc/modmenu/util/mod/BadgeManager.java @@ -0,0 +1,35 @@ +package com.terraformersmc.modmenu.util.mod; + +import com.mojang.logging.LogUtils; +import com.terraformersmc.modmenu.ModMenu; +import net.minecraft.resources.FileToIdConverter; +import net.minecraft.resources.Identifier; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; +import net.minecraft.util.profiling.ProfilerFiller; + +import java.util.Map; +import java.util.stream.Collectors; + +public class BadgeManager extends SimpleJsonResourceReloadListener { + private static final FileToIdConverter ASSET_LISTER = FileToIdConverter.json("modmenu/badge"); + public static final BadgeManager INSTANCE = new BadgeManager(); + private Map badges = Map.of(); + + protected BadgeManager() { + super(Mod.Badge.CODEC, ASSET_LISTER); + } + + @Override + protected void apply(Map preparations, ResourceManager manager, ProfilerFiller profiler) { + badges = preparations.entrySet() + .stream() + .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, entry -> new BadgeHolder(entry.getKey(), entry.getValue()))); + + ModMenu.MODS.values().forEach(Mod::recalculateBadges); + } + + public static BadgeHolder getBadge(Identifier id) { + return INSTANCE.badges.get(id); + } +} diff --git a/src/main/java/com/terraformersmc/modmenu/util/mod/Mod.java b/src/main/java/com/terraformersmc/modmenu/util/mod/Mod.java index 6f02de0c6..56d5be2fa 100644 --- a/src/main/java/com/terraformersmc/modmenu/util/mod/Mod.java +++ b/src/main/java/com/terraformersmc/modmenu/util/mod/Mod.java @@ -1,5 +1,7 @@ package com.terraformersmc.modmenu.util.mod; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import com.terraformersmc.modmenu.ModMenu; import com.terraformersmc.modmenu.TextPlaceholderApiCompat; import com.terraformersmc.modmenu.api.UpdateChecker; @@ -9,6 +11,9 @@ import eu.pb4.placeholders.api.ParserContext; import net.fabricmc.loader.api.metadata.ContactInformation; import net.minecraft.locale.Language; +import net.minecraft.network.chat.ComponentSerialization; +import net.minecraft.resources.Identifier; +import net.minecraft.util.ExtraCodecs; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -95,7 +100,7 @@ default Component getFormattedDescription() { */ @NotNull SortedMap> getCredits(); - @NotNull Set getBadges(); + @NotNull Set getBadges(); @Nullable String getWebsite(); @@ -140,55 +145,25 @@ default boolean hasUpdate() { boolean isHidden(); - enum Badge { - LIBRARY( - "modmenu.badge.library", - 0xFF107454, - 0xFF093929, - "library" - ), - CLIENT( - "modmenu.badge.clientsideOnly", - 0xFF2b4b7c, - 0xFF0e2a55, - null - ), - DEPRECATED( - "modmenu.badge.deprecated", - 0xFF841426, - 0xFF530C17, - "deprecated" - ), - PATCHWORK_FORGE( - "modmenu.badge.forge", - 0xFF1f2d42, - 0xFF101721, - null - ), - MODPACK( - "modmenu.badge.modpack", - 0xFF7a2b7c, - 0xFF510d54, - null - ), - MINECRAFT( - "modmenu.badge.minecraft", - 0xFF6f6c6a, - 0xFF31302f, - null - ); - - private final Component text; - private final int outlineColor, fillColor; - private final String key; - private static final Map KEY_MAP = new HashMap<>(); - - Badge(String translationKey, int outlineColor, int fillColor, String key) { - this.text = Component.translatable(translationKey); - this.outlineColor = outlineColor; - this.fillColor = fillColor; - this.key = key; - } + void recalculateBadges(); + + record Badge(Component text, int outlineColor, int fillColor, int textColor, Optional searchTerms) { + + public static final Identifier LIBRARY = Identifier.fromNamespaceAndPath(ModMenu.MOD_ID, "library"); + public static final Identifier CLIENT = Identifier.fromNamespaceAndPath(ModMenu.MOD_ID, "clientside_only"); + public static final Identifier DEPRECATED = Identifier.fromNamespaceAndPath(ModMenu.MOD_ID, "deprecated"); + public static final Identifier PATCHWORK_FORGE = Identifier.fromNamespaceAndPath(ModMenu.MOD_ID, "patchwork_forge"); + public static final Identifier MODPACK = Identifier.fromNamespaceAndPath(ModMenu.MOD_ID, "modpack"); + public static final Identifier MINECRAFT = Identifier.fromNamespaceAndPath(ModMenu.MOD_ID, "minecraft"); + + public static final Codec CODEC = RecordCodecBuilder.create(instance -> + instance.group( + ComponentSerialization.CODEC.fieldOf("text").forGetter(Badge::getText), + ExtraCodecs.STRING_ARGB_COLOR.fieldOf("outline_color").forGetter(Badge::outlineColor), + ExtraCodecs.STRING_ARGB_COLOR.fieldOf("fill_color").forGetter(Badge::fillColor), + ExtraCodecs.STRING_ARGB_COLOR.optionalFieldOf("text_color", 0xFFCACACA).forGetter(Badge::textColor), + Codec.STRING.optionalFieldOf("search_terms").forGetter(Badge::searchTerms) + ).apply(instance, Badge::new)); public Component getText() { return this.text; @@ -202,18 +177,15 @@ public int getFillColor() { return this.fillColor; } - public static Set convert(Set badgeKeys, String modId) { + public static Set convert(Set badgeKeys, String modId) { return badgeKeys.stream().map(key -> { - if (!KEY_MAP.containsKey(key)) { + BadgeHolder badgeHolder = BadgeManager.getBadge(key); + if (badgeHolder == null) { ModMenu.LOGGER.warn("Skipping unknown badge key '{}' specified by mod '{}'", key, modId); } - return KEY_MAP.get(key); + return badgeHolder; }).filter(Objects::nonNull).collect(Collectors.toSet()); } - - static { - Arrays.stream(values()).forEach(badge -> KEY_MAP.put(badge.key, badge)); - } } } diff --git a/src/main/java/com/terraformersmc/modmenu/util/mod/ModBadgeRenderer.java b/src/main/java/com/terraformersmc/modmenu/util/mod/ModBadgeRenderer.java index f5690f935..426a57454 100644 --- a/src/main/java/com/terraformersmc/modmenu/util/mod/ModBadgeRenderer.java +++ b/src/main/java/com/terraformersmc/modmenu/util/mod/ModBadgeRenderer.java @@ -27,8 +27,8 @@ public ModBadgeRenderer(int startX, int startY, int endX, Mod mod, ModsScreen sc public void draw(GuiGraphicsExtractor drawContext, int mouseX, int mouseY) { this.badgeX = startX; this.badgeY = startY; - Set badges = mod.getBadges(); - badges.forEach(badge -> drawBadge(drawContext, badge, mouseX, mouseY)); + Set badges = mod.getBadges(); + badges.forEach(badge -> drawBadge(drawContext, badge.badge(), mouseX, mouseY)); } public void drawBadge(GuiGraphicsExtractor drawContext, Mod.Badge badge, int mouseX, int mouseY) { @@ -37,6 +37,7 @@ public void drawBadge(GuiGraphicsExtractor drawContext, Mod.Badge badge, int mou badge.getText().getVisualOrderText(), badge.getOutlineColor(), badge.getFillColor(), + badge.textColor(), mouseX, mouseY ); @@ -47,12 +48,13 @@ public void drawBadge( FormattedCharSequence text, int outlineColor, int fillColor, + int textColor, int mouseX, int mouseY ) { int width = client.font.width(text) + 6; if (badgeX + width < badgeMax) { - DrawingUtil.drawBadge(drawContext, badgeX, badgeY, width, text, outlineColor, fillColor, 0xFFCACACA); + DrawingUtil.drawBadge(drawContext, badgeX, badgeY, width, text, outlineColor, fillColor, textColor); badgeX += width + 3; } } diff --git a/src/main/java/com/terraformersmc/modmenu/util/mod/ModSearch.java b/src/main/java/com/terraformersmc/modmenu/util/mod/ModSearch.java index 384a2acee..acdbef3e9 100644 --- a/src/main/java/com/terraformersmc/modmenu/util/mod/ModSearch.java +++ b/src/main/java/com/terraformersmc/modmenu/util/mod/ModSearch.java @@ -39,11 +39,6 @@ private static int passesFilters(ModsScreen screen, Mod mod, String query) { String modDescription = mod.getDescription(); String modSummary = mod.getSummary(); - String library = I18n.get("modmenu.searchTerms.library"); - String patchwork = I18n.get("modmenu.searchTerms.patchwork"); - String modpack = I18n.get("modmenu.searchTerms.modpack"); - String deprecated = I18n.get("modmenu.searchTerms.deprecated"); - String clientside = I18n.get("modmenu.searchTerms.clientside"); String configurable = I18n.get("modmenu.searchTerms.configurable"); String hasUpdate = I18n.get("modmenu.searchTerms.hasUpdate"); @@ -63,13 +58,8 @@ private static int passesFilters(ModsScreen screen, Mod mod, String query) { if (modDescription.toLowerCase(Locale.ROOT).contains(query) // Search default mod description || modSummary.toLowerCase(Locale.ROOT).contains(query) // Search mod summary || authorMatches(mod, query) // Search via author - || library.contains(query) && mod.getBadges().contains(Mod.Badge.LIBRARY) // Search for lib mods - || patchwork.contains(query) && mod.getBadges() - .contains(Mod.Badge.PATCHWORK_FORGE) // Search for patchwork mods - || modpack.contains(query) && mod.getBadges().contains(Mod.Badge.MODPACK) // Search for modpack mods - || deprecated.contains(query) && mod.getBadges() - .contains(Mod.Badge.DEPRECATED) // Search for deprecated mods - || clientside.contains(query) && mod.getBadges().contains(Mod.Badge.CLIENT) // Search for clientside mods + || mod.getBadges().stream().anyMatch(badgeHolder -> + badgeHolder.badge().searchTerms().map(key -> I18n.get(key).contains(query)).orElse(false)) // Search for badges || configurable.contains(query) && screen.getModHasConfigScreen(modId) // Search for mods that can be configured || hasUpdate.contains(query) && mod.hasUpdate() // Search for mods that have updates ) { diff --git a/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/CustomValueUtil.java b/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/CustomValueUtil.java index 80efaaf41..ef13bdcf7 100644 --- a/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/CustomValueUtil.java +++ b/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/CustomValueUtil.java @@ -1,7 +1,9 @@ package com.terraformersmc.modmenu.util.mod.fabric; +import com.terraformersmc.modmenu.ModMenu; import net.fabricmc.loader.api.metadata.CustomValue; import net.fabricmc.loader.api.metadata.ModMetadata; +import net.minecraft.resources.Identifier; import java.util.*; @@ -64,6 +66,32 @@ public static Optional> getStringSet(String key, CustomValue.CvObjec return Optional.empty(); } + public static Optional> getIdentifierSet(String key, CustomValue.CvObject object) { + if (object.containsKey(key)) { + Set ids = new HashSet<>(); + for (CustomValue value : object.get(key).getAsArray()) { + ids.add(bySeparatorModMenuId(value.getAsString(), ':')); + } + return Optional.of(ids); + } + return Optional.empty(); + } + + private static Identifier bySeparatorModMenuId(final String identifier, final char separator) { + int separatorIndex = identifier.indexOf(separator); + if (separatorIndex >= 0) { + String path = identifier.substring(separatorIndex + 1); + if (separatorIndex != 0) { + String namespace = identifier.substring(0, separatorIndex); + return Identifier.fromNamespaceAndPath(namespace, path); + } else { + return Identifier.fromNamespaceAndPath(ModMenu.MOD_ID, path); + } + } else { + return Identifier.fromNamespaceAndPath(ModMenu.MOD_ID, identifier); + } + } + public static Optional> getStringMap(String key, CustomValue.CvObject object) { if (object.containsKey(key)) { Map strings = new HashMap<>(); diff --git a/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricDummyParentMod.java b/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricDummyParentMod.java index 51023d73c..6bbc66ec2 100644 --- a/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricDummyParentMod.java +++ b/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricDummyParentMod.java @@ -4,6 +4,8 @@ import com.terraformersmc.modmenu.api.UpdateChecker; import com.terraformersmc.modmenu.api.UpdateInfo; import com.terraformersmc.modmenu.config.ModMenuConfig; +import com.terraformersmc.modmenu.util.mod.BadgeHolder; +import com.terraformersmc.modmenu.util.mod.BadgeManager; import com.terraformersmc.modmenu.util.mod.Mod; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; @@ -110,24 +112,31 @@ public ContactInformation getContact(String author) { } @Override - public @NotNull Set getBadges() { + public @NotNull Set getBadges() { FabricMod.ModMenuData.DummyParentData parentData = host.getModMenuData().getDummyParentData(); if (parentData != null) { return parentData.getBadges(); } - var badges = new HashSet(); + var badges = new HashSet(); if (id.equals("fabric-api")) { - badges.add(Badge.LIBRARY); + BadgeHolder library = BadgeManager.getBadge(Badge.LIBRARY); + if (library != null) { + badges.add(library); + } } boolean modpackChildren = true; + BadgeHolder modpackBadge = BadgeManager.getBadge(Badge.MODPACK); + if (modpackBadge == null) { + return badges; + } for (Mod mod : ModMenu.PARENT_MAP.get(this)) { - if (!mod.getBadges().contains(Badge.MODPACK)) { + if (!mod.getBadges().contains(modpackBadge)) { modpackChildren = false; } } if (modpackChildren) { - badges.add(Badge.MODPACK); + badges.add(modpackBadge); } return badges; @@ -207,4 +216,12 @@ public void setChildHasUpdate() { public boolean isHidden() { return ModMenuConfig.HIDDEN_MODS.getValue().contains(this.getId()); } + + @Override + public void recalculateBadges() { + FabricMod.ModMenuData.DummyParentData parentData = host.getModMenuData().getDummyParentData(); + if (parentData != null) { + parentData.setBadges(Mod.Badge.convert(parentData.getBadgeIds(), parentData.getId())); + } + } } diff --git a/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricMod.java b/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricMod.java index 3c5c0ab4e..3eed7c35f 100644 --- a/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricMod.java +++ b/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricMod.java @@ -9,12 +9,14 @@ import com.terraformersmc.modmenu.api.UpdateInfo; import com.terraformersmc.modmenu.config.ModMenuConfig; import com.terraformersmc.modmenu.util.VersionUtil; +import com.terraformersmc.modmenu.util.mod.BadgeHolder; import com.terraformersmc.modmenu.util.mod.Mod; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; import net.fabricmc.loader.api.metadata.*; import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.client.resources.language.I18n; +import net.minecraft.resources.Identifier; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -33,8 +35,6 @@ public class FabricMod implements Mod { protected final ModMenuData modMenuData; - protected final Set badges; - protected final Map links = new HashMap<>(); protected @Nullable UpdateChecker updateChecker = null; @@ -58,7 +58,7 @@ public FabricMod(ModContainer modContainer, Set modpackMods) { /* Load modern mod menu custom value data */ Optional parentId = Optional.empty(); ModMenuData.DummyParentData parentData = null; - Set badgeNames = new HashSet<>(); + Set badgeIds = new HashSet<>(); CustomValue modMenuValue = metadata.getCustomValue("modmenu"); if (modMenuValue != null && modMenuValue.getType() == CustomValue.CvType.OBJECT) { CustomValue.CvObject modMenuObject = modMenuValue.getAsObject(); @@ -75,7 +75,7 @@ public FabricMod(ModContainer modContainer, Set modpackMods) { CustomValueUtil.getString("name", parentObj), CustomValueUtil.getString("description", parentObj), CustomValueUtil.getString("icon", parentObj), - CustomValueUtil.getStringSet("badges", parentObj).orElse(new HashSet<>()) + CustomValueUtil.getIdentifierSet("badges", parentObj).orElse(new HashSet<>()) ); if (parentId.orElse("").equals(id)) { parentId = Optional.empty(); @@ -87,7 +87,7 @@ public FabricMod(ModContainer modContainer, Set modpackMods) { } } } - badgeNames.addAll(CustomValueUtil.getStringSet("badges", modMenuObject).orElse(new HashSet<>())); + badgeIds.addAll(CustomValueUtil.getIdentifierSet("badges", modMenuObject).orElse(new HashSet<>())); links.putAll(CustomValueUtil.getStringMap("links", modMenuObject).orElse(new HashMap<>())); allowsUpdateChecks = CustomValueUtil.getBoolean("update_checker", modMenuObject).orElse(true); } @@ -99,7 +99,7 @@ public FabricMod(ModContainer modContainer, Set modpackMods) { ModContainer inside = container.getContainingMod().get(); parentId = Optional.of(inside.getMetadata().getId()); } - this.modMenuData = new ModMenuData(badgeNames, parentId, parentData, id); + this.modMenuData = new ModMenuData(badgeIds, parentId, parentData); /* Hardcode parents and badges for Fabric API & Fabric Loader */ if (id.startsWith("fabric") && metadata.containsCustomValue("fabric-api:module-lifecycle")) { @@ -110,39 +110,38 @@ public FabricMod(ModContainer modContainer, Set modpackMods) { modMenuData.fillParentIfEmpty("fabric"); } - modMenuData.badges.add(Badge.LIBRARY); + modMenuData.badgeIds.add(Badge.LIBRARY); } if (id.startsWith("fabric") && (id.equals("fabricloader") || metadata.getProvides() .contains("fabricloader") || id.equals("fabric") || id.equals("fabric-api") || metadata.getProvides() .contains("fabric") || metadata.getProvides() .contains("fabric-api") || id.equals("fabric-language-kotlin"))) { - modMenuData.badges.add(Badge.LIBRARY); + modMenuData.badgeIds.add(Badge.LIBRARY); } /* Add additional badges */ - this.badges = modMenuData.badges; if (this.metadata.getEnvironment() == ModEnvironment.CLIENT) { - badges.add(Badge.CLIENT); + modMenuData.badgeIds.add(Badge.CLIENT); } if (isGenerated || "java".equals(id)) { - badges.add(Badge.LIBRARY); + modMenuData.badgeIds.add(Badge.LIBRARY); } if ("deprecated".equals(CustomValueUtil.getString("fabric-api:module-lifecycle", metadata).orElse(null))) { - badges.add(Badge.DEPRECATED); + modMenuData.badgeIds.add(Badge.DEPRECATED); } if (metadata.containsCustomValue("patchwork:patcherMeta")) { - badges.add(Badge.PATCHWORK_FORGE); + modMenuData.badgeIds.add(Badge.PATCHWORK_FORGE); } if (modpackMods.contains(getId()) && !"builtin".equals(this.metadata.getType())) { - badges.add(Badge.MODPACK); + modMenuData.badgeIds.add(Badge.MODPACK); } if ("minecraft".equals(getId())) { - badges.add(Badge.MINECRAFT); + modMenuData.badgeIds.add(Badge.MINECRAFT); } } @@ -282,8 +281,8 @@ public ContactInformation getContact(String author) { } @Override - public @NotNull Set getBadges() { - return badges; + public @NotNull Set getBadges() { + return modMenuData.getBadges(); } @Override @@ -404,22 +403,36 @@ public boolean isHidden() { return ModMenuConfig.HIDDEN_MODS.getValue().contains(this.getId()); } - static class ModMenuData { - private final Set badges; + @Override + public void recalculateBadges() { + getModMenuData().setBadges(Mod.Badge.convert(getModMenuData().getBadgeIds(), getId())); + } + + public static class ModMenuData { + private final Set badgeIds; + private Set badges = Set.of(); private Optional parent; private @Nullable final DummyParentData dummyParentData; - public ModMenuData(Set badges, Optional parent, DummyParentData dummyParentData, String id) { - this.badges = Badge.convert(badges, id); + public ModMenuData(Set badges, Optional parent, DummyParentData dummyParentData) { + this.badgeIds = badges; this.parent = parent; this.dummyParentData = dummyParentData; } - public Set getBadges() { + public Set getBadges() { return badges; } + public void setBadges(Set badges) { + this.badges = badges; + } + + public Set getBadgeIds() { + return badgeIds; + } + public Optional getParent() { return parent; } @@ -430,13 +443,13 @@ public Optional getParent() { public void addClientBadge(boolean add) { if (add) { - badges.add(Badge.CLIENT); + badgeIds.add(Badge.CLIENT); } } public void addLibraryBadge(boolean add) { if (add) { - badges.add(Badge.LIBRARY); + badgeIds.add(Badge.LIBRARY); } } @@ -451,20 +464,21 @@ public static class DummyParentData { private final Optional name; private final Optional description; private final Optional icon; - private final Set badges; + private final Set badgeIds; + private Set badges = Set.of(); public DummyParentData( String id, Optional name, Optional description, Optional icon, - Set badges + Set badges ) { this.id = id; this.name = name; this.description = description; this.icon = icon; - this.badges = Badge.convert(badges, id); + this.badgeIds = badges; } public String getId() { @@ -483,9 +497,17 @@ public Optional getIcon() { return icon; } - public Set getBadges() { + public Set getBadges() { return badges; } + + public void setBadges(Set badges) { + this.badges = badges; + } + + public Set getBadgeIds() { + return badgeIds; + } } } } diff --git a/src/main/java/com/terraformersmc/modmenu/util/mod/quilt/QuiltMod.java b/src/main/java/com/terraformersmc/modmenu/util/mod/quilt/QuiltMod.java index 9af968b54..0855b0679 100644 --- a/src/main/java/com/terraformersmc/modmenu/util/mod/quilt/QuiltMod.java +++ b/src/main/java/com/terraformersmc/modmenu/util/mod/quilt/QuiltMod.java @@ -27,7 +27,7 @@ public QuiltMod(net.fabricmc.loader.api.ModContainer fabricModContainer, Set Date: Sun, 11 Oct 2026 10:37:21 +0200 Subject: [PATCH 2/2] Fix hide library not working --- src/main/java/com/terraformersmc/modmenu/ModMenu.java | 2 +- .../com/terraformersmc/modmenu/config/ModMenuConfig.java | 4 ++-- .../java/com/terraformersmc/modmenu/gui/ModsScreen.java | 6 +++--- src/main/java/com/terraformersmc/modmenu/util/mod/Mod.java | 5 +++-- .../resources/assets/modmenu/modmenu/badge/library.json | 3 ++- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/terraformersmc/modmenu/ModMenu.java b/src/main/java/com/terraformersmc/modmenu/ModMenu.java index ebe19015f..f807629ad 100644 --- a/src/main/java/com/terraformersmc/modmenu/ModMenu.java +++ b/src/main/java/com/terraformersmc/modmenu/ModMenu.java @@ -230,7 +230,7 @@ public static String getDisplayedModCount() { return false; } - boolean isLibrary = mod.getBadges().contains(Mod.Badge.LIBRARY); + boolean isLibrary = mod.getBadges().stream().anyMatch(badgeHolder -> badgeHolder.badge().library()); if (!includeLibraries && isLibrary) { return false; } diff --git a/src/main/java/com/terraformersmc/modmenu/config/ModMenuConfig.java b/src/main/java/com/terraformersmc/modmenu/config/ModMenuConfig.java index abd18bebd..a9654fbdb 100644 --- a/src/main/java/com/terraformersmc/modmenu/config/ModMenuConfig.java +++ b/src/main/java/com/terraformersmc/modmenu/config/ModMenuConfig.java @@ -99,8 +99,8 @@ public enum LibraryVisibility { public boolean hideMod(Mod mod, boolean hasConfig) { return switch (this) { case TRUE -> false; - case FALSE -> mod.getBadges().contains(Mod.Badge.LIBRARY); - case WITH_CONFIG -> mod.getBadges().contains(Mod.Badge.LIBRARY) && !hasConfig; + case FALSE -> mod.getBadges().stream().anyMatch(badgeHolder -> badgeHolder.badge().library()); + case WITH_CONFIG -> mod.getBadges().stream().anyMatch(badgeHolder -> badgeHolder.badge().library()) && !hasConfig; }; } diff --git a/src/main/java/com/terraformersmc/modmenu/gui/ModsScreen.java b/src/main/java/com/terraformersmc/modmenu/gui/ModsScreen.java index 22e114e55..5c94ef38d 100644 --- a/src/main/java/com/terraformersmc/modmenu/gui/ModsScreen.java +++ b/src/main/java/com/terraformersmc/modmenu/gui/ModsScreen.java @@ -473,7 +473,7 @@ public void extractRenderState(GuiGraphicsExtractor drawContext, int mouseX, int private Component computeModCountText(boolean includeLibs, boolean onInit) { int[] rootMods = formatModCount(ModMenu.ROOT_MODS.values() .stream() - .filter(mod -> !mod.isHidden() && !mod.getBadges().contains(Mod.Badge.LIBRARY)) + .filter(mod -> !mod.isHidden() && !mod.getBadges().stream().anyMatch(badgeHolder -> badgeHolder.badge().library())) .map(Mod::getId) .collect(Collectors.toSet()), onInit); if (includeLibs && !onInit) { @@ -481,7 +481,7 @@ private Component computeModCountText(boolean includeLibs, boolean onInit) { int[] rootLibs = formatModCount(ModMenu.ROOT_MODS.values() .stream() - .filter(mod -> !mod.isHidden() && mod.getBadges().contains(Mod.Badge.LIBRARY) && !visibility.hideMod(mod, getModHasConfigScreen(mod.getId()))) + .filter(mod -> !mod.isHidden() && mod.getBadges().stream().anyMatch(badgeHolder -> badgeHolder.badge().library()) && !visibility.hideMod(mod, getModHasConfigScreen(mod.getId()))) .map(Mod::getId) .collect(Collectors.toSet()), false); @@ -498,7 +498,7 @@ private Component computeLibraryCountText(boolean onInit) { if (!onInit) { int[] rootLibs = formatModCount(ModMenu.ROOT_MODS.values() .stream() - .filter(mod -> !mod.isHidden() && mod.getBadges().contains(Mod.Badge.LIBRARY) && !visibility.hideMod(mod, this.getModHasConfigScreen(mod.getId()))) + .filter(mod -> !mod.isHidden() && mod.getBadges().stream().anyMatch(badgeHolder -> badgeHolder.badge().library()) && !visibility.hideMod(mod, this.getModHasConfigScreen(mod.getId()))) .map(Mod::getId) .collect(Collectors.toSet()), false); return TranslationUtil.translateNumeric("modmenu.showingLibraries", rootLibs); diff --git a/src/main/java/com/terraformersmc/modmenu/util/mod/Mod.java b/src/main/java/com/terraformersmc/modmenu/util/mod/Mod.java index 56d5be2fa..0d7f91ce1 100644 --- a/src/main/java/com/terraformersmc/modmenu/util/mod/Mod.java +++ b/src/main/java/com/terraformersmc/modmenu/util/mod/Mod.java @@ -147,7 +147,7 @@ default boolean hasUpdate() { void recalculateBadges(); - record Badge(Component text, int outlineColor, int fillColor, int textColor, Optional searchTerms) { + record Badge(Component text, int outlineColor, int fillColor, int textColor, Optional searchTerms, boolean library) { public static final Identifier LIBRARY = Identifier.fromNamespaceAndPath(ModMenu.MOD_ID, "library"); public static final Identifier CLIENT = Identifier.fromNamespaceAndPath(ModMenu.MOD_ID, "clientside_only"); @@ -162,7 +162,8 @@ record Badge(Component text, int outlineColor, int fillColor, int textColor, Opt ExtraCodecs.STRING_ARGB_COLOR.fieldOf("outline_color").forGetter(Badge::outlineColor), ExtraCodecs.STRING_ARGB_COLOR.fieldOf("fill_color").forGetter(Badge::fillColor), ExtraCodecs.STRING_ARGB_COLOR.optionalFieldOf("text_color", 0xFFCACACA).forGetter(Badge::textColor), - Codec.STRING.optionalFieldOf("search_terms").forGetter(Badge::searchTerms) + Codec.STRING.optionalFieldOf("search_terms").forGetter(Badge::searchTerms), + Codec.BOOL.optionalFieldOf("library", false).forGetter(Badge::library) ).apply(instance, Badge::new)); public Component getText() { diff --git a/src/main/resources/assets/modmenu/modmenu/badge/library.json b/src/main/resources/assets/modmenu/modmenu/badge/library.json index 0388d02a7..18633f072 100644 --- a/src/main/resources/assets/modmenu/modmenu/badge/library.json +++ b/src/main/resources/assets/modmenu/modmenu/badge/library.json @@ -4,5 +4,6 @@ }, "outline_color": "#FF107454", "fill_color": "#FF093929", - "search_terms": "modmenu.searchTerms.library" + "search_terms": "modmenu.searchTerms.library", + "library": true } \ No newline at end of file