mirror of
https://github.com/Anuken/Mindustry.git
synced 2026-01-25 22:12:16 -08:00
Many various logic changes
This commit is contained in:
parent
b28e7de1db
commit
ea8dccdfb2
16 changed files with 384 additions and 182 deletions
|
|
@ -39,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, Senseable{
|
||||
abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, QuadTreeObject, Displayable, Senseable, Controllable{
|
||||
//region vars and initialization
|
||||
static final float timeToSleep = 60f * 1;
|
||||
static final ObjectSet<Building> tmpTiles = new ObjectSet<>();
|
||||
|
|
@ -1168,19 +1168,20 @@ 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.itemCapacity) return block.itemCapacity;
|
||||
if(sensor == LSensor.liquidCapacity) return block.liquidCapacity;
|
||||
if(sensor == LSensor.powerCapacity) return block.consumes.hasPower() ? block.consumes.getPower().capacity : 0f;
|
||||
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();
|
||||
if(sensor == LSensor.powerNetCapacity && power != null) return power.graph.getBatteryCapacity();
|
||||
public double sense(LAccess sensor){
|
||||
if(sensor == LAccess.health) return health;
|
||||
if(sensor == LAccess.efficiency) return efficiency();
|
||||
if(sensor == LAccess.rotation) return rotation;
|
||||
if(sensor == LAccess.totalItems && items != null) return items.total();
|
||||
if(sensor == LAccess.totalLiquids && liquids != null) return liquids.total();
|
||||
if(sensor == LAccess.totalPower && power != null) return power.status * (block.consumes.getPower().buffered ? block.consumes.getPower().capacity : 1f);
|
||||
if(sensor == LAccess.itemCapacity) return block.itemCapacity;
|
||||
if(sensor == LAccess.liquidCapacity) return block.liquidCapacity;
|
||||
if(sensor == LAccess.powerCapacity) return block.consumes.hasPower() ? block.consumes.getPower().capacity : 0f;
|
||||
if(sensor == LAccess.powerNetIn && power != null) return power.graph.getPowerProduced();
|
||||
if(sensor == LAccess.powerNetOut && power != null) return power.graph.getPowerNeeded();
|
||||
if(sensor == LAccess.powerNetStored && power != null) return power.graph.getLastPowerStored();
|
||||
if(sensor == LAccess.powerNetCapacity && power != null) return power.graph.getBatteryCapacity();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1191,6 +1192,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void control(LAccess type, double p1, double p2, double p3, double p4){
|
||||
if(type == LAccess.enabled){
|
||||
enabled = !Mathf.zero((float)p1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(){
|
||||
if(sound != null){
|
||||
|
|
|
|||
|
|
@ -70,9 +70,9 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||
}
|
||||
|
||||
@Override
|
||||
public double sense(LSensor sensor){
|
||||
if(sensor == LSensor.totalItems) return stack().amount;
|
||||
if(sensor == LSensor.health) return health;
|
||||
public double sense(LAccess sensor){
|
||||
if(sensor == LAccess.totalItems) return stack().amount;
|
||||
if(sensor == LAccess.health) return health;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,9 +86,9 @@ public class TypeIO{
|
|||
}else if(object instanceof Building){
|
||||
write.b((byte)12);
|
||||
write.i(((Building)object).pos());
|
||||
}else if(object instanceof LSensor){
|
||||
}else if(object instanceof LAccess){
|
||||
write.b((byte)13);
|
||||
write.s(((LSensor)object).ordinal());
|
||||
write.s(((LAccess)object).ordinal());
|
||||
}else{
|
||||
throw new IllegalArgumentException("Unknown object type: " + object.getClass());
|
||||
}
|
||||
|
|
@ -111,7 +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()];
|
||||
case 13: return LAccess.all[read.s()];
|
||||
default: throw new IllegalArgumentException("Unknown object type: " + type);
|
||||
}
|
||||
}
|
||||
|
|
@ -303,7 +303,7 @@ public class TypeIO{
|
|||
//make sure player exists
|
||||
if(player == null) return prev;
|
||||
return player;
|
||||
}else if(type == 1){
|
||||
}else if(type == 1){ //formation controller
|
||||
int id = read.i();
|
||||
return prev instanceof FormationAI ? prev : new FormationAI(Groups.unit.getByID(id), null);
|
||||
}else{
|
||||
|
|
|
|||
6
core/src/mindustry/logic/Controllable.java
Normal file
6
core/src/mindustry/logic/Controllable.java
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
package mindustry.logic;
|
||||
|
||||
/** An object that can be controlled with logic. */
|
||||
public interface Controllable{
|
||||
void control(LAccess type, double p1, double p2, double p3, double p4);
|
||||
}
|
||||
35
core/src/mindustry/logic/LAccess.java
Normal file
35
core/src/mindustry/logic/LAccess.java
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
package mindustry.logic;
|
||||
|
||||
import arc.struct.*;
|
||||
|
||||
/** Setter/getter enum for logic-controlled objects. */
|
||||
public enum LAccess{
|
||||
totalItems,
|
||||
totalLiquids,
|
||||
totalPower,
|
||||
itemCapacity,
|
||||
liquidCapacity,
|
||||
powerCapacity,
|
||||
powerNetStored,
|
||||
powerNetCapacity,
|
||||
powerNetIn,
|
||||
powerNetOut,
|
||||
health,
|
||||
heat,
|
||||
efficiency,
|
||||
rotation,
|
||||
|
||||
//values with parameters are considered controllable
|
||||
enabled("to"),
|
||||
shoot("x", "y", "shoot");
|
||||
|
||||
public final String[] parameters;
|
||||
|
||||
public static final LAccess[] all = values();
|
||||
public static final LAccess[] senseable = Seq.select(all, t -> t.parameters.length <= 1).toArray(LAccess.class);
|
||||
public static final LAccess[] controls = Seq.select(all, t -> t.parameters.length > 0).toArray(LAccess.class);
|
||||
|
||||
LAccess(String... parameters){
|
||||
this.parameters = parameters;
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import arc.util.ArcAnnotate.*;
|
|||
import mindustry.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.logic.LExecutor.*;
|
||||
import mindustry.logic.LStatements.*;
|
||||
import mindustry.type.*;
|
||||
|
||||
/** "Compiles" a sequence of statements into instructions. */
|
||||
|
|
@ -39,7 +40,7 @@ public class LAssembler{
|
|||
|
||||
//store sensor constants
|
||||
|
||||
for(LSensor sensor : LSensor.all){
|
||||
for(LAccess sensor : LAccess.all){
|
||||
putConst("@" + sensor.name(), sensor);
|
||||
}
|
||||
}
|
||||
|
|
@ -64,22 +65,48 @@ public class LAssembler{
|
|||
}
|
||||
|
||||
public static Seq<LStatement> read(String data){
|
||||
//empty data check
|
||||
if(data == null || data.isEmpty()) return new Seq<>();
|
||||
|
||||
Seq<LStatement> statements = new Seq<>();
|
||||
String[] lines = data.split("[;\n]+");
|
||||
for(String line : lines){
|
||||
//comments
|
||||
if(line.startsWith("#")) continue;
|
||||
|
||||
String[] tokens = line.split(" ");
|
||||
LStatement st = LogicIO.read(tokens);
|
||||
if(st != null){
|
||||
statements.add(st);
|
||||
}else{
|
||||
//attempt parsing using custom parser if a match is found - this is for mods
|
||||
String first = tokens[0];
|
||||
if(customParsers.containsKey(first)){
|
||||
statements.add(customParsers.get(first).get(tokens));
|
||||
try{
|
||||
//yes, I am aware that this can be split with regex, but that's slow and even more incomprehensible
|
||||
Seq<String> tokens = new Seq<>();
|
||||
boolean inString = false;
|
||||
int lastIdx = 0;
|
||||
|
||||
for(int i = 0; i < line.length() + 1; i++){
|
||||
char c = i == line.length() ? ' ' : line.charAt(i);
|
||||
if(c == '"'){
|
||||
inString = !inString;
|
||||
}else if(c == ' ' && !inString){
|
||||
tokens.add(line.substring(lastIdx, i).replace("\\n", "\n"));
|
||||
lastIdx = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
String[] arr = tokens.toArray(String.class);
|
||||
LStatement st = LogicIO.read(arr);
|
||||
if(st != null){
|
||||
statements.add(st);
|
||||
}else{
|
||||
//attempt parsing using custom parser if a match is found - this is for mods
|
||||
String first = arr[0];
|
||||
if(customParsers.containsKey(first)){
|
||||
statements.add(customParsers.get(first).get(arr));
|
||||
}else{
|
||||
//unparseable statement
|
||||
statements.add(new InvalidStatement());
|
||||
}
|
||||
}
|
||||
}catch(Exception parseFailed){
|
||||
//when parsing fails, add a dummy invalid statement
|
||||
statements.add(new InvalidStatement());
|
||||
}
|
||||
}
|
||||
return statements;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import arc.util.*;
|
|||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.logic.LStatements.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.ui.dialogs.*;
|
||||
|
||||
|
|
@ -56,12 +55,6 @@ public class LCanvas extends Table{
|
|||
dialog.addCloseButton();
|
||||
dialog.show();
|
||||
}).height(50f).left().width(400f).marginLeft(10f);
|
||||
|
||||
add(new PrintStatement());
|
||||
add(new SetStatement());
|
||||
add(new JumpStatement());
|
||||
add(new EnableStatement());
|
||||
add(new BinaryOpStatement());
|
||||
}
|
||||
|
||||
private void drawGrid(){
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@ import mindustry.*;
|
|||
import mindustry.ctype.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.blocks.logic.LogicDisplay.*;
|
||||
|
||||
import static mindustry.world.blocks.logic.LogicDisplay.*;
|
||||
import mindustry.world.blocks.storage.MessageBlock.*;
|
||||
|
||||
public class LExecutor{
|
||||
//special variables
|
||||
|
|
@ -16,10 +15,16 @@ public class LExecutor{
|
|||
varCounter = 0,
|
||||
varTime = 1;
|
||||
|
||||
public static final int
|
||||
maxGraphicsBuffer = 512,
|
||||
maxTextBuffer = 256;
|
||||
|
||||
public double[] memory = {};
|
||||
public LInstruction[] instructions = {};
|
||||
public Var[] vars = {};
|
||||
|
||||
public LongSeq graphicsBuffer = new LongSeq();
|
||||
public StringBuilder textBuffer = new StringBuilder();
|
||||
|
||||
public boolean initialized(){
|
||||
return instructions != null && vars != null && instructions.length > 0;
|
||||
|
|
@ -125,21 +130,30 @@ public class LExecutor{
|
|||
void run(LExecutor exec);
|
||||
}
|
||||
|
||||
/** Enables/disables a building. */
|
||||
public static class EnableI implements LInstruction{
|
||||
public int target, value;
|
||||
/** Controls a building's state. */
|
||||
public static class ControlI implements LInstruction{
|
||||
public int target;
|
||||
public LAccess type = LAccess.enabled;
|
||||
public int p1, p2, p3, p4;
|
||||
|
||||
public EnableI(int target, int value){
|
||||
public ControlI(LAccess type, int target, int p1, int p2, int p3, int p4){
|
||||
this.type = type;
|
||||
this.target = target;
|
||||
this.value = value;
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
this.p3 = p3;
|
||||
this.p4 = p4;
|
||||
}
|
||||
|
||||
EnableI(){}
|
||||
ControlI(){}
|
||||
|
||||
@Override
|
||||
public void run(LExecutor exec){
|
||||
Building b = exec.building(target);
|
||||
if(b != null) b.enabled = exec.bool(value);
|
||||
Object obj = exec.obj(target);
|
||||
if(obj instanceof Controllable){
|
||||
Controllable cont = (Controllable)obj;
|
||||
cont.control(type, exec.num(p1), exec.num(p2), exec.num(p3), exec.num(p4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -205,8 +219,8 @@ public class LExecutor{
|
|||
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));
|
||||
}else if(sense instanceof LAccess){
|
||||
output = ((Senseable)target).sense(((LAccess)sense));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -288,12 +302,17 @@ public class LExecutor{
|
|||
}
|
||||
}
|
||||
|
||||
public static class DisplayI implements LInstruction{
|
||||
public static class NoopI implements LInstruction{
|
||||
@Override
|
||||
public void run(LExecutor exec){}
|
||||
}
|
||||
|
||||
public static class DrawI implements LInstruction{
|
||||
public byte type;
|
||||
public int target;
|
||||
public int x, y, p1, p2, p3;
|
||||
|
||||
public DisplayI(byte type, int target, int x, int y, int p1, int p2, int p3){
|
||||
public DrawI(byte type, int target, int x, int y, int p1, int p2, int p3){
|
||||
this.type = type;
|
||||
this.target = target;
|
||||
this.x = x;
|
||||
|
|
@ -303,7 +322,7 @@ public class LExecutor{
|
|||
this.p3 = p3;
|
||||
}
|
||||
|
||||
public DisplayI(){
|
||||
public DrawI(){
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -311,63 +330,91 @@ public class LExecutor{
|
|||
//graphics on headless servers are useless.
|
||||
if(Vars.headless) return;
|
||||
|
||||
if(type == commandFlush){
|
||||
Building build = exec.building(target);
|
||||
if(build instanceof LogicDisplayEntity){
|
||||
//flush is a special command
|
||||
LogicDisplayEntity d = (LogicDisplayEntity)build;
|
||||
for(int i = 0; i < exec.graphicsBuffer.size; i++){
|
||||
d.commands.addLast(exec.graphicsBuffer.items[i]);
|
||||
}
|
||||
exec.graphicsBuffer.clear();
|
||||
}
|
||||
//add graphics calls, cap graphics buffer size
|
||||
if(exec.graphicsBuffer.size < maxGraphicsBuffer){
|
||||
exec.graphicsBuffer.add(DisplayCmd.get(type, exec.numi(x), exec.numi(y), exec.numi(p1), exec.numi(p2), exec.numi(p3)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
//add graphics calls, cap graphics buffer size
|
||||
if(exec.graphicsBuffer.size < 1024){
|
||||
exec.graphicsBuffer.add(DisplayCmd.get(type, exec.numi(x), exec.numi(y), exec.numi(p1), exec.numi(p2), exec.numi(p3)));
|
||||
public static class DrawFlushI implements LInstruction{
|
||||
public int target;
|
||||
|
||||
public DrawFlushI(int target){
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public DrawFlushI(){
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(LExecutor exec){
|
||||
//graphics on headless servers are useless.
|
||||
if(Vars.headless) return;
|
||||
|
||||
Building build = exec.building(target);
|
||||
if(build instanceof LogicDisplayEntity){
|
||||
LogicDisplayEntity d = (LogicDisplayEntity)build;
|
||||
for(int i = 0; i < exec.graphicsBuffer.size; i++){
|
||||
d.commands.addLast(exec.graphicsBuffer.items[i]);
|
||||
}
|
||||
exec.graphicsBuffer.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class PrintI implements LInstruction{
|
||||
private static final StringBuilder out = new StringBuilder();
|
||||
public int value;
|
||||
|
||||
public int value, target;
|
||||
|
||||
public PrintI(int value, int target){
|
||||
public PrintI(int value){
|
||||
this.value = value;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
PrintI(){}
|
||||
|
||||
@Override
|
||||
public void run(LExecutor exec){
|
||||
Building b = exec.building(target);
|
||||
|
||||
if(b == null) return;
|
||||
if(exec.textBuffer.length() >= maxTextBuffer) return;
|
||||
|
||||
//this should avoid any garbage allocation
|
||||
Var v = exec.vars[value];
|
||||
if(v.isobj && value != 0){
|
||||
if(v.objval instanceof String){
|
||||
b.handleString(v.objval);
|
||||
}else if(v.objval == null){
|
||||
b.handleString("null");
|
||||
}else{
|
||||
b.handleString("[object]");
|
||||
}
|
||||
String strValue = v.objval instanceof String ? (String)v.objval : v.objval == null ? "null" : "[object]";
|
||||
|
||||
exec.textBuffer.append(strValue);
|
||||
}else{
|
||||
out.setLength(0);
|
||||
//display integer version when possible
|
||||
if(Math.abs(v.numval - (long)v.numval) < 0.000001){
|
||||
out.append((long)v.numval);
|
||||
exec.textBuffer.append((long)v.numval);
|
||||
}else{
|
||||
out.append(v.numval);
|
||||
exec.textBuffer.append(v.numval);
|
||||
}
|
||||
b.handleString(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class PrintFlushI implements LInstruction{
|
||||
public int target;
|
||||
|
||||
public PrintFlushI(int target){
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public PrintFlushI(){
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(LExecutor exec){
|
||||
|
||||
Building build = exec.building(target);
|
||||
if(build instanceof MessageBlockEntity){
|
||||
MessageBlockEntity d = (MessageBlockEntity)build;
|
||||
|
||||
d.message.setLength(0);
|
||||
d.message.append(exec.textBuffer, 0, Math.min(exec.textBuffer.length(), maxTextBuffer));
|
||||
|
||||
exec.textBuffer.setLength(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
package mindustry.logic;
|
||||
|
||||
public enum LSensor{
|
||||
totalItems,
|
||||
totalLiquids,
|
||||
totalPower,
|
||||
itemCapacity,
|
||||
liquidCapacity,
|
||||
powerCapacity,
|
||||
powerNetStored,
|
||||
powerNetCapacity,
|
||||
powerNetIn,
|
||||
powerNetOut,
|
||||
health,
|
||||
heat,
|
||||
efficiency;
|
||||
|
||||
public static final LSensor[] all = values();
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ import arc.scene.*;
|
|||
import arc.scene.actions.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.gen.*;
|
||||
|
|
@ -27,9 +28,8 @@ public abstract class LStatement{
|
|||
public LStatement copy(){
|
||||
StringBuilder build = new StringBuilder();
|
||||
write(build);
|
||||
String[] split = build.toString().split(" ");
|
||||
LStatement result = LogicIO.read(split);
|
||||
return result == null && LAssembler.customParsers.containsKey(split[0]) ? LAssembler.customParsers.get(split[0]).get(split) : result;
|
||||
Seq<LStatement> read = LAssembler.read(build.toString());
|
||||
return read.size == 0 ? null : read.first();
|
||||
}
|
||||
|
||||
//protected methods are only for internal UI layout utilities
|
||||
|
|
|
|||
|
|
@ -37,6 +37,24 @@ public class LStatements{
|
|||
}
|
||||
}
|
||||
|
||||
@RegisterStatement("noop")
|
||||
public static class InvalidStatement extends LStatement{
|
||||
|
||||
@Override
|
||||
public void build(Table table){
|
||||
}
|
||||
|
||||
@Override
|
||||
public LCategory category(){
|
||||
return LCategory.operations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LInstruction build(LAssembler builder){
|
||||
return new NoopI();
|
||||
}
|
||||
}
|
||||
|
||||
@RegisterStatement("write")
|
||||
public static class WriteStatement extends LStatement{
|
||||
public String to = "0";
|
||||
|
|
@ -90,7 +108,7 @@ public class LStatements{
|
|||
|
||||
@RegisterStatement("draw")
|
||||
public static class DrawStatement extends LStatement{
|
||||
public CommandType type = CommandType.line;
|
||||
public GraphicsType type = GraphicsType.line;
|
||||
public String x = "0", y = "0", p1 = "0", p2 = "0", p3 = "0";
|
||||
|
||||
@Override
|
||||
|
|
@ -105,13 +123,13 @@ public class LStatements{
|
|||
|
||||
table.button(b -> {
|
||||
b.label(() -> type.name());
|
||||
b.clicked(() -> showSelect(b, CommandType.allNormal, type, t -> {
|
||||
b.clicked(() -> showSelect(b, GraphicsType.all, type, t -> {
|
||||
type = t;
|
||||
rebuild(table);
|
||||
}, 2, cell -> cell.size(100, 50)));
|
||||
}, Styles.logict, () -> {}).size(90, 40).color(table.color).left().padLeft(2);
|
||||
|
||||
if(type != CommandType.stroke){
|
||||
if(type != GraphicsType.stroke){
|
||||
table.row();
|
||||
}
|
||||
|
||||
|
|
@ -158,7 +176,6 @@ public class LStatements{
|
|||
}
|
||||
}).expand().left();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -168,13 +185,13 @@ public class LStatements{
|
|||
|
||||
@Override
|
||||
public LInstruction build(LAssembler builder){
|
||||
return new DisplayI((byte)type.ordinal(), 0, builder.var(x), builder.var(y), builder.var(p1), builder.var(p2), builder.var(p3));
|
||||
return new DrawI((byte)type.ordinal(), 0, builder.var(x), builder.var(y), builder.var(p1), builder.var(p2), builder.var(p3));
|
||||
}
|
||||
}
|
||||
|
||||
@RegisterStatement("flush")
|
||||
public static class FlushStatement extends LStatement{
|
||||
public String target = "display";
|
||||
@RegisterStatement("drawflush")
|
||||
public static class DrawFlushStatement extends LStatement{
|
||||
public String target = "@0";
|
||||
|
||||
@Override
|
||||
public void build(Table table){
|
||||
|
|
@ -189,7 +206,102 @@ public class LStatements{
|
|||
|
||||
@Override
|
||||
public LInstruction build(LAssembler builder){
|
||||
return new DisplayI(commandFlush, builder.var(target), 0, 0, 0, 0, 0);
|
||||
return new DrawFlushI(builder.var(target));
|
||||
}
|
||||
}
|
||||
|
||||
@RegisterStatement("print")
|
||||
public static class PrintStatement extends LStatement{
|
||||
public String value = "\"frog\"";
|
||||
|
||||
@Override
|
||||
public void build(Table table){
|
||||
field(table, value, str -> value = str).width(0f).growX().padRight(3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LInstruction build(LAssembler builder){
|
||||
return new PrintI(builder.var(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LCategory category(){
|
||||
return LCategory.control;
|
||||
}
|
||||
}
|
||||
|
||||
@RegisterStatement("printflush")
|
||||
public static class PrintFlushStatement extends LStatement{
|
||||
public String target = "@0";
|
||||
|
||||
@Override
|
||||
public void build(Table table){
|
||||
table.add(" to ");
|
||||
field(table, target, str -> target = str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LCategory category(){
|
||||
return LCategory.blocks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LInstruction build(LAssembler builder){
|
||||
return new PrintFlushI(builder.var(target));
|
||||
}
|
||||
}
|
||||
|
||||
@RegisterStatement("control")
|
||||
public static class ControlStatement extends LStatement{
|
||||
public LAccess type = LAccess.enabled;
|
||||
public String target = "@0", p1 = "0", p2 = "0", p3 = "0", p4 = "0";
|
||||
|
||||
@Override
|
||||
public void build(Table table){
|
||||
rebuild(table);
|
||||
}
|
||||
|
||||
void rebuild(Table table){
|
||||
table.clearChildren();
|
||||
|
||||
table.left();
|
||||
|
||||
table.add(" set ");
|
||||
|
||||
table.button(b -> {
|
||||
b.label(() -> type.name());
|
||||
b.clicked(() -> showSelect(b, LAccess.controls, type, t -> {
|
||||
type = t;
|
||||
rebuild(table);
|
||||
}, 2, cell -> cell.size(100, 50)));
|
||||
}, Styles.logict, () -> {
|
||||
}).size(90, 40).color(table.color).left().padLeft(2);
|
||||
|
||||
table.add(" of ");
|
||||
|
||||
field(table, target, v -> target = v);
|
||||
|
||||
table.row();
|
||||
|
||||
//Q: why don't you just use arrays for this?
|
||||
//A: arrays aren't as easy to serialize so the code generator doesn't handle them
|
||||
int c = 0;
|
||||
for(int i = 0; i < type.parameters.length; i++){
|
||||
|
||||
fields(table, type.parameters[i], i == 0 ? p1 : i == 1 ? p2 : i == 2 ? p3 : p4, i == 0 ? v -> p1 = v : i == 1 ? v -> p2 = v : i == 2 ? v -> p3 = v : v -> p4 = v);
|
||||
|
||||
if(++c % 2 == 0) table.row();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LCategory category(){
|
||||
return LCategory.blocks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LInstruction build(LAssembler builder){
|
||||
return new ControlI(type, builder.var(target), builder.var(p1), builder.var(p2), builder.var(p3), builder.var(p4));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -246,7 +358,7 @@ public class LStatements{
|
|||
}),
|
||||
//sensors
|
||||
new Table(i -> {
|
||||
for(LSensor sensor : LSensor.all){
|
||||
for(LAccess sensor : LAccess.senseable){
|
||||
i.button(sensor.name(), Styles.cleart, () -> {
|
||||
stype("@" + sensor.name());
|
||||
hide.run();
|
||||
|
|
@ -321,31 +433,6 @@ public class LStatements{
|
|||
}
|
||||
}
|
||||
|
||||
@RegisterStatement("enable")
|
||||
public static class EnableStatement extends LStatement{
|
||||
public String target = "result";
|
||||
public String value = "0";
|
||||
|
||||
@Override
|
||||
public void build(Table table){
|
||||
field(table, target, str -> target = str);
|
||||
|
||||
table.add(" -> ");
|
||||
|
||||
field(table, value, str -> value = str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LCategory category(){
|
||||
return LCategory.blocks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LInstruction build(LAssembler builder){
|
||||
return new EnableI(builder.var(target), builder.var(value));
|
||||
}
|
||||
}
|
||||
|
||||
@RegisterStatement("bop")
|
||||
public static class BinaryOpStatement extends LStatement{
|
||||
public BinaryOp op = BinaryOp.add;
|
||||
|
|
@ -428,31 +515,6 @@ public class LStatements{
|
|||
}
|
||||
}
|
||||
|
||||
@RegisterStatement("print")
|
||||
public static class PrintStatement extends LStatement{
|
||||
public String value = "\"frog\"";
|
||||
public String target = "result";
|
||||
|
||||
@Override
|
||||
public void build(Table table){
|
||||
field(table, value, str -> value = str);
|
||||
|
||||
table.add(" to ");
|
||||
|
||||
field(table, target, str -> target = str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LInstruction build(LAssembler builder){
|
||||
return new PrintI(builder.var(value), builder.var(target));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LCategory category(){
|
||||
return LCategory.control;
|
||||
}
|
||||
}
|
||||
|
||||
@RegisterStatement("jump")
|
||||
public static class JumpStatement extends LStatement{
|
||||
public transient StatementElem dest;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@ package mindustry.logic;
|
|||
import mindustry.ctype.*;
|
||||
|
||||
public interface Senseable{
|
||||
double sense(LSensor sensor);
|
||||
double sense(LAccess sensor);
|
||||
double sense(Content content);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package mindustry.world.blocks.defense;
|
|||
import arc.Graphics.*;
|
||||
import arc.Graphics.Cursor.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
|
|
@ -12,6 +13,8 @@ import mindustry.content.*;
|
|||
import mindustry.entities.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.logic.*;
|
||||
import mindustry.world.blocks.defense.Door.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
|
|
@ -33,6 +36,11 @@ public class Door extends Wall{
|
|||
Sounds.door.at(base);
|
||||
|
||||
for(DoorEntity entity : base.chained){
|
||||
//skip doors with things in them
|
||||
if((Units.anyEntities(entity.tile) && !open) || entity.open == open){
|
||||
continue;
|
||||
}
|
||||
|
||||
entity.open = open;
|
||||
pathfinder.updateTile(entity.tile());
|
||||
entity.effect();
|
||||
|
|
@ -66,6 +74,19 @@ public class Door extends Wall{
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void control(LAccess type, double p1, double p2, double p3, double p4){
|
||||
if(type == LAccess.enabled){
|
||||
boolean shouldOpen = !Mathf.zero(p1);
|
||||
|
||||
if(open == shouldOpen || (Units.anyEntities(tile) && !shouldOpen) || !timer(timerToggle, 60f)){
|
||||
return;
|
||||
}
|
||||
|
||||
configureAny(shouldOpen);
|
||||
}
|
||||
}
|
||||
|
||||
public void effect(){
|
||||
(open ? closefx : openfx).at(this);
|
||||
}
|
||||
|
|
@ -104,7 +125,7 @@ public class Door extends Wall{
|
|||
|
||||
@Override
|
||||
public void tapped(Player player){
|
||||
if((Units.anyEntities(tile) && open) || !timer(timerToggle, 30f)){
|
||||
if((Units.anyEntities(tile) && open) || !timer(timerToggle, 40f)){
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import mindustry.entities.bullet.*;
|
|||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.logic.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
|
|
@ -25,9 +26,12 @@ import mindustry.world.consumers.*;
|
|||
import mindustry.world.meta.*;
|
||||
import mindustry.world.meta.values.*;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public abstract class Turret extends Block{
|
||||
//after being logic-controlled and this amount of time passes, the turret will resume normal AI
|
||||
public final static float logicControlCooldown = 60 * 2;
|
||||
|
||||
public final int timerTarget = timers++;
|
||||
public int targetInterval = 20;
|
||||
|
||||
|
|
@ -140,8 +144,9 @@ public abstract class Turret extends Block{
|
|||
public class TurretEntity extends Building implements ControlBlock{
|
||||
public Seq<AmmoEntry> ammo = new Seq<>();
|
||||
public int totalAmmo;
|
||||
public float reload, rotation = 90, recoil, heat;
|
||||
public float reload, rotation = 90, recoil, heat, logicControlTime = -1;
|
||||
public int shotCounter;
|
||||
public boolean logicShooting = false;
|
||||
public @Nullable Posc target;
|
||||
public Vec2 targetPos = new Vec2();
|
||||
public @NonNull BlockUnitc unit = Nulls.blockUnit;
|
||||
|
|
@ -152,11 +157,26 @@ public abstract class Turret extends Block{
|
|||
unit.tile(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void control(LAccess type, double p1, double p2, double p3, double p4){
|
||||
if(type == LAccess.shoot && !unit.isPlayer()){
|
||||
targetPos.set((float)p1, (float)p2);
|
||||
logicControlTime = logicControlCooldown;
|
||||
logicShooting = !Mathf.zero(p3);
|
||||
}
|
||||
|
||||
super.control(type, p1, p2, p3, p4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unit unit(){
|
||||
return (Unit)unit;
|
||||
}
|
||||
|
||||
public boolean logicControlled(){
|
||||
return logicControlTime > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
Draw.rect(baseRegion, x, y);
|
||||
|
|
@ -184,6 +204,10 @@ public abstract class Turret extends Block{
|
|||
unit.rotation(rotation);
|
||||
unit.team(team);
|
||||
|
||||
if(logicControlTime > 0){
|
||||
logicControlTime -= Time.delta;
|
||||
}
|
||||
|
||||
if(hasAmmo()){
|
||||
|
||||
if(timer(timerTarget, targetInterval)){
|
||||
|
|
@ -193,10 +217,11 @@ public abstract class Turret extends Block{
|
|||
if(validateTarget()){
|
||||
boolean canShoot = true;
|
||||
|
||||
//player behavior
|
||||
if(isControlled()){
|
||||
if(isControlled()){ //player behavior
|
||||
targetPos.set(unit.aimX(), unit.aimY());
|
||||
canShoot = unit.isShooting();
|
||||
}else if(logicControlled()){ //logic behavior
|
||||
canShoot = logicShooting;
|
||||
}else{ //default AI behavior
|
||||
BulletType type = peekAmmo();
|
||||
float speed = type.speed;
|
||||
|
|
|
|||
|
|
@ -19,8 +19,7 @@ public class LogicDisplay extends Block{
|
|||
commandRect = 4,
|
||||
commandLineRect = 5,
|
||||
commandPoly = 6,
|
||||
commandLinePoly = 7,
|
||||
commandFlush = 8;
|
||||
commandLinePoly = 7;
|
||||
|
||||
public int maxSides = 25;
|
||||
|
||||
|
|
@ -91,7 +90,7 @@ public class LogicDisplay extends Block{
|
|||
}
|
||||
}
|
||||
|
||||
public enum CommandType{
|
||||
public enum GraphicsType{
|
||||
clear,
|
||||
color,
|
||||
stroke,
|
||||
|
|
@ -99,11 +98,9 @@ public class LogicDisplay extends Block{
|
|||
rect,
|
||||
lineRect,
|
||||
poly,
|
||||
linePoly,
|
||||
flush;
|
||||
linePoly;
|
||||
|
||||
public static final CommandType[] all = values();
|
||||
public static final CommandType[] allNormal = Seq.select(all, t -> t != flush).toArray(CommandType.class);
|
||||
public static final GraphicsType[] all = values();
|
||||
}
|
||||
|
||||
@Struct
|
||||
|
|
|
|||
|
|
@ -109,8 +109,8 @@ public class NuclearReactor extends PowerGenerator{
|
|||
}
|
||||
|
||||
@Override
|
||||
public double sense(LSensor sensor){
|
||||
if(sensor == LSensor.heat) return heat;
|
||||
public double sense(LAccess sensor){
|
||||
if(sensor == LAccess.heat) return heat;
|
||||
return super.sense(sensor);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue