Compare commits

..

4 Commits

20 changed files with 266 additions and 285 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ aechannel=stable
aebuild=7 aebuild=7
aegroup=appeng aegroup=appeng
aebasename=appliedenergistics2 aebasename=appliedenergistics2
trousers=omni-fixes-v45 trousers=omni-fixes-v44
######################################################### #########################################################
# Versions # # Versions #
@@ -52,4 +52,9 @@ public interface IMEMonitorHandlerReceiver<T extends IAEStack<T>>
* called when the list updates its contents, this is mostly for handling power events. * called when the list updates its contents, this is mostly for handling power events.
*/ */
void onListUpdate(); void onListUpdate();
default boolean hasListeners()
{
return true;
}
} }
+3 -56
View File
@@ -59,7 +59,6 @@ public class CraftingJob implements Runnable, ICraftingJob
private final IItemList<IAEItemStack> missing = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); private final IItemList<IAEItemStack> missing = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private final HashMap<String, TwoIntegers> opsAndMultiplier = new HashMap<>(); private final HashMap<String, TwoIntegers> opsAndMultiplier = new HashMap<>();
private final Object monitor = new Object(); private final Object monitor = new Object();
private final Stopwatch watch = Stopwatch.createUnstarted();
private CraftingTreeNode tree; private CraftingTreeNode tree;
private final IAEItemStack output; private final IAEItemStack output;
private boolean simulate = false; private boolean simulate = false;
@@ -67,10 +66,7 @@ public class CraftingJob implements Runnable, ICraftingJob
private long bytes = 0; private long bytes = 0;
private final IActionSource actionSrc; private final IActionSource actionSrc;
private final ICraftingCallback callback; private final ICraftingCallback callback;
private boolean running = false;
private boolean done = false; private boolean done = false;
private int time;
private int incTime;
private World wrapWorld( final World w ) private World wrapWorld( final World w )
{ {
@@ -137,7 +133,6 @@ public class CraftingJob implements Runnable, ICraftingJob
try try
{ {
TickHandler.INSTANCE.registerCraftingSimulation( this.world, this ); TickHandler.INSTANCE.registerCraftingSimulation( this.world, this );
this.handlePausing();
final Stopwatch timer = Stopwatch.createStarted(); final Stopwatch timer = Stopwatch.createStarted();
@@ -219,41 +214,6 @@ public class CraftingJob implements Runnable, ICraftingJob
this.finish(); this.finish();
} }
void handlePausing() throws InterruptedException
{
if( !this.actionSrc.player().isPresent() && this.incTime > 100 )
{
this.incTime = 0;
synchronized ( this.monitor )
{
if( this.watch.elapsed( TimeUnit.MICROSECONDS ) > this.time )
{
this.running = false;
this.watch.stop();
this.monitor.notify();
}
if( !this.running )
{
AELog.craftingDebug( "crafting job will now sleep" );
while ( !this.running )
{
this.monitor.wait();
}
AELog.craftingDebug( "crafting job now active" );
}
}
if( Thread.interrupted() )
{
throw new InterruptedException();
}
}
this.incTime++;
}
private void finish() private void finish()
{ {
if( this.callback != null ) if( this.callback != null )
@@ -265,7 +225,6 @@ public class CraftingJob implements Runnable, ICraftingJob
synchronized( this.monitor ) synchronized( this.monitor )
{ {
this.running = false;
this.done = true; this.done = true;
this.monitor.notify(); this.monitor.notify();
} }
@@ -311,25 +270,13 @@ public class CraftingJob implements Runnable, ICraftingJob
/** /**
* @return true if this needs more simulation * @return true if this needs more simulation
*/ */
public boolean simulateFor(final int milli) public boolean simulateFor()
{ {
this.time = milli; synchronized( this.monitor ) {
if ( this.done ) {
synchronized ( this.monitor )
{
if( this.done )
{
return false; return false;
} }
if( !this.actionSrc.player().isPresent() )
{
this.watch.reset();
this.watch.start();
this.monitor.notify();
}
this.running = true;
} }
return true; return true;
} }
@@ -119,7 +119,7 @@ public class CraftingTreeNode
IAEItemStack request( final MECraftingInventory inv, long l, final IActionSource src ) throws CraftBranchFailure, InterruptedException IAEItemStack request( final MECraftingInventory inv, long l, final IActionSource src ) throws CraftBranchFailure, InterruptedException
{ {
this.job.handlePausing();
final List<IAEItemStack> thingsUsed = new ArrayList<>(); final List<IAEItemStack> thingsUsed = new ArrayList<>();
this.what.setStackSize( l ); this.what.setStackSize( l );
@@ -185,7 +185,7 @@ public class CraftingTreeProcess
void request( final MECraftingInventory inv, final long i, final IActionSource src ) throws CraftBranchFailure, InterruptedException void request( final MECraftingInventory inv, final long i, final IActionSource src ) throws CraftBranchFailure, InterruptedException
{ {
this.job.handlePausing();
if( this.fullSimulation ) if( this.fullSimulation )
{ {
final InventoryCrafting ic = new InventoryCrafting( new ContainerNull(), 3, 3 ); final InventoryCrafting ic = new InventoryCrafting( new ContainerNull(), 3, 3 );
@@ -27,7 +27,6 @@ import java.util.Map;
import appeng.api.config.Settings; import appeng.api.config.Settings;
import appeng.api.config.StorageFilter; import appeng.api.config.StorageFilter;
import appeng.me.GridAccessException;
import appeng.parts.misc.PartStorageBus; import appeng.parts.misc.PartStorageBus;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler;
@@ -93,14 +92,9 @@ public class FluidHandlerAdapter implements IMEInventory<IAEFluidStack>, IBaseMo
if( type == Actionable.MODULATE ) if( type == Actionable.MODULATE )
{ {
try this.cache
{ .currentlyCached
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); .add( input.copy().setStackSize( wasFillled ));
}
catch( GridAccessException ignore )
{
// meh
}
} }
fluidStack.amount = remaining; fluidStack.amount = remaining;
@@ -125,13 +119,10 @@ public class FluidHandlerAdapter implements IMEInventory<IAEFluidStack>, IBaseMo
IAEFluidStack gatheredAEFluidstack = AEFluidStack.fromFluidStack( gathered ); IAEFluidStack gatheredAEFluidstack = AEFluidStack.fromFluidStack( gathered );
if( mode == Actionable.MODULATE ) if( mode == Actionable.MODULATE )
{ {
try IAEFluidStack e = this.cache.currentlyCached.findPrecise( gatheredAEFluidstack );
if (e != null)
{ {
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); e.decStackSize( gathered.amount );
}
catch( GridAccessException ignore )
{
// meh
} }
} }
return gatheredAEFluidstack; return gatheredAEFluidstack;
@@ -206,6 +197,7 @@ public class FluidHandlerAdapter implements IMEInventory<IAEFluidStack>, IBaseMo
private final StorageFilter mode; private final StorageFilter mode;
IItemList<IAEFluidStack> currentlyCached = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList(); IItemList<IAEFluidStack> currentlyCached = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList();
public InventoryCache( IFluidHandler fluidHandler, StorageFilter mode ) public InventoryCache( IFluidHandler fluidHandler, StorageFilter mode )
{ {
this.mode = mode; this.mode = mode;
@@ -204,7 +204,7 @@ public class PartFluidFormationPlane extends PartAbstractFormationPlane<IAEFluid
@Override @Override
public List<IMEInventoryHandler> getCellArray( final IStorageChannel channel ) public List<IMEInventoryHandler> getCellArray( final IStorageChannel channel )
{ {
if( channel == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ) if( this.getProxy().isActive() && channel == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) )
{ {
final List<IMEInventoryHandler> handler = new ArrayList<>( 1 ); final List<IMEInventoryHandler> handler = new ArrayList<>( 1 );
handler.add( this.myHandler ); handler.add( this.myHandler );
@@ -270,7 +270,8 @@ public class PartFluidStorageBus extends PartSharedStorageBus implements IMEMoni
{ {
this.getProxy().getStorage().postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ), change, this.source ); this.getProxy().getStorage().postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ), change, this.source );
} }
} catch ( final GridAccessException e ) }
catch( final GridAccessException e )
{ {
// :( // :(
} }
+12 -7
View File
@@ -187,15 +187,20 @@ public class TickHandler
if( ev.type == Type.WORLD && ev.phase == Phase.END ) if( ev.type == Type.WORLD && ev.phase == Phase.END )
{ {
final WorldTickEvent wte = (WorldTickEvent) ev; final WorldTickEvent wte = (WorldTickEvent) ev;
synchronized ( this.craftingJobs ) synchronized( this.craftingJobs )
{ {
final Collection<CraftingJob> jobSet = this.craftingJobs.get( wte.world ); final Collection<CraftingJob> jobSet = this.craftingJobs.get( wte.world );
if (!jobSet.isEmpty()) { if( !jobSet.isEmpty() )
final int jobSize = jobSet.size(); {
final int microSecondsPerTick = AEConfig.instance().getCraftingCalculationTimePerTick() * 1000; final Iterator<CraftingJob> i = jobSet.iterator();
final int simTime = Math.max(1, microSecondsPerTick / jobSize); while( i.hasNext() )
{
jobSet.removeIf( cj -> !cj.simulateFor( simTime ) ); final CraftingJob cj = i.next();
if( !cj.simulateFor() )
{
i.remove();
}
}
} }
} }
} }
+40 -88
View File
@@ -19,10 +19,21 @@
package appeng.me.cache; package appeng.me.cache;
import java.util.*; import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.NavigableSet;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.*; import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
import appeng.api.config.AccessRestriction; import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
@@ -70,7 +81,7 @@ public class EnergyGridCache implements IEnergyGrid
// Should only be modified from the add/remove methods below to guard against // Should only be modified from the add/remove methods below to guard against
// concurrent modifications // concurrent modifications
private final double averageLength = 40.0; private final double averageLength = 40.0;
private final Multimap<Integer,IAEPowerStorage> providers = HashMultimap.create(); private final Set<IAEPowerStorage> providers = new LinkedHashSet<>();
// Used to track whether an extraction is currently in progress, to fail fast // Used to track whether an extraction is currently in progress, to fail fast
// when something externally // when something externally
// modifies the energy grid. // modifies the energy grid.
@@ -78,7 +89,7 @@ public class EnergyGridCache implements IEnergyGrid
// Should only be modified from the add/remove methods below to guard against // Should only be modified from the add/remove methods below to guard against
// concurrent modifications // concurrent modifications
private final Multimap<Integer,IAEPowerStorage> requesters = HashMultimap.create(); private final Set<IAEPowerStorage> requesters = new LinkedHashSet<>();
// Used to track whether an injection is currently in progress, to fail fast // Used to track whether an injection is currently in progress, to fail fast
// when something externally // when something externally
// modifies the energy grid. // modifies the energy grid.
@@ -123,8 +134,8 @@ public class EnergyGridCache implements IEnergyGrid
public EnergyGridCache( final IGrid g ) public EnergyGridCache( final IGrid g )
{ {
this.myGrid = g; this.myGrid = g;
this.requesters.put( 0, this.localStorage ); this.requesters.add( this.localStorage );
this.providers.put( 1, this.localStorage ); this.providers.add( this.localStorage );
} }
@MENetworkEventSubscribe @MENetworkEventSubscribe
@@ -307,7 +318,7 @@ public class EnergyGridCache implements IEnergyGrid
{ {
this.availableTicksSinceUpdate = 0; this.availableTicksSinceUpdate = 0;
this.globalAvailablePower = 0; this.globalAvailablePower = 0;
for( final IAEPowerStorage p : this.providers.values() ) for( final IAEPowerStorage p : this.providers )
{ {
this.globalAvailablePower += p.getAECurrentPower(); this.globalAvailablePower += p.getAECurrentPower();
} }
@@ -324,20 +335,10 @@ public class EnergyGridCache implements IEnergyGrid
{ {
double extractedPower = 0; double extractedPower = 0;
providersToAdd.forEach( provider -> { this.providers.addAll( providersToAdd );
if( provider instanceof GridPowerStorage )
{
providers.put( 1, provider );
}
else
{
providers.put( 0, provider );
}
} );
providersToAdd.clear(); providersToAdd.clear();
final Iterator<IAEPowerStorage> it = this.providers.values().iterator(); final Iterator<IAEPowerStorage> it = this.providers.iterator();
ongoingExtractOperation = true; ongoingExtractOperation = true;
try try
@@ -357,16 +358,7 @@ public class EnergyGridCache implements IEnergyGrid
} }
} finally } finally
{ {
providerToRemove.forEach( provider -> { providers.removeIf( p -> providerToRemove.contains( p ) );
if( provider instanceof GridPowerStorage )
{
providers.remove( 1, provider );
}
else
{
providers.remove( 0, provider );
}
} );
this.providerToRemove.clear(); this.providerToRemove.clear();
ongoingExtractOperation = false; ongoingExtractOperation = false;
} }
@@ -392,18 +384,10 @@ public class EnergyGridCache implements IEnergyGrid
{ {
final double originalAmount = amt; final double originalAmount = amt;
requesterToAdd.forEach( requester -> { this.requesters.addAll( requesterToAdd );
if( requester instanceof GridPowerStorage ) requesterToAdd.clear();
{
requesters.put( 0, requester );
}
else
{
requesters.put( 1, requester );
}
} );
final Iterator<IAEPowerStorage> it = this.requesters.values().iterator(); final Iterator<IAEPowerStorage> it = this.requesters.iterator();
ongoingInjectOperation = true; ongoingInjectOperation = true;
try try
@@ -421,16 +405,7 @@ public class EnergyGridCache implements IEnergyGrid
} }
} finally } finally
{ {
requesterToRemove.forEach( requester -> { requesters.removeIf( r -> requesterToRemove.contains( r ) );
if( requester instanceof GridPowerStorage )
{
requesters.remove( 0, requester );
}
else
{
requesters.remove( 1, requester );
}
} );
this.requesterToRemove.clear(); this.requesterToRemove.clear();
ongoingInjectOperation = false; ongoingInjectOperation = false;
} }
@@ -450,7 +425,7 @@ public class EnergyGridCache implements IEnergyGrid
{ {
double required = 0; double required = 0;
final Iterator<IAEPowerStorage> it = this.requesters.values().iterator(); final Iterator<IAEPowerStorage> it = this.requesters.iterator();
while( required < maxRequired && it.hasNext() ) while( required < maxRequired && it.hasNext() )
{ {
final IAEPowerStorage node = it.next(); final IAEPowerStorage node = it.next();
@@ -619,55 +594,28 @@ public class EnergyGridCache implements IEnergyGrid
private void addRequester(IAEPowerStorage requester) { private void addRequester(IAEPowerStorage requester) {
Preconditions.checkState(!ongoingInjectOperation, Preconditions.checkState(!ongoingInjectOperation,
"Cannot modify energy requesters while energy is being injected."); "Cannot modify energy requesters while energy is being injected.");
if( requester instanceof GridPowerStorage ) this.requesters.add(requester);
{
requesters.put( 0, requester );
}
else
{
requesters.put( 1, requester );
}
} }
private void removeRequester(IAEPowerStorage requester) { private void removeRequester(IAEPowerStorage requester) {
Preconditions.checkState(!ongoingInjectOperation, Preconditions.checkState(!ongoingInjectOperation,
"Cannot modify energy requesters while energy is being injected."); "Cannot modify energy requesters while energy is being injected.");
if( requester instanceof GridPowerStorage ) this.requesters.remove(requester);
{
requesters.remove( 0, requester );
}
else
{
requesters.remove( 1, requester );
}
} }
private void addProvider(IAEPowerStorage provider) { private void addProvider(IAEPowerStorage provider) {
Preconditions.checkState(!ongoingExtractOperation, Preconditions.checkState(!ongoingExtractOperation,
"Cannot modify energy providers while energy is being extracted."); "Cannot modify energy providers while energy is being extracted.");
if( provider instanceof GridPowerStorage ) this.providers.add(provider);
{
providers.put( 1, provider );
}
else
{
providers.put( 0, provider );
}
} }
private void removeProvider(IAEPowerStorage provider) private void removeProvider(IAEPowerStorage provider) {
{ Preconditions.checkState(!ongoingExtractOperation,
Preconditions.checkState( !ongoingExtractOperation, "Cannot modify energy providers while energy is being extracted." ); "Cannot modify energy providers while energy is being extracted.");
if( provider instanceof GridPowerStorage ) this.providers.remove(provider);
{
providers.remove( 1, provider );
}
else
{
providers.remove( 0, provider );
}
} }
@Override @Override
public void addNode( final IGridNode node, final IGridHost machine ) public void addNode( final IGridNode node, final IGridHost machine )
{ {
@@ -840,8 +788,12 @@ public class EnergyGridCache implements IEnergyGrid
if( this.stored < 0.01 ) if( this.stored < 0.01 )
{ {
EnergyGridCache.this.ticksSinceHasPowerChange = 0; refreshPower();
EnergyGridCache.this.publicPowerState( false, EnergyGridCache.this.myGrid ); if (globalAvailablePower < MAX_BUFFER_STORAGE - 0.001)
{
EnergyGridCache.this.ticksSinceHasPowerChange = 0;
EnergyGridCache.this.publicPowerState( false, EnergyGridCache.this.myGrid );
}
} }
} }
} }
+105 -20
View File
@@ -19,10 +19,24 @@
package appeng.me.cache; package appeng.me.cache;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.Iterator;
import java.util.Map.Entry;
import javax.annotation.Nonnegative; import javax.annotation.Nonnegative;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import appeng.api.AEApi; import appeng.api.AEApi;
import appeng.api.storage.channels.IFluidStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IAEItemStack;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Queues;
import appeng.api.config.AccessRestriction; import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
import appeng.api.networking.events.MENetworkStorageEvent; import appeng.api.networking.events.MENetworkStorageEvent;
@@ -31,20 +45,12 @@ import appeng.api.storage.IMEInventoryHandler;
import appeng.api.storage.IMEMonitor; import appeng.api.storage.IMEMonitor;
import appeng.api.storage.IMEMonitorHandlerReceiver; import appeng.api.storage.IMEMonitorHandlerReceiver;
import appeng.api.storage.IStorageChannel; 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.IAEStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.me.storage.ItemWatcher; import appeng.me.storage.ItemWatcher;
import com.google.common.collect.Queues;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; 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> public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
{ {
@@ -61,7 +67,7 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
private final Object2ObjectMap<IMEMonitorHandlerReceiver<T>, Object> listeners; private final Object2ObjectMap<IMEMonitorHandlerReceiver<T>, Object> listeners;
private boolean sendEvent = false; private boolean sendEvent = false;
private boolean forceUpdate = false; private boolean hasChanged = false;
@Nonnegative @Nonnegative
private int localDepthSemaphore = 0; private int localDepthSemaphore = 0;
private long gridItemCount; private long gridItemCount;
@@ -90,7 +96,21 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
@Override @Override
public T extractItems( final T request, final Actionable mode, final IActionSource src ) public T extractItems( final T request, final Actionable mode, final IActionSource src )
{ {
return this.getHandler().extractItems( request, mode, 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;
} }
@Override @Override
@@ -153,9 +173,9 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
@Override @Override
public IItemList<T> getStorageList() public IItemList<T> getStorageList()
{ {
if( forceUpdate ) if( hasChanged )
{ {
forceUpdate = false; hasChanged = false;
this.cachedList.resetStatus(); this.cachedList.resetStatus();
return this.getAvailableItems( this.cachedList ); return this.getAvailableItems( this.cachedList );
} }
@@ -166,7 +186,21 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
@Override @Override
public T injectItems( final T input, final Actionable mode, final IActionSource src ) public T injectItems( final T input, final Actionable mode, final IActionSource src )
{ {
return this.getHandler().injectItems( input, mode, 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;
} }
@Override @Override
@@ -198,15 +232,37 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
return this.listeners.entrySet().iterator(); 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 ) private void notifyListenersOfChange( final Iterable<T> diff, final IActionSource src )
{ {
this.hasChanged = true;
final Iterator<Entry<IMEMonitorHandlerReceiver<T>, Object>> i = this.getListeners(); final Iterator<Entry<IMEMonitorHandlerReceiver<T>, Object>> i = this.getListeners();
while( i.hasNext() ) while( i.hasNext() )
{ {
final Entry<IMEMonitorHandlerReceiver<T>, Object> o = i.next(); final Entry<IMEMonitorHandlerReceiver<T>, Object> o = i.next();
final IMEMonitorHandlerReceiver<T> receiver = o.getKey(); final IMEMonitorHandlerReceiver<T> receiver = o.getKey();
if( receiver.isValid( o.getValue() ) ) if( receiver.isValid( o.getValue() ) && receiver.hasListeners() )
{ {
receiver.postChange( this, diff, src ); receiver.postChange( this, diff, src );
} }
@@ -217,26 +273,35 @@ 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 ) protected void postChange( final boolean add, final Iterable<T> changes, final IActionSource src )
{ {
if ( GLOBAL_DEPTH.contains( this )) if( this.localDepthSemaphore > 0 || GLOBAL_DEPTH.contains( this ) )
{ {
return; return;
} }
GLOBAL_DEPTH.push( this ); GLOBAL_DEPTH.push( this );
this.localDepthSemaphore++;
this.sendEvent = true; this.sendEvent = true;
for ( final T changedItem : changes ) for ( final T changedItem : changes )
{ {
T difference = changedItem;
if( !add && changedItem != null ) if( !add && changedItem != null )
{ {
changedItem.setStackSize( -changedItem.getStackSize() ); difference = changedItem.copy();
difference.setStackSize( -changedItem.getStackSize() );
} }
incGridCurrentCount( changedItem.getStackSize() ); incGridCurrentCount( difference.getStackSize() );
this.cachedList.add( changedItem ); this.cachedList.add( difference );
if( this.myGridCache.getInterestManager().containsKey( changedItem ) ) if( this.myGridCache.getInterestManager().containsKey( changedItem ) )
{ {
@@ -248,7 +313,7 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
for( final ItemWatcher iw : list ) for( final ItemWatcher iw : list )
{ {
iw.getHost().onStackChange( changedItem, this.getChannel() ); iw.getHost().onStackChange( difference, this.getChannel() );
} }
this.myGridCache.getInterestManager().disableTransactions(); this.myGridCache.getInterestManager().disableTransactions();
@@ -259,6 +324,7 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
this.notifyListenersOfChange( changes, src ); this.notifyListenersOfChange( changes, src );
final NetworkMonitor<?> last = GLOBAL_DEPTH.pop(); final NetworkMonitor<?> last = GLOBAL_DEPTH.pop();
this.localDepthSemaphore--;
if( last != this ) if( last != this )
{ {
@@ -268,7 +334,26 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
void forceUpdate() void forceUpdate()
{ {
this.forceUpdate = true; this.hasChanged = true;
//when the grid comes back online, reset the count to 0 so
//it reflects the correct amount after the changes are accounted for
if( myChannel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) )
{
gridItemCount = 0;
for( IAEItemStack iaeItemStack : (Iterable<IAEItemStack>) getStorageList() )
{
gridItemCount += iaeItemStack.getStackSize();
}
}
else if( myChannel == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) )
{
gridFluidCount = 0;
for( IAEFluidStack iaeFluidStack : (Iterable<IAEFluidStack>) getStorageList() )
{
gridFluidCount += iaeFluidStack.getStackSize();
}
}
final Iterator<Entry<IMEMonitorHandlerReceiver<T>, Object>> i = this.getListeners(); final Iterator<Entry<IMEMonitorHandlerReceiver<T>, Object>> i = this.getListeners();
while ( i.hasNext() ) while ( i.hasNext() )
@@ -19,10 +19,6 @@
package appeng.me.storage; 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 net.minecraft.item.ItemStack;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
@@ -40,7 +36,6 @@ public class DriveWatcher<T extends IAEStack<T>> extends MEInventoryHandler<T>
private final ItemStack is; private final ItemStack is;
private final ICellHandler handler; private final ICellHandler handler;
private final IChestOrDrive cord; private final IChestOrDrive cord;
private IActionSource source;
public DriveWatcher( final ICellInventoryHandler<T> i, final ItemStack is, final ICellHandler han, final IChestOrDrive cod ) public DriveWatcher( final ICellInventoryHandler<T> i, final ItemStack is, final ICellHandler han, final IChestOrDrive cod )
{ {
@@ -48,7 +43,6 @@ public class DriveWatcher<T extends IAEStack<T>> extends MEInventoryHandler<T>
this.is = is; this.is = is;
this.handler = han; this.handler = han;
this.cord = cod; this.cord = cod;
this.source = new MachineSource( cod );
} }
public int getStatus() public int getStatus()
@@ -72,14 +66,6 @@ public class DriveWatcher<T extends IAEStack<T>> extends MEInventoryHandler<T>
this.cord.blinkCell( this.getSlot() ); this.cord.blinkCell( this.getSlot() );
this.oldStatus = newStatus; 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; return a;
@@ -99,15 +85,6 @@ public class DriveWatcher<T extends IAEStack<T>> extends MEInventoryHandler<T>
this.cord.blinkCell( this.getSlot() ); this.cord.blinkCell( this.getSlot() );
this.oldStatus = newStatus; 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; 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() final IItemList<T> after = this.getInternal() == null ? this.getWrappedChannel().createList() : this.getInternal()
.getAvailableItems( new ItemListIgnoreCrafting( this.getWrappedChannel().createList() ) ); .getAvailableItems( new ItemListIgnoreCrafting( this.getWrappedChannel().createList() ) );
if( this.monitor != null && this.listeners.size() > 0 ) if( this.monitor != null )
{ {
this.monitor.addListener( this, this.monitor ); this.monitor.addListener( this, this.monitor );
} }
@@ -124,6 +124,12 @@ public class MEMonitorPassThrough<T extends IAEStack<T>> extends MEPassThrough<T
return verificationToken == this.monitor; return verificationToken == this.monitor;
} }
@Override
public boolean hasListeners()
{
return this.listeners.size() > 0;
}
@Override @Override
public void postChange( final IBaseMonitor<T> monitor, final Iterable<T> change, final IActionSource source ) public void postChange( final IBaseMonitor<T> monitor, final Iterable<T> change, final IActionSource source )
{ {
@@ -206,7 +206,7 @@ public class PartFormationPlane extends PartAbstractFormationPlane<IAEItemStack>
@Override @Override
public List<IMEInventoryHandler> getCellArray( final IStorageChannel channel ) public List<IMEInventoryHandler> getCellArray( final IStorageChannel channel )
{ {
if( channel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) if( this.getProxy().isActive() && channel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) )
{ {
final List<IMEInventoryHandler> handler = new ArrayList<>( 1 ); final List<IMEInventoryHandler> handler = new ArrayList<>( 1 );
handler.add( this.myHandler ); handler.add( this.myHandler );
@@ -19,16 +19,49 @@
package appeng.parts.automation; package appeng.parts.automation;
import java.util.Collections;
import java.util.Optional;
import java.util.Random;
import appeng.api.networking.events.*;
import appeng.me.Grid;
import appeng.me.GridNode;
import appeng.me.cache.NetworkMonitor;
import appeng.util.item.AEItemStack;
import appeng.util.item.OreHelper;
import appeng.util.item.OreReference;
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.AEApi;
import appeng.api.config.*; import appeng.api.config.FuzzyMode;
import appeng.api.networking.crafting.*; 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.networking.energy.IEnergyGrid; import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.energy.IEnergyWatcher; import appeng.api.networking.energy.IEnergyWatcher;
import appeng.api.networking.energy.IEnergyWatcherHost; import appeng.api.networking.energy.IEnergyWatcherHost;
import appeng.api.networking.events.MENetworkChannelsChanged;
import appeng.api.networking.events.MENetworkCraftingPatternChange;
import appeng.api.networking.events.MENetworkEventSubscribe;
import appeng.api.networking.events.MENetworkPowerStatusChange;
import appeng.api.networking.security.IActionSource; import appeng.api.networking.security.IActionSource;
import appeng.api.networking.storage.IBaseMonitor; import appeng.api.networking.storage.IBaseMonitor;
import appeng.api.networking.storage.IStackWatcher; import appeng.api.networking.storage.IStackWatcher;
@@ -49,28 +82,10 @@ import appeng.core.sync.GuiBridge;
import appeng.helpers.Reflected; import appeng.helpers.Reflected;
import appeng.items.parts.PartModels; import appeng.items.parts.PartModels;
import appeng.me.GridAccessException; import appeng.me.GridAccessException;
import appeng.me.cache.NetworkMonitor;
import appeng.parts.PartModel; import appeng.parts.PartModel;
import appeng.tile.inventory.AppEngInternalAEInventory; import appeng.tile.inventory.AppEngInternalAEInventory;
import appeng.util.Platform; import appeng.util.Platform;
import appeng.util.inv.InvOperation; 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 public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherHost, IStackWatcherHost, ICraftingWatcherHost, IMEMonitorHandlerReceiver<IAEItemStack>, ICraftingProvider
@@ -33,7 +33,6 @@ import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.core.AELog; import appeng.core.AELog;
import appeng.me.GridAccessException;
import appeng.me.helpers.IGridProxyable; import appeng.me.helpers.IGridProxyable;
import appeng.me.storage.ITickingMonitor; import appeng.me.storage.ITickingMonitor;
import appeng.util.inv.ItemHandlerIterator; import appeng.util.inv.ItemHandlerIterator;
@@ -118,15 +117,9 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
if( type == Actionable.MODULATE ) if( type == Actionable.MODULATE )
{ {
try this.cache
{ .currentlyCached
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); .add( AEItemStack.fromItemStack( orgInput ).setStackSize( orgInput.getCount() - remaining.getCount() ) );
}
catch( GridAccessException ex )
{
// meh
}
} }
return AEItemStack.fromItemStack( remaining ); return AEItemStack.fromItemStack( remaining );
@@ -200,13 +193,10 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
IAEItemStack gatheredAEItemStack = AEItemStack.fromItemStack( gathered ); IAEItemStack gatheredAEItemStack = AEItemStack.fromItemStack( gathered );
if( mode == Actionable.MODULATE ) if( mode == Actionable.MODULATE )
{ {
try IAEItemStack e = this.cache.currentlyCached.findPrecise( gatheredAEItemStack );
if (e != null)
{ {
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); e.decStackSize( gathered.getCount() );
}
catch( GridAccessException ex )
{
// meh
} }
} }
@@ -285,6 +275,7 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
private final StorageFilter mode; private final StorageFilter mode;
IItemList<IAEItemStack> currentlyCached = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); IItemList<IAEItemStack> currentlyCached = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
public InventoryCache( IItemHandler itemHandler, StorageFilter mode ) public InventoryCache( IItemHandler itemHandler, StorageFilter mode )
{ {
this.mode = mode; this.mode = mode;
@@ -13,7 +13,6 @@ import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.core.AELog; import appeng.core.AELog;
import appeng.me.GridAccessException;
import appeng.me.helpers.IGridProxyable; import appeng.me.helpers.IGridProxyable;
import appeng.me.storage.ITickingMonitor; import appeng.me.storage.ITickingMonitor;
import appeng.util.item.AEItemStack; import appeng.util.item.AEItemStack;
@@ -84,14 +83,9 @@ class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<
if( type == Actionable.MODULATE ) if( type == Actionable.MODULATE )
{ {
try this.cache
{ .currentlyCached
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); .add( AEItemStack.fromItemStack( orgInput ).setStackSize( orgInput.getCount() - remaining.getCount() ) );
}
catch( GridAccessException ex )
{
// meh
}
} }
return AEItemStack.fromItemStack( remaining ); return AEItemStack.fromItemStack( remaining );
@@ -111,8 +105,7 @@ class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<
{ {
// Something broke. It should never return more than we requested... // Something broke. It should never return more than we requested...
// We're going to silently eat the remainder // We're going to silently eat the remainder
AELog.warn( "Mod that provided item handler %s is broken. Returned %s items while only requesting %d.", AELog.warn( "Mod that provided item handler %s is broken. Returned %s items while only requesting %d.", this.itemRepository.getClass().getName(), extracted.toString(), remainingSize );
this.itemRepository.getClass().getName(), extracted.toString(), remainingSize );
extracted.setCount( remainingSize ); extracted.setCount( remainingSize );
} }
@@ -121,13 +114,10 @@ class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<
IAEItemStack extractedAEItemStack = AEItemStack.fromItemStack( extracted ); IAEItemStack extractedAEItemStack = AEItemStack.fromItemStack( extracted );
if( mode == Actionable.MODULATE ) if( mode == Actionable.MODULATE )
{ {
try IAEItemStack e = this.cache.currentlyCached.findPrecise( extractedAEItemStack );
if (e != null)
{ {
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); e.decStackSize( extracted.getCount() );
}
catch( GridAccessException ex )
{
// meh
} }
} }
return extractedAEItemStack; return extractedAEItemStack;
@@ -264,7 +264,8 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
{ {
this.getProxy().getStorage().postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), change, this.mySrc ); this.getProxy().getStorage().postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), change, this.mySrc );
} }
} catch ( final GridAccessException e ) }
catch( final GridAccessException e )
{ {
// :( // :(
} }
@@ -554,10 +554,14 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
@Override @Override
public List<IMEInventoryHandler> getCellArray( final IStorageChannel channel ) public List<IMEInventoryHandler> getCellArray( final IStorageChannel channel )
{ {
this.updateHandler(); if( this.getProxy().isActive() )
if( this.cellHandler != null && this.cellHandler.getChannel() == channel )
{ {
return Collections.singletonList( this.cellHandler ); this.updateHandler();
if( this.cellHandler != null && this.cellHandler.getChannel() == channel )
{
return Collections.singletonList( this.cellHandler );
}
} }
return Collections.emptyList(); return Collections.emptyList();
} }
@@ -688,16 +692,21 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
@Override @Override
public void postChange( final IBaseMonitor<T> monitor, final Iterable<T> change, final IActionSource source ) public void postChange( final IBaseMonitor<T> monitor, final Iterable<T> change, final IActionSource source )
{ {
try if( source == TileChest.this.mySrc || source.machine().map( machine -> machine == TileChest.this ).orElse( false ) )
{ {
if( TileChest.this.getProxy().isActive() ) try
{ {
TileChest.this.getProxy().getStorage().postAlterationOfStoredItems( this.chan, change, TileChest.this.mySrc ); if( TileChest.this.getProxy().isActive() )
{
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 );
} }
@@ -334,8 +334,13 @@ public class TileDrive extends AENetworkInvTile implements IChestOrDrive, IPrior
@Override @Override
public List<IMEInventoryHandler> getCellArray( final IStorageChannel channel ) public List<IMEInventoryHandler> getCellArray( final IStorageChannel channel )
{ {
this.updateState(); if( this.getProxy().isActive() )
return this.inventoryHandlers.get( channel ); {
this.updateState();
return this.inventoryHandlers.get( channel );
}
return Collections.emptyList();
} }
@Override @Override