mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
fix: correct PathNode.Pack bit overlap causing hash collisions
The X and Z fields shared bit 36, causing nodes like (1,80,0) and (0,80,0) to hash to the same value. Fixed by using proper non-overlapping bit allocation: X in bits 38-63, Z in bits 12-37, Y in bits 0-11. Added diagnostic logging to pathfind command. Made-with: Cursor
This commit is contained in:
parent
1abab20f17
commit
e9b19d3cbb
7 changed files with 1389 additions and 3 deletions
|
|
@ -96,6 +96,9 @@ namespace MinecraftClient.Pathing.Core
|
|||
current.IsClosed = true;
|
||||
nodesExplored++;
|
||||
|
||||
if (nodesExplored <= 10)
|
||||
DebugLog?.Invoke($"[A*] Expand #{nodesExplored}: ({current.X},{current.Y},{current.Z}) F={current.FCost:F2} G={current.GCost:F2} H={current.HCost:F2}, openSet={openSet.Count}");
|
||||
|
||||
if (goal.IsInGoal(current.X, current.Y, current.Z))
|
||||
{
|
||||
DebugLog?.Invoke($"[A*] Goal reached! {nodesExplored} nodes, {sw.ElapsedMilliseconds}ms");
|
||||
|
|
@ -108,6 +111,15 @@ namespace MinecraftClient.Pathing.Core
|
|||
moveResult.Cost = 0;
|
||||
move.Calculate(ctx, current.X, current.Y, current.Z, ref moveResult);
|
||||
|
||||
if (nodesExplored <= 2)
|
||||
{
|
||||
if (moveResult.IsImpossible)
|
||||
DebugLog?.Invoke($"[A*] move {move.Type}({move.XOffset},{move.ZOffset}) from ({current.X},{current.Y},{current.Z}): IMPOSSIBLE");
|
||||
else
|
||||
DebugLog?.Invoke($"[A*] move {move.Type}({move.XOffset},{move.ZOffset}) from ({current.X},{current.Y},{current.Z}): " +
|
||||
$"-> ({moveResult.DestX},{moveResult.DestY},{moveResult.DestZ}) cost={moveResult.Cost:F2}");
|
||||
}
|
||||
|
||||
if (moveResult.IsImpossible)
|
||||
continue;
|
||||
|
||||
|
|
@ -127,6 +139,8 @@ namespace MinecraftClient.Pathing.Core
|
|||
|
||||
if (nodeMap.TryGetValue(packed, out var neighbor))
|
||||
{
|
||||
if (nodesExplored <= 2)
|
||||
DebugLog?.Invoke($"[A*] EXISTS ({nx},{ny},{nz}) pack={packed} actual=({neighbor.X},{neighbor.Y},{neighbor.Z}) closed={neighbor.IsClosed} tentG={tentativeG:F2} existG={neighbor.GCost:F2}");
|
||||
if (neighbor.IsClosed)
|
||||
continue;
|
||||
if (tentativeG >= neighbor.GCost)
|
||||
|
|
@ -140,6 +154,8 @@ namespace MinecraftClient.Pathing.Core
|
|||
}
|
||||
else
|
||||
{
|
||||
if (nodesExplored <= 2)
|
||||
DebugLog?.Invoke($"[A*] NEW ({nx},{ny},{nz}) pack={packed} G={tentativeG:F2} H={goal.Heuristic(nx, ny, nz):F2}");
|
||||
neighbor = new PathNode(nx, ny, nz)
|
||||
{
|
||||
GCost = tentativeG,
|
||||
|
|
@ -155,6 +171,8 @@ namespace MinecraftClient.Pathing.Core
|
|||
double partialScore = neighbor.HCost + neighbor.GCost * 0.5;
|
||||
if (partialScore < bestPartialScore)
|
||||
{
|
||||
if (nodesExplored <= 3)
|
||||
DebugLog?.Invoke($"[A*] partial improved: ({neighbor.X},{neighbor.Y},{neighbor.Z}) score={partialScore:F2} < {bestPartialScore:F2}");
|
||||
bestPartialScore = partialScore;
|
||||
bestPartialNode = neighbor;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,9 +31,11 @@ namespace MinecraftClient.Pathing.Core
|
|||
|
||||
public static long Pack(int x, int y, int z)
|
||||
{
|
||||
return ((long)(x + 30_000_000) << 36)
|
||||
| ((long)(z + 30_000_000) << 12)
|
||||
| (long)((y + 64) & 0xFFF);
|
||||
// 26 bits for X (0..60M), 26 bits for Z (0..60M), 12 bits for Y (-2048..2047)
|
||||
long px = (long)(x + 30_000_000) & 0x3FFFFFF;
|
||||
long pz = (long)(z + 30_000_000) & 0x3FFFFFF;
|
||||
long py = (long)(y + 2048) & 0xFFF;
|
||||
return (px << 38) | (pz << 12) | py;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue