// System using System; using System.Collections.Generic; // Unity using UnityEngine; // GUPS - AntiCheat - Core using GUPS.AntiCheat.Core.Detector; using GUPS.AntiCheat.Core.Watch; namespace GUPS.AntiCheat.Detector { /// /// Abstract base class for detectors that can watch for possible cheating and notify observers about detected threats. /// /// /// /// /// The class acts as bsae class for detectors to identify potential cheating activities. /// Inherite from this class to watch for suspicious behavior and notify observers through the observer pattern when threats are detected. /// /// /// /// The interface extends once interface, providing additional functionality and specifications: /// - : Allows the detector to observe and notify observers about possible detected threats. /// /// public abstract class ADetector : MonoBehaviour, IDetector { // Name #region Name /// /// The name of the detector. /// public abstract String Name { get; } #endregion // Platform #region Platform /// /// Gets whether the detector is supported on the current platform. /// public abstract bool IsSupported { get; } /// /// Gets or sets whether the detector is active and watching for possible cheating (Default: true). /// [SerializeField] [Header("General - Settings")] [Tooltip("Gets or sets whether the detector is active and watching for possible cheating (Default: true).")] private bool isActive = true; /// /// Gets or sets whether the detector is active and watching for possible cheating (Default: true). /// public bool IsActive { get => this.isActive; set => this.isActive = value; } #endregion // Threat Rating #region Threat Rating /// /// Gets the threat rating of the detector, indicating the assessed level of potential threat. /// /// /// A higher values denote greater perceived threats. /// public abstract uint ThreatRating { get; protected set; } /// /// Get whether the detector has detected a possible cheating activity. /// public abstract bool PossibleCheatingDetected { get; protected set; } #endregion // Observable #region Observable /// /// The list of observers subscribed to the monitor. /// private List> observers = new List>(); /// /// Subscribes an observer to receive notifications of the monitor. /// /// The observer to subscribe. /// An object that can be used to unsubscribe the observer. public IDisposable Subscribe(IObserver _Observer) { if (!this.observers.Contains(_Observer)) { this.observers.Add(_Observer); } return new Unsubscriber(this.observers, _Observer); } /// /// Notifies the observers of the monitor of the detected status and possible cheating. /// /// public void Notify(IDetectorStatus _Subject) { foreach (var var_Observer in this.observers) { if (var_Observer == null) { continue; } var_Observer.OnNext(_Subject); } } /// /// Represents a disposable object used to unsubscribe an observer from the monitor. /// private class Unsubscriber : IDisposable { private List> observers; private IObserver observer; /// /// Initializes a new instance of the class. /// /// The list of observers to manage. /// The observer to unsubscribe. public Unsubscriber(List> observers, IObserver observer) { this.observers = observers; this.observer = observer; } /// /// Disposes of the observer, removing it from the list of observers. /// public void Dispose() { if (this.observer != null && this.observers.Contains(this.observer)) { this.observers.Remove(this.observer); } } } /// /// Notifies the observers that the monitor has completed. /// public void Dispose() { foreach (var var_Observer in this.observers) { if (var_Observer == null) { continue; } var_Observer.OnCompleted(); } this.observers.Clear(); } #endregion // Observer #region Observer /// /// Called when the observed monitor has completed. /// public abstract void OnCompleted(); /// /// Called when an error occurs in the observed monitor. /// /// The error that occurred. public abstract void OnError(Exception _Error); /// /// Called when the observed monitor has a new status. /// /// The new status of the monitor. public abstract void OnNext(IWatchedSubject _Subject); #endregion // Lifecycle #region Lifecycle /// /// On awake, check if the detector is supported and disable it if it is not. /// protected virtual void Awake() { // If the detector is not supported, disable it. if (!this.IsSupported) { // Disable the detector. this.isActive = false; this.enabled = false; } } #endregion } }