diff options
Diffstat (limited to 'src/main')
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); } |