Merged ItemGenerator, LiquidGenerator and ItemLiquidGenerator into a single class.

Unit tests now test the ItemsOnly, LiquidsOnly and LiquidsAndItems cases
This commit is contained in:
Timmeey86
2018-11-30 18:37:51 +01:00
parent 42cf80106f
commit 28f73d0a76
7 changed files with 222 additions and 298 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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;
}
}