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;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user