mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-07-22 05:38:19 +07:00
Continued work on power generators
This commit is contained in:
@ -20,17 +20,13 @@ public class PowerBlocks extends BlockList implements ContentList{
|
|||||||
|
|
||||||
thermalGenerator = new LiquidHeatGenerator("thermal-generator"){{
|
thermalGenerator = new LiquidHeatGenerator("thermal-generator"){{
|
||||||
maxLiquidGenerate = 4f;
|
maxLiquidGenerate = 4f;
|
||||||
// TODO: Balance
|
powerProduction = 8f;
|
||||||
powerProduction = 0.17f;
|
|
||||||
liquidPowerMultiplier = 0.1f;
|
|
||||||
generateEffect = BlockFx.redgeneratespark;
|
generateEffect = BlockFx.redgeneratespark;
|
||||||
size = 2;
|
size = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
turbineGenerator = new TurbineGenerator("turbine-generator"){{
|
turbineGenerator = new TurbineGenerator("turbine-generator"){{
|
||||||
// TODO: Balance
|
|
||||||
powerProduction = 0.28f;
|
powerProduction = 0.28f;
|
||||||
liquidPowerMultiplier = 0.3f;
|
|
||||||
itemDuration = 30f;
|
itemDuration = 30f;
|
||||||
consumes.liquid(Liquids.water, 0.05f);
|
consumes.liquid(Liquids.water, 0.05f);
|
||||||
size = 2;
|
size = 2;
|
||||||
|
@ -30,7 +30,6 @@ public class ItemLiquidGenerator extends PowerGenerator{
|
|||||||
protected float itemDuration = 70f;
|
protected float itemDuration = 70f;
|
||||||
|
|
||||||
protected float minLiquidEfficiency = 0.2f;
|
protected float minLiquidEfficiency = 0.2f;
|
||||||
protected float liquidPowerMultiplier = 1.3f; // A liquid with 100% flammability will be 30% more efficient than an item with 100% flammability.
|
|
||||||
/** Maximum liquid used per frame. */
|
/** Maximum liquid used per frame. */
|
||||||
protected float maxLiquidGenerate = 0.4f;
|
protected float maxLiquidGenerate = 0.4f;
|
||||||
|
|
||||||
@ -100,14 +99,14 @@ public class ItemLiquidGenerator extends PowerGenerator{
|
|||||||
}
|
}
|
||||||
//liquid takes priority over solids
|
//liquid takes priority over solids
|
||||||
if(hasLiquids && liquid != null && entity.liquids.get(liquid) >= 0.001f){
|
if(hasLiquids && liquid != null && entity.liquids.get(liquid) >= 0.001f){
|
||||||
float baseLiquidEfficiency = getLiquidEfficiency(liquid) * this.liquidPowerMultiplier;
|
float baseLiquidEfficiency = getLiquidEfficiency(liquid);
|
||||||
float maximumPossible = maxLiquidGenerate * calculationDelta;
|
float maximumPossible = maxLiquidGenerate * calculationDelta;
|
||||||
float used = Math.min(entity.liquids.get(liquid) * calculationDelta, maximumPossible);
|
float used = Math.min(entity.liquids.get(liquid) * calculationDelta, maximumPossible);
|
||||||
|
|
||||||
entity.liquids.remove(liquid, used);
|
entity.liquids.remove(liquid, used);
|
||||||
|
|
||||||
// Note: 1 Item with 100% Flammability = 100% efficiency. This means 100% is not max but rather a reference point for this generator.
|
// Note: 0.5 = 100%. PowerGraph will multiply this efficiency by two on its own.
|
||||||
entity.productionEfficiency = baseLiquidEfficiency * used / maximumPossible;
|
entity.productionEfficiency = Mathf.clamp(baseLiquidEfficiency * used / maximumPossible);
|
||||||
|
|
||||||
if(used > 0.001f && Mathf.chance(0.05 * entity.delta())){
|
if(used > 0.001f && Mathf.chance(0.05 * entity.delta())){
|
||||||
Effects.effect(generateEffect, tile.drawx() + Mathf.range(3f), tile.drawy() + Mathf.range(3f));
|
Effects.effect(generateEffect, tile.drawx() + Mathf.range(3f), tile.drawy() + Mathf.range(3f));
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package io.anuke.mindustry.world.blocks.power;
|
package io.anuke.mindustry.world.blocks.power;
|
||||||
|
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.content.Liquids;
|
||||||
import io.anuke.mindustry.type.Liquid;
|
import io.anuke.mindustry.type.Liquid;
|
||||||
import io.anuke.mindustry.world.meta.BlockStat;
|
import io.anuke.mindustry.world.meta.BlockStat;
|
||||||
import io.anuke.mindustry.world.meta.StatUnit;
|
import io.anuke.mindustry.world.meta.StatUnit;
|
||||||
@ -16,8 +16,8 @@ public class LiquidHeatGenerator extends ItemLiquidGenerator{
|
|||||||
super.setStats();
|
super.setStats();
|
||||||
|
|
||||||
stats.remove(BlockStat.basePowerGeneration);
|
stats.remove(BlockStat.basePowerGeneration);
|
||||||
// TODO Adapt to new new power system. Maybe this override can be removed.
|
// Right now, Lava is the only thing that can be used.
|
||||||
//stats.add(BlockStat.basePowerGeneration, <Do something with maxLiquidGenerate, basePowerGeneration and liquidPowerMultiplier> * 60f, StatUnit.powerSecond);
|
stats.add(BlockStat.basePowerGeneration, powerProduction * getLiquidEfficiency(Liquids.lava) / maxLiquidGenerate * 60f, StatUnit.powerSecond);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -33,12 +33,14 @@ public class PowerGenerator extends PowerDistributor{
|
|||||||
@Override
|
@Override
|
||||||
public void setStats(){
|
public void setStats(){
|
||||||
super.setStats();
|
super.setStats();
|
||||||
stats.add(generationType, powerProduction * 60.0f, StatUnit.powerSecond);
|
// Divide power production by two since that is what is produced at an efficiency of 0.5, which currently represents 100%
|
||||||
|
stats.add(generationType, powerProduction * 60.0f / 2.0f, StatUnit.powerSecond);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getPowerProduction(Tile tile){
|
public float getPowerProduction(Tile tile){
|
||||||
return powerProduction * tile.<GeneratorEntity>entity().productionEfficiency;
|
// Multiply all efficiencies by two since 0.5 = 100% efficiency
|
||||||
|
return powerProduction * tile.<GeneratorEntity>entity().productionEfficiency * 2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,7 +26,6 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{
|
|||||||
private ItemLiquidGenerator generator;
|
private ItemLiquidGenerator generator;
|
||||||
private Tile tile;
|
private Tile tile;
|
||||||
private ItemLiquidGenerator.ItemLiquidGeneratorEntity entity;
|
private ItemLiquidGenerator.ItemLiquidGeneratorEntity entity;
|
||||||
private final float fakeLiquidPowerMultiplier = 2.0f;
|
|
||||||
private final float fakeItemDuration = 60f; // 60 ticks
|
private final float fakeItemDuration = 60f; // 60 ticks
|
||||||
private final float maximumLiquidUsage = 0.5f;
|
private final float maximumLiquidUsage = 0.5f;
|
||||||
|
|
||||||
@ -35,7 +34,6 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{
|
|||||||
{
|
{
|
||||||
powerProduction = 0.1f;
|
powerProduction = 0.1f;
|
||||||
itemDuration = 60f;
|
itemDuration = 60f;
|
||||||
liquidPowerMultiplier = fakeLiquidPowerMultiplier;
|
|
||||||
itemDuration = fakeItemDuration;
|
itemDuration = fakeItemDuration;
|
||||||
maxLiquidGenerate = maximumLiquidUsage;
|
maxLiquidGenerate = maximumLiquidUsage;
|
||||||
}
|
}
|
||||||
@ -79,7 +77,7 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void simulateLiquidConsumption(ItemLiquidGenerator.InputType inputType, Liquid liquid, float availableLiquidAmount, String parameterDescription){
|
void simulateLiquidConsumption(ItemLiquidGenerator.InputType inputType, Liquid liquid, float availableLiquidAmount, String parameterDescription){
|
||||||
final float baseEfficiency = fakeLiquidPowerMultiplier * liquid.flammability;
|
final float baseEfficiency = liquid.flammability;
|
||||||
final float expectedEfficiency = Math.min(1.0f, availableLiquidAmount / maximumLiquidUsage) * baseEfficiency;
|
final float expectedEfficiency = Math.min(1.0f, availableLiquidAmount / maximumLiquidUsage) * baseEfficiency;
|
||||||
final float expectedConsumptionPerTick = Math.min(maximumLiquidUsage, availableLiquidAmount);
|
final float expectedConsumptionPerTick = Math.min(maximumLiquidUsage, availableLiquidAmount);
|
||||||
final float expectedRemainingLiquidAmount = Math.max(0.0f, availableLiquidAmount - expectedConsumptionPerTick * FakeThreadHandler.fakeDelta);
|
final float expectedRemainingLiquidAmount = Math.max(0.0f, availableLiquidAmount - expectedConsumptionPerTick * FakeThreadHandler.fakeDelta);
|
||||||
|
74
tests/src/test/java/power/PowerBalancingTests.java
Normal file
74
tests/src/test/java/power/PowerBalancingTests.java
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package power;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.math.MathUtils;
|
||||||
|
import io.anuke.mindustry.content.Items;
|
||||||
|
import io.anuke.mindustry.content.Liquids;
|
||||||
|
import io.anuke.mindustry.content.blocks.PowerBlocks;
|
||||||
|
import io.anuke.mindustry.type.Item;
|
||||||
|
import io.anuke.mindustry.type.Liquid;
|
||||||
|
import io.anuke.mindustry.world.Block;
|
||||||
|
import io.anuke.mindustry.world.Tile;
|
||||||
|
import io.anuke.mindustry.world.blocks.power.BurnerGenerator;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
/** Sets expectations to specific production blocks using specific inputs. */
|
||||||
|
|
||||||
|
public class PowerBalancingTests extends PowerTestFixture{
|
||||||
|
// Last updated to values of: v63
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the produced power of a power block with items or liquids.
|
||||||
|
* @apiNote Tests only a single tick with a fixed delta and interpolates that to match one second.
|
||||||
|
* @param powerBlock The block to be tested.
|
||||||
|
* @param inputItem The item to be supplied (may be null).
|
||||||
|
* @param inputLiquid The liquid to be supplied (may be null).
|
||||||
|
* @param expectedPowerPerSecond The amount of power which should be produced per second.
|
||||||
|
*/
|
||||||
|
public void testPowerGenerator(Block powerBlock, Item inputItem, Liquid inputLiquid, float expectedPowerPerSecond){
|
||||||
|
Tile fakeTile = createFakeTile(0, 0, powerBlock);
|
||||||
|
if(inputItem != null){
|
||||||
|
fakeTile.entity.items.add(inputItem, 1);
|
||||||
|
}
|
||||||
|
if(inputLiquid != null){
|
||||||
|
fakeTile.entity.liquids.add(inputLiquid, 1);
|
||||||
|
}
|
||||||
|
fakeTile.entity.cons.update(fakeTile.entity);
|
||||||
|
powerBlock.update(fakeTile);
|
||||||
|
|
||||||
|
assertEquals(expectedPowerPerSecond, fakeTile.entity.power.graph.getPowerProduced() * 60f, MathUtils.FLOAT_ROUNDING_ERROR * 10.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCombustionWithCoal(){
|
||||||
|
testPowerGenerator(PowerBlocks.combustionGenerator, Items.coal, null, 2.7f); // 100% flammability
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCombustionWithOil(){
|
||||||
|
testPowerGenerator(PowerBlocks.combustionGenerator, null, Liquids.oil, 2.7f * 1.2f); // 120% flammability
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCombustionWithBlastCompound(){
|
||||||
|
testPowerGenerator(PowerBlocks.combustionGenerator, Items.blastCompound, null, 2.7f * 0.4f); // 40% flammability
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTurbineWithCoal(){
|
||||||
|
testPowerGenerator(PowerBlocks.turbineGenerator, Items.coal, Liquids.water, 8.4f); // 100% flammability
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTurbineWithBiomatter(){
|
||||||
|
testPowerGenerator(PowerBlocks.turbineGenerator, Items.biomatter, Liquids.water, 8.4f * 0.8f); // 100% flammability
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testThermalWithLava(){
|
||||||
|
testPowerGenerator(PowerBlocks.thermalGenerator, null, Liquids.lava, 36f); // 100% flammability
|
||||||
|
}
|
||||||
|
}
|
@ -49,7 +49,7 @@ public class PowerTests extends PowerTestFixture{
|
|||||||
}
|
}
|
||||||
void simulateDirectConsumption(float producedPower, float requiredPower, float expectedSatisfaction, String parameterDescription){
|
void simulateDirectConsumption(float producedPower, float requiredPower, float expectedSatisfaction, String parameterDescription){
|
||||||
Tile producerTile = createFakeTile(0, 0, createFakeProducerBlock(producedPower));
|
Tile producerTile = createFakeTile(0, 0, createFakeProducerBlock(producedPower));
|
||||||
producerTile.<PowerGenerator.GeneratorEntity>entity().productionEfficiency = 1.0f;
|
producerTile.<PowerGenerator.GeneratorEntity>entity().productionEfficiency = 0.5f; // Currently, 0.5f = 100%
|
||||||
Tile directConsumerTile = createFakeTile(0, 1, createFakeDirectConsumer(requiredPower, 0.6f));
|
Tile directConsumerTile = createFakeTile(0, 1, createFakeDirectConsumer(requiredPower, 0.6f));
|
||||||
|
|
||||||
PowerGraph powerGraph = new PowerGraph();
|
PowerGraph powerGraph = new PowerGraph();
|
||||||
@ -89,7 +89,7 @@ public class PowerTests extends PowerTestFixture{
|
|||||||
}
|
}
|
||||||
void simulateBufferedConsumption(float producedPower, float maxBuffer, float powerConsumedPerTick, float initialSatisfaction, float expectedSatisfaction, String parameterDescription){
|
void simulateBufferedConsumption(float producedPower, float maxBuffer, float powerConsumedPerTick, float initialSatisfaction, float expectedSatisfaction, String parameterDescription){
|
||||||
Tile producerTile = createFakeTile(0, 0, createFakeProducerBlock(producedPower));
|
Tile producerTile = createFakeTile(0, 0, createFakeProducerBlock(producedPower));
|
||||||
producerTile.<PowerGenerator.GeneratorEntity>entity().productionEfficiency = 1.0f;
|
producerTile.<PowerGenerator.GeneratorEntity>entity().productionEfficiency = 0.5f; // Currently, 0.5 = 100%
|
||||||
Tile bufferedConsumerTile = createFakeTile(0, 1, createFakeBufferedConsumer(maxBuffer, maxBuffer > 0.0f ? maxBuffer/powerConsumedPerTick : 1.0f));
|
Tile bufferedConsumerTile = createFakeTile(0, 1, createFakeBufferedConsumer(maxBuffer, maxBuffer > 0.0f ? maxBuffer/powerConsumedPerTick : 1.0f));
|
||||||
bufferedConsumerTile.entity.power.satisfaction = initialSatisfaction;
|
bufferedConsumerTile.entity.power.satisfaction = initialSatisfaction;
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ public class PowerTests extends PowerTestFixture{
|
|||||||
|
|
||||||
if(producedPower > 0.0f){
|
if(producedPower > 0.0f){
|
||||||
Tile producerTile = createFakeTile(0, 0, createFakeProducerBlock(producedPower));
|
Tile producerTile = createFakeTile(0, 0, createFakeProducerBlock(producedPower));
|
||||||
producerTile.<PowerGenerator.GeneratorEntity>entity().productionEfficiency = 1.0f;
|
producerTile.<PowerGenerator.GeneratorEntity>entity().productionEfficiency = 0.5f; // Currently, 0.5f = 100%
|
||||||
powerGraph.add(producerTile);
|
powerGraph.add(producerTile);
|
||||||
}
|
}
|
||||||
Tile directConsumerTile = null;
|
Tile directConsumerTile = null;
|
||||||
|
Reference in New Issue
Block a user