aboutsummaryrefslogtreecommitdiff
path: root/runtime/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/src/main/java')
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java2
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/gui/OverlaySearchField.java70
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringScreen.java5
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/gui/plugin/entry/FluidEntryDefinition.java12
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/gui/plugin/entry/ItemEntryDefinition.java10
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/OverlaySearchFieldSyntaxHighlighter.java46
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/SearchArgument.java100
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/TextTransformations.java55
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/entry/EmptyEntryDefinition.java7
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/search/AlwaysMatchingArgument.java11
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/search/Argument.java28
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/search/ArgumentsRegistry.java6
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/search/MatchStatus.java17
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/search/ModArgument.java53
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/search/RegexArgument.java30
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/search/TagArgument.java57
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/search/TextArgument.java17
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/search/TooltipArgument.java26
18 files changed, 432 insertions, 120 deletions
diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java b/runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java
index 3dbaf62c6..62daa5b07 100644
--- a/runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java
+++ b/runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java
@@ -228,7 +228,7 @@ public class ContainerScreenOverlay extends WidgetWithBounds implements REIOverl
}
ScreenHelper.getSearchField().getBounds().setBounds(getSearchFieldArea());
this.widgets.add(ScreenHelper.getSearchField());
- ScreenHelper.getSearchField().setChangedListener(s -> ENTRY_LIST_WIDGET.updateSearch(s, false));
+ ScreenHelper.getSearchField().setResponder(s -> ENTRY_LIST_WIDGET.updateSearch(s, false));
if (!ConfigObject.getInstance().isEntryListWidgetScrolled()) {
widgets.add(leftButton = Widgets.createButton(new Rectangle(bounds.x, bounds.y + (ConfigObject.getInstance().getSearchFieldLocation() == SearchFieldLocation.TOP_SIDE ? 24 : 0) + 5, 16, 16), new TranslatableComponent("text.rei.left_arrow"))
.onClick(button -> {
diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/OverlaySearchField.java b/runtime/src/main/java/me/shedaniel/rei/gui/OverlaySearchField.java
index 33caf9915..9edb9880f 100644
--- a/runtime/src/main/java/me/shedaniel/rei/gui/OverlaySearchField.java
+++ b/runtime/src/main/java/me/shedaniel/rei/gui/OverlaySearchField.java
@@ -27,25 +27,38 @@ import com.google.common.collect.Lists;
import com.mojang.blaze3d.platform.InputConstants;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
+import me.shedaniel.math.Color;
import me.shedaniel.math.Point;
import me.shedaniel.math.impl.PointHelper;
import me.shedaniel.rei.api.ConfigObject;
-import me.shedaniel.rei.api.REIHelper;
import me.shedaniel.rei.gui.widget.TextFieldWidget;
+import me.shedaniel.rei.impl.OverlaySearchFieldSyntaxHighlighter;
import me.shedaniel.rei.impl.ScreenHelper;
+import me.shedaniel.rei.impl.TextTransformations;
+import me.shedaniel.rei.impl.search.Argument;
+import me.shedaniel.rei.impl.search.ArgumentsRegistry;
+import me.shedaniel.rei.impl.search.TextArgument;
+import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.language.I18n;
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
+import net.minecraft.network.chat.Style;
+import net.minecraft.network.chat.TextColor;
import net.minecraft.sounds.SoundEvents;
+import net.minecraft.util.FormattedCharSequence;
import net.minecraft.util.Tuple;
import org.jetbrains.annotations.ApiStatus;
import java.util.List;
+import java.util.function.Consumer;
@ApiStatus.Internal
-public class OverlaySearchField extends TextFieldWidget {
-
+public class OverlaySearchField extends TextFieldWidget implements TextFieldWidget.TextFormatter {
public static boolean isHighlighting = false;
+ private static final Style SPLITTER_STYLE = Style.EMPTY.withColor(ChatFormatting.GRAY);
+ private static final Style QUOTES_STYLE = Style.EMPTY.withColor(ChatFormatting.GOLD);
+ private static final Style ERROR_STYLE = Style.EMPTY.withColor(TextColor.fromRgb(0xff5555));
+ private final OverlaySearchFieldSyntaxHighlighter highlighter = new OverlaySearchFieldSyntaxHighlighter(this);
public long keybindFocusTime = -1;
public int keybindFocusKey = -1;
public boolean isMain = true;
@@ -55,6 +68,42 @@ public class OverlaySearchField extends TextFieldWidget {
public OverlaySearchField(int x, int y, int width, int height) {
super(x, y, width, height);
setMaxLength(10000);
+ setFormatter(this);
+ super.setResponder(highlighter);
+ }
+
+ @Override
+ public FormattedCharSequence format(TextFieldWidget widget, String text, int index) {
+ return TextTransformations.forwardWithTransformation(text, (s, charIndex, c) -> {
+ byte arg = highlighter.highlighted[charIndex + index];
+ Style style;
+ if (arg > 0) {
+ Argument<?, ?> argument = ArgumentsRegistry.ARGUMENT_LIST.get(arg - 1);
+ style = argument.getHighlightedStyle();
+ if (argument instanceof TextArgument) {
+ if (isMain && ContainerScreenOverlay.getEntryListWidget().getAllStacks().isEmpty() && !getText().isEmpty()) {
+ style = ERROR_STYLE;
+ }
+ }
+ } else if (arg == -1) {
+ style = SPLITTER_STYLE;
+ } else if (arg == -2) {
+ style = QUOTES_STYLE;
+ } else {
+ style = Style.EMPTY;
+ }
+
+
+ if (containsMouse(PointHelper.ofMouse()) || isFocused()) {
+ return style;
+ }
+ return style.withColor(TextColor.fromRgb(Color.ofOpaque(style.getColor() == null ? -1 : style.getColor().getValue()).brighter(0.75).getColor()));
+ });
+ }
+
+ @Override
+ public void setResponder(Consumer<String> responder) {
+ super.setResponder(highlighter.andThen(responder));
}
@Override
@@ -68,15 +117,14 @@ public class OverlaySearchField extends TextFieldWidget {
public void addToHistory(String text) {
if (!text.isEmpty()) {
history.removeIf(str -> str.equalsIgnoreCase(text));
- history.add(text);
if (history.size() > 100)
history.remove(0);
+ history.add(text);
}
}
public void laterRender(PoseStack matrices, int int_1, int int_2, float float_1) {
RenderSystem.disableDepthTest();
- setEditableColor(isMain && ContainerScreenOverlay.getEntryListWidget().getAllStacks().isEmpty() && !getText().isEmpty() ? 16733525 : isHighlighting && isMain ? -852212 : (containsMouse(PointHelper.ofMouse()) || isFocused()) ? (REIHelper.getInstance().isDarkThemeEnabled() ? -17587 : -1) : -6250336);
setSuggestion(!isFocused() && getText().isEmpty() ? I18n.get("text.rei.search.field.suggestion") : null);
super.render(matrices, int_1, int_2, float_1);
RenderSystem.enableDepthTest();
@@ -86,10 +134,13 @@ public class OverlaySearchField extends TextFieldWidget {
protected void renderSuggestion(PoseStack matrices, int x, int y) {
matrices.pushPose();
matrices.translate(0, 0, 400);
- if (containsMouse(PointHelper.ofMouse()) || isFocused())
- this.font.drawShadow(matrices, this.font.plainSubstrByWidth(this.getSuggestion(), this.getWidth()), x, y, REIHelper.getInstance().isDarkThemeEnabled() ? 0xccddaa3d : 0xddeaeaea);
- else
- this.font.drawShadow(matrices, this.font.plainSubstrByWidth(this.getSuggestion(), this.getWidth()), x, y, -6250336);
+ int color;
+ if (containsMouse(PointHelper.ofMouse()) || isFocused()) {
+ color = 0xddeaeaea;
+ } else {
+ color = -6250336;
+ }
+ this.font.drawShadow(matrices, this.font.plainSubstrByWidth(this.getSuggestion(), this.getWidth()), x, y, color);
matrices.popPose();
}
@@ -180,5 +231,4 @@ public class OverlaySearchField extends TextFieldWidget {
@Override
public void render(PoseStack matrices, int mouseX, int mouseY, float delta) {
}
-
}
diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringScreen.java b/runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringScreen.java
index d6e662857..dbbb9fbf4 100644
--- a/runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringScreen.java
+++ b/runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringScreen.java
@@ -173,18 +173,19 @@ public class FilteringScreen extends Screen {
super.init();
Rectangle bounds = getBounds();
updateSearch(this.searchField.getText());
- this.searchField.getBounds().setBounds(bounds.getCenterX() - 75, bounds.getMaxY() - 22, 150, 18);
this.selectAllButton.x = 2;
this.selectAllButton.y = bounds.getMaxY() - 22;
this.selectNoneButton.x = 4 + selectAllButton.getWidth();
this.selectNoneButton.y = bounds.getMaxY() - 22;
+ int searchFieldWidth = Math.max(bounds.width - (selectNoneButton.x + selectNoneButton.getWidth() + hideButton.getWidth() + showButton.getWidth() + 12), 100);
+ this.searchField.getBounds().setBounds(selectNoneButton.x + selectNoneButton.getWidth() + 4, bounds.getMaxY() - 21, searchFieldWidth, 18);
this.hideButton.x = bounds.getMaxX() - hideButton.getWidth() - showButton.getWidth() - 4;
this.hideButton.y = bounds.getMaxY() - 22;
this.showButton.x = bounds.getMaxX() - showButton.getWidth() - 2;
this.showButton.y = bounds.getMaxY() - 22;
this.backButton.x = 4;
this.backButton.y = 4;
- this.searchField.setChangedListener(this::updateSearch);
+ this.searchField.setResponder(this::updateSearch);
}
protected void renderHoleBackground(PoseStack matrices, int y1, int y2, int tint, int alpha1, int alpha2) {
diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/plugin/entry/FluidEntryDefinition.java b/runtime/src/main/java/me/shedaniel/rei/gui/plugin/entry/FluidEntryDefinition.java
index 9c7941985..34dbaa6c8 100644
--- a/runtime/src/main/java/me/shedaniel/rei/gui/plugin/entry/FluidEntryDefinition.java
+++ b/runtime/src/main/java/me/shedaniel/rei/gui/plugin/entry/FluidEntryDefinition.java
@@ -45,12 +45,12 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation;
+import net.minecraft.tags.TagCollection;
+import net.minecraft.world.level.material.Fluid;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
+import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -136,6 +136,12 @@ public class FluidEntryDefinition implements EntryDefinition<FluidStack> {
return value.getFluid().defaultFluidState().createLegacyBlock().getBlock().getName();
}
+ @Override
+ public @NotNull Collection<ResourceLocation> getTagsFor(EntryStack<FluidStack> entry, FluidStack value) {
+ TagCollection<Fluid> collection = Minecraft.getInstance().getConnection().getTags().get(Registry.FLUID_REGISTRY);
+ return collection == null ? Collections.emptyList() : collection.getMatchingTags(value.getFluid());
+ }
+
public static class FluidEntryRenderer extends AbstractEntryRenderer<FluidStack> {
@Override
public void render(EntryStack<FluidStack> entry, PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) {
diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/plugin/entry/ItemEntryDefinition.java b/runtime/src/main/java/me/shedaniel/rei/gui/plugin/entry/ItemEntryDefinition.java
index 4407563f3..1a2357d10 100644
--- a/runtime/src/main/java/me/shedaniel/rei/gui/plugin/entry/ItemEntryDefinition.java
+++ b/runtime/src/main/java/me/shedaniel/rei/gui/plugin/entry/ItemEntryDefinition.java
@@ -52,12 +52,16 @@ import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
+import net.minecraft.tags.TagCollection;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
+import net.minecraft.world.level.material.Fluid;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Optional;
@@ -211,6 +215,12 @@ public class ItemEntryDefinition implements EntryDefinition<ItemStack> {
return new ImmutableLiteralText("ERROR");
}
+ @Override
+ public @NotNull Collection<ResourceLocation> getTagsFor(EntryStack<ItemStack> entry, ItemStack value) {
+ TagCollection<Item> collection = Minecraft.getInstance().getConnection().getTags().get(Registry.ITEM_REGISTRY);
+ return collection == null ? Collections.emptyList() : collection.getMatchingTags(value.getItem());
+ }
+
private List<Component> tryGetItemStackToolTip(EntryStack<ItemStack> entry, ItemStack value, boolean careAboutAdvanced) {
if (!SEARCH_BLACKLISTED.contains(value.getItem()))
try {
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/OverlaySearchFieldSyntaxHighlighter.java b/runtime/src/main/java/me/shedaniel/rei/impl/OverlaySearchFieldSyntaxHighlighter.java
new file mode 100644
index 000000000..c63895f2c
--- /dev/null
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/OverlaySearchFieldSyntaxHighlighter.java
@@ -0,0 +1,46 @@
+package me.shedaniel.rei.impl;
+
+import me.shedaniel.rei.gui.OverlaySearchField;
+import me.shedaniel.rei.impl.search.ArgumentsRegistry;
+import org.jetbrains.annotations.ApiStatus;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+@ApiStatus.Internal
+public class OverlaySearchFieldSyntaxHighlighter implements Consumer<String> {
+ private final OverlaySearchField field;
+ public byte[] highlighted;
+
+ public OverlaySearchFieldSyntaxHighlighter(OverlaySearchField field) {
+ this.field = field;
+ this.accept(field.getText());
+ }
+
+ @Override
+ public void accept(String text) {
+ this.highlighted = new byte[text.length()];
+ SearchArgument.ProcessedSink sink = new SearchArgument.ProcessedSink() {
+ @Override
+ public void addQuote(int index) {
+ highlighted[index] = -2;
+ }
+
+ @Override
+ public void addSplitter(int index) {
+ highlighted[index] = -1;
+ }
+ };
+ List<SearchArgument.SearchArguments> arguments = SearchArgument.processSearchTerm(text, sink);
+ for (SearchArgument.SearchArguments argument : arguments) {
+ if (!argument.isAlways()) {
+ for (SearchArgument<?, ?> searchArgument : argument.getArguments()) {
+ int argIndex = ArgumentsRegistry.ARGUMENT_LIST.indexOf(searchArgument.getArgument()) + 1;
+ for (int i = searchArgument.start(); i < searchArgument.end(); i++) {
+ highlighted[i] = (byte) argIndex;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/SearchArgument.java b/runtime/src/main/java/me/shedaniel/rei/impl/SearchArgument.java
index 9ed2cb05b..78798ac87 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/SearchArgument.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/SearchArgument.java
@@ -37,8 +37,12 @@ import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component;
+import net.minecraft.util.Unit;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.commons.lang3.mutable.MutableObject;
import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Locale;
@@ -47,38 +51,73 @@ import java.util.regex.Pattern;
@ApiStatus.Internal
@Environment(EnvType.CLIENT)
-public class SearchArgument {
+public class SearchArgument<T, R> {
public static final String SPACE = " ", EMPTY = "";
- private static final SearchArgument ALWAYS = new SearchArgument(AlwaysMatchingArgument.INSTANCE, EMPTY, true);
- private Argument argument;
+ private static final SearchArgument<Unit, Unit> ALWAYS = new SearchArgument<>(AlwaysMatchingArgument.INSTANCE, EMPTY, true, -1, -1);
+ private Argument<T, R> argument;
private String text;
- private Object data;
+ private T filterData;
private boolean regular;
+ private final int start;
+ private final int end;
private static final Pattern SPLIT_PATTERN = Pattern.compile("(?:\"([^\"]*)\")|([^\\s]+)");
- public SearchArgument(Argument argument, String text, boolean regular) {
- this(argument, text, regular, true);
+ public SearchArgument(Argument<T, R> argument, String text, boolean regular, int start, int end) {
+ this(argument, text, regular, start, end, true);
}
- public SearchArgument(Argument argument, String text, boolean regular, boolean lowercase) {
+ public SearchArgument(Argument<T, R> argument, String text, boolean regular, int start, int end, boolean lowercase) {
this.argument = argument;
this.text = lowercase ? text.toLowerCase(Locale.ROOT) : text;
this.regular = regular;
- this.data = null;
+ this.filterData = null;
+ this.start = start;
+ this.end = end;
+ }
+
+ public int start() {
+ return start;
+ }
+
+ public int end() {
+ return end;
+ }
+
+ public interface ProcessedSink {
+ void addQuote(int index);
+
+ void addSplitter(int index);
}
@ApiStatus.Internal
public static List<SearchArgument.SearchArguments> processSearchTerm(String searchTerm) {
+ return processSearchTerm(searchTerm, null);
+ }
+
+ @ApiStatus.Internal
+ public static List<SearchArgument.SearchArguments> processSearchTerm(String searchTerm, @Nullable ProcessedSink sink) {
List<SearchArgument.SearchArguments> searchArguments = Lists.newArrayList();
- for (String split : StringUtils.splitByWholeSeparatorPreserveAllTokens(searchTerm, "|")) {
- Matcher terms = SPLIT_PATTERN.matcher(split);
- List<SearchArgument> arguments = Lists.newArrayList();
+ int tokenStartIndex = 0;
+ String[] allTokens = StringUtils.splitByWholeSeparatorPreserveAllTokens(searchTerm, "|");
+ for (String token : allTokens) {
+ Matcher terms = SPLIT_PATTERN.matcher(token);
+ List<SearchArgument<?, ?>> arguments = Lists.newArrayList();
while (terms.find()) {
String term = MoreObjects.firstNonNull(terms.group(1), terms.group(2));
- for (Argument argument : ArgumentsRegistry.ARGUMENT_LIST) {
+ for (Argument<?, ?> argument : ArgumentsRegistry.ARGUMENT_LIST) {
MatchStatus status = argument.matchesArgumentPrefix(term);
if (status.isMatched()) {
- arguments.add(new SearchArgument(argument, status.getText(), !status.isInverted(), !status.shouldPreserveCasing()));
+ if (terms.group(1) != null) {
+ arguments.add(new SearchArgument<>(argument, status.getText(), !status.isInverted(), terms.start(1) + tokenStartIndex, terms.end(1) + tokenStartIndex, !status.shouldPreserveCasing()));
+ if (sink != null) {
+ sink.addQuote(terms.start() + tokenStartIndex);
+ if (terms.end() - 1 + tokenStartIndex < searchTerm.length()) {
+ sink.addQuote(terms.end() - 1 + tokenStartIndex);
+ }
+ }
+ } else {
+ arguments.add(new SearchArgument<>(argument, status.getText(), !status.isInverted(), terms.start(2) + tokenStartIndex, terms.end(2) + tokenStartIndex, !status.shouldPreserveCasing()));
+ }
break;
}
}
@@ -88,25 +127,31 @@ public class SearchArgument {
} else {
searchArguments.add(new SearchArgument.SearchArguments(arguments.toArray(new SearchArgument[0])));
}
+ tokenStartIndex += 1 + token.length();
+ if (sink != null && tokenStartIndex - 1 < searchTerm.length()) {
+ sink.addSplitter(tokenStartIndex - 1);
+ }
}
for (SearchArguments arguments : searchArguments) {
- for (SearchArgument argument : arguments.getArguments()) {
- argument.data = argument.argument.prepareSearchData(argument.getText());
+ for (SearchArgument<?, ?> argument : arguments.getArguments()) {
+ //noinspection RedundantCast
+ ((SearchArgument<Object, Object>) argument).filterData = argument.argument.prepareSearchFilter(argument.getText());
}
}
return searchArguments;
}
@ApiStatus.Internal
- public static boolean canSearchTermsBeAppliedTo(EntryStack stack, List<SearchArgument.SearchArguments> searchArguments) {
+ public static boolean canSearchTermsBeAppliedTo(EntryStack<?> stack, List<SearchArgument.SearchArguments> searchArguments) {
if (searchArguments.isEmpty())
return true;
Minecraft minecraft = Minecraft.getInstance();
- Object[] data = new Object[ArgumentsRegistry.ARGUMENT_LIST.size()];
+ Mutable<?> mutable = new MutableObject<>();
for (SearchArgument.SearchArguments arguments : searchArguments) {
boolean applicable = true;
- for (SearchArgument argument : arguments.getArguments()) {
- if (argument.getArgument().matches(data, stack, argument.getText(), argument.data) != argument.isRegular()) {
+ for (SearchArgument<?, ?> argument : arguments.getArguments()) {
+ mutable.setValue(null);
+ if (matches(argument.getArgument(), mutable, stack, argument.getText(), argument.filterData) != argument.isRegular()) {
applicable = false;
break;
}
@@ -117,14 +162,18 @@ public class SearchArgument {
return false;
}
- public static String tryGetEntryStackTooltip(EntryStack stack) {
+ private static <T, R, Z, B> boolean matches(Argument<T, B> argument, Mutable<Z> data, EntryStack<?> stack, String filter, R filterData) {
+ return argument.matches((Mutable<B>) data, stack, filter, (T) filterData);
+ }
+
+ public static String tryGetEntryStackTooltip(EntryStack<?> stack) {
Tooltip tooltip = stack.getTooltip(new Point());
if (tooltip != null)
return CollectionUtils.mapAndJoinToString(tooltip.getText(), Component::getString, "\n");
return "";
}
- public Argument getArgument() {
+ public Argument<?, ?> getArgument() {
return argument;
}
@@ -142,14 +191,14 @@ public class SearchArgument {
}
public static class SearchArguments {
- public static final SearchArguments ALWAYS = new SearchArguments(new SearchArgument[]{SearchArgument.ALWAYS});
- private SearchArgument[] arguments;
+ public static final SearchArguments ALWAYS = new SearchArguments(SearchArgument.ALWAYS);
+ private SearchArgument<?, ?>[] arguments;
- public SearchArguments(SearchArgument[] arguments) {
+ public SearchArguments(SearchArgument<?, ?>... arguments) {
this.arguments = arguments;
}
- public SearchArgument[] getArguments() {
+ public SearchArgument<?, ?>[] getArguments() {
return arguments;
}
@@ -157,5 +206,4 @@ public class SearchArgument {
return this == ALWAYS;
}
}
-
}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/TextTransformations.java b/runtime/src/main/java/me/shedaniel/rei/impl/TextTransformations.java
index 711bf95f0..5ac8dadb7 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/TextTransformations.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/TextTransformations.java
@@ -26,6 +26,7 @@ package me.shedaniel.rei.impl;
import me.shedaniel.math.Color;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
+import net.minecraft.network.chat.Style;
import net.minecraft.network.chat.TextColor;
import net.minecraft.util.FormattedCharSequence;
import org.jetbrains.annotations.ApiStatus;
@@ -41,4 +42,58 @@ public class TextTransformations {
return sink.accept(charIndex, style.withColor(TextColor.fromRgb(rgb)), codePoint);
});
}
+
+ public static FormattedCharSequence forwardWithTransformation(String text, CharSequenceTransformer transformer) {
+ if (text.isEmpty()) {
+ return FormattedCharSequence.EMPTY;
+ }
+ return sink -> {
+ int length = text.length();
+
+ for (int charIndex = 0; charIndex < length; ++charIndex) {
+ char c = text.charAt(charIndex);
+
+ if (Character.isHighSurrogate(c)) {
+ if (charIndex + 1 >= length) {
+ // Broken?
+ if (!sink.accept(charIndex, Style.EMPTY, 65533)) {
+ return false;
+ }
+ break;
+ }
+
+ char forward = text.charAt(charIndex + 1);
+ if (Character.isLowSurrogate(forward)) {
+ // Combine them together
+ if (!sink.accept(charIndex, Style.EMPTY, Character.toCodePoint(c, forward))) {
+ return false;
+ }
+
+ charIndex++;
+ } else {
+ // Broken?
+ if (!sink.accept(charIndex, Style.EMPTY, 65533)) {
+ return false;
+ }
+ }
+ } else if (Character.isSurrogate(c)) {
+ // This is weird, broken?
+ if (!sink.accept(charIndex, Style.EMPTY, 65533)) {
+ return false;
+ }
+ } else {
+ if (!sink.accept(charIndex, transformer.apply(text, charIndex, c), c)) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ };
+ }
+
+ @FunctionalInterface
+ public interface CharSequenceTransformer {
+ Style apply(String text, int charIndex, char c);
+ }
}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/entry/EmptyEntryDefinition.java b/runtime/src/main/java/me/shedaniel/rei/impl/entry/EmptyEntryDefinition.java
index a4daa0b3e..f75e38ade 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/entry/EmptyEntryDefinition.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/entry/EmptyEntryDefinition.java
@@ -39,6 +39,8 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Optional;
@ApiStatus.Internal
@@ -119,6 +121,11 @@ public enum EmptyEntryDefinition implements EntryDefinition<Unit> {
return ImmutableLiteralText.EMPTY;
}
+ @Override
+ public @NotNull Collection<ResourceLocation> getTagsFor(EntryStack<Unit> entry, Unit value) {
+ return Collections.emptyList();
+ }
+
private enum EmptyRenderer implements EntryRenderer<Unit> {
INSTANCE;
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/search/AlwaysMatchingArgument.java b/runtime/src/main/java/me/shedaniel/rei/impl/search/AlwaysMatchingArgument.java
index 7a0ed1523..7f76d0304 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/search/AlwaysMatchingArgument.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/search/AlwaysMatchingArgument.java
@@ -26,11 +26,13 @@ package me.shedaniel.rei.impl.search;
import me.shedaniel.rei.api.EntryStack;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
+import net.minecraft.util.Unit;
+import org.apache.commons.lang3.mutable.Mutable;
import org.jetbrains.annotations.ApiStatus;
@ApiStatus.Internal
@Environment(EnvType.CLIENT)
-public final class AlwaysMatchingArgument extends Argument {
+public final class AlwaysMatchingArgument extends Argument<Unit, Unit> {
public static final AlwaysMatchingArgument INSTANCE = new AlwaysMatchingArgument();
@Override
@@ -39,11 +41,16 @@ public final class AlwaysMatchingArgument extends Argument {
}
@Override
- public boolean matches(Object[] data, EntryStack<?> stack, String searchText, Object searchData) {
+ public boolean matches(Mutable<Unit> data, EntryStack<?> stack, String searchText, Unit filterData) {
return true;
}
@Override
+ public Unit prepareSearchFilter(String searchText) {
+ return Unit.INSTANCE;
+ }
+
+ @Override
public MatchStatus matchesArgumentPrefix(String text) {
return MatchStatus.unmatched();
}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/search/Argument.java b/runtime/src/main/java/me/shedaniel/rei/impl/search/Argument.java
index c74413625..2806f2d52 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/search/Argument.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/search/Argument.java
@@ -26,17 +26,18 @@ package me.shedaniel.rei.impl.search;
import me.shedaniel.rei.api.EntryStack;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
+import net.minecraft.network.chat.Style;
+import org.apache.commons.lang3.mutable.Mutable;
import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ApiStatus.Internal
@Environment(EnvType.CLIENT)
-public abstract class Argument {
+public abstract class Argument<T, R> {
public Argument() {
}
- private int dataOrdinal = -1;
-
public abstract String getName();
@Nullable
@@ -44,24 +45,21 @@ public abstract class Argument {
return null;