diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 96608bbc..8ba184f1 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -2085,6 +2085,7 @@ Synchronized time-of-day between server and client Skybox reflects time of day Standardize data sourcing in MacroTemporalData Macro pathfinding scaffolding +Macro pathfinding work diff --git a/src/main/java/electrosphere/engine/threads/ThreadCounts.java b/src/main/java/electrosphere/engine/threads/ThreadCounts.java index 10142218..ace832a6 100644 --- a/src/main/java/electrosphere/engine/threads/ThreadCounts.java +++ b/src/main/java/electrosphere/engine/threads/ThreadCounts.java @@ -25,6 +25,11 @@ public class ThreadCounts { */ public static final int PATHFINDING_THREADS = 1; + /** + * Number of threads for solving macro pathfinding + */ + public static final int MACRO_PATHING_THREADS = 1; + /** * Number of threads for gridded datacell manager chunk loading/unloading */ diff --git a/src/main/java/electrosphere/server/ServerState.java b/src/main/java/electrosphere/server/ServerState.java index 2de0063e..b69d73ad 100644 --- a/src/main/java/electrosphere/server/ServerState.java +++ b/src/main/java/electrosphere/server/ServerState.java @@ -12,6 +12,7 @@ import electrosphere.server.db.DatabaseController; import electrosphere.server.saves.Save; import electrosphere.server.service.CharacterService; import electrosphere.server.service.LODEmitterService; +import electrosphere.server.service.MacroPathingService; import electrosphere.server.service.StructureScanningService; import electrosphere.server.simulation.MicroSimulation; @@ -65,6 +66,11 @@ public class ServerState { */ public final LODEmitterService lodEmitterService; + /** + * The macro pathing service + */ + public final MacroPathingService macroPathingService; + /** * behavior tree tracking service */ @@ -92,6 +98,7 @@ public class ServerState { this.characterService = (CharacterService)Globals.engineState.serviceManager.registerService(new CharacterService()); this.structureScanningService = (StructureScanningService)Globals.engineState.serviceManager.registerService(new StructureScanningService()); this.lodEmitterService = (LODEmitterService)Globals.engineState.serviceManager.registerService(new LODEmitterService()); + this.macroPathingService = (MacroPathingService)Globals.engineState.serviceManager.registerService(new MacroPathingService()); } } diff --git a/src/main/java/electrosphere/server/ai/nodes/plan/MacroPathfindingNode.java b/src/main/java/electrosphere/server/ai/nodes/plan/MacroPathfindingNode.java index 8c0fbcb3..ee89adc4 100644 --- a/src/main/java/electrosphere/server/ai/nodes/plan/MacroPathfindingNode.java +++ b/src/main/java/electrosphere/server/ai/nodes/plan/MacroPathfindingNode.java @@ -9,7 +9,8 @@ import electrosphere.server.ai.AI; import electrosphere.server.ai.blackboard.Blackboard; import electrosphere.server.ai.nodes.AITreeNode; import electrosphere.server.datacell.Realm; -import electrosphere.server.datacell.interfaces.PathfindingManager; +import electrosphere.server.macro.MacroData; +import electrosphere.server.macro.spatial.MacroAreaObject; import electrosphere.server.macro.spatial.path.MacroPathNode; import electrosphere.server.macro.structure.VirtualStructure; import electrosphere.server.pathfinding.recast.PathingProgressiveData; @@ -70,30 +71,32 @@ public class MacroPathfindingNode implements AITreeNode { //create a path if we don't already have one if(!PathfindingNode.hasPathfindingData(blackboard)){ + + // + //figure out what we're targeting Object targetRaw = blackboard.get(this.targetEntityKey); - Vector3d targetPos = null; if(targetRaw == null){ throw new Error("Target undefined!"); } - if(targetRaw instanceof Vector3d){ - targetPos = (Vector3d)targetRaw; - } else if(targetRaw instanceof Entity){ - targetPos = EntityUtils.getPosition((Entity)targetRaw); - } else if(targetRaw instanceof VirtualStructure){ - targetPos = ((VirtualStructure)targetRaw).getPos(); + if(targetRaw instanceof MacroAreaObject){ } else { throw new Error("Unsupported target type " + targetRaw); } - Realm realm = Globals.serverState.realmManager.getEntityRealm(entity); - PathfindingManager pathfindingManager = realm.getPathfindingManager(); + MacroPathNode targetMacro = realm.getMacroData().getPathCache().getPathingNode(((MacroAreaObject)targetRaw).getPos()); - Vector3d entityPos = EntityUtils.getPosition(entity); - PathingProgressiveData pathingProgressiveData = pathfindingManager.findPathAsync(entityPos, targetPos); + // + //Find where the entity is currently + MacroPathNode currentPos = this.solveCurrentNode(entity); + + // + //Queue the pathfinding operation + PathingProgressiveData pathingProgressiveData = Globals.serverState.macroPathingService.queuePathfinding(realm, currentPos, targetMacro); PathfindingNode.setPathfindingData(blackboard, pathingProgressiveData); } + //make sure we found a path if(!PathfindingNode.hasPathfindingData(blackboard)){ throw new Error("Failed to find path! Unhandled"); } @@ -106,8 +109,9 @@ public class MacroPathfindingNode implements AITreeNode { } + // + //walk along the path if it exists Vector3d entityPos = EntityUtils.getPosition(entity); - Vector3d currentPathPos = null; if(pathingProgressiveData.getCurrentPoint() < pathingProgressiveData.getPoints().size()){ currentPathPos = pathingProgressiveData.getPoints().get(pathingProgressiveData.getCurrentPoint()); @@ -152,4 +156,22 @@ public class MacroPathfindingNode implements AITreeNode { return AITreeNodeResult.SUCCESS; } + /** + * Gets the pathing node of this entity + * @param entity The entity + * @return The pathing node + */ + private MacroPathNode solveCurrentNode(Entity entity){ + Realm realm = Globals.serverState.realmManager.getEntityRealm(entity); + if(realm == null){ + throw new Error("Entity is not attached to a realm!"); + } + MacroData macroData = realm.getMacroData(); + if(macroData == null){ + throw new Error("Macro data undefined!"); + } + Vector3d entityPos = EntityUtils.getPosition(entity); + return macroData.getPathCache().getPathingNode(entityPos); + } + } diff --git a/src/main/java/electrosphere/server/macro/spatial/path/MacroPathCache.java b/src/main/java/electrosphere/server/macro/spatial/path/MacroPathCache.java index b445e292..21a73d59 100644 --- a/src/main/java/electrosphere/server/macro/spatial/path/MacroPathCache.java +++ b/src/main/java/electrosphere/server/macro/spatial/path/MacroPathCache.java @@ -5,6 +5,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import org.joml.Vector3d; + import electrosphere.util.annotation.Exclude; /** @@ -60,4 +62,22 @@ public class MacroPathCache { idNodeMap.put(node.getId(),node); } + /** + * Gets the pathing node at a given point + * @param point The point + * @return The corresponding pathing node + */ + public MacroPathNode getPathingNode(Vector3d point){ + double minDist = 100; + MacroPathNode rVal = null; + for(MacroPathNode node : this.nodes){ + double dist = point.distance(node.getPosition()); + if(dist < minDist){ + minDist = dist; + rVal = node; + } + } + return rVal; + } + } diff --git a/src/main/java/electrosphere/server/pathfinding/recast/PathingProgressiveData.java b/src/main/java/electrosphere/server/pathfinding/recast/PathingProgressiveData.java index 907b2457..7a5a084f 100644 --- a/src/main/java/electrosphere/server/pathfinding/recast/PathingProgressiveData.java +++ b/src/main/java/electrosphere/server/pathfinding/recast/PathingProgressiveData.java @@ -12,22 +12,22 @@ public class PathingProgressiveData { /** * The list of points that represent the path */ - List points; + private List points; /** * The current point to move towards (ie all previous points have already been pathed to) */ - int currentPoint; + private int currentPoint; /** * The goal position */ - Vector3d goal; + private Vector3d goal; /** * Tracks whether this data is ready to be used or not */ - boolean ready = false; + private boolean ready = false; /** diff --git a/src/main/java/electrosphere/server/service/MacroPathingService.java b/src/main/java/electrosphere/server/service/MacroPathingService.java new file mode 100644 index 00000000..0c8bf113 --- /dev/null +++ b/src/main/java/electrosphere/server/service/MacroPathingService.java @@ -0,0 +1,81 @@ +package electrosphere.server.service; + +import java.util.List; +import java.util.concurrent.ExecutorService; + +import org.joml.Vector3d; + +import electrosphere.engine.signal.Signal.SignalType; +import electrosphere.engine.Globals; +import electrosphere.engine.signal.SignalServiceImpl; +import electrosphere.engine.threads.ThreadCounts; +import electrosphere.server.datacell.Realm; +import electrosphere.server.macro.MacroData; +import electrosphere.server.macro.spatial.path.MacroPathNode; +import electrosphere.server.pathfinding.recast.PathingProgressiveData; + +/** + * Service for solving pathing between macro area objects + */ +public class MacroPathingService extends SignalServiceImpl { + + /** + * The executor service + */ + final ExecutorService executorService; + + /** + * Constructor + */ + public MacroPathingService() { + super("MacroPathingService", new SignalType[]{ + }); + this.executorService = Globals.engineState.threadManager.requestFixedThreadPool(ThreadCounts.MACRO_PATHING_THREADS); + } + + /** + * Simulates the macro pathing service + */ + public void simulate(){ + } + + /** + * Queues a pathfinding job + * @param realm The realm + * @param start The start point + * @param end The end point + * @return The object that will eventually hold the pathfinding data + */ + public PathingProgressiveData queuePathfinding(Realm realm, MacroPathNode start, MacroPathNode end){ + PathingProgressiveData rVal = new PathingProgressiveData(end.getPosition()); + executorService.submit(() -> { + try { + List points = this.findPath(realm.getMacroData(), start, end); + rVal.setPoints(points); + rVal.setReady(true); + } catch(Throwable e){ + e.printStackTrace(); + } + }); + return rVal; + } + + /** + * Halts all threads in the pathfinding service + */ + public void haltThreads(){ + executorService.shutdownNow(); + } + + /** + * Finds a path between macro area objects + * @param macroData The macro data + * @param start The start area + * @param end The end area + * @return The path + */ + private List findPath(MacroData macroData, MacroPathNode start, MacroPathNode end){ + throw new Error("Not implemented yet!"); + } + +}