From aac3b152f19ba23b09add9f186f1b7ef477ab061 Mon Sep 17 00:00:00 2001 From: ASKLL Date: Fri, 23 Oct 2026 23:36:44 +0800 Subject: [PATCH] feat: group OneConfig subconfigs by category --- gradle.properties | 2 +- .../mixin/oneconfig/ModsPageMixin.java | 121 ++++++++++++++++++ .../mixin/oneconfig/SubModsPageMixin.java | 63 +++++++++ .../platform/oneconfig/OneConfigAdapter.java | 4 +- .../pit12/runtime/config/ConfigCategory.java | 4 + src/main/resources/mixins.pit12.json | 2 + 6 files changed, 193 insertions(+), 3 deletions(-) create mode 100644 src/main/java/pit12/platform/mixin/oneconfig/ModsPageMixin.java create mode 100644 src/main/java/pit12/platform/mixin/oneconfig/SubModsPageMixin.java diff --git a/gradle.properties b/gradle.properties index 1d4ee58d..5aaf3dec 100644 --- a/gradle.properties +++ b/gradle.properties @@ -34,4 +34,4 @@ mixinRuntimeVersion=0.7.11-SNAPSHOT mixinProcessorVersion=0.8.5-SNAPSHOT devAuthVersion=1.2.2 archUnitVersion=1.5.0 -oneConfigVersion=0.2.2-alpha228 +oneConfigVersion=0.2.2-alpha230 diff --git a/src/main/java/pit12/platform/mixin/oneconfig/ModsPageMixin.java b/src/main/java/pit12/platform/mixin/oneconfig/ModsPageMixin.java new file mode 100644 index 00000000..ba10ee29 --- /dev/null +++ b/src/main/java/pit12/platform/mixin/oneconfig/ModsPageMixin.java @@ -0,0 +1,121 @@ +/* + * This file is part of 12pit. + * + * Copyright (C) 2026 The 12pit Authors and contributors + * + * 12pit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * 12pit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 12pit. If not, see . + */ +package pit12.platform.mixin.oneconfig; + +import cc.polyfrost.oneconfig.config.data.Mod; +import cc.polyfrost.oneconfig.gui.elements.BasicButton; +import cc.polyfrost.oneconfig.gui.elements.ModCard; +import cc.polyfrost.oneconfig.gui.pages.ModsPage; +import cc.polyfrost.oneconfig.gui.pages.SubModsPage; +import cc.polyfrost.oneconfig.internal.config.core.ConfigCore; +import cc.polyfrost.oneconfig.renderer.NanoVGHelper; +import cc.polyfrost.oneconfig.renderer.font.Fonts; +import cc.polyfrost.oneconfig.utils.InputHandler; +import cc.polyfrost.oneconfig.utils.color.ColorPalette; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.Map; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import pit12.platform.oneconfig.OneConfigAdapter; +import pit12.runtime.config.ConfigCategory; + +@Pseudo +@Mixin(targets = "cc.polyfrost.oneconfig.gui.pages.ModsPage", remap = false) +public abstract class ModsPageMixin { + @Shadow + @Final + private ArrayList modCategories; + @Unique + private Map pit12$featureCategories; + + @Shadow + private void unselect(int index) {} + + @Inject(method = "reloadMods", at = @At("TAIL"), remap = false) + private void pit12$addFeatureCategories(CallbackInfo callback) { + if (pit12$featureCategories != null || !((Object) this instanceof SubModsPage)) { + return; + } + Mod parent = ((SubModsPage) (Object) this).parentMod; + // SubModsPage assigns its parent after the first reload. + if (parent == null || !(parent.config instanceof OneConfigAdapter.RootView)) { + return; + } + pit12$featureCategories = new LinkedHashMap<>(); + modCategories.subList(1, modCategories.size()).clear(); + for (Mod mod : ConfigCore.subMods.get(parent)) { + ConfigCategory category = ((OneConfigAdapter.View) mod.config).feature.category(); + if (category == null || pit12$featureCategories.containsKey(category.id())) { + continue; + } + BasicButton button = + new BasicButton(0, BasicButton.SIZE_32, category.originalDisplayName(), + BasicButton.ALIGNMENT_CENTER, ColorPalette.SECONDARY); + button.setToggleable(true); + modCategories.add(button); + pit12$featureCategories.put(category.id(), button); + } + for (int index = 0; index < modCategories.size(); index++) { + int selected = index; + modCategories.get(index).setClickAction(() -> { + unselect(selected); + ((ModsPage) (Object) this).finishUpAndClose(); + }); + } + } + + @Inject(method = "drawStatic", at = @At("HEAD"), remap = false) + private void pit12$sizeFeatureCategories(long vg, int x, int y, InputHandler inputHandler, + CallbackInfoReturnable callback) { + if (pit12$featureCategories == null) { + return; + } + for (BasicButton button : pit12$featureCategories.values()) { + if (button.getWidth() == 0) { + button.setWidth((int) Math.ceil( + NanoVGHelper.INSTANCE.getTextWidth(vg, button.getText(), 12f, Fonts.MEDIUM)) + + 24); + } + } + } + + @Inject(method = "inSelection", at = @At("HEAD"), cancellable = true, remap = false) + private void pit12$filterFeatureCategory(ModCard card, + CallbackInfoReturnable callback) { + if (pit12$featureCategories == null) { + return; + } + if (modCategories.get(0).isToggled()) { + callback.setReturnValue(true); + return; + } + ConfigCategory category = + ((OneConfigAdapter.View) card.getModData().config).feature.category(); + BasicButton button = category == null ? null : pit12$featureCategories.get(category.id()); + callback.setReturnValue(button != null && button.isToggled()); + } +} diff --git a/src/main/java/pit12/platform/mixin/oneconfig/SubModsPageMixin.java b/src/main/java/pit12/platform/mixin/oneconfig/SubModsPageMixin.java new file mode 100644 index 00000000..770c5a55 --- /dev/null +++ b/src/main/java/pit12/platform/mixin/oneconfig/SubModsPageMixin.java @@ -0,0 +1,63 @@ +/* + * This file is part of 12pit. + * + * Copyright (C) 2026 The 12pit Authors and contributors + * + * 12pit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * 12pit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 12pit. If not, see . + */ +package pit12.platform.mixin.oneconfig; + +import cc.polyfrost.oneconfig.config.data.Mod; +import cc.polyfrost.oneconfig.gui.pages.ModsPage; +import cc.polyfrost.oneconfig.utils.InputHandler; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import pit12.platform.oneconfig.OneConfigAdapter; + +@Pseudo +@Mixin(targets = "cc.polyfrost.oneconfig.gui.pages.SubModsPage", remap = false) +public abstract class SubModsPageMixin extends ModsPage { + @Shadow + public Mod parentMod; + + // SubModsPage hides the category bar that ModsPage already draws. + @Inject(method = "draw", at = @At("HEAD"), cancellable = true, remap = false) + private void pit12$drawFeatureCards(long vg, int x, int y, InputHandler inputHandler, + CallbackInfo callback) { + if (parentMod.config instanceof OneConfigAdapter.RootView) { + super.draw(vg, x, y, inputHandler); + callback.cancel(); + } + } + + @Inject(method = "drawStatic", at = @At("HEAD"), cancellable = true, remap = false) + private void pit12$drawFeatureCategories(long vg, int x, int y, InputHandler inputHandler, + CallbackInfoReturnable callback) { + if (parentMod.config instanceof OneConfigAdapter.RootView) { + callback.setReturnValue(super.drawStatic(vg, x, y, inputHandler)); + } + } + + @Inject(method = "getMaxScrollHeight", at = @At("HEAD"), cancellable = true, remap = false) + private void pit12$featureScrollHeight(CallbackInfoReturnable callback) { + if (parentMod.config instanceof OneConfigAdapter.RootView) { + callback.setReturnValue(super.getMaxScrollHeight()); + } + } +} diff --git a/src/main/java/pit12/platform/oneconfig/OneConfigAdapter.java b/src/main/java/pit12/platform/oneconfig/OneConfigAdapter.java index 312af9a6..686ec54e 100644 --- a/src/main/java/pit12/platform/oneconfig/OneConfigAdapter.java +++ b/src/main/java/pit12/platform/oneconfig/OneConfigAdapter.java @@ -127,7 +127,7 @@ private void buildPage(View target, FeatureConfig feature) { } // OneConfig hides SubConfig from the main list. This one needs to stay visible. - private static final class RootView extends Config { + public static final class RootView extends Config { RootView() { super(new Mod("12pit", ModType.HYPIXEL), "pit12-oneconfig-view/root.json", true, false); initialize(); @@ -153,7 +153,7 @@ public boolean supportsProfiles() { } } public static final class View extends SubConfig { - private final FeatureConfig feature; + public final FeatureConfig feature; View(FeatureConfig feature) { super(feature.originalDisplayName(), "pit12-oneconfig-view/" + feature.id() + ".json", diff --git a/src/main/java/pit12/runtime/config/ConfigCategory.java b/src/main/java/pit12/runtime/config/ConfigCategory.java index 8133d595..adf576fc 100644 --- a/src/main/java/pit12/runtime/config/ConfigCategory.java +++ b/src/main/java/pit12/runtime/config/ConfigCategory.java @@ -42,4 +42,8 @@ public String id() { public String displayName() { return displayName; } + + public String originalDisplayName() { + return originalDisplayName; + } } diff --git a/src/main/resources/mixins.pit12.json b/src/main/resources/mixins.pit12.json index 02460ade..14751b07 100644 --- a/src/main/resources/mixins.pit12.json +++ b/src/main/resources/mixins.pit12.json @@ -17,6 +17,8 @@ "network.NetworkPlayerInfoMixin", "projectile.EntityArrowMixin", "oneconfig.ModCardMixin", + "oneconfig.ModsPageMixin", + "oneconfig.SubModsPageMixin", "patcher.FontRendererHookMixin", "scoreboard.ScoreboardMixin", "world.WorldClientMixin",