diff options
| author | shedaniel <daniel@shedaniel.me> | 2022-11-27 17:50:11 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2022-11-27 18:05:58 +0800 |
| commit | 2123544fcf3ad7ec6d89e671a993a75737e3a44e (patch) | |
| tree | d9f47994a2d3f715914eaa703ad05c55aba274b5 | |
| parent | 9c865aff50b8c49e89ee1a7d6319d52cdcdd229a (diff) | |
| download | RoughlyEnoughItems-2123544fcf3ad7ec6d89e671a993a75737e3a44e.tar.gz RoughlyEnoughItems-2123544fcf3ad7ec6d89e671a993a75737e3a44e.tar.bz2 RoughlyEnoughItems-2123544fcf3ad7ec6d89e671a993a75737e3a44e.zip | |
Make filtering more immediate
18 files changed, 876 insertions, 439 deletions
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/entry/filtering/FilteringContext.java b/api/src/main/java/me/shedaniel/rei/api/client/entry/filtering/FilteringContext.java index d46709af9..8cf2179e0 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/entry/filtering/FilteringContext.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/entry/filtering/FilteringContext.java @@ -23,6 +23,7 @@ package me.shedaniel.rei.api.client.entry.filtering; +import it.unimi.dsi.fastutil.longs.LongCollection; import me.shedaniel.rei.api.common.entry.EntryStack; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -53,4 +54,28 @@ public interface FilteringContext { * @return the list of stacks that are previously marked as hidden from other filtering rules. */ Collection<EntryStack<?>> getHiddenStacks(); + + /** + * Returns the list of hashes that are previously marked as <b>shown</b> from other filtering rules. + * + * @return the list of hashes that are previously marked as shown from other filtering rules. + */ + @ApiStatus.Experimental + LongCollection getShownExactHashes(); + + /** + * Returns the list of hashes that are previously marked as <b>hidden</b> from other filtering rules. + * + * @return the list of hashes that are previously marked as hidden from other filtering rules. + */ + @ApiStatus.Experimental + LongCollection getUnsetExactHashes(); + + /** + * Returns the list of hashes that are previously marked as <b>hidden</b> from other filtering rules. + * + * @return the list of hashes that are previously marked as hidden from other filtering rules. + */ + @ApiStatus.Experimental + LongCollection getHiddenExactHashes(); } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/entry/filtering/FilteringRule.java b/api/src/main/java/me/shedaniel/rei/api/client/entry/filtering/FilteringRule.java index 1f3cb5b50..a133de686 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/entry/filtering/FilteringRule.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/entry/filtering/FilteringRule.java @@ -23,9 +23,15 @@ package me.shedaniel.rei.api.client.entry.filtering; +import it.unimi.dsi.fastutil.longs.LongCollection; +import me.shedaniel.rei.api.client.registry.entry.EntryRegistry; +import me.shedaniel.rei.api.common.entry.EntryStack; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; /** * A filtering rule type that is used to filter the entries on the entry panel, @@ -63,4 +69,20 @@ public interface FilteringRule<Cache> { * @return the result of the processing */ FilteringResult processFilteredStacks(FilteringContext context, FilteringResultFactory resultFactory, Cache cache, boolean async); + + /** + * Returns whether the entry registry is in its reloading phase. + * Registration after the reloading phase will be slow and may not be reflected immediately. + * + * @return whether the entry registry is in its reloading phase + */ + @ApiStatus.NonExtendable + default boolean isReloading() { + return EntryRegistry.getInstance().isReloading(); + } + + @ApiStatus.NonExtendable + default void markDirty(Collection<EntryStack<?>> stacks, @Nullable LongCollection hashes) { + EntryRegistry.getInstance().markFilteringRuleDirty(this, stacks, hashes); + } }
\ No newline at end of file diff --git a/api/src/main/java/me/shedaniel/rei/api/client/entry/filtering/base/BasicFilteringRule.java b/api/src/main/java/me/shedaniel/rei/api/client/entry/filtering/base/BasicFilteringRule.java index 26b2986c2..4800a430e 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/entry/filtering/base/BasicFilteringRule.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/entry/filtering/base/BasicFilteringRule.java @@ -26,11 +26,15 @@ package me.shedaniel.rei.api.client.entry.filtering.base; import me.shedaniel.rei.api.client.entry.filtering.FilteringResult; import me.shedaniel.rei.api.client.entry.filtering.FilteringRule; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; +import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.registry.Reloadable; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import org.jetbrains.annotations.ApiStatus; +import java.util.Collection; +import java.util.function.Supplier; + /** * The basic filtering rule that can be used to filter entries, * without registering a new filtering rule type, for external @@ -41,4 +45,12 @@ import org.jetbrains.annotations.ApiStatus; @ApiStatus.Experimental @Environment(EnvType.CLIENT) public interface BasicFilteringRule<Cache> extends Reloadable<REIClientPlugin>, FilteringRule<Cache>, FilteringResult { + MarkDirty hide(Supplier<Collection<EntryStack<?>>> provider); + + MarkDirty show(Supplier<Collection<EntryStack<?>>> provider); + + @ApiStatus.NonExtendable + interface MarkDirty { + void markDirty(); + } } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/EntryRegistry.java b/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/EntryRegistry.java index 63ed14d72..9e4713957 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/EntryRegistry.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/EntryRegistry.java @@ -23,6 +23,8 @@ package me.shedaniel.rei.api.client.registry.entry; +import it.unimi.dsi.fastutil.longs.LongCollection; +import me.shedaniel.rei.api.client.entry.filtering.FilteringRule; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.plugins.PluginManager; @@ -207,4 +209,7 @@ public interface EntryRegistry extends Reloadable<REIClientPlugin> { * @return whether the registry is in its reloading phase */ boolean isReloading(); + + @ApiStatus.Experimental + <Cache> void markFilteringRuleDirty(FilteringRule<Cache> cacheFilteringRule, Collection<EntryStack<?>> stacks, @Nullable LongCollection hashes); } 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 % |
