Replaced Watcher using Collection with a more fitting interface (#2693)

Replaced the watchers for energy, storage and crafting with a more fitting interface compared to a common collection.

Fixes #229
This commit is contained in:
yueh 2016-12-14 18:30:49 +01:00 committed by GitHub
parent e3305c1963
commit fb79fd284d
12 changed files with 211 additions and 433 deletions

View File

@ -24,12 +24,36 @@
package appeng.api.networking.crafting;
import java.util.Collection;
import appeng.api.storage.data.IAEStack;
public interface ICraftingWatcher extends Collection<IAEStack>
/**
* DO NOT IMPLEMENT.
*
* Will be injected when adding an {@link ICraftingWatcherHost} to a grid.
*/
public interface ICraftingWatcher
{
/**
* Add a specific {@link IAEStack} to watch.
*
* Supports multiple values, duplicate ones will not be added.
*
* @param stack
* @return true, if successfully added.
*/
boolean add( IAEStack<?> stack );
/**
* Remove a specific {@link IAEStack} from the watcher.
*
* @param stack
* @return true, if successfully removed.
*/
boolean remove( IAEStack<?> stack );
/**
* Removes all watched stacks and resets the watcher to a clean state.
*/
void reset();
}

View File

@ -24,10 +24,34 @@
package appeng.api.networking.energy;
import java.util.Collection;
public interface IEnergyWatcher extends Collection<Double>
/**
* DO NOT IMPLEMENT.
*
* Will be injected when adding an {@link IEnergyWatcherHost} to a grid.
*/
public interface IEnergyWatcher
{
/**
* Add a specific threshold to watch.
*
* Supports multiple values, duplicate ones will not be added.
*
* @param amount
* @return true, if successfully added.
*/
boolean add( double amount );
/**
* Remove a specific threshold from the watcher.
*
* @param amount
* @return true, if successfully removed.
*/
boolean remove( double amount );
/**
* Removes all thresholds and resets the watcher to a clean state.
*/
void reset();
}

View File

@ -24,12 +24,36 @@
package appeng.api.networking.storage;
import java.util.Collection;
import appeng.api.storage.data.IAEStack;
public interface IStackWatcher extends Collection<IAEStack>
/**
* DO NOT IMPLEMENT.
*
* Will be injected when adding an {@link IStackWatcherHost} to a grid.
*/
public interface IStackWatcher
{
/**
* Add a specific {@link IAEStack} to watch.
*
* Supports multiple values, duplicate ones will not be added.
*
* @param stack
* @return true, if successfully added.
*/
boolean add( IAEStack<?> stack );
/**
* Remove a specific {@link IAEStack} from the watcher.
*
* @param stack
* @return true, if successfully removed.
*/
boolean remove( IAEStack<?> stack );
/**
* Removes all watched stacks and resets the watcher to a clean state.
*/
void reset();
}

View File

@ -19,11 +19,9 @@
package appeng.crafting;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import javax.annotation.Nonnull;
import java.util.Set;
import appeng.api.networking.crafting.ICraftingWatcher;
import appeng.api.networking.crafting.ICraftingWatcherHost;
@ -39,7 +37,7 @@ public class CraftingWatcher implements ICraftingWatcher
private final CraftingGridCache gsc;
private final ICraftingWatcherHost host;
private final HashSet<IAEStack> myInterests = new HashSet<IAEStack>();
private final Set<IAEStack> myInterests = new HashSet<IAEStack>();
public CraftingWatcher( final CraftingGridCache cache, final ICraftingWatcherHost host )
{
@ -52,45 +50,6 @@ public class CraftingWatcher implements ICraftingWatcher
return this.host;
}
@Override
public int size()
{
return this.myInterests.size();
}
@Override
public boolean isEmpty()
{
return this.myInterests.isEmpty();
}
@Override
public boolean contains( final Object o )
{
return this.myInterests.contains( o );
}
@Nonnull
@Override
public Iterator<IAEStack> iterator()
{
return new ItemWatcherIterator( this, this.myInterests.iterator() );
}
@Nonnull
@Override
public Object[] toArray()
{
return this.myInterests.toArray();
}
@Nonnull
@Override
public <T> T[] toArray( @Nonnull final T[] a )
{
return this.myInterests.toArray( a );
}
@Override
public boolean add( final IAEStack e )
{
@ -103,100 +62,20 @@ public class CraftingWatcher implements ICraftingWatcher
}
@Override
public boolean remove( final Object o )
public boolean remove( final IAEStack o )
{
return this.myInterests.remove( o ) && this.gsc.getInterestManager().remove( (IAEStack) o, this );
}
@Override
public boolean containsAll( @Nonnull final Collection<?> c )
{
return this.myInterests.containsAll( c );
}
@Override
public boolean addAll( @Nonnull final Collection<? extends IAEStack> c )
{
boolean didChange = false;
for( final IAEStack o : c )
{
didChange = this.add( o ) || didChange;
}
return didChange;
}
@Override
public boolean removeAll( @Nonnull final Collection<?> c )
{
boolean didSomething = false;
for( final Object o : c )
{
didSomething = this.remove( o ) || didSomething;
}
return didSomething;
}
@Override
public boolean retainAll( @Nonnull final Collection<?> c )
{
boolean changed = false;
final Iterator<IAEStack> i = this.iterator();
while( i.hasNext() )
{
if( !c.contains( i.next() ) )
{
i.remove();
changed = true;
}
}
return changed;
}
@Override
public void clear()
public void reset()
{
final Iterator<IAEStack> i = this.myInterests.iterator();
while( i.hasNext() )
{
this.gsc.getInterestManager().remove( i.next(), this );
i.remove();
}
}
private class ItemWatcherIterator implements Iterator<IAEStack>
{
private final CraftingWatcher watcher;
private final Iterator<IAEStack> interestIterator;
private IAEStack myLast;
public ItemWatcherIterator( final CraftingWatcher parent, final Iterator<IAEStack> i )
{
this.watcher = parent;
this.interestIterator = i;
}
@Override
public boolean hasNext()
{
return this.interestIterator.hasNext();
}
@Override
public IAEStack next()
{
return this.myLast = this.interestIterator.next();
}
@Override
public void remove()
{
CraftingWatcher.this.gsc.getInterestManager().remove( this.myLast, this.watcher );
this.interestIterator.remove();
}
}
}

