From 1513ba3f6a448c8faca09a5e50f97cffd3c935b3 Mon Sep 17 00:00:00 2001 From: yueh Date: Thu, 24 Aug 2017 11:06:31 +0200 Subject: [PATCH] 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 --- .../energy/IEnergyGridProvider.java | 22 +- .../modules/ic2/IC2PowerSinkAdapter.java | 3 +- .../java/appeng/me/cache/EnergyGridCache.java | 322 ++++++++++++------ .../parts/networking/PartQuartzFiber.java | 80 ++++- .../java/appeng/tile/misc/TileCharger.java | 7 +- .../tile/networking/TileController.java | 15 +- .../tile/networking/TileEnergyAcceptor.java | 8 +- .../tile/powersink/AEBasePoweredTile.java | 32 +- .../tile/powersink/ForgeEnergyAdapter.java | 12 +- .../tile/powersink/IExternalPowerSink.java | 17 +- .../tile/powersink/TeslaEnergyAdapter.java | 14 +- 11 files changed, 354 insertions(+), 178 deletions(-) diff --git a/src/api/java/appeng/api/networking/energy/IEnergyGridProvider.java b/src/api/java/appeng/api/networking/energy/IEnergyGridProvider.java index b24af8e3..d7e6d782 100644 --- a/src/api/java/appeng/api/networking/energy/IEnergyGridProvider.java +++ b/src/api/java/appeng/api/networking/energy/IEnergyGridProvider.java @@ -24,6 +24,7 @@ package appeng.api.networking.energy; +import java.util.Collection; import java.util.Set; import appeng.api.config.Actionable; @@ -37,15 +38,30 @@ public interface IEnergyGridProvider /** * internal use only */ - double extractAEPower( double amt, Actionable mode, Set seen ); + Collection providers(); /** * internal use only */ - double injectAEPower( double amt, Actionable mode, Set seen ); + double extractProviderPower( double amt, Actionable mode, Set seen ); /** * internal use only */ - double getEnergyDemand( double d, Set seen ); + double injectProviderPower( double amt, Actionable mode, Set seen ); + + /** + * internal use only + */ + double getProviderEnergyDemand( double d, Set seen ); + + /** + * internal use only + */ + double getProviderStoredEnergy(); + + /** + * internal use only + */ + double getProviderMaxEnergy(); } diff --git a/src/main/java/appeng/integration/modules/ic2/IC2PowerSinkAdapter.java b/src/main/java/appeng/integration/modules/ic2/IC2PowerSinkAdapter.java index 5672d952..b15740d4 100644 --- a/src/main/java/appeng/integration/modules/ic2/IC2PowerSinkAdapter.java +++ b/src/main/java/appeng/integration/modules/ic2/IC2PowerSinkAdapter.java @@ -28,6 +28,7 @@ import net.minecraft.util.EnumFacing; import ic2.api.energy.prefab.BasicSink; import ic2.api.energy.tile.IEnergyEmitter; +import appeng.api.config.Actionable; import appeng.api.config.PowerUnits; import appeng.integration.abstraction.IC2PowerSink; import appeng.tile.powersink.IExternalPowerSink; @@ -76,7 +77,7 @@ public class IC2PowerSinkAdapter extends BasicSink implements IC2PowerSink @Override public double injectEnergy( EnumFacing directionFrom, double amount, double voltage ) { - return PowerUnits.EU.convertTo( PowerUnits.AE, this.powerSink.injectExternalPower( PowerUnits.EU, amount ) ); + return PowerUnits.EU.convertTo( PowerUnits.AE, this.powerSink.injectExternalPower( PowerUnits.EU, amount, Actionable.MODULATE ) ); } @Override diff --git a/src/main/java/appeng/me/cache/EnergyGridCache.java b/src/main/java/appeng/me/cache/EnergyGridCache.java index 81d65528..7a191013 100644 --- a/src/main/java/appeng/me/cache/EnergyGridCache.java +++ b/src/main/java/appeng/me/cache/EnergyGridCache.java @@ -19,11 +19,16 @@ package appeng.me.cache; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.NavigableSet; +import java.util.PriorityQueue; +import java.util.Queue; import java.util.Set; import com.google.common.collect.HashMultiset; @@ -48,8 +53,8 @@ import appeng.api.networking.events.MENetworkPostCacheConstruction; import appeng.api.networking.events.MENetworkPowerIdleChange; import appeng.api.networking.events.MENetworkPowerStatusChange; import appeng.api.networking.events.MENetworkPowerStorage; +import appeng.api.networking.events.MENetworkPowerStorage.PowerEventType; import appeng.api.networking.pathing.IPathingGrid; -import appeng.api.networking.storage.IStackWatcherHost; import appeng.me.Grid; import appeng.me.GridNode; import appeng.me.energy.EnergyThreshold; @@ -59,6 +64,18 @@ import appeng.me.energy.EnergyWatcher; public class EnergyGridCache implements IEnergyGrid { + private static final double MAX_BUFFER_STORAGE = 200; + private static final Comparator COMPARATOR_HIGHEST_AMOUNT_STORED_FIRST = ( o1, o2 ) -> Double.compare( o2.getProviderStoredEnergy(), + o1.getProviderStoredEnergy() ); + + private static final Comparator COMPARATOR_LOWEST_PERCENTAGE_FIRST = ( o1, o2 ) -> + { + final double percent1 = ( o1.getProviderStoredEnergy() + 1 ) / ( o1.getProviderMaxEnergy() + 1 ); + final double percent2 = ( o2.getProviderStoredEnergy() + 1 ) / ( o2.getProviderMaxEnergy() + 1 ); + + return Double.compare( percent1, percent2 ); + }; + private final NavigableSet interests = Sets.newTreeSet(); private final double averageLength = 40.0; private final Set providers = new LinkedHashSet<>(); @@ -66,13 +83,14 @@ public class EnergyGridCache implements IEnergyGrid private final Multiset energyGridProviders = HashMultiset.create(); private final IGrid myGrid; private final HashMap watchers = new HashMap<>(); - private final Set localSeen = new HashSet<>(); + /** * estimated power available. */ private int availableTicksSinceUpdate = 0; private double globalAvailablePower = 0; - private double globalMaxPower = 0; + private double globalMaxPower = MAX_BUFFER_STORAGE; + /** * idle draw. */ @@ -81,24 +99,25 @@ public class EnergyGridCache implements IEnergyGrid private double avgInjectionPerTick = 0; private double tickDrainPerTick = 0; private double tickInjectionPerTick = 0; + /** * power status */ private boolean publicHasPower = false; private boolean hasPower = true; private long ticksSinceHasPowerChange = 900; - /** - * excess power in the system. - */ - private double extra = 0; + private IAEPowerStorage lastProvider; private IAEPowerStorage lastRequester; private PathGridCache pgc; private double lastStoredPower = -1; + private final GridPowerStorage localStorage = new GridPowerStorage(); + public EnergyGridCache( final IGrid g ) { this.myGrid = g; + this.requesters.add( this.localStorage ); } @MENetworkEventSubscribe @@ -179,12 +198,12 @@ public class EnergyGridCache implements IEnergyGrid if( this.drainPerTick > 0.0001 ) { - final double drained = this.extractAEPower( this.getIdlePowerUsage(), Actionable.MODULATE, PowerMultiplier.CONFIG ); + final double drained = this.localStorage.extractAEPower( this.getIdlePowerUsage(), Actionable.MODULATE, PowerMultiplier.CONFIG ); currentlyHasPower = drained >= this.drainPerTick - 0.001; } else { - currentlyHasPower = this.extractAEPower( 0.1, Actionable.SIMULATE, PowerMultiplier.CONFIG ) > 0; + currentlyHasPower = this.localStorage.extractAEPower( 0.1, Actionable.SIMULATE, PowerMultiplier.CONFIG ) > 0; } // ticks since change.. @@ -216,8 +235,30 @@ public class EnergyGridCache implements IEnergyGrid @Override public double extractAEPower( final double amt, final Actionable mode, final PowerMultiplier pm ) { - this.localSeen.clear(); - return pm.divide( this.extractAEPower( pm.multiply( amt ), mode, this.localSeen ) ); + final double toExtract = pm.multiply( amt ); + final Queue toVisit = new PriorityQueue<>( COMPARATOR_HIGHEST_AMOUNT_STORED_FIRST ); + final Set visited = new HashSet<>(); + + double extracted = 0; + toVisit.add( this ); + + while( !toVisit.isEmpty() && extracted < toExtract ) + { + final IEnergyGridProvider next = toVisit.poll(); + visited.add( next ); + + extracted += next.extractProviderPower( toExtract - extracted, mode, visited ); + + for( IEnergyGridProvider iEnergyGridProvider : next.providers() ) + { + if( !visited.contains( iEnergyGridProvider ) ) + { + toVisit.add( iEnergyGridProvider ); + } + } + } + + return pm.divide( extracted ); } @Override @@ -244,7 +285,7 @@ public class EnergyGridCache implements IEnergyGrid private void refreshPower() { this.availableTicksSinceUpdate = 0; - this.globalAvailablePower = 0; + this.globalAvailablePower = this.localStorage.getAECurrentPower(); for( final IAEPowerStorage p : this.providers ) { this.globalAvailablePower += p.getAECurrentPower(); @@ -252,55 +293,37 @@ public class EnergyGridCache implements IEnergyGrid } @Override - public double extractAEPower( final double amt, final Actionable mode, final Set seen ) + public Collection providers() { - if( !seen.add( this ) ) - { - return 0; - } + return this.energyGridProviders; + } - double extractedPower = this.extra; + @Override + public double extractProviderPower( final double amt, final Actionable mode, final Set seen ) + { + double extractedPower = 0; if( mode == Actionable.SIMULATE ) { extractedPower += this.simulateExtract( extractedPower, amt ); - if( extractedPower < amt ) - { - final Iterator i = this.energyGridProviders.iterator(); - while( extractedPower < amt && i.hasNext() ) - { - extractedPower += i.next().extractAEPower( amt - extractedPower, mode, seen ); - } - } - return extractedPower; } else { - this.extra = 0; extractedPower = this.doExtract( extractedPower, amt ); } // got more then we wanted? if( extractedPower > amt ) { - this.extra = extractedPower - amt; + this.localStorage.addAECurrentPower( extractedPower - amt ); this.globalAvailablePower -= amt; this.tickDrainPerTick += amt; return amt; } - if( extractedPower < amt ) - { - final Iterator i = this.energyGridProviders.iterator(); - while( extractedPower < amt && i.hasNext() ) - { - extractedPower += i.next().extractAEPower( amt - extractedPower, mode, seen ); - } - } - // go less or the correct amount? this.globalAvailablePower -= extractedPower; this.tickDrainPerTick += extractedPower; @@ -308,16 +331,8 @@ public class EnergyGridCache implements IEnergyGrid } @Override - public double injectAEPower( double amt, final Actionable mode, final Set seen ) + public double injectProviderPower( double amt, final Actionable mode, final Set seen ) { - if( !seen.add( this ) ) - { - return 0; - } - - final double ignore = this.extra; - amt += this.extra; - if( mode == Actionable.SIMULATE ) { final Iterator it = this.requesters.iterator(); @@ -327,16 +342,10 @@ public class EnergyGridCache implements IEnergyGrid amt = node.injectAEPower( amt, Actionable.SIMULATE ); } - final Iterator i = this.energyGridProviders.iterator(); - while( amt > 0 && i.hasNext() ) - { - amt = i.next().injectAEPower( amt, mode, seen ); - } } else { - this.tickInjectionPerTick += amt - ignore; - // totalInjectionPastTicks[0] += i; + this.tickInjectionPerTick += amt; while( amt > 0 && !this.requesters.isEmpty() ) { @@ -349,35 +358,15 @@ public class EnergyGridCache implements IEnergyGrid this.lastRequester = null; } } - - final Iterator i = this.energyGridProviders.iterator(); - while( amt > 0 && i.hasNext() ) - { - final IEnergyGridProvider what = i.next(); - final Set listCopy = new HashSet<>(); - listCopy.addAll( seen ); - - final double cannotHold = what.injectAEPower( amt, Actionable.SIMULATE, listCopy ); - what.injectAEPower( amt - cannotHold, mode, seen ); - - amt = cannotHold; - } - - this.extra = amt; } - return Math.max( 0.0, amt - this.buffer() ); + return Math.max( 0.0, amt ); } @Override - public double getEnergyDemand( final double maxRequired, final Set seen ) + public double getProviderEnergyDemand( final double maxRequired, final Set seen ) { - if( !seen.add( this ) ) - { - return 0; - } - - double required = this.buffer() - this.extra; + double required = 0; final Iterator it = this.requesters.iterator(); while( required < maxRequired && it.hasNext() ) @@ -389,13 +378,6 @@ public class EnergyGridCache implements IEnergyGrid } } - final Iterator ix = this.energyGridProviders.iterator(); - while( required < maxRequired && ix.hasNext() ) - { - final IEnergyGridProvider node = ix.next(); - required += node.getEnergyDemand( maxRequired - required, seen ); - } - return required; } @@ -432,7 +414,6 @@ public class EnergyGridCache implements IEnergyGrid } } - // totalDrainPastTicks[0] += extractedPower; return extractedPower; } @@ -468,8 +449,32 @@ public class EnergyGridCache implements IEnergyGrid @Override public double injectPower( final double amt, final Actionable mode ) { - this.localSeen.clear(); - return this.injectAEPower( amt, mode, this.localSeen ); + final Queue toVisit = new PriorityQueue<>( COMPARATOR_LOWEST_PERCENTAGE_FIRST ); + final Set visited = new HashSet<>(); + toVisit.add( this ); + + double leftover = this.localStorage.injectAEPower( amt, mode ); + + while( !toVisit.isEmpty() && leftover > 0 ) + { + final IEnergyGridProvider next = toVisit.poll(); + visited.add( next ); + + final double cannotHold = next.injectProviderPower( amt, Actionable.SIMULATE, visited ); + next.injectProviderPower( leftover - cannotHold, mode, visited ); + + leftover = cannotHold; + + for( IEnergyGridProvider iEnergyGridProvider : next.providers() ) + { + if( !visited.contains( iEnergyGridProvider ) ) + { + toVisit.add( iEnergyGridProvider ); + } + } + } + + return leftover; } private IAEPowerStorage getFirstRequester() @@ -483,11 +488,6 @@ public class EnergyGridCache implements IEnergyGrid return this.lastRequester; } - private double buffer() - { - return this.providers.isEmpty() ? 1000.0 : 0.0; - } - @Override public double getStoredPower() { @@ -508,8 +508,41 @@ public class EnergyGridCache implements IEnergyGrid @Override public double getEnergyDemand( final double maxRequired ) { - this.localSeen.clear(); - return this.getEnergyDemand( maxRequired, this.localSeen ); + final Queue toVisit = new ArrayDeque<>(); + final Set visited = new HashSet<>(); + toVisit.add( this ); + + double required = 0; + + while( !toVisit.isEmpty() && required < maxRequired ) + { + final IEnergyGridProvider next = toVisit.poll(); + visited.add( next ); + + required += next.getProviderEnergyDemand( maxRequired - required, visited ); + + for( IEnergyGridProvider iEnergyGridProvider : next.providers() ) + { + if( !visited.contains( iEnergyGridProvider ) ) + { + toVisit.add( iEnergyGridProvider ); + } + } + } + + return required; + } + + @Override + public double getProviderStoredEnergy() + { + return this.getStoredPower(); + } + + @Override + public double getProviderMaxEnergy() + { + return this.getMaxStoredPower(); } @Override @@ -517,7 +550,7 @@ public class EnergyGridCache implements IEnergyGrid { if( machine instanceof IEnergyGridProvider ) { - this.energyGridProviders.remove( machine ); + this.energyGridProviders.remove( (IEnergyGridProvider) machine ); } // idle draw. @@ -546,18 +579,19 @@ public class EnergyGridCache implements IEnergyGrid this.lastRequester = null; } - this.providers.remove( machine ); - this.requesters.remove( machine ); + this.providers.remove( ps ); + this.requesters.remove( ps ); } } - if( machine instanceof IStackWatcherHost ) + if( machine instanceof IEnergyWatcherHost ) { - final IEnergyWatcher myWatcher = this.watchers.get( machine ); - if( myWatcher != null ) + final IEnergyWatcher watcher = this.watchers.get( node ); + + if( watcher != null ) { - myWatcher.reset(); - this.watchers.remove( machine ); + watcher.reset(); + this.watchers.remove( node ); } } } @@ -607,6 +641,7 @@ public class EnergyGridCache implements IEnergyGrid { final IEnergyWatcherHost swh = (IEnergyWatcherHost) machine; final EnergyWatcher iw = new EnergyWatcher( this, swh ); + this.watchers.put( node, iw ); swh.updateWatcher( iw ); } @@ -617,20 +652,21 @@ public class EnergyGridCache implements IEnergyGrid @Override public void onSplit( final IGridStorage storageB ) { - this.extra /= 2; - storageB.dataObject().setDouble( "extraEnergy", this.extra ); + final double newBuffer = this.localStorage.getAECurrentPower() / 2; + this.localStorage.setAECurrentPower( newBuffer ); + storageB.dataObject().setDouble( "buffer", newBuffer ); } @Override public void onJoin( final IGridStorage storageB ) { - this.extra += storageB.dataObject().getDouble( "extraEnergy" ); + this.localStorage.addAECurrentPower( storageB.dataObject().getDouble( "buffer" ) ); } @Override public void populateGridStorage( final IGridStorage storage ) { - storage.dataObject().setDouble( "extraEnergy", this.extra ); + storage.dataObject().setDouble( "buffer", this.localStorage.getAECurrentPower() ); } public boolean registerEnergyInterest( final EnergyThreshold threshold ) @@ -643,4 +679,78 @@ public class EnergyGridCache implements IEnergyGrid return this.interests.remove( threshold ); } + private class GridPowerStorage implements IAEPowerStorage + { + double stored = 0; + + @Override + public double extractAEPower( double amt, Actionable mode, PowerMultiplier usePowerMultiplier ) + { + double extracted = Math.min( amt, this.stored ); + + if( mode == Actionable.MODULATE ) + { + this.stored -= extracted; + + if( this.stored < MAX_BUFFER_STORAGE - 0.001 ) + { + EnergyGridCache.this.myGrid.postEvent( new MENetworkPowerStorage( this, PowerEventType.REQUEST_POWER ) ); + } + } + + if( extracted < amt ) + { + extracted += EnergyGridCache.this.extractAEPower( amt - extracted, Actionable.MODULATE, PowerMultiplier.CONFIG ); + } + + return extracted; + } + + @Override + public boolean isAEPublicPowerStorage() + { + return true; + } + + @Override + public double injectAEPower( double amt, Actionable mode ) + { + double toStore = Math.min( amt, MAX_BUFFER_STORAGE - this.stored ); + + if( mode == Actionable.MODULATE ) + { + this.stored += toStore; + } + + return amt - toStore; + } + + @Override + public AccessRestriction getPowerFlow() + { + return AccessRestriction.READ_WRITE; + } + + @Override + public double getAEMaxPower() + { + return MAX_BUFFER_STORAGE; + } + + @Override + public double getAECurrentPower() + { + return this.stored; + } + + public void setAECurrentPower( double amount ) + { + this.stored = amount; + } + + public void addAECurrentPower( double amount ) + { + this.stored += amount; + } + } } diff --git a/src/main/java/appeng/parts/networking/PartQuartzFiber.java b/src/main/java/appeng/parts/networking/PartQuartzFiber.java index ae32fe5c..b7015fa8 100644 --- a/src/main/java/appeng/parts/networking/PartQuartzFiber.java +++ b/src/main/java/appeng/parts/networking/PartQuartzFiber.java @@ -19,7 +19,9 @@ package appeng.parts.networking; +import java.util.Collection; import java.util.EnumSet; +import java.util.LinkedList; import java.util.Set; import net.minecraft.entity.player.EntityPlayer; @@ -131,14 +133,14 @@ public class PartQuartzFiber extends AEBasePart implements IEnergyGridProvider } @Override - public double extractAEPower( final double amt, final Actionable mode, final Set seen ) + public Collection providers() { - double acquiredPower = 0; + Collection stuff = new LinkedList<>(); try { final IEnergyGrid eg = this.getProxy().getEnergy(); - acquiredPower += eg.extractAEPower( amt - acquiredPower, mode, seen ); + stuff.add( eg ); } catch( final GridAccessException e ) { @@ -148,7 +150,43 @@ public class PartQuartzFiber extends AEBasePart implements IEnergyGridProvider try { final IEnergyGrid eg = this.outerProxy.getEnergy(); - acquiredPower += eg.extractAEPower( amt - acquiredPower, mode, seen ); + stuff.add( eg ); + } + catch( final GridAccessException e ) + { + // :P + } + + return stuff; + } + + @Override + public double extractProviderPower( final double amt, final Actionable mode, final Set seen ) + { + double acquiredPower = 0; + + try + { + final IEnergyGrid eg = this.getProxy().getEnergy(); + + if( !seen.contains( eg ) ) + { + acquiredPower += eg.extractProviderPower( amt - acquiredPower, mode, seen ); + } + } + catch( final GridAccessException e ) + { + // :P + } + + try + { + final IEnergyGrid eg = this.outerProxy.getEnergy(); + + if( !seen.contains( eg ) ) + { + acquiredPower += eg.extractProviderPower( amt - acquiredPower, mode, seen ); + } } catch( final GridAccessException e ) { @@ -159,15 +197,17 @@ public class PartQuartzFiber extends AEBasePart implements IEnergyGridProvider } @Override - public double injectAEPower( final double amt, final Actionable mode, final Set seen ) + public double injectProviderPower( final double amt, final Actionable mode, final Set seen ) { + double amount = amt; + try { final IEnergyGrid eg = this.getProxy().getEnergy(); if( !seen.contains( eg ) ) { - return eg.injectAEPower( amt, mode, seen ); + amount = eg.injectProviderPower( amount, mode, seen ); } } catch( final GridAccessException e ) @@ -180,7 +220,7 @@ public class PartQuartzFiber extends AEBasePart implements IEnergyGridProvider final IEnergyGrid eg = this.outerProxy.getEnergy(); if( !seen.contains( eg ) ) { - return eg.injectAEPower( amt, mode, seen ); + amount = eg.injectProviderPower( amount, mode, seen ); } } catch( final GridAccessException e ) @@ -188,18 +228,21 @@ public class PartQuartzFiber extends AEBasePart implements IEnergyGridProvider // :P } - return amt; + return amount; } @Override - public double getEnergyDemand( final double amt, final Set seen ) + public double getProviderEnergyDemand( final double amt, final Set seen ) { double demand = 0; try { final IEnergyGrid eg = this.getProxy().getEnergy(); - demand += eg.getEnergyDemand( amt - demand, seen ); + if( !seen.contains( eg ) ) + { + demand += eg.getProviderEnergyDemand( amt - demand, seen ); + } } catch( final GridAccessException e ) { @@ -209,7 +252,10 @@ public class PartQuartzFiber extends AEBasePart implements IEnergyGridProvider try { final IEnergyGrid eg = this.outerProxy.getEnergy(); - demand += eg.getEnergyDemand( amt - demand, seen ); + if( !seen.contains( eg ) ) + { + demand += eg.getProviderEnergyDemand( amt - demand, seen ); + } } catch( final GridAccessException e ) { @@ -219,6 +265,18 @@ public class PartQuartzFiber extends AEBasePart implements IEnergyGridProvider return demand; } + @Override + public double getProviderStoredEnergy() + { + return 0; + } + + @Override + public double getProviderMaxEnergy() + { + return 0; + } + @Override public IPartModel getStaticModels() { diff --git a/src/main/java/appeng/tile/misc/TileCharger.java b/src/main/java/appeng/tile/misc/TileCharger.java index dfe69dc9..cca24530 100644 --- a/src/main/java/appeng/tile/misc/TileCharger.java +++ b/src/main/java/appeng/tile/misc/TileCharger.java @@ -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() ) diff --git a/src/main/java/appeng/tile/networking/TileController.java b/src/main/java/appeng/tile/networking/TileController.java index e11f8bed..e3a042e7 100644 --- a/src/main/java/appeng/tile/networking/TileController.java +++ b/src/main/java/appeng/tile/networking/TileController.java @@ -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 ) { diff --git a/src/main/java/appeng/tile/networking/TileEnergyAcceptor.java b/src/main/java/appeng/tile/networking/TileEnergyAcceptor.java index c9ecb7bd..69607da2 100644 --- a/src/main/java/appeng/tile/networking/TileEnergyAcceptor.java +++ b/src/main/java/appeng/tile/networking/TileEnergyAcceptor.java @@ -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 ) { diff --git a/src/main/java/appeng/tile/powersink/AEBasePoweredTile.java b/src/main/java/appeng/tile/powersink/AEBasePoweredTile.java index 774e7e0c..8dd4bb13 100644 --- a/src/main/java/appeng/tile/powersink/AEBasePoweredTile.java +++ b/src/main/java/appeng/tile/powersink/AEBasePoweredTile.java @@ -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 ) diff --git a/src/main/java/appeng/tile/powersink/ForgeEnergyAdapter.java b/src/main/java/appeng/tile/powersink/ForgeEnergyAdapter.java index 3c257375..c5572c60 100644 --- a/src/main/java/appeng/tile/powersink/ForgeEnergyAdapter.java +++ b/src/main/java/appeng/tile/powersink/ForgeEnergyAdapter.java @@ -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 diff --git a/src/main/java/appeng/tile/powersink/IExternalPowerSink.java b/src/main/java/appeng/tile/powersink/IExternalPowerSink.java index a4884375..568bc696 100644 --- a/src/main/java/appeng/tile/powersink/IExternalPowerSink.java +++ b/src/main/java/appeng/tile/powersink/IExternalPowerSink.java @@ -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 ); } diff --git a/src/main/java/appeng/tile/powersink/TeslaEnergyAdapter.java b/src/main/java/appeng/tile/powersink/TeslaEnergyAdapter.java index 6d3c71dc..a644c88c 100644 --- a/src/main/java/appeng/tile/powersink/TeslaEnergyAdapter.java +++ b/src/main/java/appeng/tile/powersink/TeslaEnergyAdapter.java @@ -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 ); } - }