From 6a8bc6a8c34af1e3ff15fe8a802ef5ece3c417d2 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Mon, 28 Aug 2023 13:16:57 +0800 Subject: Reworked the transfer api See https://www.craft.me/s/TVL01jO3OZarPE for the documentation of the new experimental simple transfer handle --- .../client/registry/transfer/TransferHandler.java | 69 ++++++- .../transfer/simple/SimpleTransferHandler.java | 201 +++++++++++++++++++++ .../shedaniel/rei/api/common/display/Display.java | 16 ++ .../rei/api/common/entry/InputIngredient.java | 37 ++++ .../rei/api/common/plugins/REIPlugin.java | 11 ++ .../rei/api/common/transfer/RecipeFinder.java | 134 +++++++------- .../api/common/transfer/RecipeFinderPopulator.java | 1 + .../rei/api/common/transfer/info/MenuInfo.java | 1 + .../api/common/transfer/info/MenuInfoContext.java | 1 + .../api/common/transfer/info/MenuInfoProvider.java | 1 + .../api/common/transfer/info/MenuInfoRegistry.java | 1 + .../transfer/info/MenuSerializationContext.java | 1 + .../transfer/info/clean/InputCleanHandler.java | 1 + .../common/transfer/info/simple/DumpHandler.java | 1 + .../info/simple/RecipeBookGridMenuInfo.java | 1 + .../transfer/info/simple/SimpleGridMenuInfo.java | 1 + .../info/simple/SimpleMenuInfoProvider.java | 1 + .../info/simple/SimplePlayerInventoryMenuInfo.java | 3 +- .../transfer/info/stack/ContainerSlotAccessor.java | 1 + .../info/stack/PlayerInventorySlotAccessor.java | 59 ++++++ .../common/transfer/info/stack/SlotAccessor.java | 10 + .../transfer/info/stack/SlotAccessorRegistry.java | 62 +++++++ .../transfer/info/stack/VanillaSlotAccessor.java | 4 + .../me/shedaniel/rei/impl/ClientInternals.java | 13 ++ 24 files changed, 561 insertions(+), 70 deletions(-) create mode 100644 api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/simple/SimpleTransferHandler.java create mode 100644 api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/PlayerInventorySlotAccessor.java create mode 100644 api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/SlotAccessorRegistry.java (limited to 'api/src/main/java/me/shedaniel') 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 994bb1aae..d639d340e 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 @@ -27,6 +27,7 @@ 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.transfer.info.MenuTransferException; import me.shedaniel.rei.impl.ClientInternals; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -40,6 +41,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.function.BiConsumer; import java.util.function.Supplier; @@ -50,7 +52,7 @@ import java.util.function.Supplier; * as a lightweight and simple way to implement recipe transfers. * * @see TransferHandlerRegistry - * @see me.shedaniel.rei.api.common.transfer.info.MenuInfo + * @see me.shedaniel.rei.api.client.registry.transfer.simple.SimpleTransferHandler */ @Environment(EnvType.CLIENT) public interface TransferHandler extends Comparable { @@ -61,6 +63,16 @@ public interface TransferHandler extends Comparable { return 0d; } + /** + * Returns whether the transfer handler is applicable to the current context. + * + * @param context the context of the transfer + * @return whether the transfer handler is applicable to the current context. + */ + default ApplicabilityResult checkApplicable(Context context) { + return ApplicabilityResult.createApplicable(); + } + /** * Handles the transfer of the specified display. *

