2013-12-27 23:59:59 +01:00
|
|
|
package appeng.me.cache;
|
|
|
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.PriorityQueue;
|
|
|
|
|
|
|
|
import net.minecraft.tileentity.TileEntity;
|
|
|
|
import appeng.api.networking.IGrid;
|
|
|
|
import appeng.api.networking.IGridHost;
|
|
|
|
import appeng.api.networking.IGridNode;
|
|
|
|
import appeng.api.networking.IGridStorage;
|
|
|
|
import appeng.api.networking.ticking.IGridTickable;
|
|
|
|
import appeng.api.networking.ticking.ITickManager;
|
|
|
|
import appeng.api.networking.ticking.TickRateModulation;
|
|
|
|
import appeng.api.networking.ticking.TickingRequest;
|
|
|
|
import appeng.core.AELog;
|
|
|
|
import appeng.me.cache.helpers.TickTracker;
|
|
|
|
|
|
|
|
public class TickManagerCache implements ITickManager
|
|
|
|
{
|
|
|
|
|
|
|
|
private long currentTick = 0;
|
|
|
|
|
|
|
|
final IGrid myGrid;
|
|
|
|
|
|
|
|
public TickManagerCache(IGrid g) {
|
|
|
|
myGrid = g;
|
|
|
|
}
|
|
|
|
|
|
|
|
HashMap<IGridNode, TickTracker> alertable = new HashMap<IGridNode, TickTracker>();
|
|
|
|
|
|
|
|
HashMap<IGridNode, TickTracker> sleeping = new HashMap<IGridNode, TickTracker>();
|
|
|
|
HashMap<IGridNode, TickTracker> awake = new HashMap<IGridNode, TickTracker>();
|
|
|
|
|
|
|
|
PriorityQueue<TickTracker> upcomingTicks = new PriorityQueue<TickTracker>();
|
|
|
|
|
|
|
|
public long getCurrentTick()
|
|
|
|
{
|
|
|
|
return currentTick;
|
|
|
|
}
|
|
|
|
|
|
|
|
public long getAvgNanoTime(IGridNode node)
|
|
|
|
{
|
|
|
|
TickTracker tt = awake.get( node );
|
|
|
|
|
|
|
|
if ( tt == null )
|
|
|
|
tt = sleeping.get( node );
|
|
|
|
|
|
|
|
if ( tt == null )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return tt.getAvgNanos();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2014-02-04 17:11:29 +01:00
|
|
|
public void onUpdateTick()
|
2013-12-27 23:59:59 +01:00
|
|
|
{
|
|
|
|
currentTick++;
|
|
|
|
while (!upcomingTicks.isEmpty())
|
|
|
|
{
|
|
|
|
TickTracker tt = upcomingTicks.peek();
|
|
|
|
int diff = (int) (currentTick - tt.lastTick);
|
|
|
|
if ( diff >= tt.current_rate )
|
|
|
|
{
|
|
|
|
// remove tt..
|
|
|
|
upcomingTicks.poll();
|
|
|
|
TickRateModulation mod = tt.gt.tickingRequest( tt.node, diff );
|
|
|
|
|
|
|
|
switch (mod)
|
|
|
|
{
|
|
|
|
case FASTER:
|
|
|
|
tt.setRate( tt.current_rate - 1 );
|
|
|
|
break;
|
|
|
|
case IDLE:
|
|
|
|
tt.setRate( tt.request.maxTickRate );
|
|
|
|
break;
|
|
|
|
case SAME:
|
|
|
|
break;
|
|
|
|
case SLEEP:
|
|
|
|
sleepDevice( tt.node );
|
|
|
|
break;
|
|
|
|
case SLOWER:
|
|
|
|
tt.setRate( tt.current_rate + 1 );
|
|
|
|
break;
|
|
|
|
case URGENT:
|
|
|
|
tt.setRate( 0 );
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( awake.containsKey( tt.node ) )
|
|
|
|
addToQueue( tt );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return; // done!
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void addToQueue(TickTracker tt)
|
|
|
|
{
|
|
|
|
tt.lastTick = currentTick;
|
|
|
|
upcomingTicks.add( tt );
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean alertDevice(IGridNode node)
|
|
|
|
{
|
|
|
|
TickTracker tt = alertable.get( node );
|
|
|
|
if ( tt == null )
|
2014-02-14 07:25:49 +01:00
|
|
|
return false;
|
|
|
|
// throw new RuntimeException(
|
|
|
|
// "Invalid Alertted device, this node is not marked as alertable, or part of this grid." );
|
2013-12-27 23:59:59 +01:00
|
|
|
|
2014-02-12 05:43:17 +01:00
|
|
|
// set to awake, this is for sanity.
|
|
|
|
sleeping.remove( node );
|
|
|
|
awake.put( node, tt );
|
|
|
|
|
|
|
|
tt.lastTick = tt.lastTick - tt.request.maxTickRate;
|
|
|
|
upcomingTicks.add( tt );
|
2013-12-27 23:59:59 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean sleepDevice(IGridNode node)
|
|
|
|
{
|
|
|
|
if ( awake.containsKey( node ) )
|
|
|
|
{
|
|
|
|
TickTracker gt = awake.get( node );
|
|
|
|
awake.remove( node );
|
|
|
|
sleeping.put( node, gt );
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean wakeDevice(IGridNode node)
|
|
|
|
{
|
|
|
|
if ( sleeping.containsKey( node ) )
|
|
|
|
{
|
|
|
|
TickTracker gt = sleeping.get( node );
|
|
|
|
sleeping.remove( node );
|
|
|
|
awake.put( node, gt );
|
|
|
|
addToQueue( gt );
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2014-02-04 17:11:29 +01:00
|
|
|
public void removeNode(IGridNode gridNode, IGridHost machine)
|
2013-12-27 23:59:59 +01:00
|
|
|
{
|
|
|
|
if ( machine instanceof IGridTickable )
|
|
|
|
{
|
|
|
|
alertable.remove( gridNode );
|
|
|
|
sleeping.remove( gridNode );
|
|
|
|
awake.remove( gridNode );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2014-02-04 17:11:29 +01:00
|
|
|
public void addNode(IGridNode gridNode, IGridHost machine)
|
2013-12-27 23:59:59 +01:00
|
|
|
{
|
|
|
|
if ( machine instanceof IGridTickable )
|
|
|
|
{
|
|
|
|
TickingRequest tr = ((IGridTickable) machine).getTickingRequest( gridNode );
|
|
|
|
if ( tr != null )
|
|
|
|
{
|
|
|
|
if ( machine instanceof TileEntity && ((TileEntity) machine).canUpdate() )
|
|
|
|
AELog.warning( "Tile: " + machine.getClass().getName() + " - reports to use MC ticking, but also requests Network Based Ticking." );
|
|
|
|
|
|
|
|
TickTracker tt = new TickTracker( tr, gridNode, (IGridTickable) machine, currentTick, this );
|
|
|
|
|
|
|
|
if ( tr.canBeAlerted )
|
|
|
|
alertable.put( gridNode, tt );
|
|
|
|
|
|
|
|
if ( tr.isSleeping )
|
|
|
|
sleeping.put( gridNode, tt );
|
|
|
|
else
|
|
|
|
{
|
|
|
|
awake.put( gridNode, tt );
|
|
|
|
addToQueue( tt );
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSplit(IGridStorage storageB)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onJoin(IGridStorage storageB)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void populateGridStorage(IGridStorage storage)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|