fix(physics): #147 — far-town city/perimeter walls had no collision (portal-less buildings skipped)
A town's outer/perimeter walls have NO collision even on a fresh login: the player walks straight through them while houses block fine. Confirmed NOT a frame issue — #146's bldOrigin probe showed Arwic buildings are correctly framed (~12 m from the player, not km off), so the "#145 far-town frame" premise was wrong here. Root cause (dat-confirmed, Issue147ArwicBuildingsDumpTests): a perimeter wall is stored in LandBlockInfo.Buildings as a doorless shell — 16 of Arwic's 30 buildings are PORTAL-LESS, ringing the town at 24 m intervals (x=12/132, y=12/108). The building-collision cache loop skipped them via `if (building.Portals.Count == 0) continue;` — a filter meant only for the transit/entry feature (CellTransit.CheckBuildingTransit) that also dropped the collision shell. Retail's find_building_collisions (0x006b5300) tests the shell BSP independent of the portal list, so a doorless wall still collides. Fix: don't skip portal-less buildings — cache them with an empty portal list (no transit) but their collision shell (ModelId) intact. User-verified: Arwic perimeter walls now block (Collided/Slid). Adds the dat-dump fixture test. Suites green: Core 1569(+2 skip), App 468(+2 skip), UI 425, Net 317. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
31612e99c3
commit
9743537e62
2 changed files with 77 additions and 1 deletions
|
|
@ -0,0 +1,64 @@
|
|||
using System.IO;
|
||||
using System.Text;
|
||||
using DatReaderWriter;
|
||||
using DatReaderWriter.DBObjs;
|
||||
using DatReaderWriter.Options;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using Env = System.Environment;
|
||||
|
||||
namespace AcDream.Core.Tests.Physics;
|
||||
|
||||
/// <summary>
|
||||
/// #147 dat fixture: dump Arwic's (0xC6A9FFFE) LandBlockInfo Buildings + Objects
|
||||
/// to decide what the city/perimeter WALLS are — buildings WITHOUT portals
|
||||
/// (skipped by the building-collision cache loop's
|
||||
/// <c>if (building.Portals.Count == 0) continue;</c>) vs landblock-static stabs
|
||||
/// (a separate shadow-object collision path). Dat-data-dependent; SKIPs cleanly
|
||||
/// without ACDREAM_DAT_DIR / the real dats.
|
||||
/// </summary>
|
||||
public sealed class Issue147ArwicBuildingsDumpTests
|
||||
{
|
||||
private readonly ITestOutputHelper _out;
|
||||
public Issue147ArwicBuildingsDumpTests(ITestOutputHelper o) => _out = o;
|
||||
|
||||
[Fact]
|
||||
public void DumpArwicBuildingsAndObjects()
|
||||
{
|
||||
var datDir = Env.GetEnvironmentVariable("ACDREAM_DAT_DIR")
|
||||
?? Path.Combine(Env.GetFolderPath(Env.SpecialFolder.UserProfile),
|
||||
"Documents", "Asheron's Call");
|
||||
if (!Directory.Exists(datDir)) { _out.WriteLine($"SKIP: no dats at {datDir}"); return; }
|
||||
|
||||
using var dats = new DatCollection(datDir, DatAccessType.Read);
|
||||
var info = dats.Get<LandBlockInfo>(0xC6A9FFFEu); // Arwic landblock info
|
||||
Assert.NotNull(info);
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"Arwic 0xC6A9FFFE: Buildings={info.Buildings.Count} Objects={info.Objects.Count}");
|
||||
|
||||
int portalless = 0;
|
||||
sb.AppendLine("--- Buildings (ModelId, portals, origin) ---");
|
||||
foreach (var b in info.Buildings)
|
||||
{
|
||||
if (b.Portals.Count == 0) portalless++;
|
||||
sb.AppendLine(System.FormattableString.Invariant(
|
||||
$" model=0x{b.ModelId:X8} portals={b.Portals.Count} origin=({b.Frame.Origin.X:F1},{b.Frame.Origin.Y:F1},{b.Frame.Origin.Z:F1})"));
|
||||
}
|
||||
sb.AppendLine($"--- portal-less buildings (skipped by the collision cache): {portalless} ---");
|
||||
|
||||
sb.AppendLine("--- Objects / stabs (first 50: Id, origin) ---");
|
||||
int n = 0;
|
||||
foreach (var o in info.Objects)
|
||||
{
|
||||
if (n++ >= 50) break;
|
||||
sb.AppendLine(System.FormattableString.Invariant(
|
||||
$" id=0x{o.Id:X8} origin=({o.Frame.Origin.X:F1},{o.Frame.Origin.Y:F1},{o.Frame.Origin.Z:F1})"));
|
||||
}
|
||||
|
||||
var outPath = Path.Combine(Path.GetTempPath(), "arwic-buildings-dump.txt");
|
||||
File.WriteAllText(outPath, sb.ToString());
|
||||
_out.WriteLine(sb.ToString());
|
||||
_out.WriteLine($"(also written to {outPath})");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue