This commit is contained in:
parent
6339181aec
commit
abcf4761df
@ -1664,6 +1664,7 @@ Blocks factor into voxel pathfinding
|
||||
Debugging pathfinding code
|
||||
New AI behaviors
|
||||
- Will explore for resources if local ones aren't available
|
||||
Async pathfinding
|
||||
|
||||
|
||||
|
||||
|
||||
@ -77,11 +77,13 @@ public class ImGuiAI {
|
||||
|
||||
if(ImGui.collapsingHeader("Statuses")){
|
||||
for(AI ai : Globals.aiManager.getAIList()){
|
||||
ImGui.indent();
|
||||
if(ImGui.collapsingHeader(ai.getParent().getId() + " - " + ai.getStatus())){
|
||||
if(ImGui.button("Draw current pathing")){
|
||||
throw new Error("Unsupported currently!");
|
||||
}
|
||||
}
|
||||
ImGui.unindent();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -728,6 +728,7 @@ public class Globals {
|
||||
Globals.clientSynchronizationManager = new ClientSynchronizationManager();
|
||||
Globals.server = null;
|
||||
Globals.serverSynchronizationManager = new ServerSynchronizationManager();
|
||||
Globals.aiManager.shutdown();
|
||||
if(Globals.realmManager != null){
|
||||
Globals.realmManager.reset();
|
||||
}
|
||||
@ -739,6 +740,7 @@ public class Globals {
|
||||
*/
|
||||
public static void resetGlobals(){
|
||||
Globals.unloadScene();
|
||||
Globals.aiManager.shutdown();
|
||||
//
|
||||
//Actual globals to destroy
|
||||
Globals.assetManager = null;
|
||||
@ -757,6 +759,7 @@ public class Globals {
|
||||
Globals.clientSynchronizationManager = null;
|
||||
Globals.server = null;
|
||||
Globals.serverSynchronizationManager = null;
|
||||
Globals.aiManager = null;
|
||||
Globals.playerManager = null;
|
||||
Globals.javaPID = null;
|
||||
Globals.RENDER_FLAG_RENDER_SHADOW_MAP = true;
|
||||
|
||||
@ -10,6 +10,7 @@ import electrosphere.entity.Entity;
|
||||
import electrosphere.game.data.creature.type.ai.AITreeData;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.server.ai.services.NearbyEntityService;
|
||||
import electrosphere.server.ai.services.PathfindingService;
|
||||
import electrosphere.server.ai.services.TimerService;
|
||||
|
||||
/**
|
||||
@ -47,6 +48,11 @@ public class AIManager {
|
||||
*/
|
||||
NearbyEntityService nearbyEntityService = new NearbyEntityService();
|
||||
|
||||
/**
|
||||
* Service for performing pathfinding
|
||||
*/
|
||||
PathfindingService pathfindingService = new PathfindingService();
|
||||
|
||||
/**
|
||||
* The random of the ai
|
||||
*/
|
||||
@ -156,6 +162,14 @@ public class AIManager {
|
||||
return nearbyEntityService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pathfinding service
|
||||
* @return The pathfinding service
|
||||
*/
|
||||
public PathfindingService getPathfindingService(){
|
||||
return this.pathfindingService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ai manager's random
|
||||
* @return The random
|
||||
@ -163,5 +177,14 @@ public class AIManager {
|
||||
public Random getRandom(){
|
||||
return random;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down the ai manager
|
||||
*/
|
||||
public void shutdown(){
|
||||
this.pathfindingService.shutdown();
|
||||
this.nearbyEntityService.shutdown();
|
||||
this.timerService.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
package electrosphere.server.ai.nodes.plan;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
@ -52,7 +50,7 @@ public class PathfindingNode implements AITreeNode {
|
||||
//make sure that the solved pathfinding data is for the point we want
|
||||
if(PathfindingNode.hasPathfindingData(blackboard)){
|
||||
PathingProgressiveData pathingProgressiveData = PathfindingNode.getPathfindingData(blackboard);
|
||||
Vector3d actualPoint = pathingProgressiveData.getPoints().get(pathingProgressiveData.getPoints().size() - 1);
|
||||
Vector3d actualPoint = pathingProgressiveData.getGoal();
|
||||
Object targetRaw = blackboard.get(this.targetEntityKey);
|
||||
Vector3d targetPos = null;
|
||||
if(targetRaw == null){
|
||||
@ -95,9 +93,7 @@ public class PathfindingNode implements AITreeNode {
|
||||
|
||||
Vector3d entityPos = EntityUtils.getPosition(entity);
|
||||
|
||||
List<Vector3d> path = pathfindingManager.findPath(entityPos, targetPos);
|
||||
path.add(targetPos);
|
||||
PathingProgressiveData pathingProgressiveData = new PathingProgressiveData(path);
|
||||
PathingProgressiveData pathingProgressiveData = pathfindingManager.findPathAsync(entityPos, targetPos);
|
||||
PathfindingNode.setPathfindingData(blackboard, pathingProgressiveData);
|
||||
}
|
||||
|
||||
@ -105,9 +101,15 @@ public class PathfindingNode implements AITreeNode {
|
||||
throw new Error("Failed to find path! Unhandled");
|
||||
}
|
||||
|
||||
//check if the path has been found
|
||||
PathingProgressiveData pathingProgressiveData = PathfindingNode.getPathfindingData(blackboard);
|
||||
if(!pathingProgressiveData.isReady()){
|
||||
return AITreeNodeResult.RUNNING;
|
||||
}
|
||||
|
||||
|
||||
Vector3d entityPos = EntityUtils.getPosition(entity);
|
||||
|
||||
PathingProgressiveData pathingProgressiveData = PathfindingNode.getPathfindingData(blackboard);
|
||||
Vector3d currentPathPos = null;
|
||||
if(pathingProgressiveData.getCurrentPoint() < pathingProgressiveData.getPoints().size()){
|
||||
currentPathPos = pathingProgressiveData.getPoints().get(pathingProgressiveData.getCurrentPoint());
|
||||
|
||||
@ -10,4 +10,9 @@ public interface AIService {
|
||||
*/
|
||||
public void exec();
|
||||
|
||||
/**
|
||||
* Shuts down the service
|
||||
*/
|
||||
public void shutdown();
|
||||
|
||||
}
|
||||
|
||||
@ -61,4 +61,8 @@ public class NearbyEntityService implements AIService {
|
||||
return blackboard.has(BlackboardKeys.NEARBY_ENTITIES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,58 @@
|
||||
package electrosphere.server.ai.services;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.server.datacell.interfaces.VoxelCellManager;
|
||||
import electrosphere.server.pathfinding.recast.PathingProgressiveData;
|
||||
import electrosphere.server.pathfinding.voxel.VoxelPathfinder;
|
||||
|
||||
/**
|
||||
* Service for performing pathfinding
|
||||
*/
|
||||
public class PathfindingService implements AIService {
|
||||
|
||||
/**
|
||||
* The executor service
|
||||
*/
|
||||
ExecutorService executorService;
|
||||
|
||||
/**
|
||||
* Queues a pathfinding job
|
||||
* @param start The start point
|
||||
* @param end The end point
|
||||
* @param pathfinder The pathfinder object
|
||||
* @param voxelCellManager The voxel cell manager
|
||||
* @return The object that will eventually hold the pathfinding data
|
||||
*/
|
||||
public PathingProgressiveData queuePathfinding(Vector3d start, Vector3d end, VoxelPathfinder pathfinder, VoxelCellManager voxelCellManager){
|
||||
PathingProgressiveData rVal = new PathingProgressiveData(end);
|
||||
if(executorService == null){
|
||||
executorService = Executors.newFixedThreadPool(2);
|
||||
}
|
||||
executorService.submit(() -> {
|
||||
List<Vector3d> points = pathfinder.findPath(voxelCellManager, start, end, VoxelPathfinder.DEFAULT_MAX_COST);
|
||||
points.add(end);
|
||||
rVal.setPoints(points);
|
||||
rVal.setReady(true);
|
||||
});
|
||||
return rVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exec() {
|
||||
//No synchronous logic required yet
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
if(executorService != null){
|
||||
executorService.shutdownNow();
|
||||
}
|
||||
executorService = null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -93,5 +93,9 @@ public class TimerService implements AIService {
|
||||
}
|
||||
timerMap.put(timerId,frameCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import electrosphere.server.ai.nodes.checks.spatial.TargetRangeCheckNode;
|
||||
import electrosphere.server.ai.nodes.meta.DataDeleteNode;
|
||||
import electrosphere.server.ai.nodes.meta.collections.SelectorNode;
|
||||
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
|
||||
import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode;
|
||||
import electrosphere.server.ai.nodes.meta.decorators.RunnerNode;
|
||||
import electrosphere.server.ai.nodes.meta.decorators.SucceederNode;
|
||||
import electrosphere.server.ai.nodes.plan.PathfindingNode;
|
||||
@ -47,7 +48,9 @@ public class MoveToTree {
|
||||
|
||||
//not in range of target, keep moving towards it
|
||||
new SequenceNode(
|
||||
new PublishStatusNode("Thinking about pathing"),
|
||||
PathfindingNode.createPathEntity(targetKey),
|
||||
new PublishStatusNode("Moving"),
|
||||
new FaceTargetNode(BlackboardKeys.PATHFINDING_POINT),
|
||||
new RunnerNode(new MoveStartNode(MovementRelativeFacing.FORWARD))
|
||||
)
|
||||
@ -76,7 +79,9 @@ public class MoveToTree {
|
||||
|
||||
//not in range of target, keep moving towards it
|
||||
new SequenceNode(
|
||||
new PublishStatusNode("Thinking about pathing"),
|
||||
PathfindingNode.createPathEntity(targetKey),
|
||||
new PublishStatusNode("Moving"),
|
||||
new FaceTargetNode(BlackboardKeys.PATHFINDING_POINT),
|
||||
new RunnerNode(new MoveStartNode(MovementRelativeFacing.FORWARD))
|
||||
)
|
||||
|
||||
@ -37,6 +37,7 @@ import electrosphere.server.datacell.interfaces.VoxelCellManager;
|
||||
import electrosphere.server.datacell.physics.PhysicsDataCell;
|
||||
import electrosphere.server.entity.ServerContentManager;
|
||||
import electrosphere.server.entity.serialization.ContentSerialization;
|
||||
import electrosphere.server.pathfinding.recast.PathingProgressiveData;
|
||||
import electrosphere.server.pathfinding.voxel.VoxelPathfinder;
|
||||
import electrosphere.server.physics.block.manager.ServerBlockManager;
|
||||
import electrosphere.server.physics.fluid.manager.ServerFluidChunk;
|
||||
@ -1140,4 +1141,9 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
return serverTerrainManager.getChunk(worldX, worldY, worldZ, ServerChunkCache.STRIDE_FULL_RES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathingProgressiveData findPathAsync(Vector3d start, Vector3d end) {
|
||||
return Globals.aiManager.getPathfindingService().queuePathfinding(start, end, this.pathfinder, this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -4,6 +4,8 @@ import java.util.List;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.server.pathfinding.recast.PathingProgressiveData;
|
||||
|
||||
/**
|
||||
* Performs pathfinding
|
||||
*/
|
||||
@ -17,4 +19,12 @@ public interface PathfindingManager {
|
||||
*/
|
||||
public List<Vector3d> findPath(Vector3d start, Vector3d end);
|
||||
|
||||
/**
|
||||
* Solves a path
|
||||
* @param start The start point
|
||||
* @param end The end point
|
||||
* @return The path if it exists, null otherwise
|
||||
*/
|
||||
public PathingProgressiveData findPathAsync(Vector3d start, Vector3d end);
|
||||
|
||||
}
|
||||
|
||||
@ -20,11 +20,22 @@ public class PathingProgressiveData {
|
||||
int currentPoint;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param points The points for the path
|
||||
* The goal position
|
||||
*/
|
||||
public PathingProgressiveData(List<Vector3d> points){
|
||||
this.points = points;
|
||||
Vector3d goal;
|
||||
|
||||
/**
|
||||
* Tracks whether this data is ready to be used or not
|
||||
*/
|
||||
boolean ready = false;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param goal The goal point
|
||||
*/
|
||||
public PathingProgressiveData(Vector3d goal){
|
||||
this.goal = goal;
|
||||
this.currentPoint = 0;
|
||||
}
|
||||
|
||||
@ -60,6 +71,37 @@ public class PathingProgressiveData {
|
||||
this.currentPoint = currentPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the goal point
|
||||
* @return The goal point
|
||||
*/
|
||||
public Vector3d getGoal() {
|
||||
return goal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the goal point
|
||||
* @param goal The goal point
|
||||
*/
|
||||
public void setGoal(Vector3d goal) {
|
||||
this.goal = goal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this data is ready or not
|
||||
* @return true if it is ready, false otherwise
|
||||
*/
|
||||
public boolean isReady() {
|
||||
return ready;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ready status of this data
|
||||
* @param ready true if the data is ready, false otherwise
|
||||
*/
|
||||
public void setReady(boolean ready) {
|
||||
this.ready = ready;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user