From 132b36bb9367658a0d551aa59ebdc2f1b8a0b317 Mon Sep 17 00:00:00 2001 From: yueh Date: Wed, 1 Oct 2014 16:02:24 +0200 Subject: [PATCH] Optimizes the search in interface terminals Removed the amount of data by only searching the output names Added a caching layer so every subsequent search will narrow the previous one down and not search everything again --- .../implementations/GuiInterfaceTerminal.java | 74 +++++++++++++++++-- 1 file changed, 69 insertions(+), 5 deletions(-) diff --git a/src/main/java/appeng/client/gui/implementations/GuiInterfaceTerminal.java b/src/main/java/appeng/client/gui/implementations/GuiInterfaceTerminal.java index 1220a5f74..a1f6aa4b2 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiInterfaceTerminal.java +++ b/src/main/java/appeng/client/gui/implementations/GuiInterfaceTerminal.java @@ -3,7 +3,11 @@ package appeng.client.gui.implementations; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; @@ -12,6 +16,7 @@ import net.minecraft.nbt.NBTTagCompound; import org.lwjgl.opengl.GL11; +import appeng.api.storage.data.IAEItemStack; import appeng.client.gui.AEBaseGui; import appeng.client.gui.widgets.GuiScrollbar; import appeng.client.gui.widgets.MEGuiTextField; @@ -19,7 +24,9 @@ import appeng.client.me.ClientDCInternalInv; import appeng.client.me.SlotDisconnected; import appeng.container.implementations.ContainerInterfaceTerminal; import appeng.core.localization.GuiText; +import appeng.helpers.PatternHelper; import appeng.parts.reporting.PartMonitor; +import appeng.util.Platform; import com.google.common.collect.HashMultimap; @@ -37,6 +44,8 @@ public class GuiInterfaceTerminal extends AEBaseGui private final ArrayList lines = new ArrayList(); private final EntityPlayer player; + private final Map> cachedSearches = new WeakHashMap>(); + private boolean refreshList = false; private MEGuiTextField searchField; @@ -204,12 +213,14 @@ public class GuiInterfaceTerminal extends AEBaseGui if ( refreshList ) { refreshList = false; + // invalid caches on refresh + cachedSearches.clear(); refreshList(); } } /** - * rebuilds the list of interfaces. + * Rebuilds the list of interfaces. * * Respects a search term if present (ignores case) and adding only matching patterns. */ @@ -219,11 +230,19 @@ public class GuiInterfaceTerminal extends AEBaseGui final String searchFilterLowerCase = searchField.getText().toLowerCase(); + final Set cachedSearch = this.getCacheForSearchTerm( searchFilterLowerCase ); + final boolean rebuild = cachedSearch.isEmpty(); + for (ClientDCInternalInv entry : byId.values()) { + // ignore inventory if not doing a full rebuild or cache already marks it as miss. + if ( !rebuild && !cachedSearch.contains( entry ) ) + continue; + // Shortcut to skip any filter if search term is ""/empty boolean found = searchFilterLowerCase.isEmpty(); + // Search if the current inventory holds a pattern containing the search term. if ( !found && !searchFilterLowerCase.equals( "" ) ) { @@ -231,11 +250,15 @@ public class GuiInterfaceTerminal extends AEBaseGui { if ( itemStack != null ) { - String tooltipLowerCase = String.valueOf( itemStack.getTooltip( player, false ) ).toLowerCase(); - if ( tooltipLowerCase.contains( searchFilterLowerCase ) ) + final PatternHelper ph = new PatternHelper( itemStack, player.worldObj ); + final IAEItemStack[] output = ph.getCondensedOutputs(); + for (IAEItemStack iaeItemStack : output) { - found = true; - break; + if ( Platform.getItemDisplayName( iaeItemStack ).toLowerCase().contains( searchFilterLowerCase ) ) + { + found = true; + break; + } } } } @@ -243,7 +266,14 @@ public class GuiInterfaceTerminal extends AEBaseGui // if found, filter skipped or machine name matching the search term, add it if ( found || entry.getName().toLowerCase().contains( searchFilterLowerCase ) ) + { byName.put( entry.getName(), entry ); + cachedSearch.add( entry ); + } + else + { + cachedSearch.remove( entry ); + } } names.clear(); @@ -268,6 +298,40 @@ public class GuiInterfaceTerminal extends AEBaseGui myScrollBar.setRange( 0, lines.size() - LINES_ON_PAGE, 2 ); } + /** + * Tries to retrieve a cache for a with search term as keyword. + * + * If this cache should be empty, it will populate it with an earlier cache if available or at least the cache for + * the empty string. + * + * @param searchTerm + * the corresponding search + * @return a Set matching a superset of the search term + */ + private Set getCacheForSearchTerm(String searchTerm) + { + if ( !cachedSearches.containsKey( searchTerm ) ) + { + cachedSearches.put( searchTerm, new HashSet() ); + } + + Set cache = cachedSearches.get( searchTerm ); + + if ( cache.isEmpty() ) + { + if ( searchTerm.length() > 1 && cachedSearches.containsKey( searchTerm.substring( 0, searchTerm.length() - 1 ) ) ) + { + cache.addAll( cachedSearches.get( searchTerm.substring( 0, searchTerm.length() - 1 ) ) ); + } + else + { + cache.addAll( cachedSearches.get( "" ) ); + } + } + + return cache; + } + /** * The max amount of unique names and each inv row. Not affected by the filtering. *