View File

@ -172,7 +172,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
final ICraftingWatcher craftingWatcher = this.craftingWatchers.get( machine );
if( craftingWatcher != null )
{
craftingWatcher.clear();
craftingWatcher.reset();
this.craftingWatchers.remove( machine );
}
}

View File

@ -23,11 +23,12 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.NavigableSet;
import java.util.Set;
import java.util.TreeSet;
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.Actionable;
@ -58,8 +59,8 @@ import appeng.me.energy.EnergyWatcher;
public class EnergyGridCache implements IEnergyGrid
{
private final TreeSet<EnergyThreshold> interests = new TreeSet<EnergyThreshold>();
private final double AvgLength = 40.0;
private final NavigableSet<EnergyThreshold> interests = Sets.newTreeSet();
private final double averageLength = 40.0;
private final Set<IAEPowerStorage> providers = new LinkedHashSet<IAEPowerStorage>();
private final Set<IAEPowerStorage> requesters = new LinkedHashSet<IAEPowerStorage>();
private final Multiset<IEnergyGridProvider> energyGridProviders = HashMultiset.create();
@ -150,24 +151,25 @@ public class EnergyGridCache implements IEnergyGrid
@Override
public void onUpdateTick()
{
if( !this.getInterests().isEmpty() )
if( !this.interests.isEmpty() )
{
final double oldPower = this.lastStoredPower;
this.lastStoredPower = this.getStoredPower();
final EnergyThreshold low = new EnergyThreshold( Math.min( oldPower, this.lastStoredPower ), null );
final EnergyThreshold high = new EnergyThreshold( Math.max( oldPower, this.lastStoredPower ), null );
for( final EnergyThreshold th : this.getInterests().subSet( low, true, high, true ) )
final EnergyThreshold low = new EnergyThreshold( Math.min( oldPower, this.lastStoredPower ), Integer.MIN_VALUE );
final EnergyThreshold high = new EnergyThreshold( Math.max( oldPower, this.lastStoredPower ), Integer.MAX_VALUE );
for( final EnergyThreshold th : this.interests.subSet( low, true, high, true ) )
{
( (EnergyWatcher) th.getWatcher() ).post( this );
( (EnergyWatcher) th.getEnergyWatcher() ).post( this );
}
}
this.avgDrainPerTick *= ( this.AvgLength - 1 ) / this.AvgLength;
this.avgInjectionPerTick *= ( this.AvgLength - 1 ) / this.AvgLength;
this.avgDrainPerTick *= ( this.averageLength - 1 ) / this.averageLength;
this.avgInjectionPerTick *= ( this.averageLength - 1 ) / this.averageLength;
this.avgDrainPerTick += this.tickDrainPerTick / this.AvgLength;
this.avgInjectionPerTick += this.tickInjectionPerTick / this.AvgLength;
this.avgDrainPerTick += this.tickDrainPerTick / this.averageLength;
this.avgInjectionPerTick += this.tickInjectionPerTick / this.averageLength;
this.tickDrainPerTick = 0;
this.tickInjectionPerTick = 0;
@ -554,7 +556,7 @@ public class EnergyGridCache implements IEnergyGrid
final IEnergyWatcher myWatcher = this.watchers.get( machine );
if( myWatcher != null )
{
myWatcher.clear();
myWatcher.reset();
this.watchers.remove( machine );
}
}
@ -631,8 +633,14 @@ public class EnergyGridCache implements IEnergyGrid
storage.dataObject().setDouble( "extraEnergy", this.extra );
}
public TreeSet<EnergyThreshold> getInterests()
public boolean registerEnergyInterest( final EnergyThreshold threshold )
{
return this.interests;
return this.interests.add( threshold );
}
public boolean unregisterEnergyInterest( final EnergyThreshold threshold )
{
return this.interests.remove( threshold );
}
}

