feat(runtime): own deferred set-position residence
This commit is contained in:
parent
e84a388e6f
commit
4c02ac4259
18 changed files with 5557 additions and 34 deletions
|
|
@ -16,6 +16,7 @@ public sealed class ParentAttachmentState
|
|||
private readonly Dictionary<uint, ParentAttachmentRelation> _stagedByChild = new();
|
||||
private readonly Dictionary<uint, ParentAttachmentRelation> _recoveryByChild = new();
|
||||
private readonly Dictionary<uint, ParentAttachmentRelation> _lastAcceptedByChild = new();
|
||||
private readonly Dictionary<ParentIncarnation, List<uint>> _committedChildrenByParent = new();
|
||||
|
||||
public int UnresolvedRelationCount =>
|
||||
_unresolvedByChild.Values.Sum(queue => queue.Count);
|
||||
|
|
@ -148,6 +149,9 @@ public sealed class ParentAttachmentState
|
|||
out ParentAttachmentRelation committed)
|
||||
&& committed == relation;
|
||||
|
||||
public bool HasCommittedParent(uint childGuid) =>
|
||||
_lastAcceptedByChild.ContainsKey(childGuid);
|
||||
|
||||
public bool IsPending(
|
||||
ParentAttachmentRelation relation,
|
||||
ParentProjectionCandidateKind kind) =>
|
||||
|
|
@ -184,7 +188,20 @@ public sealed class ParentAttachmentState
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RemoveCommittedChild(relation.ChildGuid);
|
||||
_lastAcceptedByChild[relation.ChildGuid] = relation;
|
||||
var parent = new ParentIncarnation(
|
||||
relation.ParentGuid,
|
||||
relation.ParentInstanceSequence);
|
||||
if (!_committedChildrenByParent.TryGetValue(
|
||||
parent,
|
||||
out List<uint>? children))
|
||||
{
|
||||
children = [];
|
||||
_committedChildrenByParent.Add(parent, children);
|
||||
}
|
||||
children.Add(relation.ChildGuid);
|
||||
_stagedByChild.Remove(relation.ChildGuid);
|
||||
_recoveryByChild[relation.ChildGuid] = relation;
|
||||
return true;
|
||||
|
|
@ -233,16 +250,34 @@ public sealed class ParentAttachmentState
|
|||
return result.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns only the exact direct children currently committed to one
|
||||
/// parent incarnation. Lost-cell destruction follows retail's live
|
||||
/// CHILDLIST and must not capture staged, unresolved, or future-generation
|
||||
/// relations that merely reuse the same parent GUID.
|
||||
/// </summary>
|
||||
public IReadOnlyList<uint> ChildrenAttachedToParent(
|
||||
uint parentGuid,
|
||||
ushort parentInstanceSequence)
|
||||
{
|
||||
var parent = new ParentIncarnation(parentGuid, parentInstanceSequence);
|
||||
return _committedChildrenByParent.TryGetValue(
|
||||
parent,
|
||||
out List<uint>? children)
|
||||
? children
|
||||
: Array.Empty<uint>();
|
||||
}
|
||||
|
||||
public void RemoveObject(uint guid)
|
||||
{
|
||||
_stagedByChild.Remove(guid);
|
||||
_recoveryByChild.Remove(guid);
|
||||
_lastAcceptedByChild.Remove(guid);
|
||||
RemoveCommittedChild(guid);
|
||||
_unresolvedByChild.Remove(guid);
|
||||
|
||||
RemoveParentReferences(_stagedByChild, guid);
|
||||
RemoveParentReferences(_recoveryByChild, guid);
|
||||
RemoveParentReferences(_lastAcceptedByChild, guid);
|
||||
RemoveCommittedParentReferences(guid);
|
||||
|
||||
uint[] children = _unresolvedByChild.Keys.ToArray();
|
||||
for (int i = 0; i < children.Length; i++)
|
||||
|
|
@ -268,10 +303,10 @@ public sealed class ParentAttachmentState
|
|||
relation => relation.WaitOwner is ParentAttachmentWaitOwner.Parent);
|
||||
_stagedByChild.Remove(guid);
|
||||
_recoveryByChild.Remove(guid);
|
||||
_lastAcceptedByChild.Remove(guid);
|
||||
RemoveCommittedChild(guid);
|
||||
RemoveParentReferences(_stagedByChild, guid);
|
||||
RemoveParentReferences(_recoveryByChild, guid);
|
||||
RemoveParentReferences(_lastAcceptedByChild, guid);
|
||||
RemoveCommittedParentReferences(guid);
|
||||
FilterParentCandidates(
|
||||
guid,
|
||||
relation => relation.ParentInstanceSequence == replacementGeneration
|
||||
|
|
@ -292,10 +327,10 @@ public sealed class ParentAttachmentState
|
|||
relation => relation.WaitOwner is ParentAttachmentWaitOwner.Parent);
|
||||
_stagedByChild.Remove(guid);
|
||||
_recoveryByChild.Remove(guid);
|
||||
_lastAcceptedByChild.Remove(guid);
|
||||
RemoveCommittedChild(guid);
|
||||
RemoveParentReferences(_stagedByChild, guid);
|
||||
RemoveParentReferences(_recoveryByChild, guid);
|
||||
RemoveParentReferences(_lastAcceptedByChild, guid);
|
||||
RemoveCommittedParentReferences(guid);
|
||||
FilterParentCandidates(
|
||||
guid,
|
||||
relation => PhysicsTimestampGate.IsNewer(
|
||||
|
|
@ -311,14 +346,14 @@ public sealed class ParentAttachmentState
|
|||
{
|
||||
_stagedByChild.Remove(childGuid);
|
||||
_recoveryByChild.Remove(childGuid);
|
||||
_lastAcceptedByChild.Remove(childGuid);
|
||||
RemoveCommittedChild(childGuid);
|
||||
}
|
||||
|
||||
public void RemoveChild(uint childGuid)
|
||||
{
|
||||
_stagedByChild.Remove(childGuid);
|
||||
_recoveryByChild.Remove(childGuid);
|
||||
_lastAcceptedByChild.Remove(childGuid);
|
||||
RemoveCommittedChild(childGuid);
|
||||
_unresolvedByChild.Remove(childGuid);
|
||||
}
|
||||
|
||||
|
|
@ -328,6 +363,50 @@ public sealed class ParentAttachmentState
|
|||
_stagedByChild.Clear();
|
||||
_recoveryByChild.Clear();
|
||||
_lastAcceptedByChild.Clear();
|
||||
foreach (List<uint> children in _committedChildrenByParent.Values)
|
||||
children.Clear();
|
||||
_committedChildrenByParent.Clear();
|
||||
}
|
||||
|
||||
private void RemoveCommittedChild(uint childGuid)
|
||||
{
|
||||
if (!_lastAcceptedByChild.Remove(
|
||||
childGuid,
|
||||
out ParentAttachmentRelation relation))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var parent = new ParentIncarnation(
|
||||
relation.ParentGuid,
|
||||
relation.ParentInstanceSequence);
|
||||
if (!_committedChildrenByParent.TryGetValue(
|
||||
parent,
|
||||
out List<uint>? children))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int childIndex = children.IndexOf(childGuid);
|
||||
if (childIndex >= 0)
|
||||
{
|
||||
int lastIndex = children.Count - 1;
|
||||
children[childIndex] = children[lastIndex];
|
||||
children.RemoveAt(lastIndex);
|
||||
}
|
||||
|
||||
if (children.Count == 0)
|
||||
_committedChildrenByParent.Remove(parent);
|
||||
}
|
||||
|
||||
private void RemoveCommittedParentReferences(uint parentGuid)
|
||||
{
|
||||
uint[] children = _lastAcceptedByChild
|
||||
.Where(pair => pair.Value.ParentGuid == parentGuid)
|
||||
.Select(pair => pair.Key)
|
||||
.ToArray();
|
||||
for (int i = 0; i < children.Length; i++)
|
||||
RemoveCommittedChild(children[i]);
|
||||
}
|
||||
|
||||
private static void RemoveParentReferences(
|
||||
|
|
@ -377,6 +456,10 @@ public sealed class ParentAttachmentState
|
|||
else
|
||||
_unresolvedByChild[childGuid] = retained;
|
||||
}
|
||||
|
||||
private readonly record struct ParentIncarnation(
|
||||
uint ServerGuid,
|
||||
ushort InstanceSequence);
|
||||
}
|
||||
|
||||
public readonly record struct ParentAttachmentRelation(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue