// https://github.com/XtraCube/Reactor/blob/main/Reactor/Utilities/StateMachineWrapper.cs using System; using System.Reflection; using HarmonyLib; #pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. namespace EHR.Modules; /// /// A wrapper for state machine objects to access their parent instance and state. /// /// The type of the parent class that owns the state machine. public class StateMachineWrapper : CompilerGeneratedObjectWrapper { #if IL2CPP // normally it is fields, but IL2CPP turns them into properties private readonly PropertyInfo _thisProperty; private readonly PropertyInfo _stateProperty; #else private readonly FieldInfo _stateField; private readonly FieldInfo _thisField; #endif private T? _parentInstance; /// /// Gets the instance of the parent class that owns the state machine. /// #if IL2CPP public T Instance => _parentInstance ??= (T) (_thisProperty.GetValue(GeneratedObject)!); #else public T Instance => _parentInstance ??= (T) (_thisField.GetValue(GeneratedObject)!); #endif /// /// Gets or sets the current state of the state machine. /// /// The current state as an integer. public int State { #if IL2CPP get => (int) _stateProperty.GetValue(GeneratedObject)!; set => _stateProperty.SetValue(GeneratedObject, value); #else get => (int) _stateField.GetValue(GeneratedObject)!; set => _stateField.SetValue(GeneratedObject, value); #endif } /// /// Initializes a new instance of the class. /// /// The state machine instance to wrap. public StateMachineWrapper(object stateMachine) : base(stateMachine) { #if IL2CPP _thisProperty = AccessTools.Property(GeneratedType, "__4__this"); _stateProperty = AccessTools.Property(GeneratedType, "__1__state"); #else _thisField = AccessTools.Field(GeneratedType, "<>4__this"); _stateField = AccessTools.Field(GeneratedType, "<>1__state"); #endif } /// /// Gets a parameter from the state machine by its name. /// /// The name of the parameter to retrieve. /// The type of the parameter to retrieve. /// >The value of the specified parameter. /// Thrown if the specified parameter does not exist. public TField GetParameter(string parameterName) { return GetField(parameterName); } /// /// Sets a parameter in the state machine by its name. /// /// The name of the parameter to set. /// The value to set for the parameter. /// The type of the parameter to set. /// Thrown if the specified parameter does not exist. public void SetParameter(string parameterName, TField value) { SetField(parameterName, value); } }