namespace Aeshnidae.Hud; /// /// /hud on|off|sync - the switch a capable client flips, and the fan-out to the /// mods that own panels. /// /// The client says "/hud on" once it is in the world. This mod marks the session as /// listening and then invokes every provider command (see Feed.ProviderPrefix), each /// of which sends its own panel. The providers are found in ACE's command registry /// at call time, so a new panel is a new "hud-x" command in whichever mod owns the /// numbers, and nothing here changes. /// public static class Commands { [CommandHandler("hud", AccessLevel.Player, CommandHandlerFlag.RequiresWorld, -1, "Server-drawn panels, for clients that can show them (OpenAC with the Aelrynth HUD plugin).", "/hud on|off|sync")] public static void HandleHud(Session session, params string[] parameters) { var player = session.Player; if (player is null) return; var verb = parameters.Length > 0 ? parameters[0].ToLowerInvariant() : "status"; switch (verb) { case "on": player.SetProperty(Feed.Listening, true); // One line per login is cheap, and it is the only trace a client that // draws nothing leaves: did the server ever hear from it? ModManager.Log($"[{Mod.Name}] {player.Name} turned the HUD feed on"); Sync(session); break; case "off": player.RemoveProperty(Feed.Listening); player.SendMessage("HUD feed off."); break; case "sync": if (Feed.IsOn(player)) Sync(session); else player.SendMessage("HUD feed is off - /hud on first."); break; default: player.SendMessage($"HUD feed is {(Feed.IsOn(player) ? "on" : "off")}. " + "It only does anything in a client that can draw the panels."); break; } } /// /// Ask every provider to send its panel. One provider throwing must not stop the /// rest, so each is called on its own and logged on its own. /// private static void Sync(Session session) { var providers = CommandManager.GetCommands() .Where(c => c.Attribute.Command.StartsWith(Feed.ProviderPrefix, StringComparison.Ordinal)) .OrderBy(c => c.Attribute.Command, StringComparer.Ordinal) .ToList(); ModManager.Log($"[{Mod.Name}] sync for {session.Player?.Name}: {string.Join(", ", providers.Select(p => "/" + p.Attribute.Command))}"); foreach (var provider in providers) { try { ((CommandHandler)provider.Handler)(session, "sync"); } catch (Exception ex) { ModManager.Log($"[{Mod.Name}] provider /{provider.Attribute.Command} failed for {session.Player?.Name}: {ex}", ModManager.LogLevel.Warn); } } } }