aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2024-04-25 22:36:25 +0900
committershedaniel <daniel@shedaniel.me>2024-04-25 22:36:25 +0900
commit74e800ab4ccd8124c556af804a33e06f9e76b528 (patch)
tree5aaf8e5104ddb97eee0bcd3d8672396ca2f60893
parentc8aac81ec745aca534b301185af61c7b35d35025 (diff)
parentf3d38af79d6e1f6244e17a6583e9d18795419ba5 (diff)
downloadRoughlyEnoughItems-74e800ab4ccd8124c556af804a33e06f9e76b528.tar.gz
RoughlyEnoughItems-74e800ab4ccd8124c556af804a33e06f9e76b528.tar.bz2
RoughlyEnoughItems-74e800ab4ccd8124c556af804a33e06f9e76b528.zip
Merge remote-tracking branch 'origin/13.x-1.20.2' into 14.x-1.20.4
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java1
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionWidget.java5
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigCategories.java3
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigGroups.java2
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java2
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryWidget.java2
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/PaginatedEntryListWidget.java3
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayCache.java88
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayCacheImpl.java172
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayRegistryImpl.java12
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplaysHolder.java55
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplaysHolderImpl.java144
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/view/ViewsImpl.java8
-rwxr-xr-xruntime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json2
14 files changed, 335 insertions, 164 deletions
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java
index b08ad02ef..7840fa6cd 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java
@@ -625,6 +625,7 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData {
public boolean scrollingEntryListWidget = false;
@Comment("Declares whether entry panel should be invisible when not searching")
public boolean hideEntryPanelIfIdle = false;
+ public boolean rainbow = false;
public static class Layout {
@Comment("Declares the position of the search field.")
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionWidget.java
index e695d79b0..265a78d72 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionWidget.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionWidget.java
@@ -34,6 +34,7 @@ import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds;
import me.shedaniel.rei.api.client.gui.widgets.Widgets;
import me.shedaniel.rei.api.client.util.MatrixUtils;
import me.shedaniel.rei.impl.client.gui.config.ConfigAccess;
+import me.shedaniel.rei.impl.client.gui.config.options.AllREIConfigOptions;
import me.shedaniel.rei.impl.client.gui.config.options.CompositeOption;
import me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils;
import me.shedaniel.rei.impl.client.gui.text.TextTransformations;
@@ -48,6 +49,7 @@ import org.joml.Matrix4f;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import static me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils.literal;
import static me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils.translatable;
@@ -59,7 +61,8 @@ public class ConfigOptionWidget {
int[] height = {12};
Label fieldNameLabel;
widgets.add(fieldNameLabel = Widgets.createLabel(new Point(0, 0), TextTransformations.highlightText(option.getName().copy(), option.getOptionNameHighlight(), style -> style.withColor(0xFFC0C0C0)))
- .leftAligned());
+ .leftAligned()
+ .rainbow(Objects.equals(option.getId(), AllREIConfigOptions.RAINBOW.getId())));
WidgetWithBounds optionValue = ConfigOptionValueWidget.create(access, option, width - 10 - fieldNameLabel.getBounds().width);
widgets.add(Widgets.withTranslate(optionValue, () -> new Matrix4f().translate(width - optionValue.getBounds().width - optionValue.getBounds().x, 0, 0)));
widgets.add(new WidgetWithBounds() {
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigCategories.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigCategories.java
index 9122bf1d4..40e94ae10 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigCategories.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigCategories.java
@@ -40,7 +40,8 @@ public interface AllREIConfigCategories {
OptionCategory APPEARANCE = make("appearance")
.add(APPEARANCE_INTERFACE)
- .add(APPEARANCE_TOOLTIPS);
+ .add(APPEARANCE_TOOLTIPS)
+ .add(APPEARANCE_ADVANCED);
OptionCategory INPUT = make("input")
.add(INPUT_KEYBINDS)
/*.add(KEYBINDS_ADVANCED)*/;
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigGroups.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigGroups.java
index a661862a6..28b83e639 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigGroups.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigGroups.java
@@ -39,6 +39,8 @@ public interface AllREIConfigGroups {
OptionGroup APPEARANCE_TOOLTIPS = make("appearance.tooltips")
.add(APPEND_MOD_NAMES)
.add(APPEND_FAVORITES_HINT);
+ OptionGroup APPEARANCE_ADVANCED = make("appearance.advanced")
+ .add(RAINBOW);
OptionGroup INPUT_KEYBINDS = make("input.keybinds")
.add(RECIPE_KEYBIND)
.add(USAGE_KEYBIND)
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java
index 241bd41f1..30340bfba 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java
@@ -69,6 +69,8 @@ public interface AllREIConfigOptions {
CompositeOption<DisplayScreenType> RECIPE_LOOKUP_STYLE = make("appearance.recipe_lookup_style", i -> i.appearance.recipeScreenType, (i, v) -> i.appearance.recipeScreenType = v)
.options(DisplayScreenType.ORIGINAL, DisplayScreenType.COMPOSITE)
.defaultValue(() -> DisplayScreenType.ORIGINAL);
+ CompositeOption<Boolean> RAINBOW = make("appearance.rainbow", i -> i.appearance.rainbow, (i, v) -> i.appearance.rainbow = v)
+ .enabledDisabled();
CompositeOption<Boolean> APPEND_MOD_NAMES = make("appearance.append_mod_names", i -> i.advanced.tooltips.appendModNames, (i, v) -> i.advanced.tooltips.appendModNames = v)
.enabledDisabled();
CompositeOption<Boolean> APPEND_FAVORITES_HINT = make("appearance.append_favorites_hint", i -> i.advanced.tooltips.displayFavoritesTooltip, (i, v) -> i.advanced.tooltips.displayFavoritesTooltip = v)
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryWidget.java
index ca9d7725a..499084650 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryWidget.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryWidget.java
@@ -329,7 +329,7 @@ public class EntryWidget extends Slot implements DraggableStackProviderWidget {
Map<CategoryIdentifier<?>, Boolean> filteringQuickCraftCategories = ConfigObject.getInstance().getFilteringQuickCraftCategories();
boolean shouldFilterDisplays = ConfigObject.getInstance().shouldFilterDisplays();
- for (Display display : displaysHolder.getAllDisplaysByOutputs(getEntries())) {
+ for (Display display : displaysHolder.cache().getAllDisplaysByOutputs(getEntries())) {
CategoryIdentifier<?> categoryIdentifier = display.getCategoryIdentifier();
Optional<? extends CategoryRegistry.CategoryConfiguration<?>> configuration;
if ((configuration = categoryRegistry.tryGet(categoryIdentifier)).isEmpty()
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/PaginatedEntryListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/PaginatedEntryListWidget.java
index 1c9afa42d..726e101d8 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/PaginatedEntryListWidget.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/PaginatedEntryListWidget.java
@@ -37,6 +37,7 @@ import me.shedaniel.rei.api.client.gui.widgets.Widgets;
import me.shedaniel.rei.api.common.entry.EntryStack;
import me.shedaniel.rei.api.common.util.CollectionUtils;
import me.shedaniel.rei.impl.client.ClientHelperImpl;
+import me.shedaniel.rei.impl.client.config.ConfigManagerImpl;
import me.shedaniel.rei.impl.client.gui.InternalTextures;
import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl;
import me.shedaniel.rei.impl.client.gui.widget.BatchedEntryRendererManager;
@@ -242,7 +243,7 @@ public class PaginatedEntryListWidget extends CollapsingEntryListWidget {
}).tooltip(Component.translatable("text.rei.go_back_first_page"), Component.literal(" "), Component.translatable("text.rei.shift_click_to", Component.translatable("text.rei.choose_page")).withStyle(ChatFormatting.GRAY)).focusable(false).onRender((matrices, label) -> {
label.setClickable(getTotalPages() > 1);
label.setMessage(Component.literal(String.format("%s/%s", getPage() + 1, Math.max(getTotalPages(), 1))));
- }).rainbow(new Random().nextFloat() < 1.0E-4D || ClientHelperImpl.getInstance().isAprilFools.get()));
+ }).rainbow(new Random().nextFloat() < 1.0E-4D || ClientHelperImpl.getInstance().isAprilFools.get() || ConfigManagerImpl.getInstance().getConfig().appearance.rainbow));
}
@Override
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayCache.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayCache.java
new file mode 100644
index 000000000..b65aba97c
--- /dev/null
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayCache.java
@@ -0,0 +1,88 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 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.registry.display;
+
+import com.google.common.collect.Iterables;
+import me.shedaniel.rei.api.common.display.Display;
+import me.shedaniel.rei.api.common.entry.EntryStack;
+import me.shedaniel.rei.api.common.util.CollectionUtils;
+import me.shedaniel.rei.impl.client.view.ViewsImpl;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+public interface DisplayCache {
+ boolean doesCache();
+
+ boolean isCached(Display display);
+
+ void add(Display display);
+
+ boolean remove(Display display);
+
+ void endReload();
+
+ Set<Display> getDisplaysNotCached();
+
+ Set<Display> getDisplaysByInput(EntryStack<?> stack);
+
+ Set<Display> getDisplaysByOutput(EntryStack<?> stack);
+
+ default Iterable<Display> getAllDisplaysByInputs(List<EntryStack<?>> stacks) {
+ if (stacks.isEmpty()) return List.of();
+ Iterable<Display> inputCached = null;
+ if (doesCache()) {
+ for (EntryStack<?> stack : stacks) {
+ Set<Display> set = getDisplaysByInput(stack);
+ inputCached = inputCached == null ? set : Iterables.concat(inputCached, set);
+ }
+ if (stacks.size() > 1) inputCached = CollectionUtils.distinctReferenceOf(inputCached);
+ }
+ Collection<Display> notCached = this.getDisplaysNotCached();
+ if (notCached.isEmpty()) return inputCached == null ? List.of() : inputCached;
+ Iterable<Display> filteredNotCached = Iterables.filter(notCached, display ->
+ ViewsImpl.isUsagesFor(null, stacks, display));
+ if (inputCached == null) return filteredNotCached;
+ return Iterables.concat(inputCached, filteredNotCached);
+ }
+
+ default Iterable<Display> getAllDisplaysByOutputs(List<EntryStack<?>> stacks) {
+ if (stacks.isEmpty()) return List.of();
+ Iterable<Display> outputCached = null;
+ if (doesCache()) {
+ for (EntryStack<?> stack : stacks) {
+ Set<Display> set = getDisplaysByOutput(stack);
+ outputCached = outputCached == null ? set : Iterables.concat(outputCached, set);
+ }
+ if (stacks.size() > 1) outputCached = CollectionUtils.distinctReferenceOf(outputCached);
+ }
+ Collection<Display> notCached = this.getDisplaysNotCached();
+ if (notCached.isEmpty()) return outputCached == null ? List.of() : outputCached;
+ Iterable<Display> filteredNotCached = Iterables.filter(notCached, display ->
+ ViewsImpl.isRecipesFor(null, stacks, display));
+ if (outputCached == null) return filteredNotCached;
+ return Iterables.concat(outputCached, filteredNotCached);
+ }
+}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayCacheImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayCacheImpl.java
new file mode 100644
index 000000000..80a73f82e
--- /dev/null
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayCacheImpl.java
@@ -0,0 +1,172 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 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.registry.display;
+
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.SetMultimap;
+import it.unimi.dsi.fastutil.Hash;
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap;
+import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
+import me.shedaniel.rei.api.client.config.ConfigObject;
+import me.shedaniel.rei.api.common.display.Display;
+import me.shedaniel.rei.api.common.entry.EntryIngredient;
+import me.shedaniel.rei.api.common.entry.EntryStack;
+import me.shedaniel.rei.api.common.util.EntryStacks;
+import me.shedaniel.rei.impl.common.InternalLogger;
+
+import java.util.Collections;
+import java.util.Set;
+
+public class DisplayCacheImpl implements DisplayCache {
+ private final boolean cache;
+ private Set<Display> displaysCached = new ReferenceOpenHashSet<>();
+ private Set<Display> displaysNotCached = Collections.synchronizedSet(new ReferenceOpenHashSet<>());
+ private SetMultimap<EntryStack<?>, Display> displaysByInput;
+ private SetMultimap<EntryStack<?>, Display> displaysByOutput;
+ private boolean preprocessed = false;
+
+ public DisplayCacheImpl(boolean init) {
+ this.cache = init && ConfigObject.getInstance().doesCacheDisplayLookup();
+ this.displaysByInput = createSetMultimap();
+ this.displaysByOutput = createSetMultimap();
+ }
+
+ @Override
+ public boolean doesCache() {
+ return this.cache;
+ }
+
+ @Override
+ public boolean isCached(Display display) {
+ return this.cache && this.displaysCached.contains(display);
+ }
+
+ @Override
+ public void add(Display display) {
+ if (this.cache) {
+ if (!preprocessed) {
+ this.displaysNotCached.add(display);
+ } else {
+ this.process(display);
+ this.displaysCached.add(display);
+ }
+ } else {
+ this.displaysNotCached.add(display);
+ }
+ }
+
+ @Override
+ public boolean remove(Display display) {
+ if (this.cache) {
+ if (!preprocessed) {
+ return this.displaysNotCached.remove(display);
+ } else {
+ boolean removed = this.displaysCached.remove(display);
+ if (removed) {
+ for (EntryIngredient input : display.getInputEntries()) {
+ for (EntryStack<?> stack : input) {
+ this.displaysByInput.remove(stack, display);
+ }
+ }
+ for (EntryIngredient output : display.getOutputEntries()) {
+ for (EntryStack<?> stack : output) {
+ this.displaysByOutput.remove(stack, display);
+ }
+ }
+ }
+ return removed;
+ }
+ } else {
+ return this.displaysNotCached.remove(display);
+ }
+ }
+
+ @Override
+ public void endReload() {
+ if (this.cache) {
+ if (preprocessed) {
+ InternalLogger.getInstance().error("DisplayCache#endReload called after preprocessed!");
+ }
+
+ InternalLogger.getInstance().debug("Processing %d displays for optimal lookup performance...", this.displaysNotCached.size());
+ Stopwatch stopwatch = Stopwatch.createStarted();
+ this.displaysCached = new ReferenceOpenHashSet<>(this.displaysNotCached.size());
+ this.displaysByInput = createSetMultimap();
+ this.displaysByOutput = createSetMultimap();
+ for (Display display : this.displaysNotCached) {
+ this.process(display);
+ }
+ this.displaysCached.addAll(this.displaysNotCached);
+ this.displaysNotCached = Set.of();
+ this.preprocessed = true;
+ InternalLogger.getInstance().debug("Processed displays for optimal lookup performance in %s.", stopwatch.stop());
+ }
+ }
+
+ @Override
+ public Set<Display> getDisplaysNotCached() {
+ return this.displaysNotCached;
+ }
+
+ @Override
+ public Set<Display> getDisplaysByInput(EntryStack<?> stack) {
+ return this.displaysByInput.get(stack);
+ }
+
+ @Override
+ public Set<Display> getDisplaysByOutput(EntryStack<?> stack) {
+ return this.displaysByOutput.get(stack);
+ }
+
+ private void process(Display display) {
+ for (EntryIngredient input : display.getInputEntries()) {
+ for (EntryStack<?> stack : input) {
+ this.displaysByInput.put(stack, display);
+ }
+ }
+ for (EntryIngredient output : display.getOutputEntries()) {
+ for (EntryStack<?> stack : output) {
+ this.displaysByOutput.put(stack, display);
+ }
+ }
+ }
+
+ private static SetMultimap<EntryStack<?>, Display> createSetMultimap() {
+ return Multimaps.newSetMultimap(
+ new Object2ObjectOpenCustomHashMap<>(5000, new Hash.Strategy<>() {
+ @Override
+ public int hashCode(EntryStack<?> stack) {
+ return Long.hashCode(EntryStacks.hashFuzzy(stack));
+ }
+
+ @Override
+ public boolean equals(EntryStack<?> o1, EntryStack<?> o2) {
+ return EntryStacks.equalsFuzzy(o1, o2);
+ }
+ }),
+ ReferenceOpenHashSet::new
+ );
+ }
+}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayRegistryImpl.java
index 6bc909aad..9d03a4450 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayRegistryImpl.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplayRegistryImpl.java
@@ -87,7 +87,7 @@ public class DisplayRegistryImpl extends RecipeManagerContextImpl<REIClientPlugi
@Override
public Map<CategoryIdentifier<?>, List<Display>> getAll() {
- return this.displaysHolder.get();
+ return this.displaysHolder.getUnmodifiable();
}
@Override
@@ -202,8 +202,16 @@ public class DisplayRegistryImpl extends RecipeManagerContextImpl<REIClientPlugi
}
}
+ List<Display> failedDisplays = new ArrayList<>();
for (List<Display> displays : getAll().values()) {
- displays.removeIf(display -> !DisplayValidator.validate(display));
+ for (Display display : displays) {
+ if (!DisplayValidator.validate(display)) {
+ failedDisplays.add(display);
+ }
+ }
+ }
+ for (Display display : failedDisplays) {
+ this.displaysHolder.remove(display);
}
this.displaysHolder.endReload();
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplaysHolder.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplaysHolder.java
index 2480053d1..37ff40d50 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplaysHolder.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplaysHolder.java
@@ -23,27 +23,24 @@
package me.shedaniel.rei.impl.client.registry.display;
-import com.google.common.collect.Iterables;
import me.shedaniel.rei.api.common.category.CategoryIdentifier;
import me.shedaniel.rei.api.common.display.Display;
-import me.shedaniel.rei.api.common.entry.EntryStack;
-import me.shedaniel.rei.api.common.util.CollectionUtils;
-import me.shedaniel.rei.impl.client.view.ViewsImpl;
import org.jetbrains.annotations.Nullable;
-import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
public interface DisplaysHolder {
- boolean doesCache();
+ DisplayCache cache();
void add(Display display, @Nullable Object origin);
+ boolean remove(Display display);
+
int size();
- Map<CategoryIdentifier<?>, List<Display>> get();
+ Map<CategoryIdentifier<?>, List<Display>> getUnmodifiable();
@Nullable
Object getDisplayOrigin(Display display);
@@ -51,48 +48,4 @@ public interface DisplaysHolder {
void endReload();
Set<Display> getDisplaysByKey(DisplayKey key);
-
- boolean isCached(Display display);
-
- Set<Display> getDisplaysNotCached();
-
- Set<Display> getDisplaysByInput(EntryStack<?> stack);
-
- Set<Display> getDisplaysByOutput(EntryStack<?> stack);
-
- default Iterable<Display> getAllDisplaysByInputs(List<EntryStack<?>> stacks) {
- if (stacks.isEmpty()) return List.of();
- Iterable<Display> inputCached = null;
- if (doesCache()) {
- for (EntryStack<?> stack : stacks) {
- Set<Display> set = getDisplaysByInput(stack);
- inputCached = inputCached == null ? set : Iterables.concat(inputCached, set);
- }
- if (stacks.size() > 1) inputCached = CollectionUtils.distinctReferenceOf(inputCached);
- }
- Collection<Display> notCached = this.getDisplaysNotCached();
- if (notCached.isEmpty()) return inputCached == null ? List.of() : inputCached;
- Iterable<Display> filteredNotCached = Iterables.filter(notCached, display ->
- ViewsImpl.isUsagesFor(null, stacks, display));
- if (inputCached == null) return filteredNotCached;
- return Iterables.concat(inputCached, filteredNotCached);
- }
-
- default Iterable<Display> getAllDisplaysByOutputs(List<EntryStack<?>> stacks) {
- if (stacks.isEmpty()) return List.of();
- Iterable<Display> outputCached = null;
- if (doesCache()) {
- for (EntryStack<?> stack : stacks) {
- Set<Display> set = getDisplaysByOutput(stack);
- outputCached = outputCached == null ? set : Iterables.concat(outputCached, set);
- }
- if (stacks.size() > 1) outputCached = CollectionUtils.distinctReferenceOf(outputCached);
- }
- Collection<Display> notCached = this.getDisplaysNotCached();
- if (notCached.isEmpty()) return outputCached == null ? List.of() : outputCached;
- Iterable<Display> filteredNotCached = Iterables.filter(notCached, display ->
- ViewsImpl.isRecipesFor(null, stacks, display));
- if (outputCached == null) return filteredNotCached;
- return Iterables.concat(outputCached, filteredNotCached);
- }
}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplaysHolderImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplaysHolderImpl.java
index bf09618c7..09a4ff1a1 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplaysHolderImpl.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/registry/display/DisplaysHolderImpl.java
@@ -23,21 +23,13 @@
package me.shedaniel.rei.impl.client.registry.display;
-import com.google.common.base.Stopwatch;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
-import it.unimi.dsi.fastutil.Hash;
-import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap;
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
-import me.shedaniel.rei.api.client.config.ConfigObject;
import me.shedaniel.rei.api.client.registry.category.CategoryRegistry;
import me.shedaniel.rei.api.common.category.CategoryIdentifier;
import me.shedaniel.rei.api.common.display.Display;
-import me.shedaniel.rei.api.common.entry.EntryIngredient;
-import me.shedaniel.rei.api.common.entry.EntryStack;
-import me.shedaniel.rei.api.common.util.EntryStacks;
import me.shedaniel.rei.impl.client.gui.widget.favorites.history.DisplayHistoryManager;
-import me.shedaniel.rei.impl.common.InternalLogger;
import net.minecraft.resources.ResourceLocation;
import org.apache.commons.lang3.mutable.MutableInt;
import org.jetbrains.annotations.Nullable;
@@ -46,33 +38,26 @@ import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class DisplaysHolderImpl implements DisplaysHolder {
- private final boolean cache;
+ private final DisplayCache cache;
private final SetMultimap<DisplayKey, Display> displaysByKey = Multimaps.newSetMultimap(new IdentityHashMap<>(), ReferenceOpenHashSet::new);
private final Map<CategoryIdentifier<?>, DisplaysList> displays = new ConcurrentHashMap<>();
- private final Map<CategoryIdentifier<?>, List<Display>> unmodifiableDisplays;
- private final WeakHashMap<Display, Object> displaysBase = new WeakHashMap<>();
- private Set<Display> displaysCached = new ReferenceOpenHashSet<>();
- private Set<Display> displaysNotCached = Collections.synchronizedSet(new ReferenceOpenHashSet<>());
- private boolean preprocessed = false;
- private SetMultimap<EntryStack<?>, Display> displaysByInput;
- private SetMultimap<EntryStack<?>, Display> displaysByOutput;
+ private final Map<CategoryIdentifier<?>, List<Display>> unmodifiableDisplays = new RemappingMap<>(
+ Collections.unmodifiableMap(displays), list -> {
+ if (list == null) {
+ return null;
+ } else {
+ return ((DisplaysList) list).synchronizedList;
+ }
+ }, key -> CategoryRegistry.getInstance().tryGet(key).isPresent());
+ private final WeakHashMap<Display, Object> originsMap = new WeakHashMap<>();
private final MutableInt displayCount = new MutableInt(0);
public DisplaysHolderImpl(boolean init) {
- this.cache = init && ConfigObject.getInstance().doesCacheDisplayLookup();
- this.unmodifiableDisplays = new RemappingMap<>(Collections.unmodifiableMap(displays), list -> {
- if (list == null) {
- return null;
- } else {
- return ((DisplaysList) list).synchronizedList;
- }
- }, key -> CategoryRegistry.getInstance().tryGet(key).isPresent());
- this.displaysByInput = createSetMultimap();
- this.displaysByOutput = createSetMultimap();
+ this.cache = new DisplayCacheImpl(init);
}
@Override
- public boolean doesCache() {
+ public DisplayCache cache() {
return this.cache;
}
@@ -86,93 +71,63 @@ public class DisplaysHolderImpl implements DisplaysHolder {
}
this.displayCount.increment();
if (origin != null) {
- synchronized (this.displaysBase) {
- this.displaysBase.put(display, origin);
+ synchronized (this.originsMap) {
+ this.originsMap.put(display, origin);
}
}
- if (this.cache) {
- if (!preprocessed) {
- this.displaysNotCached.add(display);
- } else {
- this.process(display);
- this.displaysCached.add(display);
- }
- } else {
- this.displaysNotCached.add(display);
- }
+ this.cache.add(display);
}
@Override
- public int size() {
- return this.displayCount.intValue();
- }
-
- @Override
- public Map<CategoryIdentifier<?>, List<Display>> get() {
- return this.unmodifiableDisplays;
- }
-
- @Override
- public void endReload() {
- if (this.cache) {
- InternalLogger.getInstance().debug("Processing %d displays for optimal lookup performance...", this.size());
- Stopwatch stopwatch = Stopwatch.createStarted();
- this.displaysCached = new ReferenceOpenHashSet<>(this.size());
- this.displaysByInput = createSetMultimap();
- this.displaysByOutput = createSetMultimap();
- for (Display display : this.displaysNotCached) {
- this.process(display);
+ public boolean remove(Display display) {
+ if (this.displays.get(display.getCategoryIdentifier()).remove(display)) {
+ removeFallout(display);
+