feat(physics): port retail complete object frame pipeline
Restore the named-retail object update order across local, remote, static, projectile, animation, shadow, teleport, and effect lifetimes. Separate authoritative root commits from spatial rebucketing, preserve per-owner hook/FIFO ordering, and remove update-path allocations with exact lifecycle and residency gates. Add deterministic conformance, adversarial lifetime, GUID-reuse, pending-cell, quaternion, timestamp, and allocation coverage. Release build is warning-free and all 6,446 tests pass with five intentional skips; retail, architecture, and adversarial reviews are clean. Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
31a0889f08
commit
f961d70023
77 changed files with 12513 additions and 1871 deletions
101
src/AcDream.Core/Physics/RetailObjectActivityGate.cs
Normal file
101
src/AcDream.Core/Physics/RetailObjectActivityGate.cs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
using System.Numerics;
|
||||
|
||||
namespace AcDream.Core.Physics;
|
||||
|
||||
/// <summary>
|
||||
/// Ports the lifecycle and 96-world-unit Active gate at the head of retail
|
||||
/// <c>CPhysicsObj::update_object</c> (0x00515D10) plus the inactive branch of
|
||||
/// <c>UpdateObjectInternal</c> (0x005156B0).
|
||||
/// </summary>
|
||||
public static class RetailObjectActivityGate
|
||||
{
|
||||
public const float MaxPhysicsDistance = 96f;
|
||||
|
||||
public static RetailObjectActivityResult Evaluate(
|
||||
RetailObjectQuantumClock clock,
|
||||
PhysicsBody? body,
|
||||
bool lifecycleEligible,
|
||||
bool hasPartArray,
|
||||
bool isStatic,
|
||||
Vector3 objectPosition,
|
||||
Vector3? playerPosition,
|
||||
double elapsedSeconds)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(clock);
|
||||
|
||||
if (!lifecycleEligible)
|
||||
{
|
||||
SetActive(clock, body, active: false);
|
||||
return RetailObjectActivityResult.Suspended;
|
||||
}
|
||||
|
||||
// Retail performs both the 96-unit decision and set_active(1) only
|
||||
// while player_object exists. During login/session transitions a
|
||||
// missing player preserves the prior Active state; it must not wake a
|
||||
// previously distant object.
|
||||
if (playerPosition is null)
|
||||
{
|
||||
if (clock.IsActive)
|
||||
return RetailObjectActivityResult.Active;
|
||||
clock.Advance(elapsedSeconds);
|
||||
return RetailObjectActivityResult.Inactive;
|
||||
}
|
||||
|
||||
bool withinActiveBubble = !hasPartArray
|
||||
|| Vector3.Distance(objectPosition, playerPosition.Value)
|
||||
<= MaxPhysicsDistance;
|
||||
if (!withinActiveBubble)
|
||||
{
|
||||
SetActive(clock, body, active: false);
|
||||
// Inactive ordinary objects still consume update_time and run
|
||||
// their particle/script tail. Those owners tick elsewhere in
|
||||
// acdream; consuming the batch here prevents later catch-up.
|
||||
clock.Advance(elapsedSeconds);
|
||||
return RetailObjectActivityResult.Inactive;
|
||||
}
|
||||
|
||||
// CPhysicsObj::set_active(1) (0x0050FC40) is a no-op for Static.
|
||||
// Static objects that were initialized or removed from visibility
|
||||
// inactive therefore stay on UpdateObjectInternal's particle/script
|
||||
// tail instead of entering root physics.
|
||||
bool reactivated = false;
|
||||
if (!isStatic)
|
||||
{
|
||||
reactivated = clock.Activate();
|
||||
if (body is not null)
|
||||
body.TransientState |= TransientStateFlags.Active;
|
||||
}
|
||||
|
||||
if (!clock.IsActive)
|
||||
{
|
||||
clock.Advance(elapsedSeconds);
|
||||
return RetailObjectActivityResult.Inactive;
|
||||
}
|
||||
|
||||
return reactivated
|
||||
? RetailObjectActivityResult.Reactivated
|
||||
: RetailObjectActivityResult.Active;
|
||||
}
|
||||
|
||||
private static void SetActive(
|
||||
RetailObjectQuantumClock clock,
|
||||
PhysicsBody? body,
|
||||
bool active)
|
||||
{
|
||||
if (active)
|
||||
clock.Activate();
|
||||
else
|
||||
clock.Deactivate();
|
||||
|
||||
if (body is not null && !active)
|
||||
body.TransientState &= ~TransientStateFlags.Active;
|
||||
}
|
||||
}
|
||||
|
||||
public enum RetailObjectActivityResult
|
||||
{
|
||||
Suspended,
|
||||
Inactive,
|
||||
Reactivated,
|
||||
Active,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue