it is done

This commit is contained in:
Anuken
2019-12-25 01:39:38 -05:00
parent 5b21873f3c
commit 514d4817c8
488 changed files with 4572 additions and 4574 deletions

View File

@@ -0,0 +1,76 @@
package mindustry.world.consumers;
import arc.struct.*;
import arc.scene.ui.layout.Table;
import mindustry.entities.type.TileEntity;
import mindustry.world.Tile;
import mindustry.world.meta.BlockStats;
/** An abstract class that defines a type of resource that a block can consume. */
public abstract class Consume{
/** If true, this consumer will not influence consumer validity. */
protected boolean optional;
/** If true, this consumer will be displayed as a boost input. */
protected boolean booster;
protected boolean update = true;
/**
* Apply a filter to items accepted.
* This should set all item IDs that are present in the filter to true.
*/
public void applyItemFilter(Bits filter){
}
/**
* Apply a filter to liquids accepted.
* This should set all liquid IDs that are present in the filter to true.
*/
public void applyLiquidFilter(Bits filter){
}
public Consume optional(boolean optional, boolean boost){
this.optional = optional;
this.booster = boost;
return this;
}
public Consume boost(){
return optional(true, true);
}
public Consume update(boolean update){
this.update = update;
return this;
}
public boolean isOptional(){
return optional;
}
public boolean isBoost(){
return booster;
}
public boolean isUpdate(){
return update;
}
public abstract ConsumeType type();
public abstract void build(Tile tile, Table table);
/** Called when a consumption is triggered manually. */
public void trigger(TileEntity entity){
}
public abstract String getIcon();
public abstract void update(TileEntity entity);
public abstract boolean valid(TileEntity entity);
public abstract void display(BlockStats stats);
}

View File

@@ -0,0 +1,79 @@
package mindustry.world.consumers;
import arc.struct.*;
import arc.func.*;
import arc.scene.ui.layout.*;
import arc.util.ArcAnnotate.*;
import mindustry.entities.type.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.ui.Cicon;
import mindustry.world.*;
import mindustry.world.meta.*;
import mindustry.world.meta.values.*;
import static mindustry.Vars.*;
public class ConsumeItemFilter extends Consume{
public final @NonNull
Boolf<Item> filter;
public ConsumeItemFilter(Boolf<Item> item){
this.filter = item;
}
@Override
public void applyItemFilter(Bits arr){
content.items().each(filter, item -> arr.set(item.id));
}
@Override
public ConsumeType type(){
return ConsumeType.item;
}
@Override
public void build(Tile tile, Table table){
MultiReqImage image = new MultiReqImage();
content.items().each(i -> filter.get(i) && (!world.isZone() || data.isUnlocked(i)), item -> image.add(new ReqImage(new ItemImage(item.icon(Cicon.medium), 1), () -> tile.entity != null && tile.entity.items != null && tile.entity.items.has(item))));
table.add(image).size(8 * 4);
}
@Override
public String getIcon(){
return "icon-item";
}
@Override
public void update(TileEntity entity){
}
@Override
public void trigger(TileEntity entity){
for(int i = 0; i < content.items().size; i++){
Item item = content.item(i);
if(entity.items != null && entity.items.has(item) && this.filter.get(item)){
entity.items.remove(item, 1);
break;
}
}
}
@Override
public boolean valid(TileEntity entity){
for(int i = 0; i < content.items().size; i++){
Item item = content.item(i);
if(entity.items != null && entity.items.has(item) && this.filter.get(item)){
return true;
}
}
return false;
}
@Override
public void display(BlockStats stats){
stats.add(booster ? BlockStat.booster : BlockStat.input, new ItemFilterValue(filter));
}
}

View File

@@ -0,0 +1,71 @@
package mindustry.world.consumers;
import arc.struct.*;
import arc.scene.ui.layout.*;
import arc.util.ArcAnnotate.*;
import mindustry.entities.type.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.ui.Cicon;
import mindustry.world.*;
import mindustry.world.meta.*;
import mindustry.world.meta.values.*;
public class ConsumeItems extends Consume{
public final @NonNull ItemStack[] items;
public ConsumeItems(ItemStack[] items){
this.items = items;
}
/** Mods.*/
protected ConsumeItems(){
this(new ItemStack[]{});
}
@Override
public void applyItemFilter(Bits filter){
for(ItemStack stack : items){
filter.set(stack.item.id);
}
}
@Override
public ConsumeType type(){
return ConsumeType.item;
}
@Override
public void build(Tile tile, Table table){
for(ItemStack stack : items){
table.add(new ReqImage(new ItemImage(stack.item.icon(Cicon.medium), stack.amount), () -> tile.entity != null && tile.entity.items != null && tile.entity.items.has(stack.item, stack.amount))).size(8 * 4).padRight(5);
}
}
@Override
public String getIcon(){
return "icon-item";
}
@Override
public void update(TileEntity entity){
}
@Override
public void trigger(TileEntity entity){
for(ItemStack stack : items){
entity.items.remove(stack);
}
}
@Override
public boolean valid(TileEntity entity){
return entity.items != null && entity.items.has(items);
}
@Override
public void display(BlockStats stats){
stats.add(booster ? BlockStat.booster : BlockStat.input, new ItemListValue(items));
}
}

