Compare commits

...

25 Commits

Author SHA1 Message Date
Salomão 31a3afc18b revert inventory merging code to keep compatibility with ae2fc 2021-05-14 12:43:34 -03:00
Salomão 9d6026635d level emitter changes 2021-05-13 19:32:03 -03:00
Salomão 39038ac935 revert iitemrepository cache changes 2021-05-12 23:22:54 -03:00
Salomão 4f627b234c invert comparison 2021-05-12 03:26:12 -03:00
Salomão 6180c188e6 Revert "remove crafting failure penalty"
This reverts commit 0240a5d76a.
2021-05-12 02:42:34 -03:00
Salomão 7ada6d18ee small optimizations 2021-05-12 00:19:55 -03:00
Salomão f493767243 fix out of bounds crash 2021-05-09 22:00:20 -03:00
Salomão ba4cdbcb85 fix #16 2021-05-09 10:59:31 -03:00
Salomão f3877aa1ec Merge branch 'iir-cache' into AE2-Omnifactory 2021-05-08 22:46:56 -03:00
Salomão 366b31b3aa import bus optimization 2021-05-08 22:11:13 -03:00
Salomão 533fb5c34b initial test 2021-05-08 19:40:58 -03:00
Salomão 62d1d904c6 update item cache directly on insert/removal
import bus fails faster and throttles down when inventory is full
2021-05-08 19:08:21 -03:00
Salomão 03fb43db16 revert blocking mode to previous implementation 2021-05-05 19:45:25 -03:00
Salomão 9576bec855 renamed method. fixed round robin while blocking mode on 2021-05-04 22:51:20 -03:00
Salomão b5da6730a1 loop optimization 2021-05-04 15:15:09 -03:00
Salomão 039bab4811 drop items waiting to be injected when interface is broken 2021-05-04 11:07:31 -03:00
Salomão 4b5bdf9893 fix NPE 2021-05-04 10:57:01 -03:00
Salomão 3c3c23712d Merge branch 'rr-interfaces' into AE2-Omnifactory 2021-05-03 21:38:43 -03:00
Salomão af91c04ea1 re - implement blocking mode 2021-05-03 21:34:59 -03:00
Salomão 0240a5d76a remove crafting failure penalty 2021-05-03 21:09:03 -03:00
Salomão 0c0aafba2f make ItemSlots copy-able 2021-05-03 21:07:51 -03:00
Salomão b541025738 implement patterned input-based blocking mode
remove GTCE-specific handler and adaptor
2021-05-03 21:07:12 -03:00
Salomão 62f842d4ef visit crafting mediums in round-robin 2021-05-03 21:05:14 -03:00
Salomão fc154d8568 remove slotless capability implementation from inventory adaptor
affects  interface,import and export busses
2021-05-03 21:00:35 -03:00
Salomão 4641e48529 push patterns in round-robin 2021-04-30 12:20:36 -03:00
14 changed files with 463 additions and 251 deletions
@@ -164,7 +164,6 @@ public enum AEFeature
PATTERNS( "Patterns", Constants.CATEGORY_CRAFTING_FEATURES ), PATTERNS( "Patterns", Constants.CATEGORY_CRAFTING_FEATURES ),
CRAFTING_CPU( "CraftingCPU", Constants.CATEGORY_CRAFTING_FEATURES ), CRAFTING_CPU( "CraftingCPU", Constants.CATEGORY_CRAFTING_FEATURES ),
CRAFTING_MANAGER_FALLBACK( "CraftingManagerFallback", Constants.CATEGORY_CRAFTING_FEATURES, "Use CraftingManager to find an alternative recipe, after a pattern rejected an ingredient. Should be enabled to avoid issues, but can have a minor performance impact." ), CRAFTING_MANAGER_FALLBACK( "CraftingManagerFallback", Constants.CATEGORY_CRAFTING_FEATURES, "Use CraftingManager to find an alternative recipe, after a pattern rejected an ingredient. Should be enabled to avoid issues, but can have a minor performance impact." ),
INSANE_BLOCKING_MODE( "InsaneBlockingMode", Constants.CATEGORY_CRAFTING_FEATURES, "Use the default AE2 blocking mode that doesn't work on any machines" ),
BASIC_CARDS( "BasicCards", Constants.CATEGORY_UPGRADES ), BASIC_CARDS( "BasicCards", Constants.CATEGORY_UPGRADES ),
ADVANCED_CARDS( "AdvancedCards", Constants.CATEGORY_UPGRADES ), ADVANCED_CARDS( "AdvancedCards", Constants.CATEGORY_UPGRADES ),
@@ -263,14 +263,14 @@ public class PartFluidStorageBus extends PartSharedStorageBus implements IMEMoni
@Override @Override
public void postChange( final IBaseMonitor<IAEFluidStack> monitor, final Iterable<IAEFluidStack> change, final IActionSource source ) public void postChange( final IBaseMonitor<IAEFluidStack> monitor, final Iterable<IAEFluidStack> change, final IActionSource source )
{
if( source == this.source || source.machine().map( machine -> machine == this ).orElse( false ) )
{ {
try try
{ {
if( this.getProxy().isActive() ) if( this.getProxy().isActive() )
{ {
this.getProxy() this.getProxy().getStorage().postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ), change, this.source );
.getStorage()
.postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ), change, this.source );
} }
} }
catch( final GridAccessException e ) catch( final GridAccessException e )
@@ -278,6 +278,7 @@ public class PartFluidStorageBus extends PartSharedStorageBus implements IMEMoni
// :( // :(
} }
} }
}
public MEInventoryHandler<IAEFluidStack> getInternalHandler() public MEInventoryHandler<IAEFluidStack> getInternalHandler()
{ {
@@ -19,18 +19,14 @@
package appeng.helpers; package appeng.helpers;
import java.util.ArrayList; import java.util.*;
import java.util.Collection; import java.util.stream.Collectors;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import appeng.integration.modules.gregtech.GTCEInventoryAdaptor; import appeng.integration.modules.gregtech.GTCEInventoryAdaptor;
import appeng.util.*; import appeng.util.*;
import appeng.util.inv.*;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import gregtech.api.block.machines.BlockMachine; import gregtech.api.block.machines.BlockMachine;
@@ -93,8 +89,6 @@ import appeng.api.util.AEPartLocation;
import appeng.api.util.DimensionalCoord; import appeng.api.util.DimensionalCoord;
import appeng.api.util.IConfigManager; import appeng.api.util.IConfigManager;
import appeng.capabilities.Capabilities; import appeng.capabilities.Capabilities;
import appeng.core.AEConfig;
import appeng.core.features.AEFeature;
import appeng.core.settings.TickRates; import appeng.core.settings.TickRates;
import appeng.me.GridAccessException; import appeng.me.GridAccessException;
import appeng.me.helpers.AENetworkProxy; import appeng.me.helpers.AENetworkProxy;
@@ -106,10 +100,6 @@ import appeng.parts.automation.StackUpgradeInventory;
import appeng.parts.automation.UpgradeInventory; import appeng.parts.automation.UpgradeInventory;
import appeng.tile.inventory.AppEngInternalAEInventory; import appeng.tile.inventory.AppEngInternalAEInventory;
import appeng.tile.inventory.AppEngInternalInventory; import appeng.tile.inventory.AppEngInternalInventory;
import appeng.util.inv.AdaptorItemHandler;
import appeng.util.inv.IAEAppEngInventory;
import appeng.util.inv.IInventoryDestination;
import appeng.util.inv.InvOperation;
import appeng.util.item.AEItemStack; import appeng.util.item.AEItemStack;
import static gregtech.api.block.machines.BlockMachine.getMetaTileEntity; import static gregtech.api.block.machines.BlockMachine.getMetaTileEntity;
@@ -148,6 +138,8 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
private IMEInventory<IAEItemStack> destination; private IMEInventory<IAEItemStack> destination;
private int isWorking = -1; private int isWorking = -1;
private final Accessor accessor = new Accessor(); private final Accessor accessor = new Accessor();
private EnumSet<EnumFacing> visitedFaces = EnumSet.noneOf( EnumFacing.class );
private EnumMap<EnumFacing,List<ItemStack>> waitingToSendFacing = new EnumMap<>(EnumFacing.class);
private GTCEInventoryAdaptor GTad; private GTCEInventoryAdaptor GTad;
public DualityInterface( final AENetworkProxy networkProxy, final IInterfaceHost ih ) public DualityInterface( final AENetworkProxy networkProxy, final IInterfaceHost ih )
@@ -242,6 +234,27 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
} }
} }
data.setTag( "waitingToSend", waitingToSend ); data.setTag( "waitingToSend", waitingToSend );
NBTTagCompound sidedWaitList = new NBTTagCompound();
if (this.waitingToSendFacing != null)
{
for( EnumFacing s : this.iHost.getTargets() )
{
NBTTagList waitingListSided = new NBTTagList();
if (this.waitingToSendFacing.containsKey( s ))
{
for( final ItemStack is : this.waitingToSendFacing.get( s ) )
{
final NBTTagCompound item = new NBTTagCompound();
is.writeToNBT( item );
waitingListSided.appendTag( item );
}
sidedWaitList.setTag( s.name(), waitingListSided );
}
}
}
data.setTag( "sidedWaitList", sidedWaitList );
} }
public void readFromNBT( final NBTTagCompound data ) public void readFromNBT( final NBTTagCompound data )
@@ -261,6 +274,23 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
} }
} }
this.waitingToSendFacing = null;
final NBTTagCompound waitingListSided = data.getCompoundTag("sidedWaitList");
for (EnumFacing s : EnumFacing.values())
if (waitingListSided.hasKey( s.name() )) {
NBTTagList w = waitingListSided.getTagList( s.name(), 10 );
for( int x = 0; x < w.tagCount(); x++ )
{
final NBTTagCompound c = w.getCompoundTagAt( x );
if( c != null )
{
final ItemStack is = new ItemStack( c );
this.addToSendListFacing( is , EnumFacing.getFront( s.getIndex() ) );
}
}
}
this.craftingTracker.readFromNBT( data ); this.craftingTracker.readFromNBT( data );
this.upgrades.readFromNBT( data, "upgrades" ); this.upgrades.readFromNBT( data, "upgrades" );
this.config.readFromNBT( data, "config" ); this.config.readFromNBT( data, "config" );
@@ -296,6 +326,30 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
} }
} }
private void addToSendListFacing( final ItemStack is, EnumFacing f )
{
if( is.isEmpty() )
{
return;
}
if (this.waitingToSendFacing == null){
this.waitingToSendFacing = new EnumMap<>(EnumFacing.class);
}
this.waitingToSendFacing.computeIfAbsent( f, k -> new ArrayList<>() );
this.waitingToSendFacing.get( f ).add( is );
try
{
this.gridProxy.getTick().wakeDevice( this.gridProxy.getNode() );
}
catch( final GridAccessException e )
{
// :P
}
}
private void readConfig() private void readConfig()
{ {
this.hasConfig = false; this.hasConfig = false;
@@ -393,24 +447,22 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
} }
} }
private boolean hasWorkToDo() private boolean hasWorkToDo() {
{
if( this.hasItemsToSend() ) if (hasItemsToSend()){
{
return true; return true;
} }
else
{
for( final IAEItemStack requiredWork : this.requireWork )
{
if( requiredWork != null )
{
return true;
}
}
return false; if(hasItemsToSendFacing()){
return true;
} }
for (final IAEItemStack requiredWork : this.requireWork) {
if (requiredWork != null) {
return true;
}
}
return false;
} }
private void updatePlan( final int slot ) private void updatePlan( final int slot )
@@ -515,6 +567,21 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
return this.waitingToSend != null && !this.waitingToSend.isEmpty(); return this.waitingToSend != null && !this.waitingToSend.isEmpty();
} }
private boolean hasItemsToSendFacing()
{
if (waitingToSendFacing != null)
{
for( EnumFacing enumFacing : waitingToSendFacing.keySet() )
{
if( !waitingToSendFacing.get( enumFacing ).isEmpty() )
{
return true;
}
}
}
return false;
}
@Override @Override
public boolean canInsert( final ItemStack stack ) public boolean canInsert( final ItemStack stack )
{ {
@@ -586,11 +653,21 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
return TickRateModulation.SLEEP; return TickRateModulation.SLEEP;
} }
//Previous version might have items saved in this list
//recover them
if( this.hasItemsToSend() ) if( this.hasItemsToSend() )
{ {
this.pushItemsOut( this.iHost.getTargets() ); this.pushItemsOut( this.iHost.getTargets() );
} }
if (hasItemsToSendFacing())
{
for( EnumFacing enumFacing : waitingToSendFacing.keySet() )
{
this.pushItemsOut( enumFacing );
}
}
final boolean couldDoWork = this.updateStorage(); final boolean couldDoWork = this.updateStorage();
return this.hasWorkToDo() ? ( couldDoWork ? TickRateModulation.URGENT : TickRateModulation.SLOWER ) : TickRateModulation.SLEEP; return this.hasWorkToDo() ? ( couldDoWork ? TickRateModulation.URGENT : TickRateModulation.SLOWER ) : TickRateModulation.SLEEP;
} }
@@ -651,6 +728,47 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
} }
} }
private void pushItemsOut( final EnumFacing s )
{
if (!this.waitingToSendFacing.containsKey(s) ||
(this.waitingToSendFacing.containsKey(s) && this.waitingToSendFacing.get( s ).isEmpty())) {
return;
}
final TileEntity tile = this.iHost.getTileEntity();
final World w = tile.getWorld();
final TileEntity te = w.getTileEntity( tile.getPos().offset( s ) );
if( te == null )
{
return;
}
final Iterator<ItemStack> i = this.waitingToSendFacing.get( s ).iterator();
while ( i.hasNext() )
{
ItemStack whatToSend = i.next();
final InventoryAdaptor ad = InventoryAdaptor.getAdaptor( te, s.getOpposite() );
if( ad != null )
{
final ItemStack result = ad.addItems( whatToSend );
if( !result.isEmpty() )
{
whatToSend.setCount( whatToSend.getCount() - ( whatToSend.getCount() - result.getCount() ) );
}
else
{
i.remove();
}
}
}
if( this.waitingToSendFacing.get( s ).isEmpty() )
{
this.waitingToSendFacing.remove( s );
}
}
private boolean updateStorage() private boolean updateStorage()
{ {
boolean didSomething = false; boolean didSomething = false;
@@ -913,13 +1031,9 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
}; };
} }
private static boolean invIsBlocked( InventoryAdaptor inv ) private boolean invIsBlocked( InventoryAdaptor inv )
{ {
if( AEConfig.instance().isFeatureEnabled( AEFeature.INSANE_BLOCKING_MODE ) ) return (inv.containsItems());
{
return !inv.simulateRemove( 1, ItemStack.EMPTY, null ).isEmpty();
}
else return inv.containsItems();
} }
private static boolean invIsBlockedGTCE( GTCEInventoryAdaptor inv ) private static boolean invIsBlockedGTCE( GTCEInventoryAdaptor inv )
@@ -930,7 +1044,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
@Override @Override
public boolean pushPattern( final ICraftingPatternDetails patternDetails, final InventoryCrafting table ) public boolean pushPattern( final ICraftingPatternDetails patternDetails, final InventoryCrafting table )
{ {
if( this.hasItemsToSend() || !this.gridProxy.isActive() || !this.craftingList.contains( patternDetails ) ) if( this.hasItemsToSend() || this.hasItemsToSendFacing() || !this.gridProxy.isActive() || !this.craftingList.contains( patternDetails ) )
{ {
return false; return false;
} }
@@ -938,8 +1052,12 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
final TileEntity tile = this.iHost.getTileEntity(); final TileEntity tile = this.iHost.getTileEntity();
final World w = tile.getWorld(); final World w = tile.getWorld();
final EnumSet<EnumFacing> possibleDirections = this.iHost.getTargets(); if( this.visitedFaces.isEmpty() )
for( final EnumFacing s : possibleDirections ) {
this.visitedFaces = this.iHost.getTargets();
}
for( final EnumFacing s : visitedFaces )
{ {
final TileEntity te = w.getTileEntity( tile.getPos().offset( s ) ); final TileEntity te = w.getTileEntity( tile.getPos().offset( s ) );
if( te instanceof IInterfaceHost ) if( te instanceof IInterfaceHost )
@@ -948,6 +1066,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
{ {
if( ( (IInterfaceHost) te ).getInterfaceDuality().sameGrid( this.gridProxy.getGrid() ) ) if( ( (IInterfaceHost) te ).getInterfaceDuality().sameGrid( this.gridProxy.getGrid() ) )
{ {
visitedFaces.remove( s );
continue; continue;
} }
} }
@@ -962,6 +1081,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
final ICraftingMachine cm = (ICraftingMachine) te; final ICraftingMachine cm = (ICraftingMachine) te;
if( cm.acceptsPlans() ) if( cm.acceptsPlans() )
{ {
visitedFaces.remove( s );
if( cm.pushPattern( patternDetails, table, s.getOpposite() ) ) if( cm.pushPattern( patternDetails, table, s.getOpposite() ) )
{ {
return true; return true;
@@ -978,50 +1098,49 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
if( te.getBlockType().getRegistryName().getResourceDomain().equals( "gregtech" ) ) if( te.getBlockType().getRegistryName().getResourceDomain().equals( "gregtech" ) )
{ {
GTad = GTCEInventoryAdaptor.getAdaptor( te, s.getOpposite() ); GTad = GTCEInventoryAdaptor.getAdaptor( te, s.getOpposite() );
if( invIsBlockedGTCE( GTad ) ) if( GTad != null && !invIsBlockedGTCE( GTad ) )
{ {
visitedFaces.remove( s );
continue; continue;
} }
} }
else else if ( invIsBlocked( ad ) )
{
if( invIsBlocked( ad ) )
{ {
visitedFaces.remove( s );
continue; continue;
} }
} }
}
if( this.acceptsItems( ad, table ) ) if( this.acceptsItems( ad, table ) )
{ {
visitedFaces.remove( s );
for( int x = 0; x < table.getSizeInventory(); x++ ) for( int x = 0; x < table.getSizeInventory(); x++ )
{ {
final ItemStack is = table.getStackInSlot( x ); final ItemStack is = table.getStackInSlot( x );
if( !is.isEmpty() ) if( !is.isEmpty() )
{ {
final ItemStack added = ad.addItems( is ); addToSendListFacing( is, s );
this.addToSendList( added );
} }
} }
this.pushItemsOut( possibleDirections ); pushItemsOut( s );
return true; return true;
} }
} }
visitedFaces.remove( s );
} }
return false; return false;
} }
@Override @Override
public boolean isBusy() public boolean isBusy()
{ {
if( this.hasItemsToSend() ) boolean busy = false;
if( this.hasItemsToSend() || hasItemsToSendFacing() )
{ {
return true; return true;
} }
boolean busy = false;
if( this.isBlocking() ) if( this.isBlocking() )
{ {
final EnumSet<EnumFacing> possibleDirections = this.iHost.getTargets(); final EnumSet<EnumFacing> possibleDirections = this.iHost.getTargets();
@@ -1040,21 +1159,17 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
if( te.getBlockType().getRegistryName().getResourceDomain().equals( "gregtech" ) ) if( te.getBlockType().getRegistryName().getResourceDomain().equals( "gregtech" ) )
{ {
GTad = GTCEInventoryAdaptor.getAdaptor( te, s.getOpposite() ); GTad = GTCEInventoryAdaptor.getAdaptor( te, s.getOpposite() );
if( !invIsBlockedGTCE( GTad ) ) if( GTad != null && !invIsBlockedGTCE( GTad ) )
{ {
allAreBusy = false; allAreBusy = false;
break; break;
} }
} }
else else if( !invIsBlocked( ad ) )
{
if( !invIsBlocked( ad ) )
{ {
allAreBusy = false; allAreBusy = false;
break; break;
} }
}
} }
} }
busy = allAreBusy; busy = allAreBusy;
@@ -1117,6 +1232,20 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
} }
} }
if( this.waitingToSendFacing != null )
{
for (List<ItemStack> itemList : waitingToSendFacing.values())
{
for (final ItemStack is : itemList)
{
if (!is.isEmpty())
{
drops.add(is);
}
}
}
}
for( final ItemStack is : this.upgrades ) for( final ItemStack is : this.upgrades )
{ {
if( !is.isEmpty() ) if( !is.isEmpty() )
@@ -1,5 +1,6 @@
package appeng.integration.modules.gregtech; package appeng.integration.modules.gregtech;
import appeng.util.inv.ItemHandlerIterator;
import appeng.util.inv.ItemSlot; import appeng.util.inv.ItemSlot;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -52,6 +53,6 @@ public class GTCEItemHandler extends GTCEInventoryAdaptor
@Override @Override
public Iterator<ItemSlot> iterator() public Iterator<ItemSlot> iterator()
{ {
return null; return new ItemHandlerIterator( this.itemHandler );
} }
} }
+4 -2
View File
@@ -44,6 +44,8 @@ import appeng.api.storage.IStorageChannel;
import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.me.storage.ItemWatcher; import appeng.me.storage.ItemWatcher;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T> public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
@@ -58,7 +60,7 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
@Nonnull @Nonnull
private final IItemList<T> cachedList; private final IItemList<T> cachedList;
@Nonnull @Nonnull
private final Map<IMEMonitorHandlerReceiver<T>, Object> listeners; private final Object2ObjectMap<IMEMonitorHandlerReceiver<T>, Object> listeners;
private boolean sendEvent = false; private boolean sendEvent = false;
private boolean hasChanged = false; private boolean hasChanged = false;
@@ -70,7 +72,7 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
this.myGridCache = cache; this.myGridCache = cache;
this.myChannel = chan; this.myChannel = chan;
this.cachedList = chan.createList(); this.cachedList = chan.createList();
this.listeners = new HashMap<>(); this.listeners = new Object2ObjectOpenHashMap<>();
} }
@Override @Override
@@ -19,13 +19,9 @@
package appeng.me.cluster.implementations; package appeng.me.cluster.implementations;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.stream.Collectors;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@@ -34,8 +30,6 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagList;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.fml.common.FMLCommonHandler;
import appeng.api.AEApi; import appeng.api.AEApi;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
@@ -93,6 +87,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
private final List<TileCraftingTile> storage = new ArrayList<>(); private final List<TileCraftingTile> storage = new ArrayList<>();
private final List<TileCraftingMonitorTile> status = new ArrayList<>(); private final List<TileCraftingMonitorTile> status = new ArrayList<>();
private final HashMap<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new HashMap<>(); private final HashMap<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new HashMap<>();
private final Map<ICraftingPatternDetails, Queue<ICraftingMedium>> visitedMediums = new HashMap<>();
private ICraftingLink myLastLink; private ICraftingLink myLastLink;
private String myName = ""; private String myName = "";
private boolean isDestroyed = false; private boolean isDestroyed = false;
@@ -646,14 +641,22 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
InventoryCrafting ic = null; InventoryCrafting ic = null;
for( final ICraftingMedium m : cc.getMediums( e.getKey() ) ) if (!visitedMediums.containsKey( details ) || visitedMediums.get( details ).isEmpty())
{ {
visitedMediums.put( details, new ArrayDeque<>( cc.getMediums( details ).stream().filter( Objects::nonNull ).collect( Collectors.toList()) ) );
}
while (!visitedMediums.get( details ).isEmpty())
{
ICraftingMedium m = visitedMediums.get( details ).poll();
if( e.getValue().value <= 0 ) if( e.getValue().value <= 0 )
{ {
continue; continue;
} }
if( !m.isBusy() ) if( m != null && !m.isBusy() )
{ {
if( ic == null ) if( ic == null )
{ {
@@ -218,6 +218,12 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
private boolean importStuff( final InventoryAdaptor myAdaptor, final IAEItemStack whatToImport, final IMEMonitor<IAEItemStack> inv, final IEnergySource energy, final FuzzyMode fzMode ) private boolean importStuff( final InventoryAdaptor myAdaptor, final IAEItemStack whatToImport, final IMEMonitor<IAEItemStack> inv, final IEnergySource energy, final FuzzyMode fzMode )
{ {
final int toSend = this.calculateMaximumAmountToImport( myAdaptor, whatToImport, inv, fzMode ); final int toSend = this.calculateMaximumAmountToImport( myAdaptor, whatToImport, inv, fzMode );
if( toSend == 0 )
{
return true;
}
final ItemStack newItems; final ItemStack newItems;
if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 ) if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 )
@@ -286,8 +292,17 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
itemAmountNotStorable = inv.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source ); itemAmountNotStorable = inv.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source );
} }
if( simResult.isEmpty() )
{
return 0;
}
if( itemAmountNotStorable != null ) if( itemAmountNotStorable != null )
{ {
if( simResult.getCount() == itemAmountNotStorable.getStackSize() )
{
return 0;
}
return (int) Math.min( simResult.getCount() - itemAmountNotStorable.getStackSize(), toSend ); return (int) Math.min( simResult.getCount() - itemAmountNotStorable.getStackSize(), toSend );
} }
@@ -19,6 +19,7 @@
package appeng.parts.automation; package appeng.parts.automation;
import java.util.ArrayList;
import java.util.Random; import java.util.Random;
import appeng.me.Grid; import appeng.me.Grid;
@@ -26,6 +27,7 @@ import appeng.me.GridNode;
import appeng.util.item.AEItemStack; import appeng.util.item.AEItemStack;
import it.unimi.dsi.fastutil.objects.Object2LongMap; import it.unimi.dsi.fastutil.objects.Object2LongMap;
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.InventoryCrafting; import net.minecraft.inventory.InventoryCrafting;
@@ -126,6 +128,8 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH
static Object2LongMap<Grid> gridItemCount = new Object2LongOpenHashMap<>(); static Object2LongMap<Grid> gridItemCount = new Object2LongOpenHashMap<>();
static Object2ObjectOpenHashMap<Grid, Object2LongMap<AEItemStack>> fuzzyAEItemStackCount = new Object2ObjectOpenHashMap<>(); static Object2ObjectOpenHashMap<Grid, Object2LongMap<AEItemStack>> fuzzyAEItemStackCount = new Object2ObjectOpenHashMap<>();
static Object2ObjectOpenHashMap<Grid, Object2LongMap<AEItemStack>> preciseAEItemStackCount = new Object2ObjectOpenHashMap<>(); static Object2ObjectOpenHashMap<Grid, Object2LongMap<AEItemStack>> preciseAEItemStackCount = new Object2ObjectOpenHashMap<>();
static Object2ObjectMap<Grid,Iterable<IAEItemStack>> previousChange = new Object2ObjectOpenHashMap<>();
static Object2ObjectMap<Grid,IItemList<IAEItemStack>> cachedStorageList = new Object2ObjectOpenHashMap<>();
@Reflected @Reflected
public PartLevelEmitter( final ItemStack is ) public PartLevelEmitter( final ItemStack is )
@@ -324,54 +328,90 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH
private void updateReportingValue( final IMEMonitor<IAEItemStack> monitor ) private void updateReportingValue( final IMEMonitor<IAEItemStack> monitor )
{ {
updateReportingValue( monitor,null ); updateReportingValue( monitor, new ArrayList<>() );
} }
private void updateReportingValue( final IMEMonitor<IAEItemStack> monitor, Iterable<IAEItemStack> change ) private void updateReportingValue( final IMEMonitor<IAEItemStack> monitor, Iterable<IAEItemStack> change )
{ {
final IAEItemStack myStack = this.config.getAEStackInSlot( 0 ); final IAEItemStack myStack = this.config.getAEStackInSlot( 0 );
GridNode node = (GridNode) (this.getGridNode()); GridNode node = (GridNode) ( this.getGridNode() );
if( node != null ) if( node != null )
{ {
final Grid g = node.getInternalGrid(); final Grid g = node.getInternalGrid();
if( myStack == null ) IItemList<IAEItemStack> l;
boolean alreadyEvaluated = false;
if( previousChange.containsKey( g ) )
{ {
if( change != null ) if( change.iterator().hasNext() && previousChange.get( g ).iterator().hasNext() )
{
IAEItemStack a = change.iterator().next();
IAEItemStack b = previousChange.get( g ).iterator().next();
if( a == b )
{
alreadyEvaluated = true;
}
}
else {
alreadyEvaluated = true;
}
}
if( alreadyEvaluated )
{
l = cachedStorageList.get( g );
}
else
{
l = monitor.getStorageList();
cachedStorageList.put( g, l );
if ( change.iterator().hasNext() )
{
previousChange.put( g, change );
}
else
{
previousChange.put( g, new ArrayList<>() );
}
}
if( myStack == null )
{ {
if( gridItemCount.containsKey( g ) ) if( gridItemCount.containsKey( g ) )
{ {
change.forEach( iaeItemStack -> lastReportedValue += iaeItemStack.getStackSize() ); change.forEach( iaeItemStack -> lastReportedValue += iaeItemStack.getStackSize() );
} }
}
gridItemCount.computeIfAbsent( g, ( aLong ) -> { gridItemCount.computeIfAbsent( g, ( aLong ) -> {
this.lastReportedValue = 0; this.lastReportedValue = 0;
monitor.getStorageList().forEach( iaeItemStack -> lastReportedValue += iaeItemStack.getStackSize() ); l.forEach( iaeItemStack -> lastReportedValue += iaeItemStack.getStackSize() );
return ( lastReportedValue ); return ( lastReportedValue );
} ); } );
this.lastReportedValue = gridItemCount.get( g ); this.lastReportedValue = gridItemCount.get( g );
} }
else if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 ) else if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 )
{ {
final FuzzyMode fzMode = (FuzzyMode) this.getConfigManager().getSetting( Settings.FUZZY_MODE ); final FuzzyMode fzMode = (FuzzyMode) this.getConfigManager().getSetting( Settings.FUZZY_MODE );
if( change != null )
{
if( fuzzyAEItemStackCount.containsKey( g ) ) if( fuzzyAEItemStackCount.containsKey( g ) )
{ {
change.forEach( iaeItemStack -> { change.forEach( iaeItemStack -> {
if( iaeItemStack.sameOre( myStack ) ) lastReportedValue += iaeItemStack.getStackSize(); if( iaeItemStack.sameOre( myStack ) )
} ); {
lastReportedValue += iaeItemStack.getStackSize();
} }
} );
} }
fuzzyAEItemStackCount.computeIfAbsent( g, ( grid -> new Object2LongOpenHashMap<>() ) ); fuzzyAEItemStackCount.computeIfAbsent( g, ( grid -> new Object2LongOpenHashMap<>() ) );
fuzzyAEItemStackCount.get( g ).computeIfAbsent( (AEItemStack) myStack, ( aLong -> { fuzzyAEItemStackCount.get( g ).computeIfAbsent( (AEItemStack) myStack, ( aLong -> {
this.lastReportedValue = 0; this.lastReportedValue = 0;
monitor.getStorageList().findFuzzy( myStack, fzMode ).forEach( iaeItemStack -> lastReportedValue += iaeItemStack.getStackSize() ); l.findFuzzy( myStack, fzMode ).forEach( iaeItemStack -> lastReportedValue += iaeItemStack.getStackSize() );
return ( lastReportedValue ); return ( lastReportedValue );
} ) ); } ) );
@@ -383,8 +423,6 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH
} }
} }
else else
{
if( change != null )
{ {
if( preciseAEItemStackCount.containsKey( g ) ) if( preciseAEItemStackCount.containsKey( g ) )
{ {
@@ -392,11 +430,11 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH
if( iaeItemStack.isSameType( myStack ) ) lastReportedValue += iaeItemStack.getStackSize(); if( iaeItemStack.isSameType( myStack ) ) lastReportedValue += iaeItemStack.getStackSize();
} ); } );
} }
}
preciseAEItemStackCount.computeIfAbsent( g, ( grid -> new Object2LongOpenHashMap<>() ) ); preciseAEItemStackCount.computeIfAbsent( g, ( grid -> new Object2LongOpenHashMap<>() ) );
preciseAEItemStackCount.get( g ).computeIfAbsent( (AEItemStack) myStack, ( aLong -> { preciseAEItemStackCount.get( g ).computeIfAbsent( (AEItemStack) myStack, ( aLong -> {
this.lastReportedValue = 0; this.lastReportedValue = 0;
IAEItemStack precise = monitor.getStorageList().findPrecise( myStack ); IAEItemStack precise = l.findPrecise( myStack );
if( precise != null ) lastReportedValue = precise.getStackSize(); if( precise != null ) lastReportedValue = precise.getStackSize();
return ( lastReportedValue ); return ( lastReportedValue );
} ) ); } ) );
@@ -19,15 +19,12 @@
package appeng.parts.misc; package appeng.parts.misc;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import appeng.api.config.Settings; import appeng.api.config.Settings;
import appeng.api.config.StorageFilter; import appeng.api.config.StorageFilter;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
@@ -42,11 +39,11 @@ import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.core.AELog; import appeng.core.AELog;
import appeng.me.GridAccessException;
import appeng.me.helpers.IGridProxyable; import appeng.me.helpers.IGridProxyable;
import appeng.me.storage.ITickingMonitor; import appeng.me.storage.ITickingMonitor;
import appeng.util.Platform; import appeng.util.Platform;
import appeng.util.item.AEItemStack; import appeng.util.item.AEItemStack;
import org.apache.commons.lang3.tuple.Pair;
/** /**
@@ -54,7 +51,7 @@ import appeng.util.item.AEItemStack;
*/ */
class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAEItemStack>, ITickingMonitor class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAEItemStack>, ITickingMonitor
{ {
private final Map<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new HashMap<>(); private final Object2ObjectMap<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new Object2ObjectOpenHashMap<>();
private IActionSource mySource; private IActionSource mySource;
private final IItemHandler itemHandler; private final IItemHandler itemHandler;
private final IGridProxyable proxyable; private final IGridProxyable proxyable;
@@ -76,16 +73,28 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
@Override @Override
public IAEItemStack injectItems( IAEItemStack iox, Actionable type, IActionSource src ) public IAEItemStack injectItems( IAEItemStack iox, Actionable type, IActionSource src )
{ {
ItemStack orgInput = iox.createItemStack(); ItemStack orgInput = iox.createItemStack();
ItemStack remaining = orgInput; ItemStack remaining = orgInput;
int slotCount = this.itemHandler.getSlots(); int slotCount = this.itemHandler.getSlots();
boolean simulate = ( type == Actionable.SIMULATE ); boolean simulate = ( type == Actionable.SIMULATE );
List<Pair<Integer, Integer>> injectedList = new ArrayList<>();
// This uses a brute force approach and tries to jam it in every slot the inventory exposes. // This uses a brute force approach and tries to jam it in every slot the inventory exposes.
for( int i = 0; i < slotCount && !remaining.isEmpty(); i++ ) for( int i = 0; i < slotCount && !remaining.isEmpty(); i++ )
{ {
int countPre = remaining.getCount();
remaining = this.itemHandler.insertItem( i, remaining, simulate ); remaining = this.itemHandler.insertItem( i, remaining, simulate );
int countPos = remaining.getCount();
if( remaining.isEmpty() )
{
injectedList.add( Pair.of( i, countPre ) );
break;
}
else if( countPos < countPre )
{
injectedList.add( Pair.of( i, countPre - countPos ) );
}
} }
// At this point, we still have some items left... // At this point, we still have some items left...
@@ -97,14 +106,30 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
if( type == Actionable.MODULATE ) if( type == Actionable.MODULATE )
{ {
try if( this.cache.cachedAeStacks.length == 0 )
{ {
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); this.cache.update();
} }
catch( GridAccessException ex ) else
{ {
// meh for( Pair<Integer, Integer> pair : injectedList )
{
if( pair.getKey() >= this.cache.cachedAeStacks.length )
{
this.cache.update();
break;
} }
if( this.cache.cachedAeStacks[pair.getKey()] == null )
{
this.cache.cachedAeStacks[pair.getKey()] = iox.copy().setStackSize( pair.getValue() );
}
else
{
this.cache.cachedAeStacks[pair.getKey()].incStackSize( pair.getValue() );
}
}
}
} }
return AEItemStack.fromItemStack( remaining ); return AEItemStack.fromItemStack( remaining );
@@ -113,7 +138,6 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
@Override @Override
public IAEItemStack extractItems( IAEItemStack request, Actionable mode, IActionSource src ) public IAEItemStack extractItems( IAEItemStack request, Actionable mode, IActionSource src )
{ {
ItemStack requestedItemStack = request.createItemStack(); ItemStack requestedItemStack = request.createItemStack();
int remainingSize = requestedItemStack.getCount(); int remainingSize = requestedItemStack.getCount();
@@ -121,8 +145,10 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
ItemStack gathered = ItemStack.EMPTY; ItemStack gathered = ItemStack.EMPTY;
final boolean simulate = ( mode == Actionable.SIMULATE ); final boolean simulate = ( mode == Actionable.SIMULATE );
List<Pair<Integer, Integer>> extractedList = new ArrayList<>();
for( int i = 0; i < this.itemHandler.getSlots(); i++ )
for ( int i = 0; i < this.itemHandler.getSlots(); i++ )
{ {
ItemStack stackInInventorySlot = this.itemHandler.getStackInSlot( i ); ItemStack stackInInventorySlot = this.itemHandler.getStackInSlot( i );
@@ -140,16 +166,9 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
do do
{ {
extracted = this.itemHandler.extractItem( i, remainingCurrentSlot, simulate ); extracted = this.itemHandler.extractItem( i, remainingCurrentSlot, simulate );
if( !extracted.isEmpty() ) if( !extracted.isEmpty() )
{ {
// In order to guard against broken IItemHandler implementations, we'll try to guess if the returned
// stack (especially in simulate mode) is the same that was returned by getStackInSlot. This is
// obviously not a precise science, but it would catch the previous Forge bug:
// https://github.com/MinecraftForge/MinecraftForge/pull/6580
if (extracted == stackInInventorySlot) {
extracted = extracted.copy();
}
if( extracted.getCount() > remainingCurrentSlot ) if( extracted.getCount() > remainingCurrentSlot )
{ {
// Something broke. It should never return more than we requested... // Something broke. It should never return more than we requested...
@@ -159,17 +178,12 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
extracted.setCount( remainingCurrentSlot ); extracted.setCount( remainingCurrentSlot );
} }
// Heuristic for simulation: looping in case of simulations is pointless, since the state of the // We're just gonna use the first stack we get our hands on as the template for the rest.
// underlying inventory does not change after a simulated extraction. To still support inventories // In case some stupid itemhandler (aka forge) returns an internal state we have to do a second
// that report stacks that are larger than maxStackSize, we use this heuristic // expensive copy again.
if (simulate && extracted.getCount() == extracted.getMaxStackSize()
&& remainingCurrentSlot > extracted.getMaxStackSize()) {
extracted.setCount(remainingCurrentSlot);
}
if( gathered.isEmpty() ) if( gathered.isEmpty() )
{ {
gathered = extracted; gathered = extracted.copy();
} }
else else
{ {
@@ -178,10 +192,15 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
remainingCurrentSlot -= extracted.getCount(); remainingCurrentSlot -= extracted.getCount();
} }
} }
while( !simulate && !extracted.isEmpty() && remainingCurrentSlot > 0 ); while ( !extracted.isEmpty() && remainingCurrentSlot > 0 );
remainingSize -= stackSizeCurrentSlot - remainingCurrentSlot; remainingSize -= stackSizeCurrentSlot - remainingCurrentSlot;
if (!gathered.isEmpty())
{
extractedList.add( Pair.of( i, gathered.getCount() ) );
}
// Done? // Done?
if( remainingSize <= 0 ) if( remainingSize <= 0 )
{ {
@@ -193,13 +212,23 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
{ {
if( mode == Actionable.MODULATE ) if( mode == Actionable.MODULATE )
{ {
try if( this.cache.cachedAeStacks.length == 0 )
{ {
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); this.cache.update();
} }
catch( GridAccessException ex ) else
{ {
// meh for( Pair<Integer, Integer> pair : extractedList )
{
if( this.cache.cachedAeStacks[pair.getKey()] != null )
{
this.cache.cachedAeStacks[pair.getKey()].decStackSize( pair.getValue() );
if( this.cache.cachedAeStacks[pair.getKey()].getStackSize() == 0 )
{
this.cache.cachedAeStacks[pair.getKey()] = null;
}
}
}
} }
} }
@@ -377,7 +406,7 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
if( oldAeIS != null ) if( oldAeIS != null )
{ {
oldAeIS.setStackSize( -oldAeIS.getStackSize() ); oldAeIS.setStackSize( -oldAeIS.getStackSize() );
changes.add( oldAeIS ); changes.add( oldAeIS.copy() );
} }
// Notify the network about the new stack. Note that this is null if newIS was null // Notify the network about the new stack. Note that this is null if newIS was null
@@ -1,17 +1,14 @@
package appeng.parts.misc; package appeng.parts.misc;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import appeng.api.storage.IStorageChannel; import appeng.api.storage.IStorageChannel;
import appeng.core.AELog; import appeng.core.AELog;
import com.jaquadro.minecraft.storagedrawers.api.capabilities.IItemRepository; import com.jaquadro.minecraft.storagedrawers.api.capabilities.IItemRepository;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import appeng.api.AEApi; import appeng.api.AEApi;
@@ -38,7 +35,7 @@ import javax.annotation.Nonnull;
class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAEItemStack>, ITickingMonitor class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAEItemStack>, ITickingMonitor
{ {
private final Map<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new HashMap<>(); private final Object2ObjectMap<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new Object2ObjectOpenHashMap<>();
private IActionSource mySource; private IActionSource mySource;
private final IItemRepository itemRepository; private final IItemRepository itemRepository;
private final IGridProxyable proxyable; private final IGridProxyable proxyable;
@@ -88,13 +85,12 @@ class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<
@Override @Override
public IAEItemStack extractItems( IAEItemStack request, Actionable mode, IActionSource src ) public IAEItemStack extractItems( IAEItemStack request, Actionable mode, IActionSource src )
{ {
ItemStack requestedItemStack = request.createItemStack(); ItemStack requestedItemStack = request.getDefinition();
int remainingSize = requestedItemStack.getCount(); int remainingSize = (int) Math.min( Integer.MAX_VALUE, request.getStackSize());
final boolean simulate = ( mode == Actionable.SIMULATE ); final boolean simulate = ( mode == Actionable.SIMULATE );
ItemStack extracted; ItemStack extracted = this.itemRepository.extractItem( requestedItemStack, remainingSize, simulate );
extracted = this.itemRepository.extractItem( requestedItemStack, remainingSize, simulate );
if( extracted.getCount() > remainingSize ) if( extracted.getCount() > remainingSize )
{ {
@@ -118,10 +114,8 @@ class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<
// meh // meh
} }
} }
return AEItemStack.fromItemStack( extracted ); return AEItemStack.fromItemStack( extracted );
} }
return null; return null;
} }
@@ -290,7 +284,7 @@ class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<
if( oldAeIS != null ) if( oldAeIS != null )
{ {
oldAeIS.setStackSize( -oldAeIS.getStackSize() ); oldAeIS.setStackSize( -oldAeIS.getStackSize() );
changes.add( oldAeIS ); changes.add( oldAeIS.copy() );
} }
// Notify the network about the new stack. Note that this is null if newIS was null // Notify the network about the new stack. Note that this is null if newIS was null
@@ -257,15 +257,14 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
@Override @Override
public void postChange( final IBaseMonitor<IAEItemStack> monitor, final Iterable<IAEItemStack> change, final IActionSource source ) public void postChange( final IBaseMonitor<IAEItemStack> monitor, final Iterable<IAEItemStack> change, final IActionSource source )
{
if( source == this.mySrc || source.machine().map( machine -> machine == this ).orElse( false ) )
{ {
try try
{ {
if( this.getProxy().isActive() ) if( this.getProxy().isActive() )
{ {
this.getProxy() this.getProxy().getStorage().postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), change, this.mySrc );
.getStorage()
.postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), change,
this.mySrc );
} }
} }
catch( final GridAccessException e ) catch( final GridAccessException e )
@@ -273,6 +272,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
// :( // :(
} }
} }
}
@Override @Override
public void onListUpdate() public void onListUpdate()
@@ -206,3 +206,4 @@ public class AdaptorItemRepository extends InventoryAdaptor
return null; return null;
} }
} }
@@ -25,7 +25,7 @@ import java.util.NoSuchElementException;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
class ItemHandlerIterator implements Iterator<ItemSlot> public class ItemHandlerIterator implements Iterator<ItemSlot>
{ {
private final IItemHandler itemHandler; private final IItemHandler itemHandler;
@@ -34,7 +34,7 @@ class ItemHandlerIterator implements Iterator<ItemSlot>
private int slot = 0; private int slot = 0;
ItemHandlerIterator( IItemHandler itemHandler ) public ItemHandlerIterator( IItemHandler itemHandler )
{ {
this.itemHandler = itemHandler; this.itemHandler = itemHandler;
} }