Logic stuff
@@ -128,11 +128,11 @@ public class Annotations{
|
|||||||
String fallback() default "error";
|
String fallback() default "error";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Registers a logic node's slot. */
|
/** Registers a statement for auto serialization. */
|
||||||
@Target(ElementType.FIELD)
|
@Target(ElementType.TYPE)
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface Slot{
|
public @interface RegisterStatement{
|
||||||
boolean input() default false;
|
String value();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
package mindustry.annotations.misc;
|
||||||
|
|
||||||
|
import arc.func.*;
|
||||||
|
import arc.struct.*;
|
||||||
|
import com.squareup.javapoet.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.annotations.*;
|
||||||
|
import mindustry.annotations.util.*;
|
||||||
|
|
||||||
|
import javax.annotation.processing.*;
|
||||||
|
import javax.lang.model.element.*;
|
||||||
|
|
||||||
|
@SupportedAnnotationTypes("mindustry.annotations.Annotations.RegisterStatement")
|
||||||
|
public class LogicStatementProcessor extends BaseProcessor{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(RoundEnvironment env) throws Exception{
|
||||||
|
TypeSpec.Builder type = TypeSpec.classBuilder("LogicIO")
|
||||||
|
.addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
|
MethodSpec.Builder writer = MethodSpec.methodBuilder("write")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||||
|
.addParameter(Object.class, "obj")
|
||||||
|
.addParameter(StringBuilder.class, "out");
|
||||||
|
|
||||||
|
MethodSpec.Builder reader = MethodSpec.methodBuilder("read")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||||
|
.returns(tname("mindustry.logic.LStatement"))
|
||||||
|
.addParameter(String[].class, "tokens");
|
||||||
|
|
||||||
|
Seq<Stype> types = types(RegisterStatement.class);
|
||||||
|
|
||||||
|
type.addField(FieldSpec.builder(
|
||||||
|
ParameterizedTypeName.get(
|
||||||
|
ClassName.get(Seq.class),
|
||||||
|
ParameterizedTypeName.get(ClassName.get(Prov.class),
|
||||||
|
tname("mindustry.logic.LStatement"))), "allStatements", Modifier.PUBLIC, Modifier.STATIC)
|
||||||
|
.initializer("Seq.with(" + types.toString(", ", t -> "" + t.toString() + "::new") + ")").build());
|
||||||
|
|
||||||
|
boolean beganWrite = false, beganRead = false;
|
||||||
|
|
||||||
|
for(Stype c : types){
|
||||||
|
String name = c.annotation(RegisterStatement.class).value();
|
||||||
|
|
||||||
|
if(beganWrite){
|
||||||
|
writer.nextControlFlow("else if(obj instanceof $T)", c.mirror());
|
||||||
|
}else{
|
||||||
|
writer.beginControlFlow("if(obj instanceof $T)", c.mirror());
|
||||||
|
beganWrite = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//write the name & individual fields
|
||||||
|
writer.addStatement("out.append($S)", name);
|
||||||
|
|
||||||
|
Seq<Svar> fields = c.fields();
|
||||||
|
|
||||||
|
String readSt = "if(tokens[0].equals($S))";
|
||||||
|
if(beganRead){
|
||||||
|
reader.nextControlFlow("else " + readSt, name);
|
||||||
|
}else{
|
||||||
|
reader.beginControlFlow(readSt, name);
|
||||||
|
beganRead = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.addStatement("$T result = new $T()", c.mirror(), c.mirror());
|
||||||
|
|
||||||
|
for(int i = 0; i < fields.size; i++){
|
||||||
|
Svar field = fields.get(i);
|
||||||
|
|
||||||
|
if(field.is(Modifier.TRANSIENT)) continue;
|
||||||
|
|
||||||
|
writer.addStatement("out.append(\" \")");
|
||||||
|
writer.addStatement("out.append((($T)obj).$L)", c.mirror(), field.name());
|
||||||
|
|
||||||
|
//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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.addStatement("return result");
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.endControlFlow();
|
||||||
|
writer.endControlFlow();
|
||||||
|
|
||||||
|
reader.addStatement("return null");
|
||||||
|
|
||||||
|
type.addMethod(writer.build());
|
||||||
|
type.addMethod(reader.build());
|
||||||
|
|
||||||
|
write(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{version:3,fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{version:4,fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{version:3,fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{version:4,fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]}
|
||||||
|
Before Width: | Height: | Size: 836 B |
|
After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 836 B |
|
Before Width: | Height: | Size: 777 B After Width: | Height: | Size: 770 B |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 189 KiB |
|
Before Width: | Height: | Size: 385 KiB After Width: | Height: | Size: 382 KiB |
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.8 MiB After Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 187 KiB After Width: | Height: | Size: 190 KiB |
|
Before Width: | Height: | Size: 391 KiB After Width: | Height: | Size: 398 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
@@ -1890,7 +1890,7 @@ public class Blocks implements ContentList{
|
|||||||
logicProcessor = new LogicProcessor("logic-processor"){{
|
logicProcessor = new LogicProcessor("logic-processor"){{
|
||||||
requirements(Category.effect, BuildVisibility.debugOnly, with(Items.copper, 200, Items.lead, 100));
|
requirements(Category.effect, BuildVisibility.debugOnly, with(Items.copper, 200, Items.lead, 100));
|
||||||
|
|
||||||
size = 3;
|
size = 2;
|
||||||
alwaysUnlocked = true;
|
alwaysUnlocked = true;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
package mindustry.logic;
|
package mindustry.logic;
|
||||||
|
|
||||||
|
import arc.func.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import mindustry.io.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.logic.LCanvas.*;
|
|
||||||
import mindustry.logic.LExecutor.*;
|
import mindustry.logic.LExecutor.*;
|
||||||
|
|
||||||
/** "Compiles" a sequence of statements into instructions. */
|
/** "Compiles" a sequence of statements into instructions. */
|
||||||
public class LAssembler{
|
public class LAssembler{
|
||||||
|
public static ObjectMap<String, Func<String[], LStatement>> customParsers = new ObjectMap<>();
|
||||||
|
|
||||||
private transient int lastVar;
|
private transient int lastVar;
|
||||||
/** Maps names to variable IDs. */
|
/** Maps names to variable IDs. */
|
||||||
ObjectMap<String, BVar> vars = new ObjectMap<>();
|
ObjectMap<String, BVar> vars = new ObjectMap<>();
|
||||||
@@ -20,35 +22,47 @@ public class LAssembler{
|
|||||||
putConst("null", null);
|
putConst("null", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LAssembler assemble(Seq<StatementElem> seq){
|
public static LAssembler assemble(String data){
|
||||||
LAssembler out = new LAssembler();
|
|
||||||
|
|
||||||
seq.each(s -> s.st.saveUI());
|
|
||||||
out.instructions = seq.map(s -> s.st.build(out)).toArray(LInstruction.class);
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String toJson(Seq<StatementElem> seq){
|
|
||||||
seq.each(s -> s.st.saveUI());
|
|
||||||
LStatement[] statements = seq.map(s -> s.st).toArray(LStatement.class);
|
|
||||||
|
|
||||||
return JsonIO.write(statements);
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO this is awful and confusing
|
|
||||||
public static LAssembler fromJson(String json){
|
|
||||||
LAssembler asm = new LAssembler();
|
LAssembler asm = new LAssembler();
|
||||||
|
|
||||||
LStatement[] statements = JsonIO.read(LStatement[].class, json);
|
Seq<LStatement> st = read(data);
|
||||||
for(LStatement s : statements){
|
|
||||||
s.setupUI();
|
|
||||||
}
|
|
||||||
asm.instructions = Seq.with(statements).map(l -> l.build(asm)).toArray(LInstruction.class);
|
|
||||||
|
|
||||||
|
asm.instructions = st.map(l -> l.build(asm)).toArray(LInstruction.class);
|
||||||
return asm;
|
return asm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String write(Seq<LStatement> statements){
|
||||||
|
StringBuilder out = new StringBuilder();
|
||||||
|
for(LStatement s : statements){
|
||||||
|
s.write(out);
|
||||||
|
out.append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Seq<LStatement> read(String data){
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return statements;
|
||||||
|
}
|
||||||
|
|
||||||
/** @return a variable ID by name.
|
/** @return a variable ID by name.
|
||||||
* This may be a constant variable referring to a number or object. */
|
* This may be a constant variable referring to a number or object. */
|
||||||
public int var(String symbol){
|
public int var(String symbol){
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ import arc.util.*;
|
|||||||
import arc.util.ArcAnnotate.*;
|
import arc.util.ArcAnnotate.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.io.*;
|
|
||||||
import mindustry.logic.LStatements.*;
|
import mindustry.logic.LStatements.*;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
|
import mindustry.ui.dialogs.*;
|
||||||
|
|
||||||
public class LCanvas extends Table{
|
public class LCanvas extends Table{
|
||||||
private static final Color backgroundCol = Pal.darkMetal.cpy().mul(0.1f), gridCol = Pal.darkMetal.cpy().mul(0.5f);
|
private static final Color backgroundCol = Pal.darkMetal.cpy().mul(0.1f), gridCol = Pal.darkMetal.cpy().mul(0.5f);
|
||||||
@@ -35,8 +35,30 @@ public class LCanvas extends Table{
|
|||||||
|
|
||||||
pane(statements).grow().get().setClip(false);
|
pane(statements).grow().get().setClip(false);
|
||||||
|
|
||||||
|
row();
|
||||||
|
|
||||||
|
button("@add", Icon.add, Styles.cleart, () -> {
|
||||||
|
BaseDialog dialog = new BaseDialog("@add");
|
||||||
|
dialog.cont.pane(t -> {
|
||||||
|
t.background(Tex.button);
|
||||||
|
for(Prov<LStatement> prov : LogicIO.allStatements){
|
||||||
|
LStatement example = prov.get();
|
||||||
|
t.button(example.name(), Styles.cleart, () -> {
|
||||||
|
add(prov.get());
|
||||||
|
dialog.hide();
|
||||||
|
}).size(200f, 50f);
|
||||||
|
t.row();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialog.addCloseButton();
|
||||||
|
dialog.show();
|
||||||
|
}).height(50f).left().width(400f).marginLeft(10f);
|
||||||
|
|
||||||
add(new PrintStatement());
|
add(new PrintStatement());
|
||||||
add(new AssignStatement());
|
add(new SetStatement());
|
||||||
|
add(new JumpStatement());
|
||||||
|
add(new EnableStatement());
|
||||||
|
add(new OpStatement());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawGrid(){
|
private void drawGrid(){
|
||||||
@@ -70,18 +92,26 @@ public class LCanvas extends Table{
|
|||||||
}
|
}
|
||||||
|
|
||||||
String save(){
|
String save(){
|
||||||
return LAssembler.toJson(statements.getChildren().as());
|
Seq<LStatement> st = statements.getChildren().<StatementElem>as().map(s -> s.st);
|
||||||
|
st.each(LStatement::saveUI);
|
||||||
|
|
||||||
|
return LAssembler.write(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
void load(String json){
|
void load(String asm){
|
||||||
statements.clearChildren();
|
statements.clearChildren();
|
||||||
LStatement[] statements = JsonIO.read(LStatement[].class, json);
|
try{
|
||||||
for(LStatement st : statements){
|
Seq<LStatement> statements = LAssembler.read(asm);
|
||||||
add(st);
|
for(LStatement st : statements){
|
||||||
}
|
add(st);
|
||||||
|
}
|
||||||
|
|
||||||
for(LStatement st : statements){
|
for(LStatement st : statements){
|
||||||
st.setupUI();
|
st.setupUI();
|
||||||
|
}
|
||||||
|
}catch(Exception e){
|
||||||
|
//ignore errors reading asm
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.statements.layout();
|
this.statements.layout();
|
||||||
@@ -96,7 +126,7 @@ public class LCanvas extends Table{
|
|||||||
|
|
||||||
public class DragLayout extends WidgetGroup{
|
public class DragLayout extends WidgetGroup{
|
||||||
float margin = 4f;
|
float margin = 4f;
|
||||||
float space = 10f, width = 400f;
|
float space = 10f, width = 400f, prefWidth, prefHeight;
|
||||||
Seq<Element> seq = new Seq<>();
|
Seq<Element> seq = new Seq<>();
|
||||||
int insertPosition = 0;
|
int insertPosition = 0;
|
||||||
|
|
||||||
@@ -105,6 +135,8 @@ public class LCanvas extends Table{
|
|||||||
float cy = 0;
|
float cy = 0;
|
||||||
seq.clear();
|
seq.clear();
|
||||||
|
|
||||||
|
prefWidth = width;
|
||||||
|
|
||||||
//layout everything normally
|
//layout everything normally
|
||||||
for(int i = 0; i < getChildren().size; i++){
|
for(int i = 0; i < getChildren().size; i++){
|
||||||
Element e = getChildren().get(i);
|
Element e = getChildren().get(i);
|
||||||
@@ -143,10 +175,22 @@ public class LCanvas extends Table{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prefHeight = cy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getPrefWidth(){
|
||||||
|
return prefWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getPrefHeight(){
|
||||||
|
return prefHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void draw(){
|
||||||
|
Draw.alpha(parentAlpha);
|
||||||
|
|
||||||
//draw selection box indicating placement position
|
//draw selection box indicating placement position
|
||||||
if(dragging != null && insertPosition <= seq.size){
|
if(dragging != null && insertPosition <= seq.size){
|
||||||
@@ -260,9 +304,9 @@ public class LCanvas extends Table{
|
|||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void draw(){
|
||||||
float pad = 5f;
|
float pad = 5f;
|
||||||
Fill.dropShadow(x + width/2f, y + height/2f, width + pad, height + pad, 10f, 0.9f);
|
Fill.dropShadow(x + width/2f, y + height/2f, width + pad, height + pad, 10f, 0.9f * parentAlpha);
|
||||||
|
|
||||||
Draw.color(0, 0, 0, 0.3f);
|
Draw.color(0, 0, 0, 0.3f * parentAlpha);
|
||||||
Fill.crect(x, y, width, height);
|
Fill.crect(x, y, width, height);
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
|
|
||||||
@@ -323,24 +367,31 @@ public class LCanvas extends Table{
|
|||||||
public void draw(){
|
public void draw(){
|
||||||
super.draw();
|
super.draw();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
postDraw.add(() -> {
|
postDraw.add(() -> {
|
||||||
Element hover = to.get() == null && selecting ? hovered() : to.get();
|
Element hover = to.get() == null && selecting ? hovered() : to.get();
|
||||||
float tx = 0, ty = 0;
|
float tx = 0, ty = 0;
|
||||||
boolean draw = false;
|
boolean draw = false;
|
||||||
//capture coordinates for use in lambda
|
//capture coordinates for use in lambda
|
||||||
float rx = x, ry = y;
|
float rx = x + translation.x, ry = y + translation.y;
|
||||||
|
|
||||||
Element p = parent;
|
Element p = parent;
|
||||||
while(p != null){
|
while(p != null){
|
||||||
rx += p.x;
|
rx += p.x + p.translation.x;
|
||||||
ry += p.y;
|
ry += p.y + p.translation.y;
|
||||||
p = p.parent;
|
p = p.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hover != null){
|
if(hover != null){
|
||||||
tx = hover.getX(Align.right) + hover.translation.x;
|
tx = hover.getX(Align.right) + hover.translation.x;
|
||||||
ty = hover.getY(Align.right) + hover.translation.y;
|
ty = hover.getY(Align.right) + hover.translation.y;
|
||||||
|
|
||||||
|
Element op = hover.parent;
|
||||||
|
while(op != null){
|
||||||
|
tx += op.x + op.translation.x;
|
||||||
|
ty += op.y + op.translation.y;
|
||||||
|
op = op.parent;
|
||||||
|
}
|
||||||
|
|
||||||
draw = true;
|
draw = true;
|
||||||
}else if(selecting){
|
}else if(selecting){
|
||||||
tx = rx + mx;
|
tx = rx + mx;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class LExecutor{
|
|||||||
return instructions != null && vars != null && instructions.length > 0;
|
return instructions != null && vars != null && instructions.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Runs all the instructions at once. Debugging only. */
|
/** Runs all the instructions at once. Debugging only! */
|
||||||
public void runAll(){
|
public void runAll(){
|
||||||
counter = 0;
|
counter = 0;
|
||||||
|
|
||||||
@@ -25,6 +25,19 @@ public class LExecutor{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void runOnce(){
|
||||||
|
//reset to start
|
||||||
|
if(counter >= instructions.length) counter = 0;
|
||||||
|
|
||||||
|
if(counter < instructions.length){
|
||||||
|
instructions[counter++].run(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(Object context, String data){
|
||||||
|
load(context,LAssembler.assemble(data));
|
||||||
|
}
|
||||||
|
|
||||||
public void load(Object context, LAssembler builder){
|
public void load(Object context, LAssembler builder){
|
||||||
builder.putConst("this", context);
|
builder.putConst("this", context);
|
||||||
|
|
||||||
@@ -105,15 +118,15 @@ public class LExecutor{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Enables/disables a building. */
|
/** Enables/disables a building. */
|
||||||
public static class ToggleI implements LInstruction{
|
public static class EnableI implements LInstruction{
|
||||||
public int target, value;
|
public int target, value;
|
||||||
|
|
||||||
public ToggleI(int target, int value){
|
public EnableI(int target, int value){
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ToggleI(){}
|
EnableI(){}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(LExecutor exec){
|
public void run(LExecutor exec){
|
||||||
@@ -131,15 +144,15 @@ public class LExecutor{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AssignI implements LInstruction{
|
public static class SetI implements LInstruction{
|
||||||
public int from, to;
|
public int from, to;
|
||||||
|
|
||||||
public AssignI(int from, int to){
|
public SetI(int from, int to){
|
||||||
this.from = from;
|
this.from = from;
|
||||||
this.to = to;
|
this.to = to;
|
||||||
}
|
}
|
||||||
|
|
||||||
AssignI(){}
|
SetI(){}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(LExecutor exec){
|
public void run(LExecutor exec){
|
||||||
@@ -219,17 +232,17 @@ public class LExecutor{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class FetchBuildI implements LInstruction{
|
public static class GetBuildI implements LInstruction{
|
||||||
public int dest;
|
public int dest;
|
||||||
public int x, y;
|
public int x, y;
|
||||||
|
|
||||||
public FetchBuildI(int dest, int x, int y){
|
public GetBuildI(int dest, int x, int y){
|
||||||
this.dest = dest;
|
this.dest = dest;
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
FetchBuildI(){}
|
GetBuildI(){}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(LExecutor exec){
|
public void run(LExecutor exec){
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ package mindustry.logic;
|
|||||||
|
|
||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
import arc.util.ArcAnnotate.*;
|
import arc.util.ArcAnnotate.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
import mindustry.logic.LCanvas.*;
|
import mindustry.logic.LCanvas.*;
|
||||||
import mindustry.logic.LExecutor.*;
|
import mindustry.logic.LExecutor.*;
|
||||||
|
|
||||||
/** A statement is an intermediate representation of an instruction, to be used in UI. */
|
/**
|
||||||
|
* A statement is an intermediate representation of an instruction, to be used mostly in UI.
|
||||||
|
* Contains all relevant variable information. */
|
||||||
public abstract class LStatement{
|
public abstract class LStatement{
|
||||||
public transient @Nullable StatementElem elem;
|
public transient @Nullable StatementElem elem;
|
||||||
|
|
||||||
@@ -13,6 +16,10 @@ public abstract class LStatement{
|
|||||||
public abstract LCategory category();
|
public abstract LCategory category();
|
||||||
public abstract LInstruction build(LAssembler builder);
|
public abstract LInstruction build(LAssembler builder);
|
||||||
|
|
||||||
|
public void write(StringBuilder builder){
|
||||||
|
LogicIO.write(this,builder);
|
||||||
|
}
|
||||||
|
|
||||||
public void setupUI(){
|
public void setupUI(){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,15 @@ package mindustry.logic;
|
|||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
import arc.scene.ui.*;
|
import arc.scene.ui.*;
|
||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.logic.LExecutor.*;
|
import mindustry.logic.LExecutor.*;
|
||||||
import mindustry.logic.LCanvas.*;
|
import mindustry.logic.LCanvas.*;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
|
|
||||||
public class LStatements{
|
public class LStatements{
|
||||||
|
|
||||||
public static class AssignStatement extends LStatement{
|
@RegisterStatement("set")
|
||||||
|
public static class SetStatement extends LStatement{
|
||||||
public String to = "result";
|
public String to = "result";
|
||||||
public String from = "0";
|
public String from = "0";
|
||||||
|
|
||||||
@@ -31,12 +33,12 @@ public class LStatements{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LInstruction build(LAssembler builder){
|
public LInstruction build(LAssembler builder){
|
||||||
//TODO internal consts need to start with ___ and not be assignable to
|
return new SetI(builder.var(from), builder.var(to));
|
||||||
return new LExecutor.AssignI(builder.var(from), builder.var(to));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ToggleStatement extends LStatement{
|
@RegisterStatement("enable")
|
||||||
|
public static class EnableStatement extends LStatement{
|
||||||
public String target = "result";
|
public String target = "result";
|
||||||
public String value = "0";
|
public String value = "0";
|
||||||
|
|
||||||
@@ -57,11 +59,12 @@ public class LStatements{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LExecutor.LInstruction build(LAssembler builder){
|
public LInstruction build(LAssembler builder){
|
||||||
return new LExecutor.ToggleI(builder.var(target), builder.var(value));
|
return new EnableI(builder.var(target), builder.var(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RegisterStatement("op")
|
||||||
public static class OpStatement extends LStatement{
|
public static class OpStatement extends LStatement{
|
||||||
public BinaryOp op = BinaryOp.add;
|
public BinaryOp op = BinaryOp.add;
|
||||||
public String a = "a", b = "b", dest = "result";
|
public String a = "a", b = "b", dest = "result";
|
||||||
@@ -98,6 +101,7 @@ public class LStatements{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RegisterStatement("end")
|
||||||
public static class EndStatement extends LStatement{
|
public static class EndStatement extends LStatement{
|
||||||
@Override
|
@Override
|
||||||
public void build(Table table){
|
public void build(Table table){
|
||||||
@@ -115,6 +119,7 @@ public class LStatements{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RegisterStatement("print")
|
||||||
public static class PrintStatement extends LStatement{
|
public static class PrintStatement extends LStatement{
|
||||||
public String value = "\"frog\"";
|
public String value = "\"frog\"";
|
||||||
|
|
||||||
@@ -135,6 +140,7 @@ public class LStatements{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RegisterStatement("jump")
|
||||||
public static class JumpStatement extends LStatement{
|
public static class JumpStatement extends LStatement{
|
||||||
public transient StatementElem dest;
|
public transient StatementElem dest;
|
||||||
|
|
||||||
@@ -176,7 +182,8 @@ public class LStatements{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class FetchBuildStatement extends LStatement{
|
@RegisterStatement("getbuild")
|
||||||
|
public static class getBuildStatement extends LStatement{
|
||||||
public String x = "0", y = "0", dest = "result";
|
public String x = "0", y = "0", dest = "result";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -197,7 +204,7 @@ public class LStatements{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LInstruction build(LAssembler builder){
|
public LInstruction build(LAssembler builder){
|
||||||
return new FetchBuildI(builder.var(dest), builder.var(x), builder.var(y));
|
return new GetBuildI(builder.var(dest), builder.var(x), builder.var(y));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -16,20 +16,28 @@ public class LogicProcessor extends Block{
|
|||||||
config(String.class, (LogicEntity entity, String code) -> {
|
config(String.class, (LogicEntity entity, String code) -> {
|
||||||
if(code != null){
|
if(code != null){
|
||||||
entity.code = code;
|
entity.code = code;
|
||||||
entity.executor.load(entity, LAssembler.fromJson(code));
|
|
||||||
|
try{
|
||||||
|
entity.executor.load(entity, code);
|
||||||
|
}catch(Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
|
||||||
|
//handle malformed code and replace it with nothing
|
||||||
|
entity.executor.load(entity, "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LogicEntity extends Building{
|
public class LogicEntity extends Building{
|
||||||
/** logic "source code" as list of json statements */
|
/** logic "source code" as list of json statements */
|
||||||
String code = "[]";
|
String code = "";
|
||||||
LExecutor executor = new LExecutor();
|
LExecutor executor = new LExecutor();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateTile(){
|
public void updateTile(){
|
||||||
if(executor.initialized()){
|
if(executor.initialized()){
|
||||||
executor.runAll();
|
executor.runOnce();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +59,14 @@ public class LogicProcessor extends Block{
|
|||||||
super.read(read, revision);
|
super.read(read, revision);
|
||||||
|
|
||||||
code = read.str();
|
code = read.str();
|
||||||
executor.load(this, LAssembler.fromJson(code));
|
try{
|
||||||
|
executor.load(this, code);
|
||||||
|
}catch(Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
|
||||||
|
//handle malformed code and ignore it
|
||||||
|
executor = new LExecutor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||