more bugfixes

This commit is contained in:
Anuken
2024-04-17 23:13:10 -04:00
parent 95e4be7186
commit 5e22b093e6
2 changed files with 25 additions and 14 deletions

View File

@@ -71,8 +71,9 @@ public class HierarchyPathFinder implements Runnable{
//TODO: very dangerous usage;
//TODO - it is accessed from the main thread
//TODO - it is written to on the pathfinding thread
//maps position in world in (x + y * width format) to a cache of flow fields
IntMap<FieldCache> fields = new IntMap<>();
//TODO - it does not include
//maps position in world in (x + y * width format) | type (bitpacked to long) to a cache of flow fields
LongMap<FieldCache> fields = new LongMap<>();
//MAIN THREAD ONLY
Seq<FieldCache> fieldList = new Seq<>(false);
@@ -128,22 +129,26 @@ public class HierarchyPathFinder implements Runnable{
static class FieldCache{
final PathCost cost;
final int costId;
final int team;
final int goalPos;
//frontier for flow fields
final IntQueue frontier = new IntQueue();
//maps cluster index to field weights; 0 means uninitialized
final IntMap<int[]> fields = new IntMap<>();
final long mapKey;
//main thread only!
long lastUpdateId = state.updateId;
//TODO: how are the nodes merged? CAN they be merged?
FieldCache(PathCost cost, int team, int goalPos){
FieldCache(PathCost cost, int costId, int team, int goalPos){
this.cost = cost;
this.team = team;
this.goalPos = goalPos;
this.costId = costId;
this.mapKey = Pack.longInt(goalPos, costId);
}
}
@@ -162,7 +167,7 @@ public class HierarchyPathFinder implements Runnable{
//TODO: can the pathfinding thread even see these?
unitRequests = new ObjectMap<>();
fields = new IntMap<>();
fields = new LongMap<>();
fieldList = new Seq<>(false);
clusters = new Cluster[256][][];
@@ -213,7 +218,7 @@ public class HierarchyPathFinder implements Runnable{
//skipped N update -> drop it
if(field.lastUpdateId <= state.updateId - 30){
//make sure it's only modified on the main thread...? but what about calling get() on this thread??
queue.post(() -> fields.remove(field.goalPos));
queue.post(() -> fields.remove(field.mapKey));
Core.app.post(() -> fieldList.remove(field));
}
}
@@ -222,7 +227,7 @@ public class HierarchyPathFinder implements Runnable{
if(debug){
Events.run(Trigger.draw, () -> {
int team = player.team().id;
int cost = costGround;
int cost = 0;
Draw.draw(Layer.overlayUI, () -> {
Lines.stroke(1f);
@@ -953,13 +958,14 @@ public class HierarchyPathFinder implements Runnable{
var nodePath = clusterAstar(request, costId, node, dest);
FieldCache cache = fields.get(goalPos);
FieldCache cache = fields.get(Pack.longInt(goalPos, costId));
//if true, extra values are added on the sides of existing field cells that face new cells.
boolean addingFrontier = true;
//create the cache if it doesn't exist, and initialize it
if(cache == null){
fields.put(goalPos, cache = new FieldCache(pcost, team, goalPos));
cache = new FieldCache(pcost, costId, team, goalPos);
fields.put(cache.mapKey, cache);
FieldCache fcache = cache;
//register field in main thread for iteration
Core.app.post(() -> fieldList.add(fcache));
@@ -1038,13 +1044,15 @@ public class HierarchyPathFinder implements Runnable{
boolean any = false;
long fieldKey = Pack.longInt(destPos, costId);
//use existing request if it exists.
if(request != null && request.destination == destPos){
request.lastUpdateId = state.updateId;
Tile tileOn = unit.tileOn(), initialTileOn = tileOn;
//TODO: should fields be accessible from this thread?
FieldCache fieldCache = fields.get(destPos);
FieldCache fieldCache = fields.get(fieldKey);
if(fieldCache != null && tileOn != null){
FieldCache old = request.oldCache;
@@ -1059,7 +1067,7 @@ public class HierarchyPathFinder implements Runnable{
boolean recalc = false;
unit.hitboxTile(Tmp.r3);
//tile rect size has tile size factored in, since the ray cannot have thickness
float tileRectSize = tilesize + Tmp.r3.height - 0.1f;
float tileRectSize = tilesize + Tmp.r3.height;
//TODO last pos can change if the flowfield changes.
if(initialTileOn.pos() != request.lastTile || request.lastTargetTile == null){
@@ -1311,7 +1319,8 @@ public class HierarchyPathFinder implements Runnable{
int index = cx + cy * cwidth;
for(var req : threadPathRequests){
var field = fields.get(req.destination);
long mapKey = Pack.longInt(req.destination, pathCost);
var field = fields.get(mapKey);
if((field != null && field.fields.containsKey(index)) || req.notFound){
invalidRequests.add(req);
}
@@ -1396,14 +1405,16 @@ public class HierarchyPathFinder implements Runnable{
continue;
}
var field = fields.get(request.destination);
long mapKey = Pack.longInt(request.destination, request.costId);
var field = fields.get(mapKey);
if(field != null){
//it's only worth recalculating a path when the current frontier has finished; otherwise the unit will be following something incomplete.
if(field.frontier.isEmpty()){
//remove the field, to be recalculated next update one recalculatePath is processed
fields.remove(field.goalPos);
fields.remove(field.mapKey);
Core.app.post(() -> fieldList.remove(field));
//once the field is invalidated, make sure that all the requests that have it stored in their 'old' field, so units don't stutter during recalculations

View File

@@ -68,7 +68,7 @@ abstract class HitboxComp implements Posc, Sized, QuadTreeObject{
public void hitboxTile(Rect rect){
//tile hitboxes are never bigger than a tile, otherwise units get stuck
float size = Math.min(hitSize * 0.66f, 7.9f);
float size = Math.min(hitSize * 0.66f, 7.8f);
//TODO: better / more accurate version is
//float size = hitSize * 0.85f;
//- for tanks?