Merge pull request #2975 from Darkere/bestmatch

JEI transfer picks the most common ingredient
This commit is contained in:
Darkere
2021-10-17 16:58:40 +02:00
committed by GitHub
3 changed files with 113 additions and 15 deletions

View File

@@ -1,5 +1,7 @@
package com.refinedmods.refinedstorage.apiimpl.network.grid; package com.refinedmods.refinedstorage.apiimpl.network.grid;
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternProvider;
import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.INetwork;
import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.api.network.grid.GridType;
import com.refinedmods.refinedstorage.api.network.grid.ICraftingGridBehavior; import com.refinedmods.refinedstorage.api.network.grid.ICraftingGridBehavior;
@@ -10,9 +12,11 @@ import com.refinedmods.refinedstorage.api.util.IComparer;
import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.api.util.IStackList;
import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.API;
import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;
import com.refinedmods.refinedstorage.item.PatternItem;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.CraftingInventory; import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.InventoryHelper; import net.minecraft.inventory.InventoryHelper;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.ICraftingRecipe; import net.minecraft.item.crafting.ICraftingRecipe;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
@@ -21,8 +25,8 @@ import net.minecraftforge.fml.hooks.BasicEventHooks;
import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemHandlerHelper;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.*;
import java.util.List; import java.util.concurrent.atomic.AtomicReference;
public class CraftingGridBehavior implements ICraftingGridBehavior { public class CraftingGridBehavior implements ICraftingGridBehavior {
@Override @Override
@@ -188,11 +192,18 @@ public class CraftingGridBehavior implements ICraftingGridBehavior {
} }
} }
AtomicReference<Map<Item, ItemStack>> playerItems = new AtomicReference<>();
// Now let's fill the matrix // Now let's fill the matrix
for (int i = 0; i < grid.getCraftingMatrix().getSizeInventory(); ++i) { for (int i = 0; i < grid.getCraftingMatrix().getSizeInventory(); ++i) {
if (recipe[i] != null) { if (recipe[i] != null) {
ItemStack[] possibilities = recipe[i]; ItemStack[] possibilities = recipe[i];
if (network != null && grid.isGridActive() && network.getItemStorageCache() != null) {
// sort by the number of items in storage, craftables and inventory
Arrays.sort(possibilities, compareByItemStackCounts(player, network, playerItems));
}
// If we are a crafting grid // If we are a crafting grid
if (grid.getGridType() == GridType.CRAFTING) { if (grid.getGridType() == GridType.CRAFTING) {
boolean found = false; boolean found = false;
@@ -246,4 +257,51 @@ public class CraftingGridBehavior implements ICraftingGridBehavior {
((GridNetworkNode) grid).markDirty(); ((GridNetworkNode) grid).markDirty();
} }
} }
private Comparator<ItemStack> compareByItemStackCounts(PlayerEntity player, INetwork network, AtomicReference<Map<Item, ItemStack>> playerItems) {
return Comparator.comparingInt((ItemStack itemStack) -> {
ItemStack stack = network.getItemStorageCache().getList().get(itemStack);
if (stack != null) {
return stack.getCount();
}
if (network.getCraftingManager().getPattern(itemStack) != null) {
return 1;
}
if (playerItems.get() == null) {
playerItems.set(makePlayerInventoryMap(player, network));
}
ItemStack onPlayer = playerItems.get().get(itemStack.getItem());
if (onPlayer != null) {
return onPlayer.getCount();
}
return 0;
}).reversed();
}
private Map<Item, ItemStack> makePlayerInventoryMap(PlayerEntity player, INetwork network) {
Map<Item, ItemStack> playerItems = new HashMap<>();
for (int j = 0; j < player.inventory.getSizeInventory(); j++) {
ItemStack inventoryStack = player.inventory.getStackInSlot(j);
if (inventoryStack.getItem() instanceof ICraftingPatternProvider) {
ICraftingPattern pattern = PatternItem.fromCache(network.getWorld(), inventoryStack);
if (pattern.isValid()) {
for (ItemStack stack : pattern.getOutputs()) {
if (!stack.isEmpty()) {
playerItems.put(stack.getItem(), stack);
}
}
}
} else {
playerItems.put(inventoryStack.getItem(), inventoryStack);
}
}
return playerItems;
}
} }

View File

@@ -59,7 +59,7 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler<GridCon
} }
private RecipeTransferCraftingGridError transferRecipeForCraftingGrid(GridContainer container, IRecipeLayout recipeLayout, PlayerEntity player, boolean doTransfer) { private RecipeTransferCraftingGridError transferRecipeForCraftingGrid(GridContainer container, IRecipeLayout recipeLayout, PlayerEntity player, boolean doTransfer) {
IngredientTracker tracker = createTracker(container, recipeLayout, player); IngredientTracker tracker = createTracker(container, recipeLayout, player, doTransfer);
if (doTransfer) { if (doTransfer) {
if (tracker.hasMissingButAutocraftingAvailable() && Screen.hasControlDown()) { if (tracker.hasMissingButAutocraftingAvailable() && Screen.hasControlDown()) {
@@ -72,7 +72,7 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler<GridCon
) )
)); ));
} else { } else {
moveItems(container, recipeLayout); moveItems(container, recipeLayout, tracker);
} }
} else { } else {
if (tracker.hasMissing()) { if (tracker.hasMissing()) {
@@ -84,10 +84,10 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler<GridCon
} }
private IRecipeTransferError transferRecipeForPatternGrid(GridContainer container, IRecipeLayout recipeLayout, PlayerEntity player, boolean doTransfer) { private IRecipeTransferError transferRecipeForPatternGrid(GridContainer container, IRecipeLayout recipeLayout, PlayerEntity player, boolean doTransfer) {
IngredientTracker tracker = createTracker(container, recipeLayout, player); IngredientTracker tracker = createTracker(container, recipeLayout, player, doTransfer);
if (doTransfer) { if (doTransfer) {
moveItems(container, recipeLayout); moveItems(container, recipeLayout, tracker);
} else { } else {
if (tracker.isAutocraftingAvailable()) { if (tracker.isAutocraftingAvailable()) {
return new RecipeTransferPatternGridError(tracker); return new RecipeTransferPatternGridError(tracker);
@@ -97,8 +97,8 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler<GridCon
return null; return null;
} }
private IngredientTracker createTracker(GridContainer container, IRecipeLayout recipeLayout, PlayerEntity player) { private IngredientTracker createTracker(GridContainer container, IRecipeLayout recipeLayout, PlayerEntity player, boolean doTransfer) {
IngredientTracker tracker = new IngredientTracker(recipeLayout); IngredientTracker tracker = new IngredientTracker(recipeLayout, doTransfer);
// Using IGridView#getStacks will return a *filtered* list of items in the view, // Using IGridView#getStacks will return a *filtered* list of items in the view,
// which will cause problems - especially if the user uses JEI synchronised searching. // which will cause problems - especially if the user uses JEI synchronised searching.
@@ -140,11 +140,11 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler<GridCon
return System.currentTimeMillis() - lastTransferTimeMs <= TRANSFER_SCROLLBAR_DELAY_MS; return System.currentTimeMillis() - lastTransferTimeMs <= TRANSFER_SCROLLBAR_DELAY_MS;
} }
private void moveItems(GridContainer gridContainer, IRecipeLayout recipeLayout) { private void moveItems(GridContainer gridContainer, IRecipeLayout recipeLayout, IngredientTracker tracker) {
this.lastTransferTimeMs = System.currentTimeMillis(); this.lastTransferTimeMs = System.currentTimeMillis();
if (gridContainer.getGrid().getGridType() == GridType.PATTERN && !recipeLayout.getRecipeCategory().getUid().equals(VanillaRecipeCategoryUid.CRAFTING)) { if (gridContainer.getGrid().getGridType() == GridType.PATTERN && !recipeLayout.getRecipeCategory().getUid().equals(VanillaRecipeCategoryUid.CRAFTING)) {
moveForProcessing(recipeLayout); moveForProcessing(recipeLayout, tracker);
} else { } else {
move(gridContainer, recipeLayout); move(gridContainer, recipeLayout);
} }
@@ -157,7 +157,7 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler<GridCon
)); ));
} }
private void moveForProcessing(IRecipeLayout recipeLayout) { private void moveForProcessing(IRecipeLayout recipeLayout, IngredientTracker tracker) {
List<ItemStack> inputs = new LinkedList<>(); List<ItemStack> inputs = new LinkedList<>();
List<ItemStack> outputs = new LinkedList<>(); List<ItemStack> outputs = new LinkedList<>();
@@ -165,7 +165,7 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler<GridCon
List<FluidStack> fluidOutputs = new LinkedList<>(); List<FluidStack> fluidOutputs = new LinkedList<>();
for (IGuiIngredient<ItemStack> guiIngredient : recipeLayout.getItemStacks().getGuiIngredients().values()) { for (IGuiIngredient<ItemStack> guiIngredient : recipeLayout.getItemStacks().getGuiIngredients().values()) {
handleItemIngredient(inputs, outputs, guiIngredient); handleItemIngredient(inputs, outputs, guiIngredient, tracker);
} }
for (IGuiIngredient<FluidStack> guiIngredient : recipeLayout.getFluidStacks().getGuiIngredients().values()) { for (IGuiIngredient<FluidStack> guiIngredient : recipeLayout.getFluidStacks().getGuiIngredients().values()) {
@@ -187,9 +187,13 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler<GridCon
} }
} }
private void handleItemIngredient(List<ItemStack> inputs, List<ItemStack> outputs, IGuiIngredient<ItemStack> guiIngredient) { private void handleItemIngredient(List<ItemStack> inputs, List<ItemStack> outputs, IGuiIngredient<ItemStack> guiIngredient, IngredientTracker tracker) {
if (guiIngredient != null && guiIngredient.getDisplayedIngredient() != null) { if (guiIngredient != null && guiIngredient.getDisplayedIngredient() != null) {
ItemStack ingredient = guiIngredient.getDisplayedIngredient().copy(); ItemStack ingredient = tracker.findBestMatch(guiIngredient.getAllIngredients()).copy();
if (ingredient == ItemStack.EMPTY) {
ingredient = guiIngredient.getDisplayedIngredient().copy();
}
if (guiIngredient.isInput()) { if (guiIngredient.isInput()) {
inputs.add(ingredient); inputs.add(ingredient);

View File

@@ -1,24 +1,32 @@
package com.refinedmods.refinedstorage.integration.jei; package com.refinedmods.refinedstorage.integration.jei;
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternProvider;
import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.api.util.IComparer;
import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.API;
import com.refinedmods.refinedstorage.item.PatternItem;
import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.ingredient.IGuiIngredient; import mezz.jei.api.gui.ingredient.IGuiIngredient;
import net.minecraft.client.Minecraft;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.*; import java.util.*;
public class IngredientTracker { public class IngredientTracker {
private final List<Ingredient> ingredients = new ArrayList<>(); private final List<Ingredient> ingredients = new ArrayList<>();
private final Map<ResourceLocation, Integer> storedItems = new HashMap<>();
private boolean doTransfer;
public IngredientTracker(IRecipeLayout recipeLayout) { public IngredientTracker(IRecipeLayout recipeLayout, boolean doTransfer) {
for (IGuiIngredient<ItemStack> guiIngredient : recipeLayout.getItemStacks().getGuiIngredients().values()) { for (IGuiIngredient<ItemStack> guiIngredient : recipeLayout.getItemStacks().getGuiIngredients().values()) {
if (guiIngredient.isInput() && !guiIngredient.getAllIngredients().isEmpty()) { if (guiIngredient.isInput() && !guiIngredient.getAllIngredients().isEmpty()) {
ingredients.add(new Ingredient(guiIngredient)); ingredients.add(new Ingredient(guiIngredient));
} }
} }
this.doTransfer = doTransfer;
} }
public Collection<Ingredient> getIngredients() { public Collection<Ingredient> getIngredients() {
@@ -27,6 +35,19 @@ public class IngredientTracker {
public void addAvailableStack(ItemStack stack, @Nullable IGridStack gridStack) { public void addAvailableStack(ItemStack stack, @Nullable IGridStack gridStack) {
int available = stack.getCount(); int available = stack.getCount();
if (doTransfer) {
if (stack.getItem() instanceof ICraftingPatternProvider) {
ICraftingPattern pattern = PatternItem.fromCache(Minecraft.getInstance().world, stack);
if (pattern.isValid()) {
for (ItemStack outputStack : pattern.getOutputs()) {
storedItems.merge(outputStack.getItem().getRegistryName(), outputStack.getCount(), Integer::sum);
}
}
} else {
storedItems.merge(stack.getItem().getRegistryName(), available, Integer::sum);
}
}
for (Ingredient ingredient : ingredients) { for (Ingredient ingredient : ingredients) {
if (available == 0) { if (available == 0) {
@@ -78,4 +99,19 @@ public class IngredientTracker {
return toRequest; return toRequest;
} }
public ItemStack findBestMatch(List<ItemStack> list) {
ItemStack stack = ItemStack.EMPTY;
int count = 0;
for (ItemStack itemStack : list) {
Integer stored = storedItems.get(itemStack.getItem().getRegistryName());
if (stored != null && stored > count) {
stack = itemStack;
count = stored;
}
}
return stack;
}
} }