nightward/Assets/GUPS/AntiCheat/Source/Monitor/AMonitor.cs

313 lines
9.3 KiB
C#

// System
using System;
using System.Collections.Generic;
// Unity
using UnityEngine;
// GUPS - AntiCheat - Core
using GUPS.AntiCheat.Core.Monitor;
using GUPS.AntiCheat.Core.Watch;
namespace GUPS.AntiCheat.Monitor
{
/// <summary>
/// An abstract base class that defines the common functionality for monitors in a Unity environment.
/// Implements the <see cref="IMonitor"/> and <see cref="IWatchAble{IWatchedSubject}"/> interfaces.
/// </summary>
/// <remarks>
/// <para>
/// The <see cref="AMonitor"/> class serves as an abstract base for implementing monitors in Unity applications.
/// It provides methods to control the lifecycle of a monitoring process and supports the observer pattern
/// through the <see cref="IWatchAble{IWatchedSubject}"/> interface. Monitors can be started, paused, resumed, and stopped,
/// and they notify subscribed observers of relevant events during their lifecycle.
/// </para>
/// </remarks>
public abstract class AMonitor : MonoBehaviour, IMonitor, IWatchAble<IWatchedSubject>
{
// Name
#region Name
/// <summary>
/// The name of the monitor.
/// </summary>
public abstract String Name { get; }
#endregion
// Lifecycle
#region Lifecycle
/// <summary>
/// A value indicating whether the monitor is active and should be running (Default: true).
/// </summary>
[SerializeField]
[Header("General - Settings")]
[Tooltip("A value indicating whether the monitor is active and should be running (Default: true).")]
private bool isActive = true;
/// <summary>
/// A value indicating whether the monitor is active and should be running.
/// </summary>
public bool IsActive => this.isActive;
/// <summary>
/// Gets a value indicating whether the monitor has been started and is currently running.
/// </summary>
public bool IsStarted { get; private set; }
/// <summary>
/// Gets a value indicating whether the monitor has been paused and is currently suspended.
/// </summary>
public bool IsPaused { get; private set; }
/// <summary>
/// Initiates the monitoring process, enabling the monitor to start collecting and processing data.
/// </summary>
public void Start()
{
// Check if the monitor is already started, if so return.
if (this.IsStarted)
{
return;
}
// Set the monitor as started.
this.IsStarted = true;
// Notify.
this.OnStart();
}
/// <summary>
/// Executed when the monitor is started. Override this method to provide custom start behavior.
/// </summary>
protected virtual void OnStart()
{
}
/// <summary>
/// Pauses the monitoring process, temporarily suspending data collection and processing without terminating the monitor.
/// </summary>
public void Pause()
{
// Check if the monitor is paused, if so return.
if (this.IsPaused)
{
return;
}
// Check if the monitor not started, if so return.
if (!this.IsStarted)
{
return;
}
// Set the monitor as paused.
this.IsPaused = true;
// Notify.
this.OnPause();
}
/// <summary>
/// Executed when the monitor is paused. Override this method to provide custom pause behavior.
/// </summary>
protected virtual void OnPause()
{
}
/// <summary>
/// Resumes the monitoring process after a pause, allowing the monitor to continue collecting and processing data.
/// </summary>
public void Resume()
{
// Check if the monitor is not paused, if so return.
if (!this.IsPaused)
{
return;
}
// Check if the monitor not started, if so return.
if (!this.IsStarted)
{
return;
}
// Set the monitor as not paused.
this.IsPaused = false;
// Notify.
this.OnResume();
}
/// <summary>
/// Executed when the monitor is resumed after a pause. Override this method to provide custom resume behavior.
/// </summary>
protected virtual void OnResume()
{
}
/// <summary>
/// Stops and terminates the monitoring process, concluding data collection and finalizing any necessary cleanup operations.
/// </summary>
public void Stop()
{
// Check if the monitor is not started, if so return.
if (!this.IsStarted)
{
return;
}
// Set the monitor as not started.
this.IsStarted = false;
// Notify.
this.OnStop();
}
/// <summary>
/// Executed when the monitor is stopped. Override this method to provide custom stop behavior.
/// </summary>
protected virtual void OnStop()
{
}
/// <summary>
/// Executed on each Unity update cycle when the monitor is started and not paused.
/// </summary>
private void Update()
{
// Check if the monitor is started and not paused.
if (!this.IsStarted || this.IsPaused)
{
return;
}
// Check if the monitor is active.
if (!this.isActive)
{
return;
}
// Notify.
this.OnUpdate();
}
/// <summary>
/// Executed on each Unity update cycle when the monitor is started and not paused.
/// Override this method to implement custom update behavior.
/// </summary>
protected virtual void OnUpdate()
{
}
/// <summary>
/// When the monitor is destroyed, stop the monitor.
/// </summary>
protected virtual void OnDestroy()
{
// Stop the monitor.
this.Stop();
}
/// <summary>
/// Notifies the observers that the monitor has completed.
/// </summary>
public void Dispose()
{
foreach (var var_Observer in this.observers)
{
if (var_Observer == null)
{
continue;
}
var_Observer.OnCompleted();
}
this.observers.Clear();
}
#endregion
// Observable
#region Observable
/// <summary>
/// The list of observers subscribed to the monitor.
/// </summary>
private List<IObserver<IWatchedSubject>> observers = new List<IObserver<IWatchedSubject>>();
/// <summary>
/// Subscribes an observer to receive notifications of the monitor.
/// </summary>
/// <param name="_Observer">The observer to subscribe.</param>
/// <returns>An <see cref="IDisposable"/> object that can be used to unsubscribe the observer.</returns>
public IDisposable Subscribe(IObserver<IWatchedSubject> _Observer)
{
if (!this.observers.Contains(_Observer))
{
this.observers.Add(_Observer);
}
return new Unsubscriber(this.observers, _Observer);
}
/// <summary>
/// Notifies all subscribed observers with the provided watched monitor subject.
/// </summary>
/// <param name="_Subject">The watched subject to notify observers about.</param>
public void Notify(IWatchedSubject _Subject)
{
foreach (var var_Observer in this.observers)
{
if (var_Observer == null)
{
continue;
}
var_Observer.OnNext(_Subject);
}
}
/// <summary>
/// Represents a disposable object used to unsubscribe an observer from the monitor.
/// </summary>
private class Unsubscriber : IDisposable
{
private List<IObserver<IWatchedSubject>> observers;
private IObserver<IWatchedSubject> observer;
/// <summary>
/// Initializes a new instance of the <see cref="Unsubscriber"/> class.
/// </summary>
/// <param name="observers">The list of observers to manage.</param>
/// <param name="observer">The observer to unsubscribe.</param>
public Unsubscriber(List<IObserver<IWatchedSubject>> observers, IObserver<IWatchedSubject> observer)
{
this.observers = observers;
this.observer = observer;
}
/// <summary>
/// Disposes of the observer, removing it from the list of observers.
/// </summary>
public void Dispose()
{
if (this.observer != null && this.observers.Contains(this.observer))
{
this.observers.Remove(this.observer);
}
}
}
#endregion
}
}