diff options
| author | shedaniel <daniel@shedaniel.me> | 2021-11-21 19:10:50 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2021-11-21 19:10:50 +0800 |
| commit | 85e72e9a9bc70cf283ba872172985b338be59233 (patch) | |
| tree | bce73cb38c00b73d1323c7a014701ee638f2224b /runtime/src/main/java/me/shedaniel/rei/plugin | |
| parent | a437fe0560478c636526862679ba1098688bf2c1 (diff) | |
| parent | c4cdd997f981d0a3b763140d1515a73941b18f5c (diff) | |
| download | RoughlyEnoughItems-85e72e9a9bc70cf283ba872172985b338be59233.tar.gz RoughlyEnoughItems-85e72e9a9bc70cf283ba872172985b338be59233.tar.bz2 RoughlyEnoughItems-85e72e9a9bc70cf283ba872172985b338be59233.zip | |
Merge remote-tracking branch 'origin/6.x-1.17' into 7.x-1.18
# Conflicts:
# api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfo.java
# gradle.properties
# runtime/src/main/java/me/shedaniel/rei/impl/client/search/argument/type/TooltipArgumentType.java
# runtime/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java
Diffstat (limited to 'runtime/src/main/java/me/shedaniel/rei/plugin')
5 files changed, 176 insertions, 5 deletions
diff --git a/runtime/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java b/runtime/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java index 52385b57f..0c22cadda 100644 --- a/runtime/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java +++ b/runtime/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java @@ -30,6 +30,7 @@ import it.unimi.dsi.fastutil.ints.IntList; import me.shedaniel.rei.RoughlyEnoughItemsNetwork; import me.shedaniel.rei.api.client.ClientHelper; import me.shedaniel.rei.api.client.registry.transfer.TransferHandler; +import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerErrorRenderer; import me.shedaniel.rei.api.common.category.CategoryIdentifier; import me.shedaniel.rei.api.common.display.Display; import me.shedaniel.rei.api.common.transfer.RecipeFinder; @@ -48,11 +49,26 @@ import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.Nullable; import java.util.List; @Environment(EnvType.CLIENT) public class DefaultCategoryHandler implements TransferHandler { + private static class ErrorData { + private MenuInfoContext<AbstractContainerMenu, Player, Display> menuInfoContext; + private MenuInfo<AbstractContainerMenu, Display> menuInfo; + private List<List<ItemStack>> inputs; + private IntList intList; + + public ErrorData(MenuInfoContext<AbstractContainerMenu, Player, Display> menuInfoContext, MenuInfo<AbstractContainerMenu, Display> menuInfo, List<List<ItemStack>> inputs, IntList intList) { + this.menuInfoContext = menuInfoContext; + this.menuInfo = menuInfo; + this.inputs = inputs; + this.intList = intList; + } + } + @Override public Result handle(Context context) { Display display = context.getDisplay(); @@ -75,10 +91,10 @@ public class DefaultCategoryHandler implements TransferHandler { return Result.createNotApplicable(); } } - List<List<ItemStack>> input = menuInfo.getInputs(menuInfoContext); + List<List<ItemStack>> input = menuInfo.getInputs(menuInfoContext, false); IntList intList = hasItems(menuInfoContext, menu, menuInfo, display, input); if (!intList.isEmpty()) { - return Result.createFailed(new TranslatableComponent("error.rei.not.enough.materials"), intList); + return Result.createFailed(new TranslatableComponent("error.rei.not.enough.materials")).errorRenderer(new ErrorData(menuInfoContext, menuInfo, input, intList)); } if (!ClientHelper.getInstance().canUseMovePackets()) { return Result.createFailed(new TranslatableComponent("error.rei.not.on.server")); @@ -101,6 +117,23 @@ public class DefaultCategoryHandler implements TransferHandler { } @Override + @Environment(EnvType.CLIENT) + @Nullable + public TransferHandlerErrorRenderer provideErrorRenderer(Context context, Object data) { + if (data instanceof ErrorData) { + MenuInfoContext<AbstractContainerMenu, Player, Display> menuInfoContext = ((ErrorData) data).menuInfoContext; + MenuInfo<AbstractContainerMenu, Display> menuInfo = ((ErrorData) data).menuInfo; + List<List<ItemStack>> inputs = ((ErrorData) data).inputs; + IntList intList = ((ErrorData) data).intList; + return (matrices, mouseX, mouseY, delta, widgets, bounds, display) -> { + menuInfo.renderMissingInput(menuInfoContext, inputs, intList, matrices, mouseX, mouseY, delta, widgets, bounds); + }; + } + + return null; + } + + @Override public double getPriority() { return -10; } diff --git a/runtime/src/main/java/me/shedaniel/rei/plugin/client/entry/FluidEntryDefinition.java b/runtime/src/main/java/me/shedaniel/rei/plugin/client/entry/FluidEntryDefinition.java index 6ddaba0ba..afb0f3613 100644 --- a/runtime/src/main/java/me/shedaniel/rei/plugin/client/entry/FluidEntryDefinition.java +++ b/runtime/src/main/java/me/shedaniel/rei/plugin/client/entry/FluidEntryDefinition.java @@ -130,9 +130,14 @@ public class FluidEntryDefinition implements EntryDefinition<FluidStack>, EntryS public FluidStack normalize(EntryStack<FluidStack> entry, FluidStack value) { Fluid fluid = value.getFluid(); if (fluid instanceof FlowingFluid flowingFluid) fluid = flowingFluid.getSource(); - FluidStack copy = FluidStack.create(fluid, value.getAmount(), value.getTag()); - copy.setAmount(FluidStack.bucketAmount()); - return copy; + return FluidStack.create(fluid, FluidStack.bucketAmount(), value.getTag()); + } + + @Override + public FluidStack wildcard(EntryStack<FluidStack> entry, FluidStack value) { + Fluid fluid = value.getFluid(); + if (fluid instanceof FlowingFluid) fluid = ((FlowingFluid) fluid).getSource(); + return FluidStack.create(fluid, FluidStack.bucketAmount()); } @Override diff --git a/runtime/src/main/java/me/shedaniel/rei/plugin/client/entry/ItemEntryDefinition.java b/runtime/src/main/java/me/shedaniel/rei/plugin/client/entry/ItemEntryDefinition.java index 647d2c7dc..9b34f65d8 100644 --- a/runtime/src/main/java/me/shedaniel/rei/plugin/client/entry/ItemEntryDefinition.java +++ b/runtime/src/main/java/me/shedaniel/rei/plugin/client/entry/ItemEntryDefinition.java @@ -129,6 +129,11 @@ public class ItemEntryDefinition implements EntryDefinition<ItemStack>, EntrySer } @Override + public ItemStack wildcard(EntryStack<ItemStack> entry, ItemStack value) { + return new ItemStack(value.getItem(), 1); + } + + @Override public long hash(EntryStack<ItemStack> entry, ItemStack value, ComparisonContext context) { int code = 1; code = 31 * code + System.identityHashCode(value.getItem()); diff --git a/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/DefaultClientRuntimePlugin.java b/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/DefaultClientRuntimePlugin.java index d7c9ed2f8..2e25cf0bf 100644 --- a/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/DefaultClientRuntimePlugin.java +++ b/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/DefaultClientRuntimePlugin.java @@ -44,6 +44,7 @@ import me.shedaniel.rei.api.client.gui.widgets.Panel; import me.shedaniel.rei.api.client.gui.widgets.Tooltip; import me.shedaniel.rei.api.client.gui.widgets.Widgets; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; +import me.shedaniel.rei.api.client.registry.display.DisplayRegistry; import me.shedaniel.rei.api.client.registry.entry.EntryRegistry; import me.shedaniel.rei.api.client.registry.screen.DisplayBoundsProvider; import me.shedaniel.rei.api.client.registry.screen.ExclusionZones; @@ -62,6 +63,7 @@ import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; import me.shedaniel.rei.impl.client.gui.screen.AbstractDisplayViewingScreen; import me.shedaniel.rei.impl.client.gui.screen.DefaultDisplayViewingScreen; import me.shedaniel.rei.impl.client.gui.widget.FavoritesListWidget; +import me.shedaniel.rei.impl.common.entry.type.EntryRegistryImpl; import me.shedaniel.rei.plugin.autocrafting.DefaultCategoryHandler; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -82,6 +84,8 @@ import java.util.function.Function; @Environment(EnvType.CLIENT) @ApiStatus.Internal public class DefaultClientRuntimePlugin implements REIClientPlugin { + private final FilteredStacksVisibilityHandler filteredStacksVisibilityHandler = new FilteredStacksVisibilityHandler(); + @SuppressWarnings("rawtypes") public DefaultClientRuntimePlugin() { PluginStageExecutionWatcher watcher = new PluginStageExecutionWatcher(); @@ -111,6 +115,14 @@ public class DefaultClientRuntimePlugin implements REIClientPlugin { } })); } + + ((EntryRegistryImpl) registry).refilterListener.add(filteredStacksVisibilityHandler::reset); + } + + @Override + public void registerDisplays(DisplayRegistry registry) { + filteredStacksVisibilityHandler.reset(); + registry.registerVisibilityPredicate(filteredStacksVisibilityHandler); } @Override diff --git a/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/FilteredStacksVisibilityHandler.java b/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/FilteredStacksVisibilityHandler.java new file mode 100644 index 000000000..0f5270b3e --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/FilteredStacksVisibilityHandler.java @@ -0,0 +1,116 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021 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.plugin.client.runtime; + +import com.google.common.base.Stopwatch; +import dev.architectury.event.EventResult; +import it.unimi.dsi.fastutil.objects.Reference2BooleanMap; +import it.unimi.dsi.fastutil.objects.Reference2BooleanMaps; +import it.unimi.dsi.fastutil.objects.Reference2BooleanOpenHashMap; +import me.shedaniel.rei.RoughlyEnoughItemsCore; +import me.shedaniel.rei.api.client.config.ConfigObject; +import me.shedaniel.rei.api.client.registry.display.DisplayCategory; +import me.shedaniel.rei.api.client.registry.display.DisplayRegistry; +import me.shedaniel.rei.api.client.registry.display.visibility.DisplayVisibilityPredicate; +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.impl.client.config.ConfigObjectImpl; +import me.shedaniel.rei.impl.client.entry.filtering.*; + +import java.util.List; +import java.util.function.Predicate; + +public class FilteredStacksVisibilityHandler implements DisplayVisibilityPredicate { + private boolean checkHiddenStacks; + private Reference2BooleanMap<Display> visible = Reference2BooleanMaps.synchronize(new Reference2BooleanOpenHashMap<>()); + private List<FilteringRule<?>> filteringRules; + private FilteringCacheImpl cache; + private final Predicate<Display> displayPredicate = this::checkHiddenStacks; + + @Override + public EventResult handleDisplay(DisplayCategory<?> category, Display display) { + if (checkHiddenStacks) { + return visible.computeBooleanIfAbsent(display, displayPredicate) ? EventResult.pass() : EventResult.interruptFalse(); + } + + return EventResult.pass(); + } + + public void reset() { + checkHiddenStacks = ConfigObject.getInstance().shouldFilterDisplays(); + visible = Reference2BooleanMaps.synchronize(new Reference2BooleanOpenHashMap<>()); + + if (checkHiddenStacks) { + filteringRules = ((ConfigObjectImpl) ConfigObject.getInstance()).getFilteringRules(); + cache = new FilteringCacheImpl(); + for (int i = filteringRules.size() - 1; i >= 0; i--) { + FilteringRule<?> rule = filteringRules.get(i); + cache.setCache(rule, rule.prepareCache(false)); + } + + cacheExisting(); + } else { + filteringRules = null; + cache = null; + } + } + + public void cacheExisting() { + Stopwatch stopwatch = Stopwatch.createStarted(); + DisplayRegistry.getInstance().getAll().values().parallelStream().map(displays -> { + Reference2BooleanMap<Display> current = new Reference2BooleanOpenHashMap<>(); + for (Display display : displays) { + current.put(display, checkHiddenStacks(display)); + } + return current; + }).forEach(map -> { + visible.putAll(map); + }); + RoughlyEnoughItemsCore.LOGGER.debug("Computed existing filtered displays with %d rules in %s", filteringRules.size(), stopwatch.stop()); + } + + private boolean checkHiddenStacks(Display display) { + for (EntryIngredient ingredient : display.getInputEntries()) { + if (!ingredient.isEmpty() && isEntryIngredientAllHidden(ingredient, cache, filteringRules)) { + return false; + } + } + for (EntryIngredient ingredient : display.getOutputEntries()) { + if (!ingredient.isEmpty() && isEntryIngredientAllHidden(ingredient, cache, filteringRules)) { + return false; + } + } + + return true; + } + + private static boolean isEntryIngredientAllHidden(EntryIngredient ingredient, FilteringCache cache, List<FilteringRule<?>> rules) { + FilteringContextImpl context = new FilteringContextImpl(false, ingredient); + for (int i = rules.size() - 1; i >= 0; i--) { + FilteringRule<?> rule = rules.get(i); + context.handleResult(rule.processFilteredStacks(context, cache, false)); + } + return context.stacks.get(FilteringContextType.SHOWN).isEmpty() && context.stacks.get(FilteringContextType.DEFAULT).isEmpty(); + } +} |
