diff --git a/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java b/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java index 6b47d31a67..db497f5043 100644 --- a/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java @@ -19,17 +19,17 @@ public class PowerBlocks extends BlockList implements ContentList{ thermalGenerator = new LiquidHeatGenerator("thermal-generator"){{ maxLiquidGenerate = 4f; - // TODO: Adapt to new power system - powerProduction = -1; - powerPerLiquid = 0.1f; + // TODO: Balance + powerProduction = 0.17f; + liquidPowerMultiplier = 0.1f; generateEffect = BlockFx.redgeneratespark; size = 2; }}; turbineGenerator = new TurbineGenerator("turbine-generator"){{ - // TODO: Adapt to new power system + // TODO: Balance powerProduction = 0.28f; - powerPerLiquid = 0.1f; + 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 07f16b8767..83031719d2 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java @@ -14,7 +14,7 @@ import static io.anuke.mindustry.Vars.tilesize; public abstract class ItemLiquidGenerator extends ItemGenerator{ protected float minLiquidEfficiency = 0.2f; - protected float powerPerLiquid = 0.13f; + 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; @@ -46,15 +46,16 @@ public abstract class ItemLiquidGenerator extends ItemGenerator{ } //liquid takes priority over solids + float calculationDelta = entity.delta(); if(liquid != null && entity.liquids.get(liquid) >= 0.001f && entity.cons.valid()){ - float powerPerLiquid = getLiquidEfficiency(liquid) * this.powerPerLiquid; - float used = Math.min(entity.liquids.get(liquid), maxLiquidGenerate * entity.delta()); - // TODO: Adapt to new power system - //used = Math.min(used, (powerCapacity - entity.power.amount) / powerPerLiquid); + float baseLiquidEfficiency = getLiquidEfficiency(liquid) * this.liquidPowerMultiplier; + float maximumPossible = maxLiquidGenerate * calculationDelta; + float used = Math.min(entity.liquids.get(liquid), maximumPossible); entity.liquids.remove(liquid, used); - // TODO: Adapt to new power system - //entity.power.amount += used * powerPerLiquid; + + // 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; 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/LiquidGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/LiquidGenerator.java index 0b19f94fc0..7314c56a0d 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/LiquidGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/LiquidGenerator.java @@ -13,7 +13,7 @@ import io.anuke.ucore.util.Mathf; public abstract class LiquidGenerator extends PowerGenerator{ protected float minEfficiency = 0.2f; - protected float powerPerLiquid; + protected float liquidPowerMultiplier; /**Maximum liquid used per frame.*/ protected float maxLiquidGenerate; protected Effect generateEffect = BlockFx.generatespark; @@ -50,8 +50,9 @@ public abstract class LiquidGenerator extends PowerGenerator{ public void update(Tile tile){ TileEntity entity = tile.entity(); + // TODO Code duplication with ItemLiquidGenerator if(entity.liquids.get(entity.liquids.current()) >= 0.001f){ - float powerPerLiquid = getEfficiency(entity.liquids.current()) * this.powerPerLiquid; + //float powerPerLiquid = getEfficiency(entity.liquids.current()) * this.powerPerLiquid; float used = Math.min(entity.liquids.currentAmount(), maxLiquidGenerate * entity.delta()); // TODO Adapt to new power system //used = Math.min(used, (powerCapacity - entity.power.amount) / powerPerLiquid); 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 8b5665b4c5..9129e884e9 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/LiquidHeatGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/LiquidHeatGenerator.java @@ -14,9 +14,9 @@ public class LiquidHeatGenerator extends LiquidGenerator{ public void setStats(){ super.setStats(); - // TODO Verify for new power system stats.remove(BlockStat.basePowerGeneration); - stats.add(BlockStat.basePowerGeneration, maxLiquidGenerate * powerPerLiquid * 60f, StatUnit.powerSecond); + // TODO Adapt to new new power system. Maybe this override can be removed. + //stats.add(BlockStat.basePowerGeneration, * 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 915ef48021..48d8bd0106 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java @@ -10,7 +10,7 @@ import io.anuke.mindustry.world.meta.BlockStat; public class PowerGenerator extends PowerDistributor{ /** The amount of power produced per tick. */ - public float powerProduction; + protected float powerProduction; public BlockStat generationType = BlockStat.basePowerGeneration; public PowerGenerator(String name){ diff --git a/tests/src/test/java/power/ItemLiquidGeneratorTests.java b/tests/src/test/java/power/ItemLiquidGeneratorTests.java index 930f257cd9..cf54743faf 100644 --- a/tests/src/test/java/power/ItemLiquidGeneratorTests.java +++ b/tests/src/test/java/power/ItemLiquidGeneratorTests.java @@ -1,37 +1,57 @@ package power; +import io.anuke.mindustry.content.Liquids; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.power.BurnerGenerator; +import io.anuke.mindustry.world.blocks.power.ItemGenerator; import io.anuke.mindustry.world.blocks.power.ItemLiquidGenerator; +import io.anuke.mindustry.world.blocks.power.PowerGenerator; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assumptions.assumeTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; + /** This class tests the abstract ItemLiquidGenerator class and maybe some of its dependencies. */ public class ItemLiquidGeneratorTests extends PowerTestFixture{ - private ItemLiquidGenerator sut; // system under test (https://en.wikipedia.org/wiki/System_under_test) + private ItemLiquidGenerator generator; private Tile tile; + private ItemGenerator.ItemGeneratorEntity entity; + private final float fakeLiquidPowerMultiplier = 2.0f; + private final float fakeMaxLiquidGenerate = 0.5f; @BeforeEach - public void createItemLiquidGenerator(){ - sut = new ItemLiquidGenerator("fakegen"){ - @Override - protected float getLiquidEfficiency(Liquid liquid){ - return liquid.flammability; - } + public void createBurnerGenerator(){ + // Use a burner generator instead of a custom ItemLiquidGenerator subclass since we would implement abstract methods the same way. + generator = new BurnerGenerator("fakegen"){{ + powerProduction = 0.1f; + itemDuration = 60f; + liquidPowerMultiplier = fakeLiquidPowerMultiplier; + maxLiquidGenerate = fakeMaxLiquidGenerate; + }}; - @Override - protected float getItemEfficiency(Item item){ - return item.flammability; - } - }; - tile = createFakeTile(0, 0, sut); + tile = createFakeTile(0, 0, generator); + entity = tile.entity(); } @Test - void detectCrashes(){ - sut.update(tile); + void testLiquidConsumption(){ + final float providedUsage = 0.1f; + final float expectedEfficiency = providedUsage / fakeMaxLiquidGenerate * fakeLiquidPowerMultiplier * Liquids.oil.flammability; + + entity.liquids.add(Liquids.oil, providedUsage); + entity.cons.update(tile.entity); + assumeTrue(entity.cons.valid()); + + // Perform an update on the generator once - This should use up all oil and produce a fraction of what's possible + generator.update(tile); + + assertEquals(0.0f, entity.liquids.get(Liquids.oil)); + assertEquals(expectedEfficiency, entity.productionEfficiency); } } diff --git a/tests/src/test/java/power/PowerTestFixture.java b/tests/src/test/java/power/PowerTestFixture.java index e2bc95ec4e..1588f54188 100644 --- a/tests/src/test/java/power/PowerTestFixture.java +++ b/tests/src/test/java/power/PowerTestFixture.java @@ -3,17 +3,25 @@ package power; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.core.ContentLoader; +import io.anuke.mindustry.core.World; +import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.PowerBlock; import io.anuke.mindustry.world.blocks.power.Battery; import io.anuke.mindustry.world.blocks.power.PowerGenerator; +import io.anuke.mindustry.world.modules.ConsumeModule; +import io.anuke.mindustry.world.modules.ItemModule; +import io.anuke.mindustry.world.modules.LiquidModule; import io.anuke.mindustry.world.modules.PowerModule; +import io.anuke.ucore.entities.Entities; import org.junit.jupiter.api.BeforeAll; import java.lang.reflect.Field; import java.lang.reflect.Method; +import static io.anuke.mindustry.Vars.world; + /** This class provides objects commonly used by power related unit tests. * For now, this is a helper with static methods, but this might change. * */ @@ -62,7 +70,7 @@ public class PowerTestFixture{ // Using the Tile(int, int, byte, byte) constructor would require us to register any fake block or tile we create // Since this part shall not be part of the test and would require more work anyway, we manually set the block and floor - // and call the private changed() method through reflections. + // through reflections and then simulate part of what the changed() method does. Field field = Tile.class.getDeclaredField("wall"); field.setAccessible(true); @@ -72,10 +80,15 @@ public class PowerTestFixture{ field.setAccessible(true); field.set(tile, Blocks.sand); - Method method = Tile.class.getDeclaredMethod("changed"); - method.setAccessible(true); - method.invoke(tile); - + // Simulate the "changed" method. Calling it through reflections would require half the game to be initialized. + tile.entity = block.newEntity().init(tile, false); + tile.entity.cons = new ConsumeModule(); + if(block.hasItems) tile.entity.items = new ItemModule(); + if(block.hasLiquids) tile.entity.liquids = new LiquidModule(); + if(block.hasPower){ + tile.entity.power = new PowerModule(); + tile.entity.power.graph.add(tile); + } return tile; }catch(Exception ex){ return null;