View File

@ -102,7 +102,7 @@ public class GridStorageCache implements IStorageGrid
if( myWatcher != null )
{
myWatcher.clear();
myWatcher.reset();
this.watchers.remove( machine );
}
}

View File

@ -20,50 +20,98 @@ package appeng.me.energy;
import appeng.api.networking.energy.IEnergyWatcher;
import appeng.util.ItemSorters;
public class EnergyThreshold implements Comparable<EnergyThreshold>
{
private final double Limit;
private final double threshold;
private final IEnergyWatcher watcher;
private final int hash;
private final int watcherHash;
public EnergyThreshold( final double lim, final IEnergyWatcher wat )
public EnergyThreshold( final double lim, final IEnergyWatcher watcher )
{
this.Limit = lim;
this.watcher = wat;
this.threshold = lim;
this.watcher = watcher;
this.watcherHash = watcher.hashCode();
}
if( this.getWatcher() != null )
/**
* Special constructor to allow querying a for a subset of thresholds.
*
* @param lim
* @param bound
*/
public EnergyThreshold( final double lim, final int bound )
{
this.threshold = lim;
this.watcher = null;
this.watcherHash = bound;
}
public IEnergyWatcher getEnergyWatcher()
{
return watcher;
}
@Override
public int compareTo( EnergyThreshold o )
{
int a = Double.compare( this.threshold, o.threshold );
if( a == 0 )
{
this.hash = this.getWatcher().hashCode() ^ ( (Double) lim ).hashCode();
}
else
{
this.hash = ( (Double) lim ).hashCode();
return Integer.compare( this.watcherHash, o.watcherHash );
}
return a;
}
@Override
public int hashCode()
{
return this.hash;
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits( threshold );
result = prime * result + (int) ( temp ^ ( temp >>> 32 ) );
result = prime * result + ( ( watcher == null ) ? 0 : watcher.hashCode() );
return result;
}
@Override
public int compareTo( final EnergyThreshold o )
public boolean equals( Object obj )
{
return ItemSorters.compareDouble( this.getLimit(), o.getLimit() );
}
if( this == obj )
{
return true;
}
if( obj == null )
{
return false;
}
if( getClass() != obj.getClass() )
{
return false;
}
double getLimit()
{
return this.Limit;
}
EnergyThreshold other = (EnergyThreshold) obj;
if( Double.doubleToLongBits( threshold ) != Double.doubleToLongBits( other.threshold ) )
{
return false;
}
public IEnergyWatcher getWatcher()
{
return this.watcher;
if( watcher == null )
{
if( other.watcher != null )
{
return false;
}
}
else if( !watcher.equals( other.watcher ) )
{
return false;
}
return true;
}
}

