DEATH AND DESTRUCTION

This commit is contained in:
Anuken
2022-02-15 16:46:32 -05:00
parent 3babe7686b
commit c324f2124b
135 changed files with 704 additions and 2080 deletions

View File

@@ -59,9 +59,6 @@ public class Block extends UnlockableContent implements Senseable{
public float liquidCapacity = 10f;
public float liquidPressure = 1f;
public final BlockBars bars = new BlockBars();
public final Consumers consumes = new Consumers();
/** If true, this block outputs to its facing direction, when applicable.
* Used for blending calculations. */
public boolean outputFacing = true;
@@ -288,10 +285,25 @@ public class Block extends UnlockableContent implements Senseable{
public @Nullable Class<?> subclass;
/** Determines if this block gets a higher unloader priority. */
public boolean highUnloadPriority = false;
public float selectScroll; //scroll position for certain blocks
public Prov<Building> buildType = null; //initialized later
/** Scroll position for certain blocks. */
public float selectScroll;
/** Building that is created for this block. Initialized in init() via reflection. Set manually if modded. */
public Prov<Building> buildType = null;
/** Configuration handlers by type. */
public ObjectMap<Class<?>, Cons2> configurations = new ObjectMap<>();
/** Consumption filters. */
public boolean[] itemFilter, liquidFilter;
/** Array of consumers used by this block. Only populated after init(). */
public Consume[] consumers = {}, optionalConsumers = {};
/** Set to true if this block has any consumers in its array. */
public boolean hasConsumers;
/** The single power consumer, if applicable. */
public @Nullable ConsumePower consPower;
/** Map of bars by name. */
protected OrderedMap<String, Func<Building, Bar>> barMap = new OrderedMap<>();
/** List for building up consumption before init(). */
protected Seq<Consume> consumeBuilder = new Seq<>();
protected TextureRegion[] generatedIcons;
protected TextureRegion[] editorVariantRegions;
@@ -304,7 +316,7 @@ public class Block extends UnlockableContent implements Senseable{
public TextureRegion[] teamRegions, variantRegions, variantShadowRegions;
protected static final Seq<Tile> tempTiles = new Seq<>();
protected static final Seq<Building> tempTileEnts = new Seq<>();
protected static final Seq<Building> tempBuilds = new Seq<>();
/** Dump timer ID.*/
protected final int timerDump = timers++;
@@ -469,15 +481,29 @@ public class Block extends UnlockableContent implements Senseable{
stats.add(Stat.maxConsecutive, 2, StatUnit.none);
}
consumes.display(stats);
for(var c : consumers){
c.display(stats);
}
//Note: Power stats are added by the consumers.
if(hasLiquids) stats.add(Stat.liquidCapacity, liquidCapacity, StatUnit.liquidUnits);
if(hasItems && itemCapacity > 0) stats.add(Stat.itemCapacity, itemCapacity, StatUnit.items);
}
public <T extends Building> void addBar(String name, Func<T, Bar> sup){
barMap.put(name, (Func<Building, Bar>)sup);
}
public void removeBar(String name){
barMap.remove(name);
}
public Iterable<Func<Building, Bar>> listBars(){
return barMap.values();
}
public void addLiquidBar(Liquid liq){
bars.add("liquid-" + liq.name, entity -> new Bar(
addBar("liquid-" + liq.name, entity -> new Bar(
() -> liq.localizedName,
liq::barColor,
() -> entity.liquids.get(liq) / liquidCapacity)
@@ -486,7 +512,7 @@ public class Block extends UnlockableContent implements Senseable{
/** Adds a liquid bar that dynamically displays a liquid type. */
public <T extends Building> void addLiquidBar(Func<T, Liquid> current){
bars.add("liquid", entity -> new Bar(
addBar("liquid", entity -> new Bar(
() -> current.get((T)entity) == null || entity.liquids.get(current.get((T)entity)) <= 0.001f ? Core.bundle.get("bar.liquid") : current.get((T)entity).localizedName,
() -> current.get((T)entity) == null ? Color.clear : current.get((T)entity).barColor(),
() -> current.get((T)entity) == null ? 0f : entity.liquids.get(current.get((T)entity)) / liquidCapacity)
@@ -494,23 +520,22 @@ public class Block extends UnlockableContent implements Senseable{
}
public void setBars(){
bars.add("health", entity -> new Bar("stat.health", Pal.health, entity::healthf).blink(Color.white));
addBar("health", entity -> new Bar("stat.health", Pal.health, entity::healthf).blink(Color.white));
if(hasPower && consumes.hasPower()){
ConsumePower cons = consumes.getPower();
boolean buffered = cons.buffered;
float capacity = cons.capacity;
if(consPower != null){
boolean buffered = consPower.buffered;
float capacity = consPower.capacity;
bars.add("power", entity -> new Bar(
addBar("power", entity -> new Bar(
() -> buffered ? Core.bundle.format("bar.poweramount", Float.isNaN(entity.power.status * capacity) ? "<ERROR>" : UI.formatAmount((int)(entity.power.status * capacity))) :
Core.bundle.get("bar.power"),
() -> Pal.powerBar,
() -> Mathf.zero(cons.requestedPower(entity)) && entity.power.graph.getPowerProduced() + entity.power.graph.getBatteryStored() > 0f ? 1f : entity.power.status)
() -> Mathf.zero(consPower.requestedPower(entity)) && entity.power.graph.getPowerProduced() + entity.power.graph.getBatteryStored() > 0f ? 1f : entity.power.status)
);
}
if(hasItems && configurable){
bars.add("items", entity -> new Bar(
addBar("items", entity -> new Bar(
() -> Core.bundle.format("bar.items", entity.items.total()),
() -> Pal.items,
() -> (float)entity.items.total() / itemCapacity)
@@ -533,9 +558,9 @@ public class Block extends UnlockableContent implements Senseable{
boolean added = false;
//TODO handle in consumer
//add bars for *specific* consumed liquids
if(consumes.has(ConsumeType.liquid)){
var consl = consumes.get(ConsumeType.liquid);
for(var consl : consumers){
if(consl instanceof ConsumeLiquid liq){
added = true;
addLiquidBar(liq.liquid);
@@ -554,6 +579,14 @@ public class Block extends UnlockableContent implements Senseable{
}
}
public boolean consumesItem(Item item){
return itemFilter[item.id];
}
public boolean consumesLiquid(Liquid liq){
return liquidFilter[liq.id];
}
public boolean canReplace(Block other){
if(other.alwaysReplace) return true;
return other.replaceable && (other != this || rotate) && this.group != BlockGroup.none && other.group == this.group &&
@@ -818,6 +851,67 @@ public class Block extends UnlockableContent implements Senseable{
return cacheLayer == CacheLayer.walls;
}
public <T extends Consume> T findConsumer(Boolf<Consume> filter){
return consumers.length == 0 ? (T)consumeBuilder.find(filter) : (T)Structs.find(consumers, filter);
}
public ConsumeLiquid consumeLiquid(Liquid liquid, float amount){
return consume(new ConsumeLiquid(liquid, amount));
}
public ConsumeLiquids consumeLiquids(LiquidStack... stacks){
return consume(new ConsumeLiquids(stacks));
}
/**
* 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 consumePower(float powerPerTick){
return consume(new ConsumePower(powerPerTick, 0.0f, false));
}
/** Creates a consumer which only consumes power when the condition is met. */
public <T extends Building> ConsumePower consumePowerCond(float usage, Boolf<T> cons){
return consume(new ConsumePowerCondition(usage, (Boolf<Building>)cons));
}
/** Creates a consumer that consumes a dynamic amount of power. */
public <T extends Building> ConsumePower consumePowerDynamic(Floatf<T> usage){
return consume(new ConsumePowerDynamic((Floatf<Building>)usage));
}
/**
* Creates a consumer which stores power.
* @param powerCapacity The maximum capacity in power units.
*/
public ConsumePower consumePowerBuffered(float powerCapacity){
return consume(new ConsumePower(0f, powerCapacity, true));
}
public ConsumeItems consumeItem(Item item){
return consumeItem(item, 1);
}
public ConsumeItems consumeItem(Item item, int amount){
return consume(new ConsumeItems(new ItemStack[]{new ItemStack(item, amount)}));
}
public ConsumeItems consumeItems(ItemStack... items){
return consume(new ConsumeItems(items));
}
public <T extends Consume> T consume(T consume){
if(consume instanceof ConsumePower){
//there can only be one power consumer
consumeBuilder.removeAll(b -> b instanceof ConsumePower);
consPower = (ConsumePower)consume;
}
consumeBuilder.add(consume);
return consume;
}
public void setupRequirements(Category cat, ItemStack[] stacks){
requirements(cat, stacks);
}
@@ -904,8 +998,8 @@ public class Block extends UnlockableContent implements Senseable{
}
//also requires inputs
consumes.each(c -> {
if(c.isOptional()) return;
for(var c : consumeBuilder){
if(c.optional) continue;
if(c instanceof ConsumeItems i){
for(ItemStack stack : i.items){
@@ -918,7 +1012,7 @@ public class Block extends UnlockableContent implements Senseable{
cons.get(stack.liquid);
}
}
});
}
}
@Override
@@ -966,7 +1060,7 @@ public class Block extends UnlockableContent implements Senseable{
clipSize = Math.max(clipSize, lightRadius * 2f);
}
if(group == BlockGroup.transportation || consumes.has(ConsumeType.item) || category == Category.distribution){
if(group == BlockGroup.transportation || category == Category.distribution){
acceptsItems = true;
}
@@ -981,15 +1075,21 @@ public class Block extends UnlockableContent implements Senseable{
buildCost *= buildCostMultiplier;
if(consumes.has(ConsumeType.power)) hasPower = true;
if(consumes.has(ConsumeType.item)) hasItems = true;
if(consumes.has(ConsumeType.liquid)) hasLiquids = true;
consumers = consumeBuilder.toArray(Consume.class);
optionalConsumers = consumeBuilder.filter(consume -> consume.optional).toArray(Consume.class);
hasConsumers = consumers.length > 0;
itemFilter = new boolean[content.items().size];
liquidFilter = new boolean[content.liquids().size];
for(Consume cons : consumers){
cons.apply(this);
}
setBars();
stats.useCategories = true;
consumes.init();
//TODO check for double power consumption
if(!logicConfigurable){
configurations.each((key, val) -> {
@@ -999,9 +1099,9 @@ public class Block extends UnlockableContent implements Senseable{
});
}
if(!outputsPower && consumes.hasPower() && consumes.getPower().buffered){
if(!outputsPower && consPower != null && consPower.buffered){
Log.warn("Consumer using buffered power: @. Disabling buffered power.", name);
consumes.getPower().buffered = false;
consPower.buffered = false;
}
if(buildVisibility == BuildVisibility.sandboxOnly){
@@ -1156,7 +1256,7 @@ public class Block extends UnlockableContent implements Senseable{
case size -> size * tilesize;
case itemCapacity -> itemCapacity;
case liquidCapacity -> liquidCapacity;
case powerCapacity -> consumes.hasPower() && consumes.getPower().buffered ? consumes.getPower().capacity : 0f;
case powerCapacity -> consPower != null && consPower.buffered ? consPower.capacity : 0f;
default -> Double.NaN;
};
}

View File

@@ -41,7 +41,7 @@ public class Accelerator extends Block{
capacities[stack.item.id] = stack.amount;
itemCapacity += stack.amount;
}
consumes.items(launching.requirements);
consumeItems(launching.requirements);
super.init();
}

View File

@@ -55,10 +55,10 @@ public class LaunchPad extends Block{
public void setBars(){
super.setBars();
bars.add("items", entity -> new Bar(() -> Core.bundle.format("bar.items", entity.items.total()), () -> Pal.items, () -> (float)entity.items.total() / itemCapacity));
addBar("items", entity -> new Bar(() -> Core.bundle.format("bar.items", entity.items.total()), () -> Pal.items, () -> (float)entity.items.total() / itemCapacity));
//TODO is "bar.launchcooldown" the right terminology?
bars.add("progress", (LaunchPadBuild build) -> new Bar(() -> Core.bundle.get("bar.launchcooldown"), () -> Pal.ammo, () -> Mathf.clamp(build.launchCounter / launchTime)));
addBar("progress", (LaunchPadBuild build) -> new Bar(() -> Core.bundle.get("bar.launchcooldown"), () -> Pal.ammo, () -> Mathf.clamp(build.launchCounter / launchTime)));
}
@Override

View File

@@ -57,7 +57,6 @@ public class BuildTurret extends BaseTurret{
hitSize = 0f;
health = 1;
itemCapacity = 0;
commandLimit = 0;
rotateSpeed = BuildTurret.this.rotateSpeed;
buildBeamOffset = BuildTurret.this.buildBeamOffset;
buildRange = BuildTurret.this.range;

View File

@@ -20,6 +20,7 @@ import static mindustry.Vars.*;
//TODO use completely different layer
//TODO consume heat
//TODO broken class!!!!!
public class DirectionalForceProjector extends Block{
protected static final Vec2 intersectOut = new Vec2(), p1 = new Vec2(), p2 = new Vec2();
protected static DirectionalForceProjectorBuild paramEntity;
@@ -82,7 +83,7 @@ public class DirectionalForceProjector extends Block{
@Override
public void setBars(){
super.setBars();
bars.add("shield", (DirectionalForceProjectorBuild entity) -> new Bar("stat.shieldhealth", Pal.accent, () -> entity.broken ? 0f : 1f - entity.buildup / (shieldHealth)).blink(Color.white));
addBar("shield", (DirectionalForceProjectorBuild entity) -> new Bar("stat.shieldhealth", Pal.accent, () -> entity.broken ? 0f : 1f - entity.buildup / (shieldHealth)).blink(Color.white));
}
@Override
@@ -138,9 +139,10 @@ public class DirectionalForceProjector extends Block{
warmup = Mathf.lerpDelta(warmup, efficiency(), 0.1f);
if(buildup > 0 && consumes.has(ConsumeType.liquid)){
//TODO aaaaaaaaaaaaAAAAAAAAAAAAAAaa
if(buildup > 0 && false){
float scale = !broken ? cooldownNormal : cooldownBrokenBase;
Consume cons = consumes.get(ConsumeType.liquid);
Consume cons = null;
if(cons.valid(this)){
cons.update(this);
scale *= (cooldownLiquid * (1f + (liquids.current().heatCapacity - 0.4f) * 0.9f));

View File

@@ -37,6 +37,9 @@ public class ForceProjector extends Block{
public Effect shieldBreakEffect = Fx.shieldBreak;
public @Load("@-top") TextureRegion topRegion;
//TODO json support
public @Nullable Consume boostConsumer;
protected static ForceBuild paramEntity;
protected static Effect paramEffect;
protected static final Cons<Bullet> shieldConsumer = bullet -> {
@@ -61,7 +64,7 @@ public class ForceProjector extends Block{
ambientSoundVolume = 0.08f;
if(consumeCoolant){
consumes.add(new ConsumeCoolant(coolantConsumption)).boost().update(false);
consume(new ConsumeCoolant(coolantConsumption)).boost().update(false);
}
}
@@ -74,7 +77,7 @@ public class ForceProjector extends Block{
@Override
public void setBars(){
super.setBars();
bars.add("shield", (ForceBuild entity) -> new Bar("stat.shieldhealth", Pal.accent, () -> entity.broken ? 0f : 1f - entity.buildup / (shieldHealth + phaseShieldBoost * entity.phaseHeat)).blink(Color.white));
addBar("shield", (ForceBuild entity) -> new Bar("stat.shieldhealth", Pal.accent, () -> entity.broken ? 0f : 1f - entity.buildup / (shieldHealth + phaseShieldBoost * entity.phaseHeat)).blink(Color.white));
}
@Override
@@ -84,7 +87,7 @@ public class ForceProjector extends Block{
@Override
public void setStats(){
boolean consItems = consumes.has(ConsumeType.item);
boolean consItems = boostConsumer != null;
if(consItems) stats.timePeriod = phaseUseTime;
super.setStats();
@@ -139,7 +142,7 @@ public class ForceProjector extends Block{
@Override
public void updateTile(){
boolean phaseValid = consumes.has(ConsumeType.item) && consumes.get(ConsumeType.item).valid(this);
boolean phaseValid = boostConsumer != null && boostConsumer.valid(this);
phaseHeat = Mathf.lerpDelta(phaseHeat, Mathf.num(phaseValid), 0.1f);
@@ -158,13 +161,15 @@ public class ForceProjector extends Block{
if(buildup > 0){
float scale = !broken ? cooldownNormal : cooldownBrokenBase;
//TODO I hate this system
/*
if(consumes.has(ConsumeType.liquid)){
Consume cons = consumes.get(ConsumeType.liquid);
if(cons.valid(this)){
cons.update(this);
scale *= (cooldownLiquid * (1f + (liquids.current().heatCapacity - 0.4f) * 0.9f));
}
}
}*/
buildup -= delta() * scale;
}

View File

@@ -76,7 +76,7 @@ public class OverdriveProjector extends Block{
@Override
public void setBars(){
super.setBars();
bars.add("boost", (OverdriveBuild entity) -> new Bar(() -> Core.bundle.format("bar.boost", Mathf.round(Math.max((entity.realBoost() * 100 - 100), 0))), () -> Pal.accent, () -> entity.realBoost() / (hasBoost ? speedBoost + speedBoostPhase : speedBoost)));
addBar("boost", (OverdriveBuild entity) -> new Bar(() -> Core.bundle.format("bar.boost", Mathf.round(Math.max((entity.realBoost() * 100 - 100), 0))), () -> Pal.accent, () -> entity.realBoost() / (hasBoost ? speedBoost + speedBoostPhase : speedBoost)));
}
public class OverdriveBuild extends Building implements Ranged{

View File

@@ -20,6 +20,7 @@ public class BaseTurret extends Block{
public float rotateSpeed = 5;
public float coolantUsage = 0.2f;
@Deprecated
public boolean acceptCoolant = true;
/** Effect displayed when coolant is used. */
public Effect coolEffect = Fx.fuelburn;
@@ -28,6 +29,8 @@ public class BaseTurret extends Block{
/** Liquid that is used by coolant; null to use default. */
public @Nullable Liquid coolantOverride;
protected @Nullable ConsumeLiquidBase coolantConsumer;
public BaseTurret(String name){
super(name);
@@ -41,13 +44,18 @@ public class BaseTurret extends Block{
@Override
public void init(){
if(acceptCoolant && !consumes.has(ConsumeType.liquid)){
//TODO fundamentally flawed
if(acceptCoolant && findConsumer(f -> f instanceof ConsumeLiquidBase) == null){
hasLiquids = true;
consumes.add(coolantOverride != null ? new ConsumeLiquid(coolantOverride, coolantUsage) : new ConsumeCoolant(coolantUsage)).update(false).boost();
consume(coolantOverride != null ? new ConsumeLiquid(coolantOverride, coolantUsage) : new ConsumeCoolant(coolantUsage)).update(false).boost();
}
placeOverlapRange = Math.max(placeOverlapRange, range + placeOverlapMargin);
super.init();
if(acceptCoolant){
coolantConsumer = findConsumer(c -> c instanceof ConsumeLiquidBase && c.booster);
}
}
@Override

View File

@@ -41,7 +41,7 @@ public class ContinuousLiquidTurret extends ContinuousTurret{
@Override
public void init(){
//TODO display ammoMultiplier.
consumes.add(new ConsumeLiquidFilter(i -> ammoTypes.containsKey(i), liquidConsumed){
consume(new ConsumeLiquidFilter(i -> ammoTypes.containsKey(i), liquidConsumed){
@Override
public boolean valid(Building build){
return build.liquids.currentAmount() >= use(build);

View File

@@ -60,14 +60,9 @@ public class ContinuousTurret extends Turret{
public void updateTile(){
super.updateTile();
//unclean way of calculating ammo fraction to display
//TODO unclean way of calculating ammo fraction to display
float ammoFract = efficiency();
var liq = consumes.getOrNull(ConsumeType.liquid);
if(liq instanceof ConsumeLiquids cons){
for(var stack : cons.liquids){
ammoFract = Math.min(ammoFract, liquids.get(stack.liquid) / liquidCapacity);
}
}else if(liq instanceof ConsumeLiquid cons){
if(findConsumer(f -> f instanceof ConsumeLiquidBase) instanceof ConsumeLiquid cons){
ammoFract = Math.min(ammoFract, liquids.get(cons.liquid) / liquidCapacity);
}

View File

@@ -57,7 +57,7 @@ public class ItemTurret extends Turret{
@Override
public void init(){
consumes.add(new ConsumeItemFilter(i -> ammoTypes.containsKey(i)){
consume(new ConsumeItemFilter(i -> ammoTypes.containsKey(i)){
@Override
public void build(Building build, Table table){
MultiReqImage image = new MultiReqImage();

View File

@@ -11,6 +11,7 @@ import mindustry.world.meta.*;
import static mindustry.Vars.*;
/** A turret that fires a continuous beam with a delay between shots. Liquid coolant is required. Yes, this class name is awful. */
@Deprecated
public class LaserTurret extends PowerTurret{
public float firingMoveFract = 0.25f;
public float shootDuration = 100f;
@@ -18,7 +19,7 @@ public class LaserTurret extends PowerTurret{
public LaserTurret(String name){
super(name);
consumes.add(new ConsumeCoolant(0.01f)).update(false);
consume(new ConsumeCoolant(0.01f)).update(false);
coolantMultiplier = 1f;
}
@@ -27,7 +28,8 @@ public class LaserTurret extends PowerTurret{
super.setStats();
stats.remove(Stat.booster);
stats.add(Stat.input, StatValues.boosters(reloadTime, consumes.<ConsumeLiquidBase>get(ConsumeType.liquid).amount, coolantMultiplier, false, l -> consumes.liquidfilters.get(l.id)));
//TODO bad
stats.add(Stat.input, StatValues.boosters(reloadTime, coolantConsumer.amount, coolantMultiplier, false, l -> consumesLiquid(l)));
}
public class LaserTurretBuild extends PowerTurretBuild{
@@ -67,7 +69,7 @@ public class LaserTurret extends PowerTurret{
}else if(reload > 0){
wasShooting = true;
Liquid liquid = liquids.current();
float maxUsed = consumes.<ConsumeLiquidBase>get(ConsumeType.liquid).amount;
float maxUsed = coolantConsumer.amount;
float used = (cheating() ? maxUsed : Math.min(liquids.get(liquid), maxUsed)) * delta();
reload -= used * liquid.heatCapacity * coolantMultiplier;

View File

@@ -41,7 +41,7 @@ public class LiquidTurret extends Turret{
@Override
public void init(){
consumes.add(new ConsumeLiquidFilter(i -> ammoTypes.containsKey(i), 1f){
consume(new ConsumeLiquidFilter(i -> ammoTypes.containsKey(i), 1f){
@Override
public boolean valid(Building build){
return build.liquids.currentAmount() >= 0.001f;

View File

@@ -57,7 +57,7 @@ public class PayloadTurret extends Turret{
@Override
public void init(){
consumes.add(new ConsumePayloadFilter(i -> ammoTypes.containsKey(i)){
consume(new ConsumePayloadFilter(i -> ammoTypes.containsKey(i)){
@Override
public void build(Building build, Table table){
MultiReqImage image = new MultiReqImage();

View File

@@ -3,7 +3,6 @@ package mindustry.world.blocks.defense.turrets;
import arc.math.*;
import arc.util.*;
import mindustry.type.*;
import mindustry.world.consumers.*;
import mindustry.world.meta.*;
import static mindustry.Vars.*;
@@ -19,8 +18,8 @@ public class ReloadTurret extends BaseTurret{
public void setStats(){
super.setStats();
if(acceptCoolant){
stats.add(Stat.booster, StatValues.boosters(reloadTime, consumes.<ConsumeLiquidBase>get(ConsumeType.liquid).amount, coolantMultiplier, true, l -> l.coolant && consumes.liquidfilters.get(l.id)));
if(acceptCoolant && coolantConsumer != null){
stats.add(Stat.booster, StatValues.boosters(reloadTime, coolantConsumer.amount, coolantMultiplier, true, l -> l.coolant && consumesLiquid(l)));
}
}
@@ -36,7 +35,7 @@ public class ReloadTurret extends BaseTurret{
protected void updateCooling(){
if(reload < reloadTime && acceptCoolant){
float maxUsed = consumes.<ConsumeLiquidBase>get(ConsumeType.liquid).amount;
float maxUsed = coolantConsumer.amount;
Liquid liquid = liquids.current();
float used = Math.min(liquids.get(liquid), maxUsed * Time.delta) * baseReloadSpeed();

View File

@@ -12,7 +12,6 @@ import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.world.consumers.*;
import mindustry.world.meta.*;
import static mindustry.Vars.*;
@@ -88,7 +87,7 @@ public class TractorBeamTurret extends BaseTurret{
//consume coolant
if(target != null && acceptCoolant){
float maxUsed = consumes.<ConsumeLiquidBase>get(ConsumeType.liquid).amount;
float maxUsed = coolantConsumer.amount;
Liquid liquid = liquids.current();

View File

@@ -138,7 +138,7 @@ public class Turret extends ReloadTurret{
super.setBars();
if(heatRequirement > 0){
bars.add("heat", (TurretBuild entity) ->
addBar("heat", (TurretBuild entity) ->
new Bar(() ->
Core.bundle.format("bar.heatpercent", (int)entity.heatReq, (int)(Math.min(entity.heatReq / heatRequirement, maxHeatEfficiency) * 100)),
() -> Pal.lightOrange,

View File

@@ -61,7 +61,7 @@ public class DirectionalUnloader extends Block{
@Override
public void setBars(){
super.setBars();
bars.remove("items");
removeBar("items");
}
@Override

View File

@@ -27,7 +27,7 @@ public class HeatConductor extends Block{
super.setBars();
//TODO show number
bars.add("heat", (HeatConductorBuild entity) -> new Bar(() -> Core.bundle.format("bar.heatamount", (int)entity.heat), () -> Pal.lightOrange, () -> entity.heat / visualMaxHeat));
addBar("heat", (HeatConductorBuild entity) -> new Bar(() -> Core.bundle.format("bar.heatamount", (int)entity.heat), () -> Pal.lightOrange, () -> entity.heat / visualMaxHeat));
}
@Override

View File

@@ -33,7 +33,7 @@ public class HeatProducer extends GenericCrafter{
public void setBars(){
super.setBars();
bars.add("heat", (HeatProducerBuild entity) -> new Bar("bar.heat", Pal.lightOrange, () -> entity.heat / heatOutput));
addBar("heat", (HeatProducerBuild entity) -> new Bar("bar.heat", Pal.lightOrange, () -> entity.heat / heatOutput));
}
public class HeatProducerBuild extends GenericCrafterBuild implements HeatBlock{

View File

@@ -0,0 +1,28 @@
package mindustry.world.blocks.legacy;
import arc.util.io.*;
import mindustry.gen.*;
public class LegacyCommandCenter extends LegacyBlock{
public LegacyCommandCenter(String name){
super(name);
update = true;
}
public class CommandBuild extends Building{
@Override
public void write(Writes write){
super.write(write);
write.b(0);
}
@Override
public void read(Reads read, byte version){
super.read(read, version);
read.b();
}
}
}

View File

@@ -21,7 +21,7 @@ public class LiquidJunction extends LiquidBlock{
@Override
public void setBars(){
super.setBars();
bars.remove("liquid");
removeBar("liquid");
}
@Override

View File

@@ -33,7 +33,7 @@ public abstract class BlockProducer extends PayloadBlock{
rotate = true;
regionRotated1 = 1;
consumes.add(new ConsumeItemDynamic((BlockProducerBuild e) -> e.recipe() != null ? e.recipe().requirements : ItemStack.empty));
consume(new ConsumeItemDynamic((BlockProducerBuild e) -> e.recipe() != null ? e.recipe().requirements : ItemStack.empty));
}
@Override
@@ -52,7 +52,7 @@ public abstract class BlockProducer extends PayloadBlock{
public void setBars(){
super.setBars();
bars.add("progress", (BlockProducerBuild entity) -> new Bar("bar.progress", Pal.ammo, () -> entity.recipe() == null ? 0f : (entity.progress / entity.recipe().buildCost)));
addBar("progress", (BlockProducerBuild entity) -> new Bar("bar.progress", Pal.ammo, () -> entity.recipe() == null ? 0f : (entity.progress / entity.recipe().buildCost)));
}
public abstract class BlockProducerBuild extends PayloadBlockBuild<BuildPayload>{

View File

@@ -43,7 +43,7 @@ public class PayloadDeconstructor extends PayloadBlock{
public void setBars(){
super.setBars();
bars.add("progress", (PayloadDeconstructorBuild e) -> new Bar("bar.progress", Pal.ammo, () -> e.progress));
addBar("progress", (PayloadDeconstructorBuild e) -> new Bar("bar.progress", Pal.ammo, () -> e.progress));
}
public class PayloadDeconstructorBuild extends PayloadBlockBuild<Payload>{

View File

@@ -54,7 +54,7 @@ public class PayloadLoader extends PayloadBlock{
public void setBars(){
super.setBars();
bars.add("progress", (PayloadLoaderBuild build) -> new Bar(() ->
addBar("progress", (PayloadLoaderBuild build) -> new Bar(() ->
Core.bundle.format(build.payload != null && build.payload.block().hasItems ? "bar.items" : "bar.loadprogress",
build.payload == null || !build.payload.block().hasItems ? 0 : build.payload.build.items.total()), () -> Pal.items, build::fraction));
}
@@ -70,8 +70,8 @@ public class PayloadLoader extends PayloadBlock{
@Override
public void init(){
if(loadPowerDynamic){
basePowerUse = consumes.hasPower() ? consumes.getPower().usage : 0f;
consumes.powerDynamic((PayloadLoaderBuild loader) -> loader.hasBattery() && !loader.exporting ? maxPowerConsumption + basePowerUse : basePowerUse);
basePowerUse = consPower != null ? consPower.usage : 0f;
consumePowerDynamic((PayloadLoaderBuild loader) -> loader.hasBattery() && !loader.exporting ? maxPowerConsumption + basePowerUse : basePowerUse);
}
super.init();
@@ -90,7 +90,7 @@ public class PayloadLoader extends PayloadBlock{
//liquid container
(build.build.block().hasLiquids && build.block().liquidCapacity >= 10f) ||
//battery
(build.build.block.consumes.hasPower() && build.build.block.consumes.getPower().buffered)
(build.build.block.consPower != null && build.build.block.consPower.buffered)
);
}
@@ -153,7 +153,7 @@ public class PayloadLoader extends PayloadBlock{
payload.build.handleItem(payload.build, item);
items.remove(item, 1);
break;
}else if(payload.block().separateItemCapacity || payload.block().consumes.consumesItem(item)){
}else if(payload.block().separateItemCapacity || payload.block().consumesItem(item)){
exporting = true;
break;
}
@@ -183,7 +183,7 @@ public class PayloadLoader extends PayloadBlock{
float availableInput = Math.max(powerInput - basePowerUse, 0f);
//charge the battery
float cap = payload.block().consumes.getPower().capacity;
float cap = payload.block().consPower.capacity;
payload.build.power.status += availableInput / cap * edelta();
//export if full
@@ -212,7 +212,7 @@ public class PayloadLoader extends PayloadBlock{
}
public boolean hasBattery(){
return payload != null && payload.block().hasPower && payload.block().consumes.getPower().buffered;
return payload != null && payload.block().consPower != null && payload.block().consPower.buffered;
}
@Override

View File

@@ -92,7 +92,7 @@ public class PayloadUnloader extends PayloadLoader{
}
if(hasBattery()){
float cap = payload.block().consumes.getPower().capacity;
float cap = payload.block().consPower.capacity;
float total = payload.build.power.status * cap;
float unloaded = Math.min(maxPowerUnload * edelta(), total);
lastOutputPower = unloaded;

View File

@@ -39,9 +39,9 @@ public class Battery extends PowerDistributor{
@Override
public void overwrote(Seq<Building> previous){
for(Building other : previous){
if(other.power != null && other.block.consumes.hasPower() && other.block.consumes.getPower().buffered){
float amount = other.block.consumes.getPower().capacity * other.power.status;
power.status = Mathf.clamp(power.status + amount / block.consumes.getPower().capacity);
if(other.power != null && other.block.consPower != null && other.block.consPower.buffered){
float amount = other.block.consPower.capacity * other.power.status;
power.status = Mathf.clamp(power.status + amount / consPower.capacity);
}
}
}

View File

@@ -40,8 +40,8 @@ public class BeamNode extends PowerBlock{
public void setBars(){
super.setBars();
bars.add("power", PowerNode.makePowerBalance());
bars.add("batteries", PowerNode.makeBatteryBalance());
addBar("power", PowerNode.makePowerBalance());
addBar("batteries", PowerNode.makeBatteryBalance());
}
@Override

View File

@@ -50,9 +50,9 @@ public class ImpactReactor extends PowerGenerator{
public void setBars(){
super.setBars();
bars.add("poweroutput", (GeneratorBuild entity) -> new Bar(() ->
addBar("poweroutput", (GeneratorBuild entity) -> new Bar(() ->
Core.bundle.format("bar.poweroutput",
Strings.fixed(Math.max(entity.getPowerProduction() - consumes.getPower().usage, 0) * 60 * entity.timeScale, 1)),
Strings.fixed(Math.max(entity.getPowerProduction() - consPower.usage, 0) * 60 * entity.timeScale, 1)),
() -> Pal.powerBar,
() -> entity.productionEfficiency));
}
@@ -77,14 +77,14 @@ public class ImpactReactor extends PowerGenerator{
@Override
public void updateTile(){
if(consValid() && power.status >= 0.99f){
boolean prevOut = getPowerProduction() <= consumes.getPower().requestedPower(this);
boolean prevOut = getPowerProduction() <= consPower.requestedPower(this);
warmup = Mathf.lerpDelta(warmup, 1f, warmupSpeed * timeScale);
if(Mathf.equal(warmup, 1f, 0.001f)){
warmup = 1f;
}
if(!prevOut && (getPowerProduction() > consumes.getPower().requestedPower(this))){
if(!prevOut && (getPowerProduction() > consPower.requestedPower(this))){
Events.fire(Trigger.impactPower);
}

View File

@@ -18,6 +18,8 @@ import static mindustry.Vars.*;
* Power generation block which can use items, liquids or both as input sources for power production.
* Liquids will take priority over items.
*/
//TODO remove
@Deprecated
public class ItemLiquidGenerator extends PowerGenerator{
public float minItemEfficiency = 0.2f;
/** The time in number of ticks during which a single item will produce power. */
@@ -49,11 +51,11 @@ public class ItemLiquidGenerator extends PowerGenerator{
protected void setDefaults(){
if(hasItems){
consumes.add(new ConsumeItemFilter(item -> getItemEfficiency(item) >= minItemEfficiency)).update(false).optional(true, false);
consume(new ConsumeItemFilter(item -> getItemEfficiency(item) >= minItemEfficiency)).update(false).optional(true, false);
}
if(hasLiquids){
consumes.add(new ConsumeLiquidFilter(liquid -> getLiquidEfficiency(liquid) >= minLiquidEfficiency, maxLiquidGenerate)).update(false).optional(true, false);
consume(new ConsumeLiquidFilter(liquid -> getLiquidEfficiency(liquid) >= minLiquidEfficiency, maxLiquidGenerate)).update(false).optional(true, false);
}
defaults = true;

View File

@@ -17,7 +17,6 @@ import mindustry.graphics.*;
import mindustry.logic.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.consumers.*;
import mindustry.world.meta.*;
import static mindustry.Vars.*;
@@ -44,6 +43,8 @@ public class NuclearReactor extends PowerGenerator{
/** heat removed per unit of coolant */
public float coolantPower = 0.5f;
public Item fuelItem = Items.thorium;
public @Load("@-top") TextureRegion topRegion;
public @Load("@-lights") TextureRegion lightsRegion;
@@ -71,7 +72,7 @@ public class NuclearReactor extends PowerGenerator{
@Override
public void setBars(){
super.setBars();
bars.add("heat", (NuclearReactorBuild entity) -> new Bar("bar.heat", Pal.lightOrange, () -> entity.heat));
addBar("heat", (NuclearReactorBuild entity) -> new Bar("bar.heat", Pal.lightOrange, () -> entity.heat));
}
public class NuclearReactorBuild extends GeneratorBuild{
@@ -80,10 +81,7 @@ public class NuclearReactor extends PowerGenerator{
@Override
public void updateTile(){
ConsumeLiquid cliquid = consumes.get(ConsumeType.liquid);
Item item = consumes.getItem().items[0].item;
int fuel = items.get(item);
int fuel = items.get(fuelItem);
float fullness = (float)fuel / itemCapacity;
productionEfficiency = fullness;
@@ -97,12 +95,10 @@ public class NuclearReactor extends PowerGenerator{
productionEfficiency = 0f;
}
Liquid liquid = cliquid.liquid;
if(heat > 0){
float maxUsed = Math.min(liquids.get(liquid), heat / coolantPower);
float maxUsed = Math.min(liquids.currentAmount(), heat / coolantPower);
heat -= maxUsed * coolantPower;
liquids.remove(liquid, maxUsed);
liquids.remove(liquids.current(), maxUsed);
}
if(heat > smokeThreshold){
@@ -133,7 +129,7 @@ public class NuclearReactor extends PowerGenerator{
Sounds.explosionbig.at(this);
int fuel = items.get(consumes.<ConsumeItems>get(ConsumeType.item).items[0].item);
int fuel = items.get(fuelItem);
if((fuel < 5 && heat < 0.5f) || !state.rules.reactorExplosions) return;

View File

@@ -30,8 +30,8 @@ public class PowerDiode extends Block{
public void setBars(){
super.setBars();
bars.add("back", entity -> new Bar("bar.input", Pal.powerBar, () -> bar(entity.back())));
bars.add("front", entity -> new Bar("bar.output", Pal.powerBar, () -> bar(entity.front())));
addBar("back", entity -> new Bar("bar.input", Pal.powerBar, () -> bar(entity.back())));
addBar("front", entity -> new Bar("bar.output", Pal.powerBar, () -> bar(entity.front())));
}
@Override

View File

@@ -47,8 +47,8 @@ public class PowerGenerator extends PowerDistributor{
public void setBars(){
super.setBars();
if(hasPower && outputsPower && !consumes.hasPower()){
bars.add("power", (GeneratorBuild entity) -> new Bar(() ->
if(hasPower && outputsPower && consPower != null){
addBar("power", (GeneratorBuild entity) -> new Bar(() ->
Core.bundle.format("bar.poweroutput",
Strings.fixed(entity.getPowerProduction() * 60 * entity.timeScale(), 1)),
() -> Pal.powerBar,

View File

@@ -95,12 +95,9 @@ public class PowerGraph{
public float getPowerNeeded(){
float powerNeeded = 0f;
for(Building consumer : consumers){
Consumers consumes = consumer.block.consumes;
if(consumes.hasPower()){
ConsumePower consumePower = consumes.getPower();
if(otherConsumersAreValid(consumer, consumePower)){
powerNeeded += consumePower.requestedPower(consumer) * consumer.delta();
}
ConsumePower consumePower = consumer.block.consPower;
if(otherConsumersAreValid(consumer, consumePower)){
powerNeeded += consumePower.requestedPower(consumer) * consumer.delta();
}
}
return powerNeeded;
@@ -109,9 +106,8 @@ public class PowerGraph{
public float getBatteryStored(){
float totalAccumulator = 0f;
for(Building battery : batteries){
Consumers consumes = battery.block.consumes;
if(battery.enabled && consumes.hasPower()){
totalAccumulator += battery.power.status * consumes.getPower().capacity;
if(battery.enabled){
totalAccumulator += battery.power.status * battery.block.consPower.capacity;
}
}
return totalAccumulator;
@@ -120,9 +116,8 @@ public class PowerGraph{
public float getBatteryCapacity(){
float totalCapacity = 0f;
for(Building battery : batteries){
if(battery.enabled && battery.block.consumes.hasPower()){
ConsumePower power = battery.block.consumes.getPower();
totalCapacity += (1f - battery.power.status) * power.capacity;
if(battery.enabled){
totalCapacity += (1f - battery.power.status) * battery.block.consPower.capacity;
}
}
return totalCapacity;
@@ -131,8 +126,8 @@ public class PowerGraph{
public float getTotalBatteryCapacity(){
float totalCapacity = 0f;
for(Building battery : batteries){
if(battery.enabled && battery.block.consumes.hasPower()){
totalCapacity += battery.block.consumes.getPower().capacity;
if(battery.enabled){
totalCapacity += battery.block.consPower.capacity;
}
}
return totalCapacity;
@@ -145,8 +140,7 @@ public class PowerGraph{
float used = Math.min(stored, needed);
float consumedPowerPercentage = Math.min(1.0f, needed / stored);
for(Building battery : batteries){
Consumers consumes = battery.block.consumes;
if(battery.enabled && consumes.hasPower()){
if(battery.enabled){
battery.power.status *= (1f-consumedPowerPercentage);
}
}
@@ -160,12 +154,9 @@ public class PowerGraph{
if(Mathf.equal(capacity, 0f)) return 0f;
for(Building battery : batteries){
Consumers consumes = battery.block.consumes;
if(battery.enabled && consumes.hasPower()){
ConsumePower consumePower = consumes.getPower();
if(consumePower.capacity > 0f){
battery.power.status += (1f- battery.power.status) * chargedPercent;
}
//TODO why would it be 0
if(battery.enabled && battery.block.consPower.capacity > 0f){
battery.power.status += (1f - battery.power.status) * chargedPercent;
}
}
return Math.min(excess, capacity);
@@ -175,25 +166,23 @@ public class PowerGraph{
//distribute even if not needed. this is because some might be requiring power but not using it; it updates consumers
float coverage = Mathf.zero(needed) && Mathf.zero(produced) && !charged && Mathf.zero(lastPowerStored) ? 0f : Mathf.zero(needed) ? 1f : Math.min(1, produced / needed);
for(Building consumer : consumers){
Consumers consumes = consumer.block.consumes;
if(consumes.hasPower()){
ConsumePower consumePower = consumes.getPower();
if(consumePower.buffered){
if(!Mathf.zero(consumePower.capacity)){
// Add an equal percentage of power to all buffers, based on the global power coverage in this graph
float maximumRate = consumePower.requestedPower(consumer) * coverage * consumer.delta();
consumer.power.status = Mathf.clamp(consumer.power.status + maximumRate / consumePower.capacity);
}
}else{
//valid consumers get power as usual
if(otherConsumersAreValid(consumer, consumePower)){
consumer.power.status = coverage;
}else{ //invalid consumers get an estimate, if they were to activate
consumer.power.status = Math.min(1, produced / (needed + consumePower.usage * consumer.delta()));
//just in case
if(Float.isNaN(consumer.power.status)){
consumer.power.status = 0f;
}
//TODO how would it even be null
ConsumePower cons = consumer.block.consPower;
if(cons.buffered){
if(!Mathf.zero(cons.capacity)){
// Add an equal percentage of power to all buffers, based on the global power coverage in this graph
float maximumRate = cons.requestedPower(consumer) * coverage * consumer.delta();
consumer.power.status = Mathf.clamp(consumer.power.status + maximumRate / cons.capacity);
}
}else{
//valid consumers get power as usual
if(otherConsumersAreValid(consumer, cons)){
consumer.power.status = coverage;
}else{ //invalid consumers get an estimate, if they were to activate
consumer.power.status = Math.min(1, produced / (needed + cons.usage * consumer.delta()));
//just in case
if(Float.isNaN(consumer.power.status)){
consumer.power.status = 0f;
}
}
}
@@ -268,15 +257,17 @@ public class PowerGraph{
//there's something to update, add the entity
entity.add();
if(build.block.outputsPower && build.block.consumesPower && !build.block.consumes.getPower().buffered){
producers.add(build);
consumers.add(build);
}else if(build.block.outputsPower && build.block.consumesPower){
batteries.add(build);
}else if(build.block.outputsPower){
producers.add(build);
}else if(build.block.consumesPower){
consumers.add(build);
if(build.block.consPower != null){
if(build.block.outputsPower && build.block.consumesPower && !build.block.consPower.buffered){
producers.add(build);
consumers.add(build);
}else if(build.block.outputsPower && build.block.consumesPower){
batteries.add(build);
}else if(build.block.outputsPower){
producers.add(build);
}else if(build.block.consumesPower){
consumers.add(build);
}
}
}
}
@@ -352,8 +343,8 @@ public class PowerGraph{
}
private boolean otherConsumersAreValid(Building build, Consume consumePower){
for(Consume cons : build.block.consumes.all){
if(cons != consumePower && !cons.isOptional() && !cons.valid(build)){
for(Consume cons : build.block.consumers){
if(cons != consumePower && !cons.optional && !cons.valid(build)){
return false;
}
}

View File

@@ -100,10 +100,10 @@ public class PowerNode extends PowerBlock{
@Override
public void setBars(){
super.setBars();
bars.add("power", makePowerBalance());
bars.add("batteries", makeBatteryBalance());
addBar("power", makePowerBalance());
addBar("batteries", makeBatteryBalance());
bars.add("connections", entity -> new Bar(() ->
addBar("connections", entity -> new Bar(() ->
Core.bundle.format("bar.powerlines", entity.power.links.size, maxNodes),
() -> Pal.items,
() -> (float)entity.power.links.size / (float)maxNodes
@@ -217,7 +217,7 @@ public class PowerNode extends PowerBlock{
return t != null && t.build == other;
});
tempTileEnts.clear();
tempBuilds.clear();
graphs.clear();
//add conducting graphs to prevent double link
@@ -234,12 +234,12 @@ public class PowerNode extends PowerBlock{
Geometry.circle(tile.x, tile.y, (int)(laserRange + 2), (x, y) -> {
Building other = world.build(x, y);
if(valid.get(other) && !tempTileEnts.contains(other)){
tempTileEnts.add(other);
if(valid.get(other) && !tempBuilds.contains(other)){
tempBuilds.add(other);
}
});
tempTileEnts.sort((a, b) -> {
tempBuilds.sort((a, b) -> {
int type = -Boolean.compare(a.block instanceof PowerNode, b.block instanceof PowerNode);
if(type != 0) return type;
return Float.compare(a.dst2(tile), b.dst2(tile));
@@ -247,7 +247,7 @@ public class PowerNode extends PowerBlock{
returnInt = 0;
tempTileEnts.each(valid, t -> {
tempBuilds.each(valid, t -> {
if(returnInt ++ < maxNodes){
graphs.add(t.power.graph);
others.get(t);
@@ -269,7 +269,7 @@ public class PowerNode extends PowerBlock{
return t != null && t.build == other;
});
tempTileEnts.clear();
tempBuilds.clear();
graphs.clear();
//add conducting graphs to prevent double link
@@ -287,18 +287,18 @@ public class PowerNode extends PowerBlock{
Geometry.circle(tile.x, tile.y, 13, (x, y) -> {
Building other = world.build(x, y);
if(valid.get(other) && !tempTileEnts.contains(other)){
tempTileEnts.add(other);
if(valid.get(other) && !tempBuilds.contains(other)){
tempBuilds.add(other);
}
});
tempTileEnts.sort((a, b) -> {
tempBuilds.sort((a, b) -> {
int type = -Boolean.compare(a.block instanceof PowerNode, b.block instanceof PowerNode);
if(type != 0) return type;
return Float.compare(a.dst2(tile), b.dst2(tile));
});
tempTileEnts.each(valid, t -> {
tempBuilds.each(valid, t -> {
graphs.add(t.power.graph);
others.get(t);
});

View File

@@ -37,7 +37,7 @@ public class AttributeCrafter extends GenericCrafter{
if(!displayEfficiency) return;
bars.add("efficiency", (AttributeCrafterBuild entity) ->
addBar("efficiency", (AttributeCrafterBuild entity) ->
new Bar(() ->
Core.bundle.format("bar.efficiency", (int)(entity.efficiencyScale() * 100 * displayEfficiencyScale)),
() -> Pal.lightOrange,

View File

@@ -73,7 +73,7 @@ public class BeamDrill extends Block{
public void setBars(){
super.setBars();
bars.add("drillspeed", (BeamDrillBuild e) ->
addBar("drillspeed", (BeamDrillBuild e) ->
new Bar(() -> Core.bundle.format("bar.drillspeed", Strings.fixed(e.lastDrillSpeed * 60, 2)), () -> Pal.ammo, () -> e.warmup));
}

View File

@@ -103,7 +103,7 @@ public class Drill extends Block{
public void setBars(){
super.setBars();
bars.add("drillspeed", (DrillBuild e) ->
addBar("drillspeed", (DrillBuild e) ->
new Bar(() -> Core.bundle.format("bar.drillspeed", Strings.fixed(e.lastDrillSpeed * 60 * e.timeScale, 2)), () -> Pal.ammo, () -> e.warmup));
}

View File

@@ -77,7 +77,7 @@ public class GenericCrafter extends Block{
//set up liquid bars for liquid outputs
if(outputLiquids != null && outputLiquids.length > 0){
//no need for dynamic liquid bar
bars.remove("liquid");
removeBar("liquid");
//then display output buffer
for(var stack : outputLiquids){

View File

@@ -24,7 +24,7 @@ public class HeatCrafter extends GenericCrafter{
public void setBars(){
super.setBars();
bars.add("heat", (HeatCrafterBuild entity) ->
addBar("heat", (HeatCrafterBuild entity) ->
new Bar(() ->
Core.bundle.format("bar.heatpercent", (int)entity.heat, (int)(entity.efficiencyScale() * 100)),
() -> Pal.lightOrange,

View File

@@ -1,10 +1,12 @@
package mindustry.world.blocks.production;
import arc.math.*;
import arc.util.*;
import mindustry.world.consumers.*;
import mindustry.world.meta.*;
public class LiquidConverter extends GenericCrafter{
protected @Nullable ConsumeLiquid consumer;
public LiquidConverter(String name){
super(name);
@@ -18,13 +20,11 @@ public class LiquidConverter extends GenericCrafter{
@Override
public void init(){
if(!consumes.has(ConsumeType.liquid) || !(consumes.get(ConsumeType.liquid) instanceof ConsumeLiquid)){
throw new RuntimeException("LiquidsConverters must have a ConsumeLiquid. Note that filters are not supported.");
}
ConsumeLiquid cl = consumes.get(ConsumeType.liquid);
cl.update(false);
super.init();
consumer = findConsumer(b -> b instanceof ConsumeLiquid);
if(consumer == null) throw new RuntimeException("LiquidConverters must have a ConsumeLiquid.");
consumer.update = false;
}
@Override
@@ -44,20 +44,18 @@ public class LiquidConverter extends GenericCrafter{
@Override
public void updateTile(){
ConsumeLiquid cl = consumes.get(ConsumeType.liquid);
if(consValid()){
if(Mathf.chanceDelta(updateEffectChance)){
updateEffect.at(x + Mathf.range(size * 4f), y + Mathf.range(size * 4));
}
warmup = Mathf.lerpDelta(warmup, 1f, 0.02f);
float use = Math.min(cl.amount * edelta(), liquidCapacity - liquids.get(outputLiquid.liquid));
float ratio = outputLiquid.amount / cl.amount;
float use = Math.min(consumer.amount * edelta(), liquidCapacity - liquids.get(outputLiquid.liquid));
float ratio = outputLiquid.amount / consumer.amount;
liquids.remove(cl.liquid, Math.min(use, liquids.get(cl.liquid)));
liquids.remove(consumer.liquid, Math.min(use, liquids.get(consumer.liquid)));
progress += use / cl.amount;
progress += use / consumer.amount;
liquids.add(outputLiquid.liquid, use * ratio);
if(progress >= craftTime){
consume();

View File

@@ -18,6 +18,8 @@ import mindustry.world.meta.*;
* Extracts a random list of items from an input item and an input liquid.
*/
public class Separator extends Block{
protected @Nullable ConsumeItems consItems;
public ItemStack[] results;
public float craftTime;
@@ -43,6 +45,12 @@ public class Separator extends Block{
stats.add(Stat.productionTime, craftTime / 60f, StatUnit.seconds);
}
@Override
public void init(){
super.init();
consItems = findConsumer(c -> c instanceof ConsumeItems);
}
public class SeparatorBuild extends Building{
public float progress;
public float totalProgress;
@@ -63,9 +71,8 @@ public class Separator extends Block{
public boolean shouldConsume(){
int total = items.total();
//very inefficient way of allowing separators to ignore input buffer storage
if(consumes.has(ConsumeType.item) && consumes.get(ConsumeType.item) instanceof ConsumeItems){
ConsumeItems c = consumes.get(ConsumeType.item);
for(ItemStack stack : c.items){
if(consItems != null){
for(ItemStack stack : consItems.items){
total -= items.get(stack.item);
}
}
@@ -132,7 +139,7 @@ public class Separator extends Block{
@Override
public boolean canDump(Building to, Item item){
return !consumes.consumesItem(item);
return !consumesItem(item);
}
@Override

View File

@@ -47,7 +47,7 @@ public class SolidPump extends Pump{
@Override
public void setBars(){
super.setBars();
bars.add("efficiency", (SolidPumpBuild entity) -> new Bar(() -> Core.bundle.formatFloat("bar.pumpspeed",
addBar("efficiency", (SolidPumpBuild entity) -> new Bar(() -> Core.bundle.formatFloat("bar.pumpspeed",
entity.lastPump * 60, 1),
() -> Pal.ammo,
() -> entity.warmup * entity.efficiency()));

View File

@@ -54,7 +54,7 @@ public class WallCrafter extends Block{
public void setBars(){
super.setBars();
bars.add("drillspeed", (WallCrafterBuild e) ->
addBar("drillspeed", (WallCrafterBuild e) ->
new Bar(() -> Core.bundle.format("bar.drillspeed", Strings.fixed(e.lastEfficiency * 60 / drillTime, 2)), () -> Pal.ammo, () -> e.warmup));
}

View File

@@ -35,7 +35,7 @@ public class ItemSource extends Block{
@Override
public void setBars(){
super.setBars();
bars.remove("items");
removeBar("items");
}
@Override

View File

@@ -42,7 +42,7 @@ public class LiquidSource extends Block{
public void setBars(){
super.setBars();
bars.remove("liquid");
removeBar("liquid");
}
@Override

View File

@@ -19,7 +19,7 @@ public class LiquidVoid extends Block{
@Override
public void setBars(){
super.setBars();
bars.remove("liquid");
removeBar("liquid");
}
public class LiquidVoidBuild extends Building{

View File

@@ -7,7 +7,7 @@ public class PowerVoid extends PowerBlock{
public PowerVoid(String name){
super(name);
consumes.power(Float.MAX_VALUE);
consumePower(Float.MAX_VALUE);
envEnabled = Env.any;
enableDrawStatus = false;
}

View File

@@ -92,7 +92,7 @@ public class CoreBlock extends StorageBlock{
public void setBars(){
super.setBars();
bars.add("capacity", (CoreBuild e) -> new Bar(
addBar("capacity", (CoreBuild e) -> new Bar(
() -> Core.bundle.format("bar.capacity", UI.formatAmount(e.storageCapacity)),
() -> Pal.items,
() -> e.items.total() / ((float)e.storageCapacity * content.items().count(i -> i.unlockedNow()))

View File

@@ -54,7 +54,7 @@ public class Unloader extends Block{
@Override
public void setBars(){
super.setBars();
bars.remove("items");
removeBar("items");
}
public static class ContainerStat{

View File

@@ -1,143 +0,0 @@
package mindustry.world.blocks.units;
import arc.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.scene.style.*;
import arc.scene.ui.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
import arc.util.io.*;
import mindustry.*;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.entities.units.*;
import mindustry.game.EventType.*;
import mindustry.gen.*;
import mindustry.ui.*;
import mindustry.world.*;
import mindustry.world.meta.*;
public class CommandCenter extends Block{
public final int timerEffect = timers ++;
public TextureRegionDrawable[] commandRegions = new TextureRegionDrawable[UnitCommand.all.length];
public Color topColor = null, bottomColor = Color.valueOf("5e5e5e");
public Effect effect = Fx.commandSend;
public float effectSize = 150f;
public float forceRadius = 31f, forceStrength = 0.2f;
public CommandCenter(String name){
super(name);
flags = EnumSet.of(BlockFlag.rally);
update = true;
solid = true;
configurable = true;
drawDisabled = false;
logicConfigurable = true;
envEnabled = Env.any;
config(UnitCommand.class, (CommandBuild build, UnitCommand command) -> {
if(build.team.data().command != command){
build.team.data().command = command;
//do not spam effect
if(build.timer(timerEffect, 60f)){
effect.at(build, effectSize);
}
Events.fire(new CommandIssueEvent(build, command));
}
});
}
@Override
public void load(){
super.load();
if(Vars.ui != null){
for(UnitCommand cmd : UnitCommand.all){
commandRegions[cmd.ordinal()] = Vars.ui.getIcon("command" + Strings.capitalize(cmd.name()), "cancel");
}
}
}
@Override
public boolean configSenseable(){
return true;
}
public class CommandBuild extends Building{
@Override
public Object config(){
return team.data().command;
}
@Override
public void updateTile(){
super.updateTile();
//push away allied units
team.data().tree().intersect(x - forceRadius/2f, y - forceRadius/2f, forceRadius, forceRadius, u -> {
if(!u.isPlayer()){
float dst = dst(u);
float rs = forceRadius + u.hitSize/2f;
if(dst < rs){
u.vel.add(Tmp.v1.set(u).sub(x, y).setLength(1f - dst / rs).scl(forceStrength));
}
}
});
}
@Override
public void draw(){
super.draw();
float size = 6f;
Draw.color(bottomColor);
Draw.rect(commandRegions[team.data().command.ordinal()].getRegion(), x, y - 1, size, size);
Draw.color(topColor == null ? team.color : topColor);
Draw.rect(commandRegions[team.data().command.ordinal()].getRegion(), x, y, size, size);
Draw.color();
}
@Override
public void buildConfiguration(Table table){
ButtonGroup<ImageButton> group = new ButtonGroup<>();
Table buttons = new Table();
for(UnitCommand cmd : UnitCommand.all){
buttons.button(commandRegions[cmd.ordinal()], Styles.clearToggleTransi, () -> {
if(team.data().command != cmd) configure(cmd);
}).size(44).group(group).update(b -> b.setChecked(team.data().command == cmd));
}
table.add(buttons);
table.row();
table.label(() -> team.data().command.localized()).style(Styles.outlineLabel).center().growX().get().setAlignment(Align.center);
}
@Override
public boolean onConfigureTileTapped(Building other){
if(this == other){
deselect();
return false;
}
return true;
}
@Override
public void write(Writes write){
super.write(write);
write.b(team.data().command.ordinal());
}
@Override
public void read(Reads read, byte version){
super.read(read, version);
team.data().command = UnitCommand.all[read.b()];
}
}
}

View File

@@ -50,8 +50,8 @@ public class Reconstructor extends UnitBlock{
public void setBars(){
super.setBars();
bars.add("progress", (ReconstructorBuild entity) -> new Bar("bar.progress", Pal.ammo, entity::fraction));
bars.add("units", (ReconstructorBuild e) ->
addBar("progress", (ReconstructorBuild entity) -> new Bar("bar.progress", Pal.ammo, entity::fraction));
addBar("units", (ReconstructorBuild e) ->
new Bar(
() -> e.unit() == null ? "[lightgray]" + Iconc.cancel :
Core.bundle.format("bar.unitcap",
@@ -91,8 +91,10 @@ public class Reconstructor extends UnitBlock{
@Override
public void init(){
capacities = new int[Vars.content.items().size];
if(consumes.has(ConsumeType.item) && consumes.get(ConsumeType.item) instanceof ConsumeItems){
for(ItemStack stack : consumes.<ConsumeItems>get(ConsumeType.item).items){
ConsumeItems cons = findConsumer(c -> c instanceof ConsumeItems);
if(cons != null){
for(ItemStack stack : cons.items){
capacities[stack.item.id] = Math.max(capacities[stack.item.id], stack.amount * 2);
itemCapacity = Math.max(itemCapacity, stack.amount * 2);
}

View File

@@ -70,7 +70,7 @@ public class RepairPoint extends Block{
stats.add(Stat.repairSpeed, repairSpeed * 60f, StatUnit.perSecond);
if(acceptCoolant){
stats.add(Stat.booster, StatValues.strengthBoosters(coolantMultiplier, l -> consumes.liquidfilters.get(l.id)));
stats.add(Stat.booster, StatValues.strengthBoosters(coolantMultiplier, this::consumesLiquid));
}
}
@@ -78,10 +78,10 @@ public class RepairPoint extends Block{
public void init(){
if(acceptCoolant){
hasLiquids = true;
consumes.add(new ConsumeCoolant(coolantUse)).optional(true, true);
consume(new ConsumeCoolant(coolantUse)).optional(true, true);
}
consumes.powerCond(powerUse, (RepairPointBuild entity) -> entity.target != null);
consumePowerCond(powerUse, (RepairPointBuild entity) -> entity.target != null);
clipSize = Math.max(clipSize, (repairRadius + tilesize) * 2);
super.init();
}
@@ -172,8 +172,7 @@ public class RepairPoint extends Block{
public void updateTile(){
float multiplier = 1f;
if(acceptCoolant){
var liq = consumes.<ConsumeLiquidBase>get(ConsumeType.liquid);
multiplier = liq.valid(this) ? 1f + liquids.current().heatCapacity * coolantMultiplier : 1f;
multiplier = consOptionalValid() ? 1f + liquids.current().heatCapacity * coolantMultiplier : 1f;
}
if(target != null && (target.dead() || target.dst(this) - target.hitSize/2f > repairRadius || target.health() >= target.maxHealth())){

View File

@@ -39,6 +39,8 @@ public class UnitAssembler extends PayloadBlock{
public Seq<AssemblerUnitPlan> plans = new Seq<>(4);
protected @Nullable ConsumePayloadDynamic consPayload;
public UnitAssembler(String name){
super(name);
update = solid = true;
@@ -85,9 +87,9 @@ public class UnitAssembler extends PayloadBlock{
public void setBars(){
super.setBars();
bars.add("progress", (UnitAssemblerBuild e) -> new Bar("bar.progress", Pal.ammo, () -> e.progress));
addBar("progress", (UnitAssemblerBuild e) -> new Bar("bar.progress", Pal.ammo, () -> e.progress));
bars.add("units", (UnitAssemblerBuild e) ->
addBar("units", (UnitAssemblerBuild e) ->
new Bar(() ->
Core.bundle.format("bar.unitcap",
Fonts.getUnicodeStr(e.unit().name),
@@ -114,7 +116,7 @@ public class UnitAssembler extends PayloadBlock{
@Override
public void init(){
clipSize = Math.max(clipSize, (areaSize + size) * tilesize * 2);
consumes.add(new ConsumePayloadDynamic((UnitAssemblerBuild build) -> build.plan().requirements));
consume(consPayload = new ConsumePayloadDynamic((UnitAssemblerBuild build) -> build.plan().requirements));
super.init();
}
@@ -254,7 +256,7 @@ public class UnitAssembler extends PayloadBlock{
@Override
public boolean shouldConsume(){
//liquid is only consumed when building is being done
return enabled && !wasOccupied && Units.canCreate(team, plan().unit) && consumes.get(ConsumeType.payload).valid(this);
return enabled && !wasOccupied && Units.canCreate(team, plan().unit) && consPayload.valid(this);
}
@Override

View File

@@ -38,7 +38,7 @@ public class UnitCargoLoader extends Block{
public void setBars(){
super.setBars();
bars.add("units", (UnitTransportSourceBuild e) ->
addBar("units", (UnitTransportSourceBuild e) ->
new Bar(
() ->
Core.bundle.format("bar.unitcap",

View File

@@ -53,7 +53,7 @@ public class UnitFactory extends UnitBlock{
tile.progress = 0;
});
consumes.add(new ConsumeItemDynamic((UnitFactoryBuild e) -> e.currentPlan != -1 ? plans.get(e.currentPlan).requirements : ItemStack.empty));
consume(new ConsumeItemDynamic((UnitFactoryBuild e) -> e.currentPlan != -1 ? plans.get(e.currentPlan).requirements : ItemStack.empty));
}
@Override
@@ -72,9 +72,9 @@ public class UnitFactory extends UnitBlock{
@Override
public void setBars(){
super.setBars();
bars.add("progress", (UnitFactoryBuild e) -> new Bar("bar.progress", Pal.ammo, e::fraction));
addBar("progress", (UnitFactoryBuild e) -> new Bar("bar.progress", Pal.ammo, e::fraction));
bars.add("units", (UnitFactoryBuild e) ->
addBar("units", (UnitFactoryBuild e) ->
new Bar(
() -> e.unit() == null ? "[lightgray]" + Iconc.cancel :
Core.bundle.format("bar.unitcap",

View File

@@ -1,8 +1,8 @@
package mindustry.world.consumers;
import arc.scene.ui.layout.*;
import arc.struct.*;
import mindustry.gen.*;
import mindustry.world.*;
import mindustry.world.meta.*;
/** An abstract class that defines a type of resource that a block can consume. */
@@ -11,21 +11,15 @@ public abstract class Consume{
public boolean optional;
/** If true, this consumer will be displayed as a boost input. */
public boolean booster;
//TODO bad.
@Deprecated
public boolean update = true;
/**
* Apply a filter to items accepted.
* This should set all item IDs that are present in the filter to true.
* Apply extra filters to a block.
*/
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 void apply(Block block){
}
@@ -39,25 +33,12 @@ public abstract class Consume{
return optional(true, true);
}
@Deprecated
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 void build(Building build, Table table){}
/** Called when a consumption is triggered manually. */

View File

@@ -5,6 +5,7 @@ import arc.scene.ui.layout.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
public class ConsumeItemDynamic extends Consume{
public final Func<Building, ItemStack[]> items;
@@ -15,8 +16,9 @@ public class ConsumeItemDynamic extends Consume{
}
@Override
public ConsumeType type(){
return ConsumeType.item;
public void apply(Block block){
block.hasItems = true;
block.acceptsItems = true;
}
@Override

View File

@@ -2,10 +2,10 @@ package mindustry.world.consumers;
import arc.func.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
import mindustry.world.meta.*;
import static mindustry.Vars.*;
@@ -18,13 +18,10 @@ public class ConsumeItemFilter extends Consume{
}
@Override
public void applyItemFilter(Bits arr){
content.items().each(filter, item -> arr.set(item.id));
}
@Override
public ConsumeType type(){
return ConsumeType.item;
public void apply(Block block){
block.hasItems = true;
block.acceptsItems = true;
content.items().each(filter, item -> block.itemFilter[item.id] = true);
}
@Override

View File

@@ -1,10 +1,10 @@
package mindustry.world.consumers;
import arc.scene.ui.layout.*;
import arc.struct.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
import mindustry.world.meta.*;
public class ConsumeItems extends Consume{
@@ -20,17 +20,14 @@ public class ConsumeItems extends Consume{
}
@Override
public void applyItemFilter(Bits filter){
public void apply(Block block){
block.hasItems = true;
block.acceptsItems = true;
for(var stack : items){
filter.set(stack.item.id);
block.itemFilter[stack.item.id] = true;
}
}
@Override
public ConsumeType type(){
return ConsumeType.item;
}
@Override
public void build(Building build, Table table){
table.table(c -> {

View File

@@ -1,10 +1,10 @@
package mindustry.world.consumers;
import arc.scene.ui.layout.*;
import arc.struct.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
import mindustry.world.meta.*;
import static mindustry.Vars.*;
@@ -23,8 +23,9 @@ public class ConsumeLiquid extends ConsumeLiquidBase{
}
@Override
public void applyLiquidFilter(Bits filter){
filter.set(liquid.id);
public void apply(Block block){
super.apply(block);
block.liquidFilter[liquid.id] = true;
}
@Override

View File

@@ -1,6 +1,7 @@
package mindustry.world.consumers;
import mindustry.gen.*;
import mindustry.world.*;
public abstract class ConsumeLiquidBase extends Consume{
/** amount used per frame */
@@ -13,8 +14,8 @@ public abstract class ConsumeLiquidBase extends Consume{
public ConsumeLiquidBase(){}
@Override
public ConsumeType type(){
return ConsumeType.liquid;
public void apply(Block block){
block.hasLiquids = true;
}
protected float use(Building entity){

View File

@@ -6,6 +6,7 @@ import arc.struct.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
import mindustry.world.meta.*;
import static mindustry.Vars.*;
@@ -23,8 +24,9 @@ public class ConsumeLiquidFilter extends ConsumeLiquidBase{
}
@Override
public void applyLiquidFilter(Bits arr){
content.liquids().each(filter, item -> arr.set(item.id));
public void apply(Block block){
block.hasLiquids = true;
content.liquids().each(filter, item -> block.liquidFilter[item.id] = true);
}
@Override

View File

@@ -1,11 +1,11 @@
package mindustry.world.consumers;
import arc.scene.ui.layout.*;
import arc.struct.*;
import mindustry.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
import mindustry.world.meta.*;
//TODO test!
@@ -22,17 +22,13 @@ public class ConsumeLiquids extends Consume{
}
@Override
public void applyLiquidFilter(Bits filter){
public void apply(Block block){
block.hasLiquids = true;
for(var stack : liquids){
filter.set(stack.liquid.id);
block.itemFilter[stack.liquid.id] = true;
}
}
@Override
public ConsumeType type(){
return ConsumeType.liquid;
}
@Override
public void build(Building build, Table table){
table.table(c -> {

View File

@@ -60,9 +60,4 @@ public class ConsumePayloadDynamic extends Consume{
}
}).left();
}
@Override
public ConsumeType type(){
return ConsumeType.payload;
}
}

View File

@@ -61,9 +61,4 @@ public class ConsumePayloadFilter extends Consume{
table.add(image).size(8 * 4);
}
@Override
public ConsumeType type(){
return ConsumeType.payload;
}
}

View File

@@ -49,9 +49,4 @@ public class ConsumePayloads extends Consume{
}
}).left();
}
@Override
public ConsumeType type(){
return ConsumeType.payload;
}
}

View File

@@ -1,8 +1,8 @@
package mindustry.world.consumers;
import arc.math.*;
import arc.scene.ui.layout.*;
import mindustry.gen.*;
import mindustry.world.*;
import mindustry.world.meta.*;
/** Consumer class for blocks which consume power while being connected to a power graph. */
@@ -25,8 +25,9 @@ public class ConsumePower extends Consume{
}
@Override
public ConsumeType type(){
return ConsumeType.power;
public void apply(Block block){
block.hasPower = true;
block.consPower = this;
}
@Override

View File

@@ -1,14 +1,13 @@
package mindustry.world.blocks.power;
package mindustry.world.consumers;
import arc.func.*;
import mindustry.gen.*;
import mindustry.world.consumers.*;
/** A power consumer that only activates sometimes. */
public class ConditionalConsumePower extends ConsumePower{
public class ConsumePowerCondition extends ConsumePower{
private final Boolf<Building> consume;
public ConditionalConsumePower(float usage, Boolf<Building> consume){
public ConsumePowerCondition(float usage, Boolf<Building> consume){
super(usage, 0, false);
this.consume = consume;
}

View File

@@ -1,14 +1,13 @@
package mindustry.world.blocks.power;
package mindustry.world.consumers;
import arc.func.*;
import mindustry.gen.*;
import mindustry.world.consumers.*;
/** A power consumer that uses a dynamic amount of power. */
public class DynamicConsumePower extends ConsumePower{
public class ConsumePowerDynamic extends ConsumePower{
private final Floatf<Building> usage;
public DynamicConsumePower(Floatf<Building> usage){
public ConsumePowerDynamic(Floatf<Building> usage){
super(0, 0, false);
this.usage = usage;
}

View File

@@ -1,10 +0,0 @@
package mindustry.world.consumers;
public enum ConsumeType{
item,
power,
liquid,
payload;
public static final ConsumeType[] all = values();
}

View File

@@ -1,141 +0,0 @@
package mindustry.world.consumers;
import arc.func.*;
import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.world.blocks.power.*;
import mindustry.world.meta.*;
public class Consumers{
private Consume[] map = new Consume[ConsumeType.all.length];
public Consume[] all = {}, optionals = {};
public final Bits itemFilters = new Bits(Vars.content.items().size);
public final Bits liquidfilters = new Bits(Vars.content.liquids().size);
public boolean consumesItem(Item item){
return itemFilters.get(item.id);
}
public boolean consumesLiquid(Liquid liq){
return liquidfilters.get(liq.id);
}
public boolean any(){
return all.length > 0;
}
public void each(Cons<Consume> c){
for(var cons : map){
if(cons != null){
c.get(cons);
}
}
}
public void init(){
all = Structs.filter(Consume.class, map, m -> m != null);
optionals = Structs.filter(Consume.class, map, m -> m != null && m.isOptional());
for(Consume cons : all){
cons.applyItemFilter(itemFilters);
cons.applyLiquidFilter(liquidfilters);
}
}
public ConsumePower getPower(){
return get(ConsumeType.power);
}
public ConsumeItems getItem(){
return get(ConsumeType.item);
}
public boolean hasPower(){
return has(ConsumeType.power);
}
public ConsumeLiquid liquid(Liquid liquid, float amount){
return add(new ConsumeLiquid(liquid, amount));
}
public ConsumeLiquids liquids(LiquidStack... stacks){
return add(new ConsumeLiquids(stacks));
}
/**
* 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 <T extends Building> ConsumePower powerCond(float usage, Boolf<T> cons){
return add(new ConditionalConsumePower(usage, (Boolf<Building>)cons));
}
/** Creates a consumer that consumes a dynamic amount of power. */
public <T extends Building> ConsumePower powerDynamic(Floatf<T> usage){
return add(new DynamicConsumePower((Floatf<Building>)usage));
}
/**
* 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 @Nullable <T extends Consume>T getOrNull(ConsumeType type){
return (T)map[type.ordinal()];
}
public void display(Stats stats){
for(Consume c : map){
if(c != null){
c.display(stats);
}
}
}
}

View File

@@ -2,14 +2,15 @@ package mindustry.world.draw;
import arc.*;
import arc.graphics.g2d.*;
import arc.util.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.blocks.production.*;
import mindustry.world.consumers.*;
public class DrawLiquid extends DrawBlock{
public @Nullable Liquid liquidDrawn;
public TextureRegion inLiquid, liquid, top;
public boolean useOutputSprite = false;
@@ -25,11 +26,10 @@ public class DrawLiquid extends DrawBlock{
Draw.rect(build.block.region, build.x, build.y);
GenericCrafter type = (GenericCrafter)build.block;
if((inLiquid.found() || useOutputSprite) && type.consumes.has(ConsumeType.liquid)){
Liquid input = type.consumes.<ConsumeLiquid>get(ConsumeType.liquid).liquid;
if((inLiquid.found() || useOutputSprite) && liquidDrawn != null){
Drawf.liquid(useOutputSprite ? liquid : inLiquid, build.x, build.y,
build.liquids.get(input) / type.liquidCapacity,
input.color
build.liquids.get(liquidDrawn) / type.liquidCapacity,
liquidDrawn.color
);
}

View File

@@ -2,14 +2,15 @@ package mindustry.world.draw;
import arc.*;
import arc.graphics.g2d.*;
import arc.util.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.blocks.production.*;
import mindustry.world.consumers.*;
public class DrawMixer extends DrawBlock{
public @Nullable Liquid liquidDrawn;
public TextureRegion inLiquid, liquid, top, bottom;
public boolean useOutputSprite;
@@ -26,11 +27,10 @@ public class DrawMixer extends DrawBlock{
float rotation = build.block.rotate ? build.rotdeg() : 0;
Draw.rect(bottom, build.x, build.y, rotation);
if((inLiquid.found() || useOutputSprite) && build.block.consumes.has(ConsumeType.liquid)){
Liquid input = build.block.consumes.<ConsumeLiquid>get(ConsumeType.liquid).liquid;
if((inLiquid.found() || useOutputSprite) && liquidDrawn != null){
Drawf.liquid(useOutputSprite ? liquid : inLiquid, build.x, build.y,
build.liquids.get(input) / build.block.liquidCapacity,
input.color
build.liquids.get(liquidDrawn) / build.block.liquidCapacity,
liquidDrawn.color
);
}

View File

@@ -1,22 +0,0 @@
package mindustry.world.meta;
import arc.func.*;
import arc.struct.*;
import mindustry.gen.*;
import mindustry.ui.*;
public class BlockBars{
private OrderedMap<String, Func<Building, Bar>> bars = new OrderedMap<>();
public <T extends Building> void add(String name, Func<T, Bar> sup){
bars.put(name, (Func<Building, Bar>)sup);
}
public void remove(String name){
bars.remove(name);
}
public Iterable<Func<Building, Bar>> list(){
return bars.values();
}
}

View File

@@ -26,7 +26,6 @@ public enum Stat{
mineSpeed,
mineTier,
payloadCapacity,
commandLimit,
baseDeflectChance,
lightningChance,
lightningDamage,