diff options
| author | shedaniel <daniel@shedaniel.me> | 2021-03-21 23:29:30 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2021-03-21 23:29:30 +0800 |
| commit | 7bbef49785f594dfe3d6eac0cfc6ee84841aae80 (patch) | |
| tree | 257f04b3d0e32001ba140967ff505d128f303ffc | |
| parent | 53a861009ae84680993ee95355155fddc4554490 (diff) | |
| download | RoughlyEnoughItems-7bbef49785f594dfe3d6eac0cfc6ee84841aae80.tar.gz RoughlyEnoughItems-7bbef49785f594dfe3d6eac0cfc6ee84841aae80.tar.bz2 RoughlyEnoughItems-7bbef49785f594dfe3d6eac0cfc6ee84841aae80.zip | |
Rewrite search engine and expose as API
Signed-off-by: shedaniel <daniel@shedaniel.me>
35 files changed, 701 insertions, 391 deletions
diff --git a/api/src/main/java/me/shedaniel/rei/api/config/ConfigObject.java b/api/src/main/java/me/shedaniel/rei/api/config/ConfigObject.java index 4000844cb..d7cfb2023 100644 --- a/api/src/main/java/me/shedaniel/rei/api/config/ConfigObject.java +++ b/api/src/main/java/me/shedaniel/rei/api/config/ConfigObject.java @@ -172,5 +172,7 @@ public interface ConfigObject { SearchMode getTagSearchMode(); + SearchMode getIdentifierSearchMode(); + SearchMode getModSearchMode(); } diff --git a/api/src/main/java/me/shedaniel/rei/api/ingredient/EntryStack.java b/api/src/main/java/me/shedaniel/rei/api/ingredient/EntryStack.java index 6f4b7294f..ad7857fe3 100644 --- a/api/src/main/java/me/shedaniel/rei/api/ingredient/EntryStack.java +++ b/api/src/main/java/me/shedaniel/rei/api/ingredient/EntryStack.java @@ -47,7 +47,10 @@ import net.minecraft.util.Unit; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; @@ -113,7 +116,8 @@ public interface EntryStack<T> extends TextRepresentable, Renderer { return renderer == null ? EntryRenderer.empty() : renderer.cast(); } - Optional<ResourceLocation> getIdentifier(); + @Nullable + ResourceLocation getIdentifier(); boolean isEmpty(); @@ -131,8 +135,6 @@ public interface EntryStack<T> extends TextRepresentable, Renderer { int hash(ComparisonContext context); - boolean equals(EntryStack<T> other, ComparisonContext context); - @Deprecated boolean equals(Object o); diff --git a/api/src/main/java/me/shedaniel/rei/api/ingredient/entry/type/EntryDefinition.java b/api/src/main/java/me/shedaniel/rei/api/ingredient/entry/type/EntryDefinition.java index a4ba8f2bd..8011364d5 100644 --- a/api/src/main/java/me/shedaniel/rei/api/ingredient/entry/type/EntryDefinition.java +++ b/api/src/main/java/me/shedaniel/rei/api/ingredient/entry/type/EntryDefinition.java @@ -33,7 +33,6 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.util.Collection; -import java.util.Optional; public interface EntryDefinition<T> { Class<T> getValueType(); @@ -42,7 +41,7 @@ public interface EntryDefinition<T> { EntryRenderer<T> getRenderer(); - Optional<ResourceLocation> getIdentifier(EntryStack<T> entry, T value); + @Nullable ResourceLocation getIdentifier(EntryStack<T> entry, T value); boolean isEmpty(EntryStack<T> entry, T value); diff --git a/api/src/main/java/me/shedaniel/rei/api/ingredient/util/EntryStacks.java b/api/src/main/java/me/shedaniel/rei/api/ingredient/util/EntryStacks.java index b8a281ed2..80d007f6a 100644 --- a/api/src/main/java/me/shedaniel/rei/api/ingredient/util/EntryStacks.java +++ b/api/src/main/java/me/shedaniel/rei/api/ingredient/util/EntryStacks.java @@ -141,15 +141,15 @@ public final class EntryStacks { EntryType<A> leftType = left.getType(); EntryType<B> rightType = right.getType(); if (leftType == rightType) { - return left.equals((EntryStack<A>) right, context); + return left.getDefinition().equals(left.getValue(), right.<A>cast().getValue(), context); } - if (context == ComparisonContext.EXACT) return false; for (EntryTypeBridge<A, B> bridge : EntryTypeRegistry.getInstance().getBridgesFor(leftType, rightType)) { InteractionResultHolder<Stream<EntryStack<B>>> holder = bridge.bridge(left); if (holder.getResult() == InteractionResult.SUCCESS) { Iterator<EntryStack<B>> iterator = holder.getObject().iterator(); while (iterator.hasNext()) { - if (iterator.next().equals(right, context)) { + EntryStack<B> next = iterator.next(); + if (next.getDefinition().equals(next.getValue(), right.getValue(), context)) { return true; } } @@ -160,7 +160,8 @@ public final class EntryStacks { if (holder.getResult() == InteractionResult.SUCCESS) { Iterator<EntryStack<A>> iterator = holder.getObject().iterator(); while (iterator.hasNext()) { - if (iterator.next().equals(left, context)) { + EntryStack<A> next = iterator.next(); + if (next.getDefinition().equals(next.getValue(), left.getValue(), context)) { return true; } } diff --git a/api/src/main/java/me/shedaniel/rei/api/search/SearchFilter.java b/api/src/main/java/me/shedaniel/rei/api/search/SearchFilter.java new file mode 100644 index 000000000..d24241d84 --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/search/SearchFilter.java @@ -0,0 +1,42 @@ +package me.shedaniel.rei.api.search; + +import me.shedaniel.rei.api.ingredient.EntryStack; + +import java.util.function.Predicate; + +public interface SearchFilter extends Predicate<EntryStack<?>> { + static SearchFilter matchAll() { + return new SearchFilter() { + @Override + public String getFilter() { + return ""; + } + + @Override + public boolean test(EntryStack<?> entryStack) { + return true; + } + }; + } + + static SearchFilter matchNone() { + return new SearchFilter() { + @Override + public String getFilter() { + return ""; + } + + @Override + public boolean test(EntryStack<?> entryStack) { + return false; + } + }; + } + + /** + * Returns the original filter in {@link String}. + * + * @return the original filter + */ + String getFilter(); +} diff --git a/api/src/main/java/me/shedaniel/rei/api/search/SearchProvider.java b/api/src/main/java/me/shedaniel/rei/api/search/SearchProvider.java new file mode 100644 index 000000000..51abc5a14 --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/search/SearchProvider.java @@ -0,0 +1,19 @@ +package me.shedaniel.rei.api.search; + +import me.shedaniel.rei.api.plugins.PluginManager; +import me.shedaniel.rei.api.registry.Reloadable; + +public interface SearchProvider extends Reloadable { + static SearchProvider getInstance() { + return PluginManager.getInstance().get(SearchProvider.class); + } + + /** + * Creates a search filter, which respects user's config options and + * respects argument prefixes. + * + * @param searchTerm the search term of the filter + * @return the search filter + */ + SearchFilter createFilter(String searchTerm); +} diff --git a/runtime/src/main/java/me/shedaniel/rei/api/gui/config/entry/FilteringScreen.java b/runtime/src/main/java/me/shedaniel/rei/api/gui/config/entry/FilteringScreen.java index ac7a5e0d6..798a1c9e3 100644 --- a/runtime/src/main/java/me/shedaniel/rei/api/gui/config/entry/FilteringScreen.java +++ b/runtime/src/main/java/me/shedaniel/rei/api/gui/config/entry/FilteringScreen.java @@ -43,10 +43,13 @@ import me.shedaniel.rei.api.REIHelper; import me.shedaniel.rei.api.gui.widgets.Tooltip; import me.shedaniel.rei.api.ingredient.EntryStack; import me.shedaniel.rei.api.registry.entry.EntryRegistry; +import me.shedaniel.rei.api.search.SearchFilter; +import me.shedaniel.rei.api.search.SearchProvider; import me.shedaniel.rei.gui.ContainerScreenOverlay; import me.shedaniel.rei.gui.OverlaySearchField; import me.shedaniel.rei.gui.widget.EntryWidget; -import me.shedaniel.rei.impl.SearchArgument; +import me.shedaniel.rei.impl.search.Argument; +import me.shedaniel.rei.impl.search.CompoundArgument; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.events.GuiEventListener; @@ -103,7 +106,7 @@ public class FilteringScreen extends Screen { private Button backButton; private Rectangle selectionCache; - private List<SearchArgument.SearchArguments> lastSearchArguments = Collections.emptyList(); + private SearchFilter lastFilter = SearchFilter.matchAll(); public FilteringScreen(FilteringEntry filteringEntry) { super(new TranslatableComponent("config.roughlyenoughitems.filteringScreen")); @@ -311,10 +314,10 @@ public class FilteringScreen extends Screen { } public void updateSearch(String searchTerm) { - lastSearchArguments = SearchArgument.processSearchTerm(searchTerm); + lastFilter = SearchProvider.getInstance().createFilter(searchTerm); Set<EntryStack<?>> list = Sets.newLinkedHashSet(); EntryRegistry.getInstance().getEntryStacks().forEach(stack -> { - if (canLastSearchTermsBeAppliedTo(stack)) { + if (matches(stack)) { list.add(stack.normalize()); } }); @@ -323,8 +326,8 @@ public class FilteringScreen extends Screen { updateEntriesPosition(); } - public boolean canLastSearchTermsBeAppliedTo(EntryStack<?> stack) { - return lastSearchArguments.isEmpty() || SearchArgument.canSearchTermsBeAppliedTo(stack, lastSearchArguments); + public boolean matches(EntryStack<?> stack) { + return lastFilter.test(stack); } public void updateEntriesPosition() { 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 8d1a1209a..e466e342b 100644 --- a/runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java +++ b/runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java @@ -557,7 +557,7 @@ public class ContainerScreenOverlay extends REIOverlay { AbstractContainerScreen<?> containerScreen = (AbstractContainerScreen<?>) Minecraft.getInstance().screen; int x = containerScreen.leftPos, y = containerScreen.topPos; for (Slot slot : containerScreen.getMenu().slots) - if (!slot.hasItem() || !ENTRY_LIST_WIDGET.canLastSearchTermsBeAppliedTo(EntryStacks.of(slot.getItem()))) + if (!slot.hasItem() || !ENTRY_LIST_WIDGET.matches(EntryStacks.of(slot.getItem()))) fillGradient(matrices, x + slot.x, y + slot.y, x + slot.x + 16, y + slot.y + 16, -601874400, -601874400); } matrices.popPose(); 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 9a06211a2..3591f0ab6 100644 --- a/runtime/src/main/java/me/shedaniel/rei/gui/OverlaySearchField.java +++ b/runtime/src/main/java/me/shedaniel/rei/gui/OverlaySearchField.java @@ -35,9 +35,9 @@ import me.shedaniel.rei.api.REIHelper; import me.shedaniel.rei.api.gui.config.SyntaxHighlightingMode; import me.shedaniel.rei.impl.OverlaySearchFieldSyntaxHighlighter; 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 me.shedaniel.rei.impl.search.ArgumentType; +import me.shedaniel.rei.impl.search.ArgumentTypesRegistry; +import me.shedaniel.rei.impl.search.TextArgumentType; import me.shedaniel.rei.impl.widgets.TextFieldWidget; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; @@ -84,11 +84,11 @@ public class OverlaySearchField extends TextFieldWidget implements TextFieldWidg style = ERROR_STYLE; } if (arg > 0) { - Argument<?, ?> argument = ArgumentsRegistry.ARGUMENT_LIST.get((arg - 1) / 2); + ArgumentType<?, ?> argumentType = ArgumentTypesRegistry.ARGUMENT_TYPE_LIST.get((arg - 1) / 2); if (!isPlain) { - style = argument.getHighlightedStyle(); + style = argumentType.getHighlightedStyle(); } - if (!(argument instanceof TextArgument) && hasUnderscore && arg % 2 == 1) { + if (!(argumentType instanceof TextArgumentType) && hasUnderscore && arg % 2 == 1) { style = style.withUnderlined(true); } } else if (!isPlain) { 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 b7d6312b4..85f3e8d86 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 @@ -57,10 +57,12 @@ 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.*; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -69,23 +71,24 @@ public class FluidEntryDefinition implements EntryDefinition<FluidStack>, EntryS private final EntryRenderer<FluidStack> renderer = new FluidEntryRenderer(); @Override - public @NotNull Class<FluidStack> getValueType() { + public Class<FluidStack> getValueType() { return FluidStack.class; } @Override - public @NotNull EntryType<FluidStack> getType() { + public EntryType<FluidStack> getType() { return VanillaEntryTypes.FLUID; } @Override - public @NotNull EntryRenderer<FluidStack> getRenderer() { + public EntryRenderer<FluidStack> getRenderer() { return renderer; } @Override - public @NotNull Optional<ResourceLocation> getIdentifier(EntryStack<FluidStack> entry, FluidStack value) { - return Optional.ofNullable(Registry.FLUID.getKey(value.getFluid())); + @Nullable + public ResourceLocation getIdentifier(EntryStack<FluidStack> entry, FluidStack value) { + return Registry.FLUID.getKey(value.getFluid()); } @Override @@ -153,12 +156,12 @@ public class FluidEntryDefinition implements EntryDefinition<FluidStack>, EntryS } @Override - public @NotNull Component asFormattedText(EntryStack<FluidStack> entry, FluidStack value) { + public Component asFormattedText(EntryStack<FluidStack> entry, FluidStack value) { return value.getFluid().defaultFluidState().createLegacyBlock().getBlock().getName(); } @Override - public @NotNull Collection<ResourceLocation> getTagsFor(EntryStack<FluidStack> entry, FluidStack value) { + public Collection<ResourceLocation> getTagsFor(EntryStack<FluidStack> entry, FluidStack value) { TagCollection<Fluid> collection = Minecraft.getInstance().getConnection().getTags().getFluids(); return collection == null ? Collections.emptyList() : collection.getMatchingTags(value.getFluid()); } 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 f3c913b72..3385ae958 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 @@ -32,8 +32,6 @@ import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; import it.unimi.dsi.fastutil.objects.ReferenceSet; import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; -import me.shedaniel.rei.api.ClientHelper; -import me.shedaniel.rei.api.config.ConfigObject; import me.shedaniel.rei.api.gui.widgets.Tooltip; import me.shedaniel.rei.api.ingredient.EntryStack; import me.shedaniel.rei.api.ingredient.entry.*; @@ -55,8 +53,6 @@ import net.minecraft.client.resources.language.I18n; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.Registry; import net.minecraft.nbt.CompoundTag; -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; @@ -90,8 +86,9 @@ public class ItemEntryDefinition implements EntryDefinition<ItemStack>, EntrySer } @Override - public @NotNull Optional<ResourceLocation> getIdentifier(EntryStack<ItemStack> entry, ItemStack value) { - return Optional.ofNullable(Registry.ITEM.getKey(value.getItem())); + @Nullable + public ResourceLocation getIdentifier(EntryStack<ItemStack> entry, ItemStack value) { + return Registry.ITEM.getKey(value.getItem()); } @Override diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java b/runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java index 005f670be..242be27be 100644 --- a/runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java @@ -57,12 +57,15 @@ import me.shedaniel.rei.api.ingredient.util.EntryStacks; import me.shedaniel.rei.api.registry.entry.EntryRegistry; import me.shedaniel.rei.api.registry.screen.OverlayDecider; import me.shedaniel.rei.api.registry.screen.ScreenRegistry; +import me.shedaniel.rei.api.search.SearchFilter; +import me.shedaniel.rei.api.search.SearchProvider; import me.shedaniel.rei.api.util.CollectionUtils; import me.shedaniel.rei.api.view.Views; import me.shedaniel.rei.gui.ContainerScreenOverlay; import me.shedaniel.rei.impl.ConfigManagerImpl; import me.shedaniel.rei.impl.ConfigObjectImpl; -import me.shedaniel.rei.impl.SearchArgument; +import me.shedaniel.rei.impl.search.Argument; +import me.shedaniel.rei.impl.search.CompoundArgument; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.player.LocalPlayer; @@ -128,7 +131,7 @@ public class EntryListWidget extends WidgetWithBounds { private List<EntryListEntry> entries = Collections.emptyList(); private List<Widget> renders = Collections.emptyList(); private List<Widget> widgets = Collections.emptyList(); - private List<SearchArgument.SearchArguments> lastSearchArguments = Collections.emptyList(); + private SearchFilter lastFilter = SearchFilter.matchAll(); private String lastSearchTerm = null; public static int entrySize() { @@ -519,7 +522,7 @@ public class EntryListWidget extends WidgetWithBounds { Stopwatch stopwatch = Stopwatch.createStarted(); if (ignoreLastSearch || this.lastSearchTerm == null || !this.lastSearchTerm.equals(searchTerm)) { this.lastSearchTerm = searchTerm; - this.lastSearchArguments = SearchArgument.processSearchTerm(searchTerm); + this.lastFilter = SearchProvider.getInstance().createFilter(searchTerm); List<EntryStack<?>> list = Lists.newArrayList(); boolean checkCraftable = ConfigManager.getInstance().isCraftableOnlyEnabled() && !ContainerScreenOverlay.getInstance().inventoryStacks.isEmpty(); IntSet workingItems = checkCraftable ? new IntOpenHashSet() : null; @@ -533,7 +536,7 @@ public class EntryListWidget extends WidgetWithBounds { completableFutures.add(CompletableFuture.supplyAsync(() -> { List<EntryStack<?>> filtered = Lists.newArrayList(); for (EntryStack<?> stack : partitionStacks) { - if (canLastSearchTermsBeAppliedTo(stack)) { + if (matches(stack)) { if (workingItems != null && !workingItems.contains(EntryStacks.hashExact(stack))) continue; filtered.add(stack.normalize()); @@ -554,7 +557,7 @@ public class EntryListWidget extends WidgetWithBounds { } } else { for (EntryStack<?> stack : stacks) { - if (canLastSearchTermsBeAppliedTo(stack)) { + if (matches(stack)) { if (workingItems != null && !workingItems.contains(EntryStacks.hashExact(stack))) continue; list.add(stack.normalize()); @@ -580,8 +583,8 @@ public class EntryListWidget extends WidgetWithBounds { updateEntriesPosition(); } - public boolean canLastSearchTermsBeAppliedTo(EntryStack<?> stack) { - return lastSearchArguments.isEmpty() || SearchArgument.canSearchTermsBeAppliedTo(stack, lastSearchArguments); + public boolean matches(EntryStack<?> stack) { + return lastFilter.test(stack); } @Override diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/AbstractEntryStack.java b/runtime/src/main/java/me/shedaniel/rei/impl/AbstractEntryStack.java index c065ff64e..c77193309 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/AbstractEntryStack.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/AbstractEntryStack.java @@ -36,6 +36,7 @@ import me.shedaniel.rei.api.gui.widgets.Tooltip; import me.shedaniel.rei.api.ingredient.EntryStack; import me.shedaniel.rei.api.ingredient.entry.comparison.ComparisonContext; import me.shedaniel.rei.api.ingredient.util.EntryStacks; +import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -107,13 +108,16 @@ public abstract class AbstractEntryStack<A> extends AbstractRenderer implements @Override @Nullable public Tooltip getTooltip(Point mouse) { - Tooltip[] tooltip = {this.getDefinition().getRenderer().getTooltip(this, mouse)}; + Tooltip[] tooltip = {this.get(Settings.RENDER).apply(this).<A>cast().getTooltip(this, mouse)}; if (tooltip[0] == null) return null; tooltip[0].getText().addAll(get(EntryStack.Settings.TOOLTIP_APPEND_EXTRA).apply(this)); tooltip[0] = get(EntryStack.Settings.TOOLTIP_PROCESSOR).apply(this, tooltip[0]); if (tooltip[0] == null) return null; if (ConfigObject.getInstance().shouldAppendModNames()) { - getIdentifier().ifPresent(location -> ClientHelper.getInstance().appendModIdToTooltips(tooltip[0].getText(), location.getNamespace())); + ResourceLocation location = getIdentifier(); + if (location != null) { + ClientHelper.getInstance().appendModIdToTooltips(tooltip[0].getText(), location.getNamespace()); + } } return tooltip[0]; } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java index e2e2460a6..a498fd2f1 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/ClientHelperImpl.java @@ -172,9 +172,10 @@ public class ClientHelperImpl implements ClientHelper { return false; } } else { - ResourceLocation identifier = entry.getIdentifier().orElse(null); - if (i |
