reworked how changes are propagated in the network

This commit is contained in:
Salomão
2021-07-16 14:13:48 -03:00
parent f9c274fb48
commit 24750f00b1
20 changed files with 591 additions and 618 deletions
@@ -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 );
}
}
@@ -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<IAEFluidStack>, IBaseMo
return null;
}
IAEFluidStack gatheredAEFluidstack = AEFluidStack.fromFluidStack( gathered );
if( mode == Actionable.MODULATE )
{
try
@@ -134,7 +134,7 @@ public class FluidHandlerAdapter implements IMEInventory<IAEFluidStack>, IBaseMo
// meh
}
}
return AEFluidStack.fromFluidStack( gathered );
return gatheredAEFluidstack;
}
@Override
@@ -202,9 +202,9 @@ public class FluidHandlerAdapter implements IMEInventory<IAEFluidStack>, IBaseMo
private static class InventoryCache
{
private IAEFluidStack[] cachedAeStacks = new IAEFluidStack[0];
private final IFluidHandler fluidHandler;
private final StorageFilter mode;
IItemList<IAEFluidStack> currentlyCached = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList();
public InventoryCache( IFluidHandler fluidHandler, StorageFilter mode )
{
@@ -216,19 +216,12 @@ public class FluidHandlerAdapter implements IMEInventory<IAEFluidStack>, IBaseMo
{
final List<IAEFluidStack> 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<IAEFluidStack> 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<IAEFluidStack>, 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<IAEFluidStack> getAvailableItems( IItemList<IAEFluidStack> 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<IAEFluidStack> 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<IAEFluidStack> 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<IAEFluidStack> 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] );
}
}
}
}
@@ -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<IAEFluidStack>) monitor ).getGridCurrentCount();
}
}
else
@@ -264,7 +264,7 @@ public class PartFluidStorageBus extends PartSharedStorageBus implements IMEMoni
@Override
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 ) )
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<IAEFluidStack> out = this.getProxy().isActive() ? this.getInternalHandler() : null;
final IMEInventoryHandler<IAEFluidStack> out = this.getInternalHandler();
if( out != null )
{
return Collections.singletonList( out );
+54 -92
View File
@@ -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<T extends IAEStack<T>> implements IMEMonitor<T>
{
@@ -63,9 +61,11 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
private final Object2ObjectMap<IMEMonitorHandlerReceiver<T>, 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<T> chan )
{
@@ -90,21 +90,7 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
@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<T extends IAEStack<T>> implements IMEMonitor<T>
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<T> getStorageList()
{
if( hasChanged )
if( forceUpdate )
{
hasChanged = false;
forceUpdate = false;
this.cachedList.resetStatus();
return this.getAvailableItems( this.cachedList );
}
@@ -154,21 +166,7 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
@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<T extends IAEStack<T>> implements IMEMonitor<T>
return this.listeners.entrySet().iterator();
}
private T monitorDifference( final IAEStack<T> 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<T> diff, final IActionSource src )
{
this.hasChanged = true;
final Iterator<Entry<IMEMonitorHandlerReceiver<T>, Object>> i = this.getListeners();
while( i.hasNext() )
@@ -241,54 +217,38 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
}
}
private void postChangesToListeners( final Iterable<T> changes, final IActionSource src )
{
this.postChange( true, changes, src );
}
protected void postChange( final boolean add, final Iterable<T> 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<ItemWatcher> list = this.myGridCache.getInterestManager().get( changedItem );
if( !list.isEmpty() )
{
IAEStack<T> 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<T extends IAEStack<T>> implements IMEMonitor<T>
}
}
this.notifyListenersOfChange( changes, src );
final NetworkMonitor<?> last = GLOBAL_DEPTH.pop();
this.localDepthSemaphore--;
if( last != this )
{
@@ -307,10 +268,10 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
void forceUpdate()
{
this.hasChanged = true;
this.forceUpdate = true;
final Iterator<Entry<IMEMonitorHandlerReceiver<T>, Object>> i = this.getListeners();
while( i.hasNext() )
while ( i.hasNext() )
{
final Entry<IMEMonitorHandlerReceiver<T>, Object> o = i.next();
final IMEMonitorHandlerReceiver<T> receiver = o.getKey();
@@ -333,5 +294,6 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
this.sendEvent = false;
this.myGridCache.getGrid().postEvent( new MENetworkStorageEvent( this, this.myChannel ) );
}
}
}
-1
View File
@@ -138,7 +138,6 @@ public class TickManagerCache implements ITickManager
tt.addEntityCrashInfo( crashreportcategory );
throw new ReportedException( crashreport );
}
PartLevelEmitter.wipeCache();
}
private void addToQueue( final TickTracker tt )
@@ -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<T>
@@ -101,12 +102,30 @@ public class GenericInterestManager<T>
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<T> get( final IAEStack stack )
{
return this.container.get( stack );
Collection<T> 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
@@ -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<T extends IAEStack<T>> extends MEInventoryHandler<T>
private final ItemStack is;
private final ICellHandler handler;
private final IChestOrDrive cord;
private IActionSource source;
public DriveWatcher( final ICellInventoryHandler<T> i, final ItemStack is, final ICellHandler han, final IChestOrDrive cod )
{
@@ -43,6 +48,7 @@ public class DriveWatcher<T extends IAEStack<T>> extends MEInventoryHandler<T>
this.is = is;
this.handler = han;
this.cord = cod;
this.source = new MachineSource( cod );
}
public int getStatus()
@@ -66,6 +72,14 @@ public class DriveWatcher<T extends IAEStack<T>> extends MEInventoryHandler<T>
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<T extends IAEStack<T>> extends MEInventoryHandler<T>
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;
@@ -72,7 +72,7 @@ public class MEMonitorPassThrough<T extends IAEStack<T>> extends MEPassThrough<T
final IItemList<T> 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<T extends IAEStack<T>> extends MEPassThrough<T
@Override
public void addListener( final IMEMonitorHandlerReceiver<T> l, final Object verificationToken )
{
if( this.listeners.size() == 0 )
{
if( this.monitor != null )
{
this.monitor.addListener( this, this.monitor );
}
}
this.listeners.put( l, verificationToken );
}
@@ -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<IAEItemStack>, ICraftingProvider
@@ -123,9 +109,6 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH
private double centerX;
private double centerY;
private double centerZ;
static Object2LongMap<Grid> gridItemCount = new Object2LongOpenHashMap<>();
static Object2ObjectOpenHashMap<Grid, Object2LongMap<AEItemStack>> fuzzyAEItemStackCount = new Object2ObjectOpenHashMap<>();
static Object2ObjectOpenHashMap<Grid, Object2LongMap<AEItemStack>> 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<OreReference> 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<IAEItemStack> monitor )
{
updateReportingValue( monitor,null );
}
private void updateReportingValue( final IMEMonitor<IAEItemStack> monitor, Iterable<IAEItemStack> 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<IAEItemStack>) 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<IAEItemStack> monitor, final Iterable<IAEItemStack> change, final IActionSource actionSource )
{
this.updateReportingValue( (IMEMonitor<IAEItemStack>) monitor, change );
this.updateReportingValue( (IMEMonitor<IAEItemStack>) monitor );
}
@Override
@@ -636,9 +590,4 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH
}
}
public static void wipeCache(){
fuzzyAEItemStackCount.clear();
preciseAEItemStackCount.clear();
gridItemCount.clear();
}
}
@@ -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<IAEItemStack>, IBaseMonitor<IAE
stackCache = null;
ItemStack orgInput;
int slotCount = this.itemHandler.getSlots();
if( currentCached != null && iox.isSameType( currentCached ) )
{
// Cache is suitable, just update the count
@@ -94,10 +95,16 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
// We need a new stack :-(
orgInput = iox.createItemStack();
}
ItemStack remaining = ItemHandlerHelper.insertItem( this.itemHandler, orgInput, type == Actionable.SIMULATE );
ItemStack remaining = orgInput;
for ( int i = 0; i < slotCount && !remaining.isEmpty(); i++ )
{
remaining = this.itemHandler.insertItem( i, remaining, type == Actionable.SIMULATE );
}
// Store the stack in the cache for next time.
if (!remaining.isEmpty() && remaining != orgInput)
if( !remaining.isEmpty() && remaining != orgInput )
{
stackCache = remaining;
}
@@ -128,18 +135,17 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
@Override
public IAEItemStack extractItems( IAEItemStack request, Actionable mode, IActionSource src )
{
int remainingSize = Ints.saturatedCast(request.getStackSize());
int remainingSize = Ints.saturatedCast( request.getStackSize() );
// Use this to gather the requested items
ItemStack gathered = ItemStack.EMPTY;
final boolean simulate = ( mode == Actionable.SIMULATE );
for( int i = 0; i < this.itemHandler.getSlots(); i++ )
for ( int i = 0; i < this.itemHandler.getSlots(); i++ )
{
ItemStack stackInInventorySlot = this.itemHandler.getStackInSlot( i );
if (!request.isSameType(stackInInventorySlot))
if( !request.isSameType( stackInInventorySlot ) )
{
continue;
}
@@ -191,6 +197,7 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
if( !gathered.isEmpty() )
{
IAEItemStack gatheredAEItemStack = AEItemStack.fromItemStack( gathered );
if( mode == Actionable.MODULATE )
{
try
@@ -203,7 +210,7 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
}
}
return AEItemStack.fromItemStack( gathered );
return gatheredAEItemStack;
}
return null;
@@ -274,9 +281,9 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
private static class InventoryCache implements Iterable<ItemSlot>
{
private IAEItemStack[] cachedAeStacks = new IAEItemStack[0];
private final IItemHandler itemHandler;
private final StorageFilter mode;
IItemList<IAEItemStack> currentlyCached = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
public InventoryCache( IItemHandler itemHandler, StorageFilter mode )
{
@@ -286,7 +293,7 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
public IItemList<IAEItemStack> getAvailableItems( IItemList<IAEItemStack> out )
{
Arrays.stream( this.cachedAeStacks ).forEach( out::add );
currentlyCached.iterator().forEachRemaining( out::add );
return out;
}
@@ -298,93 +305,41 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
public List<IAEItemStack> update()
{
final List<IAEItemStack> 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<IAEItemStack> 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<IAEItemStack> 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<IAEItemStack> 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<IAEItemStack> 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<ItemSlot> iterator()
{
@@ -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<IAEItemStack>, 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<IAEItemStack>, IBaseMonitor<
if( !extracted.isEmpty() )
{
IAEItemStack extractedAEItemStack = AEItemStack.fromItemStack( extracted );
if( mode == Actionable.MODULATE )
{
try
@@ -130,7 +130,7 @@ class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<
// meh
}
}
return AEItemStack.fromItemStack( extracted );
return extractedAEItemStack;
}
return null;
}
@@ -202,7 +202,7 @@ class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<
private static class InventoryCache
{
private IAEItemStack[] cachedAeStacks = new IAEItemStack[0];
private IItemList<IAEItemStack> currentlyCached = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private final IItemRepository iItemRepository;
public InventoryCache( IItemRepository iItemRepository )
@@ -212,7 +212,7 @@ class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<
public IItemList<IAEItemStack> getAvailableItems( IItemList<IAEItemStack> out )
{
Arrays.stream( this.cachedAeStacks ).forEach( out::add );
currentlyCached.iterator().forEachRemaining( out::add );
return out;
}
@@ -220,95 +220,31 @@ class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<
{
final List<IAEItemStack> changes = new ArrayList<>();
List<IAEItemStack> out = this.iItemRepository.getAllItems().stream().map( s -> AEItemStack.fromItemStack( s.itemPrototype ).setStackSize( s.count ) ).collect( Collectors.toList() );
IItemList<IAEItemStack> 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<IAEItemStack> 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<IAEItemStack> 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<IAEItemStack> 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] );
}
}
}
}
@@ -258,7 +258,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
@Override
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 ) )
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<IAEItemStack> out = this.getProxy().isActive() ? this.getInternalHandler() : null;
final IMEInventoryHandler<IAEItemStack> out = this.getInternalHandler();
if( out != null )
{
return Collections.singletonList( out );
@@ -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";
@@ -554,14 +554,10 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
@Override
public List<IMEInventoryHandler> 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<T> monitor, final Iterable<T> 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
@@ -334,13 +334,8 @@ public class TileDrive extends AENetworkInvTile implements IChestOrDrive, IPrior
@Override
public List<IMEInventoryHandler> 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
@@ -43,7 +43,7 @@ public class OreReference
return this.otherOptions;
}
List<IAEItemStack> getAEEquivalents()
public List<IAEItemStack> getAEEquivalents()
{
if( this.aeOtherOptions == null )
{