2014-04-29 10:54:20 +10:00
|
|
|
package codechicken.nei;
|
|
|
|
|
|
2023-09-25 00:35:24 +02:00
|
|
|
import java.util.LinkedList;
|
|
|
|
|
import java.util.List;
|
2024-06-27 18:03:50 +03:00
|
|
|
import java.util.function.Function;
|
|
|
|
|
import java.util.regex.Matcher;
|
2023-09-25 00:35:24 +02:00
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
import java.util.regex.PatternSyntaxException;
|
|
|
|
|
|
2024-06-27 18:03:50 +03:00
|
|
|
import net.minecraft.client.Minecraft;
|
|
|
|
|
import net.minecraft.item.ItemStack;
|
2023-09-25 00:35:24 +02:00
|
|
|
import net.minecraft.util.EnumChatFormatting;
|
2024-06-27 18:03:50 +03:00
|
|
|
import net.minecraftforge.fluids.FluidStack;
|
2023-09-25 00:35:24 +02:00
|
|
|
|
2019-12-24 13:37:41 -08:00
|
|
|
import codechicken.lib.gui.GuiDraw;
|
2024-06-27 18:03:50 +03:00
|
|
|
import codechicken.nei.ItemList.NothingItemFilter;
|
|
|
|
|
import codechicken.nei.SearchTokenParser.ISearchParserProvider;
|
|
|
|
|
import codechicken.nei.SearchTokenParser.SearchMode;
|
2014-06-29 20:31:37 +10:00
|
|
|
import codechicken.nei.api.ItemFilter;
|
|
|
|
|
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
|
2024-06-27 18:03:50 +03:00
|
|
|
import codechicken.nei.recipe.StackInfo;
|
2022-09-11 01:35:48 +09:00
|
|
|
import codechicken.nei.util.TextHistory;
|
2014-06-29 20:31:37 +10:00
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public class SearchField extends TextField implements ItemFilterProvider {
|
2023-01-28 17:55:51 -08:00
|
|
|
|
2014-06-29 20:31:37 +10:00
|
|
|
/**
|
|
|
|
|
* Interface for returning a custom filter based on search field text
|
|
|
|
|
*/
|
2024-06-27 18:03:50 +03:00
|
|
|
@Deprecated
|
2022-06-24 12:32:13 +01:00
|
|
|
public static interface ISearchProvider {
|
2023-01-28 17:55:51 -08:00
|
|
|
|
2014-06-29 20:31:37 +10:00
|
|
|
/**
|
2014-12-26 12:39:37 +10:00
|
|
|
* @return false if this filter should only be used if no other non-default filters match the search string
|
|
|
|
|
*/
|
|
|
|
|
public boolean isPrimary();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return An item filter for items matching SearchTex null to ignore this provider
|
2014-06-29 20:31:37 +10:00
|
|
|
*/
|
|
|
|
|
public ItemFilter getFilter(String searchText);
|
|
|
|
|
}
|
2014-12-26 12:39:37 +10:00
|
|
|
|
2024-06-27 18:03:50 +03:00
|
|
|
public static class SearchParserProvider implements ISearchParserProvider {
|
2023-01-28 17:55:51 -08:00
|
|
|
|
2024-06-27 18:03:50 +03:00
|
|
|
protected final Function<Pattern, ItemFilter> createFilter;
|
|
|
|
|
protected final String name;
|
|
|
|
|
protected final char prefix;
|
|
|
|
|
protected final EnumChatFormatting highlightedColor;
|
|
|
|
|
|
|
|
|
|
public SearchParserProvider(char prefix, String name, EnumChatFormatting highlightedColor,
|
|
|
|
|
Function<Pattern, ItemFilter> createFilter) {
|
|
|
|
|
this.prefix = prefix;
|
|
|
|
|
this.name = name;
|
|
|
|
|
this.highlightedColor = highlightedColor;
|
|
|
|
|
this.createFilter = createFilter;
|
2014-12-26 12:39:37 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public ItemFilter getFilter(String searchText) {
|
2024-06-27 18:03:50 +03:00
|
|
|
Pattern pattern = SearchField.getPattern(searchText);
|
|
|
|
|
|
|
|
|
|
if (pattern != null) {
|
|
|
|
|
return this.createFilter(pattern);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new NothingItemFilter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected ItemFilter createFilter(Pattern pattern) {
|
|
|
|
|
final ItemFilter filter = this.createFilter.apply(pattern);
|
|
|
|
|
|
|
|
|
|
return filter == null ? new NothingItemFilter() : filter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public char getPrefix() {
|
|
|
|
|
return this.prefix;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public EnumChatFormatting getHighlightedColor() {
|
|
|
|
|
return this.highlightedColor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public SearchMode getSearchMode() {
|
|
|
|
|
return SearchMode.fromInt(NEIClientConfig.getIntSetting("inventory.search." + this.name + "SearchMode"));
|
2014-12-26 12:39:37 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-26 18:44:54 +03:00
|
|
|
public static class GuiSearchField extends FormattedTextField {
|
|
|
|
|
|
|
|
|
|
protected final SearchTokenParser searchParser;
|
|
|
|
|
|
|
|
|
|
public GuiSearchField() {
|
|
|
|
|
this(SearchField.searchParser);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public GuiSearchField(SearchTokenParser searchParser) {
|
|
|
|
|
super(Minecraft.getMinecraft().fontRenderer, 0, 0, 0, 0);
|
|
|
|
|
this.searchParser = searchParser;
|
|
|
|
|
setFormatter(new SearchTextFormatter(searchParser));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ItemFilter getFilter() {
|
|
|
|
|
return getFilter(getText());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ItemFilter getFilter(String filterText) {
|
|
|
|
|
return this.searchParser.getFilter(filterText);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-27 18:03:50 +03:00
|
|
|
@Deprecated
|
2019-12-30 20:19:16 -08:00
|
|
|
public static List<ISearchProvider> searchProviders = new LinkedList<>();
|
2024-07-26 18:44:54 +03:00
|
|
|
public static final SearchTokenParser searchParser = new SearchTokenParser();
|
2022-09-11 01:35:48 +09:00
|
|
|
private static final TextHistory history = new TextHistory();
|
2022-08-19 15:03:42 +03:00
|
|
|
private boolean isVisible = true;
|
2024-06-27 18:03:50 +03:00
|
|
|
private long lastclicktime;
|
2014-06-29 20:31:37 +10:00
|
|
|
|
2014-04-29 10:54:20 +10:00
|
|
|
public SearchField(String ident) {
|
|
|
|
|
super(ident);
|
2024-06-27 18:03:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void initInternalTextField() {
|
2024-07-26 18:44:54 +03:00
|
|
|
field = new GuiSearchField();
|
2024-06-27 18:03:50 +03:00
|
|
|
field.setMaxStringLength(maxSearchLength);
|
|
|
|
|
field.setCursorPositionZero();
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static boolean searchInventories() {
|
2024-07-26 18:44:54 +03:00
|
|
|
return NEIClientConfig.world.nbt.getBoolean("searchinventories");
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|
|
|
|
|
|
2022-08-19 15:03:42 +03:00
|
|
|
public boolean isVisible() {
|
|
|
|
|
return isVisible;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setVisible(boolean visible) {
|
|
|
|
|
isVisible = visible;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-29 10:54:20 +10:00
|
|
|
@Override
|
2022-06-24 12:32:13 +01:00
|
|
|
public int getTextColour() {
|
2022-01-02 23:30:54 +02:00
|
|
|
if (ItemPanels.itemPanel.getItems().isEmpty()) {
|
2019-12-24 13:37:41 -08:00
|
|
|
return focused() ? 0xFFcc3300 : 0xFF993300;
|
|
|
|
|
} else {
|
|
|
|
|
return focused() ? 0xFFE0E0E0 : 0xFF909090;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void draw(int mousex, int mousey) {
|
|
|
|
|
super.draw(mousex, mousey);
|
|
|
|
|
|
|
|
|
|
if (searchInventories()) {
|
2024-07-26 18:44:54 +03:00
|
|
|
GuiDraw.drawGradientRect(
|
|
|
|
|
field.xPosition - 1,
|
|
|
|
|
field.yPosition - 1,
|
|
|
|
|
1,
|
|
|
|
|
field.height + 2,
|
|
|
|
|
0xFFFFFF00,
|
|
|
|
|
0xFFC0B000); // Left
|
|
|
|
|
GuiDraw.drawGradientRect(
|
|
|
|
|
field.xPosition - 1,
|
|
|
|
|
field.yPosition - 1,
|
|
|
|
|
field.width + 2,
|
|
|
|
|
1,
|
|
|
|
|
0xFFFFFF00,
|
|
|
|
|
0xFFC0B000); // Top
|
|
|
|
|
GuiDraw.drawGradientRect(
|
|
|
|
|
field.xPosition + field.width,
|
|
|
|
|
field.yPosition - 1,
|
|
|
|
|
1,
|
|
|
|
|
field.height + 2,
|
|
|
|
|
0xFFFFFF00,
|
|
|
|
|
0xFFC0B000); // Left
|
|
|
|
|
GuiDraw.drawGradientRect(
|
|
|
|
|
field.xPosition - 1,
|
|
|
|
|
field.yPosition + field.height,
|
|
|
|
|
field.width + 2,
|
|
|
|
|
1,
|
|
|
|
|
0xFFFFFF00,
|
|
|
|
|
0xFFC0B000); // Bottom
|
2019-12-24 13:37:41 -08:00
|
|
|
}
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean handleClick(int mousex, int mousey, int button) {
|
|
|
|
|
if (button == 0) {
|
2022-06-24 12:32:13 +01:00
|
|
|
if (focused() && (System.currentTimeMillis() - lastclicktime < 400)) { // double click
|
2014-12-26 12:39:37 +10:00
|
|
|
NEIClientConfig.world.nbt.setBoolean("searchinventories", !searchInventories());
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|
|
|
|
|
lastclicktime = System.currentTimeMillis();
|
|
|
|
|
}
|
|
|
|
|
return super.handleClick(mousex, mousey, button);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onTextChange(String oldText) {
|
2019-12-24 13:37:41 -08:00
|
|
|
final String newText = text();
|
2024-06-27 18:03:50 +03:00
|
|
|
if (!newText.equals(oldText)) {
|
|
|
|
|
if (newText.length() > 0) NEIClientConfig.logger.debug("Searching for " + newText);
|
|
|
|
|
NEIClientConfig.setSearchExpression(newText);
|
|
|
|
|
ItemList.updateFilter.restart();
|
|
|
|
|
}
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void lastKeyTyped(int keyID, char keyChar) {
|
2022-08-19 15:03:42 +03:00
|
|
|
|
|
|
|
|
if (isVisible() && NEIClientConfig.isKeyHashDown("gui.search")) {
|
|
|
|
|
setFocus(true);
|
|
|
|
|
}
|
2024-02-04 14:09:24 +02:00
|
|
|
if (focused() && NEIClientConfig.isKeyHashDown("gui.getprevioussearch")) {
|
2022-09-11 01:35:48 +09:00
|
|
|
handleNavigateHistory(TextHistory.Direction.PREVIOUS);
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-04 14:09:24 +02:00
|
|
|
if (focused() && NEIClientConfig.isKeyHashDown("gui.getnextsearch")) {
|
2022-09-11 01:35:48 +09:00
|
|
|
handleNavigateHistory(TextHistory.Direction.NEXT);
|
|
|
|
|
}
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String filterText(String s) {
|
|
|
|
|
return EnumChatFormatting.getTextWithoutFormattingCodes(s);
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-14 17:10:00 +10:00
|
|
|
public static Pattern getPattern(String search) {
|
2024-06-27 18:03:50 +03:00
|
|
|
return getPattern(search, NEIClientConfig.getIntSetting("inventory.search.patternMode"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Pattern getPattern(String search, int patternMode) {
|
|
|
|
|
switch (patternMode) {
|
2022-06-24 12:32:13 +01:00
|
|
|
case 0: // plain
|
2024-06-27 18:03:50 +03:00
|
|
|
search = Pattern.quote(search);
|
2014-06-29 20:31:37 +10:00
|
|
|
break;
|
2024-06-27 18:03:50 +03:00
|
|
|
case 1: // extended
|
|
|
|
|
|
|
|
|
|
if (search.length() >= 3 && search.startsWith("r/") && search.endsWith("/")) {
|
|
|
|
|
search = search.substring(2, search.length() - 1);
|
|
|
|
|
} else {
|
|
|
|
|
final Matcher matcher = Pattern.compile("(\\?|\\*)").matcher(search);
|
2024-09-01 23:19:12 +03:00
|
|
|
StringBuilder cleanedString = new StringBuilder();
|
2024-06-27 18:03:50 +03:00
|
|
|
int lastEndIndex = 0;
|
|
|
|
|
|
|
|
|
|
while (matcher.find()) {
|
2024-09-01 23:19:12 +03:00
|
|
|
cleanedString.append(Pattern.quote(search.substring(lastEndIndex, matcher.start())));
|
2024-06-27 18:03:50 +03:00
|
|
|
|
|
|
|
|
switch (matcher.group(0).charAt(0)) {
|
|
|
|
|
case '?':
|
2024-09-01 23:19:12 +03:00
|
|
|
cleanedString.append(".");
|
2024-06-27 18:03:50 +03:00
|
|
|
break;
|
|
|
|
|
case '*':
|
2024-09-01 23:19:12 +03:00
|
|
|
cleanedString.append(".+?");
|
2024-06-27 18:03:50 +03:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lastEndIndex = matcher.end();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
search = cleanedString + Pattern.quote(search.substring(lastEndIndex, search.length()));
|
|
|
|
|
}
|
2014-06-29 20:31:37 +10:00
|
|
|
break;
|
2024-09-01 23:19:12 +03:00
|
|
|
default:
|
|
|
|
|
break;
|
2014-06-29 20:31:37 +10:00
|
|
|
}
|
|
|
|
|
|
2024-06-27 18:03:50 +03:00
|
|
|
if (!search.isEmpty()) {
|
|
|
|
|
try {
|
|
|
|
|
return Pattern.compile(search, Pattern.MULTILINE | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
|
|
|
|
|
} catch (PatternSyntaxException ignored) {}
|
|
|
|
|
}
|
2024-02-04 14:09:24 +02:00
|
|
|
|
2024-06-27 18:03:50 +03:00
|
|
|
return null;
|
2014-12-14 17:10:00 +10:00
|
|
|
}
|
|
|
|
|
|
2024-06-27 18:03:50 +03:00
|
|
|
public static String getEscapedSearchText(ItemStack stack) {
|
|
|
|
|
final FluidStack fluidStack = StackInfo.isFluidContainer(stack) ? null : StackInfo.getFluid(stack);
|
|
|
|
|
String displayName;
|
|
|
|
|
|
|
|
|
|
if (fluidStack != null) {
|
|
|
|
|
displayName = fluidStack.getLocalizedName();
|
|
|
|
|
} else {
|
|
|
|
|
displayName = stack.getDisplayName();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return getEscapedSearchText(displayName);
|
2024-02-04 14:09:24 +02:00
|
|
|
}
|
2014-12-14 17:10:00 +10:00
|
|
|
|
2024-06-27 18:03:50 +03:00
|
|
|
public static String getEscapedSearchText(String text) {
|
|
|
|
|
text = EnumChatFormatting.getTextWithoutFormattingCodes(text);
|
2024-02-04 14:09:24 +02:00
|
|
|
|
2024-06-27 18:03:50 +03:00
|
|
|
switch (NEIClientConfig.getIntSetting("inventory.search.patternMode")) {
|
|
|
|
|
case 1:
|
|
|
|
|
text = text.replaceAll("[\\?|\\*]", "\\\\$0");
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
text = text.replaceAll("[{}()\\[\\].+*?^$\\\\|]", "\\\\$0");
|
|
|
|
|
break;
|
2024-09-01 23:19:12 +03:00
|
|
|
default:
|
|
|
|
|
break;
|
2014-12-14 17:10:00 +10:00
|
|
|
}
|
2014-06-29 20:31:37 +10:00
|
|
|
|
2024-06-27 18:03:50 +03:00
|
|
|
if (text.contains(" ") && NEIClientConfig.getBooleanSetting("inventory.search.quoteDropItemName")) {
|
|
|
|
|
text = "\"" + text + "\"";
|
2024-02-04 14:09:24 +02:00
|
|
|
}
|
|
|
|
|
|
2024-06-27 18:03:50 +03:00
|
|
|
return text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public ItemFilter getFilter() {
|
2024-07-26 18:44:54 +03:00
|
|
|
return ((GuiSearchField) field).getFilter();
|
2024-06-27 18:03:50 +03:00
|
|
|
}
|
2024-02-04 14:09:24 +02:00
|
|
|
|
2024-06-27 18:03:50 +03:00
|
|
|
public static ItemFilter getFilter(String filterText) {
|
|
|
|
|
return SearchField.searchParser.getFilter(filterText);
|
2014-06-29 20:31:37 +10:00
|
|
|
}
|
2022-09-11 01:35:48 +09:00
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void setFocus(boolean focus) {
|
|
|
|
|
final boolean previousFocus = field.isFocused();
|
|
|
|
|
|
|
|
|
|
if (previousFocus != focus) {
|
|
|
|
|
history.add(text());
|
|
|
|
|
}
|
|
|
|
|
super.setFocus(focus);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean handleNavigateHistory(TextHistory.Direction direction) {
|
|
|
|
|
if (focused()) {
|
|
|
|
|
return history.get(direction, text()).map(newText -> {
|
|
|
|
|
setText(newText);
|
|
|
|
|
return true;
|
|
|
|
|
}).orElse(false);
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|