diff options
| author | shedaniel <daniel@shedaniel.me> | 2021-01-04 20:14:07 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2021-01-04 20:14:07 +0800 |
| commit | 5385aa5bda42b586f6da45f17f1b3309e0bc900a (patch) | |
| tree | f6f24a8eb18b09d9ada42e9b045fea441a8007b2 /runtime/src/main | |
| parent | 67171a5ff24ed77e6c4cc889543e8dfb543e8fe5 (diff) | |
| download | RoughlyEnoughItems-5385aa5bda42b586f6da45f17f1b3309e0bc900a.tar.gz RoughlyEnoughItems-5385aa5bda42b586f6da45f17f1b3309e0bc900a.tar.bz2 RoughlyEnoughItems-5385aa5bda42b586f6da45f17f1b3309e0bc900a.zip | |
Search Syntax Highlighting
Signed-off-by: shedaniel <daniel@shedaniel.me>
Diffstat (limited to 'runtime/src/main')
19 files changed, 434 insertions, 121 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; + } + + @Overr |
