using QSB.Messaging; using QSB.Player; using QSB.TriggerSync.Messages; using QSB.WorldSync; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace QSB.TriggerSync.WorldObjects { public interface IQSBTrigger : IWorldObject { List Occupants { get; } void Enter(PlayerInfo player); void Exit(PlayerInfo player); } public abstract class QSBTrigger : WorldObject, IQSBTrigger { public TO TriggerOwner { get; init; } public List Occupants { get; } = new(); protected virtual string CompareTag => "PlayerDetector"; public override void Init() { AttachedObject.OnEntry += OnEnterEvent; AttachedObject.OnExit += OnExitEvent; QSBPlayerManager.OnRemovePlayer += OnPlayerLeave; QSBCore.UnityEvents.RunWhen(() => WorldObjectManager.AllObjectsReady, () => { if (AttachedObject._trackedObjects != null && AttachedObject._trackedObjects.Any(x => x.CompareTag(CompareTag))) { ((IQSBTrigger)this).SendMessage(new TriggerMessage(true)); } }); } public override void OnRemoval() { AttachedObject.OnEntry -= OnEnterEvent; AttachedObject.OnExit -= OnExitEvent; QSBPlayerManager.OnRemovePlayer -= OnPlayerLeave; } protected void OnEnterEvent(GameObject hitObj) { if (hitObj.CompareTag(CompareTag)) { ((IQSBTrigger)this).SendMessage(new TriggerMessage(true)); } } protected void OnExitEvent(GameObject hitObj) { if (hitObj.CompareTag(CompareTag)) { ((IQSBTrigger)this).SendMessage(new TriggerMessage(false)); } } private void OnPlayerLeave(PlayerInfo player) { if (Occupants.Contains(player)) { Exit(player); } } public void Enter(PlayerInfo player) { if (!Occupants.SafeAdd(player)) { return; } OnEnter(player); } public void Exit(PlayerInfo player) { if (!Occupants.QuickRemove(player)) { return; } OnExit(player); } /// /// called when a player enters this trigger /// protected virtual void OnEnter(PlayerInfo player) { } /// /// called when a player exits this trigger or leaves the game /// protected virtual void OnExit(PlayerInfo player) { } } }