aboutsummaryrefslogtreecommitdiff
path: root/runtime/src/main/java/me/shedaniel/rei/plugin
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2021-11-21 19:10:50 +0800
committershedaniel <daniel@shedaniel.me>2021-11-21 19:10:50 +0800
commit85e72e9a9bc70cf283ba872172985b338be59233 (patch)
treebce73cb38c00b73d1323c7a014701ee638f2224b /runtime/src/main/java/me/shedaniel/rei/plugin
parenta437fe0560478c636526862679ba1098688bf2c1 (diff)
parentc4cdd997f981d0a3b763140d1515a73941b18f5c (diff)
downloadRoughlyEnoughItems-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')
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java37
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/plugin/client/entry/FluidEntryDefinition.java11
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/plugin/client/entry/ItemEntryDefinition.java5
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/DefaultClientRuntimePlugin.java12
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/FilteredStacksVisibilityHandler.java116
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();
+ }
+}