diff --git a/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java b/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java index b17493349a..8c07c31580 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java @@ -80,9 +80,15 @@ public class PowerGraph{ if(MathUtils.isEqual(stored, 0f)){ return 0f; } float used = Math.min(stored, needed); - float percentageRemaining = 1f - (used / stored); + float consumedPowerPercentage = Math.min(1.0f, needed / stored); for(Tile battery : batteries){ - battery.entity.power.satisfaction *= percentageRemaining; + Consumers consumes = battery.block().consumes; + if(consumes.has(ConsumePower.class)){ + ConsumePower consumePower = consumes.get(ConsumePower.class); + if(consumePower.powerCapacity > 0f){ + battery.entity.power.satisfaction = Math.max(0.0f, battery.entity.power.satisfaction - consumedPowerPercentage); + } + } } return used; } @@ -91,9 +97,15 @@ public class PowerGraph{ float capacity = getBatteryCapacity(); if(MathUtils.isEqual(capacity, 0f)){ return 0f; } - float thing = Math.min(1, excess / capacity); for(Tile battery : batteries){ - battery.entity.power.satisfaction += (1 - battery.entity.power.satisfaction) * thing; + Consumers consumes = battery.block().consumes; + if(consumes.has(ConsumePower.class)){ + ConsumePower consumePower = consumes.get(ConsumePower.class); + if(consumePower.powerCapacity > 0f){ + float additionalPowerPercentage = Math.min(1.0f, excess / consumePower.powerCapacity); + battery.entity.power.satisfaction = Math.min(1.0f, battery.entity.power.satisfaction + additionalPowerPercentage); + } + } } return Math.min(excess, capacity); } diff --git a/tests/src/test/java/PowerTests.java b/tests/src/test/java/PowerTests.java index 096e2d126a..6d6655a5b1 100644 --- a/tests/src/test/java/PowerTests.java +++ b/tests/src/test/java/PowerTests.java @@ -101,5 +101,38 @@ public class PowerTests extends PowerTestFixture{ powerGraph.update(); assertEquals(expectedSatisfaction, bufferedConsumerTile.entity.power.satisfaction, MathUtils.FLOAT_ROUNDING_ERROR, parameterDescription + ": Satisfaction of buffered consumer did not match"); } + + /** Tests the satisfaction of a single direct consumer after a single update of the power graph which contains a single producer and a single battery. + * The used battery is created with a maximum capacity of 100 and receives ten power per tick. + */ + @TestFactory + DynamicTest[] testDirectConsumptionWithBattery(){ + return new DynamicTest[]{ + dynamicTest("1", () -> test_directConsumptionWithBattery(10.0f, 0.0f, 0.0f, 10.0f, 0.0f, "Empty battery, no consumer")), + dynamicTest("2", () -> test_directConsumptionWithBattery(10.0f, 0.0f, 90.0f, 100.0f, 0.0f, "Battery full after update, no consumer")), + dynamicTest("3", () -> test_directConsumptionWithBattery(10.0f, 0.0f, 100.0f, 100.0f, 0.0f, "Full battery, no consumer")), + dynamicTest("4", () -> test_directConsumptionWithBattery(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, "No producer, no consumer, empty battery")), + dynamicTest("5", () -> test_directConsumptionWithBattery(0.0f, 0.0f, 100.0f, 100.0f, 0.0f, "No producer, no consumer, full battery")), + dynamicTest("6", () -> test_directConsumptionWithBattery(0.0f, 10.0f, 0.0f, 0.0f, 0.0f, "No producer, empty battery")), + dynamicTest("7", () -> test_directConsumptionWithBattery(0.0f, 10.0f, 100.0f, 90.0f, 1.0f, "No producer, full battery")), + dynamicTest("8", () -> test_directConsumptionWithBattery(0.0f, 10.0f, 5.0f, 0.0f, 0.5f, "No producer, low battery")) + }; + } + void test_directConsumptionWithBattery(float producedPower, float requestedPower, float initialBatteryCapacity, float expectedBatteryCapacity, float expectedSatisfaction, String parameterDescription){ + Tile producerTile = createFakeTile(0, 0, createFakeProducerBlock(producedPower)); + Tile directConsumerTile = createFakeTile(0, 1, createFakeDirectConsumer(requestedPower, 0.6f)); + float maxCapacity = 100f; + Tile batteryTile = createFakeTile(0, 2, createFakeBattery(maxCapacity, 10 )); + batteryTile.entity.power.satisfaction = initialBatteryCapacity / maxCapacity; + + PowerGraph powerGraph = new PowerGraph(); + powerGraph.add(producerTile); + powerGraph.add(directConsumerTile); + powerGraph.add(batteryTile); + + powerGraph.update(); + assertEquals(expectedBatteryCapacity, batteryTile.entity.power.satisfaction * maxCapacity, MathUtils.FLOAT_ROUNDING_ERROR, parameterDescription + ": Expected battery capacity did not match"); + assertEquals(expectedSatisfaction, directConsumerTile.entity.power.satisfaction, MathUtils.FLOAT_ROUNDING_ERROR, parameterDescription + ": Satisfaction of direct consumer did not match"); + } } }