@@ -257,6 +269,33 @@ public interface TransferHandler extends Comparable { } } + interface ApplicabilityResult { + static ApplicabilityResult createNotApplicable() { + return new ApplicabilityResultImpl(false, null); + } + + static ApplicabilityResult createApplicableWithError(Component error) { + return createApplicableWithError(Result.createFailed(error)); + } + + static ApplicabilityResult createApplicableWithError(TransferHandler.Result result) { + if (result == null) throw new NullPointerException("result"); + if (!result.isApplicable()) throw new IllegalArgumentException("result is not applicable"); + return new ApplicabilityResultImpl(true, result); + } + + static ApplicabilityResult createApplicable() { + return new ApplicabilityResultImpl(true, null); + } + + boolean isApplicable(); + + boolean isSuccessful(); + + @Nullable + TransferHandler.Result getError(); + } + @ApiStatus.Internal final class ResultImpl implements Result { private boolean successful, applicable, returningToScreen, blocking; @@ -413,4 +452,32 @@ public interface TransferHandler extends Comparable { return recipeDisplaySupplier.get(); } } + + @ApiStatus.Internal + final class ApplicabilityResultImpl implements ApplicabilityResult { + private boolean applicable; + @Nullable + private Result error; + + public ApplicabilityResultImpl(boolean applicable, @Nullable Result error) { + this.applicable = applicable; + this.error = error; + } + + @Override + public boolean isApplicable() { + return this.applicable; + } + + @Override + public boolean isSuccessful() { + return this.isApplicable() && this.error == null; + } + + @Nullable + @Override + public TransferHandler.Result getError() { + return this.error; + } + } } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/simple/SimpleTransferHandler.java b/api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/simple/SimpleTransferHandler.java new file mode 100644 index 000000000..e072cea9d --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/simple/SimpleTransferHandler.java @@ -0,0 +1,201 @@ +/* + * 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.api.client.registry.transfer.simple; + +import com.mojang.blaze3d.vertex.PoseStack; +import it.unimi.dsi.fastutil.ints.IntSet; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.widgets.Slot; +import me.shedaniel.rei.api.client.gui.widgets.Widget; +import me.shedaniel.rei.api.client.registry.transfer.TransferHandler; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.entry.InputIngredient; +import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; +import me.shedaniel.rei.api.common.transfer.info.stack.SlotAccessor; +import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.impl.ClientInternals; +import net.minecraft.client.gui.GuiComponent; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.ApiStatus; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +@ApiStatus.Experimental +public interface SimpleTransferHandler extends TransferHandler { + static SimpleTransferHandler create(Class containerClass, + CategoryIdentifier categoryIdentifier, + IntRange inputSlots) { + return new SimpleTransferHandler() { + @Override + public ApplicabilityResult checkApplicable(Context context) { + if (!containerClass.isInstance(context.getMenu()) + || !categoryIdentifier.equals(context.getDisplay().getCategoryIdentifier()) + || context.getContainerScreen() == null) { + return ApplicabilityResult.createNotApplicable(); + } else { + return ApplicabilityResult.createApplicable(); + } + } + + @Override + public Iterable getInputSlots(Context context) { + return IntStream.range(inputSlots.min, inputSlots.maxExclusive) + .mapToObj(id -> SlotAccessor.fromSlot(context.getMenu().getSlot(id))) + .toList(); + } + + @Override + public Iterable getInventorySlots(Context context) { + LocalPlayer player = context.getMinecraft().player; + Inventory inventory = player.getInventory(); + return IntStream.range(0, inventory.items.size()) + .mapToObj(index -> SlotAccessor.fromPlayerInventory(player, index)) + .collect(Collectors.toList()); + } + }; + } + + static SimpleTransferHandler create(Class containerClass, + CategoryIdentifier categoryIdentifier, + IntRange inputSlots, + IntRange inventorySlots) { + return new SimpleTransferHandler() { + @Override + public ApplicabilityResult checkApplicable(Context context) { + if (!containerClass.isInstance(context.getMenu()) + || !categoryIdentifier.equals(context.getDisplay().getCategoryIdentifier()) + || context.getContainerScreen() == null) { + return ApplicabilityResult.createNotApplicable(); + } else { + return ApplicabilityResult.createApplicable(); + } + } + + @Override + public Iterable getInputSlots(Context context) { + return IntStream.range(inputSlots.min, inputSlots.maxExclusive) + .mapToObj(id -> SlotAccessor.fromSlot(context.getMenu().getSlot(id))) + .toList(); + } + + @Override + public Iterable getInventorySlots(Context context) { + return IntStream.range(inventorySlots.min, inventorySlots.maxExclusive) + .mapToObj(id -> SlotAccessor.fromSlot(context.getMenu().getSlot(id))) + .toList(); + } + }; + } + + record IntRange(int min, int maxExclusive) { + } + + /** + * Returns an {@link Iterable} of {@link SlotAccessor}, of the slots that houses the inputs of the transfer. + * + * @param context the context of the transfer + * @return an {@link Iterable} of the input slots. + */ + Iterable getInputSlots(Context context); + + /** + * Returns an {@link Iterable} of {@link SlotAccessor}, of the slots that provides ingredients. + * + * @param context the context of the transfer + * @return an {@link Iterable} of the inventory slots. + */ + Iterable getInventorySlots(Context context); + + /** + * Returns the inputs of the {@link Display}. The nested lists are possible stacks for that specific slot. + * + * @param context the context of the transfer + * @return the list of lists of items + */ + default List> getInputsIndexed(Context context) { + if (context.getDisplay() == null) return Collections.emptyList(); + return CollectionUtils.map(context.getDisplay().getInputIngredients(context.getMenu(), context.getMinecraft().player), (entry) -> + InputIngredient.withType(entry, VanillaEntryTypes.ITEM)); + } + + /** + * Renders the missing ingredients of the transfer. + * + * @param context the context of the transfer + * @param inputs the list of inputs + * @param missing the list of missing stacks + * @param missingIndices the indices of the missing stacks + * @param matrices the rendering transforming context + * @param mouseX the mouse x position + * @param mouseY the mouse y position + * @param delta the delta frame time + * @param widgets the widgets set-up by the category + * @param bounds the bounds of the display + */ + default void renderMissingInput(Context context, List> inputs, List> missing, + IntSet missingIndices, PoseStack matrices, int mouseX, int mouseY, + float delta, List widgets, Rectangle bounds) { + int i = 0; + for (Widget widget : widgets) { + if (widget instanceof Slot && ((Slot) widget).getNoticeMark() == Slot.INPUT) { + if (missingIndices.contains(i++)) { + matrices.pushPose(); + matrices.translate(0, 0, 50); + Rectangle innerBounds = ((Slot) widget).getInnerBounds(); + GuiComponent.fill(matrices, innerBounds.x, innerBounds.y, innerBounds.getMaxX(), innerBounds.getMaxY(), 0x40ff0000); + matrices.popPose(); + } + } + } + } + + default MissingInputRenderer getMissingInputRenderer() { + return this::renderMissingInput; + } + + @Override + default Result handle(Context context) { + return handleSimpleTransfer(context, getMissingInputRenderer(), getInputsIndexed(context), getInputSlots(context), getInventorySlots(context)); + } + + default Result handleSimpleTransfer(TransferHandler.Context context, MissingInputRenderer missingInputRenderer, + List> inputs, Iterable inputSlots, + Iterable inventorySlots) { + return ClientInternals.getSimpleTransferHandler().handle(context, missingInputRenderer, inputs, inputSlots, inventorySlots); + } + + interface MissingInputRenderer { + void renderMissingInput(Context context, List> inputs, List> missing, + IntSet missingIndices, PoseStack matrices, int mouseX, int mouseY, + float delta, List widgets, Rectangle bounds); + } +} diff --git a/api/src/main/java/me/shedaniel/rei/api/common/display/Display.java b/api/src/main/java/me/shedaniel/rei/api/common/display/Display.java index 9fdda7940..4e436efcb 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/display/Display.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/display/Display.java @@ -32,7 +32,10 @@ import me.shedaniel.rei.api.common.transfer.info.MenuSerializationContext; import me.shedaniel.rei.api.common.util.CollectionUtils; import me.shedaniel.rei.impl.display.DisplaySpec; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Collections; @@ -68,10 +71,23 @@ public interface Display extends DisplaySpec { * * @return a list of inputs */ + @Deprecated(forRemoval = true) default List>> getInputIngredients(MenuSerializationContext context, MenuInfo info, boolean fill) { return CollectionUtils.mapIndexed(getInputEntries(context, info, fill), InputIngredient::of); } + /** + * Returns the list of inputs for this display, aligned for the menu. This only affects the stacks resolving for the display, + * and not necessarily the stacks that are displayed. + *

+ * Each ingredient is also provided with the corresponding index slot-wise. The order of the list does not matter. + * + * @return a list of inputs + */ + default List>> getInputIngredients(@Nullable AbstractContainerMenu menu, @Nullable Player player) { + return CollectionUtils.mapIndexed(getInputEntries(), InputIngredient::of); + } + /** * Returns the list of outputs for this display. This only affects the stacks resolving for the display, * and not necessarily the stacks that are displayed. diff --git a/api/src/main/java/me/shedaniel/rei/api/common/entry/InputIngredient.java b/api/src/main/java/me/shedaniel/rei/api/common/entry/InputIngredient.java index 0189d3f87..d29a798d6 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/entry/InputIngredient.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/entry/InputIngredient.java @@ -70,6 +70,34 @@ public interface InputIngredient { }; } + /** + * Creates an input ingredient at the given index. + * + * @param index the index + * @param displayIndex the display index + * @param ingredient the ingredient + * @param the type of entry + * @return the input ingredient + */ + static InputIngredient of(int index, int displayIndex, List ingredient) { + return new InputIngredient<>() { + @Override + public List get() { + return ingredient; + } + + @Override + public int getIndex() { + return index; + } + + @Override + public int getDisplayIndex() { + return displayIndex; + } + }; + } + /** * Returns an input ingredient with only the stacks matching given entry type. * @@ -93,6 +121,11 @@ public interface InputIngredient { public int getIndex() { return ingredient.getIndex(); } + + @Override + public int getDisplayIndex() { + return ingredient.getDisplayIndex(); + } }; } @@ -111,4 +144,8 @@ public interface InputIngredient { * @return the index */ int getIndex(); + + default int getDisplayIndex() { + return getIndex(); + } } diff --git a/api/src/main/java/me/shedaniel/rei/api/common/plugins/REIPlugin.java b/api/src/main/java/me/shedaniel/rei/api/common/plugins/REIPlugin.java index 6a1a320d0..ca265b611 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/plugins/REIPlugin.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/plugins/REIPlugin.java @@ -32,6 +32,7 @@ import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry; import me.shedaniel.rei.api.common.fluid.FluidSupportProvider; import me.shedaniel.rei.api.common.registry.ReloadStage; import me.shedaniel.rei.api.common.registry.Reloadable; +import me.shedaniel.rei.api.common.transfer.info.stack.SlotAccessorRegistry; import org.jetbrains.annotations.ApiStatus; import java.util.Collection; @@ -108,6 +109,16 @@ public interface REIPlugin

