gt: 			node.setLong( "k", this.lastSecurityKey );
context: /*
   * 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 <http://www.gnu.org/licenses/lgpl>.
   */
  
  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;
  import java.util.concurrent.Callable;
  
  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.IGridConnection;
  import appeng.api.networking.IGridConnectionVisitor;
  import appeng.api.networking.IGridHost;
  import appeng.api.networking.IGridNode;
  import appeng.api.networking.IGridVisitor;
  import appeng.api.networking.energy.IEnergyGrid;
  import appeng.api.networking.events.MENetworkChannelsChanged;
  import appeng.api.networking.pathing.IPathingGrid;
  import appeng.api.util.AEColor;
  import appeng.api.util.DimensionalCoord;
  import appeng.api.util.IReadOnlyCollection;
  import appeng.core.WorldSettings;
  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[] CHANNEL_COUNT = new int[] { 0, 8, 32 };
  
  	private final List<IGridConnection> connections = new LinkedList<IGridConnection>();
  	private final IGridBlock gridProxy;
  	// old power draw, used to diff
  	public double previousDraw = 0.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<? extends IGridHost> 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 );
  		}
  	}
  
  	public Grid getInternalGrid()
  	{
  		if( this.myGrid == null )
  		{
  			this.myGrid = new Grid( this );
  		}
  
  		return this.myGrid;
  	}
  
  	@Override
  	public void beginVisit( IGridVisitor g )
  	{
  		Object tracker = new Object();
  
  		LinkedList<GridNode> nextRun = new LinkedList<GridNode>();
  		nextRun.add( this );
  
  		this.visitorIterationNumber = tracker;
  
  		if( g instanceof IGridConnectionVisitor )
  		{
  			LinkedList<IGridConnection> nextConn = new LinkedList<IGridConnection>();
  			IGridConnectionVisitor gcv = (IGridConnectionVisitor) g;
  
  			while( !nextRun.isEmpty() )
  			{
  				while( !nextConn.isEmpty() )
  				{
  					gcv.visitConnection( nextConn.poll() );
  				}
  
  				Iterable<GridNode> thisRun = nextRun;
  				nextRun = new LinkedList<GridNode>();
  
  				for( GridNode n : thisRun )
  				{
  					n.visitorConnection( tracker, g, nextRun, nextConn );
  				}
  			}
  		}
  		else
  		{
  			while( !nextRun.isEmpty() )
  			{
  				Iterable<GridNode> thisRun = nextRun;
  				nextRun = new LinkedList<GridNode>();
  
  				for( GridNode n : thisRun )
  				{
  					n.visitorNode( tracker, g, nextRun );
  				}
  			}
  		}
  	}
  
  	@Override
  	public void updateState()
  	{
  		EnumSet<GridFlags> 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<ForgeDirection> getConnectedSides()
  	{
  		EnumSet<ForgeDirection> set = EnumSet.noneOf( ForgeDirection.class );
  		for( IGridConnection gc : this.connections )
  		{
  			set.add( gc.getDirection( this ) );
  		}
  		return set;
  	}
  
  	@Override
  	public IReadOnlyCollection<IGridConnection> getConnections()
  	{
  		return new ReadOnlyCollection<IGridConnection>( 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 );
  			this.playerID = node.getInteger( "p" );
  			this.lastSecurityKey = node.getLong( "k" );
  			this.setGridStorage( WorldSettings.getInstance().getGridStorage( node.getLong( "g" ) ) );
  		}
  		else
  		{
  			throw new IllegalStateException( "Loading data after part of a grid, this is invalid." );
  		}
  	}
  
  	@Override
  	public void saveToNBT( String name, NBTTagCompound nodeData )
  	{
  		if( this.myStorage != null )
  		{
  			NBTTagCompound node = new NBTTagCompound();
  
  			node.setInteger( "p", this.playerID );
  