diff options
| author | shedaniel <daniel@shedaniel.me> | 2022-06-22 18:21:04 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2022-06-28 03:21:12 +0800 |
| commit | 86f438c9d823b45f4fc113f1e813d2e12de0ca40 (patch) | |
| tree | 4a8ab3f36cea03c18f78bd615a25ebd0747aa014 | |
| parent | e982a8fbaa7b94a2eea242106322334a1a0eefe9 (diff) | |
| download | RoughlyEnoughItems-86f438c9d823b45f4fc113f1e813d2e12de0ca40.tar.gz RoughlyEnoughItems-86f438c9d823b45f4fc113f1e813d2e12de0ca40.tar.bz2 RoughlyEnoughItems-86f438c9d823b45f4fc113f1e813d2e12de0ca40.zip | |
Close #839
11 files changed, 252 insertions, 32 deletions
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/SimpleDisplayRenderer.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/SimpleDisplayRenderer.java index 872c66636..b6fbca32b 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/SimpleDisplayRenderer.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/SimpleDisplayRenderer.java @@ -33,6 +33,7 @@ import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.gui.widgets.*; import me.shedaniel.rei.api.common.entry.EntryIngredient; import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.entry.type.EntryDefinition; import me.shedaniel.rei.api.common.util.CollectionUtils; import me.shedaniel.rei.api.common.util.EntryStacks; import net.minecraft.client.gui.components.events.GuiEventListener; @@ -67,12 +68,29 @@ public class SimpleDisplayRenderer extends DisplayRenderer implements WidgetHold .disableTooltips(); } - private static List<EntryIngredient> simplify(List<EntryIngredient> original) { + public static List<EntryIngredient> simplify(List<EntryIngredient> original) { List<EntryIngredient> out = new ArrayList<>(); for (EntryIngredient ingredient : original) { EntryIngredient filter = ingredient.filter(Predicates.not(EntryStack::isEmpty)); - if (!filter.isEmpty() && out.stream().noneMatch(s -> equalsList(filter, s))) { + if (filter.isEmpty()) continue; + EntryIngredient orNull = CollectionUtils.findFirstOrNull(out, s -> equalsList(filter, s)); + if (orNull == null) { out.add(filter); + } else { + out.set(out.indexOf(orNull), orNull.map(stack -> { + for (EntryStack<?> filterStack : filter) { + if (EntryStacks.equalsExact(filterStack, stack)) { + EntryDefinition<Object> definition = (EntryDefinition<Object>) filterStack.getDefinition(); + Object newValue = definition.add(stack.getValue(), filterStack.getValue()); + + if (newValue != null) { + stack = EntryStack.of(definition, newValue); + } + } + } + + return stack; + })); } } return out; diff --git a/api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/TransferHandler.java b/api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/TransferHandler.java index a32474290..f1c6e7879 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/TransferHandler.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/TransferHandler.java @@ -26,6 +26,9 @@ package me.shedaniel.rei.api.client.registry.transfer; import me.shedaniel.math.Point; import me.shedaniel.rei.api.client.gui.widgets.Tooltip; 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.impl.ClientInternals; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.Minecraft; @@ -33,6 +36,7 @@ import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.network.chat.Component; import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.tooltip.TooltipComponent; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -160,6 +164,26 @@ public interface TransferHandler extends Comparable<TransferHandler> { Result tooltip(Component component); /** + * Adds a line of tooltip to the result. + * + * @param component the component to add + * @return the result + * @since 8.3 + */ + @ApiStatus.Experimental + Result tooltip(TooltipComponent component); + + /** + * Adds a tooltip component for the missing items. + * + * @param stacks the missing stacks + * @return the result + * @since 8.3 + */ + @ApiStatus.Experimental + Result tooltipMissing(List<EntryIngredient> stacks); + + /** * @return whether this handler has successfully handled the transfer. */ boolean isSuccessful(); @@ -197,7 +221,7 @@ public interface TransferHandler extends Comparable<TransferHandler> { BiConsumer<Point, TooltipSink> getTooltipRenderer(); @ApiStatus.Internal - void fillTooltip(List<Component> components); + void fillTooltip(List<Tooltip.Entry> entries); @FunctionalInterface interface TooltipSink { @@ -239,7 +263,7 @@ public interface TransferHandler extends Comparable<TransferHandler> { final class ResultImpl implements Result { private boolean successful, applicable, returningToScreen, blocking; private Component error; - private List<Component> tooltips = new ArrayList<>(); + private List<Tooltip.Entry> tooltips = new ArrayList<>(); private TransferHandlerRenderer renderer; private BiConsumer<Point, TooltipSink> tooltipRenderer; private int color; @@ -296,11 +320,22 @@ public interface TransferHandler extends Comparable<TransferHandler> { @Override public Result tooltip(Component component) { - this.tooltips.add(component); + this.tooltips.add(Tooltip.entry(component)); + return this; + } + + @Override + public Result tooltip(TooltipComponent component) { + this.tooltips.add(Tooltip.entry(component)); return this; } @Override + public Result tooltipMissing(List<EntryIngredient> ingredients) { + return tooltip(ClientInternals.createMissingTooltip(ingredients)); + } + + @Override public boolean isSuccessful() { return successful; } @@ -336,13 +371,12 @@ public interface TransferHandler extends Comparable<TransferHandler> { } @Override - public void fillTooltip(List<Component> components) { + public void fillTooltip(List<Tooltip.Entry> entries) { if (isApplicable()) { - if (isSuccessful()) { - components.addAll(tooltips); - } else { - components.add(getError()); + if (!isSuccessful()) { + entries.add(Tooltip.entry(getError())); } + entries.addAll(tooltips); } } } diff --git a/api/src/main/java/me/shedaniel/rei/api/common/entry/type/EntryDefinition.java b/api/src/main/java/me/shedaniel/rei/api/common/entry/type/EntryDefinition.java index e6a6e112e..f2d84da72 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/entry/type/EntryDefinition.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/entry/type/EntryDefinition.java @@ -160,6 +160,25 @@ public interface EntryDefinition<T> { return null; } + /** + * Returns a merged copy for two entries. + * <p> + * It is guaranteed that the two entries satisfy {@link #equals(Object, Object, ComparisonContext)} + * with the {@link ComparisonContext#EXACT} context. + * <p> + * Implementation of this method should just need to copy the first value and sets the count to + * the sum of both values. + * + * @param o1 the first value + * @param o2 the second value + * @return the merged copy + * @since 8.3 + */ + @Nullable + default T add(T o1, T o2) { + return null; + } + long hash(EntryStack<T> entry, T value, ComparisonContext context); boolean equals(T o1, T o2, ComparisonContext context); diff --git a/api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java b/api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java index bdf2cbefa..382f4873c 100644 --- a/api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java +++ b/api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java @@ -36,6 +36,8 @@ import me.shedaniel.rei.api.client.gui.widgets.*; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; import me.shedaniel.rei.api.client.registry.screen.ClickArea; import me.shedaniel.rei.api.client.view.ViewSearchBuilder; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.plugins.PluginManager; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -75,6 +77,7 @@ public final class ClientInternals { private static Function<Object, Tooltip.Entry> tooltipEntryProvider = (component) -> throwNotSetup(); private static Supplier<List<String>> jeiCompatMods = ClientInternals::throwNotSetup; private static Supplier<Object> builtinClientPlugin = ClientInternals::throwNotSetup; + private static Function<List<EntryIngredient>, TooltipComponent> missingTooltip = (stacks) -> throwNotSetup(); private static <T> T throwNotSetup() { throw new AssertionError("REI Internals have not been initialized!"); @@ -161,6 +164,10 @@ public final class ClientInternals { return clientPluginManager.get(); } + public static TooltipComponent createMissingTooltip(List<EntryIngredient> stacks) { + return missingTooltip.apply(stacks); + } + @Environment(EnvType.CLIENT) public interface WidgetsProvider { boolean isRenderingPanel(Panel panel); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/AutoCraftingEvaluator.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/AutoCraftingEvaluator.java index a56666c9c..6254f1d1a 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/AutoCraftingEvaluator.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/AutoCraftingEvaluator.java @@ -62,34 +62,34 @@ public class AutoCraftingEvaluator { public static AutoCraftingResult evaluateAutoCrafting(boolean actuallyCrafting, boolean stackedCrafting, Display display, Supplier<Collection<ResourceLocation>> idsSupplier) { AbstractContainerScreen<?> containerScreen = REIRuntime.getInstance().getPreviousContainerScreen(); AutoCraftingResult result = new AutoCraftingResult(); - final List<Component> errorTooltip = new ArrayList<>(); + final List<Tooltip.Entry> errorTooltip = new ArrayList<>(); result.tooltipRenderer = (pos, sink) -> { - List<Component> str = new ArrayList<>(errorTooltip); + List<Tooltip.Entry> str = new ArrayList<>(errorTooltip); if (ConfigObject.getInstance().isFavoritesEnabled()) { - str.add(Component.literal(" ")); - str.add(Component.translatable("text.rei.save.recipes", Component.literal(ConfigObject.getInstance().getFavoriteKeyCode().getLocalizedName().getString().toUpperCase(Locale.ROOT)).withStyle(ChatFormatting.BOLD)).withStyle(ChatFormatting.GRAY)); + str.add(Tooltip.entry(Component.literal(" "))); + str.add(Tooltip.entry(Component.translatable("text.rei.save.recipes", Component.literal(ConfigObject.getInstance().getFavoriteKeyCode().getLocalizedName().getString().toUpperCase(Locale.ROOT)).withStyle(ChatFormatting.BOLD)).withStyle(ChatFormatting.GRAY))); } if (Minecraft.getInstance().options.advancedItemTooltips && idsSupplier != null) { Collection<ResourceLocation> locations = idsSupplier.get(); if (!locations.isEmpty()) { - str.add(Component.literal(" ")); + str.add(Tooltip.entry(Component.literal(" "))); for (ResourceLocation location : locations) { String t = I18n.get("text.rei.recipe_id", "", location.toString()); if (t.startsWith("\n")) { t = t.substring("\n".length()); } - str.add(Component.literal(t).withStyle(ChatFormatting.GRAY)); + str.add(Tooltip.entry(Component.literal(t).withStyle(ChatFormatting.GRAY))); } } } - sink.accept(Tooltip.create(pos, str)); + sink.accept(Tooltip.from(pos, str)); }; if (containerScreen == null) { - errorTooltip.add(Component.translatable("error.rei.not.supported.move.items").withStyle(ChatFormatting.RED)); + errorTooltip.add(Tooltip.entry(Component.translatable("error.rei.not.supported.move.items").withStyle(ChatFormatting.RED))); return result; } @@ -145,38 +145,46 @@ public class AutoCraftingEvaluator { if (!result.hasApplicable) { errorTooltip.clear(); - errorTooltip.add(Component.translatable("error.rei.not.supported.move.items").withStyle(ChatFormatting.RED)); + errorTooltip.add(Tooltip.entry(Component.translatable("error.rei.not.supported.move.items").withStyle(ChatFormatting.RED))); return result; } if (errors.isEmpty()) { errorTooltip.clear(); - errorTooltip.add(Component.translatable("text.auto_craft.move_items")); + errorTooltip.add(Tooltip.entry(Component.translatable("text.auto_craft.move_items"))); if (successfulResult != null) { successfulResult.fillTooltip(errorTooltip); } } else { errorTooltip.clear(); - List<Component> tooltipsFilled = new ArrayList<>(); + List<Tooltip.Entry> tooltipsFilled = new ArrayList<>(); for (TransferHandler.Result error : errors) { error.fillTooltip(tooltipsFilled); } if (errors.size() == 1) { - for (Component tooltipFilled : tooltipsFilled) { - MutableComponent colored = tooltipFilled.copy().withStyle(ChatFormatting.RED); - if (!CollectionUtils.anyMatch(errorTooltip, ss -> ss.getString().equalsIgnoreCase(tooltipFilled.getString()))) { - errorTooltip.add(colored); + for (Tooltip.Entry tooltipFilled : tooltipsFilled) { + if (tooltipFilled.isText()) { + MutableComponent colored = tooltipFilled.getAsText().copy().withStyle(ChatFormatting.RED); + if (!CollectionUtils.anyMatch(errorTooltip, ss -> ss.isText() && ss.getAsText().getString().equalsIgnoreCase(colored.getString()))) { + errorTooltip.add(Tooltip.entry(colored)); + } + } else { + errorTooltip.add(tooltipFilled); } } } else { - errorTooltip.add(Component.translatable("error.rei.multi.errors").withStyle(ChatFormatting.RED)); - for (Component tooltipFilled : tooltipsFilled) { - MutableComponent colored = Component.literal("- ").withStyle(ChatFormatting.RED) - .append(tooltipFilled.copy().withStyle(ChatFormatting.RED)); - if (!CollectionUtils.anyMatch(errorTooltip, ss -> ss.getString().equalsIgnoreCase(colored.getString()))) { - errorTooltip.add(colored); + errorTooltip.add(Tooltip.entry(Component.translatable(new TranslatableComponent("error.rei.multi.errors").withStyle(ChatFormatting.RED)))); + for (Tooltip.Entry tooltipFilled : tooltipsFilled) { + if (tooltipFilled.isText()) { + MutableComponent colored = Component.literal("- ").withStyle(ChatFormatting.RED) + .append(tooltipFilled.getAsText().copy().withStyle(ChatFormatting.RED)); + if (!CollectionUtils.anyMatch(errorTooltip, ss -> ss.isText() && ss.getAsText().getString().equalsIgnoreCase(colored.getString()))) { + errorTooltip.add(Tooltip.entry(colored)); + } + } else { + errorTooltip.add(tooltipFilled); } } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/transfer/MissingStacksTooltip.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/transfer/MissingStacksTooltip.java new file mode 100644 index 000000000..1a6868104 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/transfer/MissingStacksTooltip.java @@ -0,0 +1,107 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 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.transfer; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.math.Matrix4f; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.SimpleDisplayRenderer; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.impl.client.gui.widget.entrylist.EntryListWidget; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.util.Mth; +import net.minecraft.world.inventory.tooltip.TooltipComponent; + +import java.util.List; + +public class MissingStacksTooltip implements ClientTooltipComponent, TooltipComponent { + private static final int MAX_WIDTH = 200; + private final List<EntryIngredient> stacks; + + public MissingStacksTooltip(List<EntryIngredient> stacks) { + this.stacks = SimpleDisplayRenderer.simplify(stacks); + } + + @Override + public int getHeight() { + int entrySize = EntryListWidget.entrySize(); + int w = Math.max(1, MAX_WIDTH / entrySize); + int height = Math.min(6, Mth.ceil(stacks.size() / (float) w)) * entrySize + 2; + height += 12; + return height; + } + + @Override + public int getWidth(Font font) { + int entrySize = EntryListWidget.entrySize(); + int w = Math.max(1, MAX_WIDTH / entrySize); + int size = stacks.size(); + int width = Math.min(size, w) * entrySize; + width = Math.max(width, font.width(new TranslatableComponent("text.rei.missing"))); + return width; + } + + @Override + public void renderImage(Font font, int x, int y, PoseStack poses, ItemRenderer renderer, int z) { + int entrySize = EntryListWidget.entrySize(); + int w = Math.max(1, MAX_WIDTH / entrySize); + int i = 0; + poses.pushPose(); + poses.translate(0, 0, z + 50); + for (EntryIngredient entry : stacks) { + int x1 = x + (i % w) * entrySize; + int y1 = y + 13 + (i / w) * entrySize; + i++; + if (i / w > 5) { + MultiBufferSource.BufferSource source = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder()); + Component text = new TextComponent("+" + (stacks.size() - w * 6 + 1)).withStyle(ChatFormatting.GRAY); + font.drawInBatch(text, x1 + entrySize / 2 - font.width(text) / 2, y1 + entrySize / 2 - 1, -1, true, poses.last().pose(), source, false, 0, 15728880); + source.endBatch(); + break; + } else { + EntryStack<?> stack; + if (entry.isEmpty()) stack = EntryStack.empty(); + else if (entry.size() == 1) stack = entry.get(0); + else stack = entry.get(Mth.floor((System.currentTimeMillis() / 1000 % (double) entry.size()))); + stack.render(poses, new Rectangle(x1, y1, entrySize, entrySize), -1000, -1000, 0); + } + } + poses.popPose(); + } + + @Override + public void renderText(Font font, int x, int y, Matrix4f pose, MultiBufferSource.BufferSource buffers) { + font.drawInBatch(new TranslatableComponent("text.rei.missing").withStyle(ChatFormatting.GRAY), + x, y + 2, -1, true, pose, buffers, false, 0, 15728880); + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/transfer/TransferHandlerRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/transfer/TransferHandlerRegistryImpl.java index 20ec402c7..43b20634b 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/transfer/TransferHandlerRegistryImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/transfer/TransferHandlerRegistryImpl.java @@ -27,12 +27,16 @@ import com.google.common.collect.Iterators; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; import me.shedaniel.rei.api.client.registry.transfer.TransferHandler; import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.impl.ClientInternals; +import net.minecraft.world.inventory.tooltip.TooltipComponent; import org.jetbrains.annotations.ApiStatus; import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; import java.util.List; +import java.util.function.Function; @ApiStatus.Internal public class TransferHandlerRegistryImpl implements TransferHandlerRegistry { @@ -58,4 +62,8 @@ public class TransferHandlerRegistryImpl implements TransferHandlerRegistry { public Iterator<TransferHandler> iterator() { return Iterators.unmodifiableIterator(handlers.iterator()); } + + static { + ClientInternals.attachInstance((Function<List<EntryIngredient>, TooltipComponent>) MissingStacksTooltip::new, "missingTooltip"); + } } 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 dcb63d6c7..b90c88707 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 @@ -41,6 +41,8 @@ import me.shedaniel.rei.api.common.transfer.info.MenuInfoContext; import me.shedaniel.rei.api.common.transfer.info.MenuInfoRegistry; import me.shedaniel.rei.api.common.transfer.info.MenuTransferException; import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.api.common.util.EntryIngredients; +import me.shedaniel.rei.api.common.util.EntryStacks; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.Minecraft; @@ -51,8 +53,10 @@ import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.ItemLike; import java.util.ArrayList; +import java.util.Collection; import java.util.List; @Environment(EnvType.CLIENT) @@ -92,7 +96,8 @@ public class DefaultCategoryHandler implements TransferHandler { .renderer((matrices, mouseX, mouseY, delta, widgets, bounds, d) -> { menuInfo.renderMissingInput(menuInfoContext, oldInputs, missingIndices, matrices, mouseX, mouseY, delta, widgets, bounds); menuInfo.renderMissingInput(menuInfoContext, input, missing, missingIndicesSet, matrices, mouseX, mouseY, delta, widgets, bounds); - }); + }) + .tooltipMissing(CollectionUtils.map(missing, ingredient -> EntryIngredients.ofItemStacks(ingredient.get()))); } if (!ClientHelper.getInstance().canUseMovePackets()) { return Result.createFailed(Component.translatable("error.rei.not.on.server")); 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 4241ccb1b..4798ac656 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 @@ -147,6 +147,12 @@ public class FluidEntryDefinition implements EntryDefinition<FluidStack>, EntryS return new ItemStack(bucket); } + @Nullable + @Override + public FluidStack add(FluidStack o1, FluidStack o2) { + return o1.copyWithAmount(o1.getAmount() + o2.getAmount()); + } + @Override public long hash(EntryStack<FluidStack> entry, FluidStack value, ComparisonContext context) { int code = 1; 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 f7d0e771f..1309b9533 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 @@ -28,6 +28,7 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.Lighting; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; +import dev.architectury.hooks.item.ItemStackHooks; import dev.architectury.utils.Env; import dev.architectury.utils.EnvExecutor; import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; @@ -137,6 +138,12 @@ public class ItemEntryDefinition implements EntryDefinition<ItemStack>, EntrySer return value.copy(); } + @Nullable + @Override + public ItemStack add(ItemStack o1, ItemStack o2) { + return ItemStackHooks.copyWithCount(o1, o1.getCount() + o2.getCount()); + } + @Override public long hash(EntryStack<ItemStack> entry, ItemStack value, ComparisonContext context) { int code = 1; diff --git a/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json b/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json index a8e443ca2..a294b4ce3 100755 --- a/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json +++ b/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json @@ -70,6 +70,7 @@ "text.rei.too_long_nbt": "§cItem NBT is too long to be applied in multiplayer.", "text.rei.accepts": "Accepts following:", "text.rei.tag_accept": "Tag: #%s", + "text.rei.missing": "Missing following:", "text.rei.performance": "Performance Analysis", "text.rei.addons": "REI Addons", "text.rei.shapeless": "Shapeless", |