> extends Comparable manager, ReloadStage stage) { } diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/RecipeFinder.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/RecipeFinder.java index 5e1ce6740..dee0825db 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/transfer/RecipeFinder.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/RecipeFinder.java @@ -26,8 +26,7 @@ package me.shedaniel.rei.api.common.transfer; import com.google.common.collect.Lists; import it.unimi.dsi.fastutil.ints.*; import net.minecraft.core.NonNullList; -import net.minecraft.core.Registry; -import net.minecraft.world.item.Item; +import net.minecraft.world.entity.player.StackedContents; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import org.jetbrains.annotations.Nullable; @@ -40,11 +39,11 @@ public class RecipeFinder { public final Int2IntMap idToAmountMap = new Int2IntOpenHashMap(); public static int getItemId(ItemStack stack) { - return Registry.ITEM.getId(stack.getItem()); + return StackedContents.getStackingIndex(stack); } public static ItemStack getStackFromId(int itemId) { - return itemId == 0 ? ItemStack.EMPTY : new ItemStack(Item.byId(itemId)); + return StackedContents.fromStackingIndex(itemId); } public void addNormalItem(ItemStack stack) { @@ -63,7 +62,6 @@ public class RecipeFinder { int itemCount = Math.min(count, stack.getCount()); this.addItem(itemId, itemCount); } - } public boolean contains(int itemId) { @@ -93,16 +91,16 @@ public class RecipeFinder { return this.findRecipe(ingredients, intList_1, 1); } - public boolean findRecipe(NonNullList ingredients, @Nullable IntList intList_1, int int_1) { - return (new RecipeFinder.Filter(ingredients)).find(int_1, intList_1); + public boolean findRecipe(NonNullList ingredients, @Nullable IntList intList_1, int maxCrafts) { + return (new RecipeFinder.Filter(ingredients)).find(maxCrafts, intList_1); } public int countRecipeCrafts(NonNullList ingredients, @Nullable IntList intList_1) { return this.countRecipeCrafts(ingredients, Integer.MAX_VALUE, intList_1); } - public int countRecipeCrafts(NonNullList ingredients, int int_1, @Nullable IntList intList_1) { - return (new RecipeFinder.Filter(ingredients)).countCrafts(int_1, intList_1); + public int countRecipeCrafts(NonNullList ingredients, int maxCrafts, @Nullable IntList intList_1) { + return (new RecipeFinder.Filter(ingredients)).countCrafts(maxCrafts, intList_1); } public void clear() { @@ -115,7 +113,7 @@ public class RecipeFinder { private final int[] usableIngredientItemIds; private final int usableIngredientSize; private final BitSet bitSet; - private final IntList field_7557 = new IntArrayList(); + private final IntList path = new IntArrayList(); private final NonNullList ingredientsInput; public Filter(NonNullList ingredientsInput) { @@ -133,7 +131,7 @@ public class RecipeFinder { // Loops over usable ingredients for (int usableIngredientIndex = 0; usableIngredientIndex < this.usableIngredientSize; ++usableIngredientIndex) { if (possibleStacks.contains(this.usableIngredientItemIds[usableIngredientIndex])) { - this.bitSet.set(this.method_7420(true, usableIngredientIndex, ingredientIndex)); + this.bitSet.set(this.getIndex(true, usableIngredientIndex, ingredientIndex)); } } } @@ -141,21 +139,21 @@ public class RecipeFinder { } @SuppressWarnings("deprecation") - public boolean find(int int_1, @Nullable IntList intList_1) { - if (int_1 <= 0) { + public boolean find(int maxCrafts, @Nullable IntList intList_1) { + if (maxCrafts <= 0) { return true; } else { int int_2; - for (int_2 = 0; this.method_7423(int_1); ++int_2) { - RecipeFinder.this.take(this.usableIngredientItemIds[this.field_7557.getInt(0)], int_1); - int int_3 = this.field_7557.size() - 1; - this.method_7421(this.field_7557.getInt(int_3)); + for (int_2 = 0; this.dfs(maxCrafts); ++int_2) { + RecipeFinder.this.take(this.usableIngredientItemIds[this.path.getInt(0)], maxCrafts); + int int_3 = this.path.size() - 1; + this.setSatisfied(this.path.getInt(int_3)); for (int int_4 = 0; int_4 < int_3; ++int_4) { - this.method_7414((int_4 & 1) == 0, this.field_7557.get(int_4), this.field_7557.get(int_4 + 1)); + this.toggleResidual((int_4 & 1) == 0, this.path.get(int_4), this.path.get(int_4 + 1)); } - this.field_7557.clear(); + this.path.clear(); this.bitSet.clear(0, this.ingredientCount + this.usableIngredientSize); } @@ -174,9 +172,9 @@ public class RecipeFinder { intList_1.add(0); } else { for (int int_7 = 0; int_7 < this.usableIngredientSize; ++int_7) { - if (this.method_7425(false, int_5, int_7)) { - this.method_7414(true, int_7, int_5); - RecipeFinder.this.addItem(this.usableIngredientItemIds[int_7], int_1); + if (this.hasResidual(false, int_5, int_7)) { + this.toggleResidual(true, int_7, int_5); + RecipeFinder.this.addItem(this.usableIngredientItemIds[int_7], maxCrafts); if (boolean_2) { intList_1.add(this.usableIngredientItemIds[int_7]); } @@ -209,18 +207,18 @@ public class RecipeFinder { return intCollection_1.toIntArray(); } - private boolean method_7423(int int_1) { + private boolean dfs(int amount) { int usableIngredientSize = this.usableIngredientSize; for (int int_3 = 0; int_3 < usableIngredientSize; ++int_3) { - if (RecipeFinder.this.idToAmountMap.get(this.usableIngredientItemIds[int_3]) >= int_1) { - this.method_7413(false, int_3); + if (RecipeFinder.this.idToAmountMap.get(this.usableIngredientItemIds[int_3]) >= amount) { + this.visit(false, int_3); - while (!this.field_7557.isEmpty()) { - int int_4 = this.field_7557.size(); + while (!this.path.isEmpty()) { + int int_4 = this.path.size(); boolean boolean_1 = (int_4 & 1) == 1; - int int_5 = this.field_7557.getInt(int_4 - 1); - if (!boolean_1 && !this.method_7416(int_5)) { + int int_5 = this.path.getInt(int_4 - 1); + if (!boolean_1 && !this.isSatisfied(int_5)) { break; } @@ -228,19 +226,19 @@ public class RecipeFinder { int int_8; for (int_8 = 0; int_8 < int_6; ++int_8) { - if (!this.method_7426(boolean_1, int_8) && this.method_7418(boolean_1, int_5, int_8) && this.method_7425(boolean_1, int_5, int_8)) { - this.method_7413(boolean_1, int_8); + if (!this.hasVisited(boolean_1, int_8) && this.hasConnection(boolean_1, int_5, int_8) && this.hasResidual(boolean_1, int_5, int_8)) { + this.visit(boolean_1, int_8); break; } } - int_8 = this.field_7557.size(); + int_8 = this.path.size(); if (int_8 == int_4) { - this.field_7557.removeInt(int_8 - 1); + this.path.removeInt(int_8 - 1); } } - if (!this.field_7557.isEmpty()) { + if (!this.path.isEmpty()) { return true; } } @@ -249,57 +247,57 @@ public class RecipeFinder { return false; } - private boolean method_7416(int int_1) { - return this.bitSet.get(this.method_7419(int_1)); + private boolean isSatisfied(int int_1) { + return this.bitSet.get(this.getSatisfiedIndex(int_1)); } - private void method_7421(int int_1) { - this.bitSet.set(this.method_7419(int_1)); + private void setSatisfied(int int_1) { + this.bitSet.set(this.getSatisfiedIndex(int_1)); } - private int method_7419(int int_1) { + private int getSatisfiedIndex(int int_1) { return this.ingredientCount + this.usableIngredientSize + int_1; } - private boolean method_7418(boolean boolean_1, int int_1, int int_2) { - return this.bitSet.get(this.method_7420(boolean_1, int_1, int_2)); + private boolean hasConnection(boolean boolean_1, int int_1, int int_2) { + return this.bitSet.get(this.getIndex(boolean_1, int_1, int_2)); } - private boolean method_7425(boolean boolean_1, int int_1, int int_2) { - return boolean_1 != this.bitSet.get(1 + this.method_7420(boolean_1, int_1, int_2)); + private boolean hasResidual(boolean boolean_1, int int_1, int int_2) { + return boolean_1 != this.bitSet.get(1 + this.getIndex(boolean_1, int_1, int_2)); } - private void method_7414(boolean boolean_1, int int_1, int int_2) { - this.bitSet.flip(1 + this.method_7420(boolean_1, int_1, int_2)); + private void toggleResidual(boolean boolean_1, int int_1, int int_2) { + this.bitSet.flip(1 + this.getIndex(boolean_1, int_1, int_2)); } - private int method_7420(boolean boolean_1, int int_1, int int_2) { + private int getIndex(boolean boolean_1, int int_1, int int_2) { int int_3 = boolean_1 ? int_1 * this.ingredientCount + int_2 : int_2 * this.ingredientCount + int_1; return this.ingredientCount + this.usableIngredientSize + this.ingredientCount + 2 * int_3; } - private void method_7413(boolean boolean_1, int int_1) { - this.bitSet.set(this.method_7424(boolean_1, int_1)); - this.field_7557.add(int_1); + private void visit(boolean boolean_1, int int_1) { + this.bitSet.set(this.getVisitedIndex(boolean_1, int_1)); + this.path.add(int_1); } - private boolean method_7426(boolean boolean_1, int int_1) { - return this.bitSet.get(this.method_7424(boolean_1, int_1)); + private boolean hasVisited(boolean boolean_1, int int_1) { + return this.bitSet.get(this.getVisitedIndex(boolean_1, int_1)); } - private int method_7424(boolean boolean_1, int int_1) { + private int getVisitedIndex(boolean boolean_1, int int_1) { return (boolean_1 ? 0 : this.ingredientCount) + int_1; } - public int countCrafts(int int_1, @Nullable IntList intList_1) { + public int countCrafts(int maxCrafts, @Nullable IntList intList_1) { int int_2 = 0; - int int_3 = Math.min(int_1, this.method_7415()) + 1; + int crafts = Math.min(maxCrafts, this.getMinIngredientCount()) + 1; while (true) { while (true) { - int int_4 = (int_2 + int_3) / 2; + int int_4 = (int_2 + crafts) / 2; if (this.find(int_4, null)) { - if (int_3 - int_2 <= 1) { + if (crafts - int_2 <= 1) { if (int_4 > 0) { this.find(int_4, intList_1); } @@ -309,30 +307,30 @@ public class RecipeFinder { int_2 = int_4; } else { - int_3 = int_4; + crafts = int_4; } } } } @SuppressWarnings("deprecation") - private int method_7415() { - int int_1 = Integer.MAX_VALUE; + private int getMinIngredientCount() { + int min = Integer.MAX_VALUE; - for (Ingredient ingredient_1 : this.ingredients) { - int int_2 = 0; + for (Ingredient ingredient : this.ingredients) { + int maxIngredientCount = 0; - int int_3; - for (IntListIterator var5 = ingredient_1.getStackingIds().iterator(); var5.hasNext(); int_2 = Math.max(int_2, RecipeFinder.this.idToAmountMap.get(int_3))) { - int_3 = var5.next(); + int currStackingId; + for (IntListIterator stackingIds = ingredient.getStackingIds().iterator(); stackingIds.hasNext(); maxIngredientCount = Math.max(maxIngredientCount, RecipeFinder.this.idToAmountMap.get(currStackingId))) { + currStackingId = stackingIds.next(); } - if (int_1 > 0) { - int_1 = Math.min(int_1, int_2); + if (min > 0) { + min = Math.min(min, maxIngredientCount); } } - return int_1; + return min; } } -} \ No newline at end of file +} diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/RecipeFinderPopulator.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/RecipeFinderPopulator.java index f7f48b277..581a552e4 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/transfer/RecipeFinderPopulator.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/RecipeFinderPopulator.java @@ -28,6 +28,7 @@ import me.shedaniel.rei.api.common.transfer.info.MenuInfoContext; import net.minecraft.world.inventory.AbstractContainerMenu; @FunctionalInterface +@Deprecated(forRemoval = true) public interface RecipeFinderPopulator { void populate(MenuInfoContext context, RecipeFinder finder); } diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfo.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfo.java index 160995292..5f2176d0b 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfo.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfo.java @@ -62,6 +62,7 @@ import java.util.List; * @see me.shedaniel.rei.api.common.transfer.info.simple.SimplePlayerInventoryMenuInfo * @see me.shedaniel.rei.api.common.transfer.info.simple.SimpleGridMenuInfo */ +@Deprecated(forRemoval = true) public interface MenuInfo { /** * Returns a {@link RecipeFinderPopulator}, used to populate a {@link RecipeFinder} with diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfoContext.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfoContext.java index 1dd45a697..25f9374bb 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfoContext.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfoContext.java @@ -34,6 +34,7 @@ import net.minecraft.world.inventory.AbstractContainerMenu; * @param

the type of {@link Player}, server sided contexts may pass {@link net.minecraft.server.level.ServerPlayer} instead * @param the type of {@link Display} */ +@Deprecated(forRemoval = true) public interface MenuInfoContext extends MenuSerializationContext { D getDisplay(); } diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfoProvider.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfoProvider.java index 45a5c2cf8..4d5a6b41c 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfoProvider.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfoProvider.java @@ -40,6 +40,7 @@ import java.util.Optional; * @param the type of display * @see SimpleMenuInfoProvider */ +@Deprecated(forRemoval = true) public interface MenuInfoProvider { @Environment(EnvType.CLIENT) Optional> provideClient(D display, MenuSerializationContext context, T menu); diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfoRegistry.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfoRegistry.java index 8cc392f3c..dda383d06 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfoRegistry.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuInfoRegistry.java @@ -39,6 +39,7 @@ import java.util.function.Predicate; /** * Registry for {@link MenuInfo}, for the default REI {@link me.shedaniel.rei.api.client.registry.transfer.TransferHandler}. */ +@Deprecated(forRemoval = true) public interface MenuInfoRegistry extends Reloadable { static MenuInfoRegistry getInstance() { return PluginManager.getServerInstance().get(MenuInfoRegistry.class); diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuSerializationContext.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuSerializationContext.java index 33fe1c01d..5cdb36fde 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuSerializationContext.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/MenuSerializationContext.java @@ -34,6 +34,7 @@ import net.minecraft.world.inventory.AbstractContainerMenu; * @param the type of {@link AbstractContainerMenu} * @param

the type of {@link Player}, server sided contexts may pass {@link net.minecraft.server.level.ServerPlayer} instead */ +@Deprecated(forRemoval = true) public interface MenuSerializationContext { T getMenu(); diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/clean/InputCleanHandler.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/clean/InputCleanHandler.java index bf27c291b..82071f4c6 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/clean/InputCleanHandler.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/clean/InputCleanHandler.java @@ -33,6 +33,7 @@ import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.ApiStatus; @FunctionalInterface +@Deprecated(forRemoval = true) public interface InputCleanHandler { void clean(MenuInfoContext context); diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/DumpHandler.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/DumpHandler.java index 03df342da..222651b79 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/DumpHandler.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/DumpHandler.java @@ -30,6 +30,7 @@ import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; @FunctionalInterface +@Deprecated(forRemoval = true) public interface DumpHandler { boolean dump(MenuInfoContext context, ItemStack stackToDump); diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/RecipeBookGridMenuInfo.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/RecipeBookGridMenuInfo.java index b353c2bf2..bd000880d 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/RecipeBookGridMenuInfo.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/RecipeBookGridMenuInfo.java @@ -30,6 +30,7 @@ import net.minecraft.world.entity.player.StackedContents; import net.minecraft.world.inventory.RecipeBookMenu; import net.minecraft.world.item.ItemStack; +@Deprecated(forRemoval = true) public class RecipeBookGridMenuInfo, D extends SimpleGridMenuDisplay> implements SimpleGridMenuInfo { private final D display; diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/SimpleGridMenuInfo.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/SimpleGridMenuInfo.java index 380abd507..e8bae7a64 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/SimpleGridMenuInfo.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/SimpleGridMenuInfo.java @@ -44,6 +44,7 @@ import java.util.stream.IntStream; * @param the type of display * @see SimpleGridMenuDisplay */ +@Deprecated(forRemoval = true) public interface SimpleGridMenuInfo extends SimplePlayerInventoryMenuInfo { default Iterable getInputSlots(MenuInfoContext context) { return getInputStackSlotIds(context) diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/SimpleMenuInfoProvider.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/SimpleMenuInfoProvider.java index c176005d7..8f394b985 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/SimpleMenuInfoProvider.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/SimpleMenuInfoProvider.java @@ -42,6 +42,7 @@ import java.util.function.Function; * @param the type of the menu * @param the type of display */ +@Deprecated(forRemoval = true) public interface SimpleMenuInfoProvider extends MenuInfoProvider { static SimpleMenuInfoProvider of(Function> provider) { return provider::apply; diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/SimplePlayerInventoryMenuInfo.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/SimplePlayerInventoryMenuInfo.java index 7a5df1a3d..11d57c129 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/SimplePlayerInventoryMenuInfo.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/simple/SimplePlayerInventoryMenuInfo.java @@ -46,6 +46,7 @@ import java.util.stream.IntStream; * @param the type of the menu * @param the type of display */ +@Deprecated(forRemoval = true) public interface SimplePlayerInventoryMenuInfo extends MenuInfo { default RecipeFinderPopulator getRecipeFinderPopulator() { return (context, finder) -> { @@ -93,7 +94,7 @@ public interface SimplePlayerInventoryMenuInfo getInventorySlots(MenuInfoContext context) { Inventory inventory = context.getPlayerEntity().getInventory(); return IntStream.range(0, inventory.items.size()) - .mapToObj(index -> SlotAccessor.fromContainer(inventory, index)) + .mapToObj(index -> SlotAccessor.fromPlayerInventory(context.getPlayerEntity(), index)) .collect(Collectors.toList()); } diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/ContainerSlotAccessor.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/ContainerSlotAccessor.java index b16f41c3b..b2ff12a3e 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/ContainerSlotAccessor.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/ContainerSlotAccessor.java @@ -29,6 +29,7 @@ import net.minecraft.world.item.ItemStack; /** * Simple implementation of {@link SlotAccessor} that wraps around a slot in {@link Container}. */ +@Deprecated(forRemoval = true) public class ContainerSlotAccessor implements SlotAccessor { protected Container container; protected int index; diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/PlayerInventorySlotAccessor.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/PlayerInventorySlotAccessor.java new file mode 100644 index 000000000..6a98f8e76 --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/PlayerInventorySlotAccessor.java @@ -0,0 +1,59 @@ +/* + * 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.api.common.transfer.info.stack; + +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; + +/** + * Simple implementation of {@link SlotAccessor} that wraps around a slot in player's inventory. + */ +public class PlayerInventorySlotAccessor implements SlotAccessor { + protected Player player; + protected int index; + + public PlayerInventorySlotAccessor(Player player, int index) { + this.player = player; + this.index = index; + } + + @Override + public ItemStack getItemStack() { + return player.getInventory().getItem(index); + } + + @Override + public void setItemStack(ItemStack stack) { + this.player.getInventory().setItem(index, stack); + } + + @Override + public ItemStack takeStack(int amount) { + return this.player.getInventory().removeItem(index, amount); + } + + public int getIndex() { + return index; + } +} diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/SlotAccessor.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/SlotAccessor.java index bc3bc3c4e..79513fe40 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/SlotAccessor.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/SlotAccessor.java @@ -24,11 +24,15 @@ package me.shedaniel.rei.api.common.transfer.info.stack; import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.ApiStatus; /** * A wrapper for accessing {@link Slot}, can be wrapped for non-vanilla {@link Slot} implementations. + * + * @see SlotAccessorRegistry */ public interface SlotAccessor { ItemStack getItemStack(); @@ -41,7 +45,13 @@ public interface SlotAccessor { return new VanillaSlotAccessor(slot); } + @Deprecated(forRemoval = true) static SlotAccessor fromContainer(Container container, int index) { return new ContainerSlotAccessor(container, index); } + + @ApiStatus.Experimental + static SlotAccessor fromPlayerInventory(Player player, int index) { + return new PlayerInventorySlotAccessor(player, index); + } } diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/SlotAccessorRegistry.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/SlotAccessorRegistry.java new file mode 100644 index 000000000..0de44ebbe --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/SlotAccessorRegistry.java @@ -0,0 +1,62 @@ +/* + * 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.api.common.transfer.info.stack; + +import me.shedaniel.rei.api.common.plugins.PluginManager; +import me.shedaniel.rei.api.common.plugins.REIServerPlugin; +import me.shedaniel.rei.api.common.registry.Reloadable; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Predicate; + +@ApiStatus.Experimental +public interface SlotAccessorRegistry extends Reloadable { + /** + * @return the instance of {@link SlotAccessorRegistry} + */ + static SlotAccessorRegistry getInstance() { + return PluginManager.getServerInstance().get(SlotAccessorRegistry.class); + } + + void register(ResourceLocation id, Predicate accessorPredicate, Serializer serializer); + + @Nullable + Serializer get(ResourceLocation id); + + CompoundTag save(AbstractContainerMenu menu, Player player, SlotAccessor accessor); + + SlotAccessor read(AbstractContainerMenu menu, Player player, CompoundTag tag); + + interface Serializer { + SlotAccessor read(AbstractContainerMenu menu, Player player, CompoundTag tag); + + @Nullable + CompoundTag save(AbstractContainerMenu menu, Player player, SlotAccessor accessor); + } +} diff --git a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/VanillaSlotAccessor.java b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/VanillaSlotAccessor.java index ab780431e..6e3c97134 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/VanillaSlotAccessor.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/transfer/info/stack/VanillaSlotAccessor.java @@ -50,4 +50,8 @@ public class VanillaSlotAccessor implements SlotAccessor { public ItemStack takeStack(int amount) { return slot.remove(amount); } + + public Slot getSlot() { + return slot; + } } 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 9f03b2549..e7e165b97 100644 --- a/api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java +++ b/api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java @@ -38,9 +38,12 @@ import me.shedaniel.rei.api.client.gui.Renderer; 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.registry.transfer.TransferHandler; import me.shedaniel.rei.api.client.view.ViewSearchBuilder; import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.entry.InputIngredient; import me.shedaniel.rei.api.common.plugins.PluginManager; +import me.shedaniel.rei.api.common.transfer.info.stack.SlotAccessor; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.gui.components.events.GuiEventListener; @@ -50,6 +53,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.chat.FormattedText; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.tooltip.TooltipComponent; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import org.apache.commons.lang3.function.TriFunction; import org.jetbrains.annotations.ApiStatus; @@ -71,6 +75,7 @@ public final class ClientInternals { private static Supplier> clientPluginManager = ClientInternals::throwNotSetup; private static Supplier> emptyEntryRenderer = ClientInternals::throwNotSetup; private static Supplier filteringRuleTypeRegistry = ClientInternals::throwNotSetup; + private static Supplier simpleTransferHandler = ClientInternals::throwNotSetup; private static BiFunction>, Supplier, FavoriteEntry> delegateFavoriteEntry = (supplier, toJson) -> throwNotSetup(); private static BiFunction, FavoriteMenuEntry> subMenuEntry = (supplier, toJson) -> throwNotSetup(); private static BiFunction toggleEntry = (supplier, toJson) -> throwNotSetup(); @@ -185,6 +190,10 @@ public final class ClientInternals { return filteringRuleTypeRegistry.get(); } + public static SimpleTransferHandler getSimpleTransferHandler() { + return simpleTransferHandler.get(); + } + @Environment(EnvType.CLIENT) public interface WidgetsProvider { boolean isRenderingPanel(Panel panel); @@ -225,4 +234,8 @@ public final class ClientInternals { WidgetWithBounds wrapPadded(int padLeft, int padRight, int padTop, int padBottom, WidgetWithBounds widget); } + + public interface SimpleTransferHandler { + TransferHandler.Result handle(TransferHandler.Context context, me.shedaniel.rei.api.client.registry.transfer.simple.SimpleTransferHandler.MissingInputRenderer missingInputRenderer, List> inputs, Iterable inputSlots, Iterable inventorySlots); + } } -- cgit