🧠 State Persistence & JSON Configuration
| Parameter | Specification |
|---|---|
| Config Manager Class | net.instantgratification.collapsiblegamerules.GameRuleStateConfig |
| File Location | .minecraft/config/collapsible-game-rules-state.json |
| Storage Structure | Set<String> expandedCategories = new HashSet<>() |
| Serialization Engine | com.google.gson.Gson (Pretty-Printing Enabled) |
| I/O Throttling Flag | private static boolean isDirty = false |
| Flush Hook | ScreenMixin targeting Screen.removed() (@At("HEAD")) |
| Persistence Key Strategy | Localization Key (TranslatableContents.getKey()) or Literal String |
📖 Overview
Collapsible Game Rules features an asynchronous, throttled state persistence engine. Rather than resetting to default expansion states every time a world or menu is opened, the mod remembers the exact categories you have expanded or collapsed across restarts.
📄 JSON Configuration Format
The state is stored in a clean, human-readable JSON array inside .minecraft/config/collapsible-game-rules-state.json:
[
"gamerule.category.spawning",
"gamerule.category.mobs",
"gamerule.category.updates"
]- Presence in Array: Indicates that the category is currently EXPANDED.
- Absence from Array: Indicates that the category is currently COLLAPSED (default state).
⚡ High-Performance I/O Throttling Architecture
Writing to disk on every mouse click or keyboard toggle creates unnecessary disk I/O and micro-stutter when players rapidly expand or collapse multiple categories.
To ensure zero frame drops, GameRuleStateConfig uses an isDirty state flag:
┌─────────────────────────────────────────────────────────────────────────────┐
│ THROTTLED PERSISTENCE WORKFLOW │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Player clicks Category Header │
│ │ │
│ ▼ │
│ GameRuleStateConfig.setExpanded(key, state) │
│ ├─ Updates in-memory HashSet<String> in 0.0001 μs │
│ └─ Marks: isDirty = true (ZERO DISK I/O) │
│ │
│ Player closes Game Rules Screen (Esc, Done, or Cancel) │
│ │ │
│ ▼ │
│ ScreenMixin.collapsible_game_rules$onRemoved() │
│ │ │
│ ▼ │
│ GameRuleStateConfig.saveIfDirty() │
│ ├─ Checks: if (isDirty) { ... } │
│ ├─ Writes JSON to disk in background buffer │
│ └─ Resets: isDirty = false │
│ │
└─────────────────────────────────────────────────────────────────────────────┘💻 API & Method Reference
GameRuleStateConfig Public Methods
| Method Signature | Return Type | Description |
|---|---|---|
load() | void | Reads collapsible-game-rules-state.json on client startup (CollapsibleGameRulesFabricClient). |
save() | void | Flushes the current expandedCategories set to disk via Files.newBufferedWriter. |
saveIfDirty() | void | Saves to disk only if isDirty == true, then resets isDirty = false. |
isExpanded(String categoryKey) | boolean | Checks if the given translation key is present in expandedCategories. |
setExpanded(String categoryKey, boolean expanded) | void | Adds or removes the key from the set and sets isDirty = true if modified. |
expandAll(Iterable<String> allKeys) | void | Adds all provided keys to the set in bulk and marks isDirty = true. |
collapseAll() | void | Clears all entries from expandedCategories and marks isDirty = true. |
🔒 Screen Removal Mixin Integration
State saving is hooked directly into Minecraft's base Screen.removed() method via ScreenMixin.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();
}
}
}This guarantees that whenever the player exits the screen—whether by clicking Done, Cancel, or pressing Escape—all modifications are safely preserved.