View File

@@ -0,0 +1,54 @@
package mindustry.world.consumers;
import arc.struct.*;
import arc.scene.ui.layout.*;
import arc.util.ArcAnnotate.*;
import mindustry.entities.type.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.ui.Cicon;
import mindustry.world.*;
import mindustry.world.meta.*;
public class ConsumeLiquid extends ConsumeLiquidBase{
public final @NonNull Liquid liquid;
public ConsumeLiquid(Liquid liquid, float amount){
super(amount);
this.liquid = liquid;
}
protected ConsumeLiquid(){
this(null, 0f);
}
@Override
public void applyLiquidFilter(Bits filter){
filter.set(liquid.id);
}
@Override
public void build(Tile tile, Table table){
table.add(new ReqImage(liquid.icon(Cicon.medium), () -> valid(tile.entity))).size(8 * 4);
}
@Override
public String getIcon(){
return "icon-liquid-consume";
}
@Override
public void update(TileEntity entity){
entity.liquids.remove(liquid, Math.min(use(entity), entity.liquids.get(liquid)));
}
@Override
public boolean valid(TileEntity entity){
return entity != null && entity.liquids != null && entity.liquids.get(liquid) >= use(entity);
}
@Override
public void display(BlockStats stats){
stats.add(booster ? BlockStat.booster : BlockStat.input, liquid, amount * timePeriod, timePeriod == 60);
}
}

View File

@@ -0,0 +1,28 @@
package mindustry.world.consumers;
import mindustry.entities.type.TileEntity;
public abstract class ConsumeLiquidBase extends Consume{
/** amount used per frame */
public final float amount;
/**
* How much time is taken to use this liquid, in ticks. Used only for visual purposes.
* Example: a normal ConsumeLiquid with 10/s and a 10 second timePeriod would display as "100 seconds".
* Without a time override, it would display as "10 liquid/second".
* This is used for generic crafters.
*/
public float timePeriod = 60;
public ConsumeLiquidBase(float amount){
this.amount = amount;
}
@Override
public ConsumeType type(){
return ConsumeType.liquid;
}
protected float use(TileEntity entity){
return Math.min(amount * entity.delta(), entity.block.liquidCapacity);
}
}

View File

@@ -0,0 +1,59 @@
package mindustry.world.consumers;
import arc.struct.*;
import arc.func.Boolf;
import arc.scene.ui.layout.Table;
import mindustry.entities.type.TileEntity;
import mindustry.type.Liquid;
import mindustry.ui.Cicon;
import mindustry.ui.MultiReqImage;
import mindustry.ui.ReqImage;
import mindustry.world.Tile;
import mindustry.world.meta.BlockStat;
import mindustry.world.meta.BlockStats;
import mindustry.world.meta.values.LiquidFilterValue;
import static mindustry.Vars.content;
public class ConsumeLiquidFilter extends ConsumeLiquidBase{
public final Boolf<Liquid> filter;
public ConsumeLiquidFilter(Boolf<Liquid> liquid, float amount){
super(amount);
this.filter = liquid;
}
@Override
public void applyLiquidFilter(Bits arr){
content.liquids().each(filter, item -> arr.set(item.id));
}
@Override
public void build(Tile tile, Table table){
Array<Liquid> list = content.liquids().select(l -> !l.isHidden() && filter.get(l));
MultiReqImage image = new MultiReqImage();
list.each(liquid -> image.add(new ReqImage(liquid.icon(Cicon.medium), () -> tile.entity != null && tile.entity.liquids != null && tile.entity.liquids.get(liquid) >= use(tile.entity))));
table.add(image).size(8 * 4);
}
@Override
public String getIcon(){
return "icon-liquid-consume";
}
@Override
public void update(TileEntity entity){
entity.liquids.remove(entity.liquids.current(), use(entity));
}
@Override
public boolean valid(TileEntity entity){
return entity != null && entity.liquids != null && filter.get(entity.liquids.current()) && entity.liquids.currentAmount() >= use(entity);
}
@Override
public void display(BlockStats stats){
stats.add(booster ? BlockStat.booster : BlockStat.input, new LiquidFilterValue(filter, amount * timePeriod, timePeriod == 60f));
}
}

View File

