using GTA; using RageCoop.Core; using RageCoop.Core.Scripting; using System.Collections.Concurrent; using System.ComponentModel; using System.Runtime.InteropServices; namespace RageCoop.Client.Scripting { [JsonDontSerialize] [ScriptAttributes(NoDefaultInstance = true)] public abstract class ClientScript : Script { ConcurrentQueue> _jobQueue = new(); Queue> _reAdd = new(); /// /// Fully qualified path to the module that the current script runs in. /// public static readonly string FullPath; static unsafe ClientScript() { char* buf = stackalloc char[260]; SHVDN.PInvoke.GetModuleFileNameW(SHVDN.Core.CurrentModule, buf, 260); if (Marshal.GetLastWin32Error() != 0) throw new Win32Exception("Failed to get path for current module"); FullPath = new(buf); } public ClientScript() { CurrentResource = APIBridge.GetResouceFromFilePath(FullPath); if (CurrentResource == null) throw new Exception("No resource associated with this script is found"); CurrentFile = CurrentResource.Files.Values.FirstOrDefault(x => x?.FullPath?.ToLower() == FullPath.ToLower()); if (CurrentFile == null) { Logger.Warning("No file associated with curent script was found"); } Tick += DoQueuedJobs; } protected void QueueAction(Func action) => _jobQueue.Enqueue(action); protected void QueueAction(Action action) => QueueAction(() => { action(); return true; }); private void DoQueuedJobs() { while (_reAdd.TryDequeue(out var toAdd)) _jobQueue.Enqueue(toAdd); while (_jobQueue.TryDequeue(out var job)) { if (!job()) _reAdd.Enqueue(job); } } /// /// Get the instance where this script is loaded from. /// public ClientFile CurrentFile { get; } /// /// Get the that this script belongs to. /// public ClientResource CurrentResource { get; } /// /// Eqivalent of in /// public ResourceLogger Logger => CurrentResource.Logger; } }