Many various fixes

This commit is contained in:
Anuken
2020-09-03 14:04:30 -04:00
parent 13a2319416
commit 90aed50ca8
15 changed files with 151 additions and 95 deletions

View File

@@ -37,7 +37,7 @@ public class BlockIndexer{
/** All ores available on this map. */
private ObjectSet<Item> allOres = new ObjectSet<>();
/** Stores teams that are present here as tiles. */
private Seq<Team> activeTeams = new Seq<>();
private Seq<Team> activeTeams = new Seq<>(Team.class);
/** Maps teams to a map of flagged tiles by flag. */
private TileArray[][] flagMap = new TileArray[Team.all.length][BlockFlag.all.length];
/** Max units by team. */
@@ -52,7 +52,7 @@ public class BlockIndexer{
private Seq<Building> breturnArray = new Seq<>();
public BlockIndexer(){
Events.on(BuildinghangeEvent.class, event -> {
Events.on(TileChangeEvent.class, event -> {
if(typeMap.get(event.tile.pos()) != null){
TileIndex index = typeMap.get(event.tile.pos());
for(BlockFlag flag : index.flags){
@@ -73,6 +73,7 @@ public class BlockIndexer{
damagedTiles = new BuildingArray[Team.all.length];
flagMap = new TileArray[Team.all.length][BlockFlag.all.length];
unitCaps = new int[Team.all.length];
activeTeams = new Seq<>(Team.class);
for(int i = 0; i < flagMap.length; i++){
for(int j = 0; j < BlockFlag.all.length; j++){
@@ -220,7 +221,10 @@ public class BlockIndexer{
}
public Building findEnemyTile(Team team, float x, float y, float range, Boolf<Building> pred){
for(Team enemy : team.enemies()){
for(int i = 0; i < activeTeams.size; i++){
Team enemy = activeTeams.items[i];
if(enemy == team) continue;
Building entity = indexer.findTile(enemy, x, y, range, pred, true);
if(entity != null){

View File

@@ -38,32 +38,35 @@ public class Pathfinder implements Runnable{
costWater = 2;
public static final Seq<PathCost> costTypes = Seq.with(
//ground
(team, tile) -> (PathTile.team(tile) == team.id || PathTile.team(tile) == 0) && PathTile.solid(tile) ? impassable : 1 +
PathTile.health(tile) * 5 +
(PathTile.nearSolid(tile) ? 2 : 0) +
(PathTile.nearLiquid(tile) ? 6 : 0) +
(PathTile.deep(tile) ? 70 : 0),
//legs
(team, tile) -> PathTile.legSolid(tile) ? impassable : 1 +
(PathTile.solid(tile) ? 5 : 0),
(team, tile) -> PathTile.solid(tile) || !PathTile.liquid(tile) ? impassable : 2 + //TODO cannot go through blocks
//water
(team, tile) -> PathTile.solid(tile) || !PathTile.liquid(tile) ? 200 : 2 + //TODO cannot go through blocks - pathfinding isn't great
(PathTile.nearGround(tile) || PathTile.nearSolid(tile) ? 14 : 0) +
(PathTile.deep(tile) ? -1 : 0)
);
//maps team, cost, type to flow field
private Flowfield[][][] cache;
Flowfield[][][] cache;
/** tile data, see PathTileStruct */
private int[][] tiles;
int[][] tiles;
/** unordered array of path data for iteration only. DO NOT iterate or access this in the main thread. */
private Seq<Flowfield> threadList = new Seq<>(), mainList = new Seq<>();
Seq<Flowfield> threadList = new Seq<>(), mainList = new Seq<>();
/** handles task scheduling on the update thread. */
private TaskQueue queue = new TaskQueue();
TaskQueue queue = new TaskQueue();
/** Current pathfinding thread */
private @Nullable Thread thread;
private IntSeq tmpArray = new IntSeq();
@Nullable Thread thread;
IntSeq tmpArray = new IntSeq();
public Pathfinder(){
clearCache();
@@ -89,7 +92,7 @@ public class Pathfinder implements Runnable{
Events.on(ResetEvent.class, event -> stop());
Events.on(BuildinghangeEvent.class, event -> updateTile(event.tile));
Events.on(TileChangeEvent.class, event -> updateTile(event.tile));
}
private void clearCache(){
@@ -115,7 +118,7 @@ public class Pathfinder implements Runnable{
tile.getTeamID(),
tile.solid(),
tile.floor().isLiquid,
tile.staticDarkness() < 2,
tile.staticDarkness() >= 2,
nearLiquid,
nearGround,
nearSolid,
@@ -220,10 +223,6 @@ public class Pathfinder implements Runnable{
}
}
//public @Nullable Tile getTargetTile(Tile tile, Team team, Position target){
// return getTargetTile(tile, team, getTarget(target));
// }
public Flowfield getField(Team team, int costType, int fieldType){
if(cache[team.id][costType][fieldType] == null){
Flowfield field = fieldTypes.get(fieldType).get();
@@ -277,8 +276,8 @@ public class Pathfinder implements Runnable{
Tile other = world.tile(dx, dy);
if(other == null) continue;
if(values[dx][dy] < value && (current == null || values[dx][dy] < tl) && !other.solid() && other.floor().drownTime <= 0 &&
!(point.x != 0 && point.y != 0 && (world.solid(tile.x + point.x, tile.y) || world.solid(tile.x, tile.y + point.y)))){ //diagonal corner trap
if(values[dx][dy] < value && (current == null || values[dx][dy] < tl) && path.passable(dx, dy) &&
!(point.x != 0 && point.y != 0 && (!path.passable(tile.x + point.x, tile.y) || !path.passable(tile.x, tile.y + point.y)))){ //diagonal corner trap
current = other;
tl = values[dx][dy];
}
@@ -390,10 +389,12 @@ public class Pathfinder implements Runnable{
}
if(cost != impassable){
//TODO this is probably slow.
for(Point2 point : Geometry.d4){
int dx = tile.x + point.x, dy = tile.y + point.y;
if(dx < 0 || dy < 0 || dx >= tiles.length || dy >= tiles[0].length) continue;
int otherCost = path.cost.getCost(path.team, tiles[dx][dy]);
if((path.weights[dx][dy] > cost + otherCost || path.searches[dx][dy] < path.search) && otherCost != impassable){
@@ -480,6 +481,10 @@ public class Pathfinder implements Runnable{
this.initialized = true;
}
protected boolean passable(int x, int y){
return cost.getCost(team, pathfinder.tiles[x][y]) != impassable;
}
/** Gets targets to pathfind towards. This must run on the main thread. */
protected abstract void getPositions(IntSeq out);
}

View File

@@ -1,5 +1,6 @@
package mindustry.ai.types;
import arc.math.*;
import mindustry.ai.*;
import mindustry.entities.*;
import mindustry.entities.units.*;
@@ -33,14 +34,14 @@ public class GroundAI extends AIController{
if(spawner != null && unit.within(spawner, state.rules.dropZoneRadius + 120f)) move = false;
}
if(move) moveToCore(FlagTarget.enemyCores);
if(move) moveTo(Pathfinder.fieldCore);
}
if(command() == UnitCommand.rally){
Teamc target = targetFlag(unit.x, unit.y, BlockFlag.rally, false);
if(target != null && !unit.within(target, 70f)){
moveToCore(FlagTarget.rallyPoints);
moveTo(Pathfinder.fieldRally);
}
}
@@ -82,7 +83,7 @@ public class GroundAI extends AIController{
if(tile == null) return;
Tile targetTile = pathfinder.getTargetTile(tile, pathfinder.getField(unit.team, costType, pathType));
if(tile == targetTile) return;
if(tile == targetTile || (costType == Pathfinder.costWater && !targetTile.floor().isLiquid)) return;
unit.moveAt(vec.trns(unit.angleTo(targetTile), unit.type().speed));
}

View File

@@ -317,7 +317,7 @@ public class World{
public void notifyChanged(Tile tile){
if(!generating){
Core.app.post(() -> Events.fire(new BuildinghangeEvent(tile)));
Core.app.post(() -> Events.fire(new TileChangeEvent(tile)));
}
}

View File

@@ -348,6 +348,7 @@ public class MapGenerateDialog extends BaseDialog{
result = executor.submit(() -> {
try{
world.setGenerating(true);
generating = true;
if(!filters.isEmpty()){
@@ -400,7 +401,7 @@ public class MapGenerateDialog extends BaseDialog{
generating = false;
e.printStackTrace();
}
return null;
world.setGenerating(false);
});
}

View File

@@ -70,13 +70,14 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc{
boolean dropUnit(UnitPayload payload){
Unit u = payload.unit;
Fx.unitDrop.at(this);
//can't drop ground units
if(((tileOn() == null || tileOn().solid()) && u.elevation < 0.1f) || (!floorOn().isLiquid && u instanceof WaterMovec)){
return false;
}
Fx.unitDrop.at(this);
//clients do not drop payloads
if(Vars.net.client()) return true;

View File

@@ -170,11 +170,10 @@ public class EventType{
}
}
/** Called from the logic thread. Do not access graphics here! */
public static class BuildinghangeEvent{
public static class TileChangeEvent{
public final Tile tile;
public BuildinghangeEvent(Tile tile){
public TileChangeEvent(Tile tile){
this.tile = tile;
}
}

View File

@@ -82,7 +82,7 @@ public class BlockRenderer implements Disposable{
dark.end();
});
Events.on(BuildinghangeEvent.class, event -> {
Events.on(TileChangeEvent.class, event -> {
shadowEvents.add(event.tile);
int avgx = (int)(camera.position.x / tilesize);

View File

@@ -36,7 +36,11 @@ public class MinimapRenderer implements Disposable{
});
//make sure to call on the graphics thread
Events.on(BuildinghangeEvent.class, event -> Core.app.post(() -> update(event.tile)));
Events.on(TileChangeEvent.class, event -> {
if(!ui.editor.isShown()){
update(event.tile);
}
});
}
public Pixmap getPixmap(){

View File

@@ -8,7 +8,6 @@ import mindustry.gen.*;
import mindustry.logic.LExecutor.*;
import mindustry.logic.LStatements.*;
import mindustry.type.*;
import mindustry.world.blocks.logic.*;
/** "Compiles" a sequence of statements into instructions. */
public class LAssembler{
@@ -66,7 +65,7 @@ public class LAssembler{
}
public static Seq<LStatement> read(String data){
return read(data, LogicBlock.maxInstructions);
return read(data, LExecutor.maxInstructions);
}
public static Seq<LStatement> read(String data, int max){

View File

@@ -17,18 +17,20 @@ import arc.util.ArcAnnotate.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.ui.*;
import mindustry.world.blocks.logic.*;
public class LCanvas extends Table{
static Seq<Runnable> postDraw = new Seq<>();
static Seq<Runnable> postDrawPriority = new Seq<>();
//ew static variables
static LCanvas canvas;
DragLayout statements;
StatementElem dragging;
ScrollPane pane;
Group jumps;
float targetWidth;
public LCanvas(){
canvas = this;
rebuild();
}
@@ -45,12 +47,16 @@ public class LCanvas extends Table{
clear();
statements = new DragLayout();
jumps = new WidgetGroup();
pane = pane(t -> {
t.center();
t.add(statements).pad(2f).center().width(targetWidth);
t.addChild(jumps);
jumps.cullable = false;
}).grow().get();
pane.setClip(false);
//pane.setClip(false);
pane.setFlickScroll(false);
//load old scroll percent
@@ -76,8 +82,10 @@ public class LCanvas extends Table{
}
void load(String asm){
jumps.clear();
Seq<LStatement> statements = LAssembler.read(asm);
statements.truncate(LogicBlock.maxInstructions);
statements.truncate(LExecutor.maxInstructions);
this.statements.clearChildren();
for(LStatement st : statements){
add(st);
@@ -104,19 +112,11 @@ public class LCanvas extends Table{
}
}
@Override
public void draw(){
postDraw.clear();
postDrawPriority.clear();
super.draw();
postDraw.each(Runnable::run);
postDrawPriority.each(Runnable::run);
}
public class DragLayout extends WidgetGroup{
float space = Scl.scl(10f), prefWidth, prefHeight;
Seq<Element> seq = new Seq<>();
int insertPosition = 0;
boolean invalidated;
{
setTransform(true);
@@ -124,6 +124,7 @@ public class LCanvas extends Table{
@Override
public void layout(){
invalidated = true;
float cy = 0;
seq.clear();
@@ -171,6 +172,10 @@ public class LCanvas extends Table{
}
invalidateHierarchy();
if(parent != null && parent instanceof Table){
setCullingArea(parent.getCullingArea());
}
}
@Override
@@ -196,7 +201,16 @@ public class LCanvas extends Table{
Tex.pane.draw(lastX, lastY - shiftAmount, width, dragging.getHeight());
}
if(invalidated){
children.each(c -> c.cullable = false);
}
super.draw();
if(invalidated){
children.each(c -> c.cullable = true);
invalidated = false;
}
}
void finishLayout(){
@@ -338,6 +352,9 @@ public class LCanvas extends Table{
boolean selecting;
float mx, my;
ClickListener listener;
StatementElem hovered;
JumpCurve curve;
public JumpButton(@NonNull Prov<StatementElem> getter, Cons<StatementElem> setter){
super(Tex.logicNode, Styles.colori);
@@ -383,53 +400,26 @@ public class LCanvas extends Table{
setColor(listener.isOver() ? hoverColor : defaultColor);
getStyle().imageUpColor = this.color;
});
curve = new JumpCurve(this);
}
@Override
public void draw(){
super.draw();
public void act(float delta){
super.act(delta);
(listener.isOver() ? postDrawPriority : postDraw).add(() -> {
Element hover = to.get() == null && selecting ? hovered() : to.get();
float tx = 0, ty = 0;
boolean draw = false;
//capture coordinates for use in lambda
float rx = x + translation.x, ry = y + translation.y;
hovered = hovered();
}
Element p = parent;
while(p != null){
rx += p.x + p.translation.x;
ry += p.y + p.translation.y;
p = p.parent;
}
@Override
protected void setScene(Scene stage){
super.setScene(stage);
if(hover != null){
tx = hover.getX(Align.right) + hover.translation.x;
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;
}else if(selecting){
tx = rx + mx;
ty = ry + my;
draw = true;
}
if(draw){
drawCurve(rx + width/2f, ry + height/2f, tx, ty);
float s = width;
Draw.color(color);
Tex.logicNode.draw(tx + s*0.75f, ty - s/2f, -s, s);
Draw.reset();
}
});
if(stage == null){
curve.remove();
}else{
canvas.jumps.addChild(curve);
}
}
StatementElem hovered(){
@@ -442,9 +432,60 @@ public class LCanvas extends Table{
if(e == null || isDescendantOf(e)) return null;
return (StatementElem)e;
}
}
public static class JumpCurve extends Element{
JumpButton button;
public JumpCurve(JumpButton button){
this.button = button;
}
@Override
public void act(float delta){
super.act(delta);
if(button.listener.isOver()){
toFront();
}
}
@Override
public void draw(){
Element hover = button.to.get() == null && button.selecting ? button.hovered : button.to.get();
boolean draw = false;
Vec2 t = Tmp.v1, r = Tmp.v2;
Group desc = canvas.pane;
button.localToAscendantCoordinates(desc, r.set(0, 0));
if(hover != null){
hover.localToAscendantCoordinates(desc, t.set(hover.getWidth(), hover.getHeight()/2f));
draw = true;
}else if(button.selecting){
t.set(r).add(button.mx, button.my);
draw = true;
}
float offset = canvas.pane.getVisualScrollY() - canvas.pane.getMaxY();
t.y += offset;
r.y += offset;
if(draw){
drawCurve(r.x + button.getWidth()/2f, r.y + button.getHeight()/2f, t.x, t.y);
float s = button.getWidth();
Draw.color(button.color);
Tex.logicNode.draw(t.x + s*0.75f, t.y - s/2f, -s, s);
Draw.reset();
}
}
void drawCurve(float x, float y, float x2, float y2){
Lines.stroke(4f, color);
Lines.stroke(4f, button.color);
Draw.alpha(parentAlpha);
float dist = 100f;
@@ -454,7 +495,7 @@ public class LCanvas extends Table{
x + dist, y,
x2 + dist, y2,
x2, y2,
Math.max(20, (int)(Mathf.dst(x, y, x2, y2) / 5))
Math.max(20, (int)(Mathf.dst(x, y, x2, y2) / 6))
);
}
}

View File

@@ -15,6 +15,8 @@ import mindustry.world.blocks.logic.MessageBlock.*;
import static mindustry.Vars.*;
public class LExecutor{
public static final int maxInstructions = 1000;
//special variables
public static final int
varCounter = 0,

View File

@@ -7,7 +7,6 @@ import mindustry.gen.*;
import mindustry.logic.LStatements.*;
import mindustry.ui.*;
import mindustry.ui.dialogs.*;
import mindustry.world.blocks.logic.*;
import static mindustry.Vars.*;
@@ -75,7 +74,7 @@ public class LogicDialog extends BaseDialog{
});
dialog.addCloseButton();
dialog.show();
}).width(170f).disabled(t -> canvas.statements.getChildren().size >= LogicBlock.maxInstructions);
}).width(170f).disabled(t -> canvas.statements.getChildren().size >= LExecutor.maxInstructions);
add(canvas).grow();

View File

@@ -478,6 +478,7 @@ public class UnitType extends UnlockableContent{
}
public <T extends Unit & Legsc> void drawLegs(T unit){
applyColor(unit);
Leg[] legs = unit.legs();
@@ -570,6 +571,7 @@ public class UnitType extends UnlockableContent{
}
public void applyColor(Unit unit){
Draw.color();
Draw.mixcol(Color.white, unit.hitTime);
if(unit.drownTime > 0 && unit.floorOn().isDeep()){
Draw.mixcol(unit.floorOn().mapColor, unit.drownTime * 0.8f);

View File

@@ -25,8 +25,6 @@ import java.util.zip.*;
import static mindustry.Vars.*;
public class LogicBlock extends Block{
public static final int maxInstructions = 1500;
public int maxInstructionScale = 5;
public int instructionsPerTick = 1;
public float range = 8 * 10;
@@ -271,7 +269,7 @@ public class LogicBlock extends Block{
try{
//create assembler to store extra variables
LAssembler asm = LAssembler.assemble(str, maxInstructions);
LAssembler asm = LAssembler.assemble(str, LExecutor.maxInstructions);
//store connections
for(LogicLink link : links){
@@ -316,7 +314,7 @@ public class LogicBlock extends Block{
e.printStackTrace();
//handle malformed code and replace it with nothing
executor.load("", maxInstructions);
executor.load("", LExecutor.maxInstructions);
}
}
}