feat(world): Phase A8 R1 — tag WorldEntity.IsBuildingShell at LandblockLoader

Adds a bool flag at the WorldEntity data layer set by LandblockLoader from
the source dat array: LandBlockInfo.Buildings → true (cottage walls, inn
walls, smithy walls); LandBlockInfo.Objects → false (trees, lampposts,
rocks, hitching posts).

Retail anchor: CLandBlock::init_buildings reads a separate BuildInfo**
array from objects (acclient.h:31893 num_buildings / buildings field;
acclient_2013_pseudo_c.txt:313854 init_buildings entry). WorldBuilder
preserves the same distinction via SceneryInstance.IsBuilding
(StaticObjectRenderManager.cs:334). Today acdream's loader reads both
arrays into the same WorldEntity pool with no tag, destroying the
distinction (the comment at GameWindow.cs:5175 already acknowledges this
gap for scenery suppression). This commit closes the gap.

Render-time consumption arrives in R2 (EntitySet partition refactor).
Two new LandblockLoader tests lock the tagging behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-26 11:31:11 +02:00
parent d2db8d5b22
commit ed72704f7b
4 changed files with 71 additions and 0 deletions

View file

@ -5133,6 +5133,7 @@ public sealed class GameWindow : IDisposable
Position = e.Position + worldOffset,
Rotation = e.Rotation,
MeshRefs = meshRefs,
IsBuildingShell = e.IsBuildingShell, // Phase A8: preserve dat-level tag
};
hydrated.Add(entity);
}

View file

@ -82,6 +82,7 @@ public static class LandblockLoader
Position = building.Frame.Origin,
Rotation = building.Frame.Orientation,
MeshRefs = Array.Empty<MeshRef>(),
IsBuildingShell = true, // Phase A8: tag at source array boundary
};
buildingEntity.RefreshAabb(); // A.5 T18: populate cached AABB at construction
result.Add(buildingEntity);

View file

@ -44,6 +44,25 @@ public sealed class WorldEntity
/// </summary>
public uint? ParentCellId { get; init; }
/// <summary>
/// True when this entity originates from <c>LandBlockInfo.Buildings[]</c>
/// (the dat array that carries building shells: cottage walls, smithy walls,
/// inn walls — every solid building enclosure). False for entities from
/// <c>LandBlockInfo.Objects[]</c> (rocks, fences, lampposts, tree clusters —
/// outdoor scenery placeholders). The two arrays are conflated through
/// hydration today but the dat itself carries the distinction; retail
/// (<c>CLandBlock::init_buildings</c>) and WorldBuilder
/// (<c>SceneryInstance.IsBuilding</c>) both preserve it.
///
/// <para>
/// Read at draw time by <c>WbDrawDispatcher</c>'s <c>IndoorPass</c>
/// partition so building shells render unconditionally when the camera
/// is inside their building (they ARE the indoor walls), not stencil-gated
/// as outdoor scenery would be.
/// </para>
/// </summary>
public bool IsBuildingShell { get; init; }
/// <summary>
/// Uniform scale applied to this entity's mesh by the scenery pipeline.
/// For scenery objects this is spawn.Scale (typically 0.81.3). For stabs