aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2022-06-21 22:04:46 +0800
committershedaniel <daniel@shedaniel.me>2022-06-28 03:21:12 +0800
commit3dd124e7d67ea84e6170329eb47d1ffd54e76463 (patch)
treea98d88c8b47258bdd534133a28156b38d5dc370c
parent83a3c0ea4a601e2cdb80c2875e9e42b28721b5c2 (diff)
downloadRoughlyEnoughItems-3dd124e7d67ea84e6170329eb47d1ffd54e76463.tar.gz
RoughlyEnoughItems-3dd124e7d67ea84e6170329eb47d1ffd54e76463.tar.bz2
RoughlyEnoughItems-3dd124e7d67ea84e6170329eb47d1ffd54e76463.zip
Refactor PreFilteredEntryList out into its own class
-rw-r--r--api/src/main/java/me/shedaniel/rei/api/client/registry/entry/EntryRegistry.java8
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryImpl.java158
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryList.java2
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/EntryRegistryListener.java45
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/NormalEntryRegistryList.java5
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/PreFilteredEntryList.java200
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/ReloadingEntryRegistryList.java5
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/DefaultClientRuntimePlugin.java15
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