View File

@ -19,9 +19,9 @@
package appeng.me.energy;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import appeng.api.networking.energy.IEnergyWatcher;
import appeng.api.networking.energy.IEnergyWatcherHost;
@ -35,170 +35,57 @@ public class EnergyWatcher implements IEnergyWatcher
{
private final EnergyGridCache gsc;
private final IEnergyWatcherHost myObject;
private final HashSet<EnergyThreshold> myInterests = new HashSet<EnergyThreshold>();
private final IEnergyWatcherHost watcherHost;
private final Set<EnergyThreshold> myInterests = new HashSet<EnergyThreshold>();
public EnergyWatcher( final EnergyGridCache cache, final IEnergyWatcherHost host )
{
this.gsc = cache;
this.myObject = host;
this.watcherHost = host;
}
public void post( final EnergyGridCache energyGridCache )
{
this.myObject.onThresholdPass( energyGridCache );
this.watcherHost.onThresholdPass( energyGridCache );
}
public IEnergyWatcherHost getHost()
{
return this.myObject;
return this.watcherHost;
}
@Override
public int size()
public boolean add( final double amount )
{
return this.myInterests.size();
}
final EnergyThreshold eh = new EnergyThreshold( amount, this );
@Override
public boolean isEmpty()
{
return this.myInterests.isEmpty();
}
if( this.myInterests.contains( eh ) )
@Override
public boolean contains( final Object o )
{
return this.myInterests.contains( o );
}
@Override
public Iterator<Double> iterator()
{
return new EnergyWatcherIterator( this, this.myInterests.iterator() );
}
@Override
public Object[] toArray()
{
return this.myInterests.toArray();
}
@Override
public <T> T[] toArray( final T[] a )
{
return this.myInterests.toArray( a );
}
@Override
public boolean add( final Double e )
{
if( this.myInterests.contains( e ) )
{
return false;
}
final EnergyThreshold eh = new EnergyThreshold( e, this );
return this.gsc.getInterests().add( eh ) && this.myInterests.add( eh );
return this.gsc.registerEnergyInterest( eh ) && this.myInterests.add( eh );
}
@Override
public boolean remove( final Object o )
public boolean remove( final double amount )
{
final EnergyThreshold eh = new EnergyThreshold( (Double) o, this );
return this.myInterests.remove( eh ) && this.gsc.getInterests().remove( eh );
final EnergyThreshold eh = new EnergyThreshold( amount, this );
return this.myInterests.remove( eh ) && this.gsc.unregisterEnergyInterest( eh );
}
@Override
public boolean containsAll( final Collection<?> c )
public void reset()
{
return this.myInterests.containsAll( c );
}
@Override
public boolean addAll( final Collection<? extends Double> c )
{
boolean didChange = false;
for( final Double o : c )
for( Iterator<EnergyThreshold> iterator = myInterests.iterator(); iterator.hasNext(); )
{
didChange = this.add( o ) || didChange;
}
final EnergyThreshold threshold = iterator.next();
return didChange;
}
@Override
public boolean removeAll( final Collection<?> c )
{
boolean didSomething = false;
for( final Object o : c )
{
didSomething = this.remove( o ) || didSomething;
}
return didSomething;
}
@Override
public boolean retainAll( final Collection<?> c )
{
boolean changed = false;
final Iterator<Double> i = this.iterator();
while( i.hasNext() )
{
if( !c.contains( i.next() ) )
{
i.remove();
changed = true;
}
}
return changed;
}
@Override
public void clear()
{
final Iterator<EnergyThreshold> i = this.myInterests.iterator();
while( i.hasNext() )
{
this.gsc.getInterests().remove( i.next() );
i.remove();
this.gsc.unregisterEnergyInterest( threshold );
iterator.remove();
}
}
private class EnergyWatcherIterator implements Iterator<Double>
{
private final EnergyWatcher watcher;
private final Iterator<EnergyThreshold> interestIterator;
private EnergyThreshold myLast;
public EnergyWatcherIterator( final EnergyWatcher parent, final Iterator<EnergyThreshold> i )
{
this.watcher = parent;
this.interestIterator = i;
}
@Override
public boolean hasNext()
{
return this.interestIterator.hasNext();
}
@Override
public Double next()
{
this.myLast = this.interestIterator.next();
return this.myLast.getLimit();
}
@Override
public void remove()
{
EnergyWatcher.this.gsc.getInterests().remove( this.myLast );
this.interestIterator.remove();
}
}
}

View File

@ -19,9 +19,9 @@
package appeng.me.storage;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import appeng.api.networking.storage.IStackWatcher;
import appeng.api.networking.storage.IStackWatcherHost;
@ -37,7 +37,7 @@ public class ItemWatcher implements IStackWatcher
private final GridStorageCache gsc;
private final IStackWatcherHost myObject;
private final HashSet<IAEStack> myInterests = new HashSet<IAEStack>();
private final Set<IAEStack> myInterests = new HashSet<IAEStack>();
public ItemWatcher( final GridStorageCache cache, final IStackWatcherHost host )
{
@ -50,42 +50,6 @@ public class ItemWatcher implements IStackWatcher
return this.myObject;
}
@Override
public int size()
{
return this.myInterests.size();
}
@Override
public boolean isEmpty()
{
return this.myInterests.isEmpty();
}
@Override
public boolean contains( final Object o )
{
return this.myInterests.contains( o );
}
@Override
public Iterator<IAEStack> iterator()
{
return new ItemWatcherIterator( this, this.myInterests.iterator() );
}
@Override
public Object[] toArray()
{
return this.myInterests.toArray();
}
@Override
public <T> T[] toArray( final T[] a )
{
return this.myInterests.toArray( a );
}
@Override
public boolean add( final IAEStack e )
{
@ -98,100 +62,20 @@ public class ItemWatcher implements IStackWatcher
}
@Override
public boolean remove( final Object o )
public boolean remove( final IAEStack o )
{
return this.myInterests.remove( o ) && this.gsc.getInterestManager().remove( (IAEStack) o, this );
}
@Override
public boolean containsAll( final Collection<?> c )
{
return this.myInterests.containsAll( c );
}
@Override
public boolean addAll( final Collection<? extends IAEStack> c )
{
boolean didChange = false;
for( final IAEStack o : c )
{
didChange = this.add( o ) || didChange;
}
return didChange;
}
@Override
public boolean removeAll( final Collection<?> c )
{
boolean didSomething = false;
for( final Object o : c )
{
didSomething = this.remove( o ) || didSomething;
}
return didSomething;
}
@Override
public boolean retainAll( final Collection<?> c )
{
boolean changed = false;
final Iterator<IAEStack> i = this.iterator();
while( i.hasNext() )
{
if( !c.contains( i.next() ) )
{
i.remove();
changed = true;
}
}
return changed;
}
@Override
public void clear()
public void reset()
{
final Iterator<IAEStack> i = this.myInterests.iterator();
while( i.hasNext() )
{
this.gsc.getInterestManager().remove( i.next(), this );
i.remove();
}
}
private class ItemWatcherIterator implements Iterator<IAEStack>
{
private final ItemWatcher watcher;
private final Iterator<IAEStack> interestIterator;
private IAEStack myLast;
public ItemWatcherIterator( final ItemWatcher parent, final Iterator<IAEStack> i )
{
this.watcher = parent;
this.interestIterator = i;
}
@Override
public boolean hasNext()
{
return this.interestIterator.hasNext();
}
@Override
public IAEStack next()
{
return this.myLast = this.interestIterator.next();
}
@Override
public void remove()
{
ItemWatcher.this.gsc.getInterestManager().remove( this.myLast, this.watcher );
this.interestIterator.remove();
}
}
}

View File

@ -229,17 +229,17 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH
if( this.myWatcher != null )
{
this.myWatcher.clear();
this.myWatcher.reset();
}
if( this.myEnergyWatcher != null )
{
this.myEnergyWatcher.clear();
this.myEnergyWatcher.reset();
}
if( this.myCraftingWatcher != null )
{
this.myCraftingWatcher.clear();
this.myCraftingWatcher.reset();
}
try

View File

@ -190,7 +190,7 @@ public abstract class AbstractPartMonitor extends AbstractPartDisplay implements
{
if( this.myWatcher != null )
{
this.myWatcher.clear();
this.myWatcher.reset();
}
try