Pathfinder bugfixes

This commit is contained in:
Anuken 2023-03-18 16:14:01 -04:00
parent ca2b51d4fe
commit d07706e039
4 changed files with 30 additions and 34 deletions

View File

@ -19,7 +19,7 @@ import mindustry.world.meta.*;
import static mindustry.Vars.*;
public class Pathfinder implements Runnable{
private static final long maxUpdate = Time.millisToNanos(7);
private static final long maxUpdate = Time.millisToNanos(8);
private static final int updateFPS = 60;
private static final int updateInterval = 1000 / updateFPS;
@ -219,8 +219,6 @@ public class Pathfinder implements Runnable{
public void updateTile(Tile tile){
if(net.client()) return;
int x = tile.x, y = tile.y;
tile.getLinkedTiles(t -> {
int pos = t.array();
if(pos < tiles.length){
@ -238,9 +236,10 @@ public class Pathfinder implements Runnable{
}
}
//mark every flow field as dirty, so it updates when it's done
queue.post(() -> {
for(Flowfield data : threadList){
updateTargets(data, x, y);
data.dirty = true;
}
});
}
@ -257,6 +256,13 @@ public class Pathfinder implements Runnable{
//each update time (not total!) no longer than maxUpdate
for(Flowfield data : threadList){
//if it's dirty and there is nothing to update, begin updating once more
if(data.dirty && data.frontier.size == 0){
updateTargets(data);
data.dirty = false;
}
updateFrontier(data, maxUpdate);
}
}
@ -315,7 +321,8 @@ public class Pathfinder implements Runnable{
}
}
int[] values = path.weights;
//use complete weights if possible; these contain a complete flow field that is not being updated
int[] values = path.hasComplete ? path.completeWeights : path.weights;
int apos = tile.array();
int value = values[apos];
@ -341,32 +348,6 @@ public class Pathfinder implements Runnable{
return current;
}
/**
* Clears the frontier, increments the search and sets up all flow sources.
* This only occurs for active teams.
*/
private void updateTargets(Flowfield path, int x, int y){
int packed = world.packArray(x, y);
if(packed > path.weights.length) return;
if(path.weights[packed] == 0){
//this was a previous target
path.frontier.clear();
}else if(!path.frontier.isEmpty()){
//skip if this path is processing
return;
}
//update cost of the tile TODO maybe only update the cost when it's not passable
path.weights[packed] = path.cost.getCost(path.team.id, tiles[packed]);
//clear frontier to prevent contamination
path.frontier.clear();
updateTargets(path);
}
/** Increments the search and sets up flow sources. Does not change the frontier. */
private void updateTargets(Flowfield path){
@ -421,6 +402,7 @@ public class Pathfinder implements Runnable{
/** Update the frontier for a path. Pathfinding thread only. */
private void updateFrontier(Flowfield path, long nsToRun){
boolean hadAny = path.frontier.size > 0;
long start = Time.nanos();
int counter = 0;
@ -462,6 +444,12 @@ public class Pathfinder implements Runnable{
}
}
}
//there WERE some things in the frontier, but now they are gone, so the path is done; copy over latest data
if(hadAny && path.frontier.size == 0){
System.arraycopy(path.weights, 0, path.completeWeights, 0, path.weights.length);
path.hasComplete = true;
}
}
public static class EnemyCoreField extends Flowfield{
@ -505,11 +493,18 @@ public class Pathfinder implements Runnable{
protected Team team = Team.derelict;
/** Function for calculating path cost. Set before using. */
protected PathCost cost = costTypes.get(costGround);
/** If true, this flow field needs updating. This flag is only set to false once the flow field finishes and the weights are copied over. */
protected boolean dirty = false;
/** Whether there are valid weights in the complete array. */
protected volatile boolean hasComplete;
/** costs of getting to a specific tile */
public int[] weights;
/** search IDs of each position - the highest, most recent search is prioritized and overwritten */
public int[] searches;
/** the last "complete" weights of this tilemap. */
public int[] completeWeights;
/** search frontier, these are Pos objects */
IntQueue frontier = new IntQueue();
/** all target positions; these positions have a cost of 0, and must be synchronized on! */
@ -524,6 +519,7 @@ public class Pathfinder implements Runnable{
void setup(int length){
this.weights = new int[length];
this.searches = new int[length];
this.completeWeights = new int[length];
this.frontier.ensureCapacity((length) / 4);
this.initialized = true;
}

View File

@ -119,7 +119,7 @@ public class BuilderAI extends AIController{
}
//follow someone and help them build
if(timer.get(timerTarget2, 60f)){
if(timer.get(timerTarget2, 20f)){
found = false;
Units.nearby(unit.team, unit.x, unit.y, buildRadius, u -> {

View File

@ -60,7 +60,7 @@ public enum LAccess{
all = values(),
senseable = Seq.select(all, t -> t.params.length <= 1).toArray(LAccess.class),
controls = Seq.select(all, t -> t.params.length > 0).toArray(LAccess.class),
settable = {x, y, rotation, team, flag, health, totalPower, payloadType}; //TODO
settable = {x, y, rotation, team, flag, health, totalPower, payloadType};
LAccess(String... params){
this.params = params;

View File

@ -25,4 +25,4 @@ org.gradle.caching=true
#used for slow jitpack builds; TODO see if this actually works
org.gradle.internal.http.socketTimeout=100000
org.gradle.internal.http.connectionTimeout=100000
archash=a96ce3b267
archash=cc9c60d49b