using System.Threading; using System.Threading.Tasks; using Dalamud.Interface.Internal.Windows.Data.Widgets; namespace Dalamud.Plugin.Services; /// /// This class represents the Framework of the native game client and grants access to various subsystems. /// /// /// Choosing between RunOnFrameworkThread and Run /// /// The game is likely to completely lock up if you call above synchronous function and getter, because starting /// a new task by default runs on , which would make the task run on the framework /// thread if invoked via Run. This includes Task.Factory.StartNew and /// Task.ContinueWith. Use Task.Run if you need to start a new task from the callback specified to /// Run, as it will force your task to be run in the default thread pool. /// See to see the difference in behaviors, and how would a misuse of these /// functions result in a deadlock. /// public interface IFramework { /// /// A delegate type used with the event. /// /// The Framework instance. public delegate void OnUpdateDelegate(IFramework framework); /// /// Event that gets fired every time the game framework updates. /// public event OnUpdateDelegate Update; /// /// Gets the last time that the Framework Update event was triggered. /// public DateTime LastUpdate { get; } /// /// Gets the last time in UTC that the Framework Update event was triggered. /// public DateTime LastUpdateUTC { get; } /// /// Gets the delta between the last Framework Update and the currently executing one. /// public TimeSpan UpdateDelta { get; } /// /// Gets a value indicating whether currently executing code is running in the game's framework update thread. /// public bool IsInFrameworkUpdateThread { get; } /// /// Gets a value indicating whether game Framework is unloading. /// public bool IsFrameworkUnloading { get; } /// Gets a that runs tasks during Framework Update event. /// The task factory. public TaskFactory GetTaskFactory(); /// /// Returns a task that completes after the given number of ticks. /// /// Number of ticks to delay. /// The cancellation token. /// A new that gets resolved after specified number of ticks happen. /// The continuation will run on the framework thread by default. public Task DelayTicks(long numTicks, CancellationToken cancellationToken = default); /// /// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call. /// /// Function to call. /// The cancellation token. /// Task representing the pending or already completed function. /// /// Starting new tasks and waiting on them synchronously from this callback will completely lock up /// the game. Use await if you need to wait on something from an async callback. /// See the remarks on if you need to choose which one to use, between /// Run and RunOnFrameworkThread. Note that RunOnTick is a fancy /// version of RunOnFrameworkThread. /// public Task Run(Action action, CancellationToken cancellationToken = default); /// /// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call. /// /// Return type. /// Function to call. /// The cancellation token. /// Task representing the pending or already completed function. /// /// Starting new tasks and waiting on them synchronously from this callback will completely lock up /// the game. Use await if you need to wait on something from an async callback. /// See the remarks on if you need to choose which one to use, between /// Run and RunOnFrameworkThread. Note that RunOnTick is a fancy /// version of RunOnFrameworkThread. /// public Task Run(Func action, CancellationToken cancellationToken = default); /// /// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call. /// /// Function to call. /// The cancellation token. /// Task representing the pending or already completed function. /// /// Starting new tasks and waiting on them synchronously from this callback will completely lock up /// the game. Use await if you need to wait on something from an async callback. /// See the remarks on if you need to choose which one to use, between /// Run and RunOnFrameworkThread. Note that RunOnTick is a fancy /// version of RunOnFrameworkThread. /// public Task Run(Func action, CancellationToken cancellationToken = default); /// /// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call. /// /// Return type. /// Function to call. /// The cancellation token. /// Task representing the pending or already completed function. /// /// Starting new tasks and waiting on them synchronously from this callback will completely lock up /// the game. Use await if you need to wait on something from an async callback. /// See the remarks on if you need to choose which one to use, between /// Run and RunOnFrameworkThread. Note that RunOnTick is a fancy /// version of RunOnFrameworkThread. /// public Task Run(Func> action, CancellationToken cancellationToken = default); /// /// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call. /// /// Return type. /// Function to call. /// Task representing the pending or already completed function. /// /// await, Task.Factory.StartNew or alike will continue off the framework thread. /// Awaiting on the returned from RunOnFrameworkThread, /// Run, or RunOnTick right away inside the callback specified to this /// function has a chance of locking up the game. Do not do await framework.RunOnFrameworkThread(...); /// directly or indirectly from the delegate passed to this function. /// See the remarks on if you need to choose which one to use, between /// Run and RunOnFrameworkThread. Note that RunOnTick is a fancy /// version of RunOnFrameworkThread. /// public Task RunOnFrameworkThread(Func func); /// /// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call. /// /// Function to call. /// Task representing the pending or already completed function. /// /// await, Task.Factory.StartNew or alike will continue off the framework thread. /// Awaiting on the returned from RunOnFrameworkThread, /// Run, or RunOnTick right away inside the callback specified to this /// function has a chance of locking up the game. Do not do await framework.RunOnFrameworkThread(...); /// directly or indirectly from the delegate passed to this function. /// See the remarks on if you need to choose which one to use, between /// Run and RunOnFrameworkThread. Note that RunOnTick is a fancy /// version of RunOnFrameworkThread. /// public Task RunOnFrameworkThread(Action action); /// /// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call. /// /// Return type. /// Function to call. /// Task representing the pending or already completed function. /// /// await, Task.Factory.StartNew or alike will continue off the framework thread. /// Awaiting on the returned from RunOnFrameworkThread, /// Run, or RunOnTick right away inside the callback specified to this /// function has a chance of locking up the game. Do not do await framework.RunOnFrameworkThread(...); /// directly or indirectly from the delegate passed to this function. /// See the remarks on if you need to choose which one to use, between /// Run and RunOnFrameworkThread. Note that RunOnTick is a fancy /// version of RunOnFrameworkThread. /// [Obsolete($"Use {nameof(RunOnTick)} instead.")] public Task RunOnFrameworkThread(Func> func); /// /// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call. /// /// Function to call. /// Task representing the pending or already completed function. /// /// await, Task.Factory.StartNew or alike will continue off the framework thread. /// Awaiting on the returned from RunOnFrameworkThread, /// Run, or RunOnTick right away inside the callback specified to this /// function has a chance of locking up the game. Do not do await framework.RunOnFrameworkThread(...); /// directly or indirectly from the delegate passed to this function. /// See the remarks on if you need to choose which one to use, between /// Run and RunOnFrameworkThread. Note that RunOnTick is a fancy /// version of RunOnFrameworkThread. /// [Obsolete($"Use {nameof(RunOnTick)} instead.")] public Task RunOnFrameworkThread(Func func); /// /// Run given function in upcoming Framework.Tick call. /// /// Return type. /// Function to call. /// Wait for given timespan before calling this function. /// Count given number of Framework.Tick calls before calling this function. This takes precedence over delay parameter. /// Cancellation token which will prevent the execution of this function if wait conditions are not met. /// Task representing the pending function. /// /// await, Task.Factory.StartNew or alike will continue off the framework thread. /// Awaiting on the returned from RunOnFrameworkThread, /// Run, or RunOnTick right away inside the callback specified to this /// function has a chance of locking up the game. Do not do await framework.RunOnFrameworkThread(...); /// directly or indirectly from the delegate passed to this function. /// See the remarks on if you need to choose which one to use, between /// Run and RunOnFrameworkThread. Note that RunOnTick is a fancy /// version of RunOnFrameworkThread. /// public Task RunOnTick(Func func, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default); /// /// Run given function in upcoming Framework.Tick call. /// /// Function to call. /// Wait for given timespan before calling this function. /// Count given number of Framework.Tick calls before calling this function. This takes precedence over delay parameter. /// Cancellation token which will prevent the execution of this function if wait conditions are not met. /// Task representing the pending function. /// /// await, Task.Factory.StartNew or alike will continue off the framework thread. /// Awaiting on the returned from RunOnFrameworkThread, /// Run, or RunOnTick right away inside the callback specified to this /// function has a chance of locking up the game. Do not do await framework.RunOnFrameworkThread(...); /// directly or indirectly from the delegate passed to this function. /// See the remarks on if you need to choose which one to use, between /// Run and RunOnFrameworkThread. Note that RunOnTick is a fancy /// version of RunOnFrameworkThread. /// public Task RunOnTick(Action action, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default); /// /// Run given function in upcoming Framework.Tick call. /// /// Return type. /// Function to call. /// Wait for given timespan before calling this function. /// Count given number of Framework.Tick calls before calling this function. This takes precedence over delay parameter. /// Cancellation token which will prevent the execution of this function if wait conditions are not met. /// Task representing the pending function. /// /// await, Task.Factory.StartNew or alike will continue off the framework thread. /// Awaiting on the returned from RunOnFrameworkThread, /// Run, or RunOnTick right away inside the callback specified to this /// function has a chance of locking up the game. Do not do await framework.RunOnFrameworkThread(...); /// directly or indirectly from the delegate passed to this function. /// See the remarks on if you need to choose which one to use, between /// Run and RunOnFrameworkThread. Note that RunOnTick is a fancy /// version of RunOnFrameworkThread. /// public Task RunOnTick(Func> func, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default); /// /// Run given function in upcoming Framework.Tick call. /// /// Function to call. /// Wait for given timespan before calling this function. /// Count given number of Framework.Tick calls before calling this function. This takes precedence over delay parameter. /// Cancellation token which will prevent the execution of this function if wait conditions are not met. /// Task representing the pending function. /// /// await, Task.Factory.StartNew or alike will continue off the framework thread. /// Awaiting on the returned from RunOnFrameworkThread, /// Run, or RunOnTick right away inside the callback specified to this /// function has a chance of locking up the game. Do not do await framework.RunOnFrameworkThread(...); /// directly or indirectly from the delegate passed to this function. /// See the remarks on if you need to choose which one to use, between /// Run and RunOnFrameworkThread. Note that RunOnTick is a fancy /// version of RunOnFrameworkThread. /// public Task RunOnTick(Func func, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default); }