diff options
| author | shedaniel <daniel@shedaniel.me> | 2022-06-21 22:04:46 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2022-06-28 03:21:12 +0800 |
| commit | 3dd124e7d67ea84e6170329eb47d1ffd54e76463 (patch) | |
| tree | a98d88c8b47258bdd534133a28156b38d5dc370c | |
| parent | 83a3c0ea4a601e2cdb80c2875e9e42b28721b5c2 (diff) | |
| download | RoughlyEnoughItems-3dd124e7d67ea84e6170329eb47d1ffd54e76463.tar.gz RoughlyEnoughItems-3dd124e7d67ea84e6170329eb47d1ffd54e76463.tar.bz2 RoughlyEnoughItems-3dd124e7d67ea84e6170329eb47d1ffd54e76463.zip | |
Refactor PreFilteredEntryList out into its own class
8 files changed, 317 insertions, 121 deletions
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 b60baec9a..63ed14d72 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 @@ -199,4 +199,12 @@ public interface EntryRegistry extends Reloadable<REIClientPlugin> { * @return whether it was successful to remove any entry */ boolean removeEntryFuzzyHashIf(LongPredicate predicate); + + /** + * Returns whether the registry is in its reloading phase. + * Registration after the reloading phase will be slow and may not be reflected immediately. + * + * @return whether the registry is in its reloading phase + */ + boolean isReloading(); } 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 5e01fa064..fa62b2bbb 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 @@ -23,16 +23,12 @@ package me.shedaniel.rei.impl.common.entry.type; -import com.google.common.base.Stopwatch; 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 me.shedaniel.rei.RoughlyEnoughItemsCore; import me.shedaniel.rei.api.client.REIRuntime; -import me.shedaniel.rei.api.client.config.ConfigObject; -import me.shedaniel.rei.api.client.config.entry.EntryStackProvider; 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; @@ -43,35 +39,25 @@ import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; 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.REIRuntimeImpl; -import me.shedaniel.rei.impl.client.config.ConfigObjectImpl; -import me.shedaniel.rei.impl.client.entry.filtering.FilteringCacheImpl; -import me.shedaniel.rei.impl.client.entry.filtering.FilteringContextImpl; -import me.shedaniel.rei.impl.client.entry.filtering.FilteringContextType; -import me.shedaniel.rei.impl.client.entry.filtering.FilteringRule; -import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; -import me.shedaniel.rei.impl.common.util.HashedEntryStackWrapper; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.core.NonNullList; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import org.apache.commons.lang3.mutable.MutableLong; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.function.LongPredicate; import java.util.function.Predicate; -import java.util.stream.Collectors; import java.util.stream.Stream; @ApiStatus.Internal @Environment(EnvType.CLIENT) public class EntryRegistryImpl implements EntryRegistry { - public List<Runnable> refilterListener = Lists.newCopyOnWriteArrayList(); - private List<EntryStack<?>> preFilteredList = Lists.newCopyOnWriteArrayList(); + public List<EntryRegistryListener> listeners = Lists.newCopyOnWriteArrayList(); + private PreFilteredEntryList preFilteredList; private EntryRegistryList registryList; private LongSet entriesHash = new LongOpenHashSet(); private boolean reloading; @@ -88,17 +74,17 @@ public class EntryRegistryImpl implements EntryRegistry { @Override public void startReload() { - refilterListener.clear(); + listeners.clear(); registryList = new ReloadingEntryRegistryList(); entriesHash = new LongOpenHashSet(); - preFilteredList = Lists.newCopyOnWriteArrayList(); + preFilteredList = new PreFilteredEntryList(this); reloading = true; } @Override public void endReload() { reloading = false; - preFilteredList = Lists.newCopyOnWriteArrayList(); + preFilteredList = new PreFilteredEntryList(this); if (!(registryList instanceof ReloadingEntryRegistryList)) { throw new IllegalStateException("Expected ReloadingEntryRegistryList, got " + registryList.getClass().getName()); } @@ -108,6 +94,11 @@ public class EntryRegistryImpl implements EntryRegistry { } @Override + public boolean isReloading() { + return reloading; + } + + @Override public int size() { return registryList.size(); } @@ -119,57 +110,18 @@ public class EntryRegistryImpl implements EntryRegistry { @Override public List<EntryStack<?>> getPreFilteredList() { - return Collections.unmodifiableList(preFilteredList); + return Collections.unmodifiableList(preFilteredList.getList()); } @Override public void refilter() { - ConfigObject config = ConfigObject.getInstance(); - if (config.getFilteredStackProviders() != null) { - List<EntryStack<?>> normalizedFilteredStacks = CollectionUtils.map(config.getFilteredStackProviders(), EntryStackProvider::provide); - normalizedFilteredStacks.removeIf(EntryStack::isEmpty); - config.getFilteredStackProviders().clear(); - config.getFilteredStackProviders().addAll(CollectionUtils.map(normalizedFilteredStacks, EntryStackProvider::ofStack)); - } - - Stopwatch stopwatch = Stopwatch.createStarted(); - - List<EntryStack<?>> entries = ((NormalEntryRegistryList) registryList).getList(); - FilteringContextImpl context = new FilteringContextImpl(entries); - FilteringCacheImpl cache = new FilteringCacheImpl(); - List<FilteringRule<?>> rules = ((ConfigObjectImpl) ConfigObject.getInstance()).getFilteringRules(); - Stopwatch innerStopwatch = Stopwatch.createStarted(); - for (int i = rules.size() - 1; i >= 0; i--) { - innerStopwatch.reset().start(); - FilteringRule<?> rule = rules.get(i); - cache.setCache(rule, rule.prepareCache(true)); - context.handleResult(rule.processFilteredStacks(context, cache, true)); - RoughlyEnoughItemsCore.LOGGER.debug("Refiltered rule [%s] in %s.", FilteringRule.REGISTRY.inverse().get(rule).toString(), innerStopwatch.stop().toString()); - } - - Set<HashedEntryStackWrapper> hiddenStacks = context.stacks.get(FilteringContextType.HIDDEN); - if (hiddenStacks.isEmpty()) { - preFilteredList = Lists.newCopyOnWriteArrayList(entries); - } else { - preFilteredList = entries.parallelStream() - .map(HashedEntryStackWrapper::new) - .filter(not(hiddenStacks::contains)) - .map(HashedEntryStackWrapper::unwrap) - .collect(Collectors.toCollection(Lists::newCopyOnWriteArrayList)); - } - - RoughlyEnoughItemsCore.LOGGER.debug("Refiltered %d entries with %d rules in %s.", entries.size() - preFilteredList.size(), rules.size(), stopwatch.stop().toString()); + List<EntryStack<?>> stacks = registryList.collect(); - for (Runnable runnable : refilterListener) { - runnable.run(); + for (EntryRegistryListener listener : listeners) { + listener.onReFilter(stacks); } } - private static <T> Predicate<T> not(Predicate<? super T> target) { - Objects.requireNonNull(target); - return (Predicate<T>) target.negate(); - } - private static final Comparator<ItemStack> STACK_COMPARATOR = (a, b) -> ItemStack.matches(a, b) ? 0 : 1; @Override @@ -197,43 +149,10 @@ public class EntryRegistryImpl implements EntryRegistry { return list; } - private void queueSearchUpdate() { - if (REIRuntimeImpl.getSearchField() != null) { - ScreenOverlayImpl.getInstance().queueReloadSearch(); - } - } - - private MutableLong lastRefilterWarning = new MutableLong(-1); - @ApiStatus.Internal @Override public Collection<EntryStack<?>> refilterNew(boolean warn, Collection<EntryStack<?>> entries) { - if (lastRefilterWarning != null && warn) { - if (lastRefilterWarning.getValue() > 0 && System.currentTimeMillis() - lastRefilterWarning.getValue() > 5000) { - RoughlyEnoughItemsCore.LOGGER.warn("Detected runtime EntryRegistry modification, this can be extremely dangerous, or be extremely inefficient!"); - } - lastRefilterWarning.setValue(System.currentTimeMillis()); - } - - FilteringContextImpl context = new FilteringContextImpl(entries); - FilteringCacheImpl cache = new FilteringCacheImpl(); - List<FilteringRule<?>> rules = ((ConfigObjectImpl) ConfigObject.getInstance()).getFilteringRules(); - for (int i = rules.size() - 1; i >= 0; i--) { - FilteringRule<?> rule = rules.get(i); - cache.setCache(rule, rule.prepareCache(true)); - context.handleResult(rule.processFilteredStacks(context, cache, true)); - } - - Set<HashedEntryStackWrapper> hiddenStacks = context.stacks.get(FilteringContextType.HIDDEN); - if (hiddenStacks.isEmpty()) { - return entries; - } else { - return entries.parallelStream() - .map(HashedEntryStackWrapper::new) - .filter(not(hiddenStacks::contains)) - .map(HashedEntryStackWrapper::unwrap) - .collect(Collectors.toList()); - } + return preFilteredList.refilterNew(warn, entries); } @Override @@ -250,9 +169,8 @@ public class EntryRegistryImpl implements EntryRegistry { registryList.add(index, stack, hashExact); } else registryList.add(stack, hashExact); - if (!reloading) { - preFilteredList.addAll(refilterNew(true, Collections.singletonList(stack))); - queueSearchUpdate(); + for (EntryRegistryListener listener : listeners) { + listener.addEntryAfter(afterEntry, stack, hashExact); } } } @@ -280,9 +198,8 @@ public class EntryRegistryImpl implements EntryRegistry { registryList.addAll(index, filtered, hashes); } else registryList.addAll(filtered, hashes); - if (!reloading) { - preFilteredList.addAll(refilterNew(true, filtered)); - queueSearchUpdate(); + for (EntryRegistryListener listener : listeners) { + listener.addEntriesAfter(afterEntry, filtered, hashes); } } @@ -292,9 +209,10 @@ public class EntryRegistryImpl implements EntryRegistry { registryList.remove(stack, hashExact); boolean removed = entriesHash.remove(hashExact); - if (removed && !reloading) { - preFilteredList.remove(stack); - queueSearchUpdate(); + if (removed) { + for (EntryRegistryListener listener : listeners) { + listener.removeEntry(stack, hashExact); + } } return removed; @@ -302,18 +220,28 @@ public class EntryRegistryImpl implements EntryRegistry { @Override public boolean removeEntryIf(Predicate<? extends EntryStack<?>> predicate) { - if (!reloading) { - preFilteredList.removeIf((Predicate<? super EntryStack<?>>) predicate); - } + List<EntryStack<?>> removedStacks = new ArrayList<>(); + LongList hashes = registryList.needsHash() ? new LongArrayList() : null; - return registryList.removeIf(stack -> { + boolean removed = registryList.removeIf(stack -> { if (((Predicate<EntryStack<?>>) predicate).test(stack)) { - entriesHash.remove(EntryStacks.hashExact(stack)); + long hashExact = EntryStacks.hashExact(stack); + entriesHash.remove(hashExact); + removedStacks.add(stack); + if (hashes != null) hashes.add(hashExact); return true; } return false; }); + + if (removed) { + for (EntryRegistryListener listener : listeners) { + listener.removeEntries(removedStacks, hashes); + } + } + + return removed; } @Override @@ -327,9 +255,10 @@ public class EntryRegistryImpl implements EntryRegistry { return false; }; - if (!reloading) { - preFilteredList.removeIf(stack -> predicate.test(EntryStacks.hashExact(stack))); + for (EntryRegistryListener listener : listeners) { + listener.removeEntriesIf(stack -> predicate.test(EntryStacks.hashExact(stack))); } + return registryList.removeExactIf(entryStackPredicate); } @@ -344,9 +273,10 @@ public class EntryRegistryImpl implements EntryRegistry { return false; }; - if (!reloading) { - preFilteredList.removeIf(entryStackPredicate); + for (EntryRegistryListener listener : listeners) { + listener.removeEntriesIf(entryStackPredicate); } + return registryList.removeIf(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 d60f10cb5..2672b077a 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 @@ -36,6 +36,8 @@ public interface EntryRegistryList { Stream<EntryStack<?>> stream(); + List<EntryStack<?>> collect(); + int indexOf(EntryStack<?> stack); int lastIndexOf(EntryStack<?> stack); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryListener.java b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryListener.java new file mode 100644 index 000000000..e7b99493c --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryListener.java @@ -0,0 +1,45 @@ +/* + * 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 org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.function.Predicate; + +public interface EntryRegistryListener { + default void addEntryAfter(@Nullable EntryStack<?> afterEntry, EntryStack<?> stack, long stackHashExact) {} + + default void addEntriesAfter(@Nullable EntryStack<?> afterEntry, List<EntryStack<?>> stacks, @Nullable LongList hashes) {} + + default void removeEntry(EntryStack<?> stack, long hashExact) {} + + default void removeEntries(List<EntryStack<?>> stacks, @Nullable LongList hashes) {} + + default void removeEntriesIf(Predicate<EntryStack<?>> predicate) {} + + default void onReFilter(List<EntryStack<?>> stacks) {} +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/NormalEntryRegistryList.java b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/NormalEntryRegistryList.java index fc3046002..a6e752c6e 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/NormalEntryRegistryList.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/NormalEntryRegistryList.java @@ -55,6 +55,11 @@ public class NormalEntryRegistryList implements EntryRegistryList { } @Override + public List<EntryStack<?>> collect() { + return list; + } + + @Override public int indexOf(EntryStack<?> stack) { return list.indexOf(stack); } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/PreFilteredEntryList.java b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/PreFilteredEntryList.java new file mode 100644 index 000000000..2a2cce586 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/PreFilteredEntryList.java @@ -0,0 +1,200 @@ +/* + * 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 com.google.common.base.Stopwatch; +import com.google.common.collect.Lists; +import it.unimi.dsi.fastutil.longs.LongList; +import me.shedaniel.rei.RoughlyEnoughItemsCore; +import me.shedaniel.rei.api.client.config.ConfigObject; +import me.shedaniel.rei.api.client.config.entry.EntryStackProvider; +import me.shedaniel.rei.api.client.registry.entry.EntryRegistry; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.impl.client.REIRuntimeImpl; +import me.shedaniel.rei.impl.client.config.ConfigObjectImpl; +import me.shedaniel.rei.impl.client.entry.filtering.FilteringCacheImpl; +import me.shedaniel.rei.impl.client.entry.filtering.FilteringContextImpl; +import me.shedaniel.rei.impl.client.entry.filtering.FilteringContextType; +import me.shedaniel.rei.impl.client.entry.filtering.FilteringRule; +import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; +import me.shedaniel.rei.impl.common.util.HashedEntryStackWrapper; +import org.apache.commons.lang3.mutable.MutableLong; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public class PreFilteredEntryList implements EntryRegistryListener { + private final EntryRegistry registry; + private final MutableLong lastRefilterWarning = new MutableLong(-1); + private List<EntryStack<?>> preFilteredList = Lists.newCopyOnWriteArrayList(); + + public PreFilteredEntryList(EntryRegistry registry) { + this.registry = registry; + } + + private static <T> Predicate<T> not(Predicate<? super T> target) { + Objects.requireNonNull(target); + return (Predicate<T>) target.negate(); + } + + @Override + public void addEntryAfter(@Nullable EntryStack<?> afterEntry, EntryStack<?> stack, long stackHashExact) { + if (!registry.isReloading()) { + Collection<EntryStack<?>> refilterNew = refilterNew(true, Collections.singletonList(stack)); + if (afterEntry != null) { + int index = preFilteredList.lastIndexOf(afterEntry); + if (index >= 0) { + preFilteredList.addAll(index, refilterNew); + queueSearchUpdate(); + return; + } + } + + preFilteredList.addAll(refilterNew); + queueSearchUpdate(); + } + } + + @Override + public void addEntriesAfter(@Nullable EntryStack<?> afterEntry, List<EntryStack<?>> stacks, @Nullable LongList hashes) { + if (!registry.isReloading()) { + Collection<EntryStack<?>> refilterNew = refilterNew(true, stacks); + if (afterEntry != null) { + int index = preFilteredList.lastIndexOf(afterEntry); + if (index >= 0) { + preFilteredList.addAll(index, refilterNew); + queueSearchUpdate(); + return; + } + } + + preFilteredList.addAll(refilterNew); + queueSearchUpdate(); + } + } + + @Override + public void removeEntry(EntryStack<?> stack, long hashExact) { + if (!registry.isReloading()) { + preFilteredList.remove(stack); + queueSearchUpdate(); + } + } + + @Override + public void removeEntries(List<EntryStack<?>> stacks, @Nullable LongList hashes) { + if (!registry.isReloading()) { + preFilteredList.removeAll(stacks); + queueSearchUpdate(); + } + } + + @Override + public void removeEntriesIf(Predicate<EntryStack<?>> predicate) { + if (!registry.isReloading()) { + preFilteredList.removeIf(predicate); + queueSearchUpdate(); + } + } + + @Override + public void onReFilter(List<EntryStack<?>> stacks) { + ConfigObject config = ConfigObject.getInstance(); + if (config.getFilteredStackProviders() != null) { + List<EntryStack<?>> normalizedFilteredStacks = CollectionUtils.map(config.getFilteredStackProviders(), EntryStackProvider::provide); + normalizedFilteredStacks.removeIf(EntryStack::isEmpty); + config.getFilteredStackProviders().clear(); + config.getFilteredStackProviders().addAll(CollectionUtils.map(normalizedFilteredStacks, EntryStackProvider::ofStack)); + } + + Stopwatch stopwatch = Stopwatch.createStarted(); + + FilteringContextImpl context = new FilteringContextImpl(stacks); + FilteringCacheImpl cache = new FilteringCacheImpl(); + List<FilteringRule<?>> rules = ((ConfigObjectImpl) ConfigObject.getInstance()).getFilteringRules(); + Stopwatch innerStopwatch = Stopwatch.createStarted(); + for (int i = rules.size() - 1; i >= 0; i--) { + innerStopwatch.reset().start(); + FilteringRule<?> rule = rules.get(i); + cache.setCache(rule, rule.prepareCache(true)); + context.handleResult(rule.processFilteredStacks(context, cache, true)); + RoughlyEnoughItemsCore.LOGGER.debug("Refiltered rule [%s] in %s.", FilteringRule.REGISTRY.inverse().get(rule).toString(), innerStopwatch.stop().toString()); + } + + Set<HashedEntryStackWrapper> hiddenStacks = context.stacks.get(FilteringContextType.HIDDEN); + if (hiddenStacks.isEmpty()) { + preFilteredList = Lists.newCopyOnWriteArrayList(stacks); + } else { + preFilteredList = stacks.parallelStream() + .map(HashedEntryStackWrapper::new) + .filter(not(hiddenStacks::contains)) + .map(HashedEntryStackWrapper::unwrap) + .collect(Collectors.toCollection(Lists::newCopyOnWriteArrayList)); + } + + RoughlyEnoughItemsCore.LOGGER.debug("Refiltered %d entries with %d rules in %s.", stacks.size() - preFilteredList.size(), rules.size(), stopwatch.stop().toString()); + } + + public Collection<EntryStack<?>> refilterNew(boolean warn, Collection<EntryStack<?>> entries) { + if (lastRefilterWarning != null && warn) { + if (lastRefilterWarning.getValue() > 0 && System.currentTimeMillis() - lastRefilterWarning.getValue() > 5000) { + RoughlyEnoughItemsCore.LOGGER.warn("Detected runtime EntryRegistry modification, this can be extremely dangerous, or be extremely inefficient!"); + } + lastRefilterWarning.setValue(System.currentTimeMillis()); + } + + FilteringContextImpl context = new FilteringContextImpl(entries); + FilteringCacheImpl cache = new FilteringCacheImpl(); + List<FilteringRule<?>> rules = ((ConfigObjectImpl) ConfigObject.getInstance()).getFilteringRules(); + for (int i = rules.size() - 1; i >= 0; i--) { + FilteringRule<?> rule = rules.get(i); + cache.setCache(rule, rule.prepareCache(true)); + context.handleResult(rule.processFilteredStacks(context, cache, true)); + } + + Set<HashedEntryStackWrapper> hiddenStacks = context.stacks.get(FilteringContextType.HIDDEN); + if (hiddenStacks.isEmpty()) { + return entries; + } else { + return entries.parallelStream() + .map(HashedEntryStackWrapper::new) + .filter(not(hiddenStacks::contains)) + .map(HashedEntryStackWrapper::unwrap) + .collect(Collectors.toList()); + } + } + + private void queueSearchUpdate() { + if (REIRuntimeImpl.getSearchField() != null) { + ScreenOverlayImpl.getInstance().queueReloadSearch(); + } + } + + public List<EntryStack<?>> getList() { + return preFilteredList; + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/ReloadingEntryRegistryList.java b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/ReloadingEntryRegistryList.java index 45578585e..44211ce2c 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/ReloadingEntryRegistryList.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/ReloadingEntryRegistryList.java @@ -49,6 +49,11 @@ public class ReloadingEntryRegistryList implements EntryRegistryList { } @Override + public List<EntryStack<?>> collect() { + return CollectionUtils.map(list, HashedEntryStackWrapper::unwrap); + } + + @Override public int indexOf(EntryStack<?> stack) { return list.indexOf(new HashedEntryStackWrapper(stack)); } diff --git a/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/DefaultClientRuntimePlugin.java b/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/DefaultClientRuntimePlugin.java index b57bc6f67..8fa55e5ba 100644 --- a/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/DefaultClientRuntimePlugin.java +++ b/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/DefaultClientRuntimePlugin.java @@ -32,15 +32,12 @@ import me.shedaniel.math.Rectangle; import me.shedaniel.rei.RoughlyEnoughItemsCoreClient; import me.shedaniel.rei.api.client.ClientHelper; import me.shedaniel.rei.api.client.REIRuntime; -import me.shedaniel.rei.api.client.config.ConfigObject; import me.shedaniel.rei.api.client.favorites.FavoriteEntry; import me.shedaniel.rei.api.client.favorites.FavoriteEntryType; import me.shedaniel.rei.api.client.gui.AbstractRenderer; import me.shedaniel.rei.api.client.gui.Renderer; -import me.shedaniel.rei.api.client.gui.config.ItemCheatingMode; import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentProviderWidget; import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentVisitorWidget; -import me.shedaniel.rei.api.client.gui.screen.DisplayScreen; import me.shedaniel.rei.api.client.gui.widgets.Panel; import me.shedaniel.rei.api.client.gui.widgets.Tooltip; import me.shedaniel.rei.api.client.gui.widgets.TooltipContext; @@ -53,7 +50,6 @@ import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry; import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry; import me.shedaniel.rei.api.client.util.ClientEntryStacks; import me.shedaniel.rei.api.common.entry.EntryStack; -import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; import me.shedaniel.rei.api.common.plugins.PluginManager; import me.shedaniel.rei.api.common.plugins.REIPlugin; import me.shedaniel.rei.api.common.registry.Reloadable; @@ -64,19 +60,19 @@ import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; import me.shedaniel.rei.impl.client.gui.screen.DefaultDisplayViewingScreen; import me.shedaniel.rei.impl.client.gui.widget.favorites.FavoritesListWidget; import me.shedaniel.rei.impl.common.entry.type.EntryRegistryImpl; +import me.shedaniel.rei.impl.common.entry.type.EntryRegistryListener; import me.shedaniel.rei.plugin.autocrafting.DefaultCategoryHandler; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.util.Collections; +import java.util.List; import java.util.function.Function; @Environment(EnvType.CLIENT) @@ -115,7 +111,12 @@ public class DefaultClientRuntimePlugin implements REIClientPlugin { })); } - ((EntryRegistryImpl) registry).refilterListener.add(filteredStacksVisibilityHandler::reset); + ((EntryRegistryImpl) registry).listeners.add(new EntryRegistryListener() { + @Override + public void onReFilter(List<EntryStack<?>> stacks) { + filteredStacksVisibilityHandler.reset(); + } + }); } @Override |
