🧩 Архитектура и подсистема Mixin
| Параметр | Спецификация |
|---|---|
| Файл конфигурации Mixin | src/main/resources/collapsible-game-rules.mixins.json |
| Идентификатор Refmap | collapsible-game-rules-refmap.json |
| Уровень совместимости | JAVA_25 |
| Default Require | 1 |
| Корневой пакет | net.instantgratification.collapsiblegamerules |
| Пакет миксинов | net.instantgratification.collapsiblegamerules.mixin |
| Всего миксинов | 4 клиентских миксина (3 инжектора + 1 интерфейсный аксессор) |
📖 Архитектура пакетов системы
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🔍 Подробный разбор миксинов
1. AbstractGameRulesScreenRuleListMixin
- Целевой класс:
net.minecraft.client.gui.screens.worldselection.AbstractGameRulesScreen.RuleList.class - Иерархия: Расширяет
ContainerObjectSelectionList<AbstractGameRulesScreen.RuleEntry> - Назначение: Главный контроллер интерфейса. Перехватывает заполнение списка, считает количество правил в категориях, фильтрует отображение по состоянию развертывания и рендерит интерактивные заголовки.
java
@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
- Целевой класс:
net.minecraft.client.gui.screens.worldselection.AbstractGameRulesScreen.CategoryRuleEntry.class - Назначение: Обеспечивает доступ к приватному полю
Component labelванильных категорий на уровне байткода.
java
@Mixin(AbstractGameRulesScreen.CategoryRuleEntry.class)
public interface CategoryRuleEntryAccessor {
@Accessor("label")
Component collapsible_game_rules$getLabel();
}3. ScreenMixin
- Целевой класс:
net.minecraft.client.gui.screens.Screen.class - Назначение: Отслеживает закрытие экрана. При выходе из
AbstractGameRulesScreenсохраняет изменения на диск черезGameRuleStateConfig.saveIfDirty().
java
@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
- Целевой класс:
net.minecraft.client.gui.screens.worldselection.AbstractGameRulesScreen.IntegerRuleEntry.class - Назначение: Предоставляет абстрактный мост к ванильным числовым полям для подключения кастомных слайдеров.
java
@Mixin(AbstractGameRulesScreen.IntegerRuleEntry.class)
public abstract class IntegerRuleEntryMixin extends AbstractGameRulesScreen.RuleEntry {
public IntegerRuleEntryMixin() {
super(null);
}
}📜 Конфигурация Mixin (collapsible-game-rules.mixins.json)
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
}
}