perf(streaming): cursor publication across frame budgets
This commit is contained in:
parent
bb16f74fd4
commit
98f1ac8934
32 changed files with 2215 additions and 823 deletions
|
|
@ -455,6 +455,18 @@ public sealed class ShadowObjectRegistry
|
|||
/// cells hydrated after a server spawn landed.
|
||||
/// </summary>
|
||||
public void RefloodLandblock(uint landblockId)
|
||||
{
|
||||
uint[] owners = CaptureRefloodOwnersForLandblock(landblockId);
|
||||
for (int i = 0; i < owners.Length; i++)
|
||||
RefloodOwnerForLandblock(owners[i], landblockId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Captures the stable ordered owner set touched by one landblock reflood.
|
||||
/// App-layer streaming can retain this receipt and advance one owner per
|
||||
/// frame without changing the collision registry's ownership rules.
|
||||
/// </summary>
|
||||
public uint[] CaptureRefloodOwnersForLandblock(uint landblockId)
|
||||
{
|
||||
uint lbPrefix = landblockId & 0xFFFF0000u;
|
||||
var toReflood = new HashSet<uint>();
|
||||
|
|
@ -487,39 +499,81 @@ public sealed class ShadowObjectRegistry
|
|||
}
|
||||
}
|
||||
|
||||
foreach (uint entityId in toReflood)
|
||||
uint[] ordered = toReflood.ToArray();
|
||||
Array.Sort(ordered);
|
||||
return ordered;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Re-runs one owner from a retained landblock-reflood receipt. A removed,
|
||||
/// suspended, or otherwise superseded owner is an idempotent no-op.
|
||||
/// </summary>
|
||||
public void RefloodOwnerForLandblock(uint entityId, uint landblockId)
|
||||
{
|
||||
uint lbPrefix = landblockId & 0xFFFF0000u;
|
||||
if (_suspendedEntities.Contains(entityId)
|
||||
|| !_entityReg.TryGetValue(
|
||||
entityId,
|
||||
out RegistrationRecord? reg))
|
||||
{
|
||||
var reg = _entityReg[entityId];
|
||||
_withdrawnPrefixesByOwner.TryGetValue(entityId, out var withdrawnBeforeReflood);
|
||||
if (reg.IsMultiPart && _entityShapes.TryGetValue(entityId, out var shapes))
|
||||
{
|
||||
RegisterMultiPart(entityId, reg.EntityWorldPos, reg.EntityWorldRot, shapes,
|
||||
reg.State, reg.Flags, 0f, 0f, lbPrefix,
|
||||
reg.SeedCellId, reg.IsStatic);
|
||||
}
|
||||
else
|
||||
{
|
||||
Register(entityId, reg.GfxObjId, reg.EntityWorldPos, reg.EntityWorldRot,
|
||||
reg.Radius, 0f, 0f, lbPrefix,
|
||||
reg.CollisionType, reg.CylHeight, reg.Scale,
|
||||
reg.State, reg.Flags, reg.SeedCellId, reg.IsStatic);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Register is also the authoritative movement/replacement API and
|
||||
// therefore clears obsolete markers. Only this streaming reflood
|
||||
// operation preserves the still-missing prefixes across replacement.
|
||||
if (withdrawnBeforeReflood is not null)
|
||||
_withdrawnPrefixesByOwner[entityId] = withdrawnBeforeReflood;
|
||||
_withdrawnPrefixesByOwner.TryGetValue(
|
||||
entityId,
|
||||
out var withdrawnBeforeReflood);
|
||||
if (reg.IsMultiPart
|
||||
&& _entityShapes.TryGetValue(entityId, out var shapes))
|
||||
{
|
||||
RegisterMultiPart(
|
||||
entityId,
|
||||
reg.EntityWorldPos,
|
||||
reg.EntityWorldRot,
|
||||
shapes,
|
||||
reg.State,
|
||||
reg.Flags,
|
||||
0f,
|
||||
0f,
|
||||
lbPrefix,
|
||||
reg.SeedCellId,
|
||||
reg.IsStatic);
|
||||
}
|
||||
else
|
||||
{
|
||||
Register(
|
||||
entityId,
|
||||
reg.GfxObjId,
|
||||
reg.EntityWorldPos,
|
||||
reg.EntityWorldRot,
|
||||
reg.Radius,
|
||||
0f,
|
||||
0f,
|
||||
lbPrefix,
|
||||
reg.CollisionType,
|
||||
reg.CylHeight,
|
||||
reg.Scale,
|
||||
reg.State,
|
||||
reg.Flags,
|
||||
reg.SeedCellId,
|
||||
reg.IsStatic);
|
||||
}
|
||||
|
||||
if (_entityToCells.TryGetValue(entityId, out var refreshedCells)
|
||||
&& refreshedCells.Exists(cell =>
|
||||
(cell & 0xFFFF0000u) == lbPrefix)
|
||||
&& _withdrawnPrefixesByOwner.TryGetValue(entityId, out var withdrawn))
|
||||
{
|
||||
withdrawn.Remove(lbPrefix);
|
||||
if (withdrawn.Count == 0)
|
||||
_withdrawnPrefixesByOwner.Remove(entityId);
|
||||
}
|
||||
// Register is also the authoritative movement/replacement API and
|
||||
// therefore clears obsolete markers. Only this streaming reflood
|
||||
// operation preserves the still-missing prefixes across replacement.
|
||||
if (withdrawnBeforeReflood is not null)
|
||||
_withdrawnPrefixesByOwner[entityId] = withdrawnBeforeReflood;
|
||||
|
||||
if (_entityToCells.TryGetValue(entityId, out var refreshedCells)
|
||||
&& refreshedCells.Exists(cell =>
|
||||
(cell & 0xFFFF0000u) == lbPrefix)
|
||||
&& _withdrawnPrefixesByOwner.TryGetValue(
|
||||
entityId,
|
||||
out var withdrawn))
|
||||
{
|
||||
withdrawn.Remove(lbPrefix);
|
||||
if (withdrawn.Count == 0)
|
||||
_withdrawnPrefixesByOwner.Remove(entityId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -596,6 +650,17 @@ public sealed class ShadowObjectRegistry
|
|||
/// are deliberately retained for spatial reflood after streaming changes.
|
||||
/// </summary>
|
||||
public void DeregisterStaticOwnersForLandblock(uint landblockId)
|
||||
{
|
||||
uint[] owners = CaptureStaticOwnersForLandblock(landblockId);
|
||||
for (int i = 0; i < owners.Length; i++)
|
||||
DeregisterStaticOwnerForLandblock(owners[i], landblockId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Captures a stable ordered receipt for static collision owners rooted in
|
||||
/// one landblock.
|
||||
/// </summary>
|
||||
public uint[] CaptureStaticOwnersForLandblock(uint landblockId)
|
||||
{
|
||||
uint prefix = landblockId & 0xFFFF0000u;
|
||||
var owners = new List<uint>();
|
||||
|
|
@ -607,9 +672,27 @@ public sealed class ShadowObjectRegistry
|
|||
owners.Add(entityId);
|
||||
}
|
||||
}
|
||||
owners.Sort();
|
||||
return owners.ToArray();
|
||||
}
|
||||
|
||||
foreach (uint entityId in owners)
|
||||
/// <summary>
|
||||
/// Removes one static owner from a retained landblock receipt. If the
|
||||
/// owner was already removed or rebound elsewhere, the operation no-ops.
|
||||
/// </summary>
|
||||
public void DeregisterStaticOwnerForLandblock(
|
||||
uint entityId,
|
||||
uint landblockId)
|
||||
{
|
||||
uint prefix = landblockId & 0xFFFF0000u;
|
||||
if (_entityReg.TryGetValue(
|
||||
entityId,
|
||||
out RegistrationRecord? registration)
|
||||
&& registration.IsStatic
|
||||
&& (registration.SeedCellId & 0xFFFF0000u) == prefix)
|
||||
{
|
||||
Deregister(entityId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue