From 7e2d0f11b3691a52f318408087790382d921ecb6 Mon Sep 17 00:00:00 2001 From: Lilith Song Date: Wed, 31 Jan 2024 19:20:10 -0500 Subject: [PATCH] New subcommands to check scripts and clear action queues In the event that a script is in an infinite queue loop (queueing a function that queues itself), you can now forcibly clear the action queue for a single script (by informal slug) or for ALL scripts. --- WoLua/Lua/ScriptContainer.cs | 16 ++++++++ WoLua/Plugin.cs | 71 ++++++++++++++++++++++++++++++------ 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/WoLua/Lua/ScriptContainer.cs b/WoLua/Lua/ScriptContainer.cs index b291834..7d605eb 100644 --- a/WoLua/Lua/ScriptContainer.cs +++ b/WoLua/Lua/ScriptContainer.cs @@ -176,6 +176,22 @@ public ScriptContainer(string file, string name, string slug) { public ScriptContainer(string file) : this(file, new DirectoryInfo(Path.GetDirectoryName(file)!).Name) { } public ScriptContainer(string file, string name) : this(file, name, NameToSlug(name)) { } + internal bool ReportError() { + if (!this.LoadSuccess) { + Service.Plugin.Error($"\"{this.PrettyName}\" ({this.InternalName}) failed to load due to an error."); + return true; + } + if (!this.Ready) { + Service.Plugin.Error($"\"{this.PrettyName}\" ({this.InternalName}) did not register a callback function."); + return true; + } + if (this.ErrorOnCall) { + Service.Plugin.Error($"\"{this.PrettyName}\" ({this.InternalName}) encountered an error during a previous call and has been disabled."); + return true; + } + return false; + } + public bool SetCallback(DynValue func) { if (this.Disposed) return false; diff --git a/WoLua/Plugin.cs b/WoLua/Plugin.cs index 01a097a..7e36b88 100644 --- a/WoLua/Plugin.cs +++ b/WoLua/Plugin.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using System.Xml.Linq; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling.Payloads; @@ -133,7 +134,7 @@ public void OnCommand(string command, string argline) { case "invoke": case "run": if (args.Length < 2) { - this.Error("Invalid usage. You must pass a command name, optionally followed by any parameters."); + this.Error("Invalid usage. You must pass a script name, optionally followed by any parameters."); } else { string name = args[1]; @@ -147,6 +148,46 @@ public void OnCommand(string command, string argline) { this.Invoke(name, parameters); } break; + case "info": + if (args.Length < 2) { + this.Error("Invalid usage. You must pass a script name."); + } + else if (this.FindScriptByInformalSlug(args[1], out ScriptContainer? script) && !script.ReportError()) { + this.Print($"\"{script.PrettyName}\" ({script.InternalName}) has {script.ActionQueue.Count} queued action{(script.ActionQueue.Count == 1 ? "" : "s")}"); + } + else { + this.Error($"No script could be found with the informal identifier {args[1]}."); + } + break; + case "halt": + case "stop": + case "clear": + if (args.Length < 2) { + this.Error("Invalid usage. You must pass a script name."); + } + else if (this.FindScriptByInformalSlug(args[1], out ScriptContainer? script) && !script.ReportError()) { + int had = script.ActionQueue.Count; + script.ActionQueue.Clear(); + this.Print($"Cleared {had} action{(had == 1 ? "" : "s")} from {script.PrettyName}'s queue."); + } + else { + this.Error($"No script could be found with the informal identifier {args[1]}."); + } + break; + case "halt-all": + case "stop-all": + case "clear-all": + case "haltall": + case "stopall": + case "clearall": + foreach (ScriptContainer script in Service.Scripts.Values) { + if (!script.ReportError()) { + int had = script.ActionQueue.Count; + script.ActionQueue.Clear(); + this.Print($"Cleared {had} action{(had == 1 ? "" : "s")} from {script.PrettyName}'s queue."); + } + } + break; case "commands": case "list": case "ls": // bit of an easter egg for programmers, I guess @@ -230,23 +271,31 @@ public void OnCommand(string command, string argline) { } } - public void Invoke(string name, string parameters) { + internal bool FindScriptByInformalSlug(string identifier, [NotNullWhen(true)] out ScriptContainer? script) { + script = null; if (this.disposed) - return; + return false; string[] tries = new string[] { - name, - name.ToLower(), - name.ToUpper(), - name.ToLowerInvariant(), - name.ToUpperInvariant(), + identifier, + identifier.ToLower(), + identifier.ToUpper(), + identifier.ToLowerInvariant(), + identifier.ToUpperInvariant(), }; - ScriptContainer? cmd = null; foreach (string attempt in tries) { - if (Service.Scripts.TryGetValue(attempt, out cmd)) + if (Service.Scripts.TryGetValue(attempt, out script)) break; } - if (cmd is not null) { + + return script is not null; + } + + public void Invoke(string name, string parameters) { + if (this.disposed) + return; + + if (this.FindScriptByInformalSlug(name, out ScriptContainer? cmd)) { cmd.Invoke(parameters); } else {