Files
Project-M/Assets/_Project/Scripts/Simulation/World/LightRelevancyMath.cs
T
kronic aeb979f8d5 LANTERN P1 step 8: light-as-territory relevancy prototype (★)
Per connection, marks every ENEMY ghost OUTSIDE the player's lamp radius
IRRELEVANT (monsters in the dark aren't replicated — the gamma test). Modelled
on the proven RegionRelevancySystem: SetIsIrrelevant so players/global ghosts
stay relevant for free. Shared-set discipline — RegionRelevancySystem is the SOLE
clearer (runs every tick); LightRelevancySystem is [UpdateAfter] it and only ADDs
light hides via TryAdd (no clear; defensive against a region+light overlap dup).
Gated on GymTag (LANTERN-only; legacy region relevancy untouched). Pure decision
in LightRelevancyMath (+3 EditMode tests, 500 green). Per-player dim/bright
(variable radius) + the L3 gamma-test verification are follow-ups; the ★adversarial
netcode review is recommended before this ships.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 08:51:24 -07:00

22 lines
1.1 KiB
C#

using Unity.Mathematics;
namespace ProjectM.Simulation
{
/// <summary>
/// Pure helpers for the LANTERN "light is territory" relevancy prototype (Build Spec Phase 1 step 8): an entity
/// outside a player's lamp radius isn't replicated to that player. The decision is a planar (XZ) distance test
/// so it's Burst-safe + unit-testable independent of the netcode <c>GhostRelevancy</c> set manipulation.
/// </summary>
public static class LightRelevancyMath
{
/// <summary>Prototype lamp radius (world units). Per-player dim/bright (a variable radius = the quiet/blind
/// trade) is the tuning follow-up; the prototype uses one fixed radius to prove the gamma test.</summary>
public const float LampRadiusDefault = 25f;
/// <summary>True when the ghost at <paramref name="ghostPos"/> is OUTSIDE the lamp centred on
/// <paramref name="playerPos"/> (planar XZ distance beyond the radius) — i.e. hidden from that player.</summary>
public static bool IsHidden(float3 playerPos, float3 ghostPos, float radiusSq)
=> math.distancesq(playerPos.xz, ghostPos.xz) > radiusSq;
}
}