Compare commits

...
7 Commits
Author SHA1 Message Date
Caedis ccab231318 Fix NPE in ItemsTooltipLineHandler (#589)
(cherry picked from commit fd08a93554)
2025-02-23 17:12:07 +01:00
Glease 0f9df94b8a fix memory leak fixes not working for MP (#590)
#258 addresses the memory leak in ItemMobSpawner. Unfortunately the clean up handler is not consistently called on every world unloaded. This PR fixes this issue by moving the call out of that if block
2025-02-04 11:16:17 +01:00
slprimeandslprime ebfd588d39 Fixed NEI reload when changing dimension (#583)
Co-authored-by: slprime <[email protected]>
2025-02-04 11:14:47 +01:00
d72bb9a1b4 Add Space Mode Settings to Search (#571)
Co-authored-by: slprime <[email protected]>
Co-authored-by: boubou19 <[email protected]>
2024-12-23 11:24:33 +01:00
Martin Robertz 23ea7e7d04 update
(cherry picked from commit 7ac3e32635)
2024-12-17 20:37:22 +01:00
Martin Robertz 6a8da78476 update
(cherry picked from commit 088d37a11a)
2024-12-17 20:37:15 +01:00
slprime 36c80863c6 Clear Search Filter Cache after Change Settings (#569)
(cherry picked from commit 6a787dd5b7)
2024-12-17 20:37:09 +01:00
15 changed files with 303 additions and 155 deletions

No files matched your search

Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
+1 -1
View File
@@ -17,7 +17,7 @@ pluginManagement {
}
plugins {
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.29'
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.30'
}
@@ -325,9 +325,8 @@ public class ClientHandler {
if (!Minecraft.getMinecraft().isSingleplayer()) // wait for server to initiate in singleplayer
NEIClientConfig.loadWorld("remote/" + ClientUtils.getServerIP().replace(':', '~'));
ItemMobSpawner.clearEntityReferences(world);
}
ItemMobSpawner.clearEntityReferences(world);
lastworld = world;
}
@@ -123,6 +123,8 @@ public class ItemsTooltipLineHandler implements ITooltipLineHandler {
for (ItemStack stack : items) {
final NBTTagCompound nbTag = StackInfo.itemStackToNBT(stack, true);
if (nbTag == null) continue;
final String GUID = StackInfo.getItemStackGUID(stack);
if (!unique.containsKey(GUID)) {
@@ -432,7 +432,15 @@ public class NEIClientConfig {
API.addOption(new OptionCycled("inventory.search.widgetAutofocus", 3, true));
tag.getTag("inventory.search.patternMode").setComment("Search Mode").getIntValue(1);
API.addOption(new OptionCycled("inventory.search.patternMode", 3, true));
API.addOption(new OptionCycled("inventory.search.patternMode", 3, true) {
@Override
public boolean onClick(int button) {
SearchField.searchParser.clearCache();
return super.onClick(button);
}
});
tag.getTag("inventory.search.quoteDropItemName").setComment("Quote Drop Item Name").getBooleanValue(true);
API.addOption(new OptionToggleButton("inventory.search.quoteDropItemName", true));
@@ -449,6 +457,7 @@ public class NEIClientConfig {
}
if (state()) {
NEIClientConfig.setIntSetting("inventory.search.spaceMode", 1);
NEIClientConfig.setIntSetting("inventory.search.modNameSearchMode", 0);
NEIClientConfig.setIntSetting("inventory.search.tooltipSearchMode", 0);
NEIClientConfig.setIntSetting("inventory.search.identifierSearchMode", 0);
@@ -458,7 +467,9 @@ public class NEIClientConfig {
SearchField.searchParser.prefixRedefinitions.clear();
SearchField.searchParser.prefixRedefinitions.put('%', '@');
SearchField.searchParser.prefixRedefinitions.put('@', '%');
SearchField.searchParser.clearCache();
} else {
NEIClientConfig.setIntSetting("inventory.search.spaceMode", 0);
NEIClientConfig.setIntSetting("inventory.search.modNameSearchMode", 1);
NEIClientConfig.setIntSetting("inventory.search.tooltipSearchMode", 0);
NEIClientConfig.setIntSetting("inventory.search.identifierSearchMode", 0);
@@ -466,6 +477,7 @@ public class NEIClientConfig {
NEIClientConfig.setIntSetting("inventory.search.subsetsSearchMode", 1);
tag.getTag("inventory.search.prefixRedefinitions").setValue("{}");
SearchField.searchParser.prefixRedefinitions.clear();
SearchField.searchParser.clearCache();
}
return true;
@@ -473,10 +485,32 @@ public class NEIClientConfig {
});
tag.getTag("inventory.search.spaceMode").setComment("Search Space Rules").getIntValue(0);
API.addOption(new OptionCycled("inventory.search.spaceMode", 3, true) {
@Override
public boolean onClick(int button) {
// SearchField.searchParser.clearCache();
return super.onClick(button);
}
@Override
public boolean isEnabled() {
return !tag.getTag("inventory.search.format").getBooleanValue();
}
});
tag.getTag("inventory.search.modNameSearchMode").setComment("Search mode for Mod Names (prefix: @)")
.getIntValue(1);
API.addOption(new OptionCycled("inventory.search.modNameSearchMode", 3, true) {
@Override
public boolean onClick(int button) {
SearchField.searchParser.clearCache();
return super.onClick(button);
}
@Override
public String getButtonText() {
return translateN(
@@ -496,6 +530,12 @@ public class NEIClientConfig {
.getIntValue(0);
API.addOption(new OptionCycled("inventory.search.tooltipSearchMode", 3, true) {
@Override
public boolean onClick(int button) {
SearchField.searchParser.clearCache();
return super.onClick(button);
}
@Override
public String getButtonText() {
return translateN(
@@ -514,6 +554,12 @@ public class NEIClientConfig {
.getIntValue(0);
API.addOption(new OptionCycled("inventory.search.identifierSearchMode", 3, true) {
@Override
public boolean onClick(int button) {
SearchField.searchParser.clearCache();
return super.onClick(button);
}
@Override
public String getButtonText() {
return translateN(
@@ -532,6 +578,12 @@ public class NEIClientConfig {
.getIntValue(0);
API.addOption(new OptionCycled("inventory.search.oreDictSearchMode", 3, true) {
@Override
public boolean onClick(int button) {
SearchField.searchParser.clearCache();
return super.onClick(button);
}
@Override
public String getButtonText() {
return translateN(
@@ -550,6 +602,12 @@ public class NEIClientConfig {
.getIntValue(1);
API.addOption(new OptionCycled("inventory.search.subsetsSearchMode", 3, true) {
@Override
public boolean onClick(int button) {
SearchField.searchParser.clearCache();
return super.onClick(button);
}
@Override
public String getButtonText() {
return translateN(
@@ -637,23 +695,25 @@ public class NEIClientConfig {
public static void loadWorld(String worldPath) {
unloadWorld();
NEIClientConfig.worldPath = worldPath;
setInternalEnabled(true);
logger.debug("Loading " + (Minecraft.getMinecraft().isSingleplayer() ? "Local" : "Remote") + " World");
final File specificDir = new File(CommonUtils.getMinecraftDir(), "saves/NEI/" + worldPath);
final boolean newWorld = !specificDir.exists();
if (!worldPath.equals(NEIClientConfig.worldPath)) {
NEIClientConfig.worldPath = worldPath;
if (newWorld) {
specificDir.mkdirs();
logger.debug("Loading " + (Minecraft.getMinecraft().isSingleplayer() ? "Local" : "Remote") + " World");
final File specificDir = new File(CommonUtils.getMinecraftDir(), "saves/NEI/" + worldPath);
final boolean newWorld = !specificDir.exists();
if (newWorld) {
specificDir.mkdirs();
}
world = new ConfigSet(new File(specificDir, "NEI.dat"), new ConfigFile(new File(specificDir, "NEI.cfg")));
bootNEI(ClientUtils.getWorld());
onWorldLoad(newWorld);
ItemPanels.bookmarkPanel.load();
}
world = new ConfigSet(new File(specificDir, "NEI.dat"), new ConfigFile(new File(specificDir, "NEI.cfg")));
bootNEI(ClientUtils.getWorld());
CollapsibleItems.load();
ItemPanels.bookmarkPanel.load();
onWorldLoad(newWorld);
}
public static String getWorldPath() {
@@ -668,7 +728,6 @@ public class NEIClientConfig {
creativeInv = new ItemStack[54];
LayoutManager.searchField.setText(getSearchExpression());
ItemPanels.itemPanel.quantity.setText(Integer.toString(getItemQuantity()));
SubsetWidget.loadHidden();
if (newWorld && Minecraft.getMinecraft().isSingleplayer()) world.config.getTag("inventory.cheatmode")
.setIntValue(NEIClientUtils.mc().playerController.isInCreativeMode() ? 2 : 0);
@@ -752,6 +811,8 @@ public class NEIClientConfig {
});
RecipeCatalysts.loadCatalystInfo();
CollapsibleItems.load();
SubsetWidget.loadHidden();
ItemSorter.loadConfig();
// Set pluginNEIConfigLoaded here before posting the NEIConfigsLoadedEvent. This used to be the
@@ -765,8 +826,6 @@ public class NEIClientConfig {
ItemList.loadItems.restart();
}
}.start();
} else {
ItemList.loadItems.restart();
}
}
@@ -1,12 +1,12 @@
package codechicken.nei;
import java.util.List;
import java.util.StringJoiner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.minecraft.util.EnumChatFormatting;
import codechicken.nei.FormattedTextField.TextFormatter;
import codechicken.nei.SearchTokenParser.SearchToken;
public class SearchTextFormatter implements TextFormatter {
@@ -17,63 +17,50 @@ public class SearchTextFormatter implements TextFormatter {
}
public String format(String text) {
final String[] parts = text.split("\\|");
final Pattern splitPattern = searchParser.getSplitPattern();
final String[] parts = (text + "| ").split("\\|");
StringJoiner formattedText = new StringJoiner(EnumChatFormatting.GRAY + "|");
for (String filterText : parts) {
Matcher filterMatcher = splitPattern.matcher(filterText);
for (int i = 0; i < parts.length - 1; i++) {
final String filterText = parts[i];
final List<SearchToken> tokens = searchParser.splitSearchText(filterText);
StringBuilder formattedPart = new StringBuilder();
int startIndex = 0;
while (filterMatcher.find()) {
boolean ignore = "-".equals(filterMatcher.group(2));
String firstChar = filterMatcher.group(3);
String token = filterMatcher.group(4);
boolean quotes = token.length() > 1 && token.startsWith("\"") && token.endsWith("\"");
if (quotes) {
token = token.substring(1, token.length() - 1);
}
formattedPart.append(filterText.substring(startIndex, filterMatcher.start()));
for (SearchToken token : tokens) {
formattedPart.append(filterText.substring(startIndex, token.start));
EnumChatFormatting tokenColor = EnumChatFormatting.RESET;
if (!firstChar.isEmpty()) {
tokenColor = searchParser.getProvider(firstChar.charAt(0)).getHighlightedColor();
if (token.firstChar != null) {
tokenColor = searchParser.getProvider(token.firstChar).getHighlightedColor();
}
if (ignore) {
if (token.ignore) {
formattedPart.append(EnumChatFormatting.BLUE + "-");
}
if (!firstChar.isEmpty()) {
formattedPart.append(tokenColor + firstChar);
if (token.firstChar != null) {
formattedPart.append(tokenColor + String.valueOf(token.firstChar));
}
if (quotes) {
if (token.quotes) {
formattedPart.append(EnumChatFormatting.GOLD + "\"");
}
if (!token.isEmpty()) {
formattedPart.append(tokenColor + token);
if (!token.rawText.isEmpty()) {
formattedPart.append(tokenColor + token.rawText);
}
if (quotes) {
if (token.quotes) {
formattedPart.append(EnumChatFormatting.GOLD + "\"");
}
startIndex = filterMatcher.end();
startIndex = token.end;
}
formattedPart.append(filterText.substring(startIndex, filterText.length()));
formattedText.add(formattedPart);
}
if (text.endsWith("|")) {
formattedText.add("");
}
return formattedText.toString();
}
}
@@ -2,11 +2,11 @@ package codechicken.nei;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -22,8 +22,6 @@ import codechicken.nei.ItemList.EverythingItemFilter;
import codechicken.nei.ItemList.NegatedItemFilter;
import codechicken.nei.ItemList.NothingItemFilter;
import codechicken.nei.api.ItemFilter;
import gnu.trove.map.TCharCharMap;
import gnu.trove.map.hash.TCharCharHashMap;
public class SearchTokenParser {
@@ -42,6 +40,20 @@ public class SearchTokenParser {
}
}
public static class SearchToken {
public boolean ignore = false;
public boolean quotes = false;
public Character firstChar = null;
public String[] words;
public String rawText = "";
public int start = 0;
public int end = 0;
}
public static interface ISearchParserProvider {
public ItemFilter getFilter(String searchText);
@@ -88,38 +100,7 @@ public class SearchTokenParser {
}
}
private static class ItemFilterCache implements ItemFilter {
public ItemFilter filter;
private final ItemStackMap<Boolean> states = new ItemStackMap<>();
private final ReentrantLock lock = new ReentrantLock();
public ItemFilterCache(ItemFilter filter) {
this.filter = filter;
}
@Override
public boolean matches(ItemStack item) {
lock.lock();
try {
Boolean match = states.get(item);
if (match == null) {
states.put(item, match = this.filter.matches(item));
}
return match;
} catch (Throwable th) {
th.printStackTrace();
return false;
} finally {
lock.unlock();
}
}
}
private static final LinkedHashMap<String, ItemFilter> filtersCache = new LinkedHashMap<>() {
private final LinkedHashMap<String, ItemFilter> filtersCache = new LinkedHashMap<>() {
private static final long serialVersionUID = 1042213947848622164L;
@@ -131,7 +112,7 @@ public class SearchTokenParser {
protected final List<ISearchParserProvider> searchProviders;
protected final ProvidersCache providersCache = new ProvidersCache();
protected final TCharCharMap prefixRedefinitions = new TCharCharHashMap();
protected final Map<Character, Character> prefixRedefinitions = new HashMap<>();
public SearchTokenParser(List<ISearchParserProvider> searchProviders) {
this.searchProviders = searchProviders;
@@ -144,6 +125,11 @@ public class SearchTokenParser {
public void addProvider(ISearchParserProvider provider) {
this.searchProviders.add(provider);
this.providersCache.clear();
this.filtersCache.clear();
}
public void clearCache() {
this.filtersCache.clear();
}
protected List<ISearchParserProvider> getProviders() {
@@ -176,30 +162,84 @@ public class SearchTokenParser {
.findFirst().orElse(null);
}
public ItemFilter getFilter(String filterText) {
public synchronized ItemFilter getFilter(String filterText) {
filterText = EnumChatFormatting.getTextWithoutFormattingCodes(filterText).toLowerCase();
if (!filtersCache.containsKey(filterText)) {
final String[] parts = EnumChatFormatting.getTextWithoutFormattingCodes(filterText).toLowerCase()
.split("\\|");
return this.filtersCache.computeIfAbsent(filterText, text -> {
final String[] parts = text.split("\\|");
final List<ItemFilter> searchTokens = Arrays.stream(parts).map(this::parseSearchText).filter(s -> s != null)
.collect(Collectors.toCollection(ArrayList::new));
if (searchTokens.isEmpty()) {
filtersCache.put(filterText, new EverythingItemFilter());
return new EverythingItemFilter();
} else if (searchTokens.size() == 1) {
filtersCache.put(filterText, new IsRegisteredItemFilter(new ItemFilterCache(searchTokens.get(0))));
return new IsRegisteredItemFilter(searchTokens.get(0));
} else {
filtersCache.put(
filterText,
new IsRegisteredItemFilter(new ItemFilterCache(new AnyMultiItemFilter(searchTokens))));
return new IsRegisteredItemFilter(new AnyMultiItemFilter(searchTokens));
}
}
});
return filtersCache.get(filterText);
}
public Pattern getSplitPattern() {
public List<SearchToken> splitSearchText(String filterText) {
if (filterText.isEmpty()) {
return Collections.emptyList();
}
final List<SearchToken> tokens = new ArrayList<>();
final String prefixes = getPrefixes();
final int spaceMode = NEIClientConfig.getIntSetting("inventory.search.spaceMode");
// The regular expression first tries to match a string that starts with a space or the beginning of the string,
// followed by a sequence of characters that do not contain special characters -"@#$%&, and ends with a space
// and the characters -"@#$%& or the end of the string.
final String patternPart1 = "(?<tokenA>(^|\\s+)(?:[^" + Pattern.quote(" -\"" + prefixes)
+ "]).+?(?=\\s+["
+ Pattern.quote("-\"" + prefixes)
+ "]|$))";
// If the first condition is not met, it tries to match a sequence of - characters, followed by @#$%&
// characters, then either a quoted string or non-space characters.
final String patternPart2 = "((?<ignore>-*)(?<firstChar>[" + Pattern.quote(prefixes)
+ "]*)(?<tokenB>\\\".*?(?:\\\"|$)|\\S+\\s*))";
final Pattern pattern = Pattern.compile(spaceMode == 0 ? patternPart2 : (patternPart1 + "|" + patternPart2));
final Matcher filterMatcher = pattern.matcher(filterText);
while (filterMatcher.find()) {
String firstChar = filterMatcher.group("firstChar");
SearchToken token = new SearchToken();
token.start = filterMatcher.start();
token.end = filterMatcher.end();
token.ignore = "-".equals(filterMatcher.group("ignore"));
token.rawText = spaceMode == 0 ? null : filterMatcher.group("tokenA");
if (firstChar != null && !firstChar.isEmpty()) {
token.firstChar = firstChar.charAt(0);
}
if (token.rawText == null) { // spaceMode == 0
token.rawText = filterMatcher.group("tokenB");
token.quotes = token.rawText.length() > 1 && token.rawText.startsWith("\"")
&& token.rawText.endsWith("\"");
if (token.quotes) {
token.rawText = token.rawText.substring(1, token.rawText.length() - 1);
}
token.words = new String[] { token.rawText.trim() };
} else if (spaceMode == 2) {
token.words = token.rawText.trim().split("\\s+");
} else {
token.words = new String[] { token.rawText.trim() };
}
tokens.add(token);
}
return tokens;
}
private String getPrefixes() {
StringBuilder prefixes = new StringBuilder().append('\0');
for (ISearchParserProvider provider : getProviders()) {
@@ -208,14 +248,11 @@ public class SearchTokenParser {
}
}
return Pattern.compile("((-*)([" + Pattern.quote(prefixes.toString()) + "]*)(\\\".*?(?:\\\"|$)|\\S+))");
return prefixes.toString();
}
public char getRedefinedPrefix(char prefix) {
if (this.prefixRedefinitions.containsKey(prefix)) {
return this.prefixRedefinitions.get(prefix);
}
return prefix;
return this.prefixRedefinitions.getOrDefault(prefix, prefix);
}
private ItemFilter parseSearchText(String filterText) {
@@ -224,28 +261,19 @@ public class SearchTokenParser {
return null;
}
final Matcher filterMatcher = getSplitPattern().matcher(filterText);
final AllMultiItemFilter searchTokens = new AllMultiItemFilter();
final List<SearchToken> tokens = splitSearchText(filterText);
while (filterMatcher.find()) {
boolean ignore = "-".equals(filterMatcher.group(2));
String firstChar = filterMatcher.group(3);
String token = filterMatcher.group(4);
boolean quotes = token.length() > 1 && token.startsWith("\"") && token.endsWith("\"");
for (SearchToken token : tokens) {
if (!token.rawText.isEmpty()) {
ItemFilter result = parseToken(token);
if (quotes) {
token = token.substring(1, token.length() - 1);
}
if (!token.isEmpty()) {
ItemFilter result = parseToken(firstChar, token);
if (ignore) {
if (token.ignore) {
searchTokens.filters.add(new NegatedItemFilter(result));
} else {
searchTokens.filters.add(result);
}
} else if (!ignore) {
} else if (!token.ignore) {
searchTokens.filters.add(new NothingItemFilter());
}
}
@@ -253,17 +281,17 @@ public class SearchTokenParser {
return searchTokens;
}
private ItemFilter parseToken(String firstChar, String token) {
final ISearchParserProvider provider = firstChar.isEmpty() ? null : this.getProvider(firstChar.charAt(0));
private ItemFilter parseToken(SearchToken token) {
final ISearchParserProvider provider = token.firstChar == null ? null : this.getProvider(token.firstChar);
if (provider == null || provider.getSearchMode() == SearchMode.NEVER) {
final List<ItemFilter> filters = new ArrayList<>();
for (ISearchParserProvider _provider : getProviders()) {
if (_provider.getSearchMode() == SearchMode.ALWAYS) {
ItemFilter filter = _provider.getFilter(token);
AllMultiItemFilter filter = generateFilters(_provider, token.words);
if (filter != null) {
if (!filter.filters.isEmpty()) {
filters.add(filter);
}
}
@@ -271,7 +299,21 @@ public class SearchTokenParser {
return filters.isEmpty() ? new NothingItemFilter() : new AnyMultiItemFilter(filters);
} else {
return provider.getFilter(token);
return generateFilters(provider, token.words);
}
}
private AllMultiItemFilter generateFilters(ISearchParserProvider provider, String[] words) {
final AllMultiItemFilter filters = new AllMultiItemFilter();
for (String work : words) {
final ItemFilter filter = provider.getFilter(work);
if (filter != null) {
filters.filters.add(filter);
}
}
return filters;
}
}
@@ -75,26 +75,25 @@ public abstract class OptionButton extends Option {
}
public String getTooltip() {
String tip = null;
if (tooltip != null) {
String s = translateN(tooltip);
if (!s.equals(namespaced(tooltip))) {
tip = s;
return s;
}
}
if (tip == null && getPrefix() != null) {
if (getPrefix() != null) {
final int width = getStringWidth(getPrefix());
final Rectangle b = buttonSize();
if (width >= b.x) {
tip = translateN(name);
return translateN(name);
}
}
return tip;
return null;
}
public void drawPrefix() {
@@ -29,6 +29,18 @@ public class OptionCycled extends OptionButton {
return prefixed ? translateN(name) : null;
}
@Override
public String getTooltip() {
String tooltip = name + "." + value() + ".tip";
String s = translateN(tooltip);
if (!s.equals(namespaced(tooltip))) {
return s;
}
return super.getTooltip();
}
@Override
public boolean onClick(int button) {
return cycle();
@@ -43,6 +43,7 @@ import codechicken.lib.gui.GuiDraw;
import codechicken.nei.ItemStackSet;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.SearchField;
import codechicken.nei.recipe.StackInfo;
import codechicken.nei.search.TooltipFilter;
import codechicken.nei.util.ReadableNumberConverter;
@@ -55,6 +56,7 @@ public class GuiContainerManager {
public void onResourceManagerReload(IResourceManager p_110549_1_) {
renderingErrorItems.clear();
TooltipFilter.populateSearchMap();
SearchField.searchParser.clearCache();
}
}
@@ -10,6 +10,7 @@ import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraftforge.fluids.FluidContainerRegistry;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidContainerItem;
@@ -18,19 +19,21 @@ import codechicken.nei.ItemStackMap;
import codechicken.nei.api.IStackStringifyHandler;
import codechicken.nei.recipe.stackinfo.DefaultStackStringifyHandler;
import codechicken.nei.recipe.stackinfo.GTFluidStackStringifyHandler;
import codechicken.nei.util.ItemStackKey;
public class StackInfo {
private static final FluidStack NULL_FLUID = new FluidStack(FluidRegistry.WATER, 0);
public static final ArrayList<IStackStringifyHandler> stackStringifyHandlers = new ArrayList<>();
private static final HashMap<String, HashMap<String, String[]>> guidfilters = new HashMap<>();
private static final ItemStackMap<String> guidcache = new ItemStackMap<>();
private static final LinkedHashMap<ItemStack, FluidStack> fluidcache = new LinkedHashMap<>() {
private static final LinkedHashMap<ItemStackKey, FluidStack> fluidcache = new LinkedHashMap<>() {
private static final long serialVersionUID = 1042213947848622164L;
@Override
protected boolean removeEldestEntry(Map.Entry<ItemStack, FluidStack> eldest) {
return size() > 20;
protected boolean removeEldestEntry(Map.Entry<ItemStackKey, FluidStack> eldest) {
return size() > 200;
}
};
@@ -92,19 +95,20 @@ public class StackInfo {
return true;
}
public static FluidStack getFluid(ItemStack stack) {
FluidStack fluid = fluidcache.get(stack);
public static synchronized FluidStack getFluid(ItemStack stack) {
ItemStackKey key = new ItemStackKey(stack);
FluidStack fluid = fluidcache.get(key);
if (fluid == null && !fluidcache.containsKey(stack)) {
if (fluid == null) {
for (int i = stackStringifyHandlers.size() - 1; i >= 0 && fluid == null; i--) {
fluid = stackStringifyHandlers.get(i).getFluid(stack);
}
fluidcache.put(stack, fluid);
fluidcache.put(key, fluid == null ? NULL_FLUID : fluid);
}
return fluid;
return fluid == NULL_FLUID ? null : fluid;
}
public static boolean isFluidContainer(ItemStack stack) {
@@ -1,7 +1,6 @@
package codechicken.nei.search;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Pattern;
import net.minecraft.item.ItemStack;
@@ -9,13 +8,12 @@ import net.minecraft.util.EnumChatFormatting;
import codechicken.nei.ItemList;
import codechicken.nei.ItemStackMap;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.api.ItemFilter;
import codechicken.nei.guihook.GuiContainerManager;
public class TooltipFilter implements ItemFilter {
private static final ItemStackMap<String> itemSearchNames = new ItemStackMap<>();
private static final ReentrantLock lock = new ReentrantLock();
private final Pattern pattern;
@@ -36,28 +34,32 @@ public class TooltipFilter implements ItemFilter {
}
protected static String getSearchTooltip(ItemStack stack) {
lock.lock();
String tooltip = itemSearchNames.get(stack);
try {
String tooltip = itemSearchNames.get(stack);
if (tooltip == null) {
tooltip = getTooltip(stack.copy());
if (tooltip == null) {
tooltip = getTooltip(stack.copy());
synchronized (itemSearchNames) {
itemSearchNames.put(stack, tooltip);
}
return tooltip;
} catch (Throwable th) {
th.printStackTrace();
return "";
} finally {
lock.unlock();
}
return tooltip;
}
private static String getTooltip(ItemStack itemstack) {
final List<String> list = GuiContainerManager.itemDisplayNameMultiline(itemstack, null, true);
return EnumChatFormatting.getTextWithoutFormattingCodes(String.join("\n", list.subList(1, list.size())));
try {
List<String> namelist = itemstack.getTooltip(NEIClientUtils.mc().thePlayer, false);
if (namelist.size() > 1) {
return EnumChatFormatting
.getTextWithoutFormattingCodes(String.join("\n", namelist.subList(1, namelist.size())));
}
} catch (Throwable ignored) {}
return "";
}
}
@@ -0,0 +1,33 @@
package codechicken.nei.util;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
public class ItemStackKey {
public final ItemStack stack;
private int hashCode = 1;
public ItemStackKey(ItemStack stack) {
this.stack = stack;
if (this.stack != null) {
this.hashCode = 31 * this.hashCode + stack.stackSize;
this.hashCode = 31 * this.hashCode + Item.getIdFromItem(stack.getItem());
this.hashCode = 31 * this.hashCode + stack.getItemDamage();
this.hashCode = 31 * this.hashCode + (!stack.hasTagCompound() ? 0 : stack.getTagCompound().hashCode());
}
}
@Override
public int hashCode() {
return this.hashCode;
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof ItemStackKey)) return false;
return ItemStack.areItemStacksEqual(this.stack, ((ItemStackKey) o).stack);
}
}
@@ -224,6 +224,13 @@ nei.options.inventory.search.patternMode=Search Mode
nei.options.inventory.search.patternMode.0=Plain
nei.options.inventory.search.patternMode.1=Extended
nei.options.inventory.search.patternMode.2=Regex
nei.options.inventory.search.spaceMode=Space Works like
nei.options.inventory.search.spaceMode.0=AND
nei.options.inventory.search.spaceMode.0.tip=Space between non-prefixed tokens works like "AND"
nei.options.inventory.search.spaceMode.1=Space
nei.options.inventory.search.spaceMode.1.tip=Space between non-prefixed tokens works like "space"
nei.options.inventory.search.spaceMode.2=AND-X
nei.options.inventory.search.spaceMode.2.tip=Space between non-prefixed tokens works like "AND" but all tokens must be within the same category
nei.options.inventory.search.quoteDropItemName=Quote Drop Item Name
nei.options.inventory.search.quoteDropItemName.true=Yes
nei.options.inventory.search.quoteDropItemName.false=No