Add logic filter (#7251)

* logic filter

* bundles

* available in map editor

* @this = null

* generating only

* ensure not using net

---------

Co-authored-by: Anuken <arnukren@gmail.com>
This commit is contained in:
BlackDeluxeCat
2024-04-25 22:23:13 +08:00
committed by GitHub
parent 7fcde1e109
commit bac6f7cfa9
4 changed files with 88 additions and 3 deletions

View File

@@ -60,7 +60,7 @@ public class LExecutor{
public @Nullable LogicBuild build;
public IntSet linkIds = new IntSet();
public Team team = Team.derelict;
public boolean privileged = false;
public boolean privileged = false, isFilter = false;
//yes, this is a minor memory leak, but it's probably not significant enough to matter
protected static IntFloatMap unitTimeouts = new IntFloatMap();
@@ -1479,7 +1479,7 @@ public class LExecutor{
if(t == null) t = Team.derelict;
if(tile.block() != b || tile.team() != t){
tile.setNet(b, t, Mathf.clamp(exec.numi(rotation), 0, 3));
tile.setBlock(b, t, Mathf.clamp(exec.numi(rotation), 0, 3));
}
}
}

View File

@@ -33,7 +33,7 @@ public class Maps{
NoiseFilter::new, ScatterFilter::new, TerrainFilter::new, DistortFilter::new,
RiverNoiseFilter::new, OreFilter::new, OreMedianFilter::new, MedianFilter::new,
BlendFilter::new, MirrorFilter::new, ClearFilter::new, CoreSpawnFilter::new,
EnemySpawnFilter::new, SpawnPathFilter::new
EnemySpawnFilter::new, SpawnPathFilter::new, LogicFilter::new
};
/** List of all built-in maps. Filenames only. */

View File

@@ -0,0 +1,82 @@
package mindustry.maps.filters;
import arc.scene.ui.layout.*;
import mindustry.gen.*;
import mindustry.logic.*;
import mindustry.maps.filters.FilterOption.*;
import mindustry.world.*;
import static mindustry.Vars.*;
public class LogicFilter extends GenerateFilter{
/** max available execution for logic filter */
public static int maxInstructionsExecution = 500 * 500 * 25;
public String code;
public boolean loop;
LExecutor executor;
@Override
public FilterOption[] options(){
return new FilterOption[]{
new FilterOption(){
final String name;
{
name = "code";
}
@Override
public void build(Table table){
table.button(b -> b.image(Icon.pencil).size(iconSmall), () -> {
ui.logic.show(code, null, true, code -> LogicFilter.this.code = code);
}).pad(4).margin(12f);
table.add("@filter.option." + name);
}
},
new ToggleOption("loop", () -> loop, f -> loop = f)
};
}
@Override
public void apply(Tiles tiles, GenerateInput in){
executor = new LExecutor();
executor.privileged = true;
executor.isFilter = true;
configure(code);
//limited run
for(int i = 1; i < maxInstructionsExecution; i++){
if(!loop && (executor.counter.numval >= executor.instructions.length || executor.counter.numval < 0)) break;
executor.runOnce();
}
}
@Override
public char icon(){
return Iconc.blockMicroProcessor;
}
@Override
public boolean isPost(){
return true;
}
void configure(String code){
try{
//create assembler to store extra variables
LAssembler asm = LAssembler.assemble(code, true);
asm.putConst("@mapw", world.width());
asm.putConst("@maph", world.height());
asm.putConst("@links", executor.links.length);
asm.putConst("@ipt", 1);
asm.putConst("@thisx", 0);
asm.putConst("@thisy", 0);
executor.load(asm);
}catch(Exception e){
//handle malformed code and replace it with nothing
executor.load(LAssembler.assemble(code = "", true));
}
}
}