diff --git a/src/main/java/appeng/fluids/parts/PartFluidStorageBus.java b/src/main/java/appeng/fluids/parts/PartFluidStorageBus.java index d299f9c66..ddf48e404 100644 --- a/src/main/java/appeng/fluids/parts/PartFluidStorageBus.java +++ b/src/main/java/appeng/fluids/parts/PartFluidStorageBus.java @@ -326,6 +326,10 @@ public class PartFluidStorageBus extends PartSharedStorageBus implements IMEMoni this.handlerHash = newHandlerHash; this.handler = null; + if( this.monitor != null ) + { + ( (IBaseMonitor) monitor ).removeListener( this ); + } this.monitor = null; if( target != null ) { diff --git a/src/main/java/appeng/helpers/DualityInterface.java b/src/main/java/appeng/helpers/DualityInterface.java index a06731ed4..a0a692a00 100644 --- a/src/main/java/appeng/helpers/DualityInterface.java +++ b/src/main/java/appeng/helpers/DualityInterface.java @@ -23,7 +23,6 @@ import java.util.*; import javax.annotation.Nullable; -import appeng.api.definitions.IItemDefinition; import appeng.integration.modules.gregtech.GTCEInventoryAdaptor; import appeng.util.*; import appeng.util.inv.*; @@ -35,7 +34,6 @@ import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.MetaTileEntityHolder; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; -import net.minecraft.client.Minecraft; import net.minecraft.init.Items; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.Item; @@ -142,15 +140,17 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn private int isWorking = -1; private final Accessor accessor = new Accessor(); private EnumSet visitedFaces = EnumSet.noneOf( EnumFacing.class ); - private EnumMap> waitingToSendFacing = new EnumMap<>(EnumFacing.class); + private EnumMap> waitingToSendFacing = new EnumMap<>( EnumFacing.class ); private GTCEInventoryAdaptor GTad; + private boolean resetConfigCache = true; + private IMEMonitor configCachedHandler; public DualityInterface( final AENetworkProxy networkProxy, final IInterfaceHost ih ) { this.gridProxy = networkProxy; this.gridProxy.setFlags( GridFlags.REQUIRE_CHANNEL ); - this.upgrades = new StackUpgradeInventory( this.gridProxy.getMachineRepresentation(), this, 4); + this.upgrades = new StackUpgradeInventory( this.gridProxy.getMachineRepresentation(), this, 4 ); this.cm.registerSetting( Settings.BLOCK, YesNo.NO ); this.cm.registerSetting( Settings.INTERFACE_TERMINAL, YesNo.YES ); @@ -180,7 +180,12 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn } if( inv == this.config && ( !removed.isEmpty() || !added.isEmpty() ) ) { + boolean cfg = hasConfig(); this.readConfig(); + if( cfg != hasConfig ) + { + resetConfigCache = true; + } } else if( inv == this.patterns && ( !removed.isEmpty() || !added.isEmpty() ) ) { @@ -975,7 +980,12 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn { if( this.hasConfig() ) { - return (IMEMonitor) new InterfaceInventory( this ); + if( resetConfigCache ) + { + resetConfigCache = false; + configCachedHandler = new InterfaceInventory( this ); + } + return (IMEMonitor) configCachedHandler; } return (IMEMonitor) this.items; @@ -1583,7 +1593,6 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn public InterfaceInventory( final DualityInterface tileInterface ) { super( new AdaptorItemHandler( tileInterface.storage ) ); - this.setActionSource( new MachineSource( DualityInterface.this.iHost ) ); } @Override diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index 99069c750..e2075727d 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -109,6 +109,9 @@ public class GridStorageCache implements IStorageGrid this.watchers.remove( node ); } } + + this.storageMonitors.forEach( ( channel, monitor ) -> monitor.forceUpdate() ); + } @Override @@ -137,6 +140,9 @@ public class GridStorageCache implements IStorageGrid this.watchers.put( node, iw ); swh.updateWatcher( iw ); } + + this.storageMonitors.forEach( ( channel, monitor ) -> monitor.forceUpdate() ); + } @Override diff --git a/src/main/java/appeng/me/cache/NetworkMonitor.java b/src/main/java/appeng/me/cache/NetworkMonitor.java index 24c8ba68b..07cde73f5 100644 --- a/src/main/java/appeng/me/cache/NetworkMonitor.java +++ b/src/main/java/appeng/me/cache/NetworkMonitor.java @@ -235,36 +235,39 @@ public class NetworkMonitor> implements IMEMonitor protected void postChange( final boolean add, final Iterable changes, final IActionSource src ) { - if( GLOBAL_DEPTH.contains( this ) ) + if( this.localDepthSemaphore > 0 || GLOBAL_DEPTH.contains( this ) ) { return; } + this.localDepthSemaphore++; GLOBAL_DEPTH.push( this ); this.sendEvent = true; - for( final T changedItem : changes ) + for( final T changed : changes ) { - if( !add && changedItem != null ) + T change = changed; + if( !add && change != null ) { - changedItem.setStackSize( -changedItem.getStackSize() ); + change = changed.copy(); + change.setStackSize( -change.getStackSize() ); } - incGridCurrentCount( changedItem.getStackSize() ); - this.cachedList.add( changedItem ); + incGridCurrentCount( change.getStackSize() ); + this.cachedList.add( change ); - if( this.myGridCache.getInterestManager().containsKey( changedItem ) ) + if( this.myGridCache.getInterestManager().containsKey( change ) ) { - final Collection list = this.myGridCache.getInterestManager().get( changedItem ); + final Collection list = this.myGridCache.getInterestManager().get( change ); if( !list.isEmpty() ) { - IAEStack fullStack = this.getStorageList().findPrecise( changedItem ); + IAEStack fullStack = this.getStorageList().findPrecise( change ); if( fullStack == null ) { - fullStack = changedItem.copy(); + fullStack = change.copy(); fullStack.setStackSize( 0 ); } @@ -272,7 +275,7 @@ public class NetworkMonitor> implements IMEMonitor for( final ItemWatcher iw : list ) { - iw.getHost().onStackChange( this.getStorageList(), fullStack, changedItem, src, this.getChannel() ); + iw.getHost().onStackChange( this.getStorageList(), fullStack, change, src, this.getChannel() ); } this.myGridCache.getInterestManager().disableTransactions(); @@ -283,6 +286,7 @@ public class NetworkMonitor> implements IMEMonitor this.notifyListenersOfChange( changes, src ); final NetworkMonitor last = GLOBAL_DEPTH.pop(); + this.localDepthSemaphore--; if( last != this ) { diff --git a/src/main/java/appeng/me/storage/MEMonitorIInventory.java b/src/main/java/appeng/me/storage/MEMonitorIInventory.java index 50f4a1b2b..dd208f990 100644 --- a/src/main/java/appeng/me/storage/MEMonitorIInventory.java +++ b/src/main/java/appeng/me/storage/MEMonitorIInventory.java @@ -19,12 +19,8 @@ package appeng.me.storage; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; +import java.util.*; import java.util.Map.Entry; -import java.util.NavigableMap; import java.util.concurrent.ConcurrentSkipListMap; import net.minecraft.item.ItemStack; @@ -51,15 +47,15 @@ public class MEMonitorIInventory implements IMEMonitor, ITickingMo private final InventoryAdaptor adaptor; private final IItemList list = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); + private IItemList cache = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); + private final HashMap, Object> listeners = new HashMap<>(); - private final NavigableMap memory; private IActionSource mySource; private StorageFilter mode = StorageFilter.EXTRACTABLE_ONLY; public MEMonitorIInventory( final InventoryAdaptor adaptor ) { this.adaptor = adaptor; - this.memory = new ConcurrentSkipListMap<>(); } @Override @@ -88,11 +84,6 @@ public class MEMonitorIInventory implements IMEMonitor, ITickingMo out = this.adaptor.addItems( input.createItemStack() ); } - if( type == Actionable.MODULATE ) - { - this.onTick(); - } - if( out.isEmpty() ) { return null; @@ -101,6 +92,15 @@ public class MEMonitorIInventory implements IMEMonitor, ITickingMo // better then doing construction from scratch :3 final IAEItemStack o = input.copy(); o.setStackSize( out.getCount() ); + + if( type == Actionable.MODULATE ) + { + IAEItemStack added = o.copy(); + this.cache.add( added ); + this.postDifference( Collections.singletonList( added ) ); + this.onTick(); + } + return o; } @@ -129,6 +129,12 @@ public class MEMonitorIInventory implements IMEMonitor, ITickingMo if( type == Actionable.MODULATE ) { + IAEItemStack cachedStack = this.cache.findPrecise( request ); + if( cachedStack != null ) + { + cachedStack.decStackSize( o.getStackSize() ); + this.postDifference( Collections.singletonList( o.copy().setStackSize( -o.getStackSize() ) ) ); + } this.onTick(); } @@ -144,110 +150,52 @@ public class MEMonitorIInventory implements IMEMonitor, ITickingMo @Override public TickRateModulation onTick() { + boolean changed = false; final List changes = new ArrayList<>(); - this.list.resetStatus(); - int high = 0; - boolean changed = false; - for( final ItemSlot is : this.adaptor ) - { - final CachedItemStack old = this.memory.get( is.getSlot() ); - high = Math.max( high, is.getSlot() ); + IItemList currentlyOnStorage = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); + for( final ItemSlot is : adaptor ) + { final ItemStack newIS = !is.isExtractable() && this.getMode() == StorageFilter.EXTRACTABLE_ONLY ? ItemStack.EMPTY : is.getItemStack(); - final ItemStack oldIS = old == null ? ItemStack.EMPTY : old.itemStack; - - if( this.isDifferent( newIS, oldIS ) ) + if( !newIS.isEmpty() ) { - final CachedItemStack cis = new CachedItemStack( is.getItemStack() ); - this.memory.put( is.getSlot(), cis ); - - if( old != null && old.aeStack != null ) - { - old.aeStack.setStackSize( -old.aeStack.getStackSize() ); - changes.add( old.aeStack ); - } - - if( cis.aeStack != null ) - { - changes.add( cis.aeStack ); - this.list.add( cis.aeStack ); - } - - changed = true; - } - else - { - final int newSize = ( newIS.isEmpty() ? 0 : newIS.getCount() ); - final int diff = newSize - ( oldIS.isEmpty() ? 0 : oldIS.getCount() ); - - final IAEItemStack stack = ( old == null || old.aeStack == null ? AEApi.instance() - .storage() - .getStorageChannel( IItemStorageChannel.class ) - .createStack( newIS ) : old.aeStack.copy() ); - if( stack != null ) - { - stack.setStackSize( newSize ); - this.list.add( stack ); - } - - if( diff != 0 && stack != null ) - { - final CachedItemStack cis = new CachedItemStack( is.getItemStack() ); - this.memory.put( is.getSlot(), cis ); - - final IAEItemStack a = stack.copy(); - a.setStackSize( diff ); - changes.add( a ); - changed = true; - } + currentlyOnStorage.add( is.getAEItemStack() ); } } - // detect dropped items; should fix non IISided Inventory Changes. - final NavigableMap end = this.memory.tailMap( high, false ); - if( !end.isEmpty() ) + for( final IAEItemStack is : cache ) { - for( final CachedItemStack cis : end.values() ) - { - if( cis != null && cis.aeStack != null ) - { - final IAEItemStack a = cis.aeStack.copy(); - a.setStackSize( -a.getStackSize() ); - changes.add( a ); - changed = true; - } - } - end.clear(); + is.setStackSize( -is.getStackSize() ); } + for( final IAEItemStack is : currentlyOnStorage ) + { + cache.add( is ); + } + + for( final IAEItemStack is : cache ) + { + if( is.getStackSize() != 0 ) + { + changes.add( is ); + } + } + + cache = currentlyOnStorage; + if( !changes.isEmpty() ) { this.postDifference( changes ); + changed = true; } return changed ? TickRateModulation.URGENT : TickRateModulation.SLOWER; } - private boolean isDifferent( final ItemStack a, final ItemStack b ) - { - if( a == b && b.isEmpty() ) - { - return false; - } - - if( ( a.isEmpty() && !b.isEmpty() ) || ( !a.isEmpty() && b.isEmpty() ) ) - { - return true; - } - - return !Platform.itemComparisons().isSameItem( a, b ); - } - private void postDifference( final Iterable a ) { - // AELog.info( a.getItemStack().getUnlocalizedName() + " @ " + a.getStackSize() ); if( a != null ) { final Iterator, Object>> i = this.listeners.entrySet().iterator(); @@ -306,9 +254,9 @@ public class MEMonitorIInventory implements IMEMonitor, ITickingMo @Override public IItemList getAvailableItems( final IItemList out ) { - for( final CachedItemStack is : this.memory.values() ) + for( IAEItemStack is : cache ) { - out.addStorage( is.aeStack ); + out.addStorage( is ); } return out; diff --git a/src/main/java/appeng/parts/misc/PartStorageBus.java b/src/main/java/appeng/parts/misc/PartStorageBus.java index f6a780bce..a5049f383 100644 --- a/src/main/java/appeng/parts/misc/PartStorageBus.java +++ b/src/main/java/appeng/parts/misc/PartStorageBus.java @@ -510,17 +510,15 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC this.handlerHash = newHandlerHash; this.handler = null; + if( this.monitor != null ) + { + ( (IBaseMonitor) monitor ).removeListener( this ); + } this.monitor = null; if( target != null ) { IMEInventory inv = this.getInventoryWrapper( target ); - if( inv instanceof MEMonitorIInventory ) - { - final MEMonitorIInventory h = (MEMonitorIInventory) inv; - h.setMode( (StorageFilter) this.getConfigManager().getSetting( Settings.STORAGE_FILTER ) ); - } - if( inv instanceof ITickingMonitor ) { this.monitor = (ITickingMonitor) inv;