diff options
Diffstat (limited to 'runtime/src/main/java')
14 files changed, 812 insertions, 439 deletions
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringRulesScreen.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringRulesScreen.java index 624ba0315..6c6d4cceb 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringRulesScreen.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringRulesScreen.java @@ -33,12 +33,13 @@ import me.shedaniel.rei.api.client.entry.filtering.FilteringRuleType; import me.shedaniel.rei.api.client.gui.widgets.Widgets; import me.shedaniel.rei.api.client.registry.entry.EntryRegistry; import me.shedaniel.rei.api.common.util.CollectionUtils; -import me.shedaniel.rei.impl.client.entry.filtering.FilteringContextImpl; -import me.shedaniel.rei.impl.client.entry.filtering.FilteringResultImpl; +import me.shedaniel.rei.impl.client.entry.filtering.FilteringContextType; import me.shedaniel.rei.impl.client.entry.filtering.rules.ManualFilteringRule; import me.shedaniel.rei.impl.client.entry.filtering.rules.SearchFilteringRuleType; import me.shedaniel.rei.impl.client.gui.InternalTextures; import me.shedaniel.rei.impl.client.gui.widget.EntryWidget; +import me.shedaniel.rei.impl.common.entry.type.FilteringLogic; +import me.shedaniel.rei.impl.common.util.HashedEntryStackWrapper; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.events.GuiEventListener; @@ -54,6 +55,7 @@ import net.minecraft.sounds.SoundEvents; import java.util.*; import java.util.function.Consumer; import java.util.function.Function; +import java.util.stream.Collectors; public class FilteringRulesScreen extends Screen { private final FilteringEntry entry; @@ -268,21 +270,19 @@ public class FilteringRulesScreen extends Screen { public void addEntries(Consumer<RuleEntry> entryConsumer) { addEmpty(entryConsumer, 10); Function<Boolean, Component> function = bool -> { - return new TranslatableComponent("rule.roughlyenoughitems.filtering.search.show." + bool); + return Component.translatable("rule.roughlyenoughitems.filtering.search.show." + bool); }; - FilteringContextImpl context = new FilteringContextImpl(EntryRegistry.getInstance().getEntryStacks().toList()); - rule.processFilteredStacks(context, () -> new FilteringResultImpl(new ArrayList<>(), new ArrayList<>()), - rule.prepareCache(false), false); + Map<FilteringContextType, Set<HashedEntryStackWrapper>> stacks = FilteringLogic.hidden(FilteringLogic.getRules(), false, false, EntryRegistry.getInstance().getEntryStacks().collect(Collectors.toList())); entryConsumer.accept(new SubRulesEntry(rule, () -> function.apply(true), Collections.singletonList(new SearchFilteringRuleType.EntryStacksRuleEntry(rule, - Suppliers.ofInstance(CollectionUtils.map(context.getShownStacks(), - stack -> (EntryWidget) Widgets.createSlot(new Rectangle(0, 0, 18, 18)).disableBackground().entry(stack.normalize()))))))); + Suppliers.ofInstance(CollectionUtils.map(stacks.get(FilteringContextType.SHOWN), + stack -> (EntryWidget) Widgets.createSlot(new Rectangle(0, 0, 18, 18)).disableBackground().entry(stack.unwrap().normalize()))))))); addEmpty(entryConsumer, 10); entryConsumer.accept(new SubRulesEntry(rule, () -> function.apply(false), Collections.singletonList(new SearchFilteringRuleType.EntryStacksRuleEntry(rule, - Suppliers.ofInstance(CollectionUtils.map(context.getHiddenStacks(), - stack -> (EntryWidget) Widgets.createSlot(new Rectangle(0, 0, 18, 18)).disableBackground().entry(stack.normalize()))))))); + Suppliers.ofInstance(CollectionUtils.map(stacks.get(FilteringContextType.HIDDEN), + stack -> (EntryWidget) Widgets.createSlot(new Rectangle(0, 0, 18, 18)).disableBackground().entry(stack.unwrap().normalize()))))))); } @Override diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/entry/filtering/FilteringContextImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/entry/filtering/FilteringContextImpl.java index d0e26a9fc..697bcde63 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/entry/filtering/FilteringContextImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/entry/filtering/FilteringContextImpl.java @@ -27,6 +27,7 @@ import com.google.common.collect.Iterators; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; +import it.unimi.dsi.fastutil.longs.*; import me.shedaniel.rei.api.client.entry.filtering.FilteringContext; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.util.CollectionUtils; @@ -69,20 +70,35 @@ public class FilteringContextImpl implements FilteringContext { @Override public Collection<EntryStack<?>> getHiddenStacks() { - return getPublicFacing(FilteringContextType.HIDDEN); + return getStacksFacing(FilteringContextType.HIDDEN); } @Override public Collection<EntryStack<?>> getShownStacks() { - return getPublicFacing(FilteringContextType.SHOWN); + return getStacksFacing(FilteringContextType.SHOWN); } @Override public Collection<EntryStack<?>> getUnsetStacks() { - return getPublicFacing(FilteringContextType.DEFAULT); + return getStacksFacing(FilteringContextType.DEFAULT); } - private Collection<EntryStack<?>> getPublicFacing(FilteringContextType type) { + @Override + public LongCollection getHiddenExactHashes() { + return getHashesFacing(FilteringContextType.HIDDEN); + } + + @Override + public LongCollection getShownExactHashes() { + return getHashesFacing(FilteringContextType.SHOWN); + } + + @Override + public LongCollection getUnsetExactHashes() { + return getHashesFacing(FilteringContextType.DEFAULT); + } + + private Collection<EntryStack<?>> getStacksFacing(FilteringContextType type) { Set<HashedEntryStackWrapper> wrappers = this.stacks.get(type); if (wrappers == null || wrappers.isEmpty()) return List.of(); return new AbstractSet<>() { @@ -98,6 +114,33 @@ public class FilteringContextImpl implements FilteringContext { }; } + private LongCollection getHashesFacing(FilteringContextType type) { + Set<HashedEntryStackWrapper> wrappers = this.stacks.get(type); + if (wrappers == null || wrappers.isEmpty()) return LongSets.emptySet(); + return new AbstractLongSet() { + @Override + public LongIterator iterator() { + Iterator<HashedEntryStackWrapper> iterator = wrappers.iterator(); + return new AbstractLongIterator() { + @Override + public long nextLong() { + return iterator.next().hashExact(); + } + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + }; + } + + @Override + public int size() { + return wrappers.size(); + } + }; + } + public void handleResult(FilteringResultImpl result) { Collection<HashedEntryStackWrapper> hiddenStacks = result.hiddenStacks; Collection<HashedEntryStackWrapper> shownStacks = result.shownStacks; diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/entry/filtering/rules/BasicFilteringRuleImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/entry/filtering/rules/BasicFilteringRuleImpl.java index 1d51eb0f2..81aa7b3ab 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/entry/filtering/rules/BasicFilteringRuleImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/entry/filtering/rules/BasicFilteringRuleImpl.java @@ -23,133 +23,212 @@ package me.shedaniel.rei.impl.client.entry.filtering.rules; -import com.google.common.collect.Lists; import com.mojang.datafixers.util.Pair; +import com.mojang.datafixers.util.Unit; +import it.unimi.dsi.fastutil.longs.LongCollection; +import it.unimi.dsi.fastutil.longs.LongIterator; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import it.unimi.dsi.fastutil.longs.LongSet; +import me.shedaniel.clothconfig2.api.LazyResettable; import me.shedaniel.rei.api.client.entry.filtering.*; import me.shedaniel.rei.api.client.entry.filtering.base.BasicFilteringRule; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.registry.ReloadStage; -import me.shedaniel.rei.api.common.util.CollectionUtils; import me.shedaniel.rei.api.common.util.EntryStacks; import me.shedaniel.rei.impl.client.util.ThreadCreator; -import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.concurrent.*; +import java.util.concurrent.ExecutorService; +import java.util.function.Supplier; import java.util.stream.Collectors; -public enum BasicFilteringRuleImpl implements BasicFilteringRule<Pair<LongSet, LongSet>> { +public enum BasicFilteringRuleImpl implements BasicFilteringRule<Unit> { INSTANCE; private static final ExecutorService EXECUTOR_SERVICE = new ThreadCreator("REI-BasicFiltering").asService(); - private final List<EntryStack<?>> hidden = new ArrayList<>(), shown = new ArrayList<>(); + private final LongSet hiddenHashes = new LongOpenHashSet(), shownHashes = new LongOpenHashSet(); + private final List<CachedProvider> hiddenProviders = new ArrayList<>(), shownProviders = new ArrayList<>(); @Override - public FilteringRuleType<? extends FilteringRule<Pair<LongSet, LongSet>>> getType() { + public FilteringRuleType<? extends FilteringRule<Unit>> getType() { return BasicFilteringRuleType.INSTANCE; } @Override - public Pair<LongSet, LongSet> prepareCache(boolean async) { - return new Pair<>(prepareCacheFor(hidden, async), prepareCacheFor(shown, async)); - } - - @NotNull - private static LongSet prepareCacheFor(List<EntryStack<?>> stacks, boolean async) { - if (async) { - LongSet all = new LongOpenHashSet(); - List<CompletableFuture<LongSet>> completableFutures = Lists.newArrayList(); - for (Iterable<EntryStack<?>> partitionStacks : CollectionUtils.partition(stacks, 100)) { - completableFutures.add(CompletableFuture.supplyAsync(() -> { - LongSet output = new LongOpenHashSet(); - for (EntryStack<?> stack : partitionStacks) { - if (stack != null && !stack.isEmpty()) { - output.add(EntryStacks.hashExact(stack)); - } - } - return output; - }, EXECUTOR_SERVICE)); - } - try { - CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0])).get(5, TimeUnit.MINUTES); - } catch (InterruptedException | ExecutionException | TimeoutException e) { - e.printStackTrace(); - } - for (CompletableFuture<LongSet> future : completableFutures) { - LongSet now = future.getNow(null); - if (now != null) { - all.addAll(now); - } - } - return all; - } else { - return stacks.stream().map(EntryStacks::hashExact).collect(Collectors.toCollection(LongOpenHashSet::new)); + public Unit prepareCache(boolean async) { + for (CachedProvider provider : hiddenProviders) { + provider.get(); + } + for (CachedProvider provider : shownProviders) { + provider.get(); } + return Unit.INSTANCE; } @Override - public FilteringResult processFilteredStacks(FilteringContext context, FilteringResultFactory resultFactory, Pair<LongSet, LongSet> cache, boolean async) { + public FilteringResult processFilteredStacks(FilteringContext context, FilteringResultFactory resultFactory, Unit cache, boolean async) { FilteringResult result = resultFactory.create(); - hideList(context.getShownStacks(), result, async, cache.getFirst()); - hideList(context.getUnsetStacks(), result, async, cache.getFirst()); - showList(context.getHiddenStacks(), result, async, cache.getSecond()); - showList(context.getUnsetStacks(), result, async, cache.getSecond()); + hideList(context.getShownStacks(), context.getShownExactHashes(), result, async, hiddenHashes); + hideList(context.getUnsetStacks(), context.getUnsetExactHashes(), result, async, hiddenHashes); + + for (CachedProvider provider : hiddenProviders) { + hideList(context.getShownStacks(), context.getShownExactHashes(), result, async, provider.getExactHashes()); + hideList(context.getUnsetStacks(), context.getUnsetExactHashes(), result, async, provider.getExactHashes()); + } + + showList(context.getHiddenStacks(), context.getHiddenExactHashes(), result, async, shownHashes); + showList(context.getUnsetStacks(), context.getUnsetExactHashes(), result, async, shownHashes); + + for (CachedProvider provider : shownProviders) { + showList(context.getHiddenStacks(), context.getHiddenExactHashes(), result, async, provider.getExactHashes()); + showList(context.getUnsetStacks(), context.getUnsetExactHashes(), result, async, provider.getExactHashes()); + } + return result; } - private void hideList(Collection<EntryStack<?>> stacks, FilteringResult result, boolean async, LongSet filteredStacks) { - result.hide((async ? stacks.parallelStream() : stacks.stream()).filter(stack -> filteredStacks.contains(EntryStacks.hashExact(stack))).collect(Collectors.toList())); + private void hideList(Collection<EntryStack<?>> stacks, LongCollection hashes, FilteringResult result, boolean async, LongSet filteredStacks) { + LongIterator iterator = hashes.iterator(); + result.hide(stacks.stream() + .filter(stack -> filteredStacks.contains(iterator.nextLong())) + .collect(Collectors.toList())); } - private void showList(Collection<EntryStack<?>> stacks, FilteringResult result, boolean async, LongSet filteredStacks) { - result.show((async ? stacks.parallelStream() : stacks.stream()).filter(stack -> filteredStacks.contains(EntryStacks.hashExact(stack))).collect(Collectors.toList())); + private void showList(Collection<EntryStack<?>> stacks, LongCollection hashes, FilteringResult result, boolean async, LongSet filteredStacks) { + LongIterator iterator = hashes.iterator(); + result.show(stacks.stream() + .filter(stack -> filteredStacks.contains(iterator.nextLong())) + .collect(Collectors.toList())); } @Override public FilteringResult hide(EntryStack<?> stack) { - hidden.add(stack); - shown.remove(stack); + long hashExact = EntryStacks.hashExact(stack); + hiddenHashes.add(hashExact); + shownHashes.remove(hashExact); + + if (!isReloading()) { + markDirty(List.of(stack), null); + } + return this; } @Override public FilteringResult hide(Collection<? extends EntryStack<?>> stacks) { - hidden.addAll(stacks); - shown.removeAll(stacks); + for (EntryStack<?> stack : stacks) { + long hashExact = EntryStacks.hashExact(stack); + hiddenHashes.add(hashExact); + shownHashes.remove(hashExact); + } + + if (!isReloading()) { + markDirty((Collection<EntryStack<?>>) stacks, null); + } + return this; } @Override public FilteringResult show(EntryStack<?> stack) { - shown.add(stack); - hidden.remove(stack); + long hashExact = EntryStacks.hashExact(stack); + shownHashes.add(hashExact); + hiddenHashes.remove(hashExact); + + if (!isReloading()) { + markDirty(List.of(stack), null); + } + return this; } @Override public FilteringResult show(Collection<? extends EntryStack<?>> stacks) { - shown.addAll(stacks); - hidden.removeAll(stacks); + for (EntryStack<?> stack : stacks) { + long hashExact = EntryStacks.hashExact(stack); + shownHashes.add(hashExact); + hiddenHashes.remove(hashExact); + } + + if (!isReloading()) { + markDirty((Collection<EntryStack<?>>) stacks, null); + } + return this; } @Override + public MarkDirty hide(Supplier<Collection<EntryStack<?>>> provider) { + CachedProvider cachedProvider = new CachedProvider(provider); + shownProviders.remove(cachedProvider); + hiddenProviders.add(cachedProvider); + + cachedProvider.markDirty(); + return cachedProvider; + } + + @Override + public MarkDirty show(Supplier<Collection<EntryStack<?>>> provider) { + CachedProvider cachedProvider = new CachedProvider(provider); + hiddenProviders.remove(cachedProvider); + shownProviders.add(cachedProvider); + + cachedProvider.markDirty(); + return cachedProvider; + } + + @Override public ReloadStage getStage() { return ReloadStage.START; } @Override public void startReload() { - hidden.clear(); - shown.clear(); + hiddenHashes.clear(); + shownHashes.clear(); + hiddenProviders.clear(); + shownProviders.clear(); } @Override public void acceptPlugin(REIClientPlugin plugin) { plugin.registerBasicEntryFiltering(this); } + + private class CachedProvider implements MarkDirty { + private final Supplier<Collection<EntryStack<?>>> provider; + private final LazyResettable<Pair<Collection<EntryStack<?>>, LongSet>> cache = new LazyResettable<>(this::compose); + + private CachedProvider(Supplier<Collection<EntryStack<?>>> provider) { + this.provider = provider; + } + + @Override + public void markDirty() { + Pair<Collection<EntryStack<?>>, LongSet> prev = this.cache.get(); + this.cache.reset(); + Pair<Collection<EntryStack<?>>, LongSet> next = this.cache.get(); + BasicFilteringRuleImpl.this.markDirty(prev.getFirst(), prev.getSecond()); + BasicFilteringRuleImpl.this.markDirty(next.getFirst(), next.getSecond()); + } + + public Collection<EntryStack<?>> get() { + return this.cache.get().getFirst(); + } + + public LongSet getExactHashes() { + return this.cache.get().getSecond(); + } + + private Pair<Collection<EntryStack<?>>, LongSet> compose() { + Collection<EntryStack<?>> stacks = this.provider.get(); + LongSet hashes = new LongOpenHashSet(stacks.size()); + for (EntryStack<?> stack : stacks) { + hashes.add(EntryStacks.hashExact(stack)); + } + return Pair.of(stacks, hashes); + } + } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryImpl.java index af9f4ddb3..11d8e0501 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryImpl.java @@ -24,11 +24,9 @@ package me.shedaniel.rei.impl.common.entry.type; import com.google.common.collect.Lists; -import it.unimi.dsi.fastutil.longs.LongArrayList; -import it.unimi.dsi.fastutil.longs.LongList; -import it.unimi.dsi.fastutil.longs.LongOpenHashSet; -import it.unimi.dsi.fastutil.longs.LongSet; +import it.unimi.dsi.fastutil.longs.*; import me.shedaniel.rei.api.client.REIRuntime; +import me.shedaniel.rei.api.client.entry.filtering.FilteringRule; import me.shedaniel.rei.api.client.overlay.ScreenOverlay; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; import me.shedaniel.rei.api.client.registry.entry.EntryRegistry; @@ -40,6 +38,7 @@ import me.shedaniel.rei.api.common.registry.ReloadStage; import me.shedaniel.rei.api.common.util.CollectionUtils; import me.shedaniel.rei.api.common.util.EntryStacks; import me.shedaniel.rei.impl.common.InternalLogger; +import me.shedaniel.rei.impl.common.util.HashedEntryStackWrapper; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.core.NonNullList; @@ -58,16 +57,15 @@ import java.util.stream.Stream; @Environment(EnvType.CLIENT) public class EntryRegistryImpl implements EntryRegistry { public List<EntryRegistryListener> listeners = Lists.newCopyOnWriteArrayList(); - private PreFilteredEntryList preFilteredList; - private EntryRegistryList registryList; + private final EntryRegistryList registryList = new EntryRegistryListImpl(); + private FilteredEntryList filteredList; private LongSet entriesHash; private boolean reloading; public EntryRegistryImpl() { - registryList = new NormalEntryRegistryList(); - entriesHash = new LongOpenHashSet(); - preFilteredList = new PreFilteredEntryList(this); - listeners.add(preFilteredList); + this.entriesHash = new LongOpenHashSet(); + this.filteredList = new PreFilteredEntryList(this, this.registryList); + this.listeners.add(this.filteredList); } @Override @@ -82,21 +80,17 @@ public class EntryRegistryImpl implements EntryRegistry { @Override public void startReload() { - listeners.clear(); - registryList = new ReloadingEntryRegistryList(); - entriesHash = new LongOpenHashSet(); - preFilteredList = new PreFilteredEntryList(this); - listeners.add(preFilteredList); - reloading = true; + this.listeners.clear(); + this.registryList.collectHashed().clear(); + this.entriesHash = new LongOpenHashSet(); + this.filteredList = new PreFilteredEntryList(this, this.registryList); + this.listeners.add(filteredList); + this.reloading = true; } @Override public void endReload() { - reloading = false; - if (!(registryList instanceof ReloadingEntryRegistryList)) { - throw new IllegalStateException("Expected ReloadingEntryRegistryList, got " + registryList.getClass().getName()); - } - registryList = new NormalEntryRegistryList(registryList.stream().filter(((Predicate<EntryStack<?>>) EntryStack::isEmpty).negate())); + this.reloading = false; refilter(); REIRuntime.getInstance().getOverlay().ifPresent(ScreenOverlay::queueReloadOverlay); InternalLogger.getInstance().debug("Reloaded entry registry with %d entries and %d filtered entries", size(), getPreFilteredList().size()); @@ -108,6 +102,11 @@ public class EntryRegistryImpl implements EntryRegistry { } @Override + public <Cache> void markFilteringRuleDirty(FilteringRule<Cache> cacheFilteringRule, Collection<EntryStack<?>> stacks, @Nullable LongCollection hashes) { + this.filteredList.refreshFilteringFor(Set.of(cacheFilteringRule), stacks, hashes); + } + + @Override public int size() { return registryList.size(); } @@ -119,12 +118,12 @@ public class EntryRegistryImpl implements EntryRegistry { @Override public List<EntryStack<?>> getPreFilteredList() { - return Collections.unmodifiableList(preFilteredList.getList()); + return Collections.unmodifiableList(filteredList.getList()); } @Override public void refilter() { - List<EntryStack<?>> stacks = registryList.collect(); + List<HashedEntryStackWrapper> stacks = registryList.collectHashed(); for (EntryRegistryListener listener : listeners) { listener.onReFilter(stacks); @@ -161,7 +160,8 @@ public class EntryRegistryImpl implements EntryRegistry { @ApiStatus.Internal @Override public Collection<EntryStack<?>> refilterNew(boolean warn, Collection<EntryStack<?>> entries) { - return preFilteredList.refilterNew(warn, entries); + if (warn) FilteringLogic.warnFiltering(); + return FilteringLogic.filter(FilteringLogic.getRules(), false, true, entries); } @Override @@ -236,9 +236,8 @@ public class EntryRegistryImpl implements EntryRegistry { List<EntryStack<?>> removedStacks = new ArrayList<>(); LongList hashes = registryList.needsHash() ? new LongArrayList() : null; - boolean removed = registryList.removeIf(stack -> { + boolean removed = registryList.removeExactIf((stack, hashExact) -> { if (((Predicate<EntryStack<?>>) predicate).test(stack)) { - long hashExact = EntryStacks.hashExact(stack); entriesHash.remove(hashExact); removedStacks.add(stack); if (hashes != null) hashes.add(hashExact); @@ -259,37 +258,35 @@ public class EntryRegistryImpl implements EntryRegistry { @Override public boolean removeEntryExactHashIf(LongPredicate predicate) { - LongPredicate entryStackPredicate = hash -> { + EntryRegistryList.StackFilteringPredicate entryStackPredicate = (stack, hash) -> { if (predicate.test(hash)) { entriesHash.remove(hash); + for (EntryRegistryListener listener : listeners) { + listener.removeEntry(stack, hash); + } return true; } return false; }; - for (EntryRegistryListener listener : listeners) { - listener.removeEntriesIf(stack -> predicate.test(EntryStacks.hashExact(stack))); - } - return registryList.removeExactIf(entryStackPredicate); } @Override public boolean removeEntryFuzzyHashIf(LongPredicate predicate) { - Predicate<EntryStack<?>> entryStackPredicate = stack -> { + EntryRegistryList.StackFilteringPredicate entryStackPredicate = (stack, hashExact) -> { if (predicate.test(EntryStacks.hashFuzzy(stack))) { - entriesHash.remove(EntryStacks.hashExact(stack)); + entriesHash.remove(hashExact); + for (EntryRegistryListener listener : listeners) { + listener.removeEntry(stack, hashExact); + } return true; } return false; }; - for (EntryRegistryListener listener : listeners) { - listener.removeEntriesIf(entryStackPredicate); - } - - return registryList.removeIf(entryStackPredicate); + return registryList.removeExactIf(entryStackPredicate); } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryList.java b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryList.java index 2672b077a..4d146f94b 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryList.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryList.java @@ -25,10 +25,9 @@ package me.shedaniel.rei.impl.common.entry.type; import it.unimi.dsi.fastutil.longs.LongList; import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.impl.common.util.HashedEntryStackWrapper; import java.util.List; -import java.util.function.LongPredicate; -import java.util.function.Predicate; import java.util.stream.Stream; public interface EntryRegistryList { @@ -38,6 +37,8 @@ public interface EntryRegistryList { List<EntryStack<?>> collect(); + List<HashedEntryStackWrapper> collectHashed(); + int indexOf(EntryStack<?> stack); int lastIndexOf(EntryStack<?> stack); @@ -52,9 +53,11 @@ public interface EntryRegistryList { void remove(EntryStack<?> stack, long hashExact); - boolean removeIf(Predicate<? extends EntryStack<?>> predicate); - - boolean removeExactIf(LongPredicate predicate); + boolean removeExactIf(StackFilteringPredicate predicate); boolean needsHash(); + + interface StackFilteringPredicate { + boolean test(EntryStack<?> stack, long hashExact); + } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryListImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryListImpl.java new file mode 100644 index 000000000..d43627aca --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryListImpl.java @@ -0,0 +1,206 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.impl.common.entry.type; + +import it.unimi.dsi.fastutil.longs.LongList; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.impl.common.util.HashedEntryStackWrapper; +import net.minecraft.core.Registry; + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class EntryRegistryListImpl implements EntryRegistryList { + private final List<HashedEntryStackWrapper> hashedList = new ArrayList<>(Registry.ITEM.keySet().size() + 100); + private final List<EntryStack<?>> list = createMappedList(hashedList); + + public EntryRegistryListImpl() { + } + + public EntryRegistryListImpl(Stream<EntryStack<?>> list) { + list.collect(Collectors.toCollection(() -> this.list)); + } + + @Override + public int size() { + return list.size(); + } + + @Override + public Stream<EntryStack<?>> stream() { + return list.stream(); + } + + @Override + public List<EntryStack<?>> collect() { + return list; + } + + @Override + public List<HashedEntryStackWrapper> collectHashed() { + return hashedList; + } + + @Override + public int indexOf(EntryStack<?> stack) { + return list.indexOf(stack); + } |
