Skip to content

26.2 Smart Search Integration

Rifa edited this page Aug 21, 2026 · 1 revision

🔍 Smart Search Integration

Parameter Specification
Intercepted Method populateChildren(Ljava/lang/String;)V
Injection Point @At("TAIL")
Mixin Class AbstractGameRulesScreenRuleListMixin
Query Normalization filter.toLowerCase(java.util.Locale.ROOT)
Active Query Flag isSearching = !currentFilter.isEmpty()
Dynamic State Rule `isExpanded = isSearching
Rebuild Method collapsible_game_rules$updateVisibleEntries()

📖 Overview

In vanilla Minecraft, the Game Rules search bar filters the rule list by matching rule names or descriptions against player input. In a collapsible interface, a naive implementation would risk hiding matching rules inside closed category folders.

Smart Search Integration solves this problem by monitoring search query changes in real time. Whenever a search query is active, any category containing a matching rule automatically expands, displaying the search results immediately without requiring extra clicks.


⚙️ How Smart Search Works

┌─────────────────────────────────────────────────────────────────────────────┐
│                          SMART SEARCH PIPELINE                              │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   Player types query into Search Bar (e.g. "fire")                          │
│        │                                                                    │
│        ▼                                                                    │
│   Vanilla AbstractGameRulesScreen.RuleList.populateChildren("fire")         │
│   (Filters the internal list to matching rules & their category headers)    │
│        │                                                                    │
│        ▼ (@Inject at TAIL)                                                  │
│   AbstractGameRulesScreenRuleListMixin.collapsible_game_rules$onPopulate... │
│        ├─ Stores normalized query: filter.toLowerCase(Locale.ROOT)          │
│        ├─ Captures filtered list: allEntries = new ArrayList<>(children())  │
│        └─ Calls updateVisibleEntries()                                      │
│             │                                                               │
│             ▼                                                               │
│        isSearching = !currentFilter.isEmpty() (Evaluates to TRUE)           │
│             │                                                               │
│             ▼                                                               │
│        Every present category header is forced isExpanded = TRUE            │
│        All matched child rules render immediately!                          │
│                                                                             │
│   Player clears Search Bar ("")                                             │
│        │                                                                    │
│        ▼                                                                    │
│   isSearching = FALSE ──> Reverts to persistent GameRuleStateConfig states! │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

💻 Technical Implementation Details

1. The @Inject Hook

The mixin intercepts the conclusion of vanilla's populateChildren method:

@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) : "";
    // Save the currently generated list of all entries
    this.collapsible_game_rules$allEntries = new ArrayList<>(this.children());
    this.collapsible_game_rules$updateVisibleEntries();
}

2. Search-Driven Expansion Evaluation

Inside updateVisibleEntries(), the expansion state is computed dynamically:

boolean isSearching = !this.collapsible_game_rules$currentFilter.isEmpty();
final String finalPersistenceKey = persistenceKey;
boolean isExpanded = isSearching || GameRuleStateConfig.isExpanded(finalPersistenceKey);

3. Non-Destructive State Recovery

Because isSearching is an ephemeral condition evaluated only during active filtering, clearing the search box immediately restores each category's exact manual collapse state from GameRuleStateConfig without overwriting the player's saved preferences on disk.


🔗 Related Documentation

Clone this wiki locally