EntryRegistryImpl.java 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. * This file is licensed under the MIT License, part of Roughly Enough Items.
  3. * Copyright (c) 2018, 2019, 2020 shedaniel
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in all
  13. * copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21. * SOFTWARE.
  22. */
  23. package me.shedaniel.rei.impl;
  24. import com.google.common.collect.Lists;
  25. import com.google.common.collect.Queues;
  26. import com.google.common.collect.Sets;
  27. import me.shedaniel.rei.RoughlyEnoughItemsCore;
  28. import me.shedaniel.rei.api.ConfigObject;
  29. import me.shedaniel.rei.api.EntryRegistry;
  30. import me.shedaniel.rei.api.EntryStack;
  31. import me.shedaniel.rei.api.RecipeHelper;
  32. import net.minecraft.item.Item;
  33. import net.minecraft.item.ItemStack;
  34. import net.minecraft.util.Pair;
  35. import net.minecraft.util.collection.DefaultedList;
  36. import org.jetbrains.annotations.ApiStatus;
  37. import org.jetbrains.annotations.Nullable;
  38. import java.util.*;
  39. import java.util.stream.Collectors;
  40. @ApiStatus.Internal
  41. public class EntryRegistryImpl implements EntryRegistry {
  42. private final List<EntryStack> preFilteredList = Lists.newCopyOnWriteArrayList();
  43. private final List<EntryStack> entries = Lists.newCopyOnWriteArrayList();
  44. private final Queue<Pair<EntryStack, Collection<? extends EntryStack>>> queueRegisterEntryStackAfter = Queues.newConcurrentLinkedQueue();
  45. private List<EntryStack> reloadList;
  46. private boolean doingDistinct = false;
  47. private static EntryStack findFirstOrNullEqualsEntryIgnoreAmount(Collection<EntryStack> list, EntryStack obj) {
  48. for (EntryStack t : list) {
  49. if (t.equalsIgnoreAmount(obj))
  50. return t;
  51. }
  52. return null;
  53. }
  54. public void distinct() {
  55. preFilteredList.clear();
  56. doingDistinct = true;
  57. while (true) {
  58. Pair<EntryStack, Collection<? extends EntryStack>> pair = queueRegisterEntryStackAfter.poll();
  59. if (pair == null)
  60. break;
  61. registerEntriesAfter(pair.getLeft(), pair.getRight());
  62. }
  63. doingDistinct = false;
  64. Set<EntryStackWrapper> set = Sets.newLinkedHashSet();
  65. set.addAll(reloadList.stream().map(EntryStackWrapper::new).collect(Collectors.toList()));
  66. set.removeIf(EntryStackWrapper::isEmpty);
  67. entries.clear();
  68. entries.addAll(set.stream().map(EntryStackWrapper::unwrap).collect(Collectors.toList()));
  69. }
  70. private static class EntryStackWrapper {
  71. private final EntryStack stack;
  72. public EntryStackWrapper(EntryStack stack) {
  73. this.stack = Objects.requireNonNull(stack);
  74. }
  75. @Override
  76. public boolean equals(Object o) {
  77. if (this == o) return true;
  78. if (o == null || getClass() != o.getClass()) return false;
  79. EntryStackWrapper that = (EntryStackWrapper) o;
  80. return stack.equalsAll(that.stack);
  81. }
  82. @Override
  83. public int hashCode() {
  84. return stack.hashCode();
  85. }
  86. public boolean isEmpty() {
  87. return stack.isEmpty();
  88. }
  89. public EntryStack unwrap() {
  90. return stack;
  91. }
  92. }
  93. @Override
  94. public List<EntryStack> getStacksList() {
  95. return RecipeHelper.getInstance().arePluginsLoading() || doingDistinct ? reloadList : entries;
  96. }
  97. @Override
  98. public List<EntryStack> getPreFilteredList() {
  99. return preFilteredList;
  100. }
  101. public void refilter() {
  102. long started = System.currentTimeMillis();
  103. Collection<EntryStack> filteredStacks = ConfigObject.getInstance().getFilteredStacks();
  104. preFilteredList.clear();
  105. for (EntryStack stack : getStacksList()) {
  106. if (findFirstOrNullEqualsEntryIgnoreAmount(filteredStacks, stack) == null)
  107. preFilteredList.add(stack);
  108. }
  109. long time = System.currentTimeMillis() - started;
  110. RoughlyEnoughItemsCore.LOGGER.info("Refiltered %d entries in %dms.", filteredStacks.size(), time);
  111. }
  112. public void reset() {
  113. doingDistinct = false;
  114. reloadList = Lists.newArrayList();
  115. queueRegisterEntryStackAfter.clear();
  116. entries.clear();
  117. reloadList.clear();
  118. preFilteredList.clear();
  119. }
  120. @Override
  121. public List<ItemStack> appendStacksForItem(Item item) {
  122. DefaultedList<ItemStack> list = new DefaultedLinkedList<>(Lists.newLinkedList(), null);
  123. item.appendStacks(item.getGroup(), list);
  124. if (list.isEmpty())
  125. list.add(item.getStackForRender());
  126. return list;
  127. }
  128. @Override
  129. public ItemStack[] getAllStacksFromItem(Item item) {
  130. List<ItemStack> list = appendStacksForItem(item);
  131. ItemStack[] array = list.toArray(new ItemStack[0]);
  132. Arrays.sort(array, (a, b) -> ItemStack.areEqualIgnoreDamage(a, b) ? 0 : 1);
  133. return array;
  134. }
  135. @Override
  136. @Deprecated
  137. @ApiStatus.Internal
  138. public void registerEntryAfter(EntryStack afterEntry, EntryStack stack, boolean checkAlreadyContains) {
  139. if (stack.isEmpty())
  140. return;
  141. if (afterEntry == null) {
  142. getStacksList().add(stack);
  143. } else {
  144. int last = getStacksList().size();
  145. for (int i = last - 1; i >= 0; i--)
  146. if (getStacksList().get(i).equalsAll(afterEntry)) {
  147. last = i + 1;
  148. break;
  149. }
  150. getStacksList().add(last, stack);
  151. }
  152. }
  153. @Override
  154. public void queueRegisterEntryAfter(EntryStack afterEntry, Collection<? extends EntryStack> stacks) {
  155. if (RecipeHelper.getInstance().arePluginsLoading()) {
  156. queueRegisterEntryStackAfter.add(new Pair<>(afterEntry, stacks));
  157. } else {
  158. registerEntriesAfter(afterEntry, stacks);
  159. }
  160. }
  161. @Override
  162. public void registerEntriesAfter(EntryStack afterStack, Collection<? extends EntryStack> stacks) {
  163. if (afterStack != null) {
  164. int index = getStacksList().size();
  165. for (int i = index - 1; i >= 0; i--) {
  166. if (getStacksList().get(i).equalsIgnoreAmount(afterStack)) {
  167. index = i + 1;
  168. break;
  169. }
  170. }
  171. getStacksList().addAll(index, stacks);
  172. } else
  173. getStacksList().addAll(stacks);
  174. }
  175. @ApiStatus.Internal
  176. public static class DefaultedLinkedList<E> extends DefaultedList<E> {
  177. public DefaultedLinkedList(List<E> delegate, @Nullable E initialElement) {
  178. super(delegate, initialElement);
  179. }
  180. }
  181. }