rewritten PowerGraph

This commit is contained in:
Baltazár Radics
2018-11-18 23:12:54 +01:00
parent 8091bec6bf
commit 285ee665ee
9 changed files with 63 additions and 161 deletions
@@ -43,13 +43,13 @@ public class PowerBlocks extends BlockList implements ContentList{
itemDuration = 220f; itemDuration = 220f;
}}; }};
solarPanel = new SolarGenerator("solar-panel"){{ solarPanel = new PowerGenerator("solar-panel"){{
generation = 0.0045f; powerGeneration = 0.0045f;
}}; }};
largeSolarPanel = new SolarGenerator("solar-panel-large"){{ largeSolarPanel = new PowerGenerator("solar-panel-large"){{
powerGeneration = 0.055f;
size = 3; size = 3;
generation = 0.055f;
}}; }};
thoriumReactor = new NuclearReactor("thorium-reactor"){{ thoriumReactor = new NuclearReactor("thorium-reactor"){{
@@ -28,6 +28,8 @@ public abstract class BaseBlock extends MappableContent{
public boolean consumesPower; public boolean consumesPower;
public boolean outputsPower; public boolean outputsPower;
public float basePowerUse = 0;
public int itemCapacity; public int itemCapacity;
public float liquidCapacity = 10f; public float liquidCapacity = 10f;
public float liquidFlowFactor = 4.9f; public float liquidFlowFactor = 4.9f;
@@ -25,7 +25,6 @@ import static io.anuke.mindustry.Vars.tilesize;
public abstract class ItemGenerator extends PowerGenerator{ public abstract class ItemGenerator extends PowerGenerator{
protected float minItemEfficiency = 0.2f; protected float minItemEfficiency = 0.2f;
protected float powerOutput;
protected float itemDuration = 70f; protected float itemDuration = 70f;
protected Effect generateEffect = BlockFx.generatespark, explodeEffect = protected Effect generateEffect = BlockFx.generatespark, explodeEffect =
BlockFx.generatespark; BlockFx.generatespark;
@@ -46,13 +45,6 @@ public abstract class ItemGenerator extends PowerGenerator{
topRegion = Draw.region(name + "-top"); topRegion = Draw.region(name + "-top");
} }
@Override
public void setStats(){
super.setStats();
stats.add(BlockStat.basePowerGeneration, powerOutput * 60f * 0.5f, StatUnit.powerSecond);
}
@Override @Override
public void setBars(){ public void setBars(){
super.setBars(); super.setBars();
@@ -84,22 +76,16 @@ public abstract class ItemGenerator extends PowerGenerator{
public void update(Tile tile){ public void update(Tile tile){
ItemGeneratorEntity entity = tile.entity(); ItemGeneratorEntity entity = tile.entity();
float maxPower = Math.min(powerCapacity - entity.power.amount, powerOutput * entity.delta()) * entity.efficiency;
if(entity.generateTime <= 0f && entity.items.total() > 0){ if(entity.generateTime <= 0f && entity.items.total() > 0){
Effects.effect(generateEffect, tile.worldx() + Mathf.range(3f), tile.worldy() + Mathf.range(3f)); Effects.effect(generateEffect, tile.worldx() + Mathf.range(3f), tile.worldy() + Mathf.range(3f));
Item item = entity.items.take(); Item item = entity.items.take();
entity.efficiency = getItemEfficiency(item); entity.productionEfficiency = getItemEfficiency(item);
entity.explosiveness = item.explosiveness; entity.explosiveness = item.explosiveness;
entity.generateTime = 1f; entity.generateTime = 1f;
} }
entity.power.graph.update();
if(entity.generateTime > 0f){ if(entity.generateTime > 0f){
entity.generateTime -= 1f / itemDuration * entity.delta(); entity.generateTime -= Math.min(1f / itemDuration * entity.delta(), entity.generateTime);
entity.power.amount += maxPower;
entity.generateTime = Mathf.clamp(entity.generateTime);
if(Mathf.chance(entity.delta() * 0.06 * Mathf.clamp(entity.explosiveness - 0.25f))){ if(Mathf.chance(entity.delta() * 0.06 * Mathf.clamp(entity.explosiveness - 0.25f))){
//this block is run last so that in the event of a block destruction, no code relies on the block type //this block is run last so that in the event of a block destruction, no code relies on the block type
@@ -117,18 +103,6 @@ public abstract class ItemGenerator extends PowerGenerator{
} }
public static class ItemGeneratorEntity extends GeneratorEntity{ public static class ItemGeneratorEntity extends GeneratorEntity{
public float efficiency;
public float explosiveness; public float explosiveness;
@Override
public void write(DataOutput stream) throws IOException{
stream.writeFloat(efficiency);
}
@Override
public void read(DataInput stream) throws IOException{
efficiency = stream.readFloat();
}
} }
} }
@@ -1,10 +1,15 @@
package io.anuke.mindustry.world.blocks.power; package io.anuke.mindustry.world.blocks.power;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.world.meta.BlockFlag;
import io.anuke.ucore.util.EnumSet; import io.anuke.ucore.util.EnumSet;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.meta.BlockFlag;
import io.anuke.mindustry.world.meta.BlockStat;
public class PowerGenerator extends PowerDistributor{ public class PowerGenerator extends PowerDistributor{
public float powerProduction;
public BlockStat generationType = BlockStat.basePowerGeneration;
public PowerGenerator(String name){ public PowerGenerator(String name){
super(name); super(name);
@@ -12,6 +17,17 @@ public class PowerGenerator extends PowerDistributor{
flags = EnumSet.of(BlockFlag.producer); flags = EnumSet.of(BlockFlag.producer);
} }
@Override
public void setStats(){
super.setStats();
stats.add(generationType, baseGeneration * 60f, StatUnit.powerSecond);
}
@Override
public float getPowerProduction(Tile tile){
return powerProduction * tile.<GeneratorEntity>entity().productionEfficiency * tile.entity.delta();
}
@Override @Override
public boolean outputsItems(){ public boolean outputsItems(){
return false; return false;
@@ -24,5 +40,6 @@ public class PowerGenerator extends PowerDistributor{
public static class GeneratorEntity extends TileEntity{ public static class GeneratorEntity extends TileEntity{
public float generateTime; public float generateTime;
public float productionEfficiency = 1;
} }
} }
@@ -17,6 +17,7 @@ public class PowerGraph{
private final ObjectSet<Tile> producers = new ObjectSet<>(); private final ObjectSet<Tile> producers = new ObjectSet<>();
private final ObjectSet<Tile> consumers = new ObjectSet<>(); private final ObjectSet<Tile> consumers = new ObjectSet<>();
private final ObjectSet<Tile> batteries = new ObjectSet<>();
private final ObjectSet<Tile> all = new ObjectSet<>(); private final ObjectSet<Tile> all = new ObjectSet<>();
private long lastFrameUpdated; private long lastFrameUpdated;
@@ -38,38 +39,43 @@ public class PowerGraph{
lastFrameUpdated = threads.getFrameID(); lastFrameUpdated = threads.getFrameID();
float totalInput = 0f; float powerProduced = 0f;
for(Tile producer : producers){ for(Tile producer : producers){
totalInput += producer.entity.power.amount; totalInput += producer.block().getPowerProduction(producer);
} }
for(Tile producer : producers){ float powerNeeded = 0f;
float accumulator = producer.entity.power.amount; for(Tile consumer : consumers){
powerNeeded += consumer.block().basePowerUse + consumer.entity.power.extraUse;
}
if(accumulator <= 0.0001f) continue; float totalAccumulator = 0f;
float totalCapacity = 0f;
for(Tile battery : batteries){
totalAccumulator += battery.entity.power.satisfaction * battery.block().basePowerUse;
totalCapacity += (1f - battery.entity.power.satisfaction) * battery.block().basePowerUse;
}
float toEach = accumulator / consumers.size; if(powerNeeded > powerProduced){
float outputs = 0f; float accumulatorUsed = Math.min(totalAccumulator, powerNeeded - powerProduced);
float thing = 1f - (accumulatorUsed / totalAccumulator);
for(Tile tile : consumers){ for(Tile battery : batteries){
outputs += Math.min(tile.block().powerCapacity - tile.entity.power.amount, toEach) / toEach; battery.entity.power.satisfaction *= thing;
} }
powerProduced += accumulatorUsed;
}
float finalEach = toEach / outputs * Timers.delta(); float powerSatisfaction = Math.max(1, powerProduced / powerNeeded);
float buffer = 0f; for(Tile consumer : producers){
consumer.power.satisfaction = powerSatisfaction;
}
if(Float.isNaN(finalEach) || Float.isInfinite(finalEach)){ if(powerProduced > powerNeeded){
continue; powerProduced -= powerNeeded;
float thing = Math.min(1, powerProduced / totalCapacity);
for(tile battery : batteries){
battery.power.satisfaction += (1 - battery.power.satisfaction) * thing;
} }
for(Tile tile : consumers){
float used = Math.min(tile.block().powerCapacity - tile.entity.power.amount, finalEach) * accumulator / totalInput;
buffer += used;
tile.entity.power.amount += used;
}
producer.entity.power.amount -= buffer;
} }
} }
@@ -83,11 +89,11 @@ public class PowerGraph{
tile.entity.power.graph = this; tile.entity.power.graph = this;
all.add(tile); all.add(tile);
if(tile.block().outputsPower){ if(tile.block().outputsPower && tile.block().consumesPower){
batteries.add(tile);
}else if(tile.block().outputsPower){
producers.add(tile); producers.add(tile);
} }else if(tile.block().consumesPower){
if(tile.block().consumesPower){
consumers.add(tile); consumers.add(tile);
} }
} }
@@ -99,6 +105,7 @@ public class PowerGraph{
all.clear(); all.clear();
producers.clear(); producers.clear();
consumers.clear(); consumers.clear();
batteries.clear();
} }
public void reflow(Tile tile){ public void reflow(Tile tile){
@@ -146,6 +153,7 @@ public class PowerGraph{
return "PowerGraph{" + return "PowerGraph{" +
"producers=" + producers + "producers=" + producers +
", consumers=" + consumers + ", consumers=" + consumers +
", batteries=" + batteries +
", all=" + all + ", all=" + all +
", lastFrameUpdated=" + lastFrameUpdated + ", lastFrameUpdated=" + lastFrameUpdated +
", graphID=" + graphID + ", graphID=" + graphID +
@@ -1,34 +0,0 @@
package io.anuke.mindustry.world.blocks.power;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.meta.BlockStat;
import io.anuke.mindustry.world.meta.StatUnit;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.util.EnumSet;
public class SolarGenerator extends PowerGenerator{
/**
* power generated per frame
*/
protected float generation = 0.005f;
public SolarGenerator(String name){
super(name);
flags = EnumSet.of();
}
@Override
public void setStats(){
super.setStats();
stats.add(BlockStat.basePowerGeneration, generation * 60f, StatUnit.powerSecond);
}
@Override
public void update(Tile tile){
addPower(tile, generation * Timers.delta());
tile.entity.power.graph.update();
}
}
@@ -1,45 +0,0 @@
package io.anuke.mindustry.world.consumers;
import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.meta.BlockStat;
import io.anuke.mindustry.world.meta.BlockStats;
import io.anuke.mindustry.world.meta.StatUnit;
public class ConsumePower extends Consume{
protected final float use;
public ConsumePower(float use){
this.use = use;
}
@Override
public void buildTooltip(Table table){
}
@Override
public String getIcon(){
return "icon-power";
}
@Override
public boolean valid(Block block, TileEntity entity){
return entity.power.satisfaction >= 1;
}
@Override
public void display(BlockStats stats){
stats.add(BlockStat.powerUse, use * 60f, StatUnit.powerSecond);
}
public float getUse(Block block, TileEntity entity){
return use * entity.delta();
}
public void addPower(float amount) {
entity.power.satisfaction = amount / getUse();
}
}
@@ -1,21 +0,0 @@
package io.anuke.mindustry.world.consumers;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.consumers.ConsumePower;
public class ConsumePowerBuffered extends ConsumePower{
@Override
public float getUse(Block block, TileEntity entity){
return use * (1 - entity.power.satisfaction);
}
@Override
public void addPower(float amount){
entity.power.satisfaction = Math.min(entity.power.satisfaction + (amount / use), 1);
}
public void usePower(float amount){
entity.power.satisfaction = Math.max(entity.power.satisfaction - (amount / use), 0);
}
}
@@ -9,6 +9,7 @@ import java.io.IOException;
public class PowerModule extends BlockModule{ public class PowerModule extends BlockModule{
public float satisfaction; public float satisfaction;
public float extraUse = 0f;
public PowerGraph graph = new PowerGraph(); public PowerGraph graph = new PowerGraph();
public IntArray links = new IntArray(); public IntArray links = new IntArray();