Merge pull request #2975 from Darkere/bestmatch
JEI transfer picks the most common ingredient
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
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.grid.GridType;
|
||||
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.apiimpl.API;
|
||||
import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode;
|
||||
import com.refinedmods.refinedstorage.item.PatternItem;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.CraftingInventory;
|
||||
import net.minecraft.inventory.InventoryHelper;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.ICraftingRecipe;
|
||||
import net.minecraft.util.NonNullList;
|
||||
@@ -21,8 +25,8 @@ import net.minecraftforge.fml.hooks.BasicEventHooks;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class CraftingGridBehavior implements ICraftingGridBehavior {
|
||||
@Override
|
||||
@@ -188,11 +192,18 @@ public class CraftingGridBehavior implements ICraftingGridBehavior {
|
||||
}
|
||||
}
|
||||
|
||||
AtomicReference<Map<Item, ItemStack>> playerItems = new AtomicReference<>();
|
||||
// Now let's fill the matrix
|
||||
for (int i = 0; i < grid.getCraftingMatrix().getSizeInventory(); ++i) {
|
||||
if (recipe[i] != null) {
|
||||
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 (grid.getGridType() == GridType.CRAFTING) {
|
||||
boolean found = false;
|
||||
@@ -246,4 +257,51 @@ public class CraftingGridBehavior implements ICraftingGridBehavior {
|
||||
((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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler<GridCon
|
||||
}
|
||||
|
||||
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 (tracker.hasMissingButAutocraftingAvailable() && Screen.hasControlDown()) {
|
||||
@@ -72,7 +72,7 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler<GridCon
|
||||
)
|
||||
));
|
||||
} else {
|
||||
moveItems(container, recipeLayout);
|
||||
moveItems(container, recipeLayout, tracker);
|
||||
}
|
||||
} else {
|
||||
if (tracker.hasMissing()) {
|
||||
@@ -84,10 +84,10 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler<GridCon
|
||||
}
|
||||
|
||||
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) {
|
||||
moveItems(container, recipeLayout);
|
||||
moveItems(container, recipeLayout, tracker);
|
||||
} else {
|
||||
if (tracker.isAutocraftingAvailable()) {
|
||||
return new RecipeTransferPatternGridError(tracker);
|
||||
@@ -97,8 +97,8 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler<GridCon
|
||||
return null;
|
||||
}
|
||||
|
||||
private IngredientTracker createTracker(GridContainer container, IRecipeLayout recipeLayout, PlayerEntity player) {
|
||||
IngredientTracker tracker = new IngredientTracker(recipeLayout);
|
||||
private IngredientTracker createTracker(GridContainer container, IRecipeLayout recipeLayout, PlayerEntity player, boolean doTransfer) {
|
||||
IngredientTracker tracker = new IngredientTracker(recipeLayout, doTransfer);
|
||||
|
||||
// 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.
|
||||
@@ -140,11 +140,11 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler<GridCon
|
||||
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();
|
||||
|
||||
if (gridContainer.getGrid().getGridType() == GridType.PATTERN && !recipeLayout.getRecipeCategory().getUid().equals(VanillaRecipeCategoryUid.CRAFTING)) {
|
||||
moveForProcessing(recipeLayout);
|
||||
moveForProcessing(recipeLayout, tracker);
|
||||
} else {
|
||||
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> outputs = new LinkedList<>();
|
||||
|
||||
@@ -165,7 +165,7 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler<GridCon
|
||||
List<FluidStack> fluidOutputs = new LinkedList<>();
|
||||
|
||||
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()) {
|
||||
@@ -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) {
|
||||
ItemStack ingredient = guiIngredient.getDisplayedIngredient().copy();
|
||||
ItemStack ingredient = tracker.findBestMatch(guiIngredient.getAllIngredients()).copy();
|
||||
|
||||
if (ingredient == ItemStack.EMPTY) {
|
||||
ingredient = guiIngredient.getDisplayedIngredient().copy();
|
||||
}
|
||||
|
||||
if (guiIngredient.isInput()) {
|
||||
inputs.add(ingredient);
|
||||
|
||||
@@ -1,24 +1,32 @@
|
||||
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.apiimpl.API;
|
||||
import com.refinedmods.refinedstorage.item.PatternItem;
|
||||
import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack;
|
||||
import mezz.jei.api.gui.IRecipeLayout;
|
||||
import mezz.jei.api.gui.ingredient.IGuiIngredient;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
|
||||
public class IngredientTracker {
|
||||
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()) {
|
||||
if (guiIngredient.isInput() && !guiIngredient.getAllIngredients().isEmpty()) {
|
||||
ingredients.add(new Ingredient(guiIngredient));
|
||||
}
|
||||
}
|
||||
this.doTransfer = doTransfer;
|
||||
}
|
||||
|
||||
public Collection<Ingredient> getIngredients() {
|
||||
@@ -27,6 +35,19 @@ public class IngredientTracker {
|
||||
|
||||
public void addAvailableStack(ItemStack stack, @Nullable IGridStack gridStack) {
|
||||
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) {
|
||||
if (available == 0) {
|
||||
@@ -78,4 +99,19 @@ public class IngredientTracker {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user