mirror of
https://github.com/goatcorp/Dalamud.git
synced 2026-01-03 06:13:40 +01:00
merge master into profiles
This commit is contained in:
commit
fe6196d0ad
57 changed files with 1118 additions and 287 deletions
|
|
@ -22,6 +22,7 @@ using Dalamud.Game.Text.SeStringHandling.Payloads;
|
|||
using Dalamud.Interface.Internal;
|
||||
using Dalamud.IoC.Internal;
|
||||
using Dalamud.Logging.Internal;
|
||||
using Dalamud.Networking.Http;
|
||||
using Dalamud.Plugin.Internal.Exceptions;
|
||||
using Dalamud.Plugin.Internal.Profiles;
|
||||
using Dalamud.Plugin.Internal.Types;
|
||||
|
|
@ -41,6 +42,9 @@ namespace Dalamud.Plugin.Internal;
|
|||
// DalamudTextureWrap registers textures to dispose with IM
|
||||
[InherentDependency<InterfaceManager>]
|
||||
|
||||
// LocalPlugin uses ServiceContainer to create scopes
|
||||
[InherentDependency<ServiceContainer>]
|
||||
|
||||
#pragma warning restore SA1015
|
||||
internal partial class PluginManager : IDisposable, IServiceType
|
||||
{
|
||||
|
|
@ -54,15 +58,6 @@ internal partial class PluginManager : IDisposable, IServiceType
|
|||
/// </summary>
|
||||
public const int PluginWaitBeforeFreeDefault = 1000; // upped from 500ms, seems more stable
|
||||
|
||||
private const string DevPluginsDisclaimerFilename = "DONT_USE_THIS_FOLDER.txt";
|
||||
|
||||
private const string DevPluginsDisclaimerText = @"Hey!
|
||||
The devPlugins folder is deprecated and will be removed soon. Please don't use it anymore for plugin development.
|
||||
Instead, open the Dalamud settings and add the path to your plugins build output folder as a dev plugin location.
|
||||
Remove your devPlugin from this folder.
|
||||
|
||||
Thanks and have fun!";
|
||||
|
||||
private static readonly ModuleLog Log = new("PLUGINM");
|
||||
|
||||
private readonly object pluginListLock = new();
|
||||
|
|
@ -81,22 +76,17 @@ Thanks and have fun!";
|
|||
[ServiceManager.ServiceDependency]
|
||||
private readonly ProfileManager profileManager = Service<ProfileManager>.Get();
|
||||
|
||||
[ServiceManager.ServiceDependency]
|
||||
private readonly HappyHttpClient happyHttpClient = Service<HappyHttpClient>.Get();
|
||||
|
||||
[ServiceManager.ServiceConstructor]
|
||||
private PluginManager()
|
||||
{
|
||||
this.pluginDirectory = new DirectoryInfo(this.startInfo.PluginDirectory!);
|
||||
this.devPluginDirectory = new DirectoryInfo(this.startInfo.DefaultPluginDirectory!);
|
||||
|
||||
if (!this.pluginDirectory.Exists)
|
||||
this.pluginDirectory.Create();
|
||||
|
||||
if (!this.devPluginDirectory.Exists)
|
||||
this.devPluginDirectory.Create();
|
||||
|
||||
var disclaimerFileName = Path.Combine(this.devPluginDirectory.FullName, DevPluginsDisclaimerFilename);
|
||||
if (!File.Exists(disclaimerFileName))
|
||||
File.WriteAllText(disclaimerFileName, DevPluginsDisclaimerText);
|
||||
|
||||
this.SafeMode = EnvironmentConfiguration.DalamudNoPlugins || this.configuration.PluginSafeMode || this.startInfo.NoLoadPlugins;
|
||||
|
||||
try
|
||||
|
|
@ -391,9 +381,6 @@ Thanks and have fun!";
|
|||
if (!this.pluginDirectory.Exists)
|
||||
this.pluginDirectory.Create();
|
||||
|
||||
if (!this.devPluginDirectory.Exists)
|
||||
this.devPluginDirectory.Create();
|
||||
|
||||
// Add installed plugins. These are expected to be in a specific format so we can look for exactly that.
|
||||
foreach (var pluginDir in this.pluginDirectory.GetDirectories())
|
||||
{
|
||||
|
|
@ -434,7 +421,7 @@ Thanks and have fun!";
|
|||
}
|
||||
|
||||
// devPlugins are more freeform. Look for any dll and hope to get lucky.
|
||||
var devDllFiles = this.devPluginDirectory.GetFiles("*.dll", SearchOption.AllDirectories).ToList();
|
||||
var devDllFiles = new List<FileInfo>();
|
||||
|
||||
foreach (var setting in this.configuration.DevPluginLoadLocations)
|
||||
{
|
||||
|
|
@ -657,11 +644,8 @@ Thanks and have fun!";
|
|||
/// </summary>
|
||||
public void ScanDevPlugins()
|
||||
{
|
||||
if (!this.devPluginDirectory.Exists)
|
||||
this.devPluginDirectory.Create();
|
||||
|
||||
// devPlugins are more freeform. Look for any dll and hope to get lucky.
|
||||
var devDllFiles = this.devPluginDirectory.GetFiles("*.dll", SearchOption.AllDirectories).ToList();
|
||||
var devDllFiles = new List<FileInfo>();
|
||||
|
||||
foreach (var setting in this.configuration.DevPluginLoadLocations)
|
||||
{
|
||||
|
|
@ -736,7 +720,7 @@ Thanks and have fun!";
|
|||
var downloadUrl = useTesting ? repoManifest.DownloadLinkTesting : repoManifest.DownloadLinkInstall;
|
||||
var version = useTesting ? repoManifest.TestingAssemblyVersion : repoManifest.AssemblyVersion;
|
||||
|
||||
var response = await Util.HttpClient.GetAsync(downloadUrl);
|
||||
var response = await this.happyHttpClient.SharedHttpClient.GetAsync(downloadUrl);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var outputDir = new DirectoryInfo(Path.Combine(this.pluginDirectory.FullName, repoManifest.InternalName, version?.ToString() ?? string.Empty));
|
||||
|
|
@ -1078,8 +1062,9 @@ Thanks and have fun!";
|
|||
/// </summary>
|
||||
/// <param name="ignoreDisabled">Ignore disabled plugins.</param>
|
||||
/// <param name="dryRun">Perform a dry run, don't install anything.</param>
|
||||
/// <param name="autoUpdate">If this action was performed as part of an auto-update.</param>
|
||||
/// <returns>Success or failure and a list of updated plugin metadata.</returns>
|
||||
public async Task<List<PluginUpdateStatus>> UpdatePluginsAsync(bool ignoreDisabled, bool dryRun)
|
||||
public async Task<List<PluginUpdateStatus>> UpdatePluginsAsync(bool ignoreDisabled, bool dryRun, bool autoUpdate = false)
|
||||
{
|
||||
Log.Information("Starting plugin update");
|
||||
|
||||
|
|
@ -1104,6 +1089,9 @@ Thanks and have fun!";
|
|||
}
|
||||
|
||||
this.NotifyInstalledPluginsChanged();
|
||||
this.NotifyPluginsForStateChange(
|
||||
autoUpdate ? PluginListInvalidationKind.AutoUpdate : PluginListInvalidationKind.Update,
|
||||
updatedList.Select(x => x.InternalName));
|
||||
|
||||
Log.Information("Plugin update OK.");
|
||||
|
||||
|
|
@ -1394,6 +1382,20 @@ Thanks and have fun!";
|
|||
this.OnInstalledPluginsChanged?.InvokeSafely();
|
||||
}
|
||||
|
||||
private void NotifyPluginsForStateChange(PluginListInvalidationKind kind, IEnumerable<string> affectedInternalNames)
|
||||
{
|
||||
foreach (var installedPlugin in this.InstalledPlugins)
|
||||
{
|
||||
if (!installedPlugin.IsLoaded || installedPlugin.DalamudInterface == null)
|
||||
continue;
|
||||
|
||||
installedPlugin.DalamudInterface.NotifyActivePluginsChanged(
|
||||
kind,
|
||||
// ReSharper disable once PossibleMultipleEnumeration
|
||||
affectedInternalNames.Contains(installedPlugin.Manifest.InternalName));
|
||||
}
|
||||
}
|
||||
|
||||
private static class Locs
|
||||
{
|
||||
public static string DalamudPluginUpdateSuccessful(string name, Version version) => Loc.Localize("DalamudPluginUpdateSuccessful", " 》 {0} updated to v{1}.").Format(name, version);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ using Dalamud.Game.Gui.Dtr;
|
|||
using Dalamud.Interface.GameFonts;
|
||||
using Dalamud.Interface.Internal;
|
||||
using Dalamud.IoC.Internal;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Logging.Internal;
|
||||
using Dalamud.Plugin.Internal.Exceptions;
|
||||
using Dalamud.Plugin.Internal.Loader;
|
||||
|
|
@ -181,10 +182,15 @@ internal class LocalPlugin : IDisposable
|
|||
public AssemblyName? AssemblyName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin name, directly from the plugin or if it is not loaded from the manifest.
|
||||
/// Gets the plugin name from the manifest.
|
||||
/// </summary>
|
||||
public string Name => this.Manifest.Name;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin internal name from the manifest.
|
||||
/// </summary>
|
||||
public string InternalName => this.Manifest.InternalName;
|
||||
|
||||
/// <summary>
|
||||
/// Gets an optional reason, if the plugin is banned.
|
||||
/// </summary>
|
||||
|
|
@ -247,6 +253,11 @@ internal class LocalPlugin : IDisposable
|
|||
public bool ApplicableForLoad => !this.IsBanned && !this.IsDecommissioned && !this.IsOrphaned && !this.IsOutdated
|
||||
&& !(!this.IsDev && this.State == PluginState.UnloadError) && this.CheckPolicy();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the service scope for this plugin.
|
||||
/// </summary>
|
||||
public IServiceScope? ServiceScope { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
|
|
@ -268,6 +279,9 @@ internal class LocalPlugin : IDisposable
|
|||
this.DalamudInterface?.ExplicitDispose();
|
||||
this.DalamudInterface = null;
|
||||
|
||||
this.ServiceScope?.Dispose();
|
||||
this.ServiceScope = null;
|
||||
|
||||
this.pluginType = null;
|
||||
this.pluginAssembly = null;
|
||||
|
||||
|
|
@ -314,8 +328,13 @@ internal class LocalPlugin : IDisposable
|
|||
case PluginState.Loaded:
|
||||
throw new InvalidPluginOperationException($"Unable to load {this.Name}, already loaded");
|
||||
case PluginState.LoadError:
|
||||
throw new InvalidPluginOperationException(
|
||||
$"Unable to load {this.Name}, load previously faulted, unload first");
|
||||
if (!this.IsDev)
|
||||
{
|
||||
throw new InvalidPluginOperationException(
|
||||
$"Unable to load {this.Name}, load previously faulted, unload first");
|
||||
}
|
||||
|
||||
break;
|
||||
case PluginState.UnloadError:
|
||||
if (!this.IsDev)
|
||||
{
|
||||
|
|
@ -423,17 +442,20 @@ internal class LocalPlugin : IDisposable
|
|||
PluginManager.PluginLocations[this.pluginType.Assembly.FullName] = new PluginPatchData(this.DllFile);
|
||||
|
||||
this.DalamudInterface =
|
||||
new DalamudPluginInterface(this.pluginAssembly.GetName().Name!, this.DllFile, reason, this.IsDev, this.Manifest);
|
||||
new DalamudPluginInterface(this, reason);
|
||||
|
||||
this.ServiceScope = ioc.GetScope();
|
||||
this.ServiceScope.RegisterPrivateScopes(this); // Add this LocalPlugin as a private scope, so services can get it
|
||||
|
||||
if (this.Manifest.LoadSync && this.Manifest.LoadRequiredState is 0 or 1)
|
||||
{
|
||||
this.instance = await framework.RunOnFrameworkThread(
|
||||
() => ioc.CreateAsync(this.pluginType!, this.DalamudInterface!)) as IDalamudPlugin;
|
||||
() => this.ServiceScope.CreateAsync(this.pluginType!, this.DalamudInterface!)) as IDalamudPlugin;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.instance =
|
||||
await ioc.CreateAsync(this.pluginType!, this.DalamudInterface!) as IDalamudPlugin;
|
||||
await this.ServiceScope.CreateAsync(this.pluginType!, this.DalamudInterface!) as IDalamudPlugin;
|
||||
}
|
||||
|
||||
if (this.instance == null)
|
||||
|
|
@ -458,7 +480,9 @@ internal class LocalPlugin : IDisposable
|
|||
catch (Exception ex)
|
||||
{
|
||||
this.State = PluginState.LoadError;
|
||||
Log.Error(ex, $"Error while loading {this.Name}");
|
||||
|
||||
if (ex is not BannedPluginException)
|
||||
Log.Error(ex, $"Error while loading {this.Name}");
|
||||
|
||||
throw;
|
||||
}
|
||||
|
|
@ -479,6 +503,7 @@ internal class LocalPlugin : IDisposable
|
|||
{
|
||||
var configuration = Service<DalamudConfiguration>.Get();
|
||||
var framework = Service<Framework>.GetNullable();
|
||||
var ioc = await Service<ServiceContainer>.GetAsync();
|
||||
|
||||
await this.pluginLoadStateLock.WaitAsync();
|
||||
try
|
||||
|
|
@ -517,6 +542,9 @@ internal class LocalPlugin : IDisposable
|
|||
this.DalamudInterface?.ExplicitDispose();
|
||||
this.DalamudInterface = null;
|
||||
|
||||
this.ServiceScope?.Dispose();
|
||||
this.ServiceScope = null;
|
||||
|
||||
this.pluginType = null;
|
||||
this.pluginAssembly = null;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,11 +3,13 @@ using System.Collections.Generic;
|
|||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Dalamud.Logging.Internal;
|
||||
using Dalamud.Networking.Http;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dalamud.Plugin.Internal.Types;
|
||||
|
|
@ -24,7 +26,11 @@ internal class PluginRepository
|
|||
|
||||
private static readonly ModuleLog Log = new("PLUGINR");
|
||||
|
||||
private static readonly HttpClient HttpClient = new()
|
||||
private static readonly HttpClient HttpClient = new(new SocketsHttpHandler
|
||||
{
|
||||
AutomaticDecompression = DecompressionMethods.All,
|
||||
ConnectCallback = Service<HappyHttpClient>.Get().SharedHappyEyeballsCallback.ConnectCallback,
|
||||
})
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(20),
|
||||
DefaultRequestHeaders =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue