Update: Pathfinding and Goal Management Enhancements

Last modified: May 19 2024 14:03:17

This update introduces significant improvements to our pathfinding logic and goal management system, enhancing the accuracy and efficiency of unit movement within the game.

Introduction

In this update, we focused on refining the pathfinding methods and improving the goal management system for our game units. These changes ensure more precise and reliable navigation within the game environment.

Changes in ActionSelectionListener.java

We modified the pathfinding method to use block locations directly, ensuring more accurate movement calculations:


- List<Location> blockPathToGoal = unitPathFind.findPath(selectedUnit.getEntity().getLocation(), targetLocation, selectedUnit.getAttributes().getMoveDistance());
+ List<Location> blockPathToGoal = unitPathFind.findPath(selectedUnit.getEntity().getLocation().getBlock().getLocation(), targetLocation.getBlock().getLocation(), selectedUnit.getAttributes().getMoveDistance());
                

This change ensures that the pathfinding algorithm starts and ends at the exact block locations, leading to more precise movement calculations.

Updates in UnitGoal.java

Several updates were made to the UnitGoal class to streamline goal management and enhance pathfinding efficiency:

  • Added Bukkit import for server-side messaging capabilities.
  • Replaced the paths queue with a targetsList to manage target locations directly.

+ import org.bukkit.Bukkit;
    private final Queue<Location> targetsList = new ArrayDeque<>();

    public UnitGoal(CustomUnit unit) {
        this.unit = unit;
        this.pathfinder = ((Mob) this.unit.getEntity()).getPathfinder();
    }

    // True if path available, false if not
    public boolean moveTo(List<Location> targets) {
        List<Location> validLocations = new ArrayList<>();

        for (Location target : targets) {
            Pathfinder.PathResult path = pathfinder.findPath(target);
            if (path == null || path.getFinalPoint() == null || target.getBlock().getLocation().distance(path.getFinalPoint()) < 0.0) {
                // The target location is unreachable
                unit.getOwner().sendMessage(Component.text("Cannot reach that location!"));
                return false;
            }
            validLocations.add(target);
        }
        targetsList.addAll(validLocations);
        return true;
    }

    public void clearPaths() {
        targetsList.clear();
    }

    @Override
    public void tick() {
        if (pathfinder.hasPath()) return;

        if (targetsList.isEmpty()) {
            return;
        }
        // get next path on queue and move to it
        pathfinder.moveTo(targetsList.poll());
    }
                

These modifications streamline the goal management, making it more efficient and reducing potential errors during pathfinding.

Enhancements in UnitPathFind.java

Enhancements were made to the pathfinding algorithm in UnitPathFind to improve accuracy and reliability:

  • Removed debugging code and improved the pathfinding criteria.
  • Updated the path reconstruction to include precise locations.
  • Refined the conditions for determining walkable blocks.

// Removed debug code
- // TODO REMOVE
- goal.clone().add(0,2,0).getBlock().setType(Material.GOLD_BLOCK);

// Improved pathfinding criteria
+ if (current.location.distance(goal) < 1.0) {
    return reconstructPath(cameFrom, goal);
}

// Updated path reconstruction
private List<Location> reconstructPath(Map<Location, Location> cameFrom, Location goal) {
    List<Location> path = new ArrayList<>();
    Location current = goal;

    while (cameFrom.containsKey(current)) {
        path.add(current.toCenterLocation().subtract(0,0.5,0));
        current = cameFrom.get(current);
    }

    Collections.reverse(path);
    return path;
}

// Refined walkable block conditions
private boolean isWalkable(Location location) {
    Block block = location.getBlock();
    Block above = location.clone().add(0, 1, 0).getBlock();
    Block below = location.clone().add(0, -1, 0).getBlock();
    return block.getType().isAir() && above.getType() == Material.AIR && below.getType().isSolid();
}
                

These changes enhance the accuracy and reliability of the pathfinding logic, ensuring units navigate the game world more effectively.

Conclusion

Overall, these updates contribute to a more robust and responsive pathfinding and goal management system in the game. Stay tuned for more updates as we continue to improve the game's mechanics!