diff --git a/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java b/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java index c2f2e24596..dbd70cbeca 100644 --- a/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java @@ -20,17 +20,13 @@ public class PowerBlocks extends BlockList implements ContentList{ thermalGenerator = new LiquidHeatGenerator("thermal-generator"){{ maxLiquidGenerate = 4f; - // TODO: Balance - powerProduction = 0.17f; - liquidPowerMultiplier = 0.1f; + powerProduction = 8f; generateEffect = BlockFx.redgeneratespark; size = 2; }}; turbineGenerator = new TurbineGenerator("turbine-generator"){{ - // TODO: Balance powerProduction = 0.28f; - liquidPowerMultiplier = 0.3f; itemDuration = 30f; consumes.liquid(Liquids.water, 0.05f); size = 2; diff --git a/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java index 7fbc233533..0fab57f16d 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java @@ -30,7 +30,6 @@ public class ItemLiquidGenerator extends PowerGenerator{ protected float itemDuration = 70f; 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. */ protected float maxLiquidGenerate = 0.4f; @@ -100,14 +99,14 @@ public class ItemLiquidGenerator extends PowerGenerator{ } //liquid takes priority over solids 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 used = Math.min(entity.liquids.get(liquid) * calculationDelta, maximumPossible); 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. - entity.productionEfficiency = baseLiquidEfficiency * used / maximumPossible; + // Note: 0.5 = 100%. PowerGraph will multiply this efficiency by two on its own. + entity.productionEfficiency = Mathf.clamp(baseLiquidEfficiency * used / maximumPossible); if(used > 0.001f && Mathf.chance(0.05 * entity.delta())){ Effects.effect(generateEffect, tile.drawx() + Mathf.range(3f), tile.drawy() + Mathf.range(3f)); diff --git a/core/src/io/anuke/mindustry/world/blocks/power/LiquidHeatGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/LiquidHeatGenerator.java index c1d95d9ff1..bf65ea8bd5 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/LiquidHeatGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/LiquidHeatGenerator.java @@ -1,6 +1,6 @@ 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.world.meta.BlockStat; import io.anuke.mindustry.world.meta.StatUnit; @@ -16,8 +16,8 @@ public class LiquidHeatGenerator extends ItemLiquidGenerator{ super.setStats(); stats.remove(BlockStat.basePowerGeneration); - // TODO Adapt to new new power system. Maybe this override can be removed. - //stats.add(BlockStat.basePowerGeneration, * 60f, StatUnit.powerSecond); + // Right now, Lava is the only thing that can be used. + stats.add(BlockStat.basePowerGeneration, powerProduction * getLiquidEfficiency(Liquids.lava) / maxLiquidGenerate * 60f, StatUnit.powerSecond); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java index 49da784b2a..84b2b6c841 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java @@ -33,12 +33,14 @@ public class PowerGenerator extends PowerDistributor{ @Override public void 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 public float getPowerProduction(Tile tile){ - return powerProduction * tile.entity().productionEfficiency; + // Multiply all efficiencies by two since 0.5 = 100% efficiency + return powerProduction * tile.entity().productionEfficiency * 2.0f; } @Override diff --git a/tests/src/test/java/power/ItemLiquidGeneratorTests.java b/tests/src/test/java/power/ItemLiquidGeneratorTests.java index 8a2fa7ff18..dcde4df3e1 100644 --- a/tests/src/test/java/power/ItemLiquidGeneratorTests.java +++ b/tests/src/test/java/power/ItemLiquidGeneratorTests.java @@ -26,7 +26,6 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ private ItemLiquidGenerator generator; private Tile tile; private ItemLiquidGenerator.ItemLiquidGeneratorEntity entity; - private final float fakeLiquidPowerMultiplier = 2.0f; private final float fakeItemDuration = 60f; // 60 ticks private final float maximumLiquidUsage = 0.5f; @@ -35,7 +34,6 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ { powerProduction = 0.1f; itemDuration = 60f; - liquidPowerMultiplier = fakeLiquidPowerMultiplier; itemDuration = fakeItemDuration; maxLiquidGenerate = maximumLiquidUsage; } @@ -79,7 +77,7 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ } 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 expectedConsumptionPerTick = Math.min(maximumLiquidUsage, availableLiquidAmount); final float expectedRemainingLiquidAmount = Math.max(0.0f, availableLiquidAmount - expectedConsumptionPerTick * FakeThreadHandler.fakeDelta); diff --git a/tests/src/test/java/power/PowerBalancingTests.java b/tests/src/test/java/power/PowerBalancingTests.java new file mode 100644 index 0000000000..72a7811e73 --- /dev/null +++ b/tests/src/test/java/power/PowerBalancingTests.java @@ -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 + } +} diff --git a/tests/src/test/java/power/PowerTests.java b/tests/src/test/java/power/PowerTests.java index 5c1bea7d0c..e8167a4aec 100644 --- a/tests/src/test/java/power/PowerTests.java +++ b/tests/src/test/java/power/PowerTests.java @@ -49,7 +49,7 @@ public class PowerTests extends PowerTestFixture{ } void simulateDirectConsumption(float producedPower, float requiredPower, float expectedSatisfaction, String parameterDescription){ Tile producerTile = createFakeTile(0, 0, createFakeProducerBlock(producedPower)); - producerTile.entity().productionEfficiency = 1.0f; + producerTile.entity().productionEfficiency = 0.5f; // Currently, 0.5f = 100% Tile directConsumerTile = createFakeTile(0, 1, createFakeDirectConsumer(requiredPower, 0.6f)); 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){ Tile producerTile = createFakeTile(0, 0, createFakeProducerBlock(producedPower)); - producerTile.entity().productionEfficiency = 1.0f; + producerTile.entity().productionEfficiency = 0.5f; // Currently, 0.5 = 100% Tile bufferedConsumerTile = createFakeTile(0, 1, createFakeBufferedConsumer(maxBuffer, maxBuffer > 0.0f ? maxBuffer/powerConsumedPerTick : 1.0f)); bufferedConsumerTile.entity.power.satisfaction = initialSatisfaction; @@ -128,7 +128,7 @@ public class PowerTests extends PowerTestFixture{ if(producedPower > 0.0f){ Tile producerTile = createFakeTile(0, 0, createFakeProducerBlock(producedPower)); - producerTile.entity().productionEfficiency = 1.0f; + producerTile.entity().productionEfficiency = 0.5f; // Currently, 0.5f = 100% powerGraph.add(producerTile); } Tile directConsumerTile = null;