From b368164e278f507cc50a85bf69a923d3d82dfd75 Mon Sep 17 00:00:00 2001 From: Andrew Gilewsky Date: Sun, 20 Oct 2024 20:49:34 +0100 Subject: [PATCH] Added transient strategy overrides, to be set via IPC - also cleaned up unused IPCs --- BossMod/Autorotation/Preset.cs | 24 ++++-- BossMod/Autorotation/UIPresetEditor.cs | 52 +++++++------ BossMod/Framework/IPCProvider.cs | 104 +++++++++++-------------- 3 files changed, 93 insertions(+), 87 deletions(-) diff --git a/BossMod/Autorotation/Preset.cs b/BossMod/Autorotation/Preset.cs index 2ddb915c5..fa079c299 100644 --- a/BossMod/Autorotation/Preset.cs +++ b/BossMod/Autorotation/Preset.cs @@ -23,21 +23,30 @@ public record struct ModuleSetting(Modifier Mod, int Track, StrategyValue Value) public StrategyValue Value = Value; } + public record class ModuleSettings + { + public readonly List Settings = []; + public int NumSerialized; // entries above this are transient and are not serialized + } + public string Name = Name; - public Dictionary> Modules = []; + public Dictionary Modules = []; - public Preset MakeClone() + public Preset MakeClone(bool includeTransient) { var res = new Preset(Name); foreach (var kv in Modules) - res.Modules[kv.Key] = [.. kv.Value]; + { + var ms = res.Modules[kv.Key] = new() { NumSerialized = kv.Value.NumSerialized }; + ms.Settings.AddRange(includeTransient ? kv.Value.Settings : kv.Value.Settings.Take(kv.Value.NumSerialized)); + } return res; } public StrategyValues ActiveStrategyOverrides(Type type, Modifier mods) { var res = new StrategyValues(RotationModuleRegistry.Modules[type].Definition.Configs); - foreach (ref var s in Modules[type].AsSpan()) + foreach (ref var s in Modules[type].Settings.AsSpan()) if ((s.Mod & mods) == s.Mod) res.Values[s.Track] = s.Value; return res; @@ -74,7 +83,7 @@ public class JsonPresetConverter : JsonConverter continue; } - var m = res.Modules[mt] = []; + var m = res.Modules[mt] = new(); foreach (var js in jm.Value.EnumerateArray()) { var s = new Preset.ModuleSetting() { Value = new() }; @@ -106,7 +115,8 @@ public class JsonPresetConverter : JsonConverter if (js.TryGetProperty(nameof(StrategyValue.Comment), out var jcomment)) s.Value.Comment = jcomment.GetString() ?? ""; - m.Add(s); + m.Settings.Add(s); + ++m.NumSerialized; } } return res; @@ -121,7 +131,7 @@ public override void Write(Utf8JsonWriter writer, Preset value, JsonSerializerOp { writer.WriteStartArray(m.Key.FullName!); var md = RotationModuleRegistry.Modules[m.Key].Definition; - foreach (var s in m.Value) + foreach (ref var s in m.Value.Settings.AsSpan()[..m.Value.NumSerialized]) { writer.WriteStartObject(); writer.WriteString(nameof(Preset.ModuleSetting.Track), md.Configs[s.Track].InternalName); diff --git a/BossMod/Autorotation/UIPresetEditor.cs b/BossMod/Autorotation/UIPresetEditor.cs index bea397f4e..3786a7904 100644 --- a/BossMod/Autorotation/UIPresetEditor.cs +++ b/BossMod/Autorotation/UIPresetEditor.cs @@ -23,7 +23,7 @@ public UIPresetEditor(PresetDatabase db, int index, bool isDefaultPreset, Type? _sourcePresetDefault = isDefaultPreset; if (index >= 0) { - Preset = (isDefaultPreset ? db.DefaultPresets : db.UserPresets)[index].MakeClone(); + Preset = (isDefaultPreset ? db.DefaultPresets : db.UserPresets)[index].MakeClone(false); } else { @@ -113,11 +113,11 @@ public void DrawModulesList() { if (list) { - foreach (var m in Preset.Modules) + foreach (var m in Preset.Modules.Keys) { - if (DrawModule(m.Key, RotationModuleRegistry.Modules[m.Key].Definition, m.Key == SelectedModuleType)) + if (DrawModule(m, RotationModuleRegistry.Modules[m].Definition, m == SelectedModuleType)) { - SelectModule(m.Key); + SelectModule(m); } } } @@ -147,7 +147,7 @@ private void DrawModuleAddPopup() { if (DrawModule(m.Key, m.Value.Definition)) { - Preset.Modules[m.Key] = []; + Preset.Modules[m.Key] = new(); Modified = true; SelectModule(m.Key); } @@ -187,11 +187,12 @@ private void DrawSettingsList() { if (list) { - for (int i = 0; i < ms.Count; ++i) + for (int i = 0; i < ms.Settings.Count; ++i) { - ref var m = ref ms.Ref(i); + var persistent = i < ms.NumSerialized; + ref var m = ref ms.Settings.Ref(i); var cfg = md.Configs[m.Track]; - if (ImGui.Selectable($"[{i + 1}] {cfg.UIName} [{m.Mod}] = {cfg.Options[m.Value.Option].UIName}###setting{_settingGuids[i]}", i == _selectedSettingIndex)) + if (ImGui.Selectable($"[{i + 1}]{(persistent ? "" : " (transient)")} {cfg.UIName} [{m.Mod}] = {cfg.Options[m.Value.Option].UIName}###setting{_settingGuids[i]}", i == _selectedSettingIndex)) { _selectedSettingIndex = i; } @@ -199,11 +200,11 @@ private void DrawSettingsList() if (ImGui.IsItemActive() && !ImGui.IsItemHovered()) { var j = ImGui.GetMouseDragDelta().Y < 0 ? i - 1 : i + 1; - if (j >= 0 && j < ms.Count) + if (j >= 0 && j < ms.Settings.Count && persistent == (j < ms.NumSerialized)) { - (ms[i], ms[j]) = (ms[j], ms[i]); + (ms.Settings[i], ms.Settings[j]) = (ms.Settings[j], ms.Settings[i]); (_settingGuids[i], _settingGuids[j]) = (_settingGuids[j], _settingGuids[i]); - Modified = true; + Modified |= persistent; if (_selectedSettingIndex == i) _selectedSettingIndex = j; else if (_selectedSettingIndex == j) @@ -219,14 +220,18 @@ private void DrawSettingsList() if (UIMisc.Button("Remove##setting", width.X, (_selectedSettingIndex < 0, "Select any strategy to remove"), (!ImGui.GetIO().KeyShift, "Hold shift"))) { - ms.RemoveAt(_selectedSettingIndex); - Modified = true; + ms.Settings.RemoveAt(_selectedSettingIndex); + if (_selectedSettingIndex < ms.NumSerialized) + { + --ms.NumSerialized; + Modified = true; + } _selectedSettingIndex = -1; RebuildSettingGuids(); } } - private void DrawAddSettingPopup(List ms, RotationModuleDefinition def) + private void DrawAddSettingPopup(Preset.ModuleSettings ms, RotationModuleDefinition def) { using var popup = ImRaii.Popup("add_setting"); if (!popup) @@ -237,8 +242,8 @@ private void DrawAddSettingPopup(List ms, RotationModuleDe var cfg = def.Configs[i]; if (ImGui.Selectable(cfg.UIName)) { - _selectedSettingIndex = ms.Count; - ms.Add(new(Preset.Modifier.None, i, new() { Option = cfg.Options.Count > 1 ? 1 : 0 })); + _selectedSettingIndex = ms.NumSerialized++; + ms.Settings.Insert(_selectedSettingIndex, new(Preset.Modifier.None, i, new() { Option = cfg.Options.Count > 1 ? 1 : 0 })); Modified = true; RebuildSettingGuids(); } @@ -274,17 +279,18 @@ private void DrawModulePreview(Type moduleType) } } - private void DrawSettingDetails(Type moduleType, List ms) + private void DrawSettingDetails(Type moduleType, Preset.ModuleSettings ms) { using var d = ImRaii.Disabled(_sourcePresetDefault); var md = RotationModuleRegistry.Modules[moduleType].Definition; - ref var s = ref ms.Ref(_selectedSettingIndex); + ref var s = ref ms.Settings.Ref(_selectedSettingIndex); var cfg = md.Configs[s.Track]; ImGui.TextUnformatted($"Setting: {cfg.UIName}"); - Modified |= DrawModifier(ref s.Mod, Preset.Modifier.Shift, "Shift"); - Modified |= DrawModifier(ref s.Mod, Preset.Modifier.Ctrl, "Ctrl"); - Modified |= DrawModifier(ref s.Mod, Preset.Modifier.Alt, "Alt"); - Modified |= UIStrategyValue.DrawEditor(ref s.Value, cfg, null, null); + var persistent = _selectedSettingIndex < ms.NumSerialized; + Modified |= DrawModifier(ref s.Mod, Preset.Modifier.Shift, "Shift") && persistent; + Modified |= DrawModifier(ref s.Mod, Preset.Modifier.Ctrl, "Ctrl") && persistent; + Modified |= DrawModifier(ref s.Mod, Preset.Modifier.Alt, "Alt") && persistent; + Modified |= UIStrategyValue.DrawEditor(ref s.Value, cfg, null, null) && persistent; } private bool DrawModifier(ref Preset.Modifier mod, Preset.Modifier flag, string label) @@ -313,6 +319,6 @@ private void RebuildSettingGuids() { _settingGuids.Clear(); if (SelectedModuleType != null && Preset.Modules.TryGetValue(SelectedModuleType, out var ms)) - _settingGuids.AddRange(Enumerable.Range(0, ms.Count)); + _settingGuids.AddRange(Enumerable.Range(0, ms.Settings.Count)); } } diff --git a/BossMod/Framework/IPCProvider.cs b/BossMod/Framework/IPCProvider.cs index 877c11fb7..8f133e71f 100644 --- a/BossMod/Framework/IPCProvider.cs +++ b/BossMod/Framework/IPCProvider.cs @@ -1,6 +1,5 @@ using BossMod.AI; using BossMod.Autorotation; -using Dalamud.Game.ClientState.Objects.Types; using System.Text.Json; namespace BossMod; @@ -9,93 +8,77 @@ sealed class IPCProvider : IDisposable { private Action? _disposeActions; - private Preset? Deserialize(string p) => JsonSerializer.Deserialize(p); - private string Serialize(Preset p) => JsonSerializer.Serialize(p); - private string? SerializeN(Preset? p) => p == null ? null : JsonSerializer.Serialize(p); - private List Serialize(IEnumerable p) => p.Select(Serialize).ToList(); - public IPCProvider(RotationModuleManager autorotation, ActionManagerEx amex, MovementOverride movement, AIManager ai) { - // TODO: this really needs to be reconsidered, this exposes implementation detail - // for usecase description, see PR 330 - really AI itself should handle heal range - Register("ActiveModuleComponentBaseList", () => autorotation.Bossmods.ActiveModule?.Components.Select(c => c.GetType().BaseType?.Name).ToList() ?? default); - Register("ActiveModuleComponentList", () => autorotation.Bossmods.ActiveModule?.Components.Select(c => c.GetType().Name).ToList() ?? default); - Register("ActiveModuleHasComponent", (string name) => autorotation.Bossmods.ActiveModule?.Components.Any(c => c.GetType().Name == name || c.GetType().BaseType?.Name == name) ?? false); - - Register("HasModule", (IGameObject obj) => BossModuleRegistry.FindByOID(obj.DataId) != null); Register("HasModuleByDataId", (uint dataId) => BossModuleRegistry.FindByOID(dataId) != null); - Register("IsMoving", movement.IsMoving); - Register("ForbiddenZonesCount", () => autorotation.Hints.ForbiddenZones.Count); Register("Configuration", (IReadOnlyList args, bool save) => Service.Config.ConsoleCommand(string.Join(' ', args), save)); - //Register("InitiateCombat", () => autorotation.ClassActions?.UpdateAutoAction(CommonActions.AutoActionAIFight, float.MaxValue, true)); - //Register("SetAutorotationState", (bool state) => Service.Config.Get().Enabled = state); - Register("Presets.List", () => Serialize(autorotation.Database.Presets.VisiblePresets)); - Register("Presets.Get", (string name) => SerializeN(autorotation.Database.Presets.FindPresetByName(name))); - Register("Presets.ForClass", (byte classId) => Serialize(autorotation.Database.Presets.PresetsForClass((Class)classId))); + Register("Presets.Get", (string name) => + { + var preset = autorotation.Database.Presets.FindPresetByName(name); + return preset != null ? JsonSerializer.Serialize(preset, Serialization.BuildSerializationOptions()) : null; + }); Register("Presets.Create", (string presetSerialized, bool overwrite) => { - var p = Deserialize(presetSerialized); + var p = JsonSerializer.Deserialize(presetSerialized, Serialization.BuildSerializationOptions()); if (p == null) return false; - var index = autorotation.Database.Presets.UserPresets.FindIndex(x => x.Name == p.Name); if (index >= 0 && !overwrite) return false; - autorotation.Database.Presets.Modify(index, p); return true; }); Register("Presets.Delete", (string name) => { - var i = autorotation.Database.Presets.UserPresets.FindIndex(x => x.Name == name); - if (i >= 0) - autorotation.Database.Presets.Modify(i, null); - - return i >= 0; + var index = autorotation.Database.Presets.UserPresets.FindIndex(x => x.Name == name); + if (index < 0) + return false; + autorotation.Database.Presets.Modify(index, null); + return true; }); Register("Presets.GetActive", () => autorotation.Preset?.Name); Register("Presets.SetActive", (string name) => { var preset = autorotation.Database.Presets.FindPresetByName(name); - if (preset != null) - { - autorotation.Preset = preset; - return true; - } - - return false; + if (preset == null) + return false; + autorotation.Preset = preset; + return true; }); Register("Presets.ClearActive", () => { if (autorotation.Preset == null) return false; - autorotation.Preset = null; return true; }); Register("Presets.GetForceDisabled", () => autorotation.Preset == RotationModuleManager.ForceDisable); Register("Presets.SetForceDisabled", () => { - if (autorotation.Preset != RotationModuleManager.ForceDisable) - { - autorotation.Preset = RotationModuleManager.ForceDisable; - return true; - } - - return false; + if (autorotation.Preset == RotationModuleManager.ForceDisable) + return false; + autorotation.Preset = RotationModuleManager.ForceDisable; + return true; }); - Register("AI.SetPreset", (string name) => + Register("Presets.AddTransientStrategy", (string presetName, string moduleTypeName, string trackName, string value) => { - Service.Log($"calling deprecated method AI.SetPreset - use Presets.SetActive instead"); - autorotation.Preset = autorotation.Database.Presets.FindPresetByName(name); - }); - Register("AI.GetPreset", () => - { - Service.Log($"calling deprecated method AI.GetPreset - use Presets.GetActive instead"); - return autorotation.Preset?.Name ?? string.Empty; + var mt = Type.GetType(moduleTypeName); + if (mt == null || !RotationModuleRegistry.Modules.TryGetValue(mt, out var md)) + return false; + var iTrack = md.Definition.Configs.FindIndex(td => td.InternalName == trackName); + if (iTrack < 0) + return false; + var iOpt = md.Definition.Configs[iTrack].Options.FindIndex(od => od.InternalName == value); + if (iOpt < 0) + return false; + var preset = autorotation.Database.Presets.FindPresetByName(presetName); + if (preset == null || !preset.Modules.TryGetValue(mt, out var ms)) + return false; + ms.Settings.Add(new(default, iTrack, new() { Option = iOpt })); + return true; }); } @@ -122,6 +105,13 @@ private void Register(string name, Func func) _disposeActions += p.UnregisterFunc; } + private void Register(string name, Func func) + { + var p = Service.PluginInterface.GetIpcProvider("BossMod." + name); + p.RegisterFunc(func); + _disposeActions += p.UnregisterFunc; + } + //private void Register(string name, Action func) //{ // var p = Service.PluginInterface.GetIpcProvider("BossMod." + name); @@ -129,10 +119,10 @@ private void Register(string name, Func func) // _disposeActions += p.UnregisterAction; //} - private void Register(string name, Action func) - { - var p = Service.PluginInterface.GetIpcProvider("BossMod." + name); - p.RegisterAction(func); - _disposeActions += p.UnregisterAction; - } + //private void Register(string name, Action func) + //{ + // var p = Service.PluginInterface.GetIpcProvider("BossMod." + name); + // p.RegisterAction(func); + // _disposeActions += p.UnregisterAction; + //} }