Files
Server/src/engine/gameManager/NavigationManager.java
T

139 lines
5.3 KiB
Java
Raw Normal View History

2023-11-05 10:45:35 -06:00
package engine.gameManager;
2023-11-07 22:55:34 -06:00
import engine.Enum;
2023-11-05 10:45:35 -06:00
import engine.math.Vector3fImmutable;
2023-11-07 22:55:34 -06:00
import engine.net.client.msg.MoveToPointMsg;
2023-11-05 10:45:35 -06:00
import engine.objects.*;
2023-11-07 21:45:16 -06:00
import java.awt.geom.Path2D;
2023-11-05 10:45:35 -06:00
import java.util.ArrayList;
public class NavigationManager {
private static final int cellGap = 1;
private static final int stepHeight = 2;
2023-11-07 22:55:34 -06:00
public static void pathfind(AbstractCharacter character, Vector3fImmutable goal) {
2023-11-07 21:45:16 -06:00
try {
2023-11-07 22:55:34 -06:00
ArrayList<Vector3fImmutable> path = getPath(character.loc, goal);//getOptimizedPath(getPath(character.loc, goal), getPath(goal, character.loc));
if (path.isEmpty()) {
MoveToPointMsg msg = new MoveToPointMsg();
msg.setSourceType(Enum.GameObjectType.Mob.ordinal());
msg.setSourceID(character.getObjectUUID());
msg.setStartCoord(character.loc);
msg.setEndCoord(goal);
Regions region = Regions.getRegionAtLocation(goal);
if (region != null) {
msg.setInBuildingFloor(region.room);
msg.setInBuilding(region.level);
msg.setStartLocType(0);
msg.setInBuildingUUID(region.parentBuildingID);
} else {
msg.setInBuildingFloor(-1);
msg.setInBuilding(-1);
msg.setStartLocType(0);
msg.setInBuildingUUID(0);
}
2023-11-07 21:45:16 -06:00
return; //no points to walk to
}
2023-11-05 10:45:35 -06:00
2023-11-07 21:45:16 -06:00
//character.destination = path.get(1);
character.navPath = path;
2023-11-05 10:45:35 -06:00
2023-11-07 22:55:34 -06:00
} catch (Exception e) {
2023-11-05 10:45:35 -06:00
//something failed
2023-11-07 21:45:16 -06:00
}
2023-11-05 10:45:35 -06:00
}
public static ArrayList<Vector3fImmutable> getOptimizedPath(ArrayList<Vector3fImmutable> startToGoal, ArrayList<Vector3fImmutable> goalToStart) {
ArrayList<Vector3fImmutable> optimalPath = new ArrayList<>();
optimalPath.add(startToGoal.get(0));
2023-11-07 22:55:34 -06:00
for (Vector3fImmutable point : startToGoal) {
if (goalToStart.contains(point) && !optimalPath.contains(point)) {
optimalPath.add(point);
2023-11-05 10:45:35 -06:00
}
2023-11-07 22:55:34 -06:00
2023-11-05 10:45:35 -06:00
}
//optimize the path to its smallest possible amount of points
return optimalPath;
}
private static ArrayList<Vector3fImmutable> getPath(Vector3fImmutable start, Vector3fImmutable goal) {
ArrayList<Vector3fImmutable> path = new ArrayList<>();
path.add(start);
Vector3fImmutable current = start;
boolean obstructed = false;
int count = 0;
2023-11-07 22:55:34 -06:00
while (current.distanceSquared(goal) > 9 && count < 250) {
2023-11-05 10:45:35 -06:00
//gather the 8 cells around the player
ArrayList<Vector3fImmutable> surroundingCells = new ArrayList<>();
surroundingCells.add(current.add(new Vector3fImmutable(cellGap, 0, 0)));
surroundingCells.add(current.add(new Vector3fImmutable(cellGap, 0, cellGap)));
surroundingCells.add(current.add(new Vector3fImmutable(0, 0, cellGap)));
surroundingCells.add(current.add(new Vector3fImmutable(-cellGap, 0, 0)));
surroundingCells.add(current.add(new Vector3fImmutable(-cellGap, 0, -cellGap)));
surroundingCells.add(current.add(new Vector3fImmutable(0, 0, -cellGap)));
surroundingCells.add(current.add(new Vector3fImmutable(-cellGap, 0, cellGap)));
surroundingCells.add(current.add(new Vector3fImmutable(cellGap, 0, -cellGap)));
Vector3fImmutable cheapest = new Vector3fImmutable(Vector3fImmutable.ZERO);
2023-11-07 22:55:34 -06:00
for (Vector3fImmutable point : surroundingCells) {
2023-11-05 10:45:35 -06:00
count++;
if (path.contains(point))
continue;
if (pointIsBlocked(point)) {
obstructed = true;
continue;
}
if (getCost(cheapest, current, goal) > getCost(point, current, goal))
cheapest = point;
}
current = cheapest;
path.add(cheapest);
}
2023-11-07 22:55:34 -06:00
if (obstructed) {
2023-11-05 10:45:35 -06:00
return path;
2023-11-07 22:55:34 -06:00
} else {
2023-11-05 10:45:35 -06:00
ArrayList<Vector3fImmutable> goalPath = new ArrayList<>();
goalPath.add(start);
2023-11-07 22:55:34 -06:00
goalPath.add(start.moveTowards(goal,32));
2023-11-05 10:45:35 -06:00
goalPath.add(goal);
return goalPath; //if the path isn't obstructed we can walk directly from start to the goal
2023-11-07 22:55:34 -06:00
2023-11-05 10:45:35 -06:00
}
}
2023-11-07 22:55:34 -06:00
2023-11-05 10:45:35 -06:00
public static float getCost(Vector3fImmutable point, Vector3fImmutable start, Vector3fImmutable goal) {
float gCost = start.distanceSquared(point);
float hCost = goal.distanceSquared(point);
return gCost + hCost;
}
public static boolean pointIsBlocked(Vector3fImmutable point) {
Building building = BuildingManager.getBuildingAtLocation(point);
2023-11-07 21:45:16 -06:00
if(building != null) {
2023-11-07 22:55:34 -06:00
for (Path2D.Float mesh : building.meshes) {
if (mesh.contains(point.x,point.z)) {
return true;
}
}
2023-11-07 21:45:16 -06:00
for (Regions region : building.getBounds().getRegions()) {
if (region.isPointInPolygon(point))
if (Math.abs(region.lerpY(point) - point.y) > stepHeight) // get the height distance between current height and target location height
2023-11-05 10:45:35 -06:00
return true;
2023-11-07 21:45:16 -06:00
}
}
return false;
2023-11-05 10:45:35 -06:00
}
}