@@ -0,0 +1,86 @@
package mindustry.world.consumers;
import arc.math.Mathf;
import arc.scene.ui.layout.Table;
import mindustry.entities.type.TileEntity;
import mindustry.world.Tile;
import mindustry.world.meta.*;
/** Consumer class for blocks which consume power while being connected to a power graph. */
public class ConsumePower extends Consume{
/** The maximum amount of power which can be processed per tick. This might influence efficiency or load a buffer. */
public final float usage;
/** The maximum power capacity in power units. */
public final float capacity;
/** True if the module can store power. */
public final boolean buffered;
public ConsumePower(float usage, float capacity, boolean buffered){
this.usage = usage;
this.capacity = capacity;
this.buffered = buffered;
}
protected ConsumePower(){
this(0f, 0f, false);
}
@Override
public ConsumeType type(){
return ConsumeType.power;
}
@Override
public void build(Tile tile, Table table){
//No tooltip for power, for now
}
@Override
public String getIcon(){
return "icon-power";
}
@Override
public void update(TileEntity entity){
// Nothing to do since PowerGraph directly updates entity.power.status
}
@Override
public boolean valid(TileEntity entity){
if(buffered){
return true;
}else{
return entity.power.status > 0f;
}
}
@Override
public void display(BlockStats stats){
if(buffered){
stats.add(BlockStat.powerCapacity, capacity, StatUnit.none);
}else{
stats.add(BlockStat.powerUse, usage * 60f, StatUnit.powerSecond);
}
}
/**
* Retrieves the amount of power which is requested for the given block and entity.
* @param entity The entity which contains the power module.
* @return The amount of power which is requested per tick.
*/
public float requestedPower(TileEntity entity){
if(entity.tile.entity == null) return 0f;
if(buffered){
return (1f-entity.power.status)*capacity;
}else{
try{
return usage * Mathf.num(entity.block.shouldConsume(entity.tile));
}catch(Exception e){
//HACK an error will only happen with a bar that is checking its requested power, and the entity is null/a different class
return 0;
}
}
}
}

View File

@@ -0,0 +1,7 @@
package mindustry.world.consumers;
public enum ConsumeType{
item,
power,
liquid
}

View File

@@ -0,0 +1,111 @@
package mindustry.world.consumers;
import arc.struct.*;
import arc.func.Boolf;
import arc.util.Structs;
import mindustry.Vars;
import mindustry.entities.type.TileEntity;
import mindustry.type.*;
import mindustry.world.blocks.power.ConditionalConsumePower;
import mindustry.world.meta.BlockStats;
public class Consumers{
private Consume[] map = new Consume[ConsumeType.values().length];
private Consume[] results, optionalResults;
public final Bits itemFilters = new Bits(Vars.content.items().size);
public final Bits liquidfilters = new Bits(Vars.content.liquids().size);
public void init(){
results = Structs.filter(Consume.class, map, m -> m != null);
optionalResults = Structs.filter(Consume.class, map, m -> m != null && m.isOptional());
for(Consume cons : results){
cons.applyItemFilter(itemFilters);
cons.applyLiquidFilter(liquidfilters);
}
}
public ConsumePower getPower(){
return get(ConsumeType.power);
}
public boolean hasPower(){
return has(ConsumeType.power);
}
public ConsumeLiquid liquid(Liquid liquid, float amount){
return add(new ConsumeLiquid(liquid, amount));
}
/**
* Creates a consumer which directly uses power without buffering it.
* @param powerPerTick The amount of power which is required each tick for 100% efficiency.
* @return the created consumer object.
*/
public ConsumePower power(float powerPerTick){
return add(new ConsumePower(powerPerTick, 0.0f, false));
}
/** Creates a consumer which only consumes power when the condition is met. */
public ConsumePower powerCond(float usage, Boolf<TileEntity> cons){
return add(new ConditionalConsumePower(usage, cons));
}
/**
* Creates a consumer which stores power.
* @param powerCapacity The maximum capacity in power units.
*/
public ConsumePower powerBuffered(float powerCapacity){
return add(new ConsumePower(0f, powerCapacity, true));
}
public ConsumeItems item(Item item){
return item(item, 1);
}
public ConsumeItems item(Item item, int amount){
return add(new ConsumeItems(new ItemStack[]{new ItemStack(item, amount)}));
}
public ConsumeItems items(ItemStack... items){
return add(new ConsumeItems(items));
}
public <T extends Consume> T add(T consume){
map[consume.type().ordinal()] = consume;
return consume;
}
public void remove(ConsumeType type){
map[type.ordinal()] = null;
}
public boolean has(ConsumeType type){
return map[type.ordinal()] != null;
}
@SuppressWarnings("unchecked")
public <T extends Consume> T get(ConsumeType type){
if(map[type.ordinal()] == null){
throw new IllegalArgumentException("Block does not contain consumer of type '" + type + "'!");
}
return (T)map[type.ordinal()];
}
public Consume[] all(){
return results;
}
public Consume[] optionals(){
return optionalResults;
}
public void display(BlockStats stats){
for(Consume c : map){
if(c != null){
c.display(stats);
}
}
}
}