diff options
Diffstat (limited to 'runtime-engine/entries/src/main/java')
7 files changed, 862 insertions, 0 deletions
diff --git a/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/EntryRegistryImpl.java b/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/EntryRegistryImpl.java new file mode 100644 index 000000000..be1ed5225 --- /dev/null +++ b/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/EntryRegistryImpl.java @@ -0,0 +1,276 @@ +/* + * 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.client.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 me.shedaniel.rei.api.client.REIRuntime; +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; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.entry.comparison.ComparisonContext; +import me.shedaniel.rei.api.common.entry.type.EntryDefinition; +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.Internals; +import me.shedaniel.rei.impl.common.InternalLogger; +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.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.Stream; + +@ApiStatus.Internal +@Environment(EnvType.CLIENT) +public class EntryRegistryImpl implements EntryRegistry { + private final List<EntryRegistryListener> listeners = Lists.newCopyOnWriteArrayList(); + private EntryRegistryList registryList; + private LongSet entriesHash; + private boolean reloading; + + public EntryRegistryImpl() { + registryList = new NormalEntryRegistryList(); + entriesHash = new LongOpenHashSet(); + listeners.addAll(Internals.resolveServices(EntryRegistryListener.class)); + } + + @Override + public void acceptPlugin(REIClientPlugin plugin) { + plugin.registerEntries(this); + } + + @Override + public ReloadStage getStage() { + return ReloadStage.START; + } + + @Override + public void startReload() { + registryList = new ReloadingEntryRegistryList(); + entriesHash = new LongOpenHashSet(); + 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())); + refilter(); + REIRuntime.getInstance().getOverlay().ifPresent(ScreenOverlay::queueReloadOverlay); + InternalLogger.getInstance().debug("Reloaded entry registry with %d entries and %d filtered entries", size(), getPreFilteredList().size()); + } + + @Override + public boolean isReloading() { + return reloading; + } + + @Override + public int size() { + return registryList.size(); + } + + @Override + public Stream<EntryStack<?>> getEntryStacks() { + return registryList.stream(); + } + + @Override + public void refilter() { + List<EntryStack<?>> stacks = registryList.collect(); + + for (EntryRegistryListener listener : listeners) { + listener.onReFilter(stacks); + } + } + + private static final Comparator<ItemStack> STACK_COMPARATOR = (a, b) -> ItemStack.matches(a, b) ? 0 : 1; + + @Override + public List<ItemStack> appendStacksForItem(Item item) { + NonNullList<ItemStack> list = NonNullList.create(); + LongSet set = new LongOpenHashSet(); + EntryDefinition<ItemStack> itemDefinition = VanillaEntryTypes.ITEM.getDefinition(); + for (CreativeModeTab tab : CreativeModeTab.TABS) { + if (tab != CreativeModeTab.TAB_HOTBAR && tab != CreativeModeTab.TAB_INVENTORY) { + NonNullList<ItemStack> tabList = NonNullList.create(); + item.fillItemCategory(tab, tabList); + for (ItemStack stack : tabList) { + if (set.add(itemDefinition.hash(null, stack, ComparisonContext.EXACT))) { + list.add(stack); + } + } + } + } + if (list.isEmpty()) { + return Collections.singletonList(item.getDefaultInstance()); + } + if (list.size() > 1) { + list.sort(STACK_COMPARATOR); + } + return list; + } + + @Override + public boolean alreadyContain(EntryStack<?> stack) { + return entriesHash.contains(EntryStacks.hashExact(stack)); + } + + @Override + public void addEntryAfter(@Nullable EntryStack<?> afterEntry, EntryStack<?> stack) { + long hashExact = EntryStacks.hashExact(stack); + if (this.entriesHash.add(hashExact)) { + if (afterEntry != null) { + int index = registryList.lastIndexOf(afterEntry); + registryList.add(index, stack, hashExact); + } else registryList.add(stack, hashExact); + + for (EntryRegistryListener listener : listeners) { + listener.addEntryAfter(afterEntry, stack, hashExact); + } + } + } + + @Override + public void addEntriesAfter(@Nullable EntryStack<?> afterEntry, Collection<? extends EntryStack<?>> stacks) { + List<EntryStack<?>> filtered; + LongList hashes = registryList.needsHash() ? new LongArrayList(stacks.size()) : null; + + if (registryList.needsHash()) { + filtered = new ArrayList<>(stacks.size()); + for (EntryStack<?> stack : stacks) { + long hashExact = EntryStacks.hashExact(stack); + if (entriesHash.add(hashExact)) { + filtered.add(stack); + hashes.add(hashExact); + } + } + } else { + filtered = CollectionUtils.filterToList((List<EntryStack<?>>) stacks, entry -> entriesHash.add(EntryStacks.hashExact(entry))); + } + + if (afterEntry != null) { + int index = registryList.lastIndexOf(afterEntry); + registryList.addAll(index, filtered, hashes); + } else registryList.addAll(filtered, hashes); + + for (EntryRegistryListener listener : listeners) { + listener.addEntriesAfter(afterEntry, filtered, hashes); + } + } + + @Override + public boolean removeEntry(EntryStack<?> stack) { + long hashExact = EntryStacks.hashExact(stack); + registryList.remove(stack, hashExact); + boolean removed = entriesHash.remove(hashExact); + + if (removed) { + for (EntryRegistryListener listener : listeners) { + listener.removeEntry(stack, hashExact); + } + } + + return removed; + } + + @Override + public boolean removeEntryIf(Predicate<? extends EntryStack<?>> predicate) { + List<EntryStack<?>> removedStacks = new ArrayList<>(); + LongList hashes = registryList.needsHash() ? new LongArrayList() : null; + + boolean removed = registryList.removeIf(stack -> { + if (((Predicate<EntryStack<?>>) predicate).test(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 + public boolean removeEntryExactHashIf(LongPredicate predicate) { + LongPredicate entryStackPredicate = hash -> { + if (predicate.test(hash)) { + entriesHash.remove(hash); + return true; + } + + return false; + }; + + for (EntryRegistryListener listener : listeners) { + listener.removeEntriesIf(stack -> predicate.test(EntryStacks.hashExact(stack))); + } + + return registryList.removeExactIf(entryStackPredicate); + } + + @Override + public boolean removeEntryFuzzyHashIf(LongPredicate predicate) { + Predicate<EntryStack<?>> entryStackPredicate = stack -> { + if (predicate.test(EntryStacks.hashFuzzy(stack))) { + entriesHash.remove(EntryStacks.hashExact(stack)); + return true; + } + + return false; + }; + + for (EntryRegistryListener listener : listeners) { + listener.removeEntriesIf(entryStackPredicate); + } + + return registryList.removeIf(entryStackPredicate); + } +} diff --git a/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/EntryRegistryList.java b/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/EntryRegistryList.java new file mode 100644 index 000000000..401bf61a9 --- /dev/null +++ b/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/EntryRegistryList.java @@ -0,0 +1,62 @@ +/* + * 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.client.entry.type; + +import it.unimi.dsi.fastutil.longs.LongList; +import me.shedaniel.rei.api.common.entry.EntryStack; +import org.jetbrains.annotations.ApiStatus; + +import java.util.List; +import java.util.function.LongPredicate; +import java.util.function.Predicate; +import java.util.stream.Stream; + +@ApiStatus.Internal +public interface EntryRegistryList { + int size(); + + Stream<EntryStack<?>> stream(); + + List<EntryStack<?>> collect(); + + int indexOf(EntryStack<?> stack); + + int lastIndexOf(EntryStack<?> stack); + + void add(EntryStack<?> stack, long hashExact); + + void add(int index, EntryStack<?> stack, long hashExact); + + void addAll(List<EntryStack<?>> stacks, LongList hashes); + + void addAll(int index, List<EntryStack<?>> stacks, LongList hashes); + + void remove(EntryStack<?> stack, long hashExact); + + boolean removeIf(Predicate<? extends EntryStack<?>> predicate); + + boolean removeExactIf(LongPredicate predicate); + + boolean needsHash(); +} diff --git a/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/EntryRegistryListener.java b/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/EntryRegistryListener.java new file mode 100644 index 000000000..b1c59e0e7 --- /dev/null +++ b/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/EntryRegistryListener.java @@ -0,0 +1,47 @@ +/* + * 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.client.entry.type; + +import it.unimi.dsi.fastutil.longs.LongList; +import me.shedaniel.rei.api.common.entry.EntryStack; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.function.Predicate; + +@ApiStatus.Internal +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-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/EntryTypeRegistryImpl.java b/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/EntryTypeRegistryImpl.java new file mode 100644 index 000000000..ad5a6261d --- /dev/null +++ b/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/EntryTypeRegistryImpl.java @@ -0,0 +1,102 @@ +/* + * 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.client.entry.type; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Table; +import me.shedaniel.rei.api.common.entry.type.EntryDefinition; +import me.shedaniel.rei.api.common.entry.type.EntryType; +import me.shedaniel.rei.api.common.entry.type.EntryTypeBridge; +import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry; +import me.shedaniel.rei.api.common.plugins.REIPlugin; +import me.shedaniel.rei.api.common.registry.ReloadStage; +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.ApiStatus; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +@ApiStatus.Internal +public class EntryTypeRegistryImpl implements EntryTypeRegistry { + private final BiMap<ResourceLocation, EntryDefinition<?>> entryTypes = HashBiMap.create(); + private final Table<ResourceLocation, ResourceLocation, List<EntryTypeBridge<?, ?>>> typeBridges = HashBasedTable.create(); + + @Override + public ReloadStage getStage() { + return ReloadStage.START; + } + + @Override + public void acceptPlugin(REIPlugin<?> plugin) { + plugin.registerEntryTypes(this); + } + + @Override + public <T> void register(ResourceLocation id, EntryDefinition<T> definition) { + this.entryTypes.put(id, definition); + } + + @Override + public <A, B> void registerBridge(EntryType<A> original, EntryType<B> destination, EntryTypeBridge<A, B> bridge) { + List<EntryTypeBridge<?, ?>> list = this.typeBridges.get(original.getId(), destination.getId()); + if (list == null) { + this.typeBridges.put(original.getId(), destination.getId(), list = new ArrayList<>()); + } + list.add(bridge); + } + + @Override + public EntryDefinition<?> get(ResourceLocation id) { + return this.entryTypes.get(id); + } + + @Override + public Set<ResourceLocation> keySet() { + return this.entryTypes.keySet(); + } + + @Override + public Set<EntryDefinition<?>> values() { + return this.entryTypes.values(); + } + + @Override + public <A, B> Iterable<EntryTypeBridge<A, B>> getBridgesFor(EntryType<A> original, EntryType<B> destination) { + List<? extends EntryTypeBridge<?, ?>> list = this.typeBridges.get(original.getId(), destination.getId()); + if (list == null) { + return Collections.emptyList(); + } + return (Iterable<EntryTypeBridge<A, B>>) list; + } + + @Override + public void startReload() { + entryTypes.clear(); + typeBridges.clear(); + } +} diff --git a/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/NormalEntryRegistryList.java b/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/NormalEntryRegistryList.java new file mode 100644 index 000000000..73f378c0f --- /dev/null +++ b/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/NormalEntryRegistryList.java @@ -0,0 +1,117 @@ +/* + * 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.client.entry.type; + +import it.unimi.dsi.fastutil.longs.LongList; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.EntryStacks; +import org.jetbrains.annotations.ApiStatus; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.LongPredicate; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@ApiStatus.Internal +public class NormalEntryRegistryList implements EntryRegistryList { + private List<EntryStack<?>> list = new ArrayList<>(); + + public NormalEntryRegistryList() { + } + + public NormalEntryRegistryList(Stream<EntryStack<?>> list) { + list.collect(Collectors.toCollection(() -> this.list)); + } + + @Override + public int size() { + return list.size(); + } + + @Override + public Stream<EntryStack<?>> stream() { + return list.stream(); + } + + @Override + public List<EntryStack<?>> collect() { + return list; + } + + @Override + public int indexOf(EntryStack<?> stack) { + return list.indexOf(stack); + } + + @Override + public int lastIndexOf(EntryStack<?> stack) { + return list.lastIndexOf(stack); + } + + @Override + public void add(EntryStack<?> stack, long hashExact) { + list.add(stack); + } + + @Override + public void add(int index, EntryStack<?> stack, long hashExact) { + list.add(index, stack); + } + + @Override + public void addAll(List<EntryStack<?>> stacks, LongList hashes) { + list.addAll(stacks); + } + + @Override + public void addAll(int index, List<EntryStack<?>> stacks, LongList hashes) { + list.addAll(index, stacks); + } + + @Override + public void remove(EntryStack<?> stack, long hashExact) { + list.remove(stack); + } + + @Override + public boolean removeIf(Predicate<? extends EntryStack<?>> predicate) { + return list.removeIf((Predicate<? super EntryStack<?>>) predicate); + } + + @Override + public boolean removeExactIf(LongPredicate predicate) { + return list.removeIf(stack -> predicate.test(EntryStacks.hashExact(stack))); + } + + @Override + public boolean needsHash() { + return false; + } + + public List<EntryStack<?>> getList() { + return list; + } +} diff --git a/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/ReloadingEntryRegistryList.java b/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/ReloadingEntryRegistryList.java new file mode 100644 index 000000000..53f21406b --- /dev/null +++ b/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/ReloadingEntryRegistryList.java @@ -0,0 +1,109 @@ +/* + * 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.client.entry.type; + +import it.unimi.dsi.fastutil.longs.LongList; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.impl.common.util.HashedEntryStackWrapper; +import net.minecraft.core.Registry; +import org.jetbrains.annotations.ApiStatus; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.LongPredicate; +import java.util.function.Predicate; +import java.util.stream.Stream; + +@ApiStatus.Internal +public class ReloadingEntryRegistryList implements EntryRegistryList { + private List<HashedEntryStackWrapper> list = new ArrayList<>(Registry.ITEM.keySet().size() + 100); + + @Override + public int size() { + return list.size(); + } + + @Override + public Stream<EntryStack<?>> stream() { + return list.stream().map(HashedEntryStackWrapper::unwrap); + } + + @Override + public List<EntryStack<?>> collect() { + return CollectionUtils.map(list, HashedEntryStackWrapper::unwrap); + } + + @Override + public int indexOf(EntryStack<?> stack) { + return list.indexOf(new HashedEntryStackWrapper(stack)); + } + + @Override + public int lastIndexOf(EntryStack<?> stack) { + return list.lastIndexOf(new HashedEntryStackWrapper(stack)); + } + + @Override + public void add(EntryStack<?> stack, long hashExact) { + list.add(new HashedEntryStackWrapper(stack, hashExact)); + } + + @Override + public void add(int index, EntryStack<?> stack, long hashExact) { + list.add(index, new HashedEntryStackWrapper(stack, hashExact)); + } + + @Override + public void addAll(List<EntryStack<?>> stacks, LongList hashes) { + List<HashedEntryStackWrapper> wrappers = CollectionUtils.mapIndexed(stacks, (i, stack) -> new HashedEntryStackWrapper(stack, hashes.getLong(i))); + list.addAll(wrappers); + } + + @Override + public void addAll(int index, List<EntryStack<?>> stacks, LongList hashes) { + List<HashedEntryStackWrapper> wrappers = CollectionUtils.mapIndexed(stacks, (i, stack) -> new HashedEntryStackWrapper(stack, hashes.getLong(i))); + list.addAll(index, wrappers); + } + + @Override + public void remove(EntryStack<?> stack, long hashExact) { + list.remove(new HashedEntryStackWrapper(stack, hashExact)); + } + + @Override + public boolean removeIf(Predicate<? extends EntryStack<?>> predicate) { + return list.removeIf(wrapper -> ((Predicate<EntryStack<?>>) predicate).test(wrapper.unwrap())); + } + + @Override + public boolean removeExactIf(LongPredicate predicate) { + return list.removeIf(wrapper -> predicate.test(wrapper.hashExact())); + } + + @Override + public boolean needsHash() { + return true; + } +} diff --git a/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/collapsed/CollapsibleEntryRegistryImpl.java b/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/collapsed/CollapsibleEntryRegistryImpl.java new file mode 100644 index 000000000..f5222f864 --- /dev/null +++ b/runtime-engine/entries/src/main/java/me/shedaniel/rei/impl/client/entry/type/collapsed/CollapsibleEntryRegistryImpl.java @@ -0,0 +1,149 @@ +/* + * 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.client.entry.type.collapsed; + +import com.google.common.collect.ForwardingList; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import me.shedaniel.rei.api.client.plugins.REIClientPlugin; +import me.shedaniel.rei.api.client.registry.entry.CollapsibleEntry; +import me.shedaniel.rei.api.client.registry.entry.CollapsibleEntryRegistry; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.EntryStacks; +import me.shedaniel.rei.impl.common.InternalLogger; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.ApiStatus; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +@ApiStatus.Internal +public class CollapsibleEntryRegistryImpl extends ForwardingList<CollapsibleEntry> implements CollapsibleEntryRegistry { + private final List<Entry> entries = new ArrayList<>(); + + @Override + public <T> void group(ResourceLocation id, Component name, List<? extends EntryStack<? extends T>> stacks) { + Objects.requireNonNull(stacks, "stacks"); + this.entries.add(new Entry(id, name, new ListMatcher(stacks))); + InternalLogger.getInstance().debug("Added collapsible entry group [%s] %s with %d entries", id, name.getString(), stacks.size()); + } + + @Override + public void group(ResourceLocation id, Component name, Predicate<? extends EntryStack<?>> predicate) { + Objects.requireNonNull(predicate, "predicate"); + this.entries.add(new Entry(id, name, (stack, hashExact) -> ((Predicate<EntryStack<?>>) predicate).test(stack))); + InternalLogger.getInstance().debug("Added collapsible entry group [%s] %s with dynamic predicate", id, name.getString()); + } + + @Override + public void startReload() { + this.entries.clear(); + } + + @Override + public void endReload() { + InternalLogger.getInstance().debug("Registered %d collapsible entry groups: ", entries.size(), + entries.stream().map(entry -> entry.getName().getString()).collect(Collectors.joining(", "))); + } + |
