forked from aly/qstbak
738 lines
26 KiB
C#
738 lines
26 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Text;
|
|
using Dalamud.Bindings.ImGui;
|
|
using Dalamud.Interface;
|
|
using Dalamud.Interface.Utility.Raii;
|
|
using Dalamud.Plugin;
|
|
using Dalamud.Plugin.Services;
|
|
using Dalamud.Utility;
|
|
using LLib;
|
|
using Questionable.Controller;
|
|
using Questionable.External;
|
|
|
|
namespace Questionable.Windows.ConfigComponents;
|
|
|
|
internal sealed class PluginConfigComponent : ConfigComponent
|
|
{
|
|
private sealed record PluginProvider(string DisplayName, string InternalName, Uri WebsiteUri, Uri? DalamudRepositoryUri, IReadOnlyList<Uri>? DalamudRepositoryAliases = null)
|
|
{
|
|
public IReadOnlyList<string> AliasUrls
|
|
{
|
|
get
|
|
{
|
|
IReadOnlyList<string>? readOnlyList = _aliasUrls;
|
|
if (readOnlyList == null)
|
|
{
|
|
IReadOnlyList<string> readOnlyList2 = DalamudRepositoryAliases?.Select((Uri u) => u.ToString()).ToList();
|
|
readOnlyList = (_aliasUrls = readOnlyList2 ?? Array.Empty<string>());
|
|
}
|
|
return readOnlyList;
|
|
}
|
|
}
|
|
|
|
private IReadOnlyList<string>? _aliasUrls;
|
|
|
|
[CompilerGenerated]
|
|
private bool PrintMembers(StringBuilder builder)
|
|
{
|
|
RuntimeHelpers.EnsureSufficientExecutionStack();
|
|
builder.Append("DisplayName = ");
|
|
builder.Append((object?)DisplayName);
|
|
builder.Append(", InternalName = ");
|
|
builder.Append((object?)InternalName);
|
|
builder.Append(", WebsiteUri = ");
|
|
builder.Append(WebsiteUri);
|
|
builder.Append(", DalamudRepositoryUri = ");
|
|
builder.Append(DalamudRepositoryUri);
|
|
builder.Append(", DalamudRepositoryAliases = ");
|
|
builder.Append(DalamudRepositoryAliases);
|
|
builder.Append(", AliasUrls = ");
|
|
builder.Append(AliasUrls);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
private sealed record PluginRequirement(string GroupName, string Description, IReadOnlyList<PluginProvider> Providers, string? ConfigCommand = null, List<PluginDetailInfo>? DetailsToCheck = null, (string Label, Uri Uri)? ExtraLink = null);
|
|
|
|
private sealed record PluginDetailInfo(string DisplayName, string Details, Func<bool> Predicate);
|
|
|
|
private const string WigglyNavInternalName = "WigglyNav";
|
|
|
|
private static readonly IReadOnlyList<PluginRequirement> RequiredPlugins = new global::_003C_003Ez__ReadOnlySingleElementList<PluginRequirement>(new PluginRequirement("Quest Progression", "Automatically accepts and turns in quests, skips cutscenes and dialogue.", new global::_003C_003Ez__ReadOnlySingleElementList<PluginProvider>(new PluginProvider("TextAdvance", "TextAdvance", new Uri("https://github.com/NightmareXIV/TextAdvance"), new Uri("https://github.com/NightmareXIV/MyDalamudPlugins/raw/main/pluginmaster.json"), new global::_003C_003Ez__ReadOnlyArray<Uri>(new Uri[3]
|
|
{
|
|
new Uri("https://raw.githubusercontent.com/NightmareXIV/MyDalamudPlugins/main/pluginmaster.json"),
|
|
new Uri("https://github.com/NightmareXIV/MyDalamudPlugins/raw/refs/heads/main/pluginmaster.json"),
|
|
new Uri("https://raw.githubusercontent.com/NightmareXIV/MyDalamudPlugins/refs/heads/main/pluginmaster.json")
|
|
})))));
|
|
|
|
private static readonly ReadOnlyDictionary<Configuration.ENavigationProvider, PluginRequirement> NavigationPlugins = new Dictionary<Configuration.ENavigationProvider, PluginRequirement>
|
|
{
|
|
{
|
|
Questionable.Configuration.ENavigationProvider.Vnavmesh,
|
|
new PluginRequirement("vnavmesh", string.Empty, new global::_003C_003Ez__ReadOnlySingleElementList<PluginProvider>(new PluginProvider("vnavmesh", "vnavmesh", new Uri("https://github.com/awgil/ffxiv_navmesh/"), new Uri("https://puni.sh/api/repository/veyn"))))
|
|
},
|
|
{
|
|
Questionable.Configuration.ENavigationProvider.WigglyNav,
|
|
new PluginRequirement("WigglyNav", string.Empty, new global::_003C_003Ez__ReadOnlySingleElementList<PluginProvider>(new PluginProvider("WigglyNav", "WigglyNav", new Uri("https://github.com/WigglyMuffin/WigglyNav"), null)))
|
|
},
|
|
{
|
|
Questionable.Configuration.ENavigationProvider.WigglyNavShim,
|
|
new PluginRequirement("WigglyNav (shim)", string.Empty, new global::_003C_003Ez__ReadOnlySingleElementList<PluginProvider>(new PluginProvider("WigglyNav", "WigglyNav", new Uri("https://github.com/WigglyMuffin/WigglyNav"), null)))
|
|
}
|
|
}.AsReadOnly();
|
|
|
|
private static readonly ReadOnlyDictionary<Configuration.ECombatModule, PluginRequirement> CombatPlugins = new Dictionary<Configuration.ECombatModule, PluginRequirement>
|
|
{
|
|
{
|
|
Questionable.Configuration.ECombatModule.BossMod,
|
|
new PluginRequirement("Boss Mod", string.Empty, new global::_003C_003Ez__ReadOnlyArray<PluginProvider>(new PluginProvider[2]
|
|
{
|
|
new PluginProvider("Boss Mod", "BossMod", new Uri("https://github.com/awgil/ffxiv_bossmod"), new Uri("https://puni.sh/api/repository/veyn")),
|
|
new PluginProvider("Boss Mod Reborn", "BossModReborn", new Uri("https://github.com/FFXIV-CombatReborn/BossmodReborn"), new Uri("https://raw.githubusercontent.com/FFXIV-CombatReborn/CombatRebornRepo/main/pluginmaster.json"))
|
|
}))
|
|
},
|
|
{
|
|
Questionable.Configuration.ECombatModule.RotationSolverReborn,
|
|
new PluginRequirement("Rotation Solver Reborn", string.Empty, new global::_003C_003Ez__ReadOnlySingleElementList<PluginProvider>(new PluginProvider("Rotation Solver Reborn", "RotationSolver", new Uri("https://github.com/FFXIV-CombatReborn/RotationSolverReborn"), new Uri("https://raw.githubusercontent.com/FFXIV-CombatReborn/CombatRebornRepo/main/pluginmaster.json"))))
|
|
},
|
|
{
|
|
Questionable.Configuration.ECombatModule.WrathCombo,
|
|
new PluginRequirement("Wrath Combo", string.Empty, new global::_003C_003Ez__ReadOnlySingleElementList<PluginProvider>(new PluginProvider("Wrath Combo", "WrathCombo", new Uri("https://github.com/PunishXIV/WrathCombo"), new Uri("https://puni.sh/api/plugins"), new global::_003C_003Ez__ReadOnlySingleElementList<Uri>(new Uri("https://love.puni.sh/ment.json")))))
|
|
}
|
|
}.AsReadOnly();
|
|
|
|
private readonly IReadOnlyList<PluginRequirement> _recommendedPlugins;
|
|
|
|
private readonly Configuration _configuration;
|
|
|
|
private readonly CombatController _combatController;
|
|
|
|
private readonly IDalamudPluginInterface _pluginInterface;
|
|
|
|
private readonly UiUtils _uiUtils;
|
|
|
|
private readonly ICommandManager _commandManager;
|
|
|
|
private readonly PluginInstaller _installer;
|
|
|
|
private readonly WigglyNavAvailability _wigglyNavAvailability;
|
|
|
|
private static readonly IReadOnlyList<PluginRequirement> ConflictEligibleGroups = (from g in RequiredPlugins.Concat(CombatPlugins.Values)
|
|
where g.Providers.Select((PluginProvider p) => p.InternalName).Distinct().Count() > 1
|
|
select g).ToList();
|
|
|
|
public PluginConfigComponent(IDalamudPluginInterface pluginInterface, Configuration configuration, CombatController combatController, UiUtils uiUtils, ICommandManager commandManager, PluginInstaller installer, WigglyNavAvailability wigglyNavAvailability)
|
|
: base(pluginInterface, configuration)
|
|
{
|
|
_configuration = configuration;
|
|
_combatController = combatController;
|
|
_pluginInterface = pluginInterface;
|
|
_uiUtils = uiUtils;
|
|
_commandManager = commandManager;
|
|
_installer = installer;
|
|
_wigglyNavAvailability = wigglyNavAvailability;
|
|
_recommendedPlugins = new global::_003C_003Ez__ReadOnlyArray<PluginRequirement>(new PluginRequirement[3]
|
|
{
|
|
new PluginRequirement("Artisan", "Handles automatic crafting for quests that require crafted items.", new global::_003C_003Ez__ReadOnlySingleElementList<PluginProvider>(new PluginProvider("Artisan", "Artisan", new Uri("https://github.com/PunishXIV/Artisan"), new Uri("https://puni.sh/api/plugins"), new global::_003C_003Ez__ReadOnlySingleElementList<Uri>(new Uri("https://love.puni.sh/ment.json"))))),
|
|
new PluginRequirement("AutoDuty", "Automatically handles dungeon and trial completion during Main Scenario Quest progression.", new global::_003C_003Ez__ReadOnlySingleElementList<PluginProvider>(new PluginProvider("AutoDuty", "AutoDuty", new Uri("https://github.com/erdelf/AutoDuty"), new Uri("https://puni.sh/api/repository/erdelf"))), null, null, ("Duty Spreadsheet", new Uri("https://docs.google.com/spreadsheets/d/151RlpqRcCpiD_VbQn6Duf-u-S71EP7d0mx3j1PDNoNA/edit?pli=1#gid=0"))),
|
|
new PluginRequirement("AutoHook", "Handles automatic fishing for Fisher class quests.", new global::_003C_003Ez__ReadOnlySingleElementList<PluginProvider>(new PluginProvider("AutoHook", "AutoHook", new Uri("https://github.com/PunishXIV/AutoHook"), new Uri("https://puni.sh/api/plugins"), new global::_003C_003Ez__ReadOnlySingleElementList<Uri>(new Uri("https://love.puni.sh/ment.json")))))
|
|
});
|
|
}
|
|
|
|
public override void DrawTab()
|
|
{
|
|
if (UiThemeUtils.IconTextButton(FontAwesomeIcon.Hammer, "Re-run setup wizard"))
|
|
{
|
|
_commandManager.ProcessCommand("/qst setup");
|
|
}
|
|
ImGui.Spacing();
|
|
DrawSections(useCards: true, out var _);
|
|
}
|
|
|
|
public void Draw(out bool allRequiredInstalled)
|
|
{
|
|
DrawSections(useCards: false, out allRequiredInstalled);
|
|
}
|
|
|
|
private void DrawSections(bool useCards, out bool allRequiredInstalled)
|
|
{
|
|
float checklistPadding;
|
|
using (_pluginInterface.UiBuilder.IconFontFixedWidthHandle.Push())
|
|
{
|
|
checklistPadding = ImGui.CalcTextSize(FontAwesomeIcon.Check.ToIconString()).X + ImGui.GetStyle().ItemSpacing.X;
|
|
}
|
|
allRequiredInstalled = true;
|
|
Header("Required");
|
|
Vector2 contentStartPos;
|
|
float availableWidth;
|
|
ImDrawListPtr drawList;
|
|
if (useCards)
|
|
{
|
|
(contentStartPos, availableWidth, drawList) = UiThemeUtils.BeginCard();
|
|
}
|
|
else
|
|
{
|
|
contentStartPos = default(Vector2);
|
|
availableWidth = 0f;
|
|
drawList = default(ImDrawListPtr);
|
|
}
|
|
foreach (PluginRequirement requiredPlugin in RequiredPlugins)
|
|
{
|
|
allRequiredInstalled &= DrawRequirement(requiredPlugin, checklistPadding);
|
|
}
|
|
allRequiredInstalled &= DrawNavigationSelection(checklistPadding);
|
|
if (useCards)
|
|
{
|
|
UiThemeUtils.EndCard(contentStartPos, availableWidth, drawList);
|
|
}
|
|
Between();
|
|
Header("Combat Plugin");
|
|
Vector2 contentStartPos2;
|
|
float availableWidth2;
|
|
ImDrawListPtr drawList2;
|
|
if (useCards)
|
|
{
|
|
(contentStartPos2, availableWidth2, drawList2) = UiThemeUtils.BeginCard();
|
|
}
|
|
else
|
|
{
|
|
contentStartPos2 = default(Vector2);
|
|
availableWidth2 = 0f;
|
|
drawList2 = default(ImDrawListPtr);
|
|
}
|
|
using (ImRaii.Disabled(_combatController.IsRunning))
|
|
{
|
|
if (ImGui.RadioButton("No rotation/combat plugin (combat must be done manually)", _configuration.General.CombatModule == Questionable.Configuration.ECombatModule.None))
|
|
{
|
|
_configuration.General.CombatModule = Questionable.Configuration.ECombatModule.None;
|
|
_pluginInterface.SavePluginConfig(_configuration);
|
|
}
|
|
allRequiredInstalled &= DrawCombatPlugin(Questionable.Configuration.ECombatModule.BossMod, checklistPadding);
|
|
allRequiredInstalled &= DrawCombatPlugin(Questionable.Configuration.ECombatModule.RotationSolverReborn, checklistPadding);
|
|
allRequiredInstalled &= DrawCombatPlugin(Questionable.Configuration.ECombatModule.WrathCombo, checklistPadding);
|
|
}
|
|
if (useCards)
|
|
{
|
|
UiThemeUtils.EndCard(contentStartPos2, availableWidth2, drawList2);
|
|
}
|
|
Between();
|
|
Header("Recommended");
|
|
Vector2 contentStartPos3;
|
|
float availableWidth3;
|
|
ImDrawListPtr drawList3;
|
|
if (useCards)
|
|
{
|
|
(contentStartPos3, availableWidth3, drawList3) = UiThemeUtils.BeginCard();
|
|
}
|
|
else
|
|
{
|
|
contentStartPos3 = default(Vector2);
|
|
availableWidth3 = 0f;
|
|
drawList3 = default(ImDrawListPtr);
|
|
}
|
|
foreach (PluginRequirement recommendedPlugin in _recommendedPlugins)
|
|
{
|
|
DrawRequirement(recommendedPlugin, checklistPadding);
|
|
}
|
|
if (useCards)
|
|
{
|
|
UiThemeUtils.EndCard(contentStartPos3, availableWidth3, drawList3);
|
|
}
|
|
if (useCards)
|
|
{
|
|
UiThemeUtils.SectionSpacing();
|
|
}
|
|
if (allRequiredInstalled)
|
|
{
|
|
Status("All required plugins installed", UiThemeUtils.StatusComplete, FontAwesomeIcon.CheckCircle);
|
|
}
|
|
else
|
|
{
|
|
Status("Required plugins missing", UiThemeUtils.StatusLocked, FontAwesomeIcon.ExclamationTriangle);
|
|
}
|
|
foreach (string item in DetectIpcConflicts())
|
|
{
|
|
Status(item, UiThemeUtils.StatusActive, FontAwesomeIcon.ExclamationTriangle);
|
|
}
|
|
void Between()
|
|
{
|
|
if (useCards)
|
|
{
|
|
UiThemeUtils.SectionSpacing();
|
|
}
|
|
else
|
|
{
|
|
ImGui.Spacing();
|
|
ImGui.Separator();
|
|
ImGui.Spacing();
|
|
}
|
|
}
|
|
void Header(string title)
|
|
{
|
|
if (useCards)
|
|
{
|
|
UiThemeUtils.SectionHeader(title);
|
|
}
|
|
else
|
|
{
|
|
ImGui.TextDisabled(title);
|
|
ImGui.Spacing();
|
|
}
|
|
}
|
|
void Status(string text, Vector4 color, FontAwesomeIcon icon)
|
|
{
|
|
if (useCards)
|
|
{
|
|
UiThemeUtils.StatusBanner(text, color, icon);
|
|
}
|
|
else
|
|
{
|
|
ImGui.Spacing();
|
|
UiThemeUtils.StatusBadge(text, color, icon);
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool IsWigglyNavInstalled()
|
|
{
|
|
return _pluginInterface.InstalledPlugins.Any((IExposedPlugin x) => x.InternalName == "WigglyNav");
|
|
}
|
|
|
|
private IExposedPlugin? FindProvider(PluginProvider provider)
|
|
{
|
|
return _pluginInterface.InstalledPlugins.FirstOrDefault((IExposedPlugin x) => x.InternalName == provider.InternalName);
|
|
}
|
|
|
|
private List<string> DetectIpcConflicts()
|
|
{
|
|
List<string> list = new List<string>();
|
|
foreach (PluginRequirement conflictEligibleGroup in ConflictEligibleGroups)
|
|
{
|
|
List<string> list2 = (from p in conflictEligibleGroup.Providers
|
|
where FindProvider(p)?.IsLoaded ?? false
|
|
select p.DisplayName).ToList();
|
|
if (list2.Count > 1)
|
|
{
|
|
list.Add(string.Join(" and ", list2) + " are both loaded - disable one to avoid unpredictable behavior");
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
private bool DrawRequirement(PluginRequirement requirement, float checklistPadding)
|
|
{
|
|
bool flag = false;
|
|
using (ImRaii.PushId("req_" + requirement.GroupName))
|
|
{
|
|
if (requirement.Providers.Count > 1)
|
|
{
|
|
ImGui.TextUnformatted(requirement.GroupName);
|
|
using (ImRaii.PushIndent(checklistPadding))
|
|
{
|
|
if (!string.IsNullOrEmpty(requirement.Description))
|
|
{
|
|
ImGui.PushTextWrapPos(0f);
|
|
ImGui.TextColored(in UiThemeUtils.DimTextColor, requirement.Description);
|
|
ImGui.PopTextWrapPos();
|
|
}
|
|
foreach (PluginProvider provider in requirement.Providers)
|
|
{
|
|
flag |= DrawProvider(provider, checklistPadding);
|
|
}
|
|
DrawRequirementExtras(requirement, checklistPadding, flag);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PluginProvider pluginProvider = requirement.Providers[0];
|
|
IExposedPlugin exposedPlugin = FindProvider(pluginProvider);
|
|
bool flag2 = exposedPlugin?.IsLoaded ?? false;
|
|
bool isDisabled = exposedPlugin != null && !exposedPlugin.IsLoaded;
|
|
flag = flag2;
|
|
_uiUtils.ChecklistItem(pluginProvider.DisplayName, flag2);
|
|
if (exposedPlugin != null)
|
|
{
|
|
ImGui.SameLine();
|
|
ImU8String text = new ImU8String(1, 1);
|
|
text.AppendLiteral("v");
|
|
text.AppendFormatted(exposedPlugin.Version);
|
|
ImGui.TextColored(in UiThemeUtils.DimTextColor, text);
|
|
}
|
|
using (ImRaii.PushIndent(checklistPadding))
|
|
{
|
|
if (!string.IsNullOrEmpty(requirement.Description))
|
|
{
|
|
ImGui.PushTextWrapPos(0f);
|
|
ImGui.TextColored(in UiThemeUtils.DimTextColor, requirement.Description);
|
|
ImGui.PopTextWrapPos();
|
|
}
|
|
DrawRequirementExtras(requirement, checklistPadding, flag2);
|
|
DrawProviderActions(pluginProvider, exposedPlugin, flag2, isDisabled);
|
|
}
|
|
}
|
|
ImGui.Spacing();
|
|
return flag;
|
|
}
|
|
}
|
|
|
|
private bool DrawProvider(PluginProvider provider, float checklistPadding)
|
|
{
|
|
using (ImRaii.PushId("prov_" + provider.DisplayName))
|
|
{
|
|
IExposedPlugin exposedPlugin = FindProvider(provider);
|
|
bool flag = exposedPlugin?.IsLoaded ?? false;
|
|
bool isDisabled = exposedPlugin != null && !exposedPlugin.IsLoaded;
|
|
_uiUtils.ChecklistItem(provider.DisplayName, flag);
|
|
if (exposedPlugin != null)
|
|
{
|
|
ImGui.SameLine();
|
|
ImU8String text = new ImU8String(1, 1);
|
|
text.AppendLiteral("v");
|
|
text.AppendFormatted(exposedPlugin.Version);
|
|
ImGui.TextColored(in UiThemeUtils.DimTextColor, text);
|
|
}
|
|
using (ImRaii.PushIndent(checklistPadding))
|
|
{
|
|
DrawProviderActions(provider, exposedPlugin, flag, isDisabled);
|
|
}
|
|
return flag;
|
|
}
|
|
}
|
|
|
|
private bool DrawNavigationSelection(float checklistPadding)
|
|
{
|
|
using (ImRaii.PushId("req_Navigation"))
|
|
{
|
|
bool flag = true;
|
|
ImGui.TextUnformatted("Navigation");
|
|
using (ImRaii.PushIndent(checklistPadding))
|
|
{
|
|
ImGui.PushTextWrapPos(0f);
|
|
ImGui.TextColored(in UiThemeUtils.DimTextColor, "Handles navigation within a zone, moving your character to quest objectives.");
|
|
ImGui.PopTextWrapPos();
|
|
flag &= DrawNavigationProvider(Questionable.Configuration.ENavigationProvider.Vnavmesh);
|
|
Configuration.ENavigationProvider navigationProvider = _configuration.General.NavigationProvider;
|
|
if (_wigglyNavAvailability.IsCompatible || navigationProvider == Questionable.Configuration.ENavigationProvider.WigglyNav)
|
|
{
|
|
flag &= DrawNavigationProvider(Questionable.Configuration.ENavigationProvider.WigglyNav);
|
|
}
|
|
if ((_configuration.Advanced.ShowWigglyNavShimProvider && IsWigglyNavInstalled()) || navigationProvider == Questionable.Configuration.ENavigationProvider.WigglyNavShim)
|
|
{
|
|
flag &= DrawNavigationProvider(Questionable.Configuration.ENavigationProvider.WigglyNavShim);
|
|
}
|
|
}
|
|
ImGui.Spacing();
|
|
return flag;
|
|
}
|
|
}
|
|
|
|
private bool DrawNavigationProvider(Configuration.ENavigationProvider navigationProvider)
|
|
{
|
|
PluginRequirement pluginRequirement = NavigationPlugins[navigationProvider];
|
|
using (ImRaii.PushId("nav_" + pluginRequirement.GroupName))
|
|
{
|
|
if (ImGui.RadioButton(pluginRequirement.GroupName, _configuration.General.NavigationProvider == navigationProvider))
|
|
{
|
|
_configuration.General.NavigationProvider = navigationProvider;
|
|
_pluginInterface.SavePluginConfig(_configuration);
|
|
}
|
|
PluginProvider pluginProvider = pluginRequirement.Providers[0];
|
|
IExposedPlugin exposedPlugin = FindProvider(pluginProvider);
|
|
bool flag = exposedPlugin?.IsLoaded ?? false;
|
|
bool flag2 = exposedPlugin != null && !exposedPlugin.IsLoaded;
|
|
if (exposedPlugin != null)
|
|
{
|
|
ImGui.SameLine(0f);
|
|
ImGui.AlignTextToFramePadding();
|
|
ImU8String text = new ImU8String(1, 1);
|
|
text.AppendLiteral("v");
|
|
text.AppendFormatted(exposedPlugin.Version);
|
|
ImGui.TextColored(in UiThemeUtils.DimTextColor, text);
|
|
}
|
|
bool flag3 = navigationProvider == Questionable.Configuration.ENavigationProvider.WigglyNav && !_wigglyNavAvailability.IsCompatible;
|
|
DrawProviderStatusIcon(flag && !flag3, flag2 || (flag && flag3));
|
|
if (!flag && pluginProvider.DalamudRepositoryUri != null)
|
|
{
|
|
DrawInlineProviderActions(pluginProvider, flag2);
|
|
}
|
|
if (navigationProvider == Questionable.Configuration.ENavigationProvider.WigglyNav && _configuration.General.NavigationProvider == navigationProvider && !_wigglyNavAvailability.IsCompatible)
|
|
{
|
|
ImGui.SameLine();
|
|
ImGui.AlignTextToFramePadding();
|
|
ImGui.TextColored(in UiThemeUtils.DimTextColor, "(unavailable - using vnavmesh)");
|
|
}
|
|
return flag || _configuration.General.NavigationProvider != navigationProvider;
|
|
}
|
|
}
|
|
|
|
private void DrawProviderActions(PluginProvider provider, IExposedPlugin? installed, bool isLoaded, bool isDisabled)
|
|
{
|
|
if (isLoaded)
|
|
{
|
|
return;
|
|
}
|
|
if (isDisabled)
|
|
{
|
|
ImGui.TextColored(in UiThemeUtils.StatusActive, "Installed but disabled");
|
|
DrawEnableButton(provider);
|
|
DrawInstallError(provider);
|
|
return;
|
|
}
|
|
DrawInstallButton(provider);
|
|
ImGui.SameLine();
|
|
if (UiThemeUtils.IconTextButton(FontAwesomeIcon.Globe, "Website"))
|
|
{
|
|
Util.OpenLink(provider.WebsiteUri.ToString());
|
|
}
|
|
if (provider.DalamudRepositoryUri != null)
|
|
{
|
|
ImGui.SameLine();
|
|
if (UiThemeUtils.IconTextButton(FontAwesomeIcon.Code, "Repo"))
|
|
{
|
|
Util.OpenLink(provider.DalamudRepositoryUri.ToString());
|
|
}
|
|
}
|
|
DrawInstallError(provider);
|
|
}
|
|
|
|
private void DrawRequirementExtras(PluginRequirement requirement, float checklistPadding, bool isLoaded)
|
|
{
|
|
(string, Uri)? extraLink = requirement.ExtraLink;
|
|
if (extraLink.HasValue)
|
|
{
|
|
(string, Uri) valueOrDefault = extraLink.GetValueOrDefault();
|
|
if (UiThemeUtils.IconTextButton(FontAwesomeIcon.ExternalLinkAlt, valueOrDefault.Item1))
|
|
{
|
|
Util.OpenLink(valueOrDefault.Item2.ToString());
|
|
}
|
|
}
|
|
if (requirement.DetailsToCheck != null)
|
|
{
|
|
foreach (PluginDetailInfo item in requirement.DetailsToCheck)
|
|
{
|
|
bool flag = item.Predicate();
|
|
_uiUtils.ChecklistItem(item.DisplayName, isLoaded && flag);
|
|
if (!string.IsNullOrEmpty(item.Details))
|
|
{
|
|
using (ImRaii.PushIndent(checklistPadding))
|
|
{
|
|
ImGui.TextUnformatted(item.Details);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (isLoaded)
|
|
{
|
|
List<PluginDetailInfo>? detailsToCheck = requirement.DetailsToCheck;
|
|
if (detailsToCheck != null && detailsToCheck.Any((PluginDetailInfo d) => !d.Predicate()) && requirement.ConfigCommand != null && requirement.ConfigCommand.StartsWith('/') && UiThemeUtils.IconTextButton(FontAwesomeIcon.Cog, "Open configuration"))
|
|
{
|
|
_commandManager.ProcessCommand(requirement.ConfigCommand);
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool DrawCombatPlugin(Configuration.ECombatModule combatModule, float checklistPadding)
|
|
{
|
|
ImGui.Spacing();
|
|
PluginRequirement pluginRequirement = CombatPlugins[combatModule];
|
|
using (ImRaii.PushId("combat_" + pluginRequirement.GroupName))
|
|
{
|
|
bool flag = false;
|
|
bool num = pluginRequirement.Providers.Count > 1;
|
|
if (ImGui.RadioButton(pluginRequirement.GroupName, _configuration.General.CombatModule == combatModule))
|
|
{
|
|
_configuration.General.CombatModule = combatModule;
|
|
_pluginInterface.SavePluginConfig(_configuration);
|
|
}
|
|
if (!num)
|
|
{
|
|
PluginProvider provider = pluginRequirement.Providers[0];
|
|
IExposedPlugin exposedPlugin = FindProvider(provider);
|
|
bool flag2 = exposedPlugin?.IsLoaded ?? false;
|
|
bool isDisabled = exposedPlugin != null && !exposedPlugin.IsLoaded;
|
|
flag = flag2;
|
|
if (exposedPlugin != null)
|
|
{
|
|
ImGui.SameLine(0f);
|
|
ImGui.AlignTextToFramePadding();
|
|
ImU8String text = new ImU8String(1, 1);
|
|
text.AppendLiteral("v");
|
|
text.AppendFormatted(exposedPlugin.Version);
|
|
ImGui.TextColored(in UiThemeUtils.DimTextColor, text);
|
|
}
|
|
DrawProviderStatusIcon(flag2, isDisabled);
|
|
if (!flag2)
|
|
{
|
|
DrawInlineProviderActions(provider, isDisabled);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
using (ImRaii.PushIndent(checklistPadding))
|
|
{
|
|
foreach (PluginProvider provider2 in pluginRequirement.Providers)
|
|
{
|
|
using (ImRaii.PushId("prov_" + provider2.DisplayName))
|
|
{
|
|
IExposedPlugin exposedPlugin2 = FindProvider(provider2);
|
|
bool flag3 = exposedPlugin2?.IsLoaded ?? false;
|
|
bool isDisabled2 = exposedPlugin2 != null && !exposedPlugin2.IsLoaded;
|
|
if (flag3)
|
|
{
|
|
flag = true;
|
|
}
|
|
_uiUtils.ChecklistItem(provider2.DisplayName, flag3);
|
|
if (exposedPlugin2 != null)
|
|
{
|
|
ImGui.SameLine();
|
|
ImU8String text2 = new ImU8String(1, 1);
|
|
text2.AppendLiteral("v");
|
|
text2.AppendFormatted(exposedPlugin2.Version);
|
|
ImGui.TextColored(in UiThemeUtils.DimTextColor, text2);
|
|
}
|
|
if (!flag3)
|
|
{
|
|
DrawInlineProviderActions(provider2, isDisabled2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return flag || _configuration.General.CombatModule != combatModule;
|
|
}
|
|
}
|
|
|
|
private void DrawProviderStatusIcon(bool isLoaded, bool isDisabled)
|
|
{
|
|
ImGui.SameLine(0f);
|
|
using (_pluginInterface.UiBuilder.IconFontFixedWidthHandle.Push())
|
|
{
|
|
Vector4 col;
|
|
FontAwesomeIcon icon;
|
|
if (isLoaded)
|
|
{
|
|
col = UiThemeUtils.StatusComplete;
|
|
icon = FontAwesomeIcon.Check;
|
|
}
|
|
else if (isDisabled)
|
|
{
|
|
col = UiThemeUtils.StatusActive;
|
|
icon = FontAwesomeIcon.ExclamationTriangle;
|
|
}
|
|
else
|
|
{
|
|
col = UiThemeUtils.StatusLocked;
|
|
icon = FontAwesomeIcon.Times;
|
|
}
|
|
ImGui.AlignTextToFramePadding();
|
|
ImGui.TextColored(in col, icon.ToIconString());
|
|
}
|
|
}
|
|
|
|
private void DrawInlineProviderActions(PluginProvider provider, bool isDisabled)
|
|
{
|
|
if (isDisabled)
|
|
{
|
|
ImGui.SameLine();
|
|
ImGui.TextColored(in UiThemeUtils.StatusActive, "Installed but disabled");
|
|
ImGui.SameLine();
|
|
DrawEnableButton(provider);
|
|
DrawInstallError(provider);
|
|
return;
|
|
}
|
|
ImGui.SameLine();
|
|
DrawInstallButton(provider);
|
|
ImGui.SameLine();
|
|
if (UiThemeUtils.IconTextButton(FontAwesomeIcon.Globe, "Website"))
|
|
{
|
|
Util.OpenLink(provider.WebsiteUri.ToString());
|
|
}
|
|
if (provider.DalamudRepositoryUri != null)
|
|
{
|
|
ImGui.SameLine();
|
|
if (UiThemeUtils.IconTextButton(FontAwesomeIcon.Code, "Repo"))
|
|
{
|
|
Util.OpenLink(provider.DalamudRepositoryUri.ToString());
|
|
}
|
|
}
|
|
DrawInstallError(provider);
|
|
}
|
|
|
|
private void DrawInstallButton(PluginProvider provider)
|
|
{
|
|
string thirdPartyRepoUrl = provider.DalamudRepositoryUri?.ToString();
|
|
string text;
|
|
bool flag;
|
|
switch (_installer.GetState(provider.InternalName, thirdPartyRepoUrl).Status)
|
|
{
|
|
case PluginInstallStatus.InProgress:
|
|
text = "Installing…";
|
|
flag = false;
|
|
break;
|
|
case PluginInstallStatus.Failed:
|
|
text = "Retry Install";
|
|
flag = !_installer.IsAnyInstallInProgress;
|
|
break;
|
|
default:
|
|
text = "Install";
|
|
flag = !_installer.IsAnyInstallInProgress;
|
|
break;
|
|
}
|
|
using (ImRaii.Disabled(!flag))
|
|
{
|
|
if (UiThemeUtils.IconTextButton(FontAwesomeIcon.Download, text))
|
|
{
|
|
_installer.TryInstall(provider.InternalName, thirdPartyRepoUrl, provider.AliasUrls);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawEnableButton(PluginProvider provider)
|
|
{
|
|
string thirdPartyRepoUrl = provider.DalamudRepositoryUri?.ToString();
|
|
string text;
|
|
bool flag;
|
|
switch (_installer.GetState(provider.InternalName, thirdPartyRepoUrl).Status)
|
|
{
|
|
case PluginInstallStatus.InProgress:
|
|
text = "Enabling…";
|
|
flag = false;
|
|
break;
|
|
case PluginInstallStatus.Failed:
|
|
text = "Retry Enable";
|
|
flag = !_installer.IsAnyInstallInProgress;
|
|
break;
|
|
default:
|
|
text = "Enable";
|
|
flag = !_installer.IsAnyInstallInProgress;
|
|
break;
|
|
}
|
|
using (ImRaii.Disabled(!flag))
|
|
{
|
|
if (UiThemeUtils.IconTextButton(FontAwesomeIcon.ToggleOn, text))
|
|
{
|
|
_installer.TryEnable(provider.InternalName, thirdPartyRepoUrl, provider.AliasUrls);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawInstallError(PluginProvider provider)
|
|
{
|
|
string thirdPartyRepoUrl = provider.DalamudRepositoryUri?.ToString();
|
|
PluginInstallState state = _installer.GetState(provider.InternalName, thirdPartyRepoUrl);
|
|
if (state.Status == PluginInstallStatus.Failed && !string.IsNullOrEmpty(state.ErrorMessage))
|
|
{
|
|
ImGui.PushTextWrapPos(0f);
|
|
ImU8String text = new ImU8String(8, 1);
|
|
text.AppendLiteral("Failed: ");
|
|
text.AppendFormatted(state.ErrorMessage);
|
|
ImGui.TextColored(in UiThemeUtils.StatusLocked, text);
|
|
ImGui.PopTextWrapPos();
|
|
}
|
|
}
|
|
}
|