diff --git a/annotations/src/main/java/mindustry/annotations/misc/LogicStatementProcessor.java b/annotations/src/main/java/mindustry/annotations/misc/LogicStatementProcessor.java index bf5f25b682..04240e4884 100644 --- a/annotations/src/main/java/mindustry/annotations/misc/LogicStatementProcessor.java +++ b/annotations/src/main/java/mindustry/annotations/misc/LogicStatementProcessor.java @@ -64,9 +64,9 @@ public class LogicStatementProcessor extends BaseProcessor{ reader.addStatement("$T result = new $T()", c.mirror(), c.mirror()); - for(int i = 0; i < fields.size; i++){ - Svar field = fields.get(i); + int index = 0; + for(Svar field : fields){ if(field.is(Modifier.TRANSIENT)) continue; writer.addStatement("out.append(\" \")"); @@ -74,12 +74,14 @@ public class LogicStatementProcessor extends BaseProcessor{ //reading primitives, strings and enums is supported; nothing else is reader.addStatement("result.$L = $L(tokens[$L])", - field.name(), - field.mirror().toString().equals("java.lang.String") ? - "" : (field.tname().isPrimitive() ? field.tname().box().toString() : - field.mirror().toString()) + ".valueOf", //if it's not a string, it must have a valueOf method - i + 1 + field.name(), + field.mirror().toString().equals("java.lang.String") ? + "" : (field.tname().isPrimitive() ? field.tname().box().toString() : + field.mirror().toString()) + ".valueOf", //if it's not a string, it must have a valueOf method + index + 1 ); + + index ++; } reader.addStatement("return result"); diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index f2a3371f5a..b3aebb9adc 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -18,11 +18,13 @@ import arc.util.io.*; import mindustry.annotations.Annotations.*; import mindustry.audio.*; import mindustry.content.*; +import mindustry.ctype.*; import mindustry.entities.*; import mindustry.game.EventType.*; import mindustry.game.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.logic.*; import mindustry.type.*; import mindustry.ui.*; import mindustry.world.*; @@ -37,7 +39,7 @@ import static mindustry.Vars.*; @EntityDef(value = {Buildingc.class}, isFinal = false, genio = false, serialize = false) @Component(base = true) -abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, QuadTreeObject, Displayable{ +abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, QuadTreeObject, Displayable, Senseable{ //region vars and initialization static final float timeToSleep = 60f * 1; static final ObjectSet tmpTiles = new ObjectSet<>(); @@ -1165,6 +1167,26 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, } } + @Override + public double sense(LSensor sensor){ + if(sensor == LSensor.health) return health; + if(sensor == LSensor.efficiency) return efficiency(); + if(sensor == LSensor.totalItems && items != null) return items.total(); + if(sensor == LSensor.totalLiquids && liquids != null) return liquids.total(); + if(sensor == LSensor.totalPower && power != null) return power.status * (block.consumes.getPower().buffered ? block.consumes.getPower().capacity : 1f); + if(sensor == LSensor.powerNetIn && power != null) return power.graph.getPowerProduced(); + if(sensor == LSensor.powerNetOut && power != null) return power.graph.getPowerNeeded(); + if(sensor == LSensor.powerNetStored && power != null) return power.graph.getLastPowerStored(); + return 0; + } + + @Override + public double sense(Content content){ + if(content instanceof Item && items != null) return items.get((Item)content); + if(content instanceof Liquid && liquids != null) return liquids.get((Liquid)content); + return 0; + } + @Override public void remove(){ if(sound != null){ diff --git a/core/src/mindustry/entities/comp/UnitComp.java b/core/src/mindustry/entities/comp/UnitComp.java index 2ee1699194..c10880a813 100644 --- a/core/src/mindustry/entities/comp/UnitComp.java +++ b/core/src/mindustry/entities/comp/UnitComp.java @@ -9,12 +9,14 @@ import arc.util.ArcAnnotate.*; import arc.util.*; import mindustry.annotations.Annotations.*; import mindustry.content.*; +import mindustry.ctype.*; import mindustry.entities.*; import mindustry.entities.units.*; import mindustry.game.EventType.*; import mindustry.game.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.logic.*; import mindustry.type.*; import mindustry.ui.*; import mindustry.world.*; @@ -23,7 +25,7 @@ import mindustry.world.blocks.environment.*; import static mindustry.Vars.*; @Component(base = true) -abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, Itemsc, Rotc, Unitc, Weaponsc, Drawc, Boundedc, Syncc, Shieldc, Displayable{ +abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, Itemsc, Rotc, Unitc, Weaponsc, Drawc, Boundedc, Syncc, Shieldc, Displayable, Senseable{ @Import boolean hovering; @Import float x, y, rotation, elevation, maxHealth, drag, armor, hitSize, health; @@ -67,6 +69,19 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I return type.region.getWidth() * 2f; } + @Override + public double sense(LSensor sensor){ + if(sensor == LSensor.totalItems) return stack().amount; + if(sensor == LSensor.health) return health; + return 0; + } + + @Override + public double sense(Content content){ + if(content == stack().item) return stack().amount; + return 0; + } + @Override public int itemCapacity(){ return type.itemCapacity; diff --git a/core/src/mindustry/io/TypeIO.java b/core/src/mindustry/io/TypeIO.java index 62c5e74966..e7291c7df8 100644 --- a/core/src/mindustry/io/TypeIO.java +++ b/core/src/mindustry/io/TypeIO.java @@ -16,6 +16,7 @@ import mindustry.entities.bullet.*; import mindustry.entities.units.*; import mindustry.game.*; import mindustry.gen.*; +import mindustry.logic.*; import mindustry.net.Administration.*; import mindustry.net.Packets.*; import mindustry.type.*; @@ -85,6 +86,9 @@ public class TypeIO{ }else if(object instanceof Building){ write.b((byte)12); write.i(((Building)object).pos()); + }else if(object instanceof LSensor){ + write.b((byte)13); + write.s(((LSensor)object).ordinal()); }else{ throw new IllegalArgumentException("Unknown object type: " + object.getClass()); } @@ -107,6 +111,7 @@ public class TypeIO{ case 10: return read.bool(); case 11: return read.d(); case 12: return world.build(read.i()); + case 13: return LSensor.all[read.s()]; default: throw new IllegalArgumentException("Unknown object type: " + type); } } diff --git a/core/src/mindustry/logic/LAssembler.java b/core/src/mindustry/logic/LAssembler.java index 2d37d0518f..85528a153e 100644 --- a/core/src/mindustry/logic/LAssembler.java +++ b/core/src/mindustry/logic/LAssembler.java @@ -12,14 +12,14 @@ import mindustry.type.*; public class LAssembler{ public static ObjectMap> customParsers = new ObjectMap<>(); - private transient int lastVar; + private int lastVar; /** Maps names to variable IDs. */ ObjectMap vars = new ObjectMap<>(); /** All instructions to be executed. */ LInstruction[] instructions; public LAssembler(){ - putVar("@counter"); + putVar("@counter").value = 0; putConst("@time", 0); //add default constants @@ -36,6 +36,12 @@ public class LAssembler{ for(Liquid liquid : Vars.content.liquids()){ putConst("@" + liquid.name, liquid); } + + //store sensor constants + + for(LSensor sensor : LSensor.all){ + putConst("@" + sensor.name(), sensor); + } } public static LAssembler assemble(String data){ diff --git a/core/src/mindustry/logic/LExecutor.java b/core/src/mindustry/logic/LExecutor.java index 04fdb5141a..1bc4091581 100644 --- a/core/src/mindustry/logic/LExecutor.java +++ b/core/src/mindustry/logic/LExecutor.java @@ -3,8 +3,8 @@ package mindustry.logic; import arc.util.ArcAnnotate.*; import arc.util.*; import mindustry.*; +import mindustry.ctype.*; import mindustry.gen.*; -import mindustry.type.*; public class LExecutor{ //special variables @@ -192,16 +192,16 @@ public class LExecutor{ @Override public void run(LExecutor exec){ - Building build = exec.building(from); + Object target = exec.obj(from); Object sense = exec.obj(type); double output = 0; - if(build != null){ - if(sense instanceof Item && build.items != null){ - output = build.items.get((Item)sense); - }else if(sense instanceof Liquid && build.liquids != null){ - output = build.liquids.get((Liquid)sense); + if(target instanceof Senseable){ + if(sense instanceof Content){ + output = ((Senseable)target).sense(((Content)sense)); + }else if(sense instanceof LSensor){ + output = ((Senseable)target).sense(((LSensor)sense)); } } @@ -285,7 +285,7 @@ public class LExecutor{ //this should avoid any garbage allocation Var v = exec.vars[value]; - if(v.isobj){ + if(v.isobj && value != 0){ if(v.objval instanceof String){ b.handleString(v.objval); }else if(v.objval == null){ diff --git a/core/src/mindustry/logic/LSensor.java b/core/src/mindustry/logic/LSensor.java new file mode 100644 index 0000000000..2551ad1254 --- /dev/null +++ b/core/src/mindustry/logic/LSensor.java @@ -0,0 +1,15 @@ +package mindustry.logic; + +public enum LSensor{ + totalItems, + totalLiquids, + totalPower, + powerNetStored, + powerNetIn, + powerNetOut, + health, + heat, + efficiency; + + public static final LSensor[] all = values(); +} diff --git a/core/src/mindustry/logic/LStatement.java b/core/src/mindustry/logic/LStatement.java index 394c31760f..b2d38f35f2 100644 --- a/core/src/mindustry/logic/LStatement.java +++ b/core/src/mindustry/logic/LStatement.java @@ -1,10 +1,12 @@ package mindustry.logic; +import arc.func.*; import arc.scene.ui.layout.*; import arc.util.ArcAnnotate.*; import mindustry.gen.*; import mindustry.logic.LCanvas.*; import mindustry.logic.LExecutor.*; +import mindustry.ui.*; /** * A statement is an intermediate representation of an instruction, to be used mostly in UI. @@ -16,6 +18,11 @@ public abstract class LStatement{ public abstract LCategory category(); public abstract LInstruction build(LAssembler builder); + protected void field(Table table, String value, Cons setter){ + table.field(value, Styles.nodeField, setter) + .size(130f, 40f).pad(2f).color(table.color); + } + public void write(StringBuilder builder){ LogicIO.write(this,builder); } diff --git a/core/src/mindustry/logic/LStatements.java b/core/src/mindustry/logic/LStatements.java index c729eda322..2f439a9ed3 100644 --- a/core/src/mindustry/logic/LStatements.java +++ b/core/src/mindustry/logic/LStatements.java @@ -3,7 +3,6 @@ package mindustry.logic; import arc.graphics.*; import arc.scene.ui.*; import arc.scene.ui.layout.*; -import arc.util.*; import mindustry.annotations.Annotations.*; import mindustry.logic.LCanvas.*; import mindustry.logic.LExecutor.*; @@ -18,15 +17,11 @@ public class LStatements{ @Override public void build(Table table){ - Log.info("mem:: "); - - table.field(to, Styles.nodeField, str -> to = str) - .size(100f, 40f).pad(2f).color(table.color); + field(table, to, str -> to = str); table.add(" = "); - table.field(from, Styles.nodeField, str -> from = str) - .size(100f, 40f).pad(2f).color(table.color); + field(table, from, str -> from = str); } @Override @@ -47,13 +42,11 @@ public class LStatements{ @Override public void build(Table table){ - table.field(to, Styles.nodeField, str -> to = str) - .size(100f, 40f).pad(2f).color(table.color); + field(table, to, str -> to = str); table.add(" = mem:: "); - table.field(from, Styles.nodeField, str -> from = str) - .size(100f, 40f).pad(2f).color(table.color); + field(table, from, str -> from = str); } @Override @@ -74,18 +67,17 @@ public class LStatements{ @Override public void build(Table table){ - table.field(to, Styles.nodeField, str -> to = str) - .size(100f, 40f).pad(2f).color(table.color); + field(table, to, str -> to = str); table.add(" = "); - table.field(type, Styles.nodeField, str -> type = str) - .size(100f, 40f).pad(2f).color(table.color); + table.row(); + + field(table, type, str -> type = str); table.add(" in "); - table.field(from, Styles.nodeField, str -> from = str) - .size(100f, 40f).pad(2f).color(table.color); + field(table, from, str -> from = str); } @Override @@ -106,13 +98,11 @@ public class LStatements{ @Override public void build(Table table){ - table.field(to, Styles.nodeField, str -> to = str) - .size(100f, 40f).pad(2f).color(table.color); + field(table, to, str -> to = str); table.add(" = "); - table.field(from, Styles.nodeField, str -> from = str) - .size(100f, 40f).pad(2f).color(table.color); + field(table, from, str -> from = str); } @Override @@ -133,13 +123,11 @@ public class LStatements{ @Override public void build(Table table){ - table.field(target, Styles.nodeField, str -> target = str) - .size(100f, 40f).pad(2f).color(table.color); + field(table, target, str -> target = str); table.add(" -> "); - table.field(value, Styles.nodeField, str -> value = str) - .size(100f, 40f).pad(2f).color(table.color); + field(table, value, str -> value = str); } @Override @@ -160,14 +148,13 @@ public class LStatements{ @Override public void build(Table table){ - table.field(dest, Styles.nodeField, str -> dest = str) - .size(100f, 40f).pad(2f).color(table.color); + field(table, dest, str -> dest = str); table.add(" = "); - table.field(a, Styles.nodeField, str -> a = str) - .size(90f, 40f).pad(2f).color(table.color); + table.row(); + field(table, a, str -> a = str); TextButton[] button = {null}; button[0] = table.button(op.symbol, Styles.cleart, () -> { @@ -175,8 +162,7 @@ public class LStatements{ button[0].setText(op.symbol); }).size(50f, 30f).pad(4f).get(); - table.field(b, Styles.nodeField, str -> b = str) - .size(90f, 40f).pad(2f).color(table.color); + field(table, b, str -> b = str); } @Override @@ -215,13 +201,11 @@ public class LStatements{ @Override public void build(Table table){ - table.field(value, Styles.nodeField, str -> value = str) - .size(100f, 40f).pad(2f).color(table.color); + field(table, value, str -> value = str); table.add(" to "); - table.field(target, Styles.nodeField, str -> target = str) - .size(100f, 40f).pad(2f).color(table.color); + field(table, target, str -> target = str); } @Override @@ -245,8 +229,8 @@ public class LStatements{ @Override public void build(Table table){ table.add("if ").padLeft(6); - table.field(condition, Styles.nodeField, str -> condition = str) - .size(100f, 40f).pad(2f).color(table.color); + field(table, condition, str -> condition = str); + table.add().growX(); table.add(new JumpButton(Color.white, () -> dest, s -> dest = s)).size(30).right().padRight(-17); } diff --git a/core/src/mindustry/logic/Senseable.java b/core/src/mindustry/logic/Senseable.java new file mode 100644 index 0000000000..b07a4d9363 --- /dev/null +++ b/core/src/mindustry/logic/Senseable.java @@ -0,0 +1,8 @@ +package mindustry.logic; + +import mindustry.ctype.*; + +public interface Senseable{ + double sense(LSensor sensor); + double sense(Content content); +} diff --git a/core/src/mindustry/world/blocks/distribution/Router.java b/core/src/mindustry/world/blocks/distribution/Router.java index 15bd106169..0bff2c5377 100644 --- a/core/src/mindustry/world/blocks/distribution/Router.java +++ b/core/src/mindustry/world/blocks/distribution/Router.java @@ -17,6 +17,7 @@ public class Router extends Block{ itemCapacity = 1; group = BlockGroup.transportation; unloadable = false; + noUpdateDisabled = true; } public class RouterEntity extends Building{ diff --git a/core/src/mindustry/world/blocks/distribution/Sorter.java b/core/src/mindustry/world/blocks/distribution/Sorter.java index f080f67f8c..a3db38f56b 100644 --- a/core/src/mindustry/world/blocks/distribution/Sorter.java +++ b/core/src/mindustry/world/blocks/distribution/Sorter.java @@ -96,7 +96,7 @@ public class Sorter extends Block{ if(dir == -1) return null; Building to; - if((item == sortItem) != invert){ + if(((item == sortItem) != invert) == enabled){ //prevent 3-chains if(isSame(source) && isSame(nearby(dir))){ return null; diff --git a/core/src/mindustry/world/blocks/power/NuclearReactor.java b/core/src/mindustry/world/blocks/power/NuclearReactor.java index 231525cd4d..b0640e12d3 100644 --- a/core/src/mindustry/world/blocks/power/NuclearReactor.java +++ b/core/src/mindustry/world/blocks/power/NuclearReactor.java @@ -13,6 +13,7 @@ import mindustry.entities.*; import mindustry.game.EventType.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.logic.*; import mindustry.type.*; import mindustry.ui.*; import mindustry.world.consumers.*; @@ -107,6 +108,12 @@ public class NuclearReactor extends PowerGenerator{ } } + @Override + public double sense(LSensor sensor){ + if(sensor == LSensor.heat) return heat; + return super.sense(sensor); + } + @Override public void onDestroyed(){ super.onDestroyed(); diff --git a/core/src/mindustry/world/blocks/power/PowerDiode.java b/core/src/mindustry/world/blocks/power/PowerDiode.java index 8ab740a4d8..5ad5226151 100644 --- a/core/src/mindustry/world/blocks/power/PowerDiode.java +++ b/core/src/mindustry/world/blocks/power/PowerDiode.java @@ -39,7 +39,7 @@ public class PowerDiode extends Block{ // battery % of the graph on either side, defaults to zero public float bar(Building tile){ - return (tile != null && tile.block().hasPower) ? tile.power.graph.getBatteryStored() / tile.power.graph.getTotalBatteryCapacity() : 0f; + return (tile != null && tile.block().hasPower) ? tile.power.graph.getLastPowerStored() / tile.power.graph.getTotalBatteryCapacity() : 0f; } public class PowerDiodeEntity extends Building{ diff --git a/core/src/mindustry/world/blocks/power/PowerGraph.java b/core/src/mindustry/world/blocks/power/PowerGraph.java index 8277f7e19f..dd197f313b 100644 --- a/core/src/mindustry/world/blocks/power/PowerGraph.java +++ b/core/src/mindustry/world/blocks/power/PowerGraph.java @@ -19,7 +19,7 @@ public class PowerGraph{ private final ObjectSet all = new ObjectSet<>(); private final WindowedMean powerBalance = new WindowedMean(60); - private float lastPowerProduced, lastPowerNeeded, lastUsageFraction; + private float lastPowerProduced, lastPowerNeeded, lastUsageFraction, lastPowerStored; private long lastFrameUpdated = -1; private final int graphID; @@ -45,6 +45,10 @@ public class PowerGraph{ return lastPowerProduced; } + public float getLastPowerStored(){ + return lastPowerStored; + } + public float getSatisfaction(){ if(Mathf.zero(lastPowerProduced)){ return 0f; @@ -196,6 +200,7 @@ public class PowerGraph{ lastPowerNeeded = powerNeeded; lastPowerProduced = powerProduced; + lastPowerStored = getBatteryStored(); powerBalance.add((lastPowerProduced - lastPowerNeeded) / Time.delta); diff --git a/core/src/mindustry/world/blocks/power/PowerNode.java b/core/src/mindustry/world/blocks/power/PowerNode.java index b9698b7813..5fc011cb05 100644 --- a/core/src/mindustry/world/blocks/power/PowerNode.java +++ b/core/src/mindustry/world/blocks/power/PowerNode.java @@ -109,9 +109,9 @@ public class PowerNode extends PowerBlock{ bars.add("batteries", entity -> new Bar(() -> Core.bundle.format("bar.powerstored", - (UI.formatAmount((int)entity.power.graph.getBatteryStored())), UI.formatAmount((int)entity.power.graph.getTotalBatteryCapacity())), + (UI.formatAmount((int)entity.power.graph.getLastPowerStored())), UI.formatAmount((int)entity.power.graph.getTotalBatteryCapacity())), () -> Pal.powerBar, - () -> Mathf.clamp(entity.power.graph.getBatteryStored() / entity.power.graph.getTotalBatteryCapacity()))); + () -> Mathf.clamp(entity.power.graph.getLastPowerStored() / entity.power.graph.getTotalBatteryCapacity()))); } @Override