fix(world+streaming): trees-in-sky Z, O(1) anim, teleport near-ring + immediate unloads
Three apparatus-confirmed fixes from the world-load/FPS deep-dive (all live-verified).
1. trees-in-sky — scenery ground-Z now samples THIS landblock's OWN heightmap
(TerrainSurface.SampleZFromHeightmap, lock-step with the physics terrain) instead
of the global PhysicsEngine.SampleTerrainZ query. At build time the landblock isn't
registered in physics yet, so that query could only return null OR a STALE
neighbour's height — the previous location's terrain, still registered after a
teleport recenter — planting scenery at the old altitude (+250..500m, confirmed via
the [scenery-z-stale] probe). Own-heightmap is correct in every case; the query is
removed. (GameWindow.BuildSceneryEntitiesForStreaming)
2. FPS per-hop — TickAnimations recovered each animated entity's server guid via an
O(N) ReferenceEquals reverse scan over ALL _entitiesByServerGuid (which never
evicts, so N climbs every teleport — the drops-with-each-hop sink). Replaced with
ae.Entity.ServerGuid: O(1), exact-equivalent (the dict key IS entity.ServerGuid).
(GameWindow.TickAnimations)
3. teleport arrival + bulk floating terrain — two streaming fixes:
- Near-ring eager-apply: a teleport applies the destination's 3x3 surroundings
(StreamingController.PriorityRadius) and holds the fade until they're resident
(PhysicsEngine.IsNeighborhoodTerrainResident), so the player arrives in a loaded,
collidable world instead of one landblock in the void.
- Immediate unloads: DrainAndApply no longer throttles UNLOADS at the per-frame
load budget — they're cheap (free GPU buffers, no upload). A teleport produced
~600 unloads draining at 4/frame, leaving the previous region resident for
seconds (floating terrain) and accumulating across rapid hops (951 resident vs a
625 window). Only GPU-upload LOADS are metered now. Cut out-of-window resident
650 -> 63 and resident 951 -> 688 (live-verified via [resid-audit]).
Includes gated-off diagnostic probes (ACDREAM_PROBE_SCENERY_FRAME / _BLDG_REACH /
_STREAM_RESID) used to root-cause the above — zero-cost when unset, same pattern as
the committed tp-probe.
The pre-existing teleport-induced "terrain arcs in the sky" (present in the dd2eb8b
baseline too, with NONE of this work) are a SEPARATE bug — investigated next.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8fbde99441
commit
15e320490d
6 changed files with 382 additions and 61 deletions
|
|
@ -45,6 +45,34 @@ public sealed class PhysicsEngine
|
|||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True once EVERY in-bounds landblock within Chebyshev <paramref name="radius"/> of the
|
||||
/// landblock covering <paramref name="cellOrLandblockId"/> has had its terrain registered.
|
||||
/// This is the teleport "surroundings are loaded" gate: holding the fade until the player's
|
||||
/// own landblock AND its immediate neighbours are resident means they arrive standing on a
|
||||
/// loaded, collidable world (their cell-walk can root into neighbour cells) instead of a
|
||||
/// single landblock floating in the void. Off-map neighbours (coords outside 0..254) are
|
||||
/// skipped — they never load, so requiring them would hang the hold until the wall-clock
|
||||
/// timeout. radius 0 is equivalent to <see cref="IsLandblockTerrainResident"/>.
|
||||
/// </summary>
|
||||
public bool IsNeighborhoodTerrainResident(uint cellOrLandblockId, int radius)
|
||||
{
|
||||
var resident = new HashSet<uint>();
|
||||
foreach (var key in _landblocks.Keys) resident.Add(key & 0xFFFF0000u);
|
||||
|
||||
int cx = (int)((cellOrLandblockId >> 24) & 0xFFu);
|
||||
int cy = (int)((cellOrLandblockId >> 16) & 0xFFu);
|
||||
for (int dx = -radius; dx <= radius; dx++)
|
||||
for (int dy = -radius; dy <= radius; dy++)
|
||||
{
|
||||
int nx = cx + dx, ny = cy + dy;
|
||||
if (nx < 0 || nx > 254 || ny < 0 || ny > 254) continue; // off-map: skip
|
||||
uint prefix = ((uint)nx << 24) | ((uint)ny << 16);
|
||||
if (!resident.Contains(prefix)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cell-based spatial index for static object collision.
|
||||
/// Populated during landblock streaming; queried by the Transition system.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue