namespace AcDream.Core.Physics.Motion;
///
/// R5 — port of retail's TargettedVoyeurInfo (acclient.h:52807,
/// struct #5801). One entry in a 's voyeur table:
/// a subscriber watching THIS object, the send-on-move
/// threshold it registered, its dead-reckoning , and the
/// already delivered to it (the delta baseline
/// CheckAndUpdateVoyeur compares against). Mutable class (retail heap
/// record updated in place by AddVoyeur/SendVoyeurUpdate).
///
public sealed class TargettedVoyeurInfo
{
///
/// Exact watcher incarnation captured when this subscription is created.
/// Retail object IDs are process-lifetime object-table identities; the App
/// preserves that pointer-like identity explicitly while an old
/// INSTANCE_TS teardown may overlap a newer record with the same GUID.
///
internal IPhysicsObjHost WatcherHost { get; }
/// +0x00 retail object_id — the subscriber's guid.
public uint ObjectId { get; }
/// +0x04 retail quantum — the subscriber's dead-reckoning
/// lookahead horizon (seconds).
public double Quantum { get; set; }
/// +0x10 retail radius — the send-on-move threshold: an
/// update is pushed only when the tracked object drifts more than this from
/// .
public float Radius { get; set; }
/// +0x14 retail last_sent_position — the position last
/// delivered to this subscriber (updated by SendVoyeurUpdate).
public Position LastSentPosition { get; set; }
public TargettedVoyeurInfo(
uint objectId,
float radius,
double quantum,
IPhysicsObjHost watcherHost)
{
ArgumentNullException.ThrowIfNull(watcherHost);
if (watcherHost.Id != objectId)
{
throw new ArgumentException(
"Watcher identity must match the voyeur object ID.",
nameof(watcherHost));
}
ObjectId = objectId;
Radius = radius;
Quantum = quantum;
WatcherHost = watcherHost;
}
}