Batch network extraction on shift crafting fixes #2104 (#2560)

* Batch network extraction on shift crafting potential fix for #2104

* resolve requested changes

* resolve more requested changes
This commit is contained in:
Darkere
2020-06-27 20:18:11 +02:00
committed by GitHub
parent 72de77f21c
commit 1591ad2239
9 changed files with 80 additions and 25 deletions

View File

@@ -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.
*/
@@ -14,8 +17,10 @@ public interface ICraftingGridBehavior {
* @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).

View File

@@ -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;
@@ -202,8 +203,10 @@ public interface IGrid {
* Called when an item is crafted in a crafting grid.
*
* @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.

View File

@@ -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);
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();

View File

@@ -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

View File

@@ -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;

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}