mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
feat: add Phase 1 core pathfinding architecture
Implements the new Baritone-inspired A* pathfinding system: - Core types: PathNode, PathResult, MoveResult, MoveType, ActionCosts - BinaryHeapOpenSet min-heap for A* open set - AStarPathFinder with timeout, cancellation, partial path support - CalculationContext for thread-safe world state snapshots - MoveHelper for block passability checks - IGoal interface + GoalBlock, GoalXZ, GoalNear, GoalComposite - IMove interface + MoveTraverse, MoveDiagonal, MoveAscend, MoveDescend, MoveClimb - /pathfind command for testing the new pathfinder Made-with: Cursor
This commit is contained in:
parent
3efe63c54d
commit
1abab20f17
23 changed files with 1222 additions and 0 deletions
42
MinecraftClient/Pathing/Goals/GoalBlock.cs
Normal file
42
MinecraftClient/Pathing/Goals/GoalBlock.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
|
||||
namespace MinecraftClient.Pathing.Goals
|
||||
{
|
||||
public sealed class GoalBlock : IGoal
|
||||
{
|
||||
public int X { get; }
|
||||
public int Y { get; }
|
||||
public int Z { get; }
|
||||
|
||||
public GoalBlock(int x, int y, int z)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
public bool IsInGoal(int x, int y, int z)
|
||||
=> x == X && y == Y && z == Z;
|
||||
|
||||
public double Heuristic(int x, int y, int z)
|
||||
{
|
||||
int dx = Math.Abs(x - X);
|
||||
int dy = Math.Abs(y - Y);
|
||||
int dz = Math.Abs(z - Z);
|
||||
return DistanceHeuristic(dx, dy, dz);
|
||||
}
|
||||
|
||||
internal static double DistanceHeuristic(int dx, int dy, int dz)
|
||||
{
|
||||
int horizontal = Math.Max(dx, dz);
|
||||
int diagonal = Math.Min(dx, dz);
|
||||
int straight = horizontal - diagonal;
|
||||
double cost = diagonal * Core.ActionCosts.SprintOneBlock * Core.ActionCosts.DiagonalMultiplier
|
||||
+ straight * Core.ActionCosts.SprintOneBlock
|
||||
+ Math.Abs(dy) * Core.ActionCosts.SprintOneBlock;
|
||||
return cost;
|
||||
}
|
||||
|
||||
public override string ToString() => $"GoalBlock({X}, {Y}, {Z})";
|
||||
}
|
||||
}
|
||||
45
MinecraftClient/Pathing/Goals/GoalComposite.cs
Normal file
45
MinecraftClient/Pathing/Goals/GoalComposite.cs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MinecraftClient.Pathing.Goals
|
||||
{
|
||||
public sealed class GoalComposite : IGoal
|
||||
{
|
||||
private readonly IGoal[] _goals;
|
||||
|
||||
public GoalComposite(params IGoal[] goals)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(goals);
|
||||
_goals = goals;
|
||||
}
|
||||
|
||||
public GoalComposite(IEnumerable<IGoal> goals)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(goals);
|
||||
_goals = goals is IGoal[] arr ? arr : [.. goals];
|
||||
}
|
||||
|
||||
public bool IsInGoal(int x, int y, int z)
|
||||
{
|
||||
foreach (var g in _goals)
|
||||
{
|
||||
if (g.IsInGoal(x, y, z))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public double Heuristic(int x, int y, int z)
|
||||
{
|
||||
double min = double.MaxValue;
|
||||
foreach (var g in _goals)
|
||||
{
|
||||
double h = g.Heuristic(x, y, z);
|
||||
if (h < min) min = h;
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
public override string ToString() => $"GoalComposite({_goals.Length} goals)";
|
||||
}
|
||||
}
|
||||
42
MinecraftClient/Pathing/Goals/GoalNear.cs
Normal file
42
MinecraftClient/Pathing/Goals/GoalNear.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
|
||||
namespace MinecraftClient.Pathing.Goals
|
||||
{
|
||||
public sealed class GoalNear : IGoal
|
||||
{
|
||||
public int X { get; }
|
||||
public int Y { get; }
|
||||
public int Z { get; }
|
||||
public int Range { get; }
|
||||
private readonly int _rangeSq;
|
||||
|
||||
public GoalNear(int x, int y, int z, int range)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
Range = range;
|
||||
_rangeSq = range * range;
|
||||
}
|
||||
|
||||
public bool IsInGoal(int x, int y, int z)
|
||||
{
|
||||
int dx = x - X;
|
||||
int dy = y - Y;
|
||||
int dz = z - Z;
|
||||
return dx * dx + dy * dy + dz * dz <= _rangeSq;
|
||||
}
|
||||
|
||||
public double Heuristic(int x, int y, int z)
|
||||
{
|
||||
int dx = Math.Abs(x - X);
|
||||
int dy = Math.Abs(y - Y);
|
||||
int dz = Math.Abs(z - Z);
|
||||
double h = GoalBlock.DistanceHeuristic(dx, dy, dz);
|
||||
double reduction = Range * Core.ActionCosts.SprintOneBlock;
|
||||
return Math.Max(0, h - reduction);
|
||||
}
|
||||
|
||||
public override string ToString() => $"GoalNear({X}, {Y}, {Z}, range={Range})";
|
||||
}
|
||||
}
|
||||
28
MinecraftClient/Pathing/Goals/GoalXZ.cs
Normal file
28
MinecraftClient/Pathing/Goals/GoalXZ.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
|
||||
namespace MinecraftClient.Pathing.Goals
|
||||
{
|
||||
public sealed class GoalXZ : IGoal
|
||||
{
|
||||
public int X { get; }
|
||||
public int Z { get; }
|
||||
|
||||
public GoalXZ(int x, int z)
|
||||
{
|
||||
X = x;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
public bool IsInGoal(int x, int y, int z)
|
||||
=> x == X && z == Z;
|
||||
|
||||
public double Heuristic(int x, int y, int z)
|
||||
{
|
||||
int dx = Math.Abs(x - X);
|
||||
int dz = Math.Abs(z - Z);
|
||||
return GoalBlock.DistanceHeuristic(dx, 0, dz);
|
||||
}
|
||||
|
||||
public override string ToString() => $"GoalXZ({X}, {Z})";
|
||||
}
|
||||
}
|
||||
8
MinecraftClient/Pathing/Goals/IGoal.cs
Normal file
8
MinecraftClient/Pathing/Goals/IGoal.cs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
namespace MinecraftClient.Pathing.Goals
|
||||
{
|
||||
public interface IGoal
|
||||
{
|
||||
bool IsInGoal(int x, int y, int z);
|
||||
double Heuristic(int x, int y, int z);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue