From 28f73d0a76f70fa27824092e8b4ab4818905c12e Mon Sep 17 00:00:00 2001 From: Timmeey86 Date: Fri, 30 Nov 2018 18:37:51 +0100 Subject: [PATCH] Merged ItemGenerator, LiquidGenerator and ItemLiquidGenerator into a single class. Unit tests now test the ItemsOnly, LiquidsOnly and LiquidsAndItems cases --- .../world/blocks/power/BurnerGenerator.java | 2 +- .../world/blocks/power/DecayGenerator.java | 5 +- .../world/blocks/power/ItemGenerator.java | 117 ------------- .../blocks/power/ItemLiquidGenerator.java | 165 ++++++++++++++---- .../world/blocks/power/LiquidGenerator.java | 91 ---------- .../blocks/power/LiquidHeatGenerator.java | 7 +- .../java/power/ItemLiquidGeneratorTests.java | 133 ++++++++------ 7 files changed, 222 insertions(+), 298 deletions(-) delete mode 100644 core/src/io/anuke/mindustry/world/blocks/power/ItemGenerator.java delete mode 100644 core/src/io/anuke/mindustry/world/blocks/power/LiquidGenerator.java diff --git a/core/src/io/anuke/mindustry/world/blocks/power/BurnerGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/BurnerGenerator.java index 91051e8a85..0441f2a876 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/BurnerGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/BurnerGenerator.java @@ -6,7 +6,7 @@ import io.anuke.mindustry.type.Liquid; public class BurnerGenerator extends ItemLiquidGenerator{ public BurnerGenerator(String name){ - super(name); + super(InputType.LiquidsAndItems, name); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/power/DecayGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/DecayGenerator.java index 225efd98c5..678da93587 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/DecayGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/DecayGenerator.java @@ -1,11 +1,12 @@ package io.anuke.mindustry.world.blocks.power; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Liquid; -public class DecayGenerator extends ItemGenerator{ +public class DecayGenerator extends ItemLiquidGenerator{ public DecayGenerator(String name){ - super(name); + super(InputType.ItemsOnly, name); hasItems = true; hasLiquids = false; } diff --git a/core/src/io/anuke/mindustry/world/blocks/power/ItemGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/ItemGenerator.java deleted file mode 100644 index b18092c111..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/power/ItemGenerator.java +++ /dev/null @@ -1,117 +0,0 @@ -package io.anuke.mindustry.world.blocks.power; - -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import io.anuke.mindustry.content.fx.BlockFx; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.world.BarType; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.consumers.ConsumeItemFilter; -import io.anuke.mindustry.world.meta.BlockBar; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.util.Mathf; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import static io.anuke.mindustry.Vars.tilesize; - -public abstract class ItemGenerator extends PowerGenerator{ - protected float minItemEfficiency = 0.2f; - protected float itemDuration = 70f; - protected Effect generateEffect = BlockFx.generatespark, explodeEffect = - BlockFx.generatespark; - protected Color heatColor = Color.valueOf("ff9b59"); - protected TextureRegion topRegion; - - public ItemGenerator(String name){ - super(name); - itemCapacity = 20; - hasItems = true; - - consumes.add(new ConsumeItemFilter(item -> getItemEfficiency(item) >= minItemEfficiency)).update(false).optional(true); - } - - @Override - public void load(){ - super.load(); - topRegion = Draw.region(name + "-top"); - } - - @Override - public void setBars(){ - super.setBars(); - bars.replace(new BlockBar(BarType.inventory, true, tile -> (float) tile.entity.items.total() / itemCapacity)); - } - - @Override - public void draw(Tile tile){ - super.draw(tile); - - GeneratorEntity entity = tile.entity(); - - if(entity.generateTime > 0){ - Draw.color(heatColor); - float alpha = (entity.items.total() > 0 ? 1f : Mathf.clamp(entity.generateTime)); - alpha = alpha * 0.7f + Mathf.absin(Timers.time(), 12f, 0.3f) * alpha; - Draw.alpha(alpha); - Draw.rect(topRegion, tile.drawx(), tile.drawy()); - Draw.reset(); - } - } - - @Override - public boolean acceptItem(Item item, Tile tile, Tile source){ - return getItemEfficiency(item) >= minItemEfficiency && tile.entity.items.total() < itemCapacity; - } - - @Override - public void update(Tile tile){ - ItemGeneratorEntity entity = tile.entity(); - - if(!entity.cons.valid()){ - entity.productionEfficiency = 0.0f; - return; - } - - if(entity.generateTime <= 0f && entity.items.total() > 0){ - Effects.effect(generateEffect, tile.worldx() + Mathf.range(3f), tile.worldy() + Mathf.range(3f)); - Item item = entity.items.take(); - entity.productionEfficiency = getItemEfficiency(item); - entity.explosiveness = item.explosiveness; - entity.generateTime = 1f; - } - - if(entity.generateTime > 0f){ - entity.generateTime -= Math.min(1f / itemDuration * entity.delta(), entity.generateTime); - - 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 - entity.damage(Mathf.random(8f)); - Effects.effect(explodeEffect, tile.worldx() + Mathf.range(size * tilesize / 2f), tile.worldy() + Mathf.range(size * tilesize / 2f)); - } - }else{ - entity.productionEfficiency = 0.0f; - } - - super.update(tile); - } - - protected abstract float getItemEfficiency(Item item); - - @Override - public TileEntity newEntity(){ - return new ItemGeneratorEntity(); - } - - public static class ItemGeneratorEntity extends GeneratorEntity{ - public float explosiveness; - } -} 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 c8af36a3ff..7fbc233533 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java @@ -1,47 +1,86 @@ package io.anuke.mindustry.world.blocks.power; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import io.anuke.mindustry.content.fx.BlockFx; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; +import io.anuke.mindustry.world.BarType; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.consumers.ConsumeItemFilter; import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter; +import io.anuke.mindustry.world.meta.BlockBar; import io.anuke.ucore.core.Effects; +import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Mathf; import static io.anuke.mindustry.Vars.content; import static io.anuke.mindustry.Vars.tilesize; -public abstract class ItemLiquidGenerator extends ItemGenerator{ +/** + * Power generation block which can use items, liquids or both as input sources for power production. + * Liquids will take priority over items. + */ +public class ItemLiquidGenerator extends PowerGenerator{ + + protected float minItemEfficiency = 0.2f; + /** The time in number of ticks during which a single item will produce power. */ + 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.*/ + /** Maximum liquid used per frame. */ protected float maxLiquidGenerate = 0.4f; - public ItemLiquidGenerator(String name){ - super(name); - hasLiquids = true; - liquidCapacity = 10f; + protected Effects.Effect generateEffect = BlockFx.generatespark; + protected Effects.Effect explodeEffect = BlockFx.generatespark; + protected Color heatColor = Color.valueOf("ff9b59"); + protected TextureRegion topRegion; - consumes.add(new ConsumeLiquidFilter(liquid -> getLiquidEfficiency(liquid) >= minLiquidEfficiency, 0.001f, true)).update(false).optional(true); + public enum InputType{ + ItemsOnly, + LiquidsOnly, + LiquidsAndItems + } + + public ItemLiquidGenerator(InputType inputType, String name){ + super(name); + this.hasItems = inputType != InputType.LiquidsOnly; + this.hasLiquids = inputType != InputType.ItemsOnly; + + if(hasItems){ + itemCapacity = 20; + consumes.add(new ConsumeItemFilter(item -> getItemEfficiency(item) >= minItemEfficiency)).update(false).optional(true); + } + + if(hasLiquids){ + liquidCapacity = 10f; + consumes.add(new ConsumeLiquidFilter(liquid -> getLiquidEfficiency(liquid) >= minLiquidEfficiency, 0.001f, true)).update(false).optional(true); + } } @Override - public void init(){ - super.init(); + public void load(){ + super.load(); + if(hasItems){ + topRegion = Draw.region(name + "-top"); + } } + @Override + public void setBars(){ + super.setBars(); + if(hasItems){ + bars.replace(new BlockBar(BarType.inventory, true, tile -> (float) tile.entity.items.total() / itemCapacity)); + } + } + + @Override public void update(Tile tile){ - ItemGeneratorEntity entity = tile.entity(); - - Liquid liquid = null; - for(Liquid other : content.liquids()){ - if(entity.liquids.get(other) >= 0.001f && getLiquidEfficiency(other) >= minLiquidEfficiency){ - liquid = other; - break; - } - } + ItemLiquidGeneratorEntity entity = tile.entity(); // Note: Do not use this delta when calculating the amount of power or the power efficiency, but use it for resource consumption if necessary. // Power amount is delta'd by PowerGraph class already. @@ -51,8 +90,16 @@ public abstract class ItemLiquidGenerator extends ItemGenerator{ entity.productionEfficiency = 0.0f; return; } + + Liquid liquid = null; + for(Liquid other : content.liquids()){ + if(hasLiquids && entity.liquids.get(other) >= 0.001f && getLiquidEfficiency(other) >= minLiquidEfficiency){ + liquid = other; + break; + } + } //liquid takes priority over solids - if(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 maximumPossible = maxLiquidGenerate * calculationDelta; float used = Math.min(entity.liquids.get(liquid) * calculationDelta, maximumPossible); @@ -65,35 +112,85 @@ public abstract class ItemLiquidGenerator extends ItemGenerator{ if(used > 0.001f && Mathf.chance(0.05 * entity.delta())){ Effects.effect(generateEffect, tile.drawx() + Mathf.range(3f), tile.drawy() + Mathf.range(3f)); } + }else if(hasItems){ + // No liquids accepted or none supplied, try using items if accepted + if(entity.generateTime <= 0f && entity.items.total() > 0){ + Effects.effect(generateEffect, tile.worldx() + Mathf.range(3f), tile.worldy() + Mathf.range(3f)); + Item item = entity.items.take(); + entity.productionEfficiency = getItemEfficiency(item); + entity.explosiveness = item.explosiveness; + entity.generateTime = 1f; + } - // Update the graph manually instead of letting the base class do it since that would consume items - entity.power.graph.update(); - }else{ - // No liquids accepted, act like a default ItemGenerator - super.update(tile); + if(entity.generateTime > 0f){ + entity.generateTime -= Math.min(1f / itemDuration * entity.delta(), entity.generateTime); + + 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 + entity.damage(Mathf.random(8f)); + Effects.effect(explodeEffect, tile.worldx() + Mathf.range(size * tilesize / 2f), tile.worldy() + Mathf.range(size * tilesize / 2f)); + } + }else{ + entity.productionEfficiency = 0.0f; + } } + + super.update(tile); + } + + @Override + public boolean acceptItem(Item item, Tile tile, Tile source){ + return hasItems && getItemEfficiency(item) >= minItemEfficiency && tile.entity.items.total() < itemCapacity; + } + + @Override + public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ + return hasLiquids && getLiquidEfficiency(liquid) >= minLiquidEfficiency && tile.entity.liquids.get(liquid) < liquidCapacity; } @Override public void draw(Tile tile){ super.draw(tile); - TileEntity entity = tile.entity(); + GeneratorEntity entity = tile.entity(); - Draw.color(entity.liquids.current().color); - Draw.alpha(entity.liquids.currentAmount() / liquidCapacity); - drawLiquidCenter(tile); - Draw.color(); - } + if(hasItems){ + if(entity.generateTime > 0){ + Draw.color(heatColor); + float alpha = (entity.items.total() > 0 ? 1f : Mathf.clamp(entity.generateTime)); + alpha = alpha * 0.7f + Mathf.absin(Timers.time(), 12f, 0.3f) * alpha; + Draw.alpha(alpha); + Draw.rect(topRegion, tile.drawx(), tile.drawy()); + Draw.reset(); + } + } - @Override - public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ - return getLiquidEfficiency(liquid) >= minLiquidEfficiency && tile.entity.liquids.get(liquid) < liquidCapacity; + if(hasLiquids){ + Draw.color(entity.liquids.current().color); + Draw.alpha(entity.liquids.currentAmount() / liquidCapacity); + drawLiquidCenter(tile); + Draw.color(); + } } public void drawLiquidCenter(Tile tile){ Draw.rect("blank", tile.drawx(), tile.drawy(), 2, 2); } - protected abstract float getLiquidEfficiency(Liquid liquid); + protected float getItemEfficiency(Item item){ + return 0.0f; + } + + protected float getLiquidEfficiency(Liquid liquid){ + return 0.0f; + } + + @Override + public TileEntity newEntity(){ + return new ItemLiquidGeneratorEntity(); + } + + public static class ItemLiquidGeneratorEntity extends GeneratorEntity{ + public float explosiveness; + } } diff --git a/core/src/io/anuke/mindustry/world/blocks/power/LiquidGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/LiquidGenerator.java deleted file mode 100644 index 67701ec58d..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/power/LiquidGenerator.java +++ /dev/null @@ -1,91 +0,0 @@ -package io.anuke.mindustry.world.blocks.power; - -import io.anuke.mindustry.content.fx.BlockFx; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.power.ItemGenerator.ItemGeneratorEntity; -import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.util.Mathf; - -public abstract class LiquidGenerator extends PowerGenerator{ - protected float minEfficiency = 0.2f; - protected float liquidPowerMultiplier; - /**Maximum liquid used per frame.*/ - protected float maxLiquidGenerate; - protected Effect generateEffect = BlockFx.generatespark; - - public LiquidGenerator(String name){ - super(name); - liquidCapacity = 30f; - hasLiquids = true; - } - - @Override - public void setStats(){ - consumes.add(new ConsumeLiquidFilter(liquid -> getEfficiency(liquid) >= minEfficiency, maxLiquidGenerate)).update(false); - super.setStats(); - } - - @Override - public void draw(Tile tile){ - super.draw(tile); - - TileEntity entity = tile.entity(); - - Draw.color(entity.liquids.current().color); - Draw.alpha(entity.liquids.total() / liquidCapacity); - drawLiquidCenter(tile); - Draw.color(); - } - - public void drawLiquidCenter(Tile tile){ - Draw.rect("blank", tile.drawx(), tile.drawy(), 2, 2); - } - - @Override - public void update(Tile tile){ - ItemGeneratorEntity entity = tile.entity(); - - // Note: Do not use this delta when calculating the amount of power or the power efficiency, but use it for resource consumption if necessary. - // Power amount is delta'd by PowerGraph class already. - float calculationDelta = entity.delta(); - - if(entity.liquids.get(entity.liquids.current()) >= 0.001f){ - float baseLiquidEfficiency = getEfficiency(entity.liquids.current()) * this.liquidPowerMultiplier; - float maximumPossible = maxLiquidGenerate * calculationDelta; - float used = Math.min(entity.liquids.currentAmount() * calculationDelta, maximumPossible); - - entity.liquids.remove(entity.liquids.current(), 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; - - if(used > 0.001f && Mathf.chance(0.05 * entity.delta())){ - Effects.effect(generateEffect, tile.drawx() + Mathf.range(3f), tile.drawy() + Mathf.range(3f)); - } - } - - super.update(tile); - } - - @Override - public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ - return getEfficiency(liquid) >= minEfficiency && super.acceptLiquid(tile, source, liquid, amount); - } - - @Override - public TileEntity newEntity(){ - return new ItemGeneratorEntity(); - } - - /** - * Returns an efficiency value for the specified liquid. - * Greater efficiency means more power generation. - * If a liquid's efficiency is below {@link #minEfficiency}, it is not accepted. - */ - protected abstract float getEfficiency(Liquid liquid); -} 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 9129e884e9..c1d95d9ff1 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/LiquidHeatGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/LiquidHeatGenerator.java @@ -1,13 +1,14 @@ package io.anuke.mindustry.world.blocks.power; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.StatUnit; -public class LiquidHeatGenerator extends LiquidGenerator{ +public class LiquidHeatGenerator extends ItemLiquidGenerator{ public LiquidHeatGenerator(String name){ - super(name); + super(InputType.LiquidsOnly, name); } @Override @@ -20,7 +21,7 @@ public class LiquidHeatGenerator extends LiquidGenerator{ } @Override - protected float getEfficiency(Liquid liquid){ + protected float getLiquidEfficiency(Liquid liquid){ return liquid.temperature - 0.5f; } } diff --git a/tests/src/test/java/power/ItemLiquidGeneratorTests.java b/tests/src/test/java/power/ItemLiquidGeneratorTests.java index aae193543d..8a2fa7ff18 100644 --- a/tests/src/test/java/power/ItemLiquidGeneratorTests.java +++ b/tests/src/test/java/power/ItemLiquidGeneratorTests.java @@ -1,48 +1,55 @@ package power; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Items; 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 org.junit.jupiter.api.*; +import java.util.ArrayList; + import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.DynamicTest.dynamicTest; /** - * This class tests ItemLiquidGenerators. Currently, testing is only performed on the BurnerGenerator subclass, - * which means only power calculations based on flammability are tested. + * This class tests generators which can process items, liquids or both. * All tests are run with a fixed delta of 0.5 so delta considerations can be tested as well. * Additionally, each PowerGraph::update() call will have its own thread frame, i.e. the method will never be called twice within the same frame. * Both of these constraints are handled by FakeThreadHandler within PowerTestFixture. - * Any power amount (produced, consumed, buffered) should be affected by FakeThreadHandler.fakeDelta but satisfaction should not! - * TODO Find a way to reuse these tests for LiquidGenerator and ItemGenerator + * Any expected power amount (produced, consumed, buffered) should be affected by FakeThreadHandler.fakeDelta but satisfaction should not! */ public class ItemLiquidGeneratorTests extends PowerTestFixture{ private ItemLiquidGenerator generator; private Tile tile; - private ItemGenerator.ItemGeneratorEntity entity; + private ItemLiquidGenerator.ItemLiquidGeneratorEntity entity; private final float fakeLiquidPowerMultiplier = 2.0f; private final float fakeItemDuration = 60f; // 60 ticks private final float maximumLiquidUsage = 0.5f; - @BeforeEach - 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; - itemDuration = fakeItemDuration; - maxLiquidGenerate = maximumLiquidUsage; - }}; + public void createGenerator(ItemLiquidGenerator.InputType inputType){ + generator = new ItemLiquidGenerator(inputType, "fakegen"){ + { + powerProduction = 0.1f; + itemDuration = 60f; + liquidPowerMultiplier = fakeLiquidPowerMultiplier; + itemDuration = fakeItemDuration; + maxLiquidGenerate = maximumLiquidUsage; + } + + @Override + public float getItemEfficiency(Item item){ + return item.flammability; + } + + @Override + public float getLiquidEfficiency(Liquid liquid){ + return liquid.flammability; + } + }; tile = createFakeTile(0, 0, generator); entity = tile.entity(); @@ -51,27 +58,35 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ /** Tests the consumption and efficiency when being supplied with liquids. */ @TestFactory DynamicTest[] generatorWorksProperlyWithLiquidInput(){ - return new DynamicTest[]{ - dynamicTest("01", () -> simulateLiquidConsumption(Liquids.oil, 0.0f, "No liquids provided")), - dynamicTest("02", () -> simulateLiquidConsumption(Liquids.oil, maximumLiquidUsage / 4.0f, "Low oil provided")), - dynamicTest("03", () -> simulateLiquidConsumption(Liquids.oil, maximumLiquidUsage * 1.0f, "Sufficient oil provided")), - dynamicTest("04", () -> simulateLiquidConsumption(Liquids.oil, maximumLiquidUsage * 2.0f, "Excess oil provided")) - // Note: The generator will decline any other liquid since it's not flammable + + // Execute all tests for the case where only liquids are accepted and for the case where liquids and items are accepted (but supply only liquids) + ItemLiquidGenerator.InputType[] inputTypesToBeTested = new ItemLiquidGenerator.InputType[]{ + ItemLiquidGenerator.InputType.LiquidsOnly, + ItemLiquidGenerator.InputType.LiquidsAndItems }; + + ArrayList tests = new ArrayList<>(); + for(ItemLiquidGenerator.InputType inputType : inputTypesToBeTested){ + tests.add(dynamicTest("01", () -> simulateLiquidConsumption(inputType, Liquids.oil, 0.0f, "No liquids provided"))); + tests.add(dynamicTest("02", () -> simulateLiquidConsumption(inputType, Liquids.oil, maximumLiquidUsage / 4.0f, "Low oil provided"))); + tests.add(dynamicTest("03", () -> simulateLiquidConsumption(inputType, Liquids.oil, maximumLiquidUsage * 1.0f, "Sufficient oil provided"))); + tests.add(dynamicTest("04", () -> simulateLiquidConsumption(inputType, Liquids.oil, maximumLiquidUsage * 2.0f, "Excess oil provided"))); + // Note: The generator will decline any other liquid since it's not flammable + } + DynamicTest[] testArray = new DynamicTest[tests.size()]; + testArray = tests.toArray(testArray); + return testArray; } - void simulateLiquidConsumption(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 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); - assertTrue(generator.acceptLiquid(tile, null, liquid, availableLiquidAmount), parameterDescription + ": Liquids which will be declined by the generator don't need to be tested - The code won't be called for those cases."); + createGenerator(inputType); + assertTrue(generator.acceptLiquid(tile, null, liquid, availableLiquidAmount), inputType + " | " + parameterDescription + ": Liquids which will be declined by the generator don't need to be tested - The code won't be called for those cases."); - // Reset liquids since BeforeEach will not be called between dynamic tests - for(Liquid tmpLiquid : Vars.content.liquids()){ - entity.liquids.reset(tmpLiquid, 0.0f); - } entity.liquids.add(liquid, availableLiquidAmount); entity.cons.update(tile.entity); assertTrue(entity.cons.valid()); @@ -79,34 +94,41 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ // Perform an update on the generator once - This should use up any resource up to the maximum liquid usage generator.update(tile); - assertEquals(expectedRemainingLiquidAmount, entity.liquids.get(liquid), parameterDescription + ": Remaining liquid amount mismatch."); - assertEquals(expectedEfficiency, entity.productionEfficiency, parameterDescription + ": Efficiency mismatch."); + assertEquals(expectedRemainingLiquidAmount, entity.liquids.get(liquid), inputType + " | " + parameterDescription + ": Remaining liquid amount mismatch."); + assertEquals(expectedEfficiency, entity.productionEfficiency, inputType + " | " + parameterDescription + ": Efficiency mismatch."); } /** Tests the consumption and efficiency when being supplied with items. */ @TestFactory DynamicTest[] generatorWorksProperlyWithItemInput(){ - return new DynamicTest[]{ - dynamicTest("01", () -> simulateItemConsumption(Items.coal, 0, "No items provided")), - dynamicTest("02", () -> simulateItemConsumption(Items.coal, 1, "Sufficient coal provided")), - dynamicTest("03", () -> simulateItemConsumption(Items.coal, 10, "Excess coal provided")), - dynamicTest("04", () -> simulateItemConsumption(Items.blastCompound, 1, "Blast compound provided")), - //dynamicTest("03", () -> simulateItemConsumption(Items.plastanium, 1, "Plastanium provided")), // Not accepted by generator due to low flammability - dynamicTest("05", () -> simulateItemConsumption(Items.biomatter, 1, "Biomatter provided")), - dynamicTest("06", () -> simulateItemConsumption(Items.pyratite, 1, "Pyratite provided")) + + // Execute all tests for the case where only items are accepted and for the case where liquids and items are accepted (but supply only items) + ItemLiquidGenerator.InputType[] inputTypesToBeTested = new ItemLiquidGenerator.InputType[]{ + ItemLiquidGenerator.InputType.ItemsOnly, + ItemLiquidGenerator.InputType.LiquidsAndItems }; + + ArrayList tests = new ArrayList<>(); + for(ItemLiquidGenerator.InputType inputType : inputTypesToBeTested){ + tests.add(dynamicTest("01", () -> simulateItemConsumption(inputType, Items.coal, 0, "No items provided"))); + tests.add(dynamicTest("02", () -> simulateItemConsumption(inputType, Items.coal, 1, "Sufficient coal provided"))); + tests.add(dynamicTest("03", () -> simulateItemConsumption(inputType, Items.coal, 10, "Excess coal provided"))); + tests.add(dynamicTest("04", () -> simulateItemConsumption(inputType, Items.blastCompound, 1, "Blast compound provided"))); + //dynamicTest("03", () -> simulateItemConsumption(inputType, Items.plastanium, 1, "Plastanium provided")), // Not accepted by generator due to low flammability + tests.add(dynamicTest("05", () -> simulateItemConsumption(inputType, Items.biomatter, 1, "Biomatter provided"))); + tests.add(dynamicTest("06", () -> simulateItemConsumption(inputType, Items.pyratite, 1, "Pyratite provided"))); + } + DynamicTest[] testArray = new DynamicTest[tests.size()]; + testArray = tests.toArray(testArray); + return testArray; } - void simulateItemConsumption(Item item, int amount, String parameterDescription){ + void simulateItemConsumption(ItemLiquidGenerator.InputType inputType, Item item, int amount, String parameterDescription){ final float expectedEfficiency = Math.min(1.0f, amount > 0 ? item.flammability : 0f); final float expectedRemainingItemAmount = Math.max(0, amount - 1); - assertTrue(generator.acceptItem(item, tile, null), parameterDescription + ": Items which will be declined by the generator don't need to be tested - The code won't be called for those cases."); - - // Clean up manually since BeforeEach will not be called between dynamic tests - entity.items.clear(); - entity.generateTime = 0.0f; - entity.productionEfficiency = 0.0f; + createGenerator(inputType); + assertTrue(generator.acceptItem(item, tile, null), inputType + " | " + parameterDescription + ": Items which will be declined by the generator don't need to be tested - The code won't be called for those cases."); if(amount > 0){ entity.items.add(item, amount); @@ -117,13 +139,24 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ // Perform an update on the generator once - This should use up one or zero items - dependent on if the item is accepted and available or not. generator.update(tile); - assertEquals(expectedRemainingItemAmount, entity.items.get(item), parameterDescription + ": Remaining item amount mismatch."); - assertEquals(expectedEfficiency, entity.productionEfficiency, parameterDescription + ": Efficiency mismatch."); + assertEquals(expectedRemainingItemAmount, entity.items.get(item), inputType + " | " + parameterDescription + ": Remaining item amount mismatch."); + assertEquals(expectedEfficiency, entity.productionEfficiency, inputType + " | " + parameterDescription + ": Efficiency mismatch."); } /** Makes sure the efficiency stays equal during the item duration. */ @Test - void efficiencyRemainsConstantWithinItemDuration(){ + void efficiencyRemainsConstantWithinItemDuration_ItemsOnly(){ + testItemDuration(ItemLiquidGenerator.InputType.ItemsOnly); + } + + /** Makes sure the efficiency stays equal during the item duration. */ + @Test + void efficiencyRemainsConstantWithinItemDuration_ItemsAndLiquids(){ + testItemDuration(ItemLiquidGenerator.InputType.LiquidsAndItems); + } + + void testItemDuration(ItemLiquidGenerator.InputType inputType){ + createGenerator(inputType); // Burn a single coal and test for the duration entity.items.add(Items.coal, 1);