diff --git a/src/api/java/appeng/api/storage/data/IAEItemStack.java b/src/api/java/appeng/api/storage/data/IAEItemStack.java index eb3dc1595..071547a41 100644 --- a/src/api/java/appeng/api/storage/data/IAEItemStack.java +++ b/src/api/java/appeng/api/storage/data/IAEItemStack.java @@ -119,6 +119,10 @@ public interface IAEItemStack extends IAEStack * * @param is An item stack */ - boolean equals(ItemStack is); + boolean equals( ItemStack is ); + + ItemStack getCachedItemStack( long stackSize ); + + void setCachedItemStack( ItemStack is ); } \ No newline at end of file diff --git a/src/main/java/appeng/helpers/DualityInterface.java b/src/main/java/appeng/helpers/DualityInterface.java index 12e7f02a8..73a8c1e6a 100644 --- a/src/main/java/appeng/helpers/DualityInterface.java +++ b/src/main/java/appeng/helpers/DualityInterface.java @@ -28,6 +28,7 @@ import appeng.util.*; import appeng.util.inv.*; import com.google.common.collect.ImmutableSet; +import com.google.common.primitives.Ints; import de.ellpeck.actuallyadditions.api.tile.IPhantomTile; import gregtech.api.block.machines.BlockMachine; import gregtech.api.metatileentity.MetaTileEntity; @@ -851,7 +852,8 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn else if( itemStack.getStackSize() > 0 ) { // make sure strange things didn't happen... - if( !adaptor.simulateAdd( itemStack.createItemStack() ).isEmpty() ) + ItemStack inputStack = itemStack.createItemStack(); + if( !adaptor.simulateAdd( inputStack ).isEmpty() ) { changed = true; throw new GridAccessException(); @@ -866,7 +868,8 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn if( acquired != null ) { changed = true; - final ItemStack issue = adaptor.addItems( acquired.createItemStack() ); + inputStack.setCount( Ints.saturatedCast( acquired.getStackSize() ) ); + final ItemStack issue = adaptor.addItems( inputStack ); if( !issue.isEmpty() ) { throw new IllegalStateException( "bad attempt at managing inventory. ( addItems )" ); diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index 974aa6079..7e06bf809 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -66,8 +66,8 @@ public class GridStorageCache implements IStorageGrid private final SetMultimap interests = HashMultimap.create(); private final GenericInterestManager interestManager = new GenericInterestManager<>( this.interests ); private final HashMap watchers = new HashMap<>(); - private Map, NetworkInventoryHandler> storageNetworks; - private Map, NetworkMonitor> storageMonitors; + private final Map, NetworkInventoryHandler> storageNetworks; + private final Map, NetworkMonitor> storageMonitors; public GridStorageCache( final IGrid g ) { diff --git a/src/main/java/appeng/parts/automation/PartExportBus.java b/src/main/java/appeng/parts/automation/PartExportBus.java index 2619350b2..84c5b97bd 100644 --- a/src/main/java/appeng/parts/automation/PartExportBus.java +++ b/src/main/java/appeng/parts/automation/PartExportBus.java @@ -19,9 +19,11 @@ package appeng.parts.automation; +import javax.annotation.Nullable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; +import com.google.common.primitives.Ints; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -278,11 +280,27 @@ public class PartExportBus extends PartSharedItemBus implements ICraftingRequest if( energy.extractAEPower( power, mode, PowerMultiplier.CONFIG ) > power - 0.01 ) { - if( mode == Actionable.MODULATE ) + ItemStack inputStack = items.getCachedItemStack( items.getStackSize() ); + + ItemStack remaining; + + remaining = mode == Actionable.SIMULATE ? d.simulateAdd( inputStack ) : d.addItems( inputStack ); + + if( !remaining.isEmpty() ) { - return AEItemStack.fromItemStack( d.addItems( items.createItemStack() ) ); + items.setCachedItemStack( remaining ); } - return AEItemStack.fromItemStack( d.simulateAdd( items.createItemStack() ) ); + else + { + items.setCachedItemStack( inputStack ); + } + + if( remaining == inputStack ) + { + return items; + } + + return AEItemStack.fromItemStack( remaining ); } } } @@ -318,11 +336,13 @@ public class PartExportBus extends PartSharedItemBus implements ICraftingRequest private void pushItemIntoTarget( final InventoryAdaptor d, final IEnergyGrid energy, final IMEInventory inv, IAEItemStack ais ) { - final ItemStack is = ais.createItemStack(); - is.setCount( (int) this.itemToSend ); + ItemStack inputStack = ais.createItemStack(); - final ItemStack o = d.simulateAdd( is ); - final long canFit = o.isEmpty() ? this.itemToSend : this.itemToSend - o.getCount(); + ItemStack toAdd = inputStack; + + final ItemStack remaining = d.simulateAdd( inputStack ); + + final long canFit = remaining.isEmpty() ? this.itemToSend : this.itemToSend - remaining.getCount(); if( canFit > 0 ) { @@ -334,7 +354,13 @@ public class PartExportBus extends PartSharedItemBus implements ICraftingRequest { this.itemToSend -= itemsToAdd.getStackSize(); - final ItemStack failed = d.addItems( itemsToAdd.createItemStack() ); + if( !remaining.isEmpty() ) + { + toAdd = remaining; + } + toAdd.setCount( Ints.saturatedCast( canFit ) ); + + final ItemStack failed = d.addItems( toAdd ); if( !failed.isEmpty() ) { ais.setStackSize( failed.getCount() ); diff --git a/src/main/java/appeng/parts/misc/ItemHandlerAdapter.java b/src/main/java/appeng/parts/misc/ItemHandlerAdapter.java index ce8b1c336..cf69c541b 100644 --- a/src/main/java/appeng/parts/misc/ItemHandlerAdapter.java +++ b/src/main/java/appeng/parts/misc/ItemHandlerAdapter.java @@ -62,8 +62,6 @@ class ItemHandlerAdapter implements IMEInventory, IBaseMonitor, IBaseMonitor, IBaseMonitor< private final InventoryCache cache; private AccessRestriction access; - private ItemStack stackCache; - ItemRepositoryAdapter( IItemRepository itemRepository, IGridProxyable proxy ) { this.itemRepository = itemRepository; @@ -61,31 +59,24 @@ class ItemRepositoryAdapter implements IMEInventory, IBaseMonitor< public IAEItemStack injectItems( IAEItemStack iox, Actionable type, IActionSource src ) { // Try to reuse the cached stack - @Nullable ItemStack currentCached = stackCache; - stackCache = null; + ItemStack inputStack = iox.getCachedItemStack( iox.getStackSize() ); - ItemStack orgInput; - if( currentCached != null && iox.isSameType( currentCached ) ) + ItemStack remaining; + + remaining = this.itemRepository.insertItem( inputStack, type == Actionable.SIMULATE ); + + // Store the stack in the cache for next time. + if( !remaining.isEmpty() ) { - // Cache is suitable, just update the count - orgInput = currentCached; - currentCached.setCount( Ints.saturatedCast( iox.getStackSize() ) ); + iox.setCachedItemStack( remaining ); } else { - // We need a new stack :-( - orgInput = iox.createItemStack(); - } - ItemStack remaining = this.itemRepository.insertItem( orgInput, type == Actionable.SIMULATE ); - - // Store the stack in the cache for next time. - if( !remaining.isEmpty() && remaining != orgInput ) - { - stackCache = remaining; + iox.setCachedItemStack( inputStack ); } // At this point, we still have some items left... - if( remaining == orgInput ) + if( remaining == inputStack ) { // The stack remained unmodified, target inventory is full return iox; diff --git a/src/main/java/appeng/tile/crafting/TileMolecularAssembler.java b/src/main/java/appeng/tile/crafting/TileMolecularAssembler.java index e6639bac3..0eea68ffb 100644 --- a/src/main/java/appeng/tile/crafting/TileMolecularAssembler.java +++ b/src/main/java/appeng/tile/crafting/TileMolecularAssembler.java @@ -22,6 +22,13 @@ package appeng.tile.crafting; import java.io.IOException; import java.util.List; +import appeng.api.networking.security.IActionSource; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.IStorageMonitorable; +import appeng.api.storage.IStorageMonitorableAccessor; +import appeng.api.storage.channels.IItemStorageChannel; +import appeng.capabilities.Capabilities; +import appeng.me.helpers.MachineSource; import io.netty.buffer.ByteBuf; import net.minecraft.inventory.InventoryCrafting; @@ -96,6 +103,7 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade private boolean isAwake = false; private boolean forcePlan = false; private boolean reboot = true; + private final IActionSource mySrc = new MachineSource( this ); public TileMolecularAssembler() { @@ -458,7 +466,7 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade final ItemStack output = this.myPlan.getOutput( this.craftingInv, this.getWorld() ); if( !output.isEmpty() ) { - this.pushOut( output.copy() ); + this.pushOut( output ); for( int x = 0; x < this.craftingInv.getSizeInventory(); x++ ) { @@ -567,6 +575,34 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade return output; } + // Prioritize a handler to directly link to another ME network + IStorageMonitorableAccessor accessor = te.getCapability( Capabilities.STORAGE_MONITORABLE_ACCESSOR, d.getOpposite() ); + + if( accessor != null ) + { + IStorageMonitorable inventory = accessor.getInventory( this.mySrc ); + if( inventory != null ) + { + IAEItemStack toInsert = AEItemStack.fromItemStack( output ); + IMEMonitor inv = inventory.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); + IAEItemStack remainder = inv.injectItems( toInsert, Actionable.SIMULATE, this.mySrc ); + if( remainder == null ) + { + inv.injectItems( toInsert, Actionable.MODULATE, this.mySrc ); + return ItemStack.EMPTY; + } + else + { + if( remainder.getStackSize() == toInsert.getStackSize() ) + { + return output.copy(); + } + inv.injectItems( toInsert.setStackSize( toInsert.getStackSize() - remainder.getStackSize() ), Actionable.MODULATE, this.mySrc ); + return remainder.createItemStack(); + } + } + } + final InventoryAdaptor adaptor = InventoryAdaptor.getAdaptor( te, d.getOpposite() ); if( adaptor == null ) @@ -575,7 +611,7 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade } final int size = output.getCount(); - output = adaptor.addItems( output ); + output = adaptor.addItems( output.copy() ); final int newSize = output.isEmpty() ? 0 : output.getCount(); if( size != newSize ) diff --git a/src/main/java/appeng/util/Platform.java b/src/main/java/appeng/util/Platform.java index f912c7385..98d85e9fc 100644 --- a/src/main/java/appeng/util/Platform.java +++ b/src/main/java/appeng/util/Platform.java @@ -1226,7 +1226,7 @@ public class Platform Preconditions.checkNotNull( src ); Preconditions.checkNotNull( mode ); - final T possible = cell.injectItems( input.copy(), Actionable.SIMULATE, src ); + final T possible = cell.injectItems( input, Actionable.SIMULATE, src ); long stored = input.getStackSize(); if( possible != null ) diff --git a/src/main/java/appeng/util/item/AEItemStack.java b/src/main/java/appeng/util/item/AEItemStack.java index b6a2e4e2a..8f869035a 100644 --- a/src/main/java/appeng/util/item/AEItemStack.java +++ b/src/main/java/appeng/util/item/AEItemStack.java @@ -25,6 +25,7 @@ import java.util.Optional; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import com.google.common.primitives.Ints; import io.netty.buffer.ByteBuf; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -51,8 +52,9 @@ public final class AEItemStack extends AEStack implements IAEItemS @SideOnly(Side.CLIENT) private String displayName; - @SideOnly(Side.CLIENT) + @SideOnly( Side.CLIENT ) private List tooltip; + private ItemStack cachedItemStack; private AEItemStack(final AEItemStack is) { this.setStackSize(is.getStackSize()); @@ -235,44 +237,83 @@ public final class AEItemStack extends AEStack implements IAEItemS } @Override - public boolean equals(final Object ia) { - if (ia instanceof AEItemStack) { - return this.isSameType((AEItemStack) ia); - } else if (ia instanceof ItemStack) { + public boolean equals( final Object ia ) + { + if( ia instanceof AEItemStack ) + { + return this.isSameType( (AEItemStack) ia ); + } + else if( ia instanceof ItemStack ) + { // this actually breaks the equals contract (being equals to unrelated classes) - return equals((ItemStack) ia); + return equals( (ItemStack) ia ); } return false; } @Override - public boolean equals(final ItemStack is) { - return this.isSameType(is); + public boolean equals( final ItemStack is ) + { + return this.isSameType( is ); } @Override - public String toString() { + public ItemStack getCachedItemStack( long stackSize ) + { + @Nullable ItemStack currentCached = this.cachedItemStack; + cachedItemStack = ItemStack.EMPTY; + + ItemStack itemStack; + + if( currentCached != null ) + { + // Cache is suitable, just update the count + itemStack = currentCached; + currentCached.setCount( Ints.saturatedCast( stackSize ) ); + } + else + { + // We need a new stack :-( + itemStack = this.createItemStack(); + } + return itemStack; + } + + @Override + public void setCachedItemStack( ItemStack itemStack ) + { + this.cachedItemStack = itemStack; + } + + @Override + public String toString() + { return this.getStackSize() + "x" + this.getDefinition().getItem().getRegistryName(); } - @SideOnly(Side.CLIENT) - public List getToolTip() { - if (this.tooltip == null) { - this.tooltip = Platform.getTooltip(this.asItemStackRepresentation()); + @SideOnly( Side.CLIENT ) + public List getToolTip() + { + if( this.tooltip == null ) + { + this.tooltip = Platform.getTooltip( this.asItemStackRepresentation() ); } return this.tooltip; } - @SideOnly(Side.CLIENT) - public String getDisplayName() { - if (this.displayName == null) { - this.displayName = Platform.getItemDisplayName(this.asItemStackRepresentation()); + @SideOnly( Side.CLIENT ) + public String getDisplayName() + { + if( this.displayName == null ) + { + this.displayName = Platform.getItemDisplayName( this.asItemStackRepresentation() ); } return this.displayName; } - @SideOnly(Side.CLIENT) - public String getModID() { + @SideOnly( Side.CLIENT ) + public String getModID() + { return this.getDefinition().getItem().getRegistryName().getResourceDomain(); } @@ -282,7 +323,8 @@ public final class AEItemStack extends AEStack implements IAEItemS } @Override - public boolean hasTagCompound() { + public boolean hasTagCompound() + { return this.getDefinition().hasTagCompound(); }