feat(net): port retail physics spawn and event timestamps
Parse the complete PhysicsDesc plus F754/F755 packets, correct every PhysicsState bit, and gate all nine retail update channels with generation-safe immutable snapshots. Preserve ForcePosition, teleport, placement, velocity, parent, pickup, delete, and same-generation CreateObject ordering from the named client. Separate accepted logical lifecycle notifications from retained UI qualities, make GUID replacement and session reset clear every projection exactly once, and add packet, wraparound, malformed-input, parent FIFO, canonical-position, reconnect, and GUID-reuse conformance coverage. Co-Authored-By: Codex <noreply@openai.com>
This commit is contained in:
parent
d53fe30ffe
commit
8a5d77f7f4
50 changed files with 3809 additions and 649 deletions
|
|
@ -21,6 +21,18 @@ public readonly record struct MoveRequestFailure(
|
|||
uint WeenieError,
|
||||
bool RolledBack);
|
||||
|
||||
public enum ClientObjectRemovalReason
|
||||
{
|
||||
Ordinary,
|
||||
LogicalDelete,
|
||||
GenerationReplacement,
|
||||
}
|
||||
|
||||
public readonly record struct ClientObjectRemoval(
|
||||
ClientObject Object,
|
||||
ClientObjectRemovalReason Reason,
|
||||
ushort Generation);
|
||||
|
||||
/// <summary>
|
||||
/// The client's table of every server object (retail <c>weenie_object_table</c> /
|
||||
/// <c>CObjectMaint</c>). Resolve by guid via <c>Get</c>.
|
||||
|
|
@ -103,6 +115,13 @@ public sealed class ClientObjectTable
|
|||
/// <summary>Fires when an object is removed from the session.</summary>
|
||||
public event Action<ClientObject>? ObjectRemoved;
|
||||
|
||||
/// <summary>
|
||||
/// Generation-aware removal stream for runtime owners. UI consumers keep
|
||||
/// using <see cref="ObjectRemoved"/>; runtime owners use the reason and
|
||||
/// generation to preserve only packets addressed to future incarnations.
|
||||
/// </summary>
|
||||
public event Action<ClientObjectRemoval>? ObjectRemovalClassified;
|
||||
|
||||
/// <summary>Fires when an object's properties are updated (typically after Appraise).</summary>
|
||||
public event Action<ClientObject>? ObjectUpdated;
|
||||
|
||||
|
|
@ -321,15 +340,47 @@ public sealed class ClientObjectTable
|
|||
/// space, stolen, etc).
|
||||
/// </summary>
|
||||
public bool Remove(uint itemId)
|
||||
=> RemoveCore(itemId, ClientObjectRemovalReason.Ordinary, 0, notifyObjectRemoved: true);
|
||||
|
||||
/// <summary>Removes an exact accepted server object incarnation.</summary>
|
||||
public bool RemoveLogicalGeneration(uint itemId, ushort generation)
|
||||
=> RemoveCore(
|
||||
itemId,
|
||||
ClientObjectRemovalReason.LogicalDelete,
|
||||
generation,
|
||||
notifyObjectRemoved: true);
|
||||
|
||||
private bool RemoveCore(
|
||||
uint itemId,
|
||||
ClientObjectRemovalReason reason,
|
||||
ushort generation,
|
||||
bool notifyObjectRemoved)
|
||||
{
|
||||
if (!_objects.TryRemove(itemId, out var item)) return false;
|
||||
if (item.ContainerId != 0 && _containerIndex.TryGetValue(item.ContainerId, out var l))
|
||||
l.Remove(itemId);
|
||||
_pendingMoves.Remove(itemId); // a destroyed item must not leave a snapshot that mis-rolls-back a recycled guid
|
||||
ObjectRemoved?.Invoke(item);
|
||||
if (notifyObjectRemoved)
|
||||
ObjectRemoved?.Invoke(item);
|
||||
ObjectRemovalClassified?.Invoke(new ClientObjectRemoval(item, reason, generation));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Atomically replaces the retained qualities for a newer server object
|
||||
/// incarnation while publishing a generation-specific teardown event.
|
||||
/// </summary>
|
||||
public ClientObject ReplaceGeneration(WeenieData data, ushort generation)
|
||||
{
|
||||
RemoveCore(
|
||||
data.Guid,
|
||||
ClientObjectRemovalReason.GenerationReplacement,
|
||||
generation,
|
||||
notifyObjectRemoved: true);
|
||||
|
||||
return Ingest(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply a <see cref="PropertyBundle"/> patch (e.g. from an
|
||||
/// <c>IdentifyObjectResponse</c>) to an existing object. Individual
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue