aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorJakub <53441451+kuba6000@users.noreply.github.com>2022-03-30 17:20:44 +0200
committerGitHub <noreply@github.com>2022-03-30 17:20:44 +0200
commitbec757c9d1f329fb30ed262b3eea9e9b69289181 (patch)
tree55443f8868271918a3d6c9295be6b3b11d361e48 /src/main
parent47c6da0439d57b67f262acec717224bb31aaf649 (diff)
downloadGT5-Unofficial-bec757c9d1f329fb30ed262b3eea9e9b69289181.tar.gz
GT5-Unofficial-bec757c9d1f329fb30ed262b3eea9e9b69289181.tar.bz2
GT5-Unofficial-bec757c9d1f329fb30ed262b3eea9e9b69289181.zip
Optimize item transfer and inventory sorting (#992)
* Optimize conveyors, input busses, chest buffers * More checks * More checks and fixes * Check for slot validity when sorting * Fix NPE * More optimization * Fix disable sort not working * Enable order in input bus, Some fixes
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Buffer.java44
-rw-r--r--src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_InputBus.java50
-rw-r--r--src/main/java/gregtech/api/util/GT_Single_Recipe_Check.java64
-rw-r--r--src/main/java/gregtech/api/util/GT_Single_Recipe_Check_Processing_Array.java22
-rw-r--r--src/main/java/gregtech/api/util/GT_Utility.java212
-rw-r--r--src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ChestBuffer.java19
-rw-r--r--src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_SuperBuffer.java44
7 files changed, 313 insertions, 142 deletions
diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Buffer.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Buffer.java
index 93e976c052..32067744d5 100644
--- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Buffer.java
+++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Buffer.java
@@ -9,6 +9,8 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.util.ForgeDirection;
+import java.util.*;
+
import static gregtech.api.enums.GT_Values.V;
import static gregtech.api.enums.Textures.BlockIcons.*;
@@ -250,7 +252,7 @@ public abstract class GT_MetaTileEntity_Buffer extends GT_MetaTileEntity_TieredM
@Override
public void onScrewdriverRightClick(byte aSide, EntityPlayer aPlayer, float aX, float aY, float aZ) {
if (aSide == getBaseMetaTileEntity().getBackFacing()) {
-
+
mTargetStackSize = (byte) ((mTargetStackSize + (aPlayer.isSneaking()? -1 : 1)) % 65);
if(mTargetStackSize <0){mTargetStackSize = mMaxStackSize;}
if (mTargetStackSize == 0) {
@@ -332,7 +334,7 @@ public abstract class GT_MetaTileEntity_Buffer extends GT_MetaTileEntity_TieredM
public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, byte aSide, ItemStack aStack) {
return aSide != aBaseMetaTileEntity.getBackFacing();
}
-
+
@Override
public boolean allowGeneralRedstoneOutput(){
return true;
@@ -346,19 +348,35 @@ public abstract class GT_MetaTileEntity_Buffer extends GT_MetaTileEntity_TieredM
}
protected void fillStacksIntoFirstSlots() {
+ HashMap<GT_Utility.ItemId, Integer> slots = new HashMap<>(mInventory.length);
+ HashMap<GT_Utility.ItemId, ItemStack> stacks = new HashMap<>(mInventory.length);
+ List<GT_Utility.ItemId> order = new ArrayList<>(mInventory.length);
+ List<Integer> validSlots = new ArrayList<>(mInventory.length);
for (int i = 0; i < mInventory.length - 1; i++) {
- if (!isValidSlot(i)) {
+ if (!isValidSlot(i))
continue;
- }
-
- for (int j = i + 1; j < mInventory.length; j++) {
- if (!isValidSlot(j)) {
- continue;
- }
-
- if (mInventory[j] != null && (mInventory[i] == null || GT_Utility.areStacksEqual(mInventory[i], mInventory[j])))
- GT_Utility.moveStackFromSlotAToSlotB(getBaseMetaTileEntity(), getBaseMetaTileEntity(), j, i, (byte) 64, (byte) 1, (byte) 64, (byte) 1);
- }
+ validSlots.add(i);
+ ItemStack s = mInventory[i];
+ if(s == null)
+ continue;
+ GT_Utility.ItemId sID = GT_Utility.ItemId.createNoCopy(s);
+ slots.merge(sID, s.stackSize, Integer::sum);
+ if(!stacks.containsKey(sID))
+ stacks.put(sID, s);
+ order.add(sID);
+ mInventory[i] = null;
+ }
+ int slotindex = 0;
+ for (GT_Utility.ItemId sID : order) {
+ int toSet = slots.get(sID);
+ if (toSet == 0)
+ continue;
+ int slot = validSlots.get(slotindex);
+ slotindex++;
+ mInventory[slot] = stacks.get(sID).copy();
+ toSet = Math.min(toSet, mInventory[slot].getMaxStackSize());
+ mInventory[slot].stackSize = toSet;
+ slots.merge(sID, toSet, (a, b) -> a - b);
}
}
diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_InputBus.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_InputBus.java
index 3b8ed18e94..c36d904f21 100644
--- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_InputBus.java
+++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_InputBus.java
@@ -7,7 +7,6 @@ import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.metatileentity.MetaTileEntity;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_ClientPreference;
-import gregtech.api.util.GT_LanguageManager;
import gregtech.api.util.GT_OreDictUnificator;
import gregtech.api.util.GT_Recipe.GT_Recipe_Map;
import gregtech.api.util.GT_Utility;
@@ -18,6 +17,11 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.StatCollector;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
import static gregtech.api.enums.Textures.BlockIcons.*;
public class GT_MetaTileEntity_Hatch_InputBus extends GT_MetaTileEntity_Hatch {
@@ -139,27 +143,47 @@ public class GT_MetaTileEntity_Hatch_InputBus extends GT_MetaTileEntity_Hatch {
@Override
public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
if (aBaseMetaTileEntity.isServerSide() && aBaseMetaTileEntity.hasInventoryBeenModified()) {
- fillStacksIntoFirstSlots();
+ updateSlots();
}
}
public void updateSlots() {
for (int i = 0; i < mInventory.length; i++)
if (mInventory[i] != null && mInventory[i].stackSize <= 0) mInventory[i] = null;
- fillStacksIntoFirstSlots();
+ if(!disableSort)
+ fillStacksIntoFirstSlots();
}
protected void fillStacksIntoFirstSlots() {
- if (disableSort) {
- for (int i = 0; i < mInventory.length; i++)
- for (int j = i + 1; j < mInventory.length; j++)
- if (mInventory[j] != null && mInventory[j].stackSize <= 0 && (mInventory[i] == null || GT_Utility.areStacksEqual(mInventory[i], mInventory[j])))
- GT_Utility.moveStackFromSlotAToSlotB(getBaseMetaTileEntity(), getBaseMetaTileEntity(), j, i, (byte) 64, (byte) 1, (byte) 64, (byte) 1);
- } else {
- for (int i = 0; i < mInventory.length; i++)
- for (int j = i + 1; j < mInventory.length; j++)
- if (mInventory[j] != null && (mInventory[i] == null || GT_Utility.areStacksEqual(mInventory[i], mInventory[j])))
- GT_Utility.moveStackFromSlotAToSlotB(getBaseMetaTileEntity(), getBaseMetaTileEntity(), j, i, (byte) 64, (byte) 1, (byte) 64, (byte) 1);
+ HashMap<GT_Utility.ItemId, Integer> slots = new HashMap<>(mInventory.length);
+ HashMap<GT_Utility.ItemId, ItemStack> stacks = new HashMap<>(mInventory.length);
+ List<GT_Utility.ItemId> order = new ArrayList<>(mInventory.length);
+ List<Integer> validSlots = new ArrayList<>(mInventory.length);
+ for (int i = 0; i < mInventory.length - 1; i++) {
+ if (!isValidSlot(i))
+ continue;
+ validSlots.add(i);
+ ItemStack s = mInventory[i];
+ if(s == null)
+ continue;
+ GT_Utility.ItemId sID = GT_Utility.ItemId.createNoCopy(s);
+ slots.merge(sID, s.stackSize, Integer::sum);
+ if(!stacks.containsKey(sID))
+ stacks.put(sID, s);
+ order.add(sID);
+ mInventory[i] = null;
+ }
+ int slotindex = 0;
+ for (GT_Utility.ItemId sID : order) {
+ int toSet = slots.get(sID);
+ if (toSet == 0)
+ continue;
+ int slot = validSlots.get(slotindex);
+ slotindex++;
+ mInventory[slot] = stacks.get(sID).copy();
+ toSet = Math.min(toSet, mInventory[slot].getMaxStackSize());
+ mInventory[slot].stackSize = toSet;
+ slots.merge(sID, toSet, (a, b) -> a - b);
}
}
diff --git a/src/main/java/gregtech/api/util/GT_Single_Recipe_Check.java b/src/main/java/gregtech/api/util/GT_Single_Recipe_Check.java
index 469f2d64a1..0be96a2e05 100644
--- a/src/main/java/gregtech/api/util/GT_Single_Recipe_Check.java
+++ b/src/main/java/gregtech/api/util/GT_Single_Recipe_Check.java
@@ -1,16 +1,12 @@
package gregtech.api.util;
-import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
-import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
-import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -19,7 +15,7 @@ import java.util.Map;
public class GT_Single_Recipe_Check {
protected final GT_MetaTileEntity_MultiBlockBase multiBlockBase;
protected final GT_Recipe recipe;
- protected final ImmutableMap<ItemId, Integer> itemCost;
+ protected final ImmutableMap<GT_Utility.ItemId, Integer> itemCost;
protected final ImmutableMap<Fluid, Integer> fluidCost;
protected final int totalItemCost;
@@ -28,7 +24,7 @@ public class GT_Single_Recipe_Check {
protected GT_Single_Recipe_Check(
GT_MetaTileEntity_MultiBlockBase multiBlockBase,
GT_Recipe recipe,
- ImmutableMap<ItemId, Integer> itemCost,
+ ImmutableMap<GT_Utility.ItemId, Integer> itemCost,
ImmutableMap<Fluid, Integer> fluidCost) {
this.multiBlockBase = multiBlockBase;
this.recipe = recipe;
@@ -50,16 +46,16 @@ public class GT_Single_Recipe_Check {
* restriction, so any multi-block that calls those can use this method.
*/
public boolean checkRecipeInputsSingleStack(boolean consumeInputs) {
- Map<ItemId, ItemStack> itemMap = null;
+ Map<GT_Utility.ItemId, ItemStack> itemMap = null;
if (totalItemCost > 0) {
itemMap = new HashMap<>();
for (ItemStack itemStack : multiBlockBase.getStoredInputs()) {
itemMap.merge(
- ItemId.createNoCopy(itemStack), itemStack,
+ GT_Utility.ItemId.createNoCopy(itemStack), itemStack,
(a, b) -> a.stackSize >= b.stackSize ? a : b);
}
- for (Map.Entry<ItemId, Integer> entry : itemCost.entrySet()) {
+ for (Map.Entry<GT_Utility.ItemId, Integer> entry : itemCost.entrySet()) {
ItemStack itemStack = itemMap.get(entry.getKey());
if (itemStack == null || itemStack.stackSize < entry.getValue()) {
return false;
@@ -86,7 +82,7 @@ public class GT_Single_Recipe_Check {
if (consumeInputs) {
if (totalItemCost > 0) {
- for (Map.Entry<ItemId, Integer> entry : itemCost.entrySet()) {
+ for (Map.Entry<GT_Utility.ItemId, Integer> entry : itemCost.entrySet()) {
itemMap.get(entry.getKey()).stackSize -= entry.getValue();
}
}
@@ -110,12 +106,12 @@ public class GT_Single_Recipe_Check {
if (totalItemCost > 0) {
items = multiBlockBase.getStoredInputs();
- Map<ItemId, Integer> itemMap = new HashMap<>();
+ Map<GT_Utility.ItemId, Integer> itemMap = new HashMap<>();
for (ItemStack itemStack : items) {
- itemMap.merge(ItemId.createNoCopy(itemStack), itemStack.stackSize, Integer::sum);
+ itemMap.merge(GT_Utility.ItemId.createNoCopy(itemStack), itemStack.stackSize, Integer::sum);
}
- for (Map.Entry<ItemId, Integer> entry : itemCost.entrySet()) {
+ for (Map.Entry<GT_Utility.ItemId, Integer> entry : itemCost.entrySet()) {
if (itemMap.getOrDefault(entry.getKey(), 0) < entry.getValue()) {
return false;
}
@@ -141,9 +137,9 @@ public class GT_Single_Recipe_Check {
if (consumeInputs) {
if (totalItemCost > 0) {
int remainingItemCost = totalItemCost;
- Map<ItemId, Integer> runningItemCost = Maps.newHashMap(itemCost);
+ Map<GT_Utility.ItemId, Integer> runningItemCost = Maps.newHashMap(itemCost);
for (ItemStack itemStack : items) {
- ItemId key = ItemId.createNoCopy(itemStack);
+ GT_Utility.ItemId key = GT_Utility.ItemId.createNoCopy(itemStack);
int runningCost = runningItemCost.getOrDefault(key, 0);
int paid = Math.min(itemStack.stackSize, runningCost);
itemStack.stackSize -= paid;
@@ -177,11 +173,11 @@ public class GT_Single_Recipe_Check {
return true;
}
- protected static Map<ItemId, Integer> buildItemMap(
+ protected static Map<GT_Utility.ItemId, Integer> buildItemMap(
GT_MetaTileEntity_MultiBlockBase multiBlockBase) {
- Map<ItemId, Integer> itemMap = new HashMap<>();
+ Map<GT_Utility.ItemId, Integer> itemMap = new HashMap<>();
for (ItemStack itemStack : multiBlockBase.getStoredInputs()) {
- itemMap.merge(ItemId.create(itemStack), itemStack.stackSize, Integer::sum);
+ itemMap.merge(GT_Utility.ItemId.create(itemStack), itemStack.stackSize, Integer::sum);
}
return itemMap;
}
@@ -204,9 +200,9 @@ public class GT_Single_Recipe_Check {
// In order to compute which items and fluids are consumed by the recipe, we compare the
// multi-block's items and fluids before and after inputs are consumed by the recipe.
- private Map<ItemId, Integer> beforeItems;
+ private Map<GT_Utility.ItemId, Integer> beforeItems;
private Map<Fluid, Integer> beforeFluids;
- private Map<ItemId, Integer> afterItems;
+ private Map<GT_Utility.ItemId, Integer> afterItems;
private Map<Fluid, Integer> afterFluids;
private GT_Recipe recipe;
@@ -235,8 +231,8 @@ public class GT_Single_Recipe_Check {
}
public GT_Single_Recipe_Check build() {
- ImmutableMap.Builder<ItemId, Integer> itemCostBuilder = ImmutableMap.builder();
- for (Map.Entry<ItemId, Integer> entry : beforeItems.entrySet()) {
+ ImmutableMap.Builder<GT_Utility.ItemId, Integer> itemCostBuilder = ImmutableMap.builder();
+ for (Map.Entry<GT_Utility.ItemId, Integer> entry : beforeItems.entrySet()) {
int cost = entry.getValue() - afterItems.getOrDefault(entry.getKey(), 0);
if (cost > 0) {
itemCostBuilder.put(entry.getKey(), cost);
@@ -256,29 +252,5 @@ public class GT_Single_Recipe_Check {
}
}
- @AutoValue
- protected abstract static class ItemId {
- /** This method copies NBT, as it is mutable. */
- protected static ItemId create(ItemStack itemStack) {
- NBTTagCompound nbt = itemStack.getTagCompound();
- if (nbt != null) {
- nbt = (NBTTagCompound) nbt.copy();
- }
-
- return new AutoValue_GT_Single_Recipe_Check_ItemId(
- itemStack.getItem(), itemStack.getItemDamage(), nbt);
- }
- /** This method does not copy NBT in order to save time. Make sure not to mutate it! */
- protected static ItemId createNoCopy(ItemStack itemStack) {
- return new AutoValue_GT_Single_Recipe_Check_ItemId(
- itemStack.getItem(), itemStack.getItemDamage(), itemStack.getTagCompound());
- }
-
- protected abstract Item item();
- protected abstract int metaData();
-
- @Nullable
- protected abstract NBTTagCompound nbt();
- }
}
diff --git a/src/main/java/gregtech/api/util/GT_Single_Recipe_Check_Processing_Array.java b/src/main/java/gregtech/api/util/GT_Single_Recipe_Check_Processing_Array.java
index 225e0bd723..871cb642c4 100644
--- a/src/main/java/gregtech/api/util/GT_Single_Recipe_Check_Processing_Array.java
+++ b/src/main/java/gregtech/api/util/GT_Single_Recipe_Check_Processing_Array.java
@@ -24,7 +24,7 @@ public class GT_Single_Recipe_Check_Processing_Array extends GT_Single_Recipe_Ch
protected GT_Single_Recipe_Check_Processing_Array(
GT_MetaTileEntity_MultiBlockBase multiBlockBase,
GT_Recipe recipe,
- ImmutableMap<ItemId, Integer> itemCost,
+ ImmutableMap<GT_Utility.ItemId, Integer> itemCost,
ImmutableMap<Fluid, Integer> fluidCost,
int recipeAmperage,
ItemStack machineStack) {
@@ -60,12 +60,12 @@ public class GT_Single_Recipe_Check_Processing_Array extends GT_Single_Recipe_Ch
if (totalItemCost > 0) {
items = multiBlockBase.getStoredInputs();
- Map<ItemId, Integer> itemMap = new HashMap<>();
+ Map<GT_Utility.ItemId, Integer> itemMap = new HashMap<>();
for (ItemStack itemStack : items) {
- itemMap.merge(ItemId.createNoCopy(itemStack), itemStack.stackSize, Integer::sum);
+ itemMap.merge(GT_Utility.ItemId.createNoCopy(itemStack), itemStack.stackSize, Integer::sum);
}
- for (Map.Entry<ItemId, Integer> entry : itemCost.entrySet()) {
+ for (Map.Entry<GT_Utility.ItemId, Integer> entry : itemCost.entrySet()) {
parallel = Math.min(parallel, itemMap.getOrDefault(entry.getKey(), 0) / entry.getValue());
if (parallel <= 0) {
return 0;
@@ -94,7 +94,7 @@ public class GT_Single_Recipe_Check_Processing_Array extends GT_Single_Recipe_Ch
if (consumeInputs) {
if (totalItemCost > 0) {
int remainingItemCost = totalItemCost * finalParallel;
- Map<ItemId, Integer> runningItemCost =
+ Map<GT_Utility.ItemId, Integer> runningItemCost =
itemCost.entrySet().stream()
.collect(
Collectors.toMap(
@@ -102,7 +102,7 @@ public class GT_Single_Recipe_Check_Processing_Array extends GT_Single_Recipe_Ch
entry -> entry.getValue() * finalParallel));
for (ItemStack itemStack : items) {
- ItemId key = ItemId.createNoCopy(itemStack);
+ GT_Utility.ItemId key = GT_Utility.ItemId.createNoCopy(itemStack);
int runningCost = runningItemCost.getOrDefault(key, 0);
int paid = Math.min(itemStack.stackSize, runningCost);
itemStack.stackSize -= paid;
@@ -151,9 +151,9 @@ public class GT_Single_Recipe_Check_Processing_Array extends GT_Single_Recipe_Ch
// In order to compute which items and fluids are consumed by the recipe, we compare the
// multi-block's items and fluids before and after inputs are consumed by the recipe.
- private Map<ItemId, Integer> beforeItems;
+ private Map<GT_Utility.ItemId, Integer> beforeItems;
private Map<Fluid, Integer> beforeFluids;
- private Map<ItemId, Integer> afterItems;
+ private Map<GT_Utility.ItemId, Integer> afterItems;
private Map<Fluid, Integer> afterFluids;
private GT_Recipe recipe;
@@ -188,8 +188,8 @@ public class GT_Single_Recipe_Check_Processing_Array extends GT_Single_Recipe_Ch
}
public GT_Single_Recipe_Check_Processing_Array build() {
- ImmutableMap.Builder<ItemId, Integer> itemCostBuilder = ImmutableMap.builder();
- for (Map.Entry<ItemId, Integer> entry : beforeItems.entrySet()) {
+ ImmutableMap.Builder<GT_Utility.ItemId, Integer> itemCostBuilder = ImmutableMap.builder();
+ for (Map.Entry<GT_Utility.ItemId, Integer> entry : beforeItems.entrySet()) {
int cost = entry.getValue() - afterItems.getOrDefault(entry.getKey(), 0);
if (cost > 0) {
itemCostBuilder.put(entry.getKey(), cost);
@@ -209,4 +209,4 @@ public class GT_Single_Recipe_Check_Processing_Array extends GT_Single_Recipe_Ch
recipeAmperage, multiBlockBase.mInventory[1].copy());
}
}
-} \ No newline at end of file
+}
diff --git a/src/main/java/gregtech/api/util/GT_Utility.java b/src/main/java/gregtech/api/util/GT_Utility.java
index c3f28d8c46..bda134bf3d 100644
--- a/src/main/java/gregtech/api/util/GT_Utility.java
+++ b/src/main/java/gregtech/api/util/GT_Utility.java
@@ -1,9 +1,9 @@
package gregtech.api.util;
import cofh.api.transport.IItemDuct;
+import com.google.auto.value.AutoValue;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
import com.gtnewhorizon.structurelib.alignment.IAlignment;
import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider;
@@ -621,59 +621,165 @@ public class GT_Utility {
if (aTileEntity1 == null || aMaxTargetStackSize <= 0 || aMinTargetStackSize <= 0 || aMaxMoveAtOnce <= 0 || aMinTargetStackSize > aMaxTargetStackSize || aMinMoveAtOnce > aMaxMoveAtOnce || aMaxStackTransfer == 0)
return 0;
- int[] tGrabSlots = null;
- if (aTileEntity1 instanceof ISidedInventory)
- tGrabSlots = ((ISidedInventory) aTileEntity1).getAccessibleSlotsFromSide(aGrabFrom);
- if (tGrabSlots == null) {
- tGrabSlots = new int[aTileEntity1.getSizeInventory()];
- for (int i = 0; i < tGrabSlots.length; i++) tGrabSlots[i] = i;
- }
+ int[] tGrabSlots = new int[aTileEntity1.getSizeInventory()];
+ int tGrabSlotsSize = 0;
+ if (aTileEntity1 instanceof ISidedInventory) {
+ for(int i : ((ISidedInventory) aTileEntity1).getAccessibleSlotsFromSide(aGrabFrom)) {
+ ItemStack s = aTileEntity1.getStackInSlot(i);
+ if (s == null || !isAllowedToTakeFromSlot(aTileEntity1, i, aGrabFrom, s) || s.stackSize < aMinMoveAtOnce || !listContainsItem(aFilter, s, true, aInvertFilter))
+ continue;
+ tGrabSlots[tGrabSlotsSize++] = i;
+ }
+ }
+ else {
+ for (int i = 0; i < tGrabSlots.length; i++)
+ {
+ ItemStack s = aTileEntity1.getStackInSlot(i);
+ if (s == null || s.stackSize < aMinMoveAtOnce || !listContainsItem(aFilter, s, true, aInvertFilter))
+ continue;
+ tGrabSlots[tGrabSlotsSize++] = i;
+ }
+ }
+
+ if(tGrabSlotsSize == 0)
+ return 0;
int tGrabInventorySize = tGrabSlots.length;
if (aTileEntity2 instanceof IInventory)
{
- int[] tPutSlots = null;
- if (aTileEntity2 instanceof ISidedInventory)
- tPutSlots = ((ISidedInventory) aTileEntity2).getAccessibleSlotsFromSide(aPutTo);
+ IInventory tPutInventory = (IInventory) aTileEntity2;
- if (tPutSlots == null) {
- tPutSlots = new int[((IInventory) aTileEntity2).getSizeInventory()];
- for (int i = 0; i < tPutSlots.length; i++) tPutSlots[i] = i;
+ HashMap<ItemId, Integer> tPutItems = new HashMap<>(tPutInventory.getSizeInventory());
+ HashMap<ItemId, List<ItemStack>> tPutItemStacks = new HashMap<>(tPutInventory.getSizeInventory());
+ List<Integer> tPutFreeSlots = new ArrayList<>(tPutInventory.getSizeInventory());
+
+ int[] accessibleSlots = null;
+ if (aTileEntity2 instanceof ISidedInventory)
+ accessibleSlots = ((ISidedInventory) tPutInventory).getAccessibleSlotsFromSide(aPutTo);
+ for (int i = 0; i < tPutInventory.getSizeInventory(); i++)
+ {
+ int slot = i;
+ if(accessibleSlots != null)
+ {
+ if(accessibleSlots.length <= i)
+ break;
+ slot = accessibleSlots[slot];
+ }
+ ItemStack s = tPutInventory.getStackInSlot(slot);
+ if(s == null)
+ tPutFreeSlots.add(slot);
+ else if((s.stackSize < s.getMaxStackSize() && s.stackSize < tPutInventory.getInventoryStackLimit()) && aMinMoveAtOnce <= s.getMaxStackSize() - s.stackSize) {
+ ItemId sID = ItemId.createNoCopy(s);
+ tPutItems.merge(sID, (Math.min(s.getMaxStackSize(), tPutInventory.getInventoryStackLimit()) - s.stackSize), Integer::sum);
+ List<ItemStack> l = tPutItemStacks.get(sID);
+ if(l == null){
+ l = new ArrayList<>(tPutInventory.getSizeInventory());
+ tPutItemStacks.put(sID, l);
+ }
+ l.add(s);
+ }
}
- IInventory tPutInventory = (IInventory) aTileEntity2;
- int tPutInventorySize = tPutSlots.length;
- int tFirstsValidSlot = 0,tStacksMoved = 0,tTotalItemsMoved = 0;
+ if(tPutItems.isEmpty() && tPutFreeSlots.isEmpty())
+ return 0;
+
+ int tStacksMoved = 0,tTotalItemsMoved = 0;
for (int grabSlot : tGrabSlots) {
- //ItemStack tInventoryStack : mInventory
int tMovedItems;
+ int tStackSize;
do {
- int tGrabSlot = grabSlot;
tMovedItems = 0;
- ItemStack tGrabStack = aTileEntity1.getStackInSlot(tGrabSlot);
- if (listContainsItem(aFilter, tGrabStack, true, aInvertFilter) &&
- (tGrabStack.stackSize >= aMinMoveAtOnce && isAllowedToTakeFromSlot(aTileEntity1, tGrabSlot, aGrabFrom, tGrabStack))) {
- int tStackSize = tGrabStack.stackSize;
+ ItemStack tGrabStack = aTileEntity1.getStackInSlot(grabSlot);
+ if(tGrabStack == null)
+ break;
+ tStackSize = tGrabStack.stackSize;
+ ItemId sID = ItemId.createNoCopy(tGrabStack);
+
+ if(tPutItems.containsKey(sID))
+ {
+ int canPut = Math.min(tPutItems.get(sID), aMaxMoveAtOnce);
+ if(canPut >= aMinMoveAtOnce) {
+ List<ItemStack> putStack = tPutItemStacks.get(sID);
+ if(!putStack.isEmpty()) {
+ int toPut = Math.min(canPut, tStackSize);
+ tMovedItems = toPut;
+ for (int i = 0; i < putStack.size(); i++) {
+ ItemStack s = putStack.get(i);
+ int sToPut = Math.min(Math.min(Math.min(toPut, s.getMaxStackSize() - s.stackSize), tPutInventory.getInventoryStackLimit() - s.stackSize), aMaxTargetStackSize - s.stackSize);
+ if (sToPut <= 0)
+ continue;
+ if (sToPut < aMinMoveAtOnce)
+ continue;
+ if (s.stackSize + sToPut < aMinTargetStackSize)
+ continue;
+ toPut -= sToPut;
+ s.stackSize += sToPut;
+ if (s.stackSize == s.getMaxStackSize() || s.stackSize == tPutInventory.getInventoryStackLimit()) {
+ putStack.remove(i);
+ i--;
+ }
+ if (toPut == 0)
+ break;
+ }
+ tMovedItems -= toPut;
+ if (tMovedItems > 0) {
+ tStackSize -= tMovedItems;
+ tTotalItemsMoved += tMovedItems;
+ tPutItems.merge(sID, tMovedItems, (a, b) -> a - b);
+ if (tPutItems.get(sID) == 0)
+ tPutItems.remove(sID);
+
+ if (tStackSize == 0)
+ aTileEntity1.setInventorySlotContents(grabSlot, null);
+ else
+ tGrabStack.stackSize = tStackSize;
- for (int tPutSlotIndex = tFirstsValidSlot; tPutSlotIndex < tPutInventorySize; tPutSlotIndex++) {
- int tPutSlot = tPutSlots[tPutSlotIndex];
- if (isAllowedToPutIntoSlot(tPutInventory, tPutSlot, aPutTo, tGrabStack, (byte) 64)) {
- int tMoved = moveStackFromSlotAToSlotB(aTileEntity1, tPutInventory, tGrabSlot, tPutSlot, aMaxTargetStackSize, aMinTargetStackSize, (byte) (aMaxMoveAtOnce - tMovedItems), aMinMoveAtOnce);
- tTotalItemsMoved += tMoved;
- tMovedItems += tMoved;
- if (tMovedItems == tStackSize)
- break;
+ aTileEntity1.markDirty();
+ tPutInventory.markDirty();
+ }
}
}
- if (tMovedItems > 0) {
- if (++tStacksMoved >= aMaxStackTransfer)
- return tTotalItemsMoved;
+ }
+ if(tStackSize > 0 && !tPutFreeSlots.isEmpty())
+ {
+ for(int i = 0; i < tPutFreeSlots.size(); i++)
+ {
+ int tPutSlot = tPutFreeSlots.get(i);
+ if (isAllowedToPutIntoSlot(tPutInventory, tPutSlot, aPutTo, tGrabStack, (byte) 64)) {
+ int tMoved = moveStackFromSlotAToSlotB(aTileEntity1, tPutInventory, grabSlot, tPutSlot, aMaxTargetStackSize, aMinTargetStackSize, (byte) (aMaxMoveAtOnce - tMovedItems), aMinMoveAtOnce);
+ if(tMoved > 0)
+ {
+ tPutFreeSlots.remove(i);
+ i--;
+ ItemStack s = tPutInventory.getStackInSlot(tPutSlot);
+ if(s.stackSize < s.getMaxStackSize() && s.stackSize < tPutInventory.getInventoryStackLimit()) {
+ ItemId ssID = ItemId.createNoCopy(s);
+ tPutItems.merge(ssID, (Math.min(s.getMaxStackSize(), tPutInventory.getInventoryStackLimit()) - s.stackSize), Integer::sum);
+ List<ItemStack> l = tPutItemStacks.get(ssID);
+ if(l == null){
+ l = new ArrayList<>(tPutInventory.getSizeInventory());
+ tPutItemStacks.put(ssID, l);
+ }
+ l.add(s);
+ }
+ tTotalItemsMoved += tMoved;
+ tMovedItems += tMoved;
+ tStackSize -= tMoved;
+ if (tStackSize == 0)
+ break;
+ }
+ }
}
}
- } while (tMovedItems > 0); //suport inventorys thgat store motre then a stack in a aslot
+
+ if (tMovedItems > 0) {
+ if (++tStacksMoved >= aMaxStackTransfer)
+ return tTotalItemsMoved;
+ }
+ } while (tMovedItems > 0 && tStackSize > 0); //suport inventorys thgat store motre then a stack in a aslot
}
if (aDoCheckChests && aTileEntity1 instanceof TileEntityChest) {
TileEntityChest tTileEntity1 = (TileEntityChest) aTileEntity1;
@@ -743,7 +849,7 @@ public class GT_Utility {
private static byte moveOneItemStack(IInventory aTileEntity1, Object aTileEntity2, byte aGrabFrom, byte aPutTo, List<ItemStack> aFilter, boolean aInvertFilter, byte aMaxTargetStackSize, byte aMinTargetStackSize, byte aMaxMoveAtOnce, byte aMinMoveAtOnce, boolean aDoCheckChests) {
if (aTileEntity1 == null || aMaxTargetStackSize <= 0 || aMinTargetStackSize <= 0 || aMaxMoveAtOnce <= 0 || aMinTargetStackSize > aMaxTargetStackSize || aMinMoveAtOnce > aMaxMoveAtOnce)
return 0;
-
+
int[] tGrabSlots = null;
if (aTileEntity1 instanceof ISidedInventory)
tGrabSlots = ((ISidedInventory) aTileEntity1).getAccessibleSlotsFromSide(aGrabFrom);
@@ -963,8 +1069,8 @@ public class GT_Utility {
}
public static boolean areStacksEqual(ItemStack aStack1, ItemStack aStack2, boolean aIgnoreNBT) {
- return aStack1 != null && aStack2 != null && aStack1.getItem() == aStack2.getItem()
- && (aIgnoreNBT || (((aStack1.getTagCompound() == null) == (aStack2.getTagCompound() == null)) && (aStack1.getTagCompound() == null || aStack1.getTagCompound().equals(aStack2.getTagCompound()))))
+ return aStack1 != null && aStack2 != null && aStack1.getItem() == aStack2.getItem()
+ && (aIgnoreNBT || (((aStack1.getTagCompound() == null) == (aStack2.getTagCompound() == null)) && (aStack1.getTagCompound() == null || aStack1.getTagCompound().equals(aStack2.getTagCompound()))))
&& (Items.feather.getDamage(aStack1) == Items.feather.getDamage(aStack2) || Items.feather.getDamage(aStack1) == W || Items.feather.getDamage(aStack2) == W);
}
@@ -1231,7 +1337,7 @@ public class GT_Utility {
if (tList == null) return false;
if (aInput != null && !tEntry.getKey().matches(aInput)) return false;
-
+
return tList.stream().anyMatch(tOutput -> (aOutput == null || areStacksEqual(GT_OreDictUnificator.get(tOutput), aOutput)));
}));
}
@@ -2378,7 +2484,7 @@ public class GT_Utility {
}
return -1;
}
-
+
private static DecimalFormat getDecimalFormat(){
return decimalFormatters.computeIfAbsent(Locale.getDefault(Locale.Category.FORMAT), locale -> {
DecimalFormat numberFormat =new DecimalFormat();//uses the necessary locale inside anyway
@@ -3089,4 +3195,30 @@ public class GT_Utility {
if (aUseNBT) base = base * 31 + Objects.hashCode(aStack.tag);
return base;
}
+
+ @AutoValue
+ public abstract static class ItemId {
+ /** This method copies NBT, as it is mutable. */
+ public static ItemId create(ItemStack itemStack) {
+ NBTTagCompound nbt = itemStack.getTagCompound();
+ if (nbt != null) {
+ nbt = (NBTTagCompound) nbt.copy();
+ }
+
+ return new AutoValue_GT_Utility_ItemId(
+ itemStack.getItem(), itemStack.getItemDamage(), nbt);
+ }
+
+ /** This method does not copy NBT in order to save time. Make sure not to mutate it! */
+ public static ItemId createNoCopy(ItemStack itemStack) {
+ return new AutoValue_GT_Utility_ItemId(
+ itemStack.getItem(), itemStack.getItemDamage(), itemStack.getTagCompound());
+ }
+
+ protected abstract Item item();
+ protected abstract int metaData();
+
+ @Nullable
+ protected abstract NBTTagCompound nbt();
+ }
}
diff --git a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ChestBuffer.java b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ChestBuffer.java
index b499e2c55e..6fab5d92d6 100644
--- a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ChestBuffer.java
+++ b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ChestBuffer.java
@@ -8,12 +8,6 @@ import gregtech.api.render.TextureFactory;
import gregtech.common.gui.GT_Container_ChestBuffer;
import gregtech.common.gui.GT_GUIContainer_ChestBuffer;
import net.minecraft.entity.player.InventoryPlayer;
-import net.minecraft.item.Item;
-import net.minecraft.item.ItemBlock;
-import net.minecraft.item.ItemStack;
-
-import java.util.Arrays;
-import java.util.Comparator;
import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_CHESTBUFFER;
import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_CHESTBUFFER_GLOW;
@@ -43,7 +37,7 @@ public class GT_MetaTileEntity_ChestBuffer extends GT_MetaTileEntity_Buffer {
public GT_MetaTileEntity_ChestBuffer(String aName, int aTier, int aInvSlotCount, String aDescription, ITexture[][][] aTextures) {
super(aName, aTier, aInvSlotCount, aDescription, aTextures);
}
-
+
public GT_MetaTileEntity_ChestBuffer(String aName, int aTier, int aInvSlotCount, String[] aDescription, ITexture[][][] aTextures) {
super(aName, aTier, aInvSlotCount, aDescription, aTextures);
}
@@ -69,9 +63,6 @@ public class GT_MetaTileEntity_ChestBuffer extends GT_MetaTileEntity_Buffer {
protected void moveItems(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
if (aTimer % tickRate[mTier] > 0) return;
- if(this.bSortStacks && aBaseMetaTileEntity.hasInventoryBeenModified()) {
- fillStacksIntoFirstSlots();
- }
// mSuccess will be negative if the call is caused by the %200 aTimer, always try to push. Otherwise it will be positive.
// For the first 6 ticks after a successful move (49->44), push every tick. Then go to every 5 ticks.
if ( (mSuccess <= 0 ) || (mSuccess > 43) || ((mSuccess % 5) == 0 )){
@@ -84,14 +75,6 @@ public class GT_MetaTileEntity_ChestBuffer extends GT_MetaTileEntity_Buffer {
}
@Override
- public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
- if (aBaseMetaTileEntity.isServerSide() && aBaseMetaTileEntity.hasInventoryBeenModified()) {
- fillStacksIntoFirstSlots();
- }
- super.onPostTick(aBaseMetaTileEntity, aTimer);
- }
-
- @Override
public Object getServerGUI(int aID, InventoryPlayer aPlayerInventory, IGregTechTileEntity aBaseMetaTileEntity) {
return new GT_Container_ChestBuffer(aPlayerInventory, aBaseMetaTileEntity);
}
diff --git a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_SuperBuffer.java b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_SuperBuffer.java
index c7a5139c59..7065e70a3e 100644
--- a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_SuperBuffer.java
+++ b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_SuperBuffer.java
@@ -4,9 +4,16 @@ import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
import gregtech.common.gui.GT_Container_SuperBuffer;
import gregtech.common.gui.GT_GUIContainer_SuperBuffer;
import net.minecraft.entity.player.InventoryPlayer;
+import net.minecraft.item.ItemStack;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_SUPERBUFFER;
import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_SUPERBUFFER_GLOW;
@@ -23,7 +30,7 @@ public class GT_MetaTileEntity_SuperBuffer extends GT_MetaTileEntity_ChestBuffer
public GT_MetaTileEntity_SuperBuffer(String aName, int aTier, int aInvSlotCount, String aDescription, ITexture[][][] aTextures) {
super(aName, aTier, aInvSlotCount, aDescription, aTextures);
}
-
+
public GT_MetaTileEntity_SuperBuffer(String aName, int aTier, int aInvSlotCount, String[] aDescription, ITexture[][][] aTextures) {
super(aName, aTier, aInvSlotCount, aDescription, aTextures);
}
@@ -41,6 +48,41 @@ public class GT_MetaTileEntity_SuperBuffer extends GT_MetaTileEntity_ChestBuffer
}
@Override
+ protected void fillStacksIntoFirstSlots() {
+ // no order, this is super buffer
+ HashMap<GT_Utility.ItemId, Integer> slots = new HashMap<>(mInventory.length);
+ HashMap<GT_Utility.ItemId, ItemStack> stacks = new HashMap<>(mInventory.length);
+ List<Integer> validSlots = new ArrayList<>(mInventory.length);
+ //List<String> order = new ArrayList<>(mInventory.length);
+ for (int i = 0; i < mInventory.length - 1; i++) {
+ if (!isValidSlot(i))
+ continue;
+ validSlots.add(i);
+ ItemStack s = mInventory[i];
+ if(s == null)
+ continue;
+ GT_Utility.ItemId sID = GT_Utility.ItemId.createNoCopy(s);
+ slots.merge(sID, s.stackSize, Integer::sum);
+ if(!stacks.containsKey(sID))
+ stacks.put(sID, s);
+ //order.add(sID);
+ mInventory[i] = null;
+ }
+ int i = 0;
+ for(Map.Entry<GT_Utility.ItemId, Integer> entry : slots.entrySet()){
+ do {
+ int slot = validSlots.get(i);
+ mInventory[slot] = stacks.get(entry.getKey()).copy();
+ int toSet = Math.min(entry.getValue(), mInventory[slot].getMaxStackSize());
+ mInventory[slot].stackSize = toSet;
+ entry.setValue(entry.getValue() - toSet);
+ i++;
+ }
+ while(entry.getValue() > 0);
+ }
+ }
+
+ @Override
public Object getServerGUI(int aID, InventoryPlayer aPlayerInventory, IGregTechTileEntity aBaseMetaTileEntity) {
return new GT_Container_SuperBuffer(aPlayerInventory, aBaseMetaTileEntity);
}