Triggers
Spatial enter/exit/dwell volumes over the world. Server-only.
Seams you implement 1
Crossplay calls these; your game supplies them. Each ships an inert or permissive default, so register yours before services.AddCrossplayTriggers(); and it wins.
ITriggerListener game SPI
SPI the game implements to give volumes meaning — the plug-in point of this piece. The framework does the geometry + the enter/leave/dwell bookkeeping; the rules decide what a capture point or a damage floor does. How to implement. Register your listener in DI BEFORE AddCrossplayTriggers (it is a TryAdd seam). Read Data to tell one volume's purpose from another (capture point A vs. a lava pool), and apply your effect in OnEnter / OnExit / OnDwell. All three fire on the world tick (poll thread).
public sealed class LavaFloorListener : ITriggerListener
{
private readonly IStatService _stats;
public LavaFloorListener(IStatService stats) => _stats = stats;
public void OnEnter(TriggerVolume v, WorldEntity e) { }
public void OnExit (TriggerVolume v, WorldEntity e) { }
public void OnDwell(TriggerVolume v, WorldEntity e, float dt)
=> _stats.Add(e.Id, StatId.Health, -10 * dt); // damage per second while standing in it
} -
void OnDwell(TriggerVolume volume, WorldEntity entity, float intervalSeconds)An entity is STILL inside, fired once per DwellIntervalSeconds.
-
void OnEnter(TriggerVolume volume, WorldEntity entity)An entity crossed INTO a volume this tick.
-
void OnExit(TriggerVolume volume, WorldEntity entity)An entity that was inside has LEFT (moved out, changed zone, or despawned).
Services you call 1
Crossplay implements these. Resolve them from DI and call them from your own systems.
ITriggerService
Server-side API for placing volumes.
-
long Add(string zone, IBoundsArea area, byte[] data = null)Registers a spatial volume; occupancy tracking begins on the next tick.
-
IReadOnlyCollection<long> Occupants(long triggerId)The entity ids currently inside a volume (empty when the id is unknown).
-
bool Remove(long triggerId)Removes a volume (fires OnExit for anyone inside).
Configuration 1
Every tunable lives in an options object — there are no magic numbers to hunt for.
TriggerOptions
Configurable trigger parameters (defaults here; never inlined in logic).
-
float DwellIntervalSeconds { get; set; }Seconds between dwell callbacks while an entity stays inside a volume (0 = no dwell).