mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
feat: add plugin installer
This commit is contained in:
parent
6d57da2fec
commit
fd95379aa3
8 changed files with 377 additions and 87 deletions
|
|
@ -44,15 +44,15 @@ namespace Dalamud.Injector {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DalamudStartInfo startInfo;
|
||||||
if (args.Length == 1) {
|
if (args.Length == 1) {
|
||||||
var defaultStartInfo = GetDefaultStartInfo();
|
startInfo = GetDefaultStartInfo();
|
||||||
Console.WriteLine("\nA Dalamud start info was not found in the program arguments. One has been generated for you.");
|
Console.WriteLine("\nA Dalamud start info was not found in the program arguments. One has been generated for you.");
|
||||||
Console.WriteLine("\nCopy the following contents into the program arguments:");
|
Console.WriteLine("\nCopy the following contents into the program arguments:");
|
||||||
Console.WriteLine(defaultStartInfo);
|
} else {
|
||||||
return;
|
startInfo = JsonConvert.DeserializeObject<DalamudStartInfo>(Encoding.UTF8.GetString(Convert.FromBase64String(args[1])));
|
||||||
}
|
}
|
||||||
|
|
||||||
var startInfo = JsonConvert.DeserializeObject<DalamudStartInfo>(Encoding.UTF8.GetString(Convert.FromBase64String(args[1])));
|
|
||||||
startInfo.WorkingDirectory = Directory.GetCurrentDirectory();
|
startInfo.WorkingDirectory = Directory.GetCurrentDirectory();
|
||||||
|
|
||||||
// Seems to help with the STATUS_INTERNAL_ERROR condition
|
// Seems to help with the STATUS_INTERNAL_ERROR condition
|
||||||
|
|
@ -77,22 +77,17 @@ namespace Dalamud.Injector {
|
||||||
Console.WriteLine("Injected");
|
Console.WriteLine("Injected");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetDefaultStartInfo() {
|
private static DalamudStartInfo GetDefaultStartInfo() {
|
||||||
DalamudStartInfo startInfo = new DalamudStartInfo();
|
var startInfo = new DalamudStartInfo {
|
||||||
|
WorkingDirectory = null,
|
||||||
startInfo.WorkingDirectory = null;
|
ConfigurationPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
|
||||||
|
@"\XIVLauncher\dalamudConfig.json",
|
||||||
startInfo.ConfigurationPath =
|
PluginDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
|
@"\XIVLauncher\plugins",
|
||||||
@"\XIVLauncher\dalamudConfig.json";
|
DefaultPluginDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
|
||||||
|
@"\XIVLauncher\defaultplugins",
|
||||||
startInfo.PluginDirectory =
|
Language = ClientLanguage.English
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\XIVLauncher\plugins";
|
};
|
||||||
|
|
||||||
startInfo.DefaultPluginDirectory =
|
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\XIVLauncher\defaultplugins";
|
|
||||||
|
|
||||||
startInfo.Language = ClientLanguage.English;
|
|
||||||
|
|
||||||
Console.WriteLine("Creating a StartInfo with:\n" +
|
Console.WriteLine("Creating a StartInfo with:\n" +
|
||||||
$"ConfigurationPath: {startInfo.ConfigurationPath}\n" +
|
$"ConfigurationPath: {startInfo.ConfigurationPath}\n" +
|
||||||
|
|
@ -100,7 +95,7 @@ namespace Dalamud.Injector {
|
||||||
$"DefaultPluginDirectory: {startInfo.DefaultPluginDirectory}\n" +
|
$"DefaultPluginDirectory: {startInfo.DefaultPluginDirectory}\n" +
|
||||||
$"Language: {startInfo.Language}");
|
$"Language: {startInfo.Language}");
|
||||||
|
|
||||||
return Convert.ToBase64String(Encoding.ASCII.GetBytes(JsonConvert.SerializeObject(startInfo)));
|
return startInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,13 @@ namespace Dalamud {
|
||||||
|
|
||||||
public readonly SigScanner SigScanner;
|
public readonly SigScanner SigScanner;
|
||||||
|
|
||||||
public Framework Framework { get; }
|
public readonly Framework Framework;
|
||||||
|
|
||||||
public CommandManager CommandManager { get; }
|
public readonly CommandManager CommandManager;
|
||||||
public ChatHandlers ChatHandlers { get; }
|
|
||||||
public NetworkHandlers NetworkHandlers { get; }
|
public readonly ChatHandlers ChatHandlers;
|
||||||
|
|
||||||
|
public readonly NetworkHandlers NetworkHandlers;
|
||||||
|
|
||||||
public readonly DiscordBotManager BotManager;
|
public readonly DiscordBotManager BotManager;
|
||||||
|
|
||||||
|
|
@ -67,27 +69,26 @@ namespace Dalamud {
|
||||||
|
|
||||||
// Initialize the process information.
|
// Initialize the process information.
|
||||||
this.targetModule = Process.GetCurrentProcess().MainModule;
|
this.targetModule = Process.GetCurrentProcess().MainModule;
|
||||||
SigScanner = new SigScanner(this.targetModule, true);
|
this.SigScanner = new SigScanner(this.targetModule, true);
|
||||||
|
|
||||||
// Initialize game subsystem
|
// Initialize game subsystem
|
||||||
Framework = new Framework(this.SigScanner, this);
|
this.Framework = new Framework(this.SigScanner, this);
|
||||||
|
|
||||||
// Initialize managers. Basically handlers for the logic
|
// Initialize managers. Basically handlers for the logic
|
||||||
CommandManager = new CommandManager(this, info.Language);
|
this.CommandManager = new CommandManager(this, info.Language);
|
||||||
SetupCommands();
|
SetupCommands();
|
||||||
|
|
||||||
ChatHandlers = new ChatHandlers(this);
|
this.ChatHandlers = new ChatHandlers(this);
|
||||||
NetworkHandlers = new NetworkHandlers(this, this.Configuration.OptOutMbCollection);
|
this.NetworkHandlers = new NetworkHandlers(this, this.Configuration.OptOutMbCollection);
|
||||||
|
|
||||||
this.Data = new DataManager(this.StartInfo.Language);
|
this.Data = new DataManager(this.StartInfo.Language);
|
||||||
//Task.Run(() => );
|
|
||||||
this.Data.Initialize();
|
this.Data.Initialize();
|
||||||
|
|
||||||
this.ClientState = new ClientState(this, info, this.SigScanner, this.targetModule);
|
this.ClientState = new ClientState(this, info, this.SigScanner, this.targetModule);
|
||||||
|
|
||||||
this.BotManager = new DiscordBotManager(this, this.Configuration.DiscordFeatureConfig);
|
this.BotManager = new DiscordBotManager(this, this.Configuration.DiscordFeatureConfig);
|
||||||
|
|
||||||
this.PluginManager = new PluginManager(this, info.PluginDirectory, info.DefaultPluginDirectory);
|
this.PluginManager = new PluginManager(this, info.PluginDirectory);
|
||||||
|
|
||||||
this.WinSock2 = new WinSockHandlers();
|
this.WinSock2 = new WinSockHandlers();
|
||||||
|
|
||||||
|
|
@ -105,18 +106,15 @@ namespace Dalamud {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.Information("Could not enable interface.");
|
Log.Information("Could not enable interface.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Framework.Enable();
|
this.Framework.Enable();
|
||||||
|
|
||||||
this.BotManager.Start();
|
this.BotManager.Start();
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
this.PluginManager.LoadPlugins();
|
this.PluginManager.LoadPlugins();
|
||||||
}
|
} catch (Exception ex) {
|
||||||
catch (Exception ex)
|
this.Framework.Gui.Chat.PrintError(
|
||||||
{
|
|
||||||
Framework.Gui.Chat.PrintError(
|
|
||||||
"[XIVLAUNCHER] There was an error loading additional plugins. Please check the log for more details.");
|
"[XIVLAUNCHER] There was an error loading additional plugins. Please check the log for more details.");
|
||||||
Log.Error(ex, "Plugin load failed.");
|
Log.Error(ex, "Plugin load failed.");
|
||||||
}
|
}
|
||||||
|
|
@ -167,9 +165,11 @@ namespace Dalamud {
|
||||||
|
|
||||||
private bool isImguiDrawLogWindow = false;
|
private bool isImguiDrawLogWindow = false;
|
||||||
private bool isImguiDrawDataWindow = false;
|
private bool isImguiDrawDataWindow = false;
|
||||||
|
private bool isImguiDrawPluginWindow = false;
|
||||||
|
|
||||||
private DalamudLogWindow logWindow;
|
private DalamudLogWindow logWindow;
|
||||||
private DalamudDataWindow dataWindow;
|
private DalamudDataWindow dataWindow;
|
||||||
|
private PluginInstallerWindow pluginWindow;
|
||||||
|
|
||||||
private void BuildDalamudUi()
|
private void BuildDalamudUi()
|
||||||
{
|
{
|
||||||
|
|
@ -209,10 +209,15 @@ namespace Dalamud {
|
||||||
|
|
||||||
if (ImGui.BeginMenu("Plugins"))
|
if (ImGui.BeginMenu("Plugins"))
|
||||||
{
|
{
|
||||||
|
if (ImGui.MenuItem("Open Plugin installer"))
|
||||||
|
{
|
||||||
|
this.pluginWindow = new PluginInstallerWindow(this.PluginManager, this.StartInfo.PluginDirectory);
|
||||||
|
this.isImguiDrawPluginWindow = true;
|
||||||
|
}
|
||||||
if (ImGui.MenuItem("Print plugin info")) {
|
if (ImGui.MenuItem("Print plugin info")) {
|
||||||
foreach (var plugin in this.PluginManager.Plugins) {
|
foreach (var plugin in this.PluginManager.Plugins) {
|
||||||
// TODO: some more here, state maybe?
|
// TODO: some more here, state maybe?
|
||||||
Log.Information($"{plugin.Name}");
|
Log.Information($"{plugin.Plugin.Name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ImGui.MenuItem("Reload plugins"))
|
if (ImGui.MenuItem("Reload plugins"))
|
||||||
|
|
@ -241,6 +246,11 @@ namespace Dalamud {
|
||||||
this.isImguiDrawDataWindow = this.dataWindow != null && this.dataWindow.Draw();
|
this.isImguiDrawDataWindow = this.dataWindow != null && this.dataWindow.Draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.isImguiDrawPluginWindow)
|
||||||
|
{
|
||||||
|
this.isImguiDrawPluginWindow = this.pluginWindow != null && this.pluginWindow.Draw();
|
||||||
|
}
|
||||||
|
|
||||||
if (this.isImguiDrawDemoWindow)
|
if (this.isImguiDrawDemoWindow)
|
||||||
ImGui.ShowDemoWindow();
|
ImGui.ShowDemoWindow();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ namespace Dalamud.Game {
|
||||||
this.dalamud.Framework.Gui.Chat.Print($"XIVLauncher in-game addon v{assemblyVersion} loaded.");
|
this.dalamud.Framework.Gui.Chat.Print($"XIVLauncher in-game addon v{assemblyVersion} loaded.");
|
||||||
|
|
||||||
foreach (var plugin in this.dalamud.PluginManager.Plugins) {
|
foreach (var plugin in this.dalamud.PluginManager.Plugins) {
|
||||||
this.dalamud.Framework.Gui.Chat.Print($" -> {plugin.Name} v{plugin.GetType().Assembly.GetName().Version} loaded.");
|
this.dalamud.Framework.Gui.Chat.Print($" -> {plugin.Plugin.Name} v{plugin.GetType().Assembly.GetName().Version} loaded.");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.hasSeenLoadingMsg = true;
|
this.hasSeenLoadingMsg = true;
|
||||||
|
|
|
||||||
16
Dalamud/Plugin/Features/IHasConfigUi.cs
Normal file
16
Dalamud/Plugin/Features/IHasConfigUi.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
using Dalamud.Interface;
|
||||||
|
|
||||||
|
namespace Dalamud.Plugin.Features
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This interface represents a Dalamud plugin that has a configuration UI which can be triggered.
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasConfigUi : IHasUi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An event handler that is fired when the plugin should show its configuration interface.
|
||||||
|
/// </summary>
|
||||||
|
EventHandler OpenConfigUi { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
21
Dalamud/Plugin/Features/IHasUi.cs
Normal file
21
Dalamud/Plugin/Features/IHasUi.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Dalamud.Interface;
|
||||||
|
|
||||||
|
namespace Dalamud.Plugin.Features
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This interface represents a Dalamud plugin that has user interface which can be drawn.
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasUi : IDalamudPlugin
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A function that gets called when Dalamud is ready to draw your UI.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uiBuilder">An <see cref="UiBuilder"/> object you can use to e.g. load images.</param>
|
||||||
|
void Draw(UiBuilder uiBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
17
Dalamud/Plugin/PluginDefinition.cs
Normal file
17
Dalamud/Plugin/PluginDefinition.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Dalamud.Plugin
|
||||||
|
{
|
||||||
|
public class PluginDefinition
|
||||||
|
{
|
||||||
|
public string Author { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string InternalName { get; set; }
|
||||||
|
public string AssemblyVersion { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
207
Dalamud/Plugin/PluginInstallerWindow.cs
Normal file
207
Dalamud/Plugin/PluginInstallerWindow.cs
Normal file
|
|
@ -0,0 +1,207 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Dalamud.Plugin.Features;
|
||||||
|
using ImGuiNET;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
namespace Dalamud.Plugin
|
||||||
|
{
|
||||||
|
class PluginInstallerWindow {
|
||||||
|
private const string PluginRepoBaseUrl = "https://goaaats.github.io/DalamudPlugins/";
|
||||||
|
|
||||||
|
private PluginManager manager;
|
||||||
|
private string pluginDirectory;
|
||||||
|
private ReadOnlyCollection<PluginDefinition> pluginMaster;
|
||||||
|
private bool errorModalDrawing = true;
|
||||||
|
|
||||||
|
private enum PluginInstallStatus {
|
||||||
|
None,
|
||||||
|
InProgress,
|
||||||
|
Success,
|
||||||
|
Fail
|
||||||
|
}
|
||||||
|
|
||||||
|
private PluginInstallStatus installStatus = PluginInstallStatus.None;
|
||||||
|
|
||||||
|
private bool masterDownloadFailed = false;
|
||||||
|
|
||||||
|
public PluginInstallerWindow(PluginManager manager, string pluginDirectory) {
|
||||||
|
this.manager = manager;
|
||||||
|
this.pluginDirectory = pluginDirectory;
|
||||||
|
Task.Run(CachePluginMaster).ContinueWith(t => { this.masterDownloadFailed = t.IsFaulted; });
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CachePluginMaster() {
|
||||||
|
try {
|
||||||
|
using var client = new WebClient();
|
||||||
|
|
||||||
|
var data = client.DownloadString(PluginRepoBaseUrl + "pluginmaster.json");
|
||||||
|
|
||||||
|
this.pluginMaster = JsonConvert.DeserializeObject<ReadOnlyCollection<PluginDefinition>>(data);
|
||||||
|
} catch {
|
||||||
|
this.masterDownloadFailed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InstallPlugin(PluginDefinition definition) {
|
||||||
|
try {
|
||||||
|
var path = Path.GetTempFileName();
|
||||||
|
|
||||||
|
Log.Information("Downloading plugin to {0}", path);
|
||||||
|
|
||||||
|
using var client = new WebClient();
|
||||||
|
|
||||||
|
client.DownloadFile(PluginRepoBaseUrl + $"/plugins/{definition.InternalName}/latest.zip", path);
|
||||||
|
var outputDir = Path.Combine(this.pluginDirectory, definition.InternalName);
|
||||||
|
|
||||||
|
if (File.Exists(Path.Combine(outputDir, ".disabled"))) {
|
||||||
|
Log.Information("Plugin was disabled, re-enabling.");
|
||||||
|
File.Delete(Path.Combine(outputDir, ".disabled"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Information("Extracting to {0}", outputDir);
|
||||||
|
|
||||||
|
Directory.CreateDirectory(outputDir);
|
||||||
|
|
||||||
|
ZipFile.ExtractToDirectory(path, outputDir);
|
||||||
|
|
||||||
|
this.installStatus = PluginInstallStatus.Success;
|
||||||
|
this.manager.LoadPluginFromAssembly(new FileInfo(Path.Combine(outputDir, $"{definition.InternalName}.dll")));
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.Error(e, "Plugin download failed hard.");
|
||||||
|
this.installStatus = PluginInstallStatus.Fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Draw() {
|
||||||
|
var windowOpen = true;
|
||||||
|
|
||||||
|
ImGui.SetNextWindowSize(new Vector2(750, 520));
|
||||||
|
|
||||||
|
ImGui.Begin("Plugin Installer", ref windowOpen,
|
||||||
|
ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoScrollbar);
|
||||||
|
|
||||||
|
ImGui.Text("This window allows you install and remove in-game plugins.");
|
||||||
|
ImGui.Text("They are made by third-party developers.");
|
||||||
|
ImGui.Separator();
|
||||||
|
|
||||||
|
ImGui.BeginChild("scrolling", new Vector2(0, 400), true, ImGuiWindowFlags.HorizontalScrollbar);
|
||||||
|
|
||||||
|
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(1, 3));
|
||||||
|
|
||||||
|
if (this.pluginMaster == null) {
|
||||||
|
ImGui.Text("Loading plugins...");
|
||||||
|
} else if (this.masterDownloadFailed) {
|
||||||
|
ImGui.Text("Download failed.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var pluginDefinition in this.pluginMaster)
|
||||||
|
{
|
||||||
|
if (ImGui.CollapsingHeader(pluginDefinition.Name))
|
||||||
|
{
|
||||||
|
ImGui.Indent();
|
||||||
|
|
||||||
|
ImGui.Text(pluginDefinition.Name);
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.TextColored(new Vector4(0.5f, 0.5f, 0.5f, 1.0f), $" by {pluginDefinition.Author}");
|
||||||
|
|
||||||
|
ImGui.Text(pluginDefinition.Description);
|
||||||
|
|
||||||
|
var isInstalled = this.manager.Plugins.Where(x=> x.Definition != null).Any(
|
||||||
|
x => x.Definition.InternalName == pluginDefinition.InternalName);
|
||||||
|
|
||||||
|
if (!isInstalled) {
|
||||||
|
if (this.installStatus == PluginInstallStatus.InProgress) {
|
||||||
|
ImGui.Button($"Install in progress...");
|
||||||
|
} else {
|
||||||
|
if (ImGui.Button($"Install v{pluginDefinition.AssemblyVersion}"))
|
||||||
|
{
|
||||||
|
this.installStatus = PluginInstallStatus.InProgress;
|
||||||
|
|
||||||
|
Task.Run(() => InstallPlugin(pluginDefinition)).ContinueWith(t => { this.installStatus = t.IsFaulted ? PluginInstallStatus.Fail : this.installStatus; });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
var installedPlugin = this.manager.Plugins.Where(x => x.Definition != null).First(
|
||||||
|
x => x.Definition.InternalName == pluginDefinition.InternalName);
|
||||||
|
|
||||||
|
if (ImGui.Button("Disable"))
|
||||||
|
{
|
||||||
|
this.manager.DisablePlugin(installedPlugin.Definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (installedPlugin.Plugin is IHasConfigUi v2Plugin && v2Plugin.OpenConfigUi != null) {
|
||||||
|
ImGui.SameLine();
|
||||||
|
|
||||||
|
if (ImGui.Button("Open Configuration"))
|
||||||
|
{
|
||||||
|
v2Plugin.OpenConfigUi?.Invoke(null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.Unindent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.PopStyleVar();
|
||||||
|
|
||||||
|
ImGui.EndChild();
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
|
||||||
|
if (ImGui.Button("Remove All"))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
|
||||||
|
if (ImGui.Button("Open Plugin folder"))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
|
||||||
|
if (ImGui.Button("Close"))
|
||||||
|
{
|
||||||
|
windowOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.Button("test modal")) {
|
||||||
|
this.installStatus = PluginInstallStatus.Fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.Spacing();
|
||||||
|
|
||||||
|
if (this.installStatus == PluginInstallStatus.Fail || this.masterDownloadFailed) {
|
||||||
|
if (ImGui.BeginPopupModal("Installer failed", ref this.errorModalDrawing, ImGuiWindowFlags.AlwaysAutoResize))
|
||||||
|
{
|
||||||
|
ImGui.TextWrapped("The installer ran into an issue. Please restart the game and report this error on our discord.");
|
||||||
|
|
||||||
|
if (ImGui.Button("OK", new Vector2(120, 40))) { ImGui.CloseCurrentPopup(); }
|
||||||
|
|
||||||
|
ImGui.EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.End();
|
||||||
|
|
||||||
|
return windowOpen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
namespace Dalamud.Plugin
|
namespace Dalamud.Plugin
|
||||||
|
|
@ -12,14 +13,14 @@ namespace Dalamud.Plugin
|
||||||
public class PluginManager {
|
public class PluginManager {
|
||||||
private readonly Dalamud dalamud;
|
private readonly Dalamud dalamud;
|
||||||
private readonly string pluginDirectory;
|
private readonly string pluginDirectory;
|
||||||
private readonly string defaultPluginDirectory;
|
|
||||||
|
|
||||||
public List<IDalamudPlugin> Plugins;
|
private readonly Type interfaceType = typeof(IDalamudPlugin);
|
||||||
|
|
||||||
public PluginManager(Dalamud dalamud, string pluginDirectory, string defaultPluginDirectory) {
|
public readonly List<(IDalamudPlugin Plugin, PluginDefinition Definition)> Plugins = new List<(IDalamudPlugin plugin, PluginDefinition def)>();
|
||||||
|
|
||||||
|
public PluginManager(Dalamud dalamud, string pluginDirectory) {
|
||||||
this.dalamud = dalamud;
|
this.dalamud = dalamud;
|
||||||
this.pluginDirectory = pluginDirectory;
|
this.pluginDirectory = pluginDirectory;
|
||||||
this.defaultPluginDirectory = defaultPluginDirectory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnloadPlugins() {
|
public void UnloadPlugins() {
|
||||||
|
|
@ -27,60 +28,83 @@ namespace Dalamud.Plugin
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (var i = 0; i < this.Plugins.Count; i++) {
|
for (var i = 0; i < this.Plugins.Count; i++) {
|
||||||
this.Plugins[i].Dispose();
|
this.Plugins[i].Plugin.Dispose();
|
||||||
this.Plugins[i] = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.Plugins.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadPlugins() {
|
public void LoadPlugins() {
|
||||||
LoadPluginsAt(new DirectoryInfo(this.defaultPluginDirectory));
|
|
||||||
LoadPluginsAt(new DirectoryInfo(this.pluginDirectory));
|
LoadPluginsAt(new DirectoryInfo(this.pluginDirectory));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DisablePlugin(PluginDefinition definition) {
|
||||||
|
var thisPlugin = this.Plugins.Where(x => x.Definition != null)
|
||||||
|
.First(x => x.Definition.InternalName == definition.InternalName);
|
||||||
|
|
||||||
|
var outputDir = Path.Combine(this.pluginDirectory, definition.InternalName);
|
||||||
|
File.Create(Path.Combine(outputDir, ".disabled"));
|
||||||
|
|
||||||
|
thisPlugin.Plugin.Dispose();
|
||||||
|
|
||||||
|
this.Plugins.Remove(thisPlugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadPluginFromAssembly(FileInfo dllFile) {
|
||||||
|
Log.Information("Loading assembly at {0}", dllFile);
|
||||||
|
var assemblyName = AssemblyName.GetAssemblyName(dllFile.FullName);
|
||||||
|
var pluginAssembly = Assembly.Load(assemblyName);
|
||||||
|
|
||||||
|
if (pluginAssembly != null)
|
||||||
|
{
|
||||||
|
Log.Information("Loading types for {0}", pluginAssembly.FullName);
|
||||||
|
var types = pluginAssembly.GetTypes();
|
||||||
|
foreach (var type in types)
|
||||||
|
{
|
||||||
|
if (type.IsInterface || type.IsAbstract)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.GetInterface(interfaceType.FullName) != null)
|
||||||
|
{
|
||||||
|
var plugin = (IDalamudPlugin)Activator.CreateInstance(type);
|
||||||
|
|
||||||
|
var dalamudInterface = new DalamudPluginInterface(this.dalamud, type.Assembly.GetName().Name);
|
||||||
|
|
||||||
|
var defJsonFile = new FileInfo(Path.Combine(dllFile.Directory.FullName, $"{Path.GetFileNameWithoutExtension(dllFile.Name)}.json"));
|
||||||
|
|
||||||
|
PluginDefinition pluginDef = null;
|
||||||
|
if (defJsonFile.Exists)
|
||||||
|
{
|
||||||
|
Log.Information("Loading definition for plugin DLL {0}", dllFile.FullName);
|
||||||
|
|
||||||
|
pluginDef =
|
||||||
|
JsonConvert.DeserializeObject<PluginDefinition>(
|
||||||
|
File.ReadAllText(defJsonFile.FullName));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Information("Plugin DLL {0} has no definition.", dllFile.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.Initialize(dalamudInterface);
|
||||||
|
Log.Information("Loaded plugin: {0}", plugin.Name);
|
||||||
|
this.Plugins.Add((plugin, pluginDef));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void LoadPluginsAt(DirectoryInfo folder) {
|
private void LoadPluginsAt(DirectoryInfo folder) {
|
||||||
if (folder.Exists)
|
if (folder.Exists)
|
||||||
{
|
{
|
||||||
Log.Debug("Loading plugins at {0}", folder);
|
Log.Information("Loading plugins at {0}", folder);
|
||||||
|
|
||||||
var pluginDlls = folder.GetFiles("*.dll", SearchOption.AllDirectories);
|
var pluginDlls = folder.GetFiles("*.dll", SearchOption.AllDirectories);
|
||||||
|
|
||||||
var assemblies = new List<Assembly>(pluginDlls.Length);
|
foreach (var dllFile in pluginDlls) {
|
||||||
foreach (var dllFile in pluginDlls)
|
LoadPluginFromAssembly(dllFile);
|
||||||
{
|
|
||||||
Log.Debug("Loading assembly at {0}", dllFile);
|
|
||||||
var assemblyName = AssemblyName.GetAssemblyName(dllFile.FullName);
|
|
||||||
var pluginAssembly = Assembly.Load(assemblyName);
|
|
||||||
assemblies.Add(pluginAssembly);
|
|
||||||
}
|
|
||||||
|
|
||||||
var interfaceType = typeof(IDalamudPlugin);
|
|
||||||
var foundImplementations = new List<Type>();
|
|
||||||
foreach (var assembly in assemblies) {
|
|
||||||
if (assembly != null) {
|
|
||||||
Log.Debug("Loading types for {0}", assembly.FullName);
|
|
||||||
var types = assembly.GetTypes();
|
|
||||||
foreach (var type in types) {
|
|
||||||
if (type.IsInterface || type.IsAbstract) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type.GetInterface(interfaceType.FullName) != null) {
|
|
||||||
foundImplementations.Add(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Plugins = new List<IDalamudPlugin>(foundImplementations.Count);
|
|
||||||
foreach (var pluginType in foundImplementations)
|
|
||||||
{
|
|
||||||
var plugin = (IDalamudPlugin)Activator.CreateInstance(pluginType);
|
|
||||||
|
|
||||||
var dalamudInterface = new DalamudPluginInterface(this.dalamud, pluginType.Assembly.GetName().Name);
|
|
||||||
|
|
||||||
plugin.Initialize(dalamudInterface);
|
|
||||||
Log.Information("Loaded plugin: {0}", plugin.Name);
|
|
||||||
this.Plugins.Add(plugin);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue