* Batch network extraction on shift crafting potential fix for #2104 * resolve requested changes * resolve more requested changes
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
package com.refinedmods.refinedstorage.api.network.grid;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.ICraftingRecipe;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Defines default behavior of crafting grids.
|
||||
*/
|
||||
@@ -11,11 +14,13 @@ public interface ICraftingGridBehavior {
|
||||
/**
|
||||
* Logic for regular crafting.
|
||||
*
|
||||
* @param grid the grid
|
||||
* @param recipe the recipe
|
||||
* @param player the player
|
||||
* @param grid the grid
|
||||
* @param recipe the recipe
|
||||
* @param player the player
|
||||
* @param availableItems the items available for shift crafting
|
||||
* @param usedItems the items used by shift crafting
|
||||
*/
|
||||
void onCrafted(INetworkAwareGrid grid, ICraftingRecipe recipe, PlayerEntity player);
|
||||
void onCrafted(INetworkAwareGrid grid, ICraftingRecipe recipe, PlayerEntity player, @Nullable IStackList<ItemStack> availableItems, @Nullable IStackList<ItemStack> usedItems);
|
||||
|
||||
/**
|
||||
* Logic for crafting with shift click (mass crafting).
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler;
|
||||
import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;
|
||||
import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;
|
||||
import com.refinedmods.refinedstorage.api.util.IFilter;
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.inventory.CraftResultInventory;
|
||||
@@ -201,9 +202,11 @@ public interface IGrid {
|
||||
/**
|
||||
* Called when an item is crafted in a crafting grid.
|
||||
*
|
||||
* @param player the player that crafted the item
|
||||
* @param player the player that crafted the item
|
||||
* @param availableItems the items available for shift crafting
|
||||
* @param usedItems the items used by shift crafting
|
||||
*/
|
||||
void onCrafted(PlayerEntity player);
|
||||
void onCrafted(PlayerEntity player, @Nullable IStackList<ItemStack> availableItems, @Nullable IStackList<ItemStack> usedItems);
|
||||
|
||||
/**
|
||||
* Called when the clear button is pressed in the pattern grid or crafting grid.
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.refinedmods.refinedstorage.api.network.grid.INetworkAwareGrid;
|
||||
import com.refinedmods.refinedstorage.api.network.security.Permission;
|
||||
import com.refinedmods.refinedstorage.api.util.Action;
|
||||
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 net.minecraft.entity.player.PlayerEntity;
|
||||
@@ -19,12 +20,13 @@ import net.minecraftforge.common.ForgeHooks;
|
||||
import net.minecraftforge.fml.hooks.BasicEventHooks;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CraftingGridBehavior implements ICraftingGridBehavior {
|
||||
@Override
|
||||
public void onCrafted(INetworkAwareGrid grid, ICraftingRecipe recipe, PlayerEntity player) {
|
||||
public void onCrafted(INetworkAwareGrid grid, ICraftingRecipe recipe, PlayerEntity player, @Nullable IStackList<ItemStack> availableItems, @Nullable IStackList<ItemStack> usedItems) {
|
||||
NonNullList<ItemStack> remainder = recipe.getRemainingItems(grid.getCraftingMatrix());
|
||||
|
||||
INetwork network = grid.getNetwork();
|
||||
@@ -53,7 +55,17 @@ public class CraftingGridBehavior implements ICraftingGridBehavior {
|
||||
}
|
||||
} else if (!slot.isEmpty()) { // We don't have a remainder, but the slot is not empty.
|
||||
if (slot.getCount() == 1 && network != null) { // Attempt to refill the slot with the same item from the network, only if we have a network and only if it's the last item.
|
||||
ItemStack refill = network.extractItem(slot, 1, Action.PERFORM);
|
||||
ItemStack refill;
|
||||
if (availableItems == null) { // for regular crafting
|
||||
refill = network.extractItem(slot, 1, Action.PERFORM);
|
||||
} else { // for shift crafting
|
||||
if (availableItems.get(slot) != null) {
|
||||
refill = availableItems.remove(slot, 1).getStack().copy();
|
||||
usedItems.add(refill);
|
||||
} else {
|
||||
refill = ItemStack.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
matrix.setInventorySlotContents(i, refill);
|
||||
|
||||
@@ -71,28 +83,48 @@ public class CraftingGridBehavior implements ICraftingGridBehavior {
|
||||
|
||||
@Override
|
||||
public void onCraftedShift(INetworkAwareGrid grid, PlayerEntity player) {
|
||||
CraftingInventory matrix = grid.getCraftingMatrix();
|
||||
INetwork network = grid.getNetwork();
|
||||
List<ItemStack> craftedItemsList = new ArrayList<>();
|
||||
int amountCrafted = 0;
|
||||
ItemStack crafted = grid.getCraftingResult().getStackInSlot(0);
|
||||
|
||||
int maxCrafted = crafted.getMaxStackSize();
|
||||
|
||||
ForgeHooks.setCraftingPlayer(player);
|
||||
int amountCrafted = 0;
|
||||
boolean useNetwork = network != null;
|
||||
|
||||
IStackList<ItemStack> availableItems = null;
|
||||
if (useNetwork) {
|
||||
// We need a modifiable list of the items in storage that are relevant for this craft.
|
||||
// For performance reason we extract these into an extra list
|
||||
availableItems = createFilteredItemList(network, matrix);
|
||||
}
|
||||
|
||||
//A second list to remember which items have been extracted
|
||||
IStackList<ItemStack> usedItems = API.instance().createItemStackList();
|
||||
|
||||
ForgeHooks.setCraftingPlayer(player);
|
||||
// Do while the item is still craftable (aka is the result slot still the same as the original item?) and we don't exceed the max stack size.
|
||||
do {
|
||||
grid.onCrafted(player);
|
||||
grid.onCrafted(player, availableItems, usedItems);
|
||||
|
||||
craftedItemsList.add(crafted.copy());
|
||||
|
||||
amountCrafted += crafted.getCount();
|
||||
} while (API.instance().getComparer().isEqual(crafted, grid.getCraftingResult().getStackInSlot(0)) && amountCrafted < maxCrafted && amountCrafted + crafted.getCount() <= maxCrafted );
|
||||
} while (API.instance().getComparer().isEqual(crafted, grid.getCraftingResult().getStackInSlot(0)) && amountCrafted < maxCrafted && amountCrafted + crafted.getCount() <= maxCrafted);
|
||||
|
||||
INetwork network = grid.getNetwork();
|
||||
if (useNetwork) {
|
||||
usedItems.getStacks().forEach(stack -> network.extractItem(stack.getStack(), stack.getStack().getCount(), Action.PERFORM));
|
||||
}
|
||||
|
||||
for (ItemStack craftedItem : craftedItemsList) {
|
||||
if (!player.inventory.addItemStackToInventory(craftedItem.copy())) {
|
||||
ItemStack remainder = network == null ? craftedItem : network.insertItem(craftedItem, craftedItem.getCount(), Action.PERFORM);
|
||||
|
||||
ItemStack remainder = craftedItem;
|
||||
|
||||
if (useNetwork) {
|
||||
remainder = network.insertItem(craftedItem, craftedItem.getCount(), Action.PERFORM);
|
||||
}
|
||||
|
||||
if (!remainder.isEmpty()) {
|
||||
InventoryHelper.spawnItemStack(player.getEntityWorld(), player.getPosition().getX(), player.getPosition().getY(), player.getPosition().getZ(), remainder);
|
||||
@@ -108,6 +140,19 @@ public class CraftingGridBehavior implements ICraftingGridBehavior {
|
||||
ForgeHooks.setCraftingPlayer(null);
|
||||
}
|
||||
|
||||
private IStackList<ItemStack> createFilteredItemList(INetwork network, CraftingInventory matrix) {
|
||||
IStackList<ItemStack> availableItems = API.instance().createItemStackList();
|
||||
for (int i = 0; i < matrix.getSizeInventory(); ++i) {
|
||||
ItemStack stack = network.getItemStorageCache().getList().get(matrix.getStackInSlot(i));
|
||||
|
||||
//Don't add the same item twice into the list. Items may appear twice in a recipe but not in storage.
|
||||
if (stack != null && availableItems.get(stack) == null) {
|
||||
availableItems.add(stack);
|
||||
}
|
||||
}
|
||||
return availableItems;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecipeTransfer(INetworkAwareGrid grid, PlayerEntity player, ItemStack[][] recipe) {
|
||||
INetwork network = grid.getNetwork();
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;
|
||||
import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;
|
||||
import com.refinedmods.refinedstorage.api.util.Action;
|
||||
import com.refinedmods.refinedstorage.api.util.IFilter;
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
import com.refinedmods.refinedstorage.apiimpl.API;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.AllowedTagList;
|
||||
import com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.FluidGridStorageCacheListener;
|
||||
@@ -55,10 +56,7 @@ import net.minecraftforge.items.wrapper.InvWrapper;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
public class GridNetworkNode extends NetworkNode implements INetworkAwareGrid, IType {
|
||||
public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid");
|
||||
@@ -422,8 +420,8 @@ public class GridNetworkNode extends NetworkNode implements INetworkAwareGrid, I
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCrafted(PlayerEntity player) {
|
||||
API.instance().getCraftingGridBehavior().onCrafted(this, currentRecipe, player);
|
||||
public void onCrafted(PlayerEntity player, @Nullable IStackList<ItemStack> availableItems, @Nullable IStackList<ItemStack> usedItems) {
|
||||
API.instance().getCraftingGridBehavior().onCrafted(this, currentRecipe, player, availableItems, usedItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,7 +23,7 @@ public class ResultCraftingGridSlot extends CraftingResultSlot {
|
||||
onCrafting(stack);
|
||||
|
||||
if (!player.getEntityWorld().isRemote) {
|
||||
grid.onCrafted(player);
|
||||
grid.onCrafted(player, null, null);
|
||||
}
|
||||
|
||||
return ItemStack.EMPTY;
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler;
|
||||
import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;
|
||||
import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;
|
||||
import com.refinedmods.refinedstorage.api.util.IFilter;
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
import com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.FluidGridStorageCacheListener;
|
||||
import com.refinedmods.refinedstorage.inventory.item.FilterItemHandler;
|
||||
import com.refinedmods.refinedstorage.item.WirelessFluidGridItem;
|
||||
@@ -271,7 +272,7 @@ public class WirelessFluidGrid implements INetworkAwareGrid {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCrafted(PlayerEntity player) {
|
||||
public void onCrafted(PlayerEntity player, @Nullable IStackList<ItemStack> availableItems, @Nullable IStackList<ItemStack> usedItems) {
|
||||
// NO OP
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler;
|
||||
import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache;
|
||||
import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener;
|
||||
import com.refinedmods.refinedstorage.api.util.IFilter;
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
import com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.ItemGridStorageCacheListener;
|
||||
import com.refinedmods.refinedstorage.inventory.item.FilterItemHandler;
|
||||
import com.refinedmods.refinedstorage.item.WirelessGridItem;
|
||||
@@ -277,7 +278,7 @@ public class WirelessGrid implements INetworkAwareGrid {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCrafted(PlayerEntity player) {
|
||||
public void onCrafted(PlayerEntity player, @Nullable IStackList<ItemStack> availableItems, @Nullable IStackList<ItemStack> usedItems) {
|
||||
// NO OP
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerCont
|
||||
import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider;
|
||||
import com.refinedmods.refinedstorage.api.storage.disk.StorageDiskSyncData;
|
||||
import com.refinedmods.refinedstorage.api.util.IFilter;
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
import com.refinedmods.refinedstorage.apiimpl.API;
|
||||
import com.refinedmods.refinedstorage.apiimpl.network.grid.handler.PortableFluidGridHandler;
|
||||
import com.refinedmods.refinedstorage.apiimpl.network.grid.handler.PortableItemGridHandler;
|
||||
@@ -397,7 +398,7 @@ public class PortableGrid implements IGrid, IPortableGrid, IStorageDiskContainer
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCrafted(PlayerEntity player) {
|
||||
public void onCrafted(PlayerEntity player, @Nullable IStackList<ItemStack> availableItems, @Nullable IStackList<ItemStack> usedItems) {
|
||||
// NO OP
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerCont
|
||||
import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider;
|
||||
import com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker;
|
||||
import com.refinedmods.refinedstorage.api.util.IFilter;
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
import com.refinedmods.refinedstorage.apiimpl.API;
|
||||
import com.refinedmods.refinedstorage.apiimpl.network.grid.handler.PortableFluidGridHandler;
|
||||
import com.refinedmods.refinedstorage.apiimpl.network.grid.handler.PortableItemGridHandler;
|
||||
@@ -490,7 +491,7 @@ public class PortableGridTile extends BaseTile implements IGrid, IPortableGrid,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCrafted(PlayerEntity player) {
|
||||
public void onCrafted(PlayerEntity player, @Nullable IStackList<ItemStack> availableItems, @Nullable IStackList<ItemStack> usedItems) {
|
||||
// NO OP
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user