diff options
| author | shedaniel <daniel@shedaniel.me> | 2024-04-25 22:35:03 +0900 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2024-04-25 22:35:03 +0900 |
| commit | f3d38af79d6e1f6244e17a6583e9d18795419ba5 (patch) | |
| tree | 9da17c321a13a6e46d1e9468e2ab0dbdc3baec4b /runtime/src | |
| parent | 1ada31ed1507733e0a45d51f3b5c9a198af4bd58 (diff) | |
| parent | 9cb2883a0bcfb0a7b1bdacfe146f7e2b6aca22a3 (diff) | |
| download | RoughlyEnoughItems-f3d38af79d6e1f6244e17a6583e9d18795419ba5.tar.gz RoughlyEnoughItems-f3d38af79d6e1f6244e17a6583e9d18795419ba5.tar.bz2 RoughlyEnoughItems-f3d38af79d6e1f6244e17a6583e9d18795419ba5.zip | |
Merge remote-tracking branch 'origin/12.x-1.20' into 13.x-1.20.2
Diffstat (limited to 'runtime/src')
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(); - |
