feat: Replace FastAStarAlgorithm with BitmapAStarAlgorithm (#2446)

## Summary

Replaces `FastAStarAlgorithm` with `BitmapAStarAlgorithm`: one cache lookup per cell expansion (8-direction mask + per-direction destination Z) instead of 8 separate `MovementImpl.CheckMovement` calls. Adds the supporting cache infrastructure to back it.

Public API unchanged — `MovementPath` / `Mobile.Move` / `CalcMoves.Find` return the same shapes; the algorithm swap is internal.

## What's in this PR

- **`BitmapAStarAlgorithm`** — A* that issues one `StepCache.TryGetMask` call per cell expansion. Inline fallthrough to the per-cell slow path for multi-Z, off-map, source-Z mismatch, and non-default walkers.
- **`StepCache`** — singleton chunk store keyed by `(mapId, chunkX, chunkY)`. Lazily built on first query, invalidated by `Sector.MultisVersion` mismatch, memory-bounded by sampled probabilistic LRU.
- **`StepProbe`** — computes static-only walkability for a single cell, mirroring `MovementImpl.Check` minus the item / mobile collision phases.
- **`StepMask` / `StepChunk`** — value / storage types for the per-cell results.
- **`CacheEvictionTimer`** — periodic cap backstop (60s interval; early-returns when not over cap).
- **`Map.Sector.MultisVersion`** promoted to `public` so the cache can detect dynamic-static invalidations cheaply.

## Eviction strategy

Sampled probabilistic LRU (Redis-style). Per eviction, sample 5 random keys from a parallel `List<long>` kept in lockstep with the chunk dictionary; evict the oldest of the sample via swap-and-pop. O(1) per eviction regardless of resident count, so sustained cap pressure has no perpetual perf hit.

## Capability handling (interim)

Non-default walkers (non-GM players, creatures with `CanSwim` / `CanFly` / `CanOpenDoors` / `CanMoveOverObstacles`) route entirely through the per-cell slow path via `BitmapAStarAlgorithm.GetSuccessorsSlowPath`. The 2-pass design (cache + capability overlay + dynamic-obstacle pass) lands in the follow-up PR.
This commit is contained in:
Kamron Batman 2026-05-05 21:53:43 -07:00 committed by GitHub
parent ee1bf23b72
commit 6a3804addc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 1832 additions and 50 deletions

View file

@ -1,8 +1,9 @@
using System;
using System.Diagnostics;
using Server.Engines.Pathing.Cache;
using Server.Items;
using Server.PathAlgorithms;
using Server.PathAlgorithms.FastAStar;
using Server.PathAlgorithms.BitmapAStar;
using Server.Spells;
using Server.Targeting;
@ -31,7 +32,7 @@ namespace Server
try
{
var alg = OverrideAlgorithm ?? FastAStarAlgorithm.Instance;
var alg = OverrideAlgorithm ?? BitmapAStarAlgorithm.Instance;
if (alg?.CheckCondition(m, map, start, goal) == true)
{
@ -59,6 +60,7 @@ namespace Server
public static void Configure()
{
CommandSystem.Register("Path", AccessLevel.GameMaster, Path_OnCommand);
CacheEvictionTimer.Configure();
}
[Usage("Path")]
@ -111,7 +113,7 @@ namespace Server
SpellHelper.GetSurfaceTop(ref p);
Path(from, p, FastAStarAlgorithm.Instance, "Fast", 0);
Path(from, p, BitmapAStarAlgorithm.Instance, "Bitmap", 0);
OverrideAlgorithm = null;
}
}