diff --git a/gradle.properties b/gradle.properties index 7d93bb7f3..911f52efa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ aechannel=stable aebuild=7 aegroup=appeng aebasename=appliedenergistics2 -trousers=omni-fixes-v43h +trousers=omni-fixes-v45 ######################################################### # Versions # diff --git a/src/api/java/appeng/api/networking/storage/IStackWatcherHost.java b/src/api/java/appeng/api/networking/storage/IStackWatcherHost.java index adcd12f2e..f45bb14cd 100644 --- a/src/api/java/appeng/api/networking/storage/IStackWatcherHost.java +++ b/src/api/java/appeng/api/networking/storage/IStackWatcherHost.java @@ -44,11 +44,8 @@ public interface IStackWatcherHost /** * Called when a watched item changes amounts. * - * @param o changed item list - * @param fullStack old stack * @param diffStack new stack - * @param src action source * @param chan storage channel */ - void onStackChange( IItemList o, IAEStack fullStack, IAEStack diffStack, IActionSource src, IStorageChannel chan ); + void onStackChange( IAEStack diffStack, IStorageChannel chan ); } diff --git a/src/api/java/appeng/api/storage/IMEMonitorHandlerReceiver.java b/src/api/java/appeng/api/storage/IMEMonitorHandlerReceiver.java index c7b0d88a7..ace2d0bc6 100644 --- a/src/api/java/appeng/api/storage/IMEMonitorHandlerReceiver.java +++ b/src/api/java/appeng/api/storage/IMEMonitorHandlerReceiver.java @@ -52,4 +52,5 @@ public interface IMEMonitorHandlerReceiver> * called when the list updates its contents, this is mostly for handling power events. */ void onListUpdate(); + } diff --git a/src/main/java/appeng/fluids/container/ContainerFluidTerminal.java b/src/main/java/appeng/fluids/container/ContainerFluidTerminal.java index 139d4365d..dde53edbc 100644 --- a/src/main/java/appeng/fluids/container/ContainerFluidTerminal.java +++ b/src/main/java/appeng/fluids/container/ContainerFluidTerminal.java @@ -24,6 +24,9 @@ import java.nio.BufferOverflowException; import javax.annotation.Nonnull; +import appeng.container.slot.AppEngSlot; +import appeng.container.slot.SlotPlayerHotBar; +import appeng.container.slot.SlotPlayerInv; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.InventoryPlayer; @@ -70,6 +73,7 @@ import appeng.me.helpers.ChannelPowerSrc; import appeng.util.ConfigManager; import appeng.util.IConfigManagerHost; import appeng.util.Platform; +import net.minecraftforge.items.IItemHandler; /** @@ -342,6 +346,89 @@ public class ContainerFluidTerminal extends AEBaseContainer implements IConfigMa } } + @Override + public ItemStack transferStackInSlot( final EntityPlayer p, final int idx ) + { + if( Platform.isClient() ) + { + return ItemStack.EMPTY; + } + EntityPlayerMP player = (EntityPlayerMP) p; + if( this.inventorySlots.get( idx ) instanceof SlotPlayerInv || this.inventorySlots.get( idx ) instanceof SlotPlayerHotBar ) + { + final AppEngSlot clickSlot = (AppEngSlot) this.inventorySlots.get( idx ); // require AE SLots! + ItemStack itemStack = clickSlot.getStack(); + + ItemStack copy = itemStack.copy(); + copy.setCount( 1 ); + IFluidHandlerItem fh = FluidUtil.getFluidHandler( copy ); + if( fh == null ) + { + // only fluid handlers items + return ItemStack.EMPTY; + } + + int heldAmount = itemStack.getCount(); + for( int i = 0; i < heldAmount; i++ ) + { + copy = itemStack.copy(); + copy.setCount( 1 ); + fh = FluidUtil.getFluidHandler( copy ); + + final FluidStack extract = fh.drain( Integer.MAX_VALUE, false ); + if( extract == null || extract.amount < 1 ) + { + return ItemStack.EMPTY; + } + + // Check if we can push into the system + final IAEFluidStack notStorable = Platform.poweredInsert( this.getPowerSource(), this.monitor, AEFluidStack.fromFluidStack( extract ), this.getActionSource(), Actionable.SIMULATE ); + + if( notStorable != null && notStorable.getStackSize() > 0 ) + { + final int toStore = (int) ( extract.amount - notStorable.getStackSize() ); + final FluidStack storable = fh.drain( toStore, false ); + + if( storable == null || storable.amount == 0 ) + { + return ItemStack.EMPTY; + } + else + { + extract.amount = storable.amount; + } + } + + // Actually drain + final FluidStack drained = fh.drain( extract, true ); + extract.amount = drained.amount; + + final IAEFluidStack notInserted = Platform.poweredInsert( this.getPowerSource(), this.monitor, AEFluidStack.fromFluidStack( extract ), this.getActionSource() ); + + if( notInserted != null && notInserted.getStackSize() > 0 ) + { + IAEFluidStack spill = this.monitor.injectItems( notInserted, Actionable.MODULATE, this.getActionSource() ); + if( spill != null && spill.getStackSize() > 0 ) + { + fh.fill( spill.getFluidStack(), true ); + } + } + + if( notInserted == null ) + { + if( !player.inventory.addItemStackToInventory( fh.getContainer() ) ) + { + player.dropItem( fh.getContainer(), false ); + } + clickSlot.decrStackSize( 1 ); + } + } + this.detectAndSendChanges(); + return ItemStack.EMPTY; + } + return super.transferStackInSlot( p, idx ); + } + @Override public void doAction( EntityPlayerMP player, InventoryAction action, int slot, long id ) { @@ -352,13 +439,9 @@ public class ContainerFluidTerminal extends AEBaseContainer implements IConfigMa } final ItemStack held = player.inventory.getItemStack(); - if( held.getCount() != 1 ) - { - // only support stacksize 1 for now - return; - } - - final IFluidHandlerItem fh = FluidUtil.getFluidHandler( held ); + ItemStack heldCopy = held.copy(); + heldCopy.setCount( 1 ); + IFluidHandlerItem fh = FluidUtil.getFluidHandler( heldCopy ); if( fh == null ) { // only fluid handlers items @@ -372,88 +455,122 @@ public class ContainerFluidTerminal extends AEBaseContainer implements IConfigMa // Check how much we can store in the item stack.setStackSize( Integer.MAX_VALUE ); int amountAllowed = fh.fill( stack.getFluidStack(), false ); - stack.setStackSize( amountAllowed ); - - // Check if we can pull out of the system - final IAEFluidStack canPull = Platform.poweredExtraction( this.getPowerSource(), this.monitor, stack, this.getActionSource(), Actionable.SIMULATE ); - if( canPull == null || canPull.getStackSize() < 1 ) + int heldAmount = held.getCount(); + for( int i = 0; i < heldAmount; i++ ) { - return; - } + ItemStack copiedFluidContainer = held.copy(); + copiedFluidContainer.setCount( 1 ); + fh = FluidUtil.getFluidHandler( copiedFluidContainer ); - // How much could fit into the container - final int canFill = fh.fill( canPull.getFluidStack(), false ); - if( canFill == 0 ) - { - return; - } - - // Now actually pull out of the system - stack.setStackSize( canFill ); - final IAEFluidStack pulled = Platform.poweredExtraction( this.getPowerSource(), this.monitor, stack, this.getActionSource() ); - if( pulled == null || pulled.getStackSize() < 1 ) - { - // Something went wrong - AELog.error( "Unable to pull fluid out of the ME system even though the simulation said yes " ); - return; - } - - // Actually fill - final int used = fh.fill( pulled.getFluidStack(), true ); - - if( used != canFill ) - { - AELog.error( "Fluid item [%s] reported a different possible amount than it actually accepted.", held.getDisplayName() ); - } - - player.inventory.setItemStack( fh.getContainer() ); - this.updateHeld( player ); - } - else if( action == InventoryAction.EMPTY_ITEM ) - { - // See how much we can drain from the item - final FluidStack extract = fh.drain( Integer.MAX_VALUE, false ); - if( extract == null || extract.amount < 1 ) - { - return; - } - - // Check if we can push into the system - final IAEFluidStack notStorable = Platform.poweredInsert( this.getPowerSource(), this.monitor, AEFluidStack.fromFluidStack( extract ), - this.getActionSource(), Actionable.SIMULATE ); - - if( notStorable != null && notStorable.getStackSize() > 0 ) - { - final int toStore = (int) ( extract.amount - notStorable.getStackSize() ); - final FluidStack storable = fh.drain( toStore, false ); - - if( storable == null || storable.amount == 0 ) + // Check if we can pull out of the system + final IAEFluidStack canPull = Platform.poweredExtraction( this.getPowerSource(), this.monitor, stack.setStackSize( amountAllowed ), this.getActionSource(), Actionable.SIMULATE ); + if( canPull == null || canPull.getStackSize() < 1 ) { return; } + + // How much could fit into the container + final int canFill = fh.fill( canPull.getFluidStack(), false ); + if( canFill == 0 ) + { + return; + } + + // Now actually pull out of the system + final IAEFluidStack pulled = Platform.poweredExtraction( this.getPowerSource(), this.monitor, stack.setStackSize( canFill ), this.getActionSource() ); + if( pulled == null || pulled.getStackSize() < 1 ) + { + // Something went wrong + AELog.error( "Unable to pull fluid out of the ME system even though the simulation said yes " ); + return; + } + + // Actually fill + final int used = fh.fill( pulled.getFluidStack(), true ); + + if( used != canFill ) + { + AELog.error( "Fluid item [%s] reported a different possible amount than it actually accepted.", held.getDisplayName() ); + } + + if( held.getCount() == 1 ) + { + player.inventory.setItemStack( fh.getContainer() ); + } else { - extract.amount = storable.amount; + player.inventory.getItemStack().shrink( 1 ); + if( !player.inventory.addItemStackToInventory( fh.getContainer() ) ) + { + player.dropItem( fh.getContainer(), false ); + } } } + this.updateHeld( player ); - // Actually drain - final FluidStack drained = fh.drain( extract, true ); - extract.amount = drained.amount; - - final IAEFluidStack notInserted = Platform.poweredInsert( this.getPowerSource(), this.monitor, AEFluidStack.fromFluidStack( extract ), - this.getActionSource() ); - - if( notInserted != null && notInserted.getStackSize() > 0 ) + } + else if( action == InventoryAction.EMPTY_ITEM ) + { + int heldAmount = held.getCount(); + for( int i = 0; i < heldAmount; i++ ) { - IAEFluidStack spill = this.monitor.injectItems( notInserted, Actionable.MODULATE, this.getActionSource() ); - if( spill != null && spill.getStackSize() > 0 ) + ItemStack copiedFluidContainer = held.copy(); + copiedFluidContainer.setCount( 1 ); + fh = FluidUtil.getFluidHandler( copiedFluidContainer ); + + // See how much we can drain from the item + final FluidStack extract = fh.drain( Integer.MAX_VALUE, false ); + if( extract == null || extract.amount < 1 ) { - fh.fill( spill.getFluidStack(), true ); + return; + } + + // Check if we can push into the system + final IAEFluidStack notStorable = Platform.poweredInsert( this.getPowerSource(), this.monitor, AEFluidStack.fromFluidStack( extract ), this.getActionSource(), Actionable.SIMULATE ); + + if( notStorable != null && notStorable.getStackSize() > 0 ) + { + final int toStore = (int) ( extract.amount - notStorable.getStackSize() ); + final FluidStack storable = fh.drain( toStore, false ); + + if( storable == null || storable.amount == 0 ) + { + return; + } + else + { + extract.amount = storable.amount; + } + } + + // Actually drain + final FluidStack drained = fh.drain( extract, true ); + extract.amount = drained.amount; + + final IAEFluidStack notInserted = Platform.poweredInsert( this.getPowerSource(), this.monitor, AEFluidStack.fromFluidStack( extract ), this.getActionSource() ); + + if( notInserted != null && notInserted.getStackSize() > 0 ) + { + IAEFluidStack spill = this.monitor.injectItems( notInserted, Actionable.MODULATE, this.getActionSource() ); + if( spill != null && spill.getStackSize() > 0 ) + { + fh.fill( spill.getFluidStack(), true ); + } + } + + if( held.getCount() == 1 ) + { + player.inventory.setItemStack( fh.getContainer() ); + } + else + { + player.inventory.getItemStack().shrink( 1 ); + if( !player.inventory.addItemStackToInventory( fh.getContainer() ) ) + { + player.dropItem( fh.getContainer(), false ); + } } } - - player.inventory.setItemStack( fh.getContainer() ); this.updateHeld( player ); } } diff --git a/src/main/java/appeng/fluids/parts/FluidHandlerAdapter.java b/src/main/java/appeng/fluids/parts/FluidHandlerAdapter.java index 6b9738873..6a492b390 100644 --- a/src/main/java/appeng/fluids/parts/FluidHandlerAdapter.java +++ b/src/main/java/appeng/fluids/parts/FluidHandlerAdapter.java @@ -20,7 +20,6 @@ package appeng.fluids.parts; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -28,6 +27,7 @@ import java.util.Map; import appeng.api.config.Settings; import appeng.api.config.StorageFilter; +import appeng.me.GridAccessException; import appeng.parts.misc.PartStorageBus; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -45,7 +45,6 @@ import appeng.api.storage.channels.IFluidStorageChannel; import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IItemList; import appeng.fluids.util.AEFluidStack; -import appeng.me.GridAccessException; import appeng.me.helpers.IGridProxyable; import appeng.me.storage.ITickingMonitor; @@ -123,6 +122,7 @@ public class FluidHandlerAdapter implements IMEInventory, IBaseMo return null; } + IAEFluidStack gatheredAEFluidstack = AEFluidStack.fromFluidStack( gathered ); if( mode == Actionable.MODULATE ) { try @@ -134,7 +134,7 @@ public class FluidHandlerAdapter implements IMEInventory, IBaseMo // meh } } - return AEFluidStack.fromFluidStack( gathered ); + return gatheredAEFluidstack; } @Override @@ -202,9 +202,9 @@ public class FluidHandlerAdapter implements IMEInventory, IBaseMo private static class InventoryCache { - private IAEFluidStack[] cachedAeStacks = new IAEFluidStack[0]; private final IFluidHandler fluidHandler; private final StorageFilter mode; + IItemList currentlyCached = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList(); public InventoryCache( IFluidHandler fluidHandler, StorageFilter mode ) { @@ -216,19 +216,12 @@ public class FluidHandlerAdapter implements IMEInventory, IBaseMo { final List changes = new ArrayList<>(); final IFluidTankProperties[] tankProperties = this.fluidHandler.getTankProperties(); - final int slots = tankProperties.length; - // Make room for new slots - if( slots > this.cachedAeStacks.length ) - { - this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, slots ); - } + IItemList currentlyOnStorage = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList(); - for( int slot = 0; slot < slots; slot++ ) + for( IFluidTankProperties tankProperty : tankProperties ) { - // Save the old stuff - final IAEFluidStack oldAEFS = this.cachedAeStacks[slot]; - FluidStack newFS = tankProperties[slot].getContents(); + FluidStack newFS = tankProperty.getContents(); if( this.mode == StorageFilter.EXTRACTABLE_ONLY && newFS != null ) { if( this.fluidHandler.drain( 1, false ) == null ) @@ -236,82 +229,40 @@ public class FluidHandlerAdapter implements IMEInventory, IBaseMo newFS = null; } } - this.handlePossibleSlotChanges( slot, oldAEFS, newFS, changes ); - } - - // Handle cases where the number of slots actually is lower now than before - if( slots < this.cachedAeStacks.length ) - { - for( int slot = slots; slot < this.cachedAeStacks.length; slot++ ) + if( newFS != null ) { - final IAEFluidStack aeStack = this.cachedAeStacks[slot]; - - if( aeStack != null ) - { - final IAEFluidStack a = aeStack.copy(); - a.setStackSize( -a.getStackSize() ); - changes.add( a ); - } + currentlyOnStorage.add( AEFluidStack.fromFluidStack( newFS ) ); } - - this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, slots ); } + + for ( final IAEFluidStack is : currentlyCached ) + { + is.setStackSize( -is.getStackSize() ); + } + + for ( final IAEFluidStack is : currentlyOnStorage ) + { + currentlyCached.add( is ); + } + + for ( final IAEFluidStack is : currentlyCached ) + { + if( is.getStackSize() != 0 ) + { + changes.add( is ); + } + } + + currentlyCached = currentlyOnStorage; + return changes; } public IItemList getAvailableItems( IItemList out ) { - Arrays.stream( this.cachedAeStacks ).forEach( out::add ); + currentlyCached.iterator().forEachRemaining( out::add ); return out; } - private void handlePossibleSlotChanges( int slot, IAEFluidStack oldAeFS, FluidStack newFS, List changes ) - { - if( oldAeFS != null && oldAeFS.getFluidStack().isFluidEqual( newFS ) ) - { - this.handleStackSizeChanged( slot, oldAeFS, newFS, changes ); - } - else - { - this.handleFluidChanged( slot, oldAeFS, newFS, changes ); - } - } - - private void handleStackSizeChanged( int slot, IAEFluidStack oldAeFS, FluidStack newFS, List changes ) - { - // Still the same fluid, but amount might have changed - final long diff = newFS.amount - oldAeFS.getStackSize(); - - if( diff != 0 ) - { - final IAEFluidStack stack = oldAeFS.copy(); - stack.setStackSize( newFS.amount ); - - this.cachedAeStacks[slot] = stack; - - final IAEFluidStack a = stack.copy(); - a.setStackSize( diff ); - changes.add( a ); - } - } - - private void handleFluidChanged( int slot, IAEFluidStack oldAeFS, FluidStack newFS, List changes ) - { - // Completely different fluid - this.cachedAeStacks[slot] = AEFluidStack.fromFluidStack( newFS ); - - // If we had a stack previously in this slot, notify the network about its disappearance - if( oldAeFS != null ) - { - oldAeFS.setStackSize( -oldAeFS.getStackSize() ); - changes.add( oldAeFS ); - } - - // Notify the network about the new stack. Note that this is null if newFS was null - if( this.cachedAeStacks[slot] != null ) - { - changes.add( this.cachedAeStacks[slot] ); - } - } } } diff --git a/src/main/java/appeng/fluids/parts/PartFluidLevelEmitter.java b/src/main/java/appeng/fluids/parts/PartFluidLevelEmitter.java index b51f1afb4..f8e2fb344 100644 --- a/src/main/java/appeng/fluids/parts/PartFluidLevelEmitter.java +++ b/src/main/java/appeng/fluids/parts/PartFluidLevelEmitter.java @@ -4,7 +4,9 @@ package appeng.fluids.parts; import java.util.Random; +import appeng.api.networking.events.MENetworkChannelChanged; import appeng.fluids.helper.IConfigurableFluidInventory; +import appeng.me.cache.NetworkMonitor; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -34,7 +36,6 @@ import appeng.api.storage.IStorageChannel; import appeng.api.storage.channels.IFluidStorageChannel; import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IAEStack; -import appeng.api.storage.data.IItemList; import appeng.api.util.AECableType; import appeng.api.util.AEPartLocation; import appeng.api.util.IConfigManager; @@ -112,11 +113,11 @@ public class PartFluidLevelEmitter extends PartUpgradeable implements IStackWatc } @Override - public void onStackChange( IItemList o, IAEStack fullStack, IAEStack diffStack, IActionSource src, IStorageChannel chan ) + public void onStackChange( IAEStack diffStack, IStorageChannel chan ) { - if( chan == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) && fullStack.equals( this.config.getFluidInSlot( 0 ) ) ) + if( chan == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) && diffStack.equals( this.config.getFluidInSlot( 0 ) ) ) { - this.lastReportedValue = fullStack.getStackSize(); + this.lastReportedValue += diffStack.getStackSize(); this.updateState(); } } @@ -128,14 +129,22 @@ public class PartFluidLevelEmitter extends PartUpgradeable implements IStackWatc } @MENetworkEventSubscribe - public void channelChanged( final MENetworkChannelsChanged c ) + public void powerStatusChange( final MENetworkPowerStatusChange powerEvent ) { + if (this.getProxy().isActive()) + { + onListUpdate(); + } this.updateState(); } @MENetworkEventSubscribe - public void powerChanged( final MENetworkPowerStatusChange c ) + public void channelChanged( final MENetworkChannelsChanged c ) { + if (this.getProxy().isActive()) + { + onListUpdate(); + } this.updateState(); } @@ -247,10 +256,9 @@ public class PartFluidLevelEmitter extends PartUpgradeable implements IStackWatc if( myStack == null ) { - this.lastReportedValue = 0; - for( final IAEFluidStack st : monitor.getStorageList() ) + if( monitor instanceof NetworkMonitor ) { - this.lastReportedValue += st.getStackSize(); + this.lastReportedValue = ( (NetworkMonitor) monitor ).getGridCurrentCount(); } } else diff --git a/src/main/java/appeng/fluids/parts/PartFluidStorageBus.java b/src/main/java/appeng/fluids/parts/PartFluidStorageBus.java index a32c9b95a..d1c0567e9 100644 --- a/src/main/java/appeng/fluids/parts/PartFluidStorageBus.java +++ b/src/main/java/appeng/fluids/parts/PartFluidStorageBus.java @@ -264,7 +264,7 @@ public class PartFluidStorageBus extends PartSharedStorageBus implements IMEMoni @Override public void postChange( final IBaseMonitor monitor, final Iterable change, final IActionSource source ) { - if( source == this.source || source.machine().map( machine -> machine == this ).orElse( false ) ) + if( this.source == source || this.source.machine().map( machine -> machine == this ).orElse( false ) ) { try { @@ -272,8 +272,7 @@ public class PartFluidStorageBus extends PartSharedStorageBus implements IMEMoni { this.getProxy().getStorage().postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ), change, this.source ); } - } - catch( final GridAccessException e ) + } catch ( final GridAccessException e ) { // :( } @@ -415,7 +414,7 @@ public class PartFluidStorageBus extends PartSharedStorageBus implements IMEMoni { if( channel == this.getStorageChannel() ) { - final IMEInventoryHandler out = this.getProxy().isActive() ? this.getInternalHandler() : null; + final IMEInventoryHandler out = this.getInternalHandler(); if( out != null ) { return Collections.singletonList( out ); diff --git a/src/main/java/appeng/me/cache/NetworkMonitor.java b/src/main/java/appeng/me/cache/NetworkMonitor.java index 306eaba21..3a26fa325 100644 --- a/src/main/java/appeng/me/cache/NetworkMonitor.java +++ b/src/main/java/appeng/me/cache/NetworkMonitor.java @@ -19,20 +19,10 @@ package appeng.me.cache; -import java.util.Collection; -import java.util.Deque; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; - import javax.annotation.Nonnegative; import javax.annotation.Nonnull; import javax.annotation.Nullable; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Queues; - +import appeng.api.AEApi; import appeng.api.config.AccessRestriction; import appeng.api.config.Actionable; import appeng.api.networking.events.MENetworkStorageEvent; @@ -41,12 +31,20 @@ import appeng.api.storage.IMEInventoryHandler; import appeng.api.storage.IMEMonitor; import appeng.api.storage.IMEMonitorHandlerReceiver; import appeng.api.storage.IStorageChannel; +import appeng.api.storage.channels.IFluidStorageChannel; +import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IItemList; import appeng.me.storage.ItemWatcher; +import com.google.common.collect.Queues; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import java.util.Collection; +import java.util.Deque; +import java.util.Iterator; +import java.util.Map.Entry; + public class NetworkMonitor> implements IMEMonitor { @@ -63,9 +61,11 @@ public class NetworkMonitor> implements IMEMonitor private final Object2ObjectMap, Object> listeners; private boolean sendEvent = false; - private boolean hasChanged = false; + private boolean forceUpdate = false; @Nonnegative private int localDepthSemaphore = 0; + private long gridItemCount; + private long gridFluidCount; public NetworkMonitor( final GridStorageCache cache, final IStorageChannel chan ) { @@ -90,21 +90,7 @@ public class NetworkMonitor> implements IMEMonitor @Override public T extractItems( final T request, final Actionable mode, final IActionSource src ) { - if( mode == Actionable.SIMULATE ) - { - return this.getHandler().extractItems( request, mode, src ); - } - - this.localDepthSemaphore++; - final T leftover = this.getHandler().extractItems( request, mode, src ); - this.localDepthSemaphore--; - - if( this.localDepthSemaphore == 0 ) - { - this.monitorDifference( request.copy(), leftover, true, src ); - } - - return leftover; + return this.getHandler().extractItems( request, mode, src ); } @Override @@ -137,13 +123,39 @@ public class NetworkMonitor> implements IMEMonitor return this.getHandler().getSlot(); } + public long getGridCurrentCount() + { + if( myChannel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) + { + return gridItemCount; + } + else if( myChannel == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ) + { + return gridFluidCount; + } + return 0; + } + + public long incGridCurrentCount(long count) + { + if( myChannel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) + { + return gridItemCount += count; + } + else if( myChannel == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ) + { + return gridFluidCount += count; + } + return 0; + } + @Nonnull @Override public IItemList getStorageList() { - if( hasChanged ) + if( forceUpdate ) { - hasChanged = false; + forceUpdate = false; this.cachedList.resetStatus(); return this.getAvailableItems( this.cachedList ); } @@ -154,21 +166,7 @@ public class NetworkMonitor> implements IMEMonitor @Override public T injectItems( final T input, final Actionable mode, final IActionSource src ) { - if( mode == Actionable.SIMULATE ) - { - return this.getHandler().injectItems( input, mode, src ); - } - - this.localDepthSemaphore++; - final T leftover = this.getHandler().injectItems( input, mode, src ); - this.localDepthSemaphore--; - - if( this.localDepthSemaphore == 0 ) - { - this.monitorDifference( input.copy(), leftover, false, src ); - } - - return leftover; + return this.getHandler().injectItems( input, mode, src ); } @Override @@ -200,30 +198,8 @@ public class NetworkMonitor> implements IMEMonitor return this.listeners.entrySet().iterator(); } - private T monitorDifference( final IAEStack original, final T leftOvers, final boolean extraction, final IActionSource src ) - { - final T diff = original.copy(); - - if( extraction ) - { - diff.setStackSize( leftOvers == null ? 0 : -leftOvers.getStackSize() ); - } - else if( leftOvers != null ) - { - diff.decStackSize( leftOvers.getStackSize() ); - } - - if( diff.getStackSize() != 0 ) - { - this.postChangesToListeners( ImmutableList.of( diff ), src ); - } - - return leftOvers; - } - private void notifyListenersOfChange( final Iterable diff, final IActionSource src ) { - this.hasChanged = true; final Iterator, Object>> i = this.getListeners(); while( i.hasNext() ) @@ -241,54 +217,38 @@ public class NetworkMonitor> implements IMEMonitor } } - private void postChangesToListeners( final Iterable changes, final IActionSource src ) - { - this.postChange( true, changes, src ); - } - protected void postChange( final boolean add, final Iterable changes, final IActionSource src ) { - if( this.localDepthSemaphore > 0 || GLOBAL_DEPTH.contains( this ) ) + if ( GLOBAL_DEPTH.contains( this )) { return; } GLOBAL_DEPTH.push( this ); - this.localDepthSemaphore++; this.sendEvent = true; - this.notifyListenersOfChange( changes, src ); - - for( final T changedItem : changes ) + for ( final T changedItem : changes ) { - T difference = changedItem; - if( !add && changedItem != null ) { - difference = changedItem.copy(); - difference.setStackSize( -changedItem.getStackSize() ); + changedItem.setStackSize( -changedItem.getStackSize() ); } + incGridCurrentCount( changedItem.getStackSize() ); + this.cachedList.add( changedItem ); + if( this.myGridCache.getInterestManager().containsKey( changedItem ) ) { final Collection list = this.myGridCache.getInterestManager().get( changedItem ); if( !list.isEmpty() ) { - IAEStack fullStack = this.getStorageList().findPrecise( changedItem ); - - if( fullStack == null ) - { - fullStack = changedItem.copy(); - fullStack.setStackSize( 0 ); - } - this.myGridCache.getInterestManager().enableTransactions(); for( final ItemWatcher iw : list ) { - iw.getHost().onStackChange( this.getStorageList(), fullStack, difference, src, this.getChannel() ); + iw.getHost().onStackChange( changedItem, this.getChannel() ); } this.myGridCache.getInterestManager().disableTransactions(); @@ -296,8 +256,9 @@ public class NetworkMonitor> implements IMEMonitor } } + this.notifyListenersOfChange( changes, src ); + final NetworkMonitor last = GLOBAL_DEPTH.pop(); - this.localDepthSemaphore--; if( last != this ) { @@ -307,10 +268,10 @@ public class NetworkMonitor> implements IMEMonitor void forceUpdate() { - this.hasChanged = true; + this.forceUpdate = true; final Iterator, Object>> i = this.getListeners(); - while( i.hasNext() ) + while ( i.hasNext() ) { final Entry, Object> o = i.next(); final IMEMonitorHandlerReceiver receiver = o.getKey(); @@ -333,5 +294,6 @@ public class NetworkMonitor> implements IMEMonitor this.sendEvent = false; this.myGridCache.getGrid().postEvent( new MENetworkStorageEvent( this, this.myChannel ) ); } + } } diff --git a/src/main/java/appeng/me/cache/TickManagerCache.java b/src/main/java/appeng/me/cache/TickManagerCache.java index 10dac7c49..bf258125c 100644 --- a/src/main/java/appeng/me/cache/TickManagerCache.java +++ b/src/main/java/appeng/me/cache/TickManagerCache.java @@ -138,7 +138,6 @@ public class TickManagerCache implements ITickManager tt.addEntityCrashInfo( crashreportcategory ); throw new ReportedException( crashreport ); } - PartLevelEmitter.wipeCache(); } private void addToQueue( final TickTracker tt ) diff --git a/src/main/java/appeng/me/helpers/GenericInterestManager.java b/src/main/java/appeng/me/helpers/GenericInterestManager.java index 1439c3424..bcd87ba66 100644 --- a/src/main/java/appeng/me/helpers/GenericInterestManager.java +++ b/src/main/java/appeng/me/helpers/GenericInterestManager.java @@ -23,9 +23,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import com.google.common.collect.Multimap; - +import appeng.api.config.FuzzyMode; import appeng.api.storage.data.IAEStack; +import appeng.util.item.AEItemStack; +import com.google.common.collect.Multimap; public class GenericInterestManager @@ -101,12 +102,30 @@ public class GenericInterestManager public boolean containsKey( final IAEStack stack ) { + if( stack.isItem() && ( ( AEItemStack ) stack ).getItem().isDamageable() ) + { + return this.container.keySet().stream().filter( s -> s.isItem() ) + .anyMatch( s -> s.fuzzyComparison( stack, FuzzyMode.IGNORE_ALL ) ); + } return this.container.containsKey( stack ); } public Collection get( final IAEStack stack ) { - return this.container.get( stack ); + Collection watchers = new ArrayList<>(); + if( stack.isItem() && ( ( AEItemStack ) stack ).getItem().isDamageable() ) + { + this.container.keySet().stream().filter( s -> s.isItem() ) + .filter( k -> k.fuzzyComparison( stack, FuzzyMode.IGNORE_ALL ) ) + .forEach( key -> + watchers.addAll( this.container.get( key ) ) + ); + } + else + { + return this.container.get( stack ); + } + return watchers; } private class SavedTransactions diff --git a/src/main/java/appeng/me/storage/DriveWatcher.java b/src/main/java/appeng/me/storage/DriveWatcher.java index 073b9fb19..2c6423203 100644 --- a/src/main/java/appeng/me/storage/DriveWatcher.java +++ b/src/main/java/appeng/me/storage/DriveWatcher.java @@ -19,6 +19,10 @@ package appeng.me.storage; +import appeng.me.GridAccessException; +import appeng.me.helpers.MachineSource; +import appeng.tile.storage.TileDrive; +import com.google.common.collect.ImmutableList; import net.minecraft.item.ItemStack; import appeng.api.config.Actionable; @@ -36,6 +40,7 @@ public class DriveWatcher> extends MEInventoryHandler private final ItemStack is; private final ICellHandler handler; private final IChestOrDrive cord; + private IActionSource source; public DriveWatcher( final ICellInventoryHandler i, final ItemStack is, final ICellHandler han, final IChestOrDrive cod ) { @@ -43,6 +48,7 @@ public class DriveWatcher> extends MEInventoryHandler this.is = is; this.handler = han; this.cord = cod; + this.source = new MachineSource( cod ); } public int getStatus() @@ -66,6 +72,14 @@ public class DriveWatcher> extends MEInventoryHandler this.cord.blinkCell( this.getSlot() ); this.oldStatus = newStatus; } + try + { + ( (TileDrive) this.cord ).getProxy().getStorage().postAlterationOfStoredItems( this.getChannel(), ImmutableList.of( input.copy().setStackSize( input.getStackSize() - ( a == null ? 0 : a.getStackSize() ) ) ), this.source ); + } + catch( GridAccessException e ) + { + e.printStackTrace(); + } } return a; @@ -85,6 +99,15 @@ public class DriveWatcher> extends MEInventoryHandler this.cord.blinkCell( this.getSlot() ); this.oldStatus = newStatus; } + + try + { + ( (TileDrive) this.cord ).getProxy().getStorage().postAlterationOfStoredItems( this.getChannel(), ImmutableList.of( request.copy().setStackSize( -a.getStackSize() ) ), this.source ); + } + catch( GridAccessException e ) + { + e.printStackTrace(); + } } return a; diff --git a/src/main/java/appeng/me/storage/MEMonitorPassThrough.java b/src/main/java/appeng/me/storage/MEMonitorPassThrough.java index 4c189eaf2..23694e9bf 100644 --- a/src/main/java/appeng/me/storage/MEMonitorPassThrough.java +++ b/src/main/java/appeng/me/storage/MEMonitorPassThrough.java @@ -72,7 +72,7 @@ public class MEMonitorPassThrough> extends MEPassThrough after = this.getInternal() == null ? this.getWrappedChannel().createList() : this.getInternal() .getAvailableItems( new ItemListIgnoreCrafting( this.getWrappedChannel().createList() ) ); - if( this.monitor != null ) + if( this.monitor != null && this.listeners.size() > 0 ) { this.monitor.addListener( this, this.monitor ); } @@ -90,6 +90,13 @@ public class MEMonitorPassThrough> extends MEPassThrough l, final Object verificationToken ) { + if( this.listeners.size() == 0 ) + { + if( this.monitor != null ) + { + this.monitor.addListener( this, this.monitor ); + } + } this.listeners.put( l, verificationToken ); } diff --git a/src/main/java/appeng/parts/automation/PartLevelEmitter.java b/src/main/java/appeng/parts/automation/PartLevelEmitter.java index ab4899152..9993a0518 100644 --- a/src/main/java/appeng/parts/automation/PartLevelEmitter.java +++ b/src/main/java/appeng/parts/automation/PartLevelEmitter.java @@ -19,40 +19,9 @@ package appeng.parts.automation; -import java.util.Random; - -import appeng.me.Grid; -import appeng.me.GridNode; -import appeng.util.item.AEItemStack; -import it.unimi.dsi.fastutil.objects.Object2LongMap; -import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.inventory.InventoryCrafting; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumHand; -import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; -import net.minecraftforge.items.IItemHandler; - import appeng.api.AEApi; -import appeng.api.config.FuzzyMode; -import appeng.api.config.LevelType; -import appeng.api.config.RedstoneMode; -import appeng.api.config.Settings; -import appeng.api.config.Upgrades; -import appeng.api.config.YesNo; -import appeng.api.networking.crafting.ICraftingGrid; -import appeng.api.networking.crafting.ICraftingPatternDetails; -import appeng.api.networking.crafting.ICraftingProvider; -import appeng.api.networking.crafting.ICraftingProviderHelper; -import appeng.api.networking.crafting.ICraftingWatcher; -import appeng.api.networking.crafting.ICraftingWatcherHost; +import appeng.api.config.*; +import appeng.api.networking.crafting.*; import appeng.api.networking.energy.IEnergyGrid; import appeng.api.networking.energy.IEnergyWatcher; import appeng.api.networking.energy.IEnergyWatcherHost; @@ -72,7 +41,6 @@ import appeng.api.storage.IStorageChannel; import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEStack; -import appeng.api.storage.data.IItemList; import appeng.api.util.AECableType; import appeng.api.util.AEPartLocation; import appeng.api.util.IConfigManager; @@ -81,10 +49,28 @@ import appeng.core.sync.GuiBridge; import appeng.helpers.Reflected; import appeng.items.parts.PartModels; import appeng.me.GridAccessException; +import appeng.me.cache.NetworkMonitor; import appeng.parts.PartModel; import appeng.tile.inventory.AppEngInternalAEInventory; import appeng.util.Platform; import appeng.util.inv.InvOperation; +import appeng.util.item.OreHelper; +import appeng.util.item.OreReference; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumHand; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.items.IItemHandler; + +import java.util.Optional; +import java.util.Random; public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherHost, IStackWatcherHost, ICraftingWatcherHost, IMEMonitorHandlerReceiver, ICraftingProvider @@ -123,9 +109,6 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH private double centerX; private double centerY; private double centerZ; - static Object2LongMap gridItemCount = new Object2LongOpenHashMap<>(); - static Object2ObjectOpenHashMap> fuzzyAEItemStackCount = new Object2ObjectOpenHashMap<>(); - static Object2ObjectOpenHashMap> preciseAEItemStackCount = new Object2ObjectOpenHashMap<>(); @Reflected public PartLevelEmitter( final ItemStack is ) @@ -156,12 +139,6 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH } } - @MENetworkEventSubscribe - public void powerChanged( final MENetworkPowerStatusChange c ) - { - this.updateState(); - } - private void updateState() { final boolean isOn = this.isLevelEmitterOn(); @@ -206,9 +183,23 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH return flipState ? this.reportingValue >= this.lastReportedValue + 1 : this.reportingValue < this.lastReportedValue + 1; } + @MENetworkEventSubscribe + public void powerStatusChange( final MENetworkPowerStatusChange powerEvent ) + { + if (this.getProxy().isActive()) + { + onListUpdate(); + } + this.updateState(); + } + @MENetworkEventSubscribe public void channelChanged( final MENetworkChannelsChanged c ) { + if (this.getProxy().isActive()) + { + onListUpdate(); + } this.updateState(); } @@ -296,24 +287,37 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH try { - if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 || myStack == null ) + + if( myStack == null ) { - this.getProxy() - .getStorage() - .getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) - .addListener( this, - this.getProxy().getGrid() ); + this.getProxy().getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ).addListener( this, this.getProxy().getGrid() ); } else { this.getProxy().getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ).removeListener( this ); - if( this.myWatcher != null ) { - this.myWatcher.add( myStack ); + if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 ) + { + Optional ores = OreHelper.INSTANCE.getOre( myStack.getDefinition() ); + if( ores.isPresent() ) + { + for( IAEItemStack iaeItemStack : ores.get().getAEEquivalents() ) + { + this.myWatcher.add( iaeItemStack ); + } + } + else + { + this.myWatcher.add( myStack ); + } + } + else + { + this.myWatcher.add( myStack ); + } } } - this.updateReportingValue( this.getProxy().getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) ); } catch( final GridAccessException e ) @@ -323,90 +327,29 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH } private void updateReportingValue( final IMEMonitor monitor ) - { - updateReportingValue( monitor,null ); - } - - private void updateReportingValue( final IMEMonitor monitor, Iterable change ) { final IAEItemStack myStack = this.config.getAEStackInSlot( 0 ); - GridNode node = (GridNode) (this.getGridNode()); - - if( node != null ) + if( myStack == null ) { - - final Grid g = node.getInternalGrid(); - - if( myStack == null ) + if( monitor instanceof NetworkMonitor ) { - if( change != null ) - { - if( gridItemCount.containsKey( g ) ) - { - change.forEach( iaeItemStack -> lastReportedValue += iaeItemStack.getStackSize() ); - } - } - gridItemCount.computeIfAbsent( g, ( aLong ) -> { - this.lastReportedValue = 0; - monitor.getStorageList().forEach( iaeItemStack -> lastReportedValue += iaeItemStack.getStackSize() ); - return ( lastReportedValue ); - } ); - this.lastReportedValue = gridItemCount.get( g ); + this.lastReportedValue = ( (NetworkMonitor) monitor ).getGridCurrentCount(); } + } - else if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 ) - { - final FuzzyMode fzMode = (FuzzyMode) this.getConfigManager().getSetting( Settings.FUZZY_MODE ); - if( change != null ) - { - if( fuzzyAEItemStackCount.containsKey( g ) ) - { - change.forEach( iaeItemStack -> { - if( iaeItemStack.sameOre( myStack ) ) lastReportedValue += iaeItemStack.getStackSize(); - } ); - } - } + else if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 ) + { + final FuzzyMode fzMode = (FuzzyMode) this.getConfigManager().getSetting( Settings.FUZZY_MODE ); - fuzzyAEItemStackCount.computeIfAbsent( g, ( grid -> new Object2LongOpenHashMap<>() ) ); - fuzzyAEItemStackCount.get( g ).computeIfAbsent( (AEItemStack) myStack, ( aLong -> { - this.lastReportedValue = 0; - monitor.getStorageList().findFuzzy( myStack, fzMode ).forEach( iaeItemStack -> lastReportedValue += iaeItemStack.getStackSize() ); - return ( lastReportedValue ); - } ) ); - - this.lastReportedValue = fuzzyAEItemStackCount.get( g ).get( myStack ); - if( this.lastReportedValue == 0 ) - { - fuzzyAEItemStackCount.get( g ).remove( myStack ); - fuzzyAEItemStackCount.trim(); - } - } - else - { - if( change != null ) - { - if( preciseAEItemStackCount.containsKey( g ) ) - { - change.forEach( iaeItemStack -> { - if( iaeItemStack.isSameType( myStack ) ) lastReportedValue += iaeItemStack.getStackSize(); - } ); - } - } - preciseAEItemStackCount.computeIfAbsent( g, ( grid -> new Object2LongOpenHashMap<>() ) ); - preciseAEItemStackCount.get( g ).computeIfAbsent( (AEItemStack) myStack, ( aLong -> { - this.lastReportedValue = 0; - IAEItemStack precise = monitor.getStorageList().findPrecise( myStack ); - if( precise != null ) lastReportedValue = precise.getStackSize(); - return ( lastReportedValue ); - } ) ); - this.lastReportedValue = preciseAEItemStackCount.get( g ).get( myStack ); - if( this.lastReportedValue == 0 ) - { - preciseAEItemStackCount.get( g ).remove( myStack ); - preciseAEItemStackCount.trim(); - } - } + this.lastReportedValue = 0; + monitor.getStorageList().findFuzzy( myStack, fzMode ).forEach( iaeItemStack -> lastReportedValue += iaeItemStack.getStackSize() ); + } + else + { + this.lastReportedValue = 0; + IAEItemStack precise = monitor.getStorageList().findPrecise( myStack ); + if( precise != null ) lastReportedValue = precise.getStackSize(); } this.updateState(); } @@ -419,12 +362,23 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH } @Override - public void onStackChange( final IItemList o, final IAEStack fullStack, final IAEStack diffStack, final IActionSource src, final IStorageChannel chan ) + public void onStackChange( final IAEStack diffStack, final IStorageChannel chan ) { - if( chan == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) && fullStack.equals( this.config.getAEStackInSlot( 0 ) ) && this - .getInstalledUpgrades( Upgrades.FUZZY ) == 0 ) + if( chan == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) { - this.lastReportedValue = fullStack.getStackSize(); + IAEItemStack myStack = this.config.getAEStackInSlot( 0 ); + if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 ) + { + final FuzzyMode fzMode = (FuzzyMode) this.getConfigManager().getSetting( Settings.FUZZY_MODE ); + if( Platform.itemComparisons().isFuzzyEqualItem( myStack.getDefinition(), ( (IAEItemStack) diffStack ).getDefinition(), fzMode ) ) + { + this.lastReportedValue += diffStack.getStackSize(); + } + } + else if( diffStack.equals( myStack ) ) + { + this.lastReportedValue += diffStack.getStackSize(); + } this.updateState(); } } @@ -459,7 +413,7 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH @Override public void postChange( final IBaseMonitor monitor, final Iterable change, final IActionSource actionSource ) { - this.updateReportingValue( (IMEMonitor) monitor, change ); + this.updateReportingValue( (IMEMonitor) monitor ); } @Override @@ -636,9 +590,4 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH } } - public static void wipeCache(){ - fuzzyAEItemStackCount.clear(); - preciseAEItemStackCount.clear(); - gridItemCount.clear(); - } } diff --git a/src/main/java/appeng/parts/misc/ItemHandlerAdapter.java b/src/main/java/appeng/parts/misc/ItemHandlerAdapter.java index 6e398cb5f..545fe05d1 100644 --- a/src/main/java/appeng/parts/misc/ItemHandlerAdapter.java +++ b/src/main/java/appeng/parts/misc/ItemHandlerAdapter.java @@ -44,7 +44,6 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.item.ItemStack; import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemHandlerHelper; import java.util.*; @@ -83,6 +82,8 @@ class ItemHandlerAdapter implements IMEInventory, IBaseMonitor, IBaseMonitor, IBaseMonitor, IBaseMonitor, IBaseMonitor, IBaseMonitor { - private IAEItemStack[] cachedAeStacks = new IAEItemStack[0]; private final IItemHandler itemHandler; private final StorageFilter mode; + IItemList currentlyCached = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); public InventoryCache( IItemHandler itemHandler, StorageFilter mode ) { @@ -286,7 +293,7 @@ class ItemHandlerAdapter implements IMEInventory, IBaseMonitor getAvailableItems( IItemList out ) { - Arrays.stream( this.cachedAeStacks ).forEach( out::add ); + currentlyCached.iterator().forEachRemaining( out::add ); return out; } @@ -298,93 +305,41 @@ class ItemHandlerAdapter implements IMEInventory, IBaseMonitor update() { final List changes = new ArrayList<>(); - final int slots = this.itemHandler.getSlots(); - // Make room for new slots - if( slots > this.cachedAeStacks.length ) - { - this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, slots ); - } + IItemList currentlyOnStorage = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); - for( final ItemSlot is : this ) + for ( final ItemSlot is : this ) { - // Save the old stuff - final IAEItemStack oldAeIS = this.cachedAeStacks[is.getSlot()]; final ItemStack newIS = !is.isExtractable() && this.getMode() == StorageFilter.EXTRACTABLE_ONLY ? ItemStack.EMPTY : is.getItemStack(); - - this.handlePossibleSlotChanges( is.getSlot(), oldAeIS, newIS, changes ); - } - // Handle cases where the number of slots actually is lower now than before - if( slots < this.cachedAeStacks.length ) - { - for( int slot = slots; slot < this.cachedAeStacks.length; slot++ ) + if( !newIS.isEmpty() ) { - final IAEItemStack aeStack = this.cachedAeStacks[slot]; - - if( aeStack != null ) - { - final IAEItemStack a = aeStack.copy(); - a.setStackSize( -a.getStackSize() ); - changes.add( a ); - } + currentlyOnStorage.add( is.getAEItemStack() ); } - - // Reduce the cache size - this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, slots ); } + for ( final IAEItemStack is : currentlyCached ) + { + is.setStackSize( -is.getStackSize() ); + } + + for ( final IAEItemStack is : currentlyOnStorage ) + { + currentlyCached.add( is ); + } + + for ( final IAEItemStack is : currentlyCached ) + { + if( is.getStackSize() != 0 ) + { + changes.add( is ); + } + } + + currentlyCached = currentlyOnStorage; + return changes; } - private void handlePossibleSlotChanges( int slot, IAEItemStack oldAeIS, ItemStack newIS, List changes ) - { - if( oldAeIS != null && oldAeIS.isSameType( newIS ) ) - { - this.handleStackSizeChanged( slot, oldAeIS, newIS, changes ); - } - else - { - this.handleItemChanged( slot, oldAeIS, newIS, changes ); - } - } - - private void handleStackSizeChanged( int slot, IAEItemStack oldAeIS, ItemStack newIS, List changes ) - { - // Still the same item, but amount might have changed - final long diff = newIS.getCount() - oldAeIS.getStackSize(); - - if( diff != 0 ) - { - final IAEItemStack stack = oldAeIS.copy(); - stack.setStackSize( newIS.getCount() ); - - this.cachedAeStacks[slot] = stack; - - final IAEItemStack a = stack.copy(); - a.setStackSize( diff ); - changes.add( a ); - } - } - - private void handleItemChanged( int slot, IAEItemStack oldAeIS, ItemStack newIS, List changes ) - { - // Completely different item - this.cachedAeStacks[slot] = AEItemStack.fromItemStack( newIS ); - - // If we had a stack previously in this slot, notify the network about its disappearance - if( oldAeIS != null ) - { - oldAeIS.setStackSize( -oldAeIS.getStackSize() ); - changes.add( oldAeIS ); - } - - // Notify the network about the new stack. Note that this is null if newIS was null - if( this.cachedAeStacks[slot] != null ) - { - changes.add( this.cachedAeStacks[slot] ); - } - } - @Override public Iterator iterator() { diff --git a/src/main/java/appeng/parts/misc/ItemRepositoryAdapter.java b/src/main/java/appeng/parts/misc/ItemRepositoryAdapter.java index 02724c9f0..157a66e3f 100644 --- a/src/main/java/appeng/parts/misc/ItemRepositoryAdapter.java +++ b/src/main/java/appeng/parts/misc/ItemRepositoryAdapter.java @@ -24,7 +24,6 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.item.ItemStack; import java.util.*; -import java.util.stream.Collectors; /** @@ -102,7 +101,7 @@ class ItemRepositoryAdapter implements IMEInventory, IBaseMonitor< @Override public IAEItemStack extractItems( IAEItemStack request, Actionable mode, IActionSource src ) { - int remainingSize = Ints.saturatedCast(request.getStackSize()); + int remainingSize = Ints.saturatedCast( request.getStackSize() ); final boolean simulate = ( mode == Actionable.SIMULATE ); @@ -119,6 +118,7 @@ class ItemRepositoryAdapter implements IMEInventory, IBaseMonitor< if( !extracted.isEmpty() ) { + IAEItemStack extractedAEItemStack = AEItemStack.fromItemStack( extracted ); if( mode == Actionable.MODULATE ) { try @@ -130,7 +130,7 @@ class ItemRepositoryAdapter implements IMEInventory, IBaseMonitor< // meh } } - return AEItemStack.fromItemStack( extracted ); + return extractedAEItemStack; } return null; } @@ -202,7 +202,7 @@ class ItemRepositoryAdapter implements IMEInventory, IBaseMonitor< private static class InventoryCache { - private IAEItemStack[] cachedAeStacks = new IAEItemStack[0]; + private IItemList currentlyCached = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); private final IItemRepository iItemRepository; public InventoryCache( IItemRepository iItemRepository ) @@ -212,7 +212,7 @@ class ItemRepositoryAdapter implements IMEInventory, IBaseMonitor< public IItemList getAvailableItems( IItemList out ) { - Arrays.stream( this.cachedAeStacks ).forEach( out::add ); + currentlyCached.iterator().forEachRemaining( out::add ); return out; } @@ -220,95 +220,31 @@ class ItemRepositoryAdapter implements IMEInventory, IBaseMonitor< { final List changes = new ArrayList<>(); - List out = this.iItemRepository.getAllItems().stream().map( s -> AEItemStack.fromItemStack( s.itemPrototype ).setStackSize( s.count ) ).collect( Collectors.toList() ); + IItemList currentlyOnStorage = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); + this.iItemRepository.getAllItems().stream().map( s -> AEItemStack.fromItemStack( s.itemPrototype ).setStackSize( s.count ) ).forEach( currentlyOnStorage::add ); - final int size = out.size(); - - // Make room for new slots - if( size > this.cachedAeStacks.length ) + for ( final IAEItemStack is : currentlyCached ) { - this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, size ); + is.setStackSize( -is.getStackSize() ); } - for( int x = 0; x < size; x++ ) + for ( final IAEItemStack is : currentlyOnStorage ) { - // Save the old stuff - final IAEItemStack oldAeIS = this.cachedAeStacks[x]; - final IAEItemStack newIS = out.get( x ); - - this.handlePossibleSlotChanges( x, oldAeIS, newIS, changes ); + currentlyCached.add( is ); } - // Handle cases where the number of slots actually is lower now than before - if( size < this.cachedAeStacks.length ) + for ( final IAEItemStack is : currentlyCached ) { - for( int x = 0; x < this.cachedAeStacks.length; x++ ) + if( is.getStackSize() != 0 ) { - final IAEItemStack aeStack = this.cachedAeStacks[x]; - - if( aeStack != null ) - { - final IAEItemStack a = aeStack.copy(); - a.setStackSize( -a.getStackSize() ); - changes.add( a ); - } + changes.add( is ); } - - // Reduce the cache size - this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, size ); } + currentlyCached = currentlyOnStorage; + return changes; } - private void handlePossibleSlotChanges( int slot, IAEItemStack oldAeIS, IAEItemStack newIS, List changes ) - { - if( oldAeIS != null && oldAeIS.isSameType( newIS ) ) - { - this.handleStackSizeChanged( slot, oldAeIS, newIS, changes ); - } - else - { - this.handleItemChanged( slot, oldAeIS, newIS, changes ); - } - } - - private void handleStackSizeChanged( int slot, IAEItemStack oldAeIS, IAEItemStack newIS, List changes ) - { - // Still the same item, but amount might have changed - final long diff = newIS.getStackSize() - oldAeIS.getStackSize(); - - if( diff != 0 ) - { - final IAEItemStack stack = oldAeIS.copy(); - stack.setStackSize( newIS.getStackSize() ); - - this.cachedAeStacks[slot] = stack; - - final IAEItemStack a = stack.copy(); - a.setStackSize( diff ); - changes.add( a ); - } - } - - private void handleItemChanged( int slot, IAEItemStack oldAeIS, IAEItemStack newIS, List changes ) - { - // Completely different item - this.cachedAeStacks[slot] = newIS ; - - // If we had a stack previously in this slot, notify the network about its disappearance - if( oldAeIS != null ) - { - oldAeIS.setStackSize( -oldAeIS.getStackSize() ); - changes.add( oldAeIS ); - } - - // Notify the network about the new stack. Note that this is null if newIS was null - if( this.cachedAeStacks[slot] != null ) - { - changes.add( this.cachedAeStacks[slot] ); - } - } - } } diff --git a/src/main/java/appeng/parts/misc/PartStorageBus.java b/src/main/java/appeng/parts/misc/PartStorageBus.java index 771f4190e..eddd99dd4 100644 --- a/src/main/java/appeng/parts/misc/PartStorageBus.java +++ b/src/main/java/appeng/parts/misc/PartStorageBus.java @@ -258,7 +258,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC @Override public void postChange( final IBaseMonitor monitor, final Iterable change, final IActionSource source ) { - if( source == this.mySrc || source.machine().map( machine -> machine == this ).orElse( false ) ) + if( this.mySrc == source || this.mySrc.machine().map( machine -> machine == this ).orElse( false ) ) { try { @@ -266,8 +266,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC { this.getProxy().getStorage().postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), change, this.mySrc ); } - } - catch( final GridAccessException e ) + } catch ( final GridAccessException e ) { // :( } @@ -598,7 +597,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC { if( channel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) { - final IMEInventoryHandler out = this.getProxy().isActive() ? this.getInternalHandler() : null; + final IMEInventoryHandler out = this.getInternalHandler(); if( out != null ) { return Collections.singletonList( out ); diff --git a/src/main/java/appeng/parts/reporting/AbstractPartMonitor.java b/src/main/java/appeng/parts/reporting/AbstractPartMonitor.java index 5c332f41d..8bedf4948 100644 --- a/src/main/java/appeng/parts/reporting/AbstractPartMonitor.java +++ b/src/main/java/appeng/parts/reporting/AbstractPartMonitor.java @@ -21,10 +21,12 @@ package appeng.parts.reporting; import java.io.IOException; +import appeng.api.networking.events.MENetworkChannelsChanged; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.events.MENetworkPowerStatusChange; import appeng.api.storage.channels.IFluidStorageChannel; import appeng.api.storage.data.IAEFluidStack; import appeng.fluids.util.AEFluidStack; -import appeng.util.item.AEStack; import io.netty.buffer.ByteBuf; import net.minecraft.client.renderer.GlStateManager; @@ -43,7 +45,6 @@ import net.minecraftforge.fml.relauncher.SideOnly; import appeng.api.AEApi; import appeng.api.implementations.parts.IPartStorageMonitor; -import appeng.api.networking.security.IActionSource; import appeng.api.networking.storage.IStackWatcher; import appeng.api.networking.storage.IStackWatcherHost; import appeng.api.parts.IPartModel; @@ -52,7 +53,6 @@ import appeng.api.storage.IStorageChannel; import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEStack; -import appeng.api.storage.data.IItemList; import appeng.client.render.TesrRenderHelper; import appeng.core.localization.PlayerMessages; import appeng.helpers.Reflected; @@ -385,19 +385,87 @@ public abstract class AbstractPartMonitor extends AbstractPartDisplay implements this.configureWatchers(); } + @MENetworkEventSubscribe + public void powerStatusChange( final MENetworkPowerStatusChange ev ) + { + if( !this.getProxy().isPowered() ) + { + if( this.myWatcher != null ) + { + if( this.configuredItem != null ) + { + this.configuredItem.setStackSize( 0 ); + } + if( this.configuredFluid != null ) + { + this.configuredFluid.setStackSize( 0 ); + } + } + } + else + { + try + { + if( this.configuredItem != null ) + { + this.updateReportingValue( this.getProxy().getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) ); + } + if( this.configuredFluid != null ) + { + this.updateReportingValue( this.getProxy().getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ) ); + } + } + catch( final GridAccessException e ) + { + // ;P + } + } + } + + @MENetworkEventSubscribe + public void channelChanged( final MENetworkChannelsChanged c ) + { + if( !this.getProxy().isPowered() ) + { + if( this.myWatcher != null ) + { + if( this.configuredItem != null ) + { + this.configuredItem.setStackSize( 0 ); + } + if( this.configuredFluid != null ) + { + this.configuredFluid.setStackSize( 0 ); + } + } + } + else + { + try + { + if( this.configuredItem != null ) + { + this.updateReportingValue( this.getProxy().getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) ); + } + if( this.configuredFluid != null ) + { + this.updateReportingValue( this.getProxy().getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ) ); + } + } + catch( final GridAccessException e ) + { + // ;P + } + } + } + @Override - public void onStackChange( final IItemList o, final IAEStack fullStack, final IAEStack diffStack, final IActionSource src, final IStorageChannel chan ) + public void onStackChange( final IAEStack diffStack, final IStorageChannel chan ) { if( this.configuredItem != null ) { - if( fullStack == null ) - { - this.configuredItem.setStackSize( 0 ); - } - else - { - this.configuredItem.setStackSize( fullStack.getStackSize() ); - } + long diff = this.configuredItem.getStackSize() + diffStack.getStackSize(); + this.configuredItem.setStackSize( diff >= 0 ? this.configuredItem.getStackSize() + diffStack.getStackSize() : 0 ); final long stackSize = this.configuredItem.getStackSize(); final String humanReadableText = NUMBER_CONVERTER.toWideReadableForm( stackSize ); @@ -410,14 +478,8 @@ public abstract class AbstractPartMonitor extends AbstractPartDisplay implements } else if( this.configuredFluid != null ) { - if( fullStack == null ) - { - this.configuredFluid.setStackSize( 0 ); - } - else - { - this.configuredFluid.setStackSize( fullStack.getStackSize() ); - } + long diff = this.configuredFluid.getStackSize() + diffStack.getStackSize(); + this.configuredFluid.setStackSize( diff >= 0 ? this.configuredFluid.getStackSize() + diffStack.getStackSize() : 0 ); final long stackSize = this.configuredFluid.getStackSize() / 1000; final String humanReadableText = NUMBER_CONVERTER.toWideReadableForm( stackSize ) + "B"; diff --git a/src/main/java/appeng/tile/storage/TileChest.java b/src/main/java/appeng/tile/storage/TileChest.java index f552db406..65df0f44d 100644 --- a/src/main/java/appeng/tile/storage/TileChest.java +++ b/src/main/java/appeng/tile/storage/TileChest.java @@ -554,14 +554,10 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal @Override public List getCellArray( final IStorageChannel channel ) { - if( this.getProxy().isActive() ) + this.updateHandler(); + if( this.cellHandler != null && this.cellHandler.getChannel() == channel ) { - this.updateHandler(); - - if( this.cellHandler != null && this.cellHandler.getChannel() == channel ) - { - return Collections.singletonList( this.cellHandler ); - } + return Collections.singletonList( this.cellHandler ); } return Collections.emptyList(); } @@ -692,7 +688,7 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal @Override public void postChange( final IBaseMonitor monitor, final Iterable change, final IActionSource source ) { - if( source == TileChest.this.mySrc || source.machine().map( machine -> machine == TileChest.this ).orElse( false ) ) + if( TileChest.this.mySrc == source || TileChest.this.mySrc.machine().map( machine -> machine == TileChest.this ).orElse( false ) ) { try { @@ -700,14 +696,12 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal { TileChest.this.getProxy().getStorage().postAlterationOfStoredItems( this.chan, change, TileChest.this.mySrc ); } - } - catch( final GridAccessException e ) + } catch ( final GridAccessException e ) { // :( } + TileChest.this.blinkCell( 0 ); } - - TileChest.this.blinkCell( 0 ); } @Override diff --git a/src/main/java/appeng/tile/storage/TileDrive.java b/src/main/java/appeng/tile/storage/TileDrive.java index c57d8cd01..c90d67325 100644 --- a/src/main/java/appeng/tile/storage/TileDrive.java +++ b/src/main/java/appeng/tile/storage/TileDrive.java @@ -334,13 +334,8 @@ public class TileDrive extends AENetworkInvTile implements IChestOrDrive, IPrior @Override public List getCellArray( final IStorageChannel channel ) { - if( this.getProxy().isActive() ) - { - this.updateState(); - - return this.inventoryHandlers.get( channel ); - } - return Collections.emptyList(); + this.updateState(); + return this.inventoryHandlers.get( channel ); } @Override diff --git a/src/main/java/appeng/util/item/OreReference.java b/src/main/java/appeng/util/item/OreReference.java index a32fa58b1..9ca625036 100644 --- a/src/main/java/appeng/util/item/OreReference.java +++ b/src/main/java/appeng/util/item/OreReference.java @@ -43,7 +43,7 @@ public class OreReference return this.otherOptions; } - List getAEEquivalents() + public List getAEEquivalents() { if( this.aeOtherOptions == null ) {