From 8abf2ed8ac0ded03586a0fbfb4091651f2543d8f Mon Sep 17 00:00:00 2001 From: thatsIch Date: Sun, 30 Nov 2014 04:58:08 +0100 Subject: [PATCH] Basic enhancement of the grid for overall usage has some performance improvement replaced outdated classes --- src/main/java/appeng/me/Grid.java | 224 ++--- src/main/java/appeng/me/GridConnection.java | 10 +- src/main/java/appeng/me/GridNode.java | 781 +++++++++--------- ...eIterable.java => GridNodeCollection.java} | 46 +- src/main/java/appeng/me/GridNodeIterator.java | 86 ++ src/main/java/appeng/me/GridPropagator.java | 16 +- src/main/java/appeng/me/NetworkEventBus.java | 170 ++-- src/main/java/appeng/me/NodeIterator.java | 71 -- 8 files changed, 741 insertions(+), 663 deletions(-) rename src/main/java/appeng/me/{NodeIterable.java => GridNodeCollection.java} (54%) create mode 100644 src/main/java/appeng/me/GridNodeIterator.java delete mode 100644 src/main/java/appeng/me/NodeIterator.java diff --git a/src/main/java/appeng/me/Grid.java b/src/main/java/appeng/me/Grid.java index 71449182..9c4a59f4 100644 --- a/src/main/java/appeng/me/Grid.java +++ b/src/main/java/appeng/me/Grid.java @@ -18,9 +18,11 @@ package appeng.me; + import java.util.Collection; import java.util.HashMap; import java.util.Iterator; +import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -29,6 +31,7 @@ import appeng.api.networking.IGrid; import appeng.api.networking.IGridCache; import appeng.api.networking.IGridHost; import appeng.api.networking.IGridNode; +import appeng.api.networking.IGridStorage; import appeng.api.networking.IMachineSet; import appeng.api.networking.events.MENetworkEvent; import appeng.api.networking.events.MENetworkPostCacheConstruction; @@ -37,86 +40,104 @@ import appeng.core.WorldSettings; import appeng.hooks.TickHandler; import appeng.util.ReadOnlyCollection; + public class Grid implements IGrid { + private final NetworkEventBus eventBus = new NetworkEventBus(); + private final Map, MachineSet> machines = new HashMap, MachineSet>(); + private final Map, GridCacheWrapper> caches = new HashMap, GridCacheWrapper>(); + private GridNode pivot; + private int priority; // how import is this network? + private GridStorage myStorage; - GridStorage myStorage; - - final NetworkEventBus bus = new NetworkEventBus(); - final HashMap, Set> Machines = new HashMap, Set>(); - final HashMap, GridCacheWrapper> caches = new HashMap, GridCacheWrapper>(); - - GridNode pivot; - int isImportant; // how import is this network? - - public Grid(GridNode center) { + public Grid( GridNode center ) + { this.pivot = center; - HashMap, IGridCache> myCaches = AEApi.instance().registries().gridCache().createCacheInstance( this ); - for (Entry, IGridCache> c : myCaches.entrySet()) + Map, IGridCache> myCaches = AEApi.instance().registries().gridCache().createCacheInstance( this ); + for ( Entry, IGridCache> c : myCaches.entrySet() ) { - bus.readClass( c.getKey(), c.getValue().getClass() ); - caches.put( c.getKey(), new GridCacheWrapper( c.getValue() ) ); + Class key = c.getKey(); + IGridCache value = c.getValue(); + Class valueClass = value.getClass(); + + this.eventBus.readClass( key, valueClass ); + this.caches.put( key, new GridCacheWrapper( value ) ); } - postEvent( new MENetworkPostCacheConstruction() ); + this.postEvent( new MENetworkPostCacheConstruction() ); TickHandler.instance.addNetwork( this ); center.setGrid( this ); } - public Set> getMachineClasses() + public int getPriority() { - return Machines.keySet(); + return this.priority; } - @Override - public IGridNode getPivot() + public IGridStorage getMyStorage() { - return pivot; + return this.myStorage; + } + + public Map, GridCacheWrapper> getCaches() + { + return this.caches; + } + + public Iterable> getMachineClasses() + { + return this.machines.keySet(); } public int size() { int out = 0; - for (Collection x : Machines.values()) + for ( Collection x : this.machines.values() ) out += x.size(); return out; } - public void remove(GridNode gridNode) + public void remove( GridNode gridNode ) { - for (IGridCache c : caches.values()) - c.removeNode( gridNode, gridNode.getMachine() ); + for ( IGridCache c : this.caches.values() ) + { + IGridHost machine = gridNode.getMachine(); + c.removeNode( gridNode, machine ); + } - Collection nodes = Machines.get( gridNode.getMachineClass() ); + Class machineClass = gridNode.getMachineClass(); + Set nodes = this.machines.get( machineClass ); if ( nodes != null ) nodes.remove( gridNode ); gridNode.setGridStorage( null ); - if ( pivot == gridNode ) + if ( this.pivot == gridNode ) { - Iterator n = getNodes().iterator(); + Iterator n = this.getNodes().iterator(); if ( n.hasNext() ) - pivot = (GridNode) n.next(); + this.pivot = ( GridNode ) n.next(); else { - pivot = null; + this.pivot = null; TickHandler.instance.removeNetwork( this ); - myStorage.remove(); + this.myStorage.remove(); } } } - public void add(GridNode gridNode) + public void add( GridNode gridNode ) { Class mClass = gridNode.getMachineClass(); - Set nodes = Machines.get( mClass ); + + MachineSet nodes = this.machines.get( mClass ); if ( nodes == null ) { - Machines.put( mClass, nodes = new MachineSet( mClass ) ); - bus.readClass( mClass, mClass ); + nodes = new MachineSet( mClass ); + this.machines.put( mClass, nodes ); + this.eventBus.readClass( mClass, mClass ); } // handle loading grid storages. @@ -127,130 +148,135 @@ public class Grid implements IGrid if ( grid == null ) { - myStorage = gs; - myStorage.setGrid( this ); + this.myStorage = gs; + this.myStorage.setGrid( this ); - for (IGridCache gc : caches.values()) - gc.onJoin( myStorage ); + for ( IGridCache gc : this.caches.values() ) + gc.onJoin( this.myStorage ); } else if ( grid != this ) { - if ( myStorage == null ) + if ( this.myStorage == null ) { - myStorage = WorldSettings.getInstance().getNewGridStorage(); - myStorage.setGrid( this ); + this.myStorage = WorldSettings.getInstance().getNewGridStorage(); + this.myStorage.setGrid( this ); } - GridStorage tmp = new GridStorage(); - if ( !gs.hasDivided( myStorage ) ) + IGridStorage tmp = new GridStorage(); + if ( !gs.hasDivided( this.myStorage ) ) { - gs.addDivided( myStorage ); + gs.addDivided( this.myStorage ); - for (IGridCache gc : ((Grid) grid).caches.values()) + for ( IGridCache gc : ( ( Grid ) grid ).caches.values() ) gc.onSplit( tmp ); - for (IGridCache gc : caches.values()) + for ( IGridCache gc : this.caches.values() ) gc.onJoin( tmp ); } } } - else if ( myStorage == null ) + else if ( this.myStorage == null ) { - myStorage = WorldSettings.getInstance().getNewGridStorage(); - myStorage.setGrid( this ); + this.myStorage = WorldSettings.getInstance().getNewGridStorage(); + this.myStorage.setGrid( this ); } // update grid node... - gridNode.setGridStorage( myStorage ); + gridNode.setGridStorage( this.myStorage ); // track node. nodes.add( gridNode ); - for (IGridCache c : caches.values()) - c.addNode( gridNode, gridNode.getMachine() ); + for ( IGridCache cache : this.caches.values() ) + { + IGridHost machine = gridNode.getMachine(); + cache.addNode( gridNode, machine ); + } - gridNode.gridProxy.gridChanged(); + gridNode.getGridProxy().gridChanged(); // postEventTo( gridNode, networkChanged ); } @Override - public IReadOnlyCollection getNodes() + @SuppressWarnings( "unchecked" ) + public C getCache( Class iface ) { - return new NodeIterable( Machines ); + return ( C ) this.caches.get( iface ).myCache; + } + + @Override + public MENetworkEvent postEvent( MENetworkEvent ev ) + { + return this.eventBus.postEvent( this, ev ); + } + + @Override + public MENetworkEvent postEventTo( IGridNode node, MENetworkEvent ev ) + { + return this.eventBus.postEventTo( this, ( GridNode ) node, ev ); } @Override public IReadOnlyCollection> getMachinesClasses() { - return new ReadOnlyCollection>( Machines.keySet() ); + Set> machineKeys = this.machines.keySet(); + + return new ReadOnlyCollection>( machineKeys ); } @Override - public IMachineSet getMachines(Class c) + public IMachineSet getMachines( Class c ) { - MachineSet s = (MachineSet) Machines.get( c ); + MachineSet s = this.machines.get( c ); if ( s == null ) return new MachineSet( c ); return s; } @Override - public C getCache(Class iface) + public IReadOnlyCollection getNodes() { - return (C) caches.get( iface ).myCache; - } - - @Override - public MENetworkEvent postEventTo(IGridNode node, MENetworkEvent ev) - { - return bus.postEventTo( this, (GridNode) node, ev ); - } - - @Override - public MENetworkEvent postEvent(MENetworkEvent ev) - { - return bus.postEvent( this, ev ); - } - - public void requestSave() - { - myStorage.markDirty(); - WorldSettings.getInstance().save(); - } - - public void update() - { - for (IGridCache gc : caches.values()) - { - // are there any nodes left? - if ( pivot != null ) - gc.onUpdateTick(); - } - } - - public Iterable getCacheWrappers() - { - return caches.values(); + return new GridNodeCollection( this.machines ); } @Override public boolean isEmpty() { - return pivot == null; + return this.pivot == null; + } + + @Override + public IGridNode getPivot() + { + return this.pivot; + } + + public void setPivot( GridNode pivot ) + { + this.pivot = pivot; + } + + public void update() + { + for ( IGridCache gc : this.caches.values() ) + { + // are there any nodes left? + if ( this.pivot != null ) + gc.onUpdateTick(); + } } public void saveState() { - for (IGridCache c : caches.values()) + for ( IGridCache c : this.caches.values() ) { - c.populateGridStorage( myStorage ); + c.populateGridStorage( this.myStorage ); } } - public void setImportantFlag(int i, boolean publicHasPower) + public void setImportantFlag( int i, boolean publicHasPower ) { int flag = 1 << i; - isImportant = (isImportant & ~flag) | (publicHasPower ? flag : 0); + this.priority = ( this.priority & ~flag ) | ( publicHasPower ? flag : 0 ); } - } diff --git a/src/main/java/appeng/me/GridConnection.java b/src/main/java/appeng/me/GridConnection.java index b3cbae9c..051a5239 100644 --- a/src/main/java/appeng/me/GridConnection.java +++ b/src/main/java/appeng/me/GridConnection.java @@ -18,10 +18,12 @@ package appeng.me; + import java.util.Arrays; import java.util.EnumSet; import net.minecraftforge.common.util.ForgeDirection; + import appeng.api.exceptions.FailedConnection; import appeng.api.networking.GridFlags; import appeng.api.networking.IGridConnection; @@ -75,18 +77,18 @@ public class GridConnection implements IGridConnection, IPathItem this.fromAtoB = fromAtoB; sideB = b; - if ( b.myGrid == null ) + if ( b.getMyGrid() == null ) { b.setGrid( a.getInternalGrid() ); } else { - if ( a.myGrid == null ) + if ( a.getMyGrid() == null ) { GridPropagator gp = new GridPropagator( b.getInternalGrid() ); a.beginVisit( gp ); } - else if ( b.myGrid == null ) + else if ( b.getMyGrid() == null ) { GridPropagator gp = new GridPropagator( a.getInternalGrid() ); b.beginVisit( gp ); @@ -113,7 +115,7 @@ public class GridConnection implements IGridConnection, IPathItem private boolean isNetworkABetter(GridNode a, GridNode b) { - return a.myGrid.isImportant > b.myGrid.isImportant || a.myGrid.size() > b.myGrid.size(); + return a.getMyGrid().getPriority() > b.getMyGrid().getPriority() || a.getMyGrid().size() > b.getMyGrid().size(); } @Override diff --git a/src/main/java/appeng/me/GridNode.java b/src/main/java/appeng/me/GridNode.java index b64edc20..037cd1a0 100644 --- a/src/main/java/appeng/me/GridNode.java +++ b/src/main/java/appeng/me/GridNode.java @@ -18,8 +18,10 @@ package appeng.me; + import java.util.Collections; import java.util.Comparator; +import java.util.Deque; import java.util.EnumSet; import java.util.LinkedList; import java.util.List; @@ -29,14 +31,15 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; + import appeng.api.exceptions.FailedConnection; import appeng.api.networking.GridFlags; import appeng.api.networking.GridNotification; import appeng.api.networking.IGrid; import appeng.api.networking.IGridBlock; import appeng.api.networking.IGridCache; -import appeng.api.networking.IGridConnectionVisitor; import appeng.api.networking.IGridConnection; +import appeng.api.networking.IGridConnectionVisitor; import appeng.api.networking.IGridHost; import appeng.api.networking.IGridNode; import appeng.api.networking.IGridVisitor; @@ -51,102 +54,277 @@ import appeng.hooks.TickHandler; import appeng.me.pathfinding.IPathItem; import appeng.util.ReadOnlyCollection; + public class GridNode implements IGridNode, IPathItem { + private static final MENetworkChannelsChanged event = new MENetworkChannelsChanged(); + private static final int[] channelCount = new int[] { 0, 8, 32 }; - final static private MENetworkChannelsChanged event = new MENetworkChannelsChanged(); - final static private int channelCount[] = new int[] { 0, 8, 32 }; - - final List Connections = new LinkedList(); - GridStorage myStorage = null; - - final IGridBlock gridProxy; - Grid myGrid; - - Object visitorIterationNumber = null; - - // connection criteria - private int compressedData = 0; - - @Override - public void updateState() - { - EnumSet set = gridProxy.getFlags(); - - compressedData = set.contains( GridFlags.CANNOT_CARRY ) ? 0 : (set.contains( GridFlags.DENSE_CAPACITY ) ? 2 : 1); - - compressedData = compressedData | (gridProxy.getGridColor().ordinal() << 3); - - for (ForgeDirection dir : gridProxy.getConnectableSides()) - compressedData = compressedData | (1 << (dir.ordinal() + 8)); - - FindConnections(); - getInternalGrid(); - } - - public int getMaxChannels() - { - return channelCount[compressedData & 0x03]; - } - - public AEColor getColor() - { - return AEColor.values()[(compressedData >> 3) & 0x1F]; - } - - private boolean isValidDirection(ForgeDirection dir) - { - return (compressedData & (1 << (8 + dir.ordinal()))) > 0; - } - + private final List connections = new LinkedList(); + private final IGridBlock gridProxy; // old power draw, used to diff public double previousDraw = 0.0; - - private int channelData = 0; - public long lastSecurityKey = -1; public int playerID = -1; + private GridStorage myStorage = null; + private Grid myGrid; + private Object visitorIterationNumber = null; + // connection criteria + private int compressedData = 0; + private int channelData = 0; + + public GridNode( IGridBlock what ) + { + this.gridProxy = what; + } + + public IGridBlock getGridProxy() + { + return this.gridProxy; + } + + public Grid getMyGrid() + { + return this.myGrid; + } + + public int usedChannels() + { + return this.channelData >> 8; + } + + public Class getMachineClass() + { + return this.getMachine().getClass(); + } + + public void addConnection( IGridConnection gridConnection ) + { + this.connections.add( gridConnection ); + if ( gridConnection.hasDirection() ) + this.gridProxy.onGridNotification( GridNotification.ConnectionsChanged ); + + final IGridNode gn = this; + + Collections.sort( this.connections, new ConnectionComparator( gn ) ); + } + + public void removeConnection( IGridConnection gridConnection ) + { + this.connections.remove( gridConnection ); + if ( gridConnection.hasDirection() ) + this.gridProxy.onGridNotification( GridNotification.ConnectionsChanged ); + } + + public boolean hasConnection( IGridNode otherSide ) + { + for ( IGridConnection gc : this.connections ) + { + if ( gc.a() == otherSide || gc.b() == otherSide ) + return true; + } + return false; + } + + public void validateGrid() + { + GridSplitDetector gsd = new GridSplitDetector( this.getInternalGrid().getPivot() ); + this.beginVisit( gsd ); + if ( !gsd.pivotFound ) + { + IGridVisitor gp = new GridPropagator( new Grid( this ) ); + this.beginVisit( gp ); + } + } @Override - public void setPlayerID(int playerID) + public void setPlayerID( int playerID ) { if ( playerID >= 0 ) this.playerID = playerID; } - public int usedChannels() + public Grid getInternalGrid() { - return channelData >> 8; - } + if ( this.myGrid == null ) + this.myGrid = new Grid( this ); - public GridNode(IGridBlock what) { - gridProxy = what; + return this.myGrid; } @Override - public void loadFromNBT(String name, NBTTagCompound nodeData) + public void beginVisit( IGridVisitor g ) { - if ( myGrid == null ) + Object tracker = new Object(); + + LinkedList nextRun = new LinkedList(); + nextRun.add( this ); + + this.visitorIterationNumber = tracker; + + if ( g instanceof IGridConnectionVisitor ) + { + LinkedList nextConn = new LinkedList(); + IGridConnectionVisitor gcv = ( IGridConnectionVisitor ) g; + + while ( !nextRun.isEmpty() ) + { + while ( !nextConn.isEmpty() ) + gcv.visitConnection( nextConn.poll() ); + + LinkedList thisRun = nextRun; + nextRun = new LinkedList(); + + for ( GridNode n : thisRun ) + n.visitorConnection( tracker, g, nextRun, nextConn ); + } + } + else + { + while ( !nextRun.isEmpty() ) + { + LinkedList thisRun = nextRun; + nextRun = new LinkedList(); + + for ( GridNode n : thisRun ) + n.visitorNode( tracker, g, nextRun ); + } + } + } + + @Override + public void updateState() + { + EnumSet set = this.gridProxy.getFlags(); + + this.compressedData = set.contains( GridFlags.CANNOT_CARRY ) ? 0 : ( set.contains( GridFlags.DENSE_CAPACITY ) ? 2 : 1 ); + + this.compressedData |= ( this.gridProxy.getGridColor().ordinal() << 3 ); + + for ( ForgeDirection dir : this.gridProxy.getConnectableSides() ) + this.compressedData |= ( 1 << ( dir.ordinal() + 8 ) ); + + this.FindConnections(); + this.getInternalGrid(); + } + + @Override + public IGridHost getMachine() + { + return this.gridProxy.getMachine(); + } + + @Override + public IGrid getGrid() + { + return this.myGrid; + } + + public void setGrid( Grid grid ) + { + if ( this.myGrid == grid ) + return; + + if ( this.myGrid != null ) + { + this.myGrid.remove( this ); + + if ( this.myGrid.isEmpty() ) + { + this.myGrid.saveState(); + + for ( IGridCache c : grid.getCaches().values() ) + c.onJoin( this.myGrid.getMyStorage() ); + } + } + + this.myGrid = grid; + this.myGrid.add( this ); + } + + @Override + public void destroy() + { + while ( !this.connections.isEmpty() ) + { + // not part of this network for real anymore. + if ( this.connections.size() == 1 ) + this.setGridStorage( null ); + + IGridConnection c = this.connections.listIterator().next(); + GridNode otherSide = ( GridNode ) c.getOtherSide( this ); + otherSide.getInternalGrid().setPivot( otherSide ); + c.destroy(); + } + + if ( this.myGrid != null ) + this.myGrid.remove( this ); + } + + @Override + public World getWorld() + { + return this.gridProxy.getLocation().getWorld(); + } + + @Override + public EnumSet getConnectedSides() + { + EnumSet set = EnumSet.noneOf( ForgeDirection.class ); + for ( IGridConnection gc : this.connections ) + set.add( gc.getDirection( this ) ); + return set; + } + + @Override + public IReadOnlyCollection getConnections() + { + return new ReadOnlyCollection( this.connections ); + } + + @Override + public IGridBlock getGridBlock() + { + return this.gridProxy; + } + + @Override + public boolean isActive() + { + IGrid g = this.getGrid(); + if ( g != null ) + { + IPathingGrid pg = g.getCache( IPathingGrid.class ); + IEnergyGrid eg = g.getCache( IEnergyGrid.class ); + return this.meetsChannelRequirements() && eg.isNetworkPowered() && !pg.isNetworkBooting(); + } + return false; + } + + @Override + public void loadFromNBT( String name, NBTTagCompound nodeData ) + { + if ( this.myGrid == null ) { NBTTagCompound node = nodeData.getCompoundTag( name ); - playerID = node.getInteger( "p" ); - lastSecurityKey = node.getLong( "k" ); - setGridStorage( WorldSettings.getInstance().getGridStorage( node.getLong( "g" ) ) ); + this.playerID = node.getInteger( "p" ); + this.lastSecurityKey = node.getLong( "k" ); + this.setGridStorage( WorldSettings.getInstance().getGridStorage( node.getLong( "g" ) ) ); } else throw new RuntimeException( "Loading data after part of a grid, this is invalid." ); } @Override - public void saveToNBT(String name, NBTTagCompound nodeData) + public void saveToNBT( String name, NBTTagCompound nodeData ) { - if ( myStorage != null ) + if ( this.myStorage != null ) { NBTTagCompound node = new NBTTagCompound(); - node.setInteger( "p", playerID ); - node.setLong( "k", lastSecurityKey ); - node.setLong( "g", myStorage.getID() ); + node.setInteger( "p", this.playerID ); + node.setLong( "k", this.lastSecurityKey ); + node.setLong( "g", this.myStorage.getID() ); nodeData.setTag( name, node ); } @@ -155,136 +333,44 @@ public class GridNode implements IGridNode, IPathItem } @Override - public IGridBlock getGridBlock() + public boolean meetsChannelRequirements() { - return gridProxy; + return ( !this.gridProxy.getFlags().contains( GridFlags.REQUIRE_CHANNEL ) || this.getUsedChannels() > 0 ); } @Override - public EnumSet getConnectedSides() + public boolean hasFlag( GridFlags flag ) { - EnumSet set = EnumSet.noneOf( ForgeDirection.class ); - for (IGridConnection gc : Connections) - set.add( gc.getDirection( this ) ); - return set; + return this.gridProxy.getFlags().contains( flag ); } - public Class getMachineClass() + public int getUsedChannels() { - return getMachine().getClass(); - } - - @Override - public IGridHost getMachine() - { - return gridProxy.getMachine(); - } - - @Override - public void beginVisit(IGridVisitor g) - { - Object tracker = new Object(); - - LinkedList nextRun = new LinkedList(); - nextRun.add( this ); - - visitorIterationNumber = tracker; - - if ( g instanceof IGridConnectionVisitor ) - { - LinkedList nextConn = new LinkedList(); - IGridConnectionVisitor gcv = (IGridConnectionVisitor) g; - - while (!nextRun.isEmpty()) - { - while (!nextConn.isEmpty()) - gcv.visitConnection( nextConn.poll() ); - - LinkedList thisRun = nextRun; - nextRun = new LinkedList(); - - for (GridNode n : thisRun) - n.visitorConnection( tracker, g, nextRun, nextConn ); - } - } - else - { - while (!nextRun.isEmpty()) - { - LinkedList thisRun = nextRun; - nextRun = new LinkedList(); - - for (GridNode n : thisRun) - n.visitorNode( tracker, g, nextRun ); - } - } - } - - private void visitorConnection(Object tracker, IGridVisitor g, LinkedList nextRun, LinkedList nextConnections) - { - if ( g.visitNode( this ) ) - { - for (IGridConnection gc : getConnections()) - { - GridNode gn = (GridNode) gc.getOtherSide( this ); - GridConnection gcc = (GridConnection) gc; - - if ( gcc.visitorIterationNumber != tracker ) - { - gcc.visitorIterationNumber = tracker; - nextConnections.add( gc ); - } - - if ( tracker == gn.visitorIterationNumber ) - continue; - - gn.visitorIterationNumber = tracker; - - nextRun.add( gn ); - } - } - } - - private void visitorNode(Object tracker, IGridVisitor g, LinkedList nextRun) - { - if ( g.visitNode( this ) ) - { - for (IGridConnection gc : getConnections()) - { - GridNode gn = (GridNode) gc.getOtherSide( this ); - - if ( tracker == gn.visitorIterationNumber ) - continue; - - gn.visitorIterationNumber = tracker; - - nextRun.add( gn ); - } - } + return this.channelData & 0xff; } public void FindConnections() { - if ( !gridProxy.isWorldAccessible() ) + if ( !this.gridProxy.isWorldAccessible() ) return; EnumSet newSecurityConnections = EnumSet.noneOf( ForgeDirection.class ); - DimensionalCoord dc = gridProxy.getLocation(); - for (ForgeDirection f : ForgeDirection.VALID_DIRECTIONS) + DimensionalCoord dc = this.gridProxy.getLocation(); + for ( ForgeDirection f : ForgeDirection.VALID_DIRECTIONS ) { - IGridHost te = findGridHost( dc.getWorld(), dc.x + f.offsetX, dc.y + f.offsetY, dc.z + f.offsetZ ); + IGridHost te = this.findGridHost( dc.getWorld(), dc.x + f.offsetX, dc.y + f.offsetY, dc.z + f.offsetZ ); if ( te != null ) { - GridNode node = (GridNode) te.getGridNode( f.getOpposite() ); + GridNode node = ( GridNode ) te.getGridNode( f.getOpposite() ); if ( node == null ) continue; boolean isValidConnection = this.canConnect( node, f ) && node.canConnect( this, f.getOpposite() ); IGridConnection con = null; // find the connection for this - // direction.. - for (IGridConnection c : getConnections()) + // direction.. + for ( IGridConnection c : this.getConnections() ) { if ( c.getDirection( this ) == f ) { @@ -319,33 +405,23 @@ public class GridNode implements IGridNode, IPathItem { new GridConnection( node, this, f.getOpposite() ); } - catch (FailedConnection e) + catch ( FailedConnection e ) { - TickHandler.instance.addCallable( node.getWorld(), new Callable() { - - @Override - public Object call() throws Exception - { - getMachine().securityBreak(); - return null; - } - - } ); + TickHandler.instance.addCallable( node.getWorld(), new MachineSecurityBreak( this ) ); return; } } } - } } - for (ForgeDirection f : newSecurityConnections) + for ( ForgeDirection f : newSecurityConnections ) { - IGridHost te = findGridHost( dc.getWorld(), dc.x + f.offsetX, dc.y + f.offsetY, dc.z + f.offsetZ ); + IGridHost te = this.findGridHost( dc.getWorld(), dc.x + f.offsetX, dc.y + f.offsetY, dc.z + f.offsetZ ); if ( te != null ) { - GridNode node = (GridNode) te.getGridNode( f.getOpposite() ); + GridNode node = ( GridNode ) te.getGridNode( f.getOpposite() ); if ( node == null ) continue; @@ -354,18 +430,9 @@ public class GridNode implements IGridNode, IPathItem { new GridConnection( node, this, f.getOpposite() ); } - catch (FailedConnection e) + catch ( FailedConnection e ) { - TickHandler.instance.addCallable( node.getWorld(), new Callable() { - - @Override - public Object call() throws Exception - { - getMachine().securityBreak(); - return null; - } - - } ); + TickHandler.instance.addCallable( node.getWorld(), new MachineSecurityBreak( this ) ); return; } @@ -373,258 +440,206 @@ public class GridNode implements IGridNode, IPathItem } } - private IGridHost findGridHost(World world, int x, int y, int z) + private IGridHost findGridHost( World world, int x, int y, int z ) { if ( world.blockExists( x, y, z ) ) { TileEntity te = world.getTileEntity( x, y, z ); if ( te instanceof IGridHost ) - return (IGridHost) te; + return ( IGridHost ) te; } return null; } - public void addConnection(IGridConnection gridConnection) + public boolean canConnect( GridNode from, ForgeDirection dir ) { - Connections.add( gridConnection ); - if ( gridConnection.hasDirection() ) - gridProxy.onGridNotification( GridNotification.ConnectionsChanged ); - - final IGridNode gn = this; - - Collections.sort( Connections, new Comparator() { - - @Override - public int compare(IGridConnection o1, IGridConnection o2) - { - boolean preferredA = o1.getOtherSide( gn ).hasFlag( GridFlags.PREFERRED ); - boolean preferredB = o2.getOtherSide( gn ).hasFlag( GridFlags.PREFERRED ); - - return preferredA == preferredB ? 0 : (preferredA ? -1 : 1); - } - - } ); - } - - public void removeConnection(IGridConnection gridConnection) - { - Connections.remove( gridConnection ); - if ( gridConnection.hasDirection() ) - gridProxy.onGridNotification( GridNotification.ConnectionsChanged ); - } - - @Override - public IReadOnlyCollection getConnections() - { - return new ReadOnlyCollection( Connections ); - } - - public boolean hasConnection(IGridNode otherSide) - { - for (IGridConnection gc : Connections) - { - if ( gc.a() == otherSide || gc.b() == otherSide ) - return true; - } - return false; - } - - public boolean canConnect(GridNode from, ForgeDirection dir) - { - if ( !isValidDirection( dir ) ) + if ( !this.isValidDirection( dir ) ) return false; - if ( !from.getColor().matches( getColor() ) ) + if ( !from.getColor().matches( this.getColor() ) ) return false; return true; } - @Override - public IGrid getGrid() + private boolean isValidDirection( ForgeDirection dir ) { - return myGrid; + return ( this.compressedData & ( 1 << ( 8 + dir.ordinal() ) ) ) > 0; } - public Grid getInternalGrid() + public AEColor getColor() { - if ( myGrid == null ) - myGrid = new Grid( this ); - - return myGrid; + return AEColor.values()[( this.compressedData >> 3 ) & 0x1F]; } - public void setGrid(Grid grid) + private void visitorConnection( Object tracker, IGridVisitor g, Deque nextRun, Deque nextConnections ) { - if ( myGrid == grid ) - return; - - if ( myGrid != null ) + if ( g.visitNode( this ) ) { - myGrid.remove( this ); - - if ( myGrid.isEmpty() ) + for ( IGridConnection gc : this.getConnections() ) { - myGrid.saveState(); + GridNode gn = ( GridNode ) gc.getOtherSide( this ); + GridConnection gcc = ( GridConnection ) gc; - for (IGridCache c : grid.caches.values()) - c.onJoin( myGrid.myStorage ); + if ( gcc.visitorIterationNumber != tracker ) + { + gcc.visitorIterationNumber = tracker; + nextConnections.add( gc ); + } + + if ( tracker == gn.visitorIterationNumber ) + continue; + + gn.visitorIterationNumber = tracker; + + nextRun.add( gn ); } } - - myGrid = grid; - myGrid.add( this ); } - public void validateGrid() + private void visitorNode( Object tracker, IGridVisitor g, Deque nextRun ) { - GridSplitDetector gsd = new GridSplitDetector( getInternalGrid().getPivot() ); - beginVisit( gsd ); - if ( !gsd.pivotFound ) + if ( g.visitNode( this ) ) { - GridPropagator gp = new GridPropagator( new Grid( this ) ); - beginVisit( gp ); + for ( IGridConnection gc : this.getConnections() ) + { + GridNode gn = ( GridNode ) gc.getOtherSide( this ); + + if ( tracker == gn.visitorIterationNumber ) + continue; + + gn.visitorIterationNumber = tracker; + + nextRun.add( gn ); + } } } - @Override - public void destroy() - { - while (!Connections.isEmpty()) - { - // not part of this network for real anymore. - if ( Connections.size() == 1 ) - setGridStorage( null ); - - IGridConnection c = Connections.listIterator().next(); - GridNode otherSide = (GridNode) c.getOtherSide( this ); - otherSide.getInternalGrid().pivot = otherSide; - c.destroy(); - } - - if ( myGrid != null ) - myGrid.remove( this ); - } - - @Override - public World getWorld() - { - return gridProxy.getLocation().getWorld(); - } - - @Override - public boolean meetsChannelRequirements() - { - return (!getGridBlock().getFlags().contains( GridFlags.REQUIRE_CHANNEL ) || getUsedChannels() > 0); - } - - @Override - public boolean isActive() - { - IGrid g = getGrid(); - if ( g != null ) - { - IPathingGrid pg = g.getCache( IPathingGrid.class ); - IEnergyGrid eg = g.getCache( IEnergyGrid.class ); - return meetsChannelRequirements() && eg.isNetworkPowered() && !pg.isNetworkBooting(); - } - return false; - } - - @Override - public boolean canSupportMoreChannels() - { - return getUsedChannels() < getMaxChannels(); - } - - @Override - public IReadOnlyCollection getPossibleOptions() - { - return (ReadOnlyCollection) getConnections(); - } - - public int getLastUsedChannels() - { - return (channelData >> 8) & 0xff; - } - - public int getUsedChannels() - { - return channelData & 0xff; - } - - @Override - public void incrementChannelCount(int usedChannels) - { - channelData += usedChannels; - } - - public void setGridStorage(GridStorage s) - { - myStorage = s; - channelData = 0; - } - public GridStorage getGridStorage() { - return myStorage; + return this.myStorage; } - @Override - public EnumSet getFlags() + public void setGridStorage( GridStorage s ) { - return getGridBlock().getFlags(); - } - - @Override - public void finalizeChannels() - { - if ( getFlags().contains( GridFlags.CANNOT_CARRY ) ) - return; - - if ( getLastUsedChannels() != getUsedChannels() ) - { - channelData = (channelData & 0xff); - channelData |= channelData << 8; - - if ( getInternalGrid() != null ) - getInternalGrid().postEventTo( this, event ); - } + this.myStorage = s; + this.channelData = 0; } @Override public IPathItem getControllerRoute() { - if ( Connections.isEmpty() || getFlags().contains( GridFlags.CANNOT_CARRY ) ) + if ( this.connections.isEmpty() || this.getFlags().contains( GridFlags.CANNOT_CARRY ) ) return null; - return (IPathItem) Connections.get( 0 ); + return ( IPathItem ) this.connections.get( 0 ); } @Override - public void setControllerRoute(IPathItem fast, boolean zeroOut) + public void setControllerRoute( IPathItem fast, boolean zeroOut ) { if ( zeroOut ) - channelData &= ~0xff; + this.channelData &= ~0xff; - int idx = Connections.indexOf( fast ); + int idx = this.connections.indexOf( fast ); if ( idx > 0 ) { - Connections.remove( fast ); - Connections.add( 0, (IGridConnection) fast ); + this.connections.remove( fast ); + this.connections.add( 0, ( IGridConnection ) fast ); } } @Override - public boolean hasFlag(GridFlags flag) + public boolean canSupportMoreChannels() { - return getGridBlock().getFlags().contains( flag ); + return this.getUsedChannels() < this.getMaxChannels(); + } + + public int getMaxChannels() + { + return channelCount[this.compressedData & 0x03]; + } + + @Override + public IReadOnlyCollection getPossibleOptions() + { + return ( ReadOnlyCollection ) this.getConnections(); + } + + @Override + public void incrementChannelCount( int usedChannels ) + { + this.channelData += usedChannels; + } + + @Override + public EnumSet getFlags() + { + return this.gridProxy.getFlags(); + } + + @Override + public void finalizeChannels() + { + if ( this.getFlags().contains( GridFlags.CANNOT_CARRY ) ) + return; + + if ( this.getLastUsedChannels() != this.getUsedChannels() ) + { + this.channelData &= 0xff; + this.channelData |= this.channelData << 8; + + if ( this.getInternalGrid() != null ) + this.getInternalGrid().postEventTo( this, event ); + } + } + + public int getLastUsedChannels() + { + return ( this.channelData >> 8 ) & 0xff; + } + + private static class MachineSecurityBreak implements Callable + { + private final GridNode node; + + public MachineSecurityBreak( GridNode node ) + { + this.node = node; + } + + @Override + public Void call() throws Exception + { + this.node.getMachine().securityBreak(); + + return null; + } + } + + + private static class ConnectionComparator implements Comparator + { + private final IGridNode gn; + + public ConnectionComparator( IGridNode gn ) + { + this.gn = gn; + } + + @Override + public int compare( IGridConnection o1, IGridConnection o2 ) + { + boolean preferredA = o1.getOtherSide( this.gn ).hasFlag( GridFlags.PREFERRED ); + boolean preferredB = o2.getOtherSide( this.gn ).hasFlag( GridFlags.PREFERRED ); + + return preferredA == preferredB ? 0 : ( preferredA ? -1 : 1 ); + } } @Override public int getPlayerID() { - return playerID; + return this.playerID; } - } diff --git a/src/main/java/appeng/me/NodeIterable.java b/src/main/java/appeng/me/GridNodeCollection.java similarity index 54% rename from src/main/java/appeng/me/NodeIterable.java rename to src/main/java/appeng/me/GridNodeCollection.java index 8a3a1465..8b7e8698 100644 --- a/src/main/java/appeng/me/NodeIterable.java +++ b/src/main/java/appeng/me/GridNodeCollection.java @@ -18,26 +18,29 @@ package appeng.me; -import java.util.HashMap; + import java.util.Iterator; +import java.util.Map; import java.util.Set; +import appeng.api.networking.IGridHost; import appeng.api.networking.IGridNode; import appeng.api.util.IReadOnlyCollection; -public class NodeIterable implements IReadOnlyCollection + +public class GridNodeCollection implements IReadOnlyCollection { + final private Map, MachineSet> machines; - final private HashMap> Machines; - - public NodeIterable(HashMap> Machines) { - this.Machines = Machines; + public GridNodeCollection( Map, MachineSet> machines ) + { + this.machines = machines; } @Override - public Iterator iterator() + public Iterator iterator() { - return new NodeIterator( Machines ); + return new GridNodeIterator( this.machines ); } @Override @@ -45,7 +48,7 @@ public class NodeIterable implements IReadOnlyCollection { int size = 0; - for (Set o : Machines.values()) + for ( Set o : this.machines.values() ) size += o.size(); return size; @@ -54,7 +57,7 @@ public class NodeIterable implements IReadOnlyCollection @Override public boolean isEmpty() { - for (Set o : Machines.values()) + for ( Set o : this.machines.values() ) if ( !o.isEmpty() ) return false; @@ -62,14 +65,25 @@ public class NodeIterable implements IReadOnlyCollection } @Override - public boolean contains(Object node) + public boolean contains( Object maybeGridNode ) { - Class c = ((IGridNode) node).getMachine().getClass(); + final boolean doesContainNode; - Set p = Machines.get( c ); - if ( p != null ) - return p.contains( node ); + if ( maybeGridNode instanceof IGridNode ) + { + final IGridNode node = ( IGridNode ) maybeGridNode; + IGridHost machine = node.getMachine(); + Class machineClass = machine.getClass(); - return false; + MachineSet machineSet = this.machines.get( machineClass ); + + doesContainNode = machineSet != null && machineSet.contains( maybeGridNode ); + } + else + { + doesContainNode = false; + } + + return doesContainNode; } } diff --git a/src/main/java/appeng/me/GridNodeIterator.java b/src/main/java/appeng/me/GridNodeIterator.java new file mode 100644 index 00000000..7921da4f --- /dev/null +++ b/src/main/java/appeng/me/GridNodeIterator.java @@ -0,0 +1,86 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. + * + * Applied Energistics 2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Applied Energistics 2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Applied Energistics 2. If not, see . + */ + +package appeng.me; + + +import java.util.Iterator; +import java.util.Map; + +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; + + +/** + * Nested iterator for {@link appeng.me.MachineSet} + * + * Traverses first over the {@link appeng.me.MachineSet} + * and then over every containing {@link appeng.api.networking.IGridNode} + */ +public class GridNodeIterator implements Iterator +{ + private final Iterator outerIterator; + private Iterator innerIterator; + + public GridNodeIterator( Map, MachineSet> machines ) + { + this.outerIterator = machines.values().iterator(); + this.innerHasNext(); + } + + private boolean innerHasNext() + { + final boolean hasNext = this.outerIterator.hasNext(); + + if ( hasNext ) + { + final MachineSet nextElem = this.outerIterator.next(); + this.innerIterator = nextElem.iterator(); + } + + return hasNext; + } + + @Override + public boolean hasNext() + { + while ( true ) + { + if ( this.innerIterator.hasNext() ) + { + return true; + } + else if ( !this.innerHasNext() ) + { + return false; + } + } + } + + @Override + public IGridNode next() + { + return this.innerIterator.next(); + } + + @Override + public void remove() + { + this.innerIterator.remove(); + } +} diff --git a/src/main/java/appeng/me/GridPropagator.java b/src/main/java/appeng/me/GridPropagator.java index 9f751e3d..c86556b0 100644 --- a/src/main/java/appeng/me/GridPropagator.java +++ b/src/main/java/appeng/me/GridPropagator.java @@ -18,28 +18,30 @@ package appeng.me; + import appeng.api.networking.IGridNode; import appeng.api.networking.IGridVisitor; + public class GridPropagator implements IGridVisitor { - final private Grid g; - public GridPropagator(Grid g) { + public GridPropagator( Grid g ) + { this.g = g; } @Override - public boolean visitNode(IGridNode n) + public boolean visitNode( IGridNode n ) { - GridNode gn = (GridNode) n; - if ( gn.myGrid != g || g.pivot == n ) + GridNode gn = ( GridNode ) n; + if ( gn.getMyGrid() != this.g || this.g.getPivot() == n ) { - gn.setGrid( g ); + gn.setGrid( this.g ); + return true; } return false; } - } diff --git a/src/main/java/appeng/me/NetworkEventBus.java b/src/main/java/appeng/me/NetworkEventBus.java index adb333df..0446e6ca 100644 --- a/src/main/java/appeng/me/NetworkEventBus.java +++ b/src/main/java/appeng/me/NetworkEventBus.java @@ -18,82 +18,28 @@ package appeng.me; + import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; -import java.util.Hashtable; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; -import java.util.Set; import appeng.api.networking.IGridNode; import appeng.api.networking.events.MENetworkEvent; import appeng.api.networking.events.MENetworkEventSubscribe; import appeng.core.AELog; + public class NetworkEventBus { + private static final Collection readClasses = new HashSet(); + private static final Map, Map> events = new HashMap, Map>(); - static class NetworkEventDone extends Throwable - { - - private static final long serialVersionUID = -3079021487019171205L; - - } - - class EventMethod - { - - public final Class objClass; - public final Method objMethod; - public final Class objEvent; - - public EventMethod(Class Event, Class ObjClass, Method ObjMethod) { - this.objClass = ObjClass; - this.objMethod = ObjMethod; - this.objEvent = Event; - } - - public void invoke(Object obj, MENetworkEvent e) throws NetworkEventDone - { - try - { - objMethod.invoke( obj, e ); - } - catch (Throwable e1) - { - AELog.severe( "[AppEng] Network Event caused exception:" ); - AELog.severe( "Offending Class: " + obj.getClass().getName() ); - AELog.severe( "Offending Object: " + obj.toString() ); - AELog.error( e1 ); - throw new RuntimeException( e1 ); - } - - if ( e.isCanceled() ) - throw new NetworkEventDone(); - } - } - - class MENetworkEventInfo - { - - private final ArrayList methods = new ArrayList(); - - public void Add(Class Event, Class ObjClass, Method ObjMethod) - { - methods.add( new EventMethod( Event, ObjClass, ObjMethod ) ); - } - - public void invoke(Object obj, MENetworkEvent e) throws NetworkEventDone - { - for (EventMethod em : methods) - em.invoke( obj, e ); - } - } - - private static final Set readClasses = new HashSet(); - private static final Hashtable, Hashtable> events = new Hashtable, Hashtable>(); - - public void readClass(Class listAs, Class c) + public void readClass( Class listAs, Class c ) { if ( readClasses.contains( c ) ) return; @@ -101,27 +47,27 @@ public class NetworkEventBus try { - for (Method m : c.getMethods()) + for ( Method m : c.getMethods() ) { MENetworkEventSubscribe s = m.getAnnotation( MENetworkEventSubscribe.class ); if ( s != null ) { - Class types[] = m.getParameterTypes(); + Class[] types = m.getParameterTypes(); if ( types.length == 1 ) { if ( MENetworkEvent.class.isAssignableFrom( types[0] ) ) { - - Hashtable classEvents = events.get( types[0] ); + + Map classEvents = events.get( types[0] ); if ( classEvents == null ) - events.put( types[0], classEvents = new Hashtable() ); - + events.put( types[0], classEvents = new HashMap() ); + MENetworkEventInfo thisEvent = classEvents.get( listAs ); if ( thisEvent == null ) thisEvent = new MENetworkEventInfo(); - + thisEvent.Add( types[0], c, m ); - + classEvents.put( listAs, thisEvent ); } else @@ -132,33 +78,32 @@ public class NetworkEventBus } } } - catch(Throwable t ) + catch ( Throwable t ) { - throw new RuntimeException( "Error while adding "+c.getName()+" to event bus", t ); + throw new RuntimeException( "Error while adding " + c.getName() + " to event bus", t ); } - } - public MENetworkEvent postEvent(Grid g, MENetworkEvent e) + public MENetworkEvent postEvent( Grid g, MENetworkEvent e ) { - Hashtable subscribers = events.get( e.getClass() ); + Map subscribers = events.get( e.getClass() ); int x = 0; try { if ( subscribers != null ) { - for (Entry subscriber : subscribers.entrySet()) + for ( Entry subscriber : subscribers.entrySet() ) { MENetworkEventInfo target = subscriber.getValue(); - GridCacheWrapper cache = g.caches.get( subscriber.getKey() ); + GridCacheWrapper cache = g.getCaches().get( subscriber.getKey() ); if ( cache != null ) { x++; target.invoke( cache.myCache, e ); } - for (IGridNode obj : g.getMachines( subscriber.getKey() )) + for ( IGridNode obj : g.getMachines( subscriber.getKey() ) ) { x++; target.invoke( obj.getMachine(), e ); @@ -166,7 +111,7 @@ public class NetworkEventBus } } } - catch (NetworkEventDone done) + catch ( NetworkEventDone done ) { // Early out. } @@ -175,9 +120,9 @@ public class NetworkEventBus return e; } - public MENetworkEvent postEventTo(Grid grid, GridNode node, MENetworkEvent e) + public MENetworkEvent postEventTo( Grid grid, GridNode node, MENetworkEvent e ) { - Hashtable subscribers = events.get( e.getClass() ); + Map subscribers = events.get( e.getClass() ); int x = 0; try @@ -192,7 +137,7 @@ public class NetworkEventBus } } } - catch (NetworkEventDone done) + catch ( NetworkEventDone done ) { // Early out. } @@ -200,4 +145,63 @@ public class NetworkEventBus e.setVisitedObjects( x ); return e; } + + static class NetworkEventDone extends Throwable + { + + private static final long serialVersionUID = -3079021487019171205L; + } + + + class EventMethod + { + + public final Class objClass; + public final Method objMethod; + public final Class objEvent; + + public EventMethod( Class Event, Class ObjClass, Method ObjMethod ) + { + this.objClass = ObjClass; + this.objMethod = ObjMethod; + this.objEvent = Event; + } + + public void invoke( Object obj, MENetworkEvent e ) throws NetworkEventDone + { + try + { + this.objMethod.invoke( obj, e ); + } + catch ( Throwable e1 ) + { + AELog.severe( "[AppEng] Network Event caused exception:" ); + AELog.severe( "Offending Class: " + obj.getClass().getName() ); + AELog.severe( "Offending Object: " + obj.toString() ); + AELog.error( e1 ); + throw new RuntimeException( e1 ); + } + + if ( e.isCanceled() ) + throw new NetworkEventDone(); + } + } + + + class MENetworkEventInfo + { + + private final List methods = new ArrayList(); + + public void Add( Class Event, Class ObjClass, Method ObjMethod ) + { + this.methods.add( new EventMethod( Event, ObjClass, ObjMethod ) ); + } + + public void invoke( Object obj, MENetworkEvent e ) throws NetworkEventDone + { + for ( EventMethod em : this.methods ) + em.invoke( obj, e ); + } + } } diff --git a/src/main/java/appeng/me/NodeIterator.java b/src/main/java/appeng/me/NodeIterator.java deleted file mode 100644 index b57a98e5..00000000 --- a/src/main/java/appeng/me/NodeIterator.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of Applied Energistics 2. - * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. - * - * Applied Energistics 2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Applied Energistics 2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Applied Energistics 2. If not, see . - */ - -package appeng.me; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Set; - -public class NodeIterator implements Iterator -{ - - boolean hasMore; - final Iterator lvl1; - Iterator lvl2; - - boolean pull() - { - hasMore = lvl1.hasNext(); - if ( hasMore ) - { - lvl2 = ((Collection) lvl1.next()).iterator(); - return true; - } - return false; - } - - public NodeIterator(HashMap> machines) { - lvl1 = machines.values().iterator(); - pull(); - } - - @Override - public boolean hasNext() - { - if ( lvl2.hasNext() ) - return true; - if ( pull() ) - return hasNext(); - return hasMore; - } - - @Override - public IGridNode next() - { - return (IGridNode) lvl2.next(); - } - - @Override - public void remove() - { - lvl2.remove(); - } - -}