From 67171a5ff24ed77e6c4cc889543e8dfb543e8fe5 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sun, 20 Dec 2020 19:59:49 +0800 Subject: wip more Signed-off-by: shedaniel --- .../me/shedaniel/rei/impl/EntryRegistryImpl.java | 201 +++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 runtime/src/main/java/me/shedaniel/rei/impl/EntryRegistryImpl.java (limited to 'runtime/src/main/java/me/shedaniel/rei/impl/EntryRegistryImpl.java') diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/EntryRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/EntryRegistryImpl.java new file mode 100644 index 000000000..ad5f46c17 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/EntryRegistryImpl.java @@ -0,0 +1,201 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020 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; + +import com.google.common.base.Stopwatch; +import com.google.common.collect.Lists; +import me.shedaniel.rei.RoughlyEnoughItemsCore; +import me.shedaniel.rei.api.ConfigObject; +import me.shedaniel.rei.api.EntryRegistry; +import me.shedaniel.rei.api.EntryStack; +import me.shedaniel.rei.api.entry.EntryStacks; +import me.shedaniel.rei.impl.filtering.FilteringContextImpl; +import me.shedaniel.rei.impl.filtering.FilteringContextType; +import me.shedaniel.rei.impl.filtering.FilteringRule; +import me.shedaniel.rei.utils.CollectionUtils; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.core.NonNullList; +import net.minecraft.core.Registry; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +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 { + private final List> preFilteredList = Lists.newCopyOnWriteArrayList(); + private final List> entries = Lists.newCopyOnWriteArrayList(); + @Nullable + private List reloadingRegistry; + private boolean reloading; + + public void finishReload() { + reloading = false; + preFilteredList.clear(); + reloadingRegistry.removeIf(AmountIgnoredEntryStackWrapper::isEmpty); + entries.clear(); + entries.addAll(CollectionUtils.map(reloadingRegistry, AmountIgnoredEntryStackWrapper::unwrap)); + reloadingRegistry = null; + } + + @Override + @NotNull + public Stream> getEntryStacks() { + return reloading ? reloadingRegistry.stream().map(AmountIgnoredEntryStackWrapper::unwrap) : entries.stream(); + } + + @Override + @NotNull + public List> getPreFilteredList() { + return preFilteredList; + } + + @Override + @ApiStatus.Experimental + public void refilter() { + Stopwatch stopwatch = Stopwatch.createStarted(); + + FilteringContextImpl context = new FilteringContextImpl(entries); + List> 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); + context.handleResult(rule.processFilteredStacks(context)); + RoughlyEnoughItemsCore.LOGGER.debug("Refiltered rule [%s] in %s.", FilteringRule.REGISTRY.getKey(rule).toString(), innerStopwatch.stop().toString()); + } + + Set hiddenStacks = context.stacks.get(FilteringContextType.HIDDEN); + if (hiddenStacks.isEmpty()) { + preFilteredList.clear(); + preFilteredList.addAll(entries); + } else { + preFilteredList.clear(); + preFilteredList.addAll(entries.parallelStream() + .map(AmountIgnoredEntryStackWrapper::new) + .filter(not(hiddenStacks::contains)) + .map(AmountIgnoredEntryStackWrapper::unwrap) + .collect(Collectors.toList())); + } + + RoughlyEnoughItemsCore.LOGGER.debug("Refiltered %d entries with %d rules in %s.", entries.size() - preFilteredList.size(), rules.size(), stopwatch.stop().toString()); + } + + static Predicate not(Predicate target) { + Objects.requireNonNull(target); + return (Predicate) target.negate(); + } + + public void resetToReloadStart() { + entries.clear(); + if (reloadingRegistry != null) + reloadingRegistry.clear(); + reloadingRegistry = Lists.newArrayListWithCapacity(Registry.ITEM.keySet().size() + 100); + preFilteredList.clear(); + reloading = true; + } + + @NotNull + @Override + public List appendStacksForItem(@NotNull Item item) { + NonNullList list = NonNullList.create(); + item.fillItemCategory(item.getItemCategory(), list); + if (list.isEmpty()) + return Collections.singletonList(item.getDefaultInstance()); + return list; + } + + @NotNull + @Override + public ItemStack[] getAllStacksFromItem(@NotNull Item item) { + List list = appendStacksForItem(item); + ItemStack[] array = list.toArray(new ItemStack[0]); + Arrays.sort(array, (a, b) -> ItemStack.matches(a, b) ? 0 : 1); + return array; + } + + @Override + public void registerEntryAfter(@Nullable EntryStack afterEntry, @NotNull EntryStack stack) { + if (reloading) { + int index = afterEntry != null ? reloadingRegistry.lastIndexOf(new AmountIgnoredEntryStackWrapper(afterEntry)) : -1; + if (index >= 0) { + reloadingRegistry.add(index, new AmountIgnoredEntryStackWrapper(stack)); + } else reloadingRegistry.add(new AmountIgnoredEntryStackWrapper(stack)); + } else { + if (afterEntry != null) { + int index = entries.lastIndexOf(afterEntry); + entries.add(index, stack); + } else entries.add(stack); + } + } + + @Override + public void registerEntriesAfter(@Nullable EntryStack afterEntry, @NotNull Collection<@NotNull ? extends EntryStack> stacks) { + if (reloading) { + int index = afterEntry != null ? reloadingRegistry.lastIndexOf(new AmountIgnoredEntryStackWrapper(afterEntry)) : -1; + if (index >= 0) { + reloadingRegistry.addAll(index, CollectionUtils.map(stacks, AmountIgnoredEntryStackWrapper::new)); + } else reloadingRegistry.addAll(CollectionUtils.map(stacks, AmountIgnoredEntryStackWrapper::new)); + } else { + if (afterEntry != null) { + int index = entries.lastIndexOf(afterEntry); + entries.addAll(index, stacks); + } else entries.addAll(stacks); + } + } + + @Override + public boolean alreadyContain(EntryStack stack) { + if (reloading) { + return reloadingRegistry.parallelStream().anyMatch(s -> EntryStacks.equalsExact(s.unwrap(), stack)); + } + return entries.parallelStream().anyMatch(s -> EntryStacks.equalsExact(s, stack)); + } + + @Override + public void removeEntry(EntryStack stack) { + if (reloading) { + reloadingRegistry.remove(new AmountIgnoredEntryStackWrapper(stack)); + } else { + entries.remove(stack); + } + } + + @Override + public void removeEntryIf(Predicate> stackPredicate) { + if (reloading) { + reloadingRegistry.removeIf(wrapper -> stackPredicate.test(wrapper.unwrap())); + } else { + entries.removeIf(stackPredicate); + } + } +} -- cgit