This commit is contained in:
parent
6339181aec
commit
abcf4761df
@ -1664,6 +1664,7 @@ Blocks factor into voxel pathfinding
|
|||||||
Debugging pathfinding code
|
Debugging pathfinding code
|
||||||
New AI behaviors
|
New AI behaviors
|
||||||
- Will explore for resources if local ones aren't available
|
- Will explore for resources if local ones aren't available
|
||||||
|
Async pathfinding
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -77,11 +77,13 @@ public class ImGuiAI {
|
|||||||
|
|
||||||
if(ImGui.collapsingHeader("Statuses")){
|
if(ImGui.collapsingHeader("Statuses")){
|
||||||
for(AI ai : Globals.aiManager.getAIList()){
|
for(AI ai : Globals.aiManager.getAIList()){
|
||||||
|
ImGui.indent();
|
||||||
if(ImGui.collapsingHeader(ai.getParent().getId() + " - " + ai.getStatus())){
|
if(ImGui.collapsingHeader(ai.getParent().getId() + " - " + ai.getStatus())){
|
||||||
if(ImGui.button("Draw current pathing")){
|
if(ImGui.button("Draw current pathing")){
|
||||||
throw new Error("Unsupported currently!");
|
throw new Error("Unsupported currently!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ImGui.unindent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -728,6 +728,7 @@ public class Globals {
|
|||||||
Globals.clientSynchronizationManager = new ClientSynchronizationManager();
|
Globals.clientSynchronizationManager = new ClientSynchronizationManager();
|
||||||
Globals.server = null;
|
Globals.server = null;
|
||||||
Globals.serverSynchronizationManager = new ServerSynchronizationManager();
|
Globals.serverSynchronizationManager = new ServerSynchronizationManager();
|
||||||
|
Globals.aiManager.shutdown();
|
||||||
if(Globals.realmManager != null){
|
if(Globals.realmManager != null){
|
||||||
Globals.realmManager.reset();
|
Globals.realmManager.reset();
|
||||||
}
|
}
|
||||||
@ -739,6 +740,7 @@ public class Globals {
|
|||||||
*/
|
*/
|
||||||
public static void resetGlobals(){
|
public static void resetGlobals(){
|
||||||
Globals.unloadScene();
|
Globals.unloadScene();
|
||||||
|
Globals.aiManager.shutdown();
|
||||||
//
|
//
|
||||||
//Actual globals to destroy
|
//Actual globals to destroy
|
||||||
Globals.assetManager = null;
|
Globals.assetManager = null;
|
||||||
@ -757,6 +759,7 @@ public class Globals {
|
|||||||
Globals.clientSynchronizationManager = null;
|
Globals.clientSynchronizationManager = null;
|
||||||
Globals.server = null;
|
Globals.server = null;
|
||||||
Globals.serverSynchronizationManager = null;
|
Globals.serverSynchronizationManager = null;
|
||||||
|
Globals.aiManager = null;
|
||||||
Globals.playerManager = null;
|
Globals.playerManager = null;
|
||||||
Globals.javaPID = null;
|
Globals.javaPID = null;
|
||||||
Globals.RENDER_FLAG_RENDER_SHADOW_MAP = true;
|
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.game.data.creature.type.ai.AITreeData;
|
||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
import electrosphere.server.ai.services.NearbyEntityService;
|
import electrosphere.server.ai.services.NearbyEntityService;
|
||||||
|
import electrosphere.server.ai.services.PathfindingService;
|
||||||
import electrosphere.server.ai.services.TimerService;
|
import electrosphere.server.ai.services.TimerService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,6 +48,11 @@ public class AIManager {
|
|||||||
*/
|
*/
|
||||||
NearbyEntityService nearbyEntityService = new NearbyEntityService();
|
NearbyEntityService nearbyEntityService = new NearbyEntityService();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for performing pathfinding
|
||||||
|
*/
|
||||||
|
PathfindingService pathfindingService = new PathfindingService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The random of the ai
|
* The random of the ai
|
||||||
*/
|
*/
|
||||||
@ -156,6 +162,14 @@ public class AIManager {
|
|||||||
return nearbyEntityService;
|
return nearbyEntityService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the pathfinding service
|
||||||
|
* @return The pathfinding service
|
||||||
|
*/
|
||||||
|
public PathfindingService getPathfindingService(){
|
||||||
|
return this.pathfindingService;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the ai manager's random
|
* Gets the ai manager's random
|
||||||
* @return The random
|
* @return The random
|
||||||
@ -164,4 +178,13 @@ public class AIManager {
|
|||||||
return random;
|
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;
|
package electrosphere.server.ai.nodes.plan;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.joml.Vector3d;
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
import electrosphere.engine.Globals;
|
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
|
//make sure that the solved pathfinding data is for the point we want
|
||||||
if(PathfindingNode.hasPathfindingData(blackboard)){
|
if(PathfindingNode.hasPathfindingData(blackboard)){
|
||||||
PathingProgressiveData pathingProgressiveData = PathfindingNode.getPathfindingData(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);
|
Object targetRaw = blackboard.get(this.targetEntityKey);
|
||||||
Vector3d targetPos = null;
|
Vector3d targetPos = null;
|
||||||
if(targetRaw == null){
|
if(targetRaw == null){
|
||||||
@ -95,9 +93,7 @@ public class PathfindingNode implements AITreeNode {
|
|||||||
|
|
||||||
Vector3d entityPos = EntityUtils.getPosition(entity);
|
Vector3d entityPos = EntityUtils.getPosition(entity);
|
||||||
|
|
||||||
List<Vector3d> path = pathfindingManager.findPath(entityPos, targetPos);
|
PathingProgressiveData pathingProgressiveData = pathfindingManager.findPathAsync(entityPos, targetPos);
|
||||||
path.add(targetPos);
|
|
||||||
PathingProgressiveData pathingProgressiveData = new PathingProgressiveData(path);
|
|
||||||
PathfindingNode.setPathfindingData(blackboard, pathingProgressiveData);
|
PathfindingNode.setPathfindingData(blackboard, pathingProgressiveData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,9 +101,15 @@ public class PathfindingNode implements AITreeNode {
|
|||||||
throw new Error("Failed to find path! Unhandled");
|
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);
|
Vector3d entityPos = EntityUtils.getPosition(entity);
|
||||||
|
|
||||||
PathingProgressiveData pathingProgressiveData = PathfindingNode.getPathfindingData(blackboard);
|
|
||||||
Vector3d currentPathPos = null;
|
Vector3d currentPathPos = null;
|
||||||
if(pathingProgressiveData.getCurrentPoint() < pathingProgressiveData.getPoints().size()){
|
if(pathingProgressiveData.getCurrentPoint() < pathingProgressiveData.getPoints().size()){
|
||||||
currentPathPos = pathingProgressiveData.getPoints().get(pathingProgressiveData.getCurrentPoint());
|
currentPathPos = pathingProgressiveData.getPoints().get(pathingProgressiveData.getCurrentPoint());
|
||||||
|
|||||||
@ -10,4 +10,9 @@ public interface AIService {
|
|||||||
*/
|
*/
|
||||||
public void exec();
|
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);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -94,4 +94,8 @@ public class TimerService implements AIService {
|
|||||||
timerMap.put(timerId,frameCount);
|
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.DataDeleteNode;
|
||||||
import electrosphere.server.ai.nodes.meta.collections.SelectorNode;
|
import electrosphere.server.ai.nodes.meta.collections.SelectorNode;
|
||||||
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
|
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.RunnerNode;
|
||||||
import electrosphere.server.ai.nodes.meta.decorators.SucceederNode;
|
import electrosphere.server.ai.nodes.meta.decorators.SucceederNode;
|
||||||
import electrosphere.server.ai.nodes.plan.PathfindingNode;
|
import electrosphere.server.ai.nodes.plan.PathfindingNode;
|
||||||
@ -47,7 +48,9 @@ public class MoveToTree {
|
|||||||
|
|
||||||
//not in range of target, keep moving towards it
|
//not in range of target, keep moving towards it
|
||||||
new SequenceNode(
|
new SequenceNode(
|
||||||
|
new PublishStatusNode("Thinking about pathing"),
|
||||||
PathfindingNode.createPathEntity(targetKey),
|
PathfindingNode.createPathEntity(targetKey),
|
||||||
|
new PublishStatusNode("Moving"),
|
||||||
new FaceTargetNode(BlackboardKeys.PATHFINDING_POINT),
|
new FaceTargetNode(BlackboardKeys.PATHFINDING_POINT),
|
||||||
new RunnerNode(new MoveStartNode(MovementRelativeFacing.FORWARD))
|
new RunnerNode(new MoveStartNode(MovementRelativeFacing.FORWARD))
|
||||||
)
|
)
|
||||||
@ -76,7 +79,9 @@ public class MoveToTree {
|
|||||||
|
|
||||||
//not in range of target, keep moving towards it
|
//not in range of target, keep moving towards it
|
||||||
new SequenceNode(
|
new SequenceNode(
|
||||||
|
new PublishStatusNode("Thinking about pathing"),
|
||||||
PathfindingNode.createPathEntity(targetKey),
|
PathfindingNode.createPathEntity(targetKey),
|
||||||
|
new PublishStatusNode("Moving"),
|
||||||
new FaceTargetNode(BlackboardKeys.PATHFINDING_POINT),
|
new FaceTargetNode(BlackboardKeys.PATHFINDING_POINT),
|
||||||
new RunnerNode(new MoveStartNode(MovementRelativeFacing.FORWARD))
|
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.datacell.physics.PhysicsDataCell;
|
||||||
import electrosphere.server.entity.ServerContentManager;
|
import electrosphere.server.entity.ServerContentManager;
|
||||||
import electrosphere.server.entity.serialization.ContentSerialization;
|
import electrosphere.server.entity.serialization.ContentSerialization;
|
||||||
|
import electrosphere.server.pathfinding.recast.PathingProgressiveData;
|
||||||
import electrosphere.server.pathfinding.voxel.VoxelPathfinder;
|
import electrosphere.server.pathfinding.voxel.VoxelPathfinder;
|
||||||
import electrosphere.server.physics.block.manager.ServerBlockManager;
|
import electrosphere.server.physics.block.manager.ServerBlockManager;
|
||||||
import electrosphere.server.physics.fluid.manager.ServerFluidChunk;
|
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);
|
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 org.joml.Vector3d;
|
||||||
|
|
||||||
|
import electrosphere.server.pathfinding.recast.PathingProgressiveData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs pathfinding
|
* Performs pathfinding
|
||||||
*/
|
*/
|
||||||
@ -17,4 +19,12 @@ public interface PathfindingManager {
|
|||||||
*/
|
*/
|
||||||
public List<Vector3d> findPath(Vector3d start, Vector3d end);
|
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;
|
int currentPoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* The goal position
|
||||||
* @param points The points for the path
|
|
||||||
*/
|
*/
|
||||||
public PathingProgressiveData(List<Vector3d> points){
|
Vector3d goal;
|
||||||
this.points = points;
|
|
||||||
|
/**
|
||||||
|
* 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;
|
this.currentPoint = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +71,37 @@ public class PathingProgressiveData {
|
|||||||
this.currentPoint = currentPoint;
|
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