Performance improvements for the energygrid (#3051)

* Performance improvements for the energygrid

Reworked the old recursive approach to a queue based loop.
Extract will try to prefer the next grid with the hightest amount of
stored energy.
Inject will try to prefer the grid with the lowest percentage stored.
Other operations are first come, first serve.

* Added a local buffer storage to EnergyGrid

This replaces the old not really working buffer with a special
IAEPowerStorage acting as buffer/proxy for the local energy demand as
well as temporary overflow should something provide more energy than
requested.

Currently it set to hold a maximum of 200 AE (+ optional overflow until
consumed). It will only be used locally, no other grid can use it to
avoid starving the neighbor grids before finding a energy cell.

* Fixes IExternalPowerSink

All implementations currently depend on the network demand being a valid
source, which might not be true.

Further it can cause the sink to iterate the network twice (demand and
inject) and both again for simulate and modulate.

Also it did not return the actual leftover amount instead of relying on
the demand matching it.

* Minor fixes related to removing nodes from a grid.

The grid did remove IStackWatcherHost not IEnergyWatcherHost, this was
fine for AE2 as only level emitters use it and they implement both.
But not for potential addons.

Also they would potentually not being removed as the are indexed by the
gridnodes not the machine.

Fixes #1004
This commit is contained in:
yueh
2017-08-24 11:06:31 +02:00
committed by GitHub
parent f03f8ec432
commit 1513ba3f6a
11 changed files with 354 additions and 178 deletions
@@ -130,7 +130,7 @@ public class TileCharger extends AENetworkPowerTile implements ICrankable, IGrid
@Override
public void applyTurn()
{
this.injectExternalPower( PowerUnits.AE, 150 );
this.injectExternalPower( PowerUnits.AE, 150, Actionable.MODULATE );
final ItemStack myItem = this.inv.getStackInSlot( 0 );
if( this.getInternalCurrentPower() > 1499 )
@@ -222,7 +222,7 @@ public class TileCharger extends AENetworkPowerTile implements ICrankable, IGrid
try
{
this.injectExternalPower( PowerUnits.AE, this.getProxy().getEnergy().extractAEPower( Math.min( 500.0, 1500.0 - this.getInternalCurrentPower() ),
Actionable.MODULATE, PowerMultiplier.ONE ) );
Actionable.MODULATE, PowerMultiplier.ONE ), Actionable.MODULATE );
}
catch( final GridAccessException e )
{
@@ -246,7 +246,8 @@ public class TileCharger extends AENetworkPowerTile implements ICrankable, IGrid
{
final double oldPower = this.getInternalCurrentPower();
final double adjustment = ps.injectAEPower( myItem, this.extractAEPower( 150.0, Actionable.MODULATE, PowerMultiplier.CONFIG ), Actionable.MODULATE );
final double adjustment = ps.injectAEPower( myItem, this.extractAEPower( 150.0, Actionable.MODULATE, PowerMultiplier.CONFIG ),
Actionable.MODULATE );
this.setInternalCurrentPower( this.getInternalCurrentPower() + adjustment );
if( oldPower > this.getInternalCurrentPower() )
@@ -29,6 +29,7 @@ import net.minecraftforge.items.wrapper.EmptyHandler;
import appeng.api.config.Actionable;
import appeng.api.networking.GridFlags;
import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.events.MENetworkControllerChange;
import appeng.api.networking.events.MENetworkEventSubscribe;
import appeng.api.networking.events.MENetworkPowerStatusChange;
@@ -137,7 +138,9 @@ public class TileController extends AENetworkPowerTile
{
try
{
return this.getProxy().getEnergy().getEnergyDemand( 8000 );
final IEnergyGrid grid = this.getProxy().getEnergy();
return grid.getEnergyDemand( maxReceived );
}
catch( final GridAccessException e )
{
@@ -151,12 +154,10 @@ public class TileController extends AENetworkPowerTile
{
try
{
final double ret = this.getProxy().getEnergy().injectPower( power, mode );
if( mode == Actionable.SIMULATE )
{
return ret;
}
return 0;
final IEnergyGrid grid = this.getProxy().getEnergy();
final double leftOver = grid.injectPower( power, mode );
return leftOver;
}
catch( final GridAccessException e )
{
@@ -69,6 +69,7 @@ public class TileEnergyAcceptor extends AENetworkPowerTile
try
{
final IEnergyGrid grid = this.getProxy().getEnergy();
return grid.getEnergyDemand( maxRequired );
}
catch( final GridAccessException e )
@@ -84,11 +85,8 @@ public class TileEnergyAcceptor extends AENetworkPowerTile
{
final IEnergyGrid grid = this.getProxy().getEnergy();
final double leftOver = grid.injectPower( power, mode );
if( mode == Actionable.SIMULATE )
{
return leftOver;
}
return 0.0;
return leftOver;
}
catch( final GridAccessException e )
{
@@ -105,9 +105,9 @@ public abstract class AEBasePoweredTile extends AEBaseInvTile implements IAEPowe
}
@Override
public final double injectExternalPower( final PowerUnits input, final double amt )
public final double injectExternalPower( final PowerUnits input, final double amt, Actionable mode )
{
return PowerUnits.AE.convertTo( input, this.funnelPowerIntoStorage( input.convertTo( PowerUnits.AE, amt ), Actionable.MODULATE ) );
return PowerUnits.AE.convertTo( input, this.funnelPowerIntoStorage( input.convertTo( PowerUnits.AE, amt ), mode ) );
}
protected double funnelPowerIntoStorage( final double power, final Actionable mode )
@@ -123,34 +123,20 @@ public abstract class AEBasePoweredTile extends AEBaseInvTile implements IAEPowe
return 0;
}
if( mode == Actionable.SIMULATE )
{
final double fakeBattery = this.getInternalCurrentPower() + amt;
final double required = this.getAEMaxPower() - this.getAECurrentPower();
final double insertable = Math.min( required, amt );
if( fakeBattery > this.getInternalMaxPower() )
{
return fakeBattery - this.getInternalMaxPower();
}
return 0;
}
else
if( mode == Actionable.MODULATE )
{
if( this.getInternalCurrentPower() < 0.01 && amt > 0.01 )
if( this.getInternalCurrentPower() < 0.01 && insertable > 0.01 )
{
this.PowerEvent( PowerEventType.PROVIDE_POWER );
}
this.setInternalCurrentPower( this.getInternalCurrentPower() + amt );
if( this.getInternalCurrentPower() > this.getInternalMaxPower() )
{
amt = this.getInternalCurrentPower() - this.getInternalMaxPower();
this.setInternalCurrentPower( this.getInternalMaxPower() );
return amt;
}
return 0;
this.setInternalCurrentPower( this.getInternalCurrentPower() + insertable );
}
return amt - insertable;
}
protected void PowerEvent( final PowerEventType x )
@@ -4,6 +4,7 @@ package appeng.tile.powersink;
import net.minecraftforge.energy.IEnergyStorage;
import appeng.api.config.Actionable;
import appeng.api.config.PowerUnits;
@@ -23,15 +24,10 @@ class ForgeEnergyAdapter implements IEnergyStorage
@Override
public final int receiveEnergy( int maxReceive, boolean simulate )
{
final int networkDemand = (int) Math.floor( this.sink.getExternalPowerDemand( PowerUnits.RF, maxReceive ) );
final int used = Math.min( maxReceive, networkDemand );
final double offered = (double) maxReceive;
final double overflow = this.sink.injectExternalPower( PowerUnits.RF, offered, simulate ? Actionable.SIMULATE : Actionable.MODULATE );
if( !simulate )
{
this.sink.injectExternalPower( PowerUnits.RF, used );
}
return used;
return (int) ( maxReceive - overflow );
}
@Override
@@ -19,6 +19,7 @@
package appeng.tile.powersink;
import appeng.api.config.Actionable;
import appeng.api.config.PowerUnits;
import appeng.api.networking.energy.IAEPowerStorage;
@@ -26,8 +27,22 @@ import appeng.api.networking.energy.IAEPowerStorage;
public interface IExternalPowerSink extends IAEPowerStorage
{
double injectExternalPower( PowerUnits input, double amt );
/**
* Inject power into the network
*
* @param externalUnit The {@link PowerUnits} used by the input
* @param amount The amount offered to the sink.
* @param mode Modulate or simulate the operation.
* @return The unused amount, which could not be inserted into the sink.
*/
double injectExternalPower( PowerUnits externalUnit, double amount, Actionable mode );
/**
*
* @param externalUnit The {@link PowerUnits} used by the input
* @param maxPowerRequired Limit the demand to this upper bound.
* @return The amount of power demanded by the sink.
*/
double getExternalPowerDemand( PowerUnits externalUnit, double maxPowerRequired );
}
@@ -21,6 +21,7 @@ package appeng.tile.powersink;
import net.darkhax.tesla.api.ITeslaConsumer;
import appeng.api.config.Actionable;
import appeng.api.config.PowerUnits;
@@ -41,17 +42,10 @@ class TeslaEnergyAdapter implements ITeslaConsumer
public long givePower( long power, boolean simulated )
{
// Cut it down to what we can represent in a double
double powerDbl = (double) power;
double offeredPower = (double) power;
double networkDemand = this.sink.getExternalPowerDemand( PowerUnits.RF, powerDbl );
long used = (long) Math.min( powerDbl, networkDemand );
final double overflow = this.sink.injectExternalPower( PowerUnits.RF, offeredPower, simulated ? Actionable.SIMULATE : Actionable.MODULATE );
if( !simulated )
{
this.sink.injectExternalPower( PowerUnits.RF, used );
}
return used;
return (long) ( power - overflow );
}
}