Logic progress
BIN
core/assets-raw/sprites/blocks/campaign/micro-processor.png
Normal file
|
After Width: | Height: | Size: 411 B |
@@ -281,3 +281,4 @@
|
|||||||
63463=risso|unit-risso-medium
|
63463=risso|unit-risso-medium
|
||||||
63462=overdrive-dome|block-overdrive-dome-medium
|
63462=overdrive-dome|block-overdrive-dome-medium
|
||||||
63461=logic-processor|block-logic-processor-medium
|
63461=logic-processor|block-logic-processor-medium
|
||||||
|
63460=micro-processor|block-micro-processor-medium
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 770 B After Width: | Height: | Size: 783 B |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 182 KiB |
|
Before Width: | Height: | Size: 382 KiB After Width: | Height: | Size: 384 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: 190 KiB After Width: | Height: | Size: 183 KiB |
|
Before Width: | Height: | Size: 398 KiB After Width: | Height: | Size: 398 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
@@ -81,11 +81,14 @@ public class Blocks implements ContentList{
|
|||||||
additiveReconstructor, multiplicativeReconstructor, exponentialReconstructor, tetrativeReconstructor,
|
additiveReconstructor, multiplicativeReconstructor, exponentialReconstructor, tetrativeReconstructor,
|
||||||
repairPoint, resupplyPoint,
|
repairPoint, resupplyPoint,
|
||||||
|
|
||||||
|
//logic
|
||||||
|
microProcessor, logicProcessor,
|
||||||
|
|
||||||
//campaign
|
//campaign
|
||||||
launchPad, launchPadLarge,
|
launchPad, launchPadLarge,
|
||||||
|
|
||||||
//misc experimental
|
//misc experimental
|
||||||
logicProcessor, blockForge, blockLoader, blockUnloader;
|
blockForge, blockLoader, blockUnloader;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(){
|
public void load(){
|
||||||
@@ -1885,15 +1888,29 @@ public class Blocks implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
//endregion campaign
|
//endregion campaign
|
||||||
//region experimental
|
//region logic
|
||||||
|
|
||||||
logicProcessor = new LogicProcessor("logic-processor"){{
|
microProcessor = new LogicBlock("micro-processor"){{
|
||||||
requirements(Category.effect, BuildVisibility.debugOnly, with(Items.copper, 200, Items.lead, 100));
|
requirements(Category.effect, with(Items.copper, 30, Items.lead, 50, Items.silicon, 30));
|
||||||
|
|
||||||
|
instructionsPerTick = 2;
|
||||||
|
memory = 32;
|
||||||
|
|
||||||
|
size = 1;
|
||||||
|
}};
|
||||||
|
|
||||||
|
logicProcessor = new LogicBlock("logic-processor"){{
|
||||||
|
requirements(Category.effect, with(Items.copper, 200, Items.lead, 120, Items.silicon, 100, Items.metaglass, 50));
|
||||||
|
|
||||||
|
instructionsPerTick = 5;
|
||||||
|
memory = 128;
|
||||||
|
|
||||||
size = 2;
|
size = 2;
|
||||||
alwaysUnlocked = true;
|
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
//region experimental
|
||||||
|
|
||||||
blockForge = new BlockForge("block-forge"){{
|
blockForge = new BlockForge("block-forge"){{
|
||||||
requirements(Category.production, BuildVisibility.debugOnly, with(Items.thorium, 100));
|
requirements(Category.production, BuildVisibility.debugOnly, with(Items.thorium, 100));
|
||||||
hasPower = true;
|
hasPower = true;
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
sound = new SoundLoop(block.activeSound, block.activeSoundVolume);
|
sound = new SoundLoop(block.activeSound, block.activeSoundVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
health(block.health);
|
health = block.health;
|
||||||
maxHealth(block.health);
|
maxHealth(block.health);
|
||||||
timer(new Interval(block.timers));
|
timer(new Interval(block.timers));
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
|
|
||||||
public final void readBase(Reads read){
|
public final void readBase(Reads read){
|
||||||
health = read.f();
|
health = read.f();
|
||||||
rotation(read.b());
|
rotation = read.b();
|
||||||
team = Team.get(read.b());
|
team = Team.get(read.b());
|
||||||
if(items != null) items.read(read);
|
if(items != null) items.read(read);
|
||||||
if(power != null) power.read(read);
|
if(power != null) power.read(read);
|
||||||
@@ -295,6 +295,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
|
|
||||||
/** Base efficiency. If this entity has non-buffered power, returns the power %, otherwise returns 1. */
|
/** Base efficiency. If this entity has non-buffered power, returns the power %, otherwise returns 1. */
|
||||||
public float efficiency(){
|
public float efficiency(){
|
||||||
|
//disabled -> 0 efficiency
|
||||||
|
if(!enabled) return 0;
|
||||||
return power != null && (block.consumes.has(ConsumeType.power) && !block.consumes.getPower().buffered) ? power.status : 1f;
|
return power != null && (block.consumes.has(ConsumeType.power) && !block.consumes.getPower().buffered) ? power.status : 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,6 +328,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
//endregion
|
//endregion
|
||||||
//region handler methods
|
//region handler methods
|
||||||
|
|
||||||
|
/** This is for logic blocks. */
|
||||||
|
public void handleString(Object value){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public void created(){}
|
public void created(){}
|
||||||
|
|
||||||
public boolean shouldConsume(){
|
public boolean shouldConsume(){
|
||||||
@@ -1190,7 +1197,9 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
loops.play(block.idleSound, base(), block.idleSoundVolume);
|
loops.play(block.idleSound, base(), block.idleSoundVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTile();
|
if(enabled || !block.noUpdateDisabled){
|
||||||
|
updateTile();
|
||||||
|
}
|
||||||
|
|
||||||
if(items != null){
|
if(items != null){
|
||||||
items.update(updateFlow);
|
items.update(updateFlow);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package mindustry.io;
|
|||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
|
import arc.util.ArcAnnotate.*;
|
||||||
import arc.util.io.*;
|
import arc.util.io.*;
|
||||||
import arc.util.pooling.*;
|
import arc.util.pooling.*;
|
||||||
import mindustry.ai.types.*;
|
import mindustry.ai.types.*;
|
||||||
@@ -78,11 +79,18 @@ public class TypeIO{
|
|||||||
}else if(object instanceof Boolean){
|
}else if(object instanceof Boolean){
|
||||||
write.b((byte)10);
|
write.b((byte)10);
|
||||||
write.bool((Boolean)object);
|
write.bool((Boolean)object);
|
||||||
|
}else if(object instanceof Double){
|
||||||
|
write.b((byte)11);
|
||||||
|
write.d((Double)object);
|
||||||
|
}else if(object instanceof Building){
|
||||||
|
write.b((byte)12);
|
||||||
|
write.i(((Building)object).pos());
|
||||||
}else{
|
}else{
|
||||||
throw new IllegalArgumentException("Unknown object type: " + object.getClass());
|
throw new IllegalArgumentException("Unknown object type: " + object.getClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public static Object readObject(Reads read){
|
public static Object readObject(Reads read){
|
||||||
byte type = read.b();
|
byte type = read.b();
|
||||||
switch(type){
|
switch(type){
|
||||||
@@ -97,6 +105,8 @@ public class TypeIO{
|
|||||||
case 8: byte len = read.b(); Point2[] out = new Point2[len]; for(int i = 0; i < len; i ++) out[i] = Point2.unpack(read.i()); return out;
|
case 8: byte len = read.b(); Point2[] out = new Point2[len]; for(int i = 0; i < len; i ++) out[i] = Point2.unpack(read.i()); return out;
|
||||||
case 9: return TechTree.getNotNull(content.getByID(ContentType.all[read.b()], read.s()));
|
case 9: return TechTree.getNotNull(content.getByID(ContentType.all[read.b()], read.s()));
|
||||||
case 10: return read.bool();
|
case 10: return read.bool();
|
||||||
|
case 11: return read.d();
|
||||||
|
case 12: return world.build(read.i());
|
||||||
default: throw new IllegalArgumentException("Unknown object type: " + type);
|
default: throw new IllegalArgumentException("Unknown object type: " + type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,11 @@ package mindustry.logic;
|
|||||||
|
|
||||||
import arc.func.*;
|
import arc.func.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
|
import arc.util.ArcAnnotate.*;
|
||||||
|
import mindustry.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.logic.LExecutor.*;
|
import mindustry.logic.LExecutor.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
|
||||||
/** "Compiles" a sequence of statements into instructions. */
|
/** "Compiles" a sequence of statements into instructions. */
|
||||||
public class LAssembler{
|
public class LAssembler{
|
||||||
@@ -16,10 +19,23 @@ public class LAssembler{
|
|||||||
LInstruction[] instructions;
|
LInstruction[] instructions;
|
||||||
|
|
||||||
public LAssembler(){
|
public LAssembler(){
|
||||||
|
putVar("@counter");
|
||||||
|
putConst("@time", 0);
|
||||||
|
|
||||||
//add default constants
|
//add default constants
|
||||||
putConst("false", 0);
|
putConst("false", 0);
|
||||||
putConst("true", 1);
|
putConst("true", 1);
|
||||||
putConst("null", null);
|
putConst("null", null);
|
||||||
|
|
||||||
|
//store base content (TODO hacky?)
|
||||||
|
|
||||||
|
for(Item item : Vars.content.items()){
|
||||||
|
putConst("@" + item.name, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Liquid liquid : Vars.content.liquids()){
|
||||||
|
putConst("@" + liquid.name, liquid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LAssembler assemble(String data){
|
public static LAssembler assemble(String data){
|
||||||
@@ -84,7 +100,7 @@ public class LAssembler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Adds a constant value by name. */
|
/** Adds a constant value by name. */
|
||||||
BVar putConst(String name, Object value){
|
public BVar putConst(String name, Object value){
|
||||||
BVar var = putVar(name);
|
BVar var = putVar(name);
|
||||||
var.constant = true;
|
var.constant = true;
|
||||||
var.value = value;
|
var.value = value;
|
||||||
@@ -92,7 +108,7 @@ public class LAssembler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Registers a variable name mapping. */
|
/** Registers a variable name mapping. */
|
||||||
BVar putVar(String name){
|
public BVar putVar(String name){
|
||||||
if(vars.containsKey(name)){
|
if(vars.containsKey(name)){
|
||||||
return vars.get(name);
|
return vars.get(name);
|
||||||
}else{
|
}else{
|
||||||
@@ -102,7 +118,11 @@ public class LAssembler{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A saved variable. */
|
public @Nullable BVar getVar(String name){
|
||||||
|
return vars.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A variable "builder". */
|
||||||
public static class BVar{
|
public static class BVar{
|
||||||
public int id;
|
public int id;
|
||||||
public boolean constant;
|
public boolean constant;
|
||||||
@@ -113,5 +133,14 @@ public class LAssembler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
BVar(){}
|
BVar(){}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return "BVar{" +
|
||||||
|
"id=" + id +
|
||||||
|
", constant=" + constant +
|
||||||
|
", value=" + value +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ import mindustry.graphics.*;
|
|||||||
public enum LCategory{
|
public enum LCategory{
|
||||||
blocks(Pal.accentBack),
|
blocks(Pal.accentBack),
|
||||||
control(Color.cyan.cpy().shiftSaturation(-0.6f).mul(0.7f)),
|
control(Color.cyan.cpy().shiftSaturation(-0.6f).mul(0.7f)),
|
||||||
operations(Pal.place.cpy().shiftSaturation(-0.5f).mul(0.7f));
|
operations(Pal.place.cpy().shiftSaturation(-0.5f).mul(0.7f)),
|
||||||
|
io(Pal.remove.cpy().shiftSaturation(-0.5f).mul(0.7f));;
|
||||||
|
|
||||||
public final Color color;
|
public final Color color;
|
||||||
|
|
||||||
|
|||||||
@@ -4,59 +4,56 @@ import arc.util.ArcAnnotate.*;
|
|||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
|
||||||
public class LExecutor{
|
public class LExecutor{
|
||||||
LInstruction[] instructions;
|
//special variables
|
||||||
int counter;
|
public static final int
|
||||||
|
varCounter = 0,
|
||||||
|
varTime = 1;
|
||||||
|
|
||||||
//values of all the variables
|
public double[] memory = {};
|
||||||
Var[] vars;
|
public LInstruction[] instructions = {};
|
||||||
|
public Var[] vars = {};
|
||||||
|
|
||||||
public boolean initialized(){
|
public boolean initialized(){
|
||||||
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 a single instruction. */
|
||||||
public void runAll(){
|
|
||||||
counter = 0;
|
|
||||||
|
|
||||||
while(counter < instructions.length){
|
|
||||||
instructions[counter++].run(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void runOnce(){
|
public void runOnce(){
|
||||||
//reset to start
|
//set time
|
||||||
if(counter >= instructions.length) counter = 0;
|
vars[varTime].numval = Time.millis();
|
||||||
|
|
||||||
if(counter < instructions.length){
|
//reset to start
|
||||||
instructions[counter++].run(this);
|
if(vars[varCounter].numval >= instructions.length) vars[varCounter].numval = 0;
|
||||||
|
|
||||||
|
if(vars[varCounter].numval < instructions.length){
|
||||||
|
instructions[(int)(vars[varCounter].numval++)].run(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load(Object context, String data){
|
public void load(String data){
|
||||||
load(context,LAssembler.assemble(data));
|
load(LAssembler.assemble(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load(Object context, LAssembler builder){
|
/** Loads with a specified assembler. Resets all variables. */
|
||||||
builder.putConst("this", context);
|
public void load(LAssembler builder){
|
||||||
|
|
||||||
vars = new Var[builder.vars.size];
|
vars = new Var[builder.vars.size];
|
||||||
instructions = builder.instructions;
|
instructions = builder.instructions;
|
||||||
counter = 0;
|
|
||||||
|
|
||||||
builder.vars.each((name, var) -> {
|
builder.vars.each((name, var) -> {
|
||||||
Var v = new Var();
|
Var dest = new Var(name);
|
||||||
vars[var.id] = v;
|
vars[var.id] = dest;
|
||||||
|
|
||||||
if(var.constant){
|
dest.constant = var.constant;
|
||||||
v.constant = true;
|
|
||||||
if(var.value instanceof Number){
|
if(var.value instanceof Number){
|
||||||
v.numval = ((Number)var.value).doubleValue();
|
dest.isobj = false;
|
||||||
}else{
|
dest.numval = ((Number)var.value).doubleValue();
|
||||||
v.isobj = true;
|
}else{
|
||||||
v.objval = var.value;
|
dest.isobj = true;
|
||||||
}
|
dest.objval = var.value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -65,12 +62,17 @@ public class LExecutor{
|
|||||||
|
|
||||||
@Nullable Building building(int index){
|
@Nullable Building building(int index){
|
||||||
Object o = vars[index].objval;
|
Object o = vars[index].objval;
|
||||||
return o == null && o instanceof Building ? (Building)o : null;
|
return vars[index].isobj && o instanceof Building ? (Building)o : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable Object obj(int index){
|
||||||
|
Object o = vars[index].objval;
|
||||||
|
return vars[index].isobj ? o : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean bool(int index){
|
boolean bool(int index){
|
||||||
Var v = vars[index];
|
Var v = vars[index];
|
||||||
return v.isobj ? v.objval != null : Math.abs(v.numval) < 0.0001;
|
return v.isobj ? v.objval != null : Math.abs(v.numval) >= 0.00001;
|
||||||
}
|
}
|
||||||
|
|
||||||
double num(int index){
|
double num(int index){
|
||||||
@@ -78,11 +80,6 @@ public class LExecutor{
|
|||||||
return v.isobj ? 0 : v.numval;
|
return v.isobj ? 0 : v.numval;
|
||||||
}
|
}
|
||||||
|
|
||||||
String str(int index){
|
|
||||||
Var v = vars[index];
|
|
||||||
return v.isobj ? String.valueOf(v.objval) : String.valueOf(v.numval);
|
|
||||||
}
|
|
||||||
|
|
||||||
int numi(int index){
|
int numi(int index){
|
||||||
return (int)num(index);
|
return (int)num(index);
|
||||||
}
|
}
|
||||||
@@ -104,11 +101,17 @@ public class LExecutor{
|
|||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
static class Var{
|
public static class Var{
|
||||||
boolean isobj, constant;
|
public final String name;
|
||||||
|
|
||||||
Object objval;
|
public boolean isobj, constant;
|
||||||
double numval;
|
|
||||||
|
public Object objval;
|
||||||
|
public double numval;
|
||||||
|
|
||||||
|
public Var(String name){
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//region instruction types
|
//region instruction types
|
||||||
@@ -135,11 +138,74 @@ public class LExecutor{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SenseI implements LInstruction{
|
public static class ReadI implements LInstruction{
|
||||||
public int from, to;
|
public int from, to;
|
||||||
|
|
||||||
|
public ReadI(int from, int to){
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadI(){
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(LExecutor exec){
|
public void run(LExecutor exec){
|
||||||
|
int address = exec.numi(from);
|
||||||
|
|
||||||
|
exec.setnum(to,address < 0 || address >= exec.memory.length ? 0 : exec.memory[address]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class WriteI implements LInstruction{
|
||||||
|
public int from, to;
|
||||||
|
|
||||||
|
public WriteI(int from, int to){
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WriteI(){
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(LExecutor exec){
|
||||||
|
int address = exec.numi(to);
|
||||||
|
|
||||||
|
if(address >= 0 && address < exec.memory.length){
|
||||||
|
exec.memory[address] = exec.num(from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SenseI implements LInstruction{
|
||||||
|
public int from, to, type;
|
||||||
|
|
||||||
|
public SenseI(int from, int to, int type){
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SenseI(){
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(LExecutor exec){
|
||||||
|
Building build = exec.building(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exec.setnum(to, output);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,22 +261,48 @@ public class LExecutor{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(LExecutor exec){
|
public void run(LExecutor exec){
|
||||||
exec.counter = exec.instructions.length;
|
exec.vars[varCounter].numval = exec.instructions.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PrintI implements LInstruction{
|
public static class PrintI implements LInstruction{
|
||||||
public int value;
|
private static final StringBuilder out = new StringBuilder();
|
||||||
|
|
||||||
public PrintI(int value){
|
public int value, target;
|
||||||
|
|
||||||
|
public PrintI(int value, int target){
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
this.target = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintI(){}
|
PrintI(){}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(LExecutor exec){
|
public void run(LExecutor exec){
|
||||||
Log.info(exec.str(value));
|
Building b = exec.building(target);
|
||||||
|
|
||||||
|
if(b == null) return;
|
||||||
|
|
||||||
|
//this should avoid any garbage allocation
|
||||||
|
Var v = exec.vars[value];
|
||||||
|
if(v.isobj){
|
||||||
|
if(v.objval instanceof String){
|
||||||
|
b.handleString(v.objval);
|
||||||
|
}else if(v.objval == null){
|
||||||
|
b.handleString("null");
|
||||||
|
}else{
|
||||||
|
b.handleString("[object]");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
out.setLength(0);
|
||||||
|
//display integer version when possible
|
||||||
|
if(Math.abs(v.numval - (int)v.numval) < 0.000001){
|
||||||
|
out.append((int)v.numval);
|
||||||
|
}else{
|
||||||
|
out.append(v.numval);
|
||||||
|
}
|
||||||
|
b.handleString(out);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +319,7 @@ public class LExecutor{
|
|||||||
@Override
|
@Override
|
||||||
public void run(LExecutor exec){
|
public void run(LExecutor exec){
|
||||||
if(to != -1 && exec.bool(cond)){
|
if(to != -1 && exec.bool(cond)){
|
||||||
exec.counter = to;
|
exec.vars[varCounter].numval = to;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,102 @@ 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 arc.util.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.logic.LExecutor.*;
|
|
||||||
import mindustry.logic.LCanvas.*;
|
import mindustry.logic.LCanvas.*;
|
||||||
|
import mindustry.logic.LExecutor.*;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
|
|
||||||
public class LStatements{
|
public class LStatements{
|
||||||
|
|
||||||
|
@RegisterStatement("write")
|
||||||
|
public static class WriteStatement extends LStatement{
|
||||||
|
public String to = "0";
|
||||||
|
public String from = "result";
|
||||||
|
|
||||||
|
@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);
|
||||||
|
|
||||||
|
table.add(" = ");
|
||||||
|
|
||||||
|
table.field(from, Styles.nodeField, str -> from = str)
|
||||||
|
.size(100f, 40f).pad(2f).color(table.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LCategory category(){
|
||||||
|
return LCategory.io;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LInstruction build(LAssembler builder){
|
||||||
|
return new WriteI(builder.var(from), builder.var(to));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RegisterStatement("read")
|
||||||
|
public static class ReadStatement extends LStatement{
|
||||||
|
public String to = "result";
|
||||||
|
public String from = "0";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build(Table table){
|
||||||
|
table.field(to, Styles.nodeField, str -> to = str)
|
||||||
|
.size(100f, 40f).pad(2f).color(table.color);
|
||||||
|
|
||||||
|
table.add(" = mem:: ");
|
||||||
|
|
||||||
|
table.field(from, Styles.nodeField, str -> from = str)
|
||||||
|
.size(100f, 40f).pad(2f).color(table.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LCategory category(){
|
||||||
|
return LCategory.io;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LInstruction build(LAssembler builder){
|
||||||
|
return new ReadI(builder.var(from), builder.var(to));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RegisterStatement("sensor")
|
||||||
|
public static class SensorStatement extends LStatement{
|
||||||
|
public String to = "result";
|
||||||
|
public String from = "@0", type = "@copper";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build(Table table){
|
||||||
|
table.field(to, Styles.nodeField, str -> to = str)
|
||||||
|
.size(100f, 40f).pad(2f).color(table.color);
|
||||||
|
|
||||||
|
table.add(" = ");
|
||||||
|
|
||||||
|
table.field(type, Styles.nodeField, str -> type = str)
|
||||||
|
.size(100f, 40f).pad(2f).color(table.color);
|
||||||
|
|
||||||
|
table.add(" in ");
|
||||||
|
|
||||||
|
table.field(from, Styles.nodeField, str -> from = str)
|
||||||
|
.size(100f, 40f).pad(2f).color(table.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LCategory category(){
|
||||||
|
return LCategory.operations;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LInstruction build(LAssembler builder){
|
||||||
|
return new SenseI(builder.var(from), builder.var(to), builder.var(type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@RegisterStatement("set")
|
@RegisterStatement("set")
|
||||||
public static class SetStatement extends LStatement{
|
public static class SetStatement extends LStatement{
|
||||||
public String to = "result";
|
public String to = "result";
|
||||||
@@ -122,16 +211,22 @@ public class LStatements{
|
|||||||
@RegisterStatement("print")
|
@RegisterStatement("print")
|
||||||
public static class PrintStatement extends LStatement{
|
public static class PrintStatement extends LStatement{
|
||||||
public String value = "\"frog\"";
|
public String value = "\"frog\"";
|
||||||
|
public String target = "result";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(Table table){
|
public void build(Table table){
|
||||||
table.field(value, Styles.nodeField, str -> value = str)
|
table.field(value, Styles.nodeField, str -> value = str)
|
||||||
.size(100f, 40f).pad(2f).color(table.color);
|
.size(100f, 40f).pad(2f).color(table.color);
|
||||||
|
|
||||||
|
table.add(" to ");
|
||||||
|
|
||||||
|
table.field(target, Styles.nodeField, str -> target = str)
|
||||||
|
.size(100f, 40f).pad(2f).color(table.color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LInstruction build(LAssembler builder){
|
public LInstruction build(LAssembler builder){
|
||||||
return new PrintI(builder.var(value));
|
return new PrintI(builder.var(value), builder.var(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -182,6 +277,8 @@ public class LStatements{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//disabled until further notice - bypasses the network
|
||||||
|
/*
|
||||||
@RegisterStatement("getbuild")
|
@RegisterStatement("getbuild")
|
||||||
public static class getBuildStatement extends LStatement{
|
public static class getBuildStatement extends LStatement{
|
||||||
public String x = "0", y = "0", dest = "result";
|
public String x = "0", y = "0", dest = "result";
|
||||||
@@ -211,5 +308,5 @@ public class LStatements{
|
|||||||
public LCategory category(){
|
public LCategory category(){
|
||||||
return LCategory.blocks;
|
return LCategory.blocks;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package mindustry.mod;
|
|||||||
|
|
||||||
/** Mod listing as a data class. */
|
/** Mod listing as a data class. */
|
||||||
public class ModListing{
|
public class ModListing{
|
||||||
public String repo, name, author, lastUpdated, description;
|
public String repo, name, author, lastUpdated, description, minGameVersion;
|
||||||
public int stars;
|
public int stars;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -13,6 +13,7 @@ public class ModListing{
|
|||||||
", author='" + author + '\'' +
|
", author='" + author + '\'' +
|
||||||
", lastUpdated='" + lastUpdated + '\'' +
|
", lastUpdated='" + lastUpdated + '\'' +
|
||||||
", description='" + description + '\'' +
|
", description='" + description + '\'' +
|
||||||
|
", minGameVersion='" + minGameVersion + '\'' +
|
||||||
", stars=" + stars +
|
", stars=" + stars +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public class Scripts implements Disposable{
|
|||||||
private final Seq<String> blacklist = Seq.with(".net.", "java.net", "files", "reflect", "javax", "rhino", "file", "channels", "jdk",
|
private final Seq<String> blacklist = Seq.with(".net.", "java.net", "files", "reflect", "javax", "rhino", "file", "channels", "jdk",
|
||||||
"runtime", "util.os", "rmi", "security", "org.", "sun.", "beans", "sql", "http", "exec", "compiler", "process", "system",
|
"runtime", "util.os", "rmi", "security", "org.", "sun.", "beans", "sql", "http", "exec", "compiler", "process", "system",
|
||||||
".awt", "socket", "classloader", "oracle", "invoke", "java.util.function", "java.util.stream", "org.");
|
".awt", "socket", "classloader", "oracle", "invoke", "java.util.function", "java.util.stream", "org.");
|
||||||
private final Seq<String> whitelist = Seq.with("mindustry.net", "netserver", "netclient", "com.sun.proxy.$proxy", "mindustry.gen.");
|
private final Seq<String> whitelist = Seq.with("mindustry.net", "netserver", "netclient", "com.sun.proxy.$proxy", "mindustry.gen.", "mindustry.logic.");
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final Scriptable scope;
|
private final Scriptable scope;
|
||||||
private boolean errored;
|
private boolean errored;
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ public class Block extends UnlockableContent{
|
|||||||
public boolean absorbLasers = false;
|
public boolean absorbLasers = false;
|
||||||
/** if false, the status is never drawn */
|
/** if false, the status is never drawn */
|
||||||
public boolean enableDrawStatus = true;
|
public boolean enableDrawStatus = true;
|
||||||
|
/** if true, the block stops updating when disabled */
|
||||||
|
public boolean noUpdateDisabled = false;
|
||||||
/** tile entity health */
|
/** tile entity health */
|
||||||
public int health = -1;
|
public int health = -1;
|
||||||
/** base block explosiveness */
|
/** base block explosiveness */
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ public class Conveyor extends Block implements Autotiler{
|
|||||||
idleSound = Sounds.conveyor;
|
idleSound = Sounds.conveyor;
|
||||||
idleSoundVolume = 0.004f;
|
idleSoundVolume = 0.004f;
|
||||||
unloadable = false;
|
unloadable = false;
|
||||||
|
noUpdateDisabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -114,7 +115,7 @@ public class Conveyor extends Block implements Autotiler{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void draw(){
|
||||||
int frame = clogHeat <= 0.5f ? (int)(((Time.time() * speed * 8f * timeScale())) % 4) : 0;
|
int frame = enabled && clogHeat <= 0.5f ? (int)(((Time.time() * speed * 8f * timeScale())) % 4) : 0;
|
||||||
|
|
||||||
//draw extra conveyors facing this one for non-square tiling purposes
|
//draw extra conveyors facing this one for non-square tiling purposes
|
||||||
Draw.z(Layer.blockUnder);
|
Draw.z(Layer.blockUnder);
|
||||||
@@ -208,10 +209,11 @@ public class Conveyor extends Block implements Autotiler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
float nextMax = aligned ? 1f - Math.max(itemSpace - nextc.minitem, 0) : 1f;
|
float nextMax = aligned ? 1f - Math.max(itemSpace - nextc.minitem, 0) : 1f;
|
||||||
|
float moved = speed * edelta();
|
||||||
|
|
||||||
for(int i = len - 1; i >= 0; i--){
|
for(int i = len - 1; i >= 0; i--){
|
||||||
float nextpos = (i == len - 1 ? 100f : ys[i + 1]) - itemSpace;
|
float nextpos = (i == len - 1 ? 100f : ys[i + 1]) - itemSpace;
|
||||||
float maxmove = Mathf.clamp(nextpos - ys[i], 0, speed * delta());
|
float maxmove = Mathf.clamp(nextpos - ys[i], 0, moved);
|
||||||
|
|
||||||
ys[i] += maxmove;
|
ys[i] += maxmove;
|
||||||
|
|
||||||
|
|||||||
293
core/src/mindustry/world/blocks/logic/LogicBlock.java
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
package mindustry.world.blocks.logic;
|
||||||
|
|
||||||
|
import arc.func.*;
|
||||||
|
import arc.scene.ui.layout.*;
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import arc.util.io.*;
|
||||||
|
import mindustry.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.io.*;
|
||||||
|
import mindustry.logic.*;
|
||||||
|
import mindustry.logic.LAssembler.*;
|
||||||
|
import mindustry.logic.LExecutor.*;
|
||||||
|
import mindustry.ui.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
|
public class LogicBlock extends Block{
|
||||||
|
private static final IntSeq removal = new IntSeq();
|
||||||
|
|
||||||
|
public int maxInstructionScale = 8;
|
||||||
|
public int instructionsPerTick = 1;
|
||||||
|
public float range = 8 * 10;
|
||||||
|
public int memory = 16;
|
||||||
|
|
||||||
|
public LogicBlock(String name){
|
||||||
|
super(name);
|
||||||
|
update = true;
|
||||||
|
configurable = true;
|
||||||
|
|
||||||
|
config(String.class, (LogicEntity entity, String code) -> entity.updateCode(code));
|
||||||
|
|
||||||
|
config(Integer.class, (LogicEntity entity, Integer pos) -> {
|
||||||
|
if(entity.connections.contains(pos)){
|
||||||
|
entity.connections.removeValue(pos);
|
||||||
|
}else{
|
||||||
|
entity.connections.add(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.updateCode(entity.code);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LogicEntity extends Building{
|
||||||
|
/** logic "source code" as list of asm statements */
|
||||||
|
public String code = "";
|
||||||
|
public LExecutor executor = new LExecutor();
|
||||||
|
public float accumulator = 0;
|
||||||
|
public IntSeq connections = new IntSeq();
|
||||||
|
public boolean loaded = false;
|
||||||
|
|
||||||
|
public LogicEntity(){
|
||||||
|
executor.memory = new double[memory];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateCode(String str){
|
||||||
|
updateCode(str, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateCode(String str, Cons<LAssembler> assemble){
|
||||||
|
if(str != null){
|
||||||
|
code = str;
|
||||||
|
|
||||||
|
try{
|
||||||
|
//create assembler to store extra variables
|
||||||
|
LAssembler asm = LAssembler.assemble(str);
|
||||||
|
|
||||||
|
//store connections
|
||||||
|
for(int i = 0; i < connections.size; i++){
|
||||||
|
asm.putConst("@" + i, world.build(connections.get(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//store any older variables
|
||||||
|
for(Var var : executor.vars){
|
||||||
|
if(!var.constant){
|
||||||
|
BVar dest = asm.getVar(var.name);
|
||||||
|
if(dest != null && !dest.constant){
|
||||||
|
dest.value = var.isobj ? var.objval : var.numval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//inject any extra variables
|
||||||
|
if(assemble != null){
|
||||||
|
assemble.get(asm);
|
||||||
|
}
|
||||||
|
|
||||||
|
asm.putConst("@this", this);
|
||||||
|
|
||||||
|
executor.load(asm);
|
||||||
|
}catch(Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
|
||||||
|
//handle malformed code and replace it with nothing
|
||||||
|
executor.load("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProximityUpdate(){
|
||||||
|
super.onProximityUpdate();
|
||||||
|
|
||||||
|
if(!loaded){
|
||||||
|
//properly fetches connections
|
||||||
|
updateCode(code);
|
||||||
|
loaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateTile(){
|
||||||
|
//remove invalid links
|
||||||
|
//TODO remove variables
|
||||||
|
removal.clear();
|
||||||
|
|
||||||
|
for(int i = 0; i < connections.size; i++){
|
||||||
|
int val = connections.get(i);
|
||||||
|
if(!validLink(val)){
|
||||||
|
removal.add(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!removal.isEmpty()){
|
||||||
|
updateCode(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
connections.removeAll(removal);
|
||||||
|
|
||||||
|
accumulator += edelta() * instructionsPerTick;
|
||||||
|
|
||||||
|
if(accumulator > maxInstructionScale * instructionsPerTick) accumulator = maxInstructionScale * instructionsPerTick;
|
||||||
|
|
||||||
|
for(int i = 0; i < (int)accumulator; i++){
|
||||||
|
if(executor.initialized()){
|
||||||
|
executor.runOnce();
|
||||||
|
}
|
||||||
|
|
||||||
|
accumulator --;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String config(){
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawConfigure(){
|
||||||
|
super.drawConfigure();
|
||||||
|
|
||||||
|
Drawf.circles(x, y, range);
|
||||||
|
|
||||||
|
for(int i = 0; i < connections.size; i++){
|
||||||
|
int pos = connections.get(i);
|
||||||
|
|
||||||
|
if(validLink(pos)){
|
||||||
|
Building other = Vars.world.build(pos);
|
||||||
|
Drawf.square(other.x, other.y, other.block.size * tilesize / 2f + 1f, Pal.place);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//draw top text on separate layer
|
||||||
|
for(int i = 0; i < connections.size; i++){
|
||||||
|
int pos = connections.get(i);
|
||||||
|
|
||||||
|
if(validLink(pos)){
|
||||||
|
Building other = Vars.world.build(pos);
|
||||||
|
other.block.drawPlaceText("@" + i, other.tileX(), other.tileY(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean validLink(int pos){
|
||||||
|
Building other = Vars.world.build(pos);
|
||||||
|
return other != null && other.team == team && other.within(this, range + other.block.size*tilesize/2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawSelect(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void buildConfiguration(Table table){
|
||||||
|
Table cont = new Table();
|
||||||
|
cont.defaults().size(40);
|
||||||
|
|
||||||
|
cont.button(Icon.pencil, Styles.clearTransi, () -> {
|
||||||
|
Vars.ui.logic.show(code, this::configure);
|
||||||
|
});
|
||||||
|
|
||||||
|
//cont.button(Icon.refreshSmall, Styles.clearTransi, () -> {
|
||||||
|
|
||||||
|
//});
|
||||||
|
|
||||||
|
table.add(cont);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onConfigureTileTapped(Building other){
|
||||||
|
if(this == other){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(validLink(other.pos())){
|
||||||
|
configure(other.pos());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onConfigureTileTapped(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Writes write){
|
||||||
|
super.write(write);
|
||||||
|
|
||||||
|
write.str(code);
|
||||||
|
write.s(connections.size);
|
||||||
|
for(int i = 0; i < connections.size; i++){
|
||||||
|
write.i(connections.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
//write only the non-constant variables
|
||||||
|
int count = Structs.count(executor.vars, v -> !v.constant);
|
||||||
|
|
||||||
|
write.i(count);
|
||||||
|
for(int i = 0; i < executor.vars.length; i++){
|
||||||
|
Var v = executor.vars[i];
|
||||||
|
|
||||||
|
if(v.constant) continue;
|
||||||
|
|
||||||
|
//write the name and the object value
|
||||||
|
write.str(v.name);
|
||||||
|
|
||||||
|
Object value = v.isobj ? v.objval : v.numval;
|
||||||
|
TypeIO.writeObject(write, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
write.i(executor.memory.length);
|
||||||
|
for(int i = 0; i < executor.memory.length; i++){
|
||||||
|
write.d(executor.memory[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(Reads read, byte revision){
|
||||||
|
super.read(read, revision);
|
||||||
|
|
||||||
|
code = read.str();
|
||||||
|
connections.clear();
|
||||||
|
short total = read.s();
|
||||||
|
for(int i = 0; i < total; i++){
|
||||||
|
connections.add(read.i());
|
||||||
|
}
|
||||||
|
|
||||||
|
int varcount = read.i();
|
||||||
|
|
||||||
|
//variables need to be temporarily stored in an array until they can be used
|
||||||
|
String[] names = new String[varcount];
|
||||||
|
Object[] values = new Object[varcount];
|
||||||
|
|
||||||
|
for(int i = 0; i < varcount; i++){
|
||||||
|
String name = read.str();
|
||||||
|
Object value = TypeIO.readObject(read);
|
||||||
|
|
||||||
|
names[i] = name;
|
||||||
|
values[i] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int memory = read.i();
|
||||||
|
double[] memorybank = executor.memory.length != memory ? new double[memory] : executor.memory;
|
||||||
|
for(int i = 0; i < memory; i++){
|
||||||
|
memorybank[i] = read.d();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCode(code, asm -> {
|
||||||
|
|
||||||
|
//load up the variables that were stored
|
||||||
|
for(int i = 0; i < varcount; i++){
|
||||||
|
BVar dest = asm.getVar(names[i]);
|
||||||
|
if(dest != null && !dest.constant){
|
||||||
|
dest.value = values[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
executor.memory = memorybank;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
package mindustry.world.blocks.logic;
|
|
||||||
|
|
||||||
import arc.util.io.*;
|
|
||||||
import mindustry.*;
|
|
||||||
import mindustry.gen.*;
|
|
||||||
import mindustry.logic.*;
|
|
||||||
import mindustry.world.*;
|
|
||||||
|
|
||||||
public class LogicProcessor extends Block{
|
|
||||||
|
|
||||||
public LogicProcessor(String name){
|
|
||||||
super(name);
|
|
||||||
update = true;
|
|
||||||
configurable = true;
|
|
||||||
|
|
||||||
config(String.class, (LogicEntity entity, String code) -> {
|
|
||||||
if(code != null){
|
|
||||||
entity.code = 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{
|
|
||||||
/** logic "source code" as list of json statements */
|
|
||||||
String code = "";
|
|
||||||
LExecutor executor = new LExecutor();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateTile(){
|
|
||||||
if(executor.initialized()){
|
|
||||||
executor.runOnce();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean configTapped(){
|
|
||||||
Vars.ui.logic.show(code, this::configure);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(Writes write){
|
|
||||||
super.write(write);
|
|
||||||
|
|
||||||
write.str(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void read(Reads read, byte revision){
|
|
||||||
super.read(read, revision);
|
|
||||||
|
|
||||||
code = read.str();
|
|
||||||
try{
|
|
||||||
executor.load(this, code);
|
|
||||||
}catch(Exception e){
|
|
||||||
e.printStackTrace();
|
|
||||||
|
|
||||||
//handle malformed code and ignore it
|
|
||||||
executor = new LExecutor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -34,7 +34,9 @@ public class MessageBlock extends Block{
|
|||||||
throw new ValidateException(player, "Player has gone above text limit.");
|
throw new ValidateException(player, "Player has gone above text limit.");
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder result = new StringBuilder(text.length());
|
tile.message.ensureCapacity(text.length());
|
||||||
|
tile.message.setLength(0);
|
||||||
|
|
||||||
text = text.trim();
|
text = text.trim();
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for(int i = 0; i < text.length(); i++){
|
for(int i = 0; i < text.length(); i++){
|
||||||
@@ -42,21 +44,17 @@ public class MessageBlock extends Block{
|
|||||||
if(c == '\n' || c == '\r'){
|
if(c == '\n' || c == '\r'){
|
||||||
count ++;
|
count ++;
|
||||||
if(count <= maxNewlines){
|
if(count <= maxNewlines){
|
||||||
result.append('\n');
|
tile.message.append('\n');
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
result.append(c);
|
tile.message.append(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tile.message = result.toString();
|
|
||||||
tile.lines = tile.message.split("\n");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MessageBlockEntity extends Building{
|
public class MessageBlockEntity extends Building{
|
||||||
public String message = "";
|
public StringBuilder message = new StringBuilder();
|
||||||
public String[] lines = {""};
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawSelect(){
|
public void drawSelect(){
|
||||||
@@ -68,7 +66,7 @@ public class MessageBlock extends Block{
|
|||||||
font.getData().setScale(1 / 4f / Scl.scl(1f));
|
font.getData().setScale(1 / 4f / Scl.scl(1f));
|
||||||
font.setUseIntegerPositions(false);
|
font.setUseIntegerPositions(false);
|
||||||
|
|
||||||
String text = message == null || message.isEmpty() ? "[lightgray]" + Core.bundle.get("empty") : message;
|
CharSequence text = message == null || message.length() == 0 ? "[lightgray]" + Core.bundle.get("empty") : message;
|
||||||
|
|
||||||
l.setText(font, text, Color.white, 90f, Align.left, true);
|
l.setText(font, text, Color.white, 90f, Align.left, true);
|
||||||
float offset = 1f;
|
float offset = 1f;
|
||||||
@@ -90,7 +88,7 @@ public class MessageBlock extends Block{
|
|||||||
table.button(Icon.pencil, () -> {
|
table.button(Icon.pencil, () -> {
|
||||||
if(mobile){
|
if(mobile){
|
||||||
Core.input.getTextInput(new TextInput(){{
|
Core.input.getTextInput(new TextInput(){{
|
||||||
text = message;
|
text = message.toString();
|
||||||
multiline = true;
|
multiline = true;
|
||||||
maxLength = maxTextLength;
|
maxLength = maxTextLength;
|
||||||
accepted = str -> configure(str);
|
accepted = str -> configure(str);
|
||||||
@@ -98,7 +96,7 @@ public class MessageBlock extends Block{
|
|||||||
}else{
|
}else{
|
||||||
BaseDialog dialog = new BaseDialog("@editmessage");
|
BaseDialog dialog = new BaseDialog("@editmessage");
|
||||||
dialog.setFillParent(false);
|
dialog.setFillParent(false);
|
||||||
TextArea a = dialog.cont.add(new TextArea(message.replace("\n", "\r"))).size(380f, 160f).get();
|
TextArea a = dialog.cont.add(new TextArea(message.toString().replace("\n", "\r"))).size(380f, 160f).get();
|
||||||
a.setFilter((textField, c) -> {
|
a.setFilter((textField, c) -> {
|
||||||
if(c == '\n' || c == '\r'){
|
if(c == '\n' || c == '\r'){
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -127,6 +125,12 @@ public class MessageBlock extends Block{
|
|||||||
}).size(40f);
|
}).size(40f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleString(Object value){
|
||||||
|
message.setLength(0);
|
||||||
|
message.append(value);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateTableAlign(Table table){
|
public void updateTableAlign(Table table){
|
||||||
Vec2 pos = Core.input.mouseScreen(x, y + size * tilesize / 2f + 1);
|
Vec2 pos = Core.input.mouseScreen(x, y + size * tilesize / 2f + 1);
|
||||||
@@ -135,19 +139,19 @@ public class MessageBlock extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String config(){
|
public String config(){
|
||||||
return message;
|
return message.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(Writes write){
|
public void write(Writes write){
|
||||||
super.write(write);
|
super.write(write);
|
||||||
write.str(message);
|
write.str(message.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(Reads read, byte revision){
|
public void read(Reads read, byte revision){
|
||||||
super.read(read, revision);
|
super.read(read, revision);
|
||||||
message = read.str();
|
message = new StringBuilder(read.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||