Skip to content

26.2 Architecture and Mixins

Rifa edited this page Aug 21, 2026 · 1 revision

๐Ÿงฉ Architecture & Mixin Subsystem

Parameter Specification
Mixin Configuration src/main/resources/collapsible-game-rules.mixins.json
Refmap Identifier collapsible-game-rules-refmap.json
Compatibility Level JAVA_25
Default Require 1
Root Package net.instantgratification.collapsiblegamerules
Mixin Package net.instantgratification.collapsiblegamerules.mixin
Total Mixins 4 Client Mixins (3 Class Injectors + 1 Interface Accessor)

๐Ÿ“– System Package Architecture

net.instantgratification.collapsiblegamerules
โ”œโ”€โ”€ CollapsibleGameRulesFabric.java           โ”€โ”€> Main ModInitializer (Guard & Hard Dependency check)
โ”œโ”€โ”€ CollapsibleGameRulesFabricClient.java     โ”€โ”€> ClientModInitializer (Loads GameRuleStateConfig)
โ”œโ”€โ”€ GameRuleStateConfig.java                  โ”€โ”€> Config & JSON state persistence (Set<String>)
โ”œโ”€โ”€ mixin
โ”‚   โ”œโ”€โ”€ AbstractGameRulesScreenRuleListMixin.java โ”€โ”€> Core engine (List interception, CollapsibleCategoryRuleEntry)
โ”‚   โ”œโ”€โ”€ CategoryRuleEntryAccessor.java        โ”€โ”€> Interface Accessor for category Component label
โ”‚   โ”œโ”€โ”€ IntegerRuleEntryMixin.java            โ”€โ”€> Abstract wrapper for integer rule entries
โ”‚   โ””โ”€โ”€ ScreenMixin.java                      โ”€โ”€> Intercepts Screen.removed() to flush pending state
โ”œโ”€โ”€ preset
โ”‚   โ””โ”€โ”€ GameRulePresetEngine.java             โ”€โ”€> Built-in preset definitions (Builder, Fast Play, Hardcore)
โ”œโ”€โ”€ ui
โ”‚   โ”œโ”€โ”€ BooleanToggleWidget.java              โ”€โ”€> Interactive emerald green / ruby red toggle switch
โ”‚   โ”œโ”€โ”€ GlobalActionsRuleEntry.java           โ”€โ”€> Pinned index 0 bulk toggle header ([ Expand ] / [ Collapse ])
โ”‚   โ””โ”€โ”€ IntegerSliderWidget.java              โ”€โ”€> Draggable numeric slider with math normalization
โ””โ”€โ”€ util
    โ”œโ”€โ”€ CategoryPrettifier.java               โ”€โ”€> Regex & string parser for unlocalized category keys
    โ”œโ”€โ”€ DasikMetadataHelper.java              โ”€โ”€> Lazy-loaded isolation layer querying DasikLibrary
    โ”œโ”€โ”€ GameRuleSliderHelper.java             โ”€โ”€> Vanilla integer rule bounds and default values
    โ””โ”€โ”€ ModVersionGuard.java                  โ”€โ”€> Zero-dependency runtime Knot ClassLoader integrity check

๐Ÿ” Complete Mixin Target Breakdown

1. AbstractGameRulesScreenRuleListMixin

  • Target Class: net.minecraft.client.gui.screens.worldselection.AbstractGameRulesScreen.RuleList.class
  • Hierarchy: Extends ContainerObjectSelectionList<AbstractGameRulesScreen.RuleEntry>
  • Role: Primary UI controller. Intercepts list population, calculates child count per category, filters visible entries based on expansion states, and renders custom interactive category headers.
@Mixin(AbstractGameRulesScreen.RuleList.class)
public abstract class AbstractGameRulesScreenRuleListMixin
        extends ContainerObjectSelectionList<AbstractGameRulesScreen.RuleEntry> {

    @Unique
    private List<AbstractGameRulesScreen.RuleEntry> collapsible_game_rules$allEntries = new ArrayList<>();

    @Unique
    private String collapsible_game_rules$currentFilter = "";

    @Inject(method = "populateChildren(Ljava/lang/String;)V", at = @At("TAIL"))
    private void collapsible_game_rules$onPopulateChildren(String filter, CallbackInfo ci) {
        this.collapsible_game_rules$currentFilter = (filter != null) ? filter.toLowerCase(java.util.Locale.ROOT) : "";
        this.collapsible_game_rules$allEntries = new ArrayList<>(this.children());
        this.collapsible_game_rules$updateVisibleEntries();
    }
}

2. CategoryRuleEntryAccessor

  • Target Class: net.minecraft.client.gui.screens.worldselection.AbstractGameRulesScreen.CategoryRuleEntry.class
  • Role: Provides direct bytecode accessor to the private Component label field of vanilla category entries.
@Mixin(AbstractGameRulesScreen.CategoryRuleEntry.class)
public interface CategoryRuleEntryAccessor {
    @Accessor("label")
    Component collapsible_game_rules$getLabel();
}

3. ScreenMixin

  • Target Class: net.minecraft.client.gui.screens.Screen.class
  • Role: Listens for screen removal. Whenever AbstractGameRulesScreen is closed, flushes pending state modifications to disk via GameRuleStateConfig.saveIfDirty().
@Mixin(Screen.class)
public abstract class ScreenMixin {

    @Inject(method = "removed", at = @At("HEAD"))
    private void collapsible_game_rules$onRemoved(CallbackInfo ci) {
        if ((Object) this instanceof AbstractGameRulesScreen) {
            GameRuleStateConfig.saveIfDirty();
        }
    }
}

4. IntegerRuleEntryMixin

  • Target Class: net.minecraft.client.gui.screens.worldselection.AbstractGameRulesScreen.IntegerRuleEntry.class
  • Role: Provides an abstract bridge into vanilla integer rule entries for specialized widget integration.
@Mixin(AbstractGameRulesScreen.IntegerRuleEntry.class)
public abstract class IntegerRuleEntryMixin extends AbstractGameRulesScreen.RuleEntry {
    public IntegerRuleEntryMixin() {
        super(null);
    }
}

๐Ÿ“œ Mixin Configuration File (collapsible-game-rules.mixins.json)

{
    "required": true,
    "package": "net.instantgratification.collapsiblegamerules.mixin",
    "refmap": "collapsible-game-rules-refmap.json",
    "compatibilityLevel": "JAVA_25",
    "client": [
        "ScreenMixin",
        "AbstractGameRulesScreenRuleListMixin",
        "CategoryRuleEntryAccessor",
        "IntegerRuleEntryMixin"
    ],
    "injectors": {
        "defaultRequire": 1
    }
}

๐Ÿ”— Related Documentation

Clone this wiki locally