using System.Numerics;
namespace AcDream.Core.Physics.Motion;
///
/// R5 seam — the acdream stand-in for retail's CPhysicsObj as seen BY
/// its owned managers. Retail's StickyManager / ConstraintManager
/// / TargetManager each hold a raw physics_obj pointer and call
/// back through it (position/velocity/radius accessors, target-tracking
/// registration, the HandleUpdateTarget fan-out) and — for the voyeur
/// system — resolve OTHER physics objects via CObjectMaint::GetObjectA
/// and drive their add_voyeur / receive_target_update /
/// remove_voyeur entry points. This interface is that back-pointer.
///
/// The App layer implements one host per entity (a remote
/// RemoteMotion or the local player), wiring the accessors to the live
/// and the /
/// / it owns.
/// is backed by the App's canonical
/// LiveEntityRuntime records, giving the voyeur round-trip its
/// cross-entity delivery path without a second GUID index.
///
public interface IPhysicsObjHost
{
/// Retail physics_obj->id — this object's guid.
uint Id { get; }
/// Retail physics_obj->m_position — world-space cell +
/// frame (acdream seams carry WORLD space; see the MoveToManager binding
/// note).
Position Position { get; }
/// Retail CPhysicsObj::get_velocity.
Vector3 Velocity { get; }
/// Retail CPhysicsObj::GetRadius — the mover's cylinder
/// radius.
float Radius { get; }
/// Retail physics_obj->transient_state & 1 — the
/// CONTACT bit (ConstraintManager's grounded gate).
bool InContact { get; }
/// Retail CPhysicsObj::get_minterp()->get_max_speed() —
/// the mover's max locomotion speed, or null if it has no motion
/// interpreter yet (StickyManager falls back to a 15.0 constant).
float? MinterpMaxSpeed { get; }
/// Retail Timer::cur_time — the wall/game clock (seconds).
/// Drives the sticky 1 s timeout and target 10 s staleness deadlines.
double CurTime { get; }
/// Retail PhysicsTimer::curr_time — the physics-tick clock
/// (seconds). Drives TargetManager::HandleTargetting's 0.5 s
/// throttle. Retail uses a DIFFERENT clock here than ;
/// acdream may bind both to the same source.
double PhysicsTimerTime { get; }
/// Retail CObjectMaint::GetObjectA(id) — resolve another
/// physics object by guid from the object table. The App additionally
/// withholds Hidden objects from ordinary relationship creation through
/// its registered TS-49 DetectionManager adaptation. This is the
/// cross-entity seam for the voyeur round-trip and sticky live-target
/// resolve.
IPhysicsObjHost? GetObjectA(uint id);
///
/// Returns the exact target incarnation captured by this host's current
/// TargetManager relationship. App teardown can overlap a newer
/// INSTANCE_TS with the same GUID, so StickyManager must not re-resolve the
/// relationship through the active GUID table.
///
IPhysicsObjHost? GetRelationshipTarget(uint objectId);
/// Retail CPhysicsObj::HandleUpdateTarget — fans a
/// to this host's
/// (move-to steering) AND (sticky follow).
/// Called from and the timeout
/// path.
void HandleUpdateTarget(TargetInfo info);
/// Retail CPhysicsObj::interrupt_current_movement →
/// MovementManager::CancelMoveTo(0x36).
void InterruptCurrentMovement();
/// Retail CPhysicsObj::set_target(ctx, objId, radius,
/// quantum) → (lazily creating
/// the TargetManager). Called by StickyManager::StickTo and
/// MoveToManager's object-move entry points.
void SetTarget(uint contextId, uint objectId, float radius, double quantum);
/// Retail CPhysicsObj::clear_target →
/// .
void ClearTarget();
/// Retail CPhysicsObj::receive_target_update →
/// . The inbound side a SENDER's
/// SendVoyeurUpdate tail-calls on the watcher.
void ReceiveTargetUpdate(TargetInfo info, IPhysicsObjHost sender);
/// Retail CPhysicsObj::add_voyeur(id, radius, quantum) →
/// (lazily creating the
/// TargetManager). Called on the TARGET when a watcher subscribes. The
/// exact watcher host preserves retail's unique object-table identity
/// while App teardown overlaps a newer same-GUID generation.
void AddVoyeur(IPhysicsObjHost watcher, float radius, double quantum);
/// Retail CPhysicsObj::remove_voyeur(id) →
/// . Called on the TARGET when a
/// watcher unsubscribes. The expected watcher identity prevents a retiring
/// same-GUID incarnation from removing a newer incarnation's subscription
/// while App teardown callbacks converge.
void RemoveVoyeur(uint watcherId, IPhysicsObjHost expectedWatcher);
}