mirror of
https://github.com/goatcorp/Dalamud.git
synced 2026-01-03 06:13:40 +01:00
Merge remote-tracking branch 'upstream/apiX' into feature/itextureprovider-updates
This commit is contained in:
commit
0d7c0a0375
335 changed files with 1640 additions and 1020 deletions
|
|
@ -1,4 +1,3 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
|
@ -19,6 +18,7 @@ using Dalamud.Game.Text.SeStringHandling.Payloads;
|
|||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Internal;
|
||||
using Dalamud.Interface.Internal.Windows.PluginInstaller;
|
||||
using Dalamud.Interface.Internal.Windows.Settings;
|
||||
using Dalamud.Plugin.Internal;
|
||||
using Dalamud.Plugin.Internal.Types;
|
||||
using Dalamud.Plugin.Internal.Types.Manifest;
|
||||
|
|
@ -27,6 +27,8 @@ using Dalamud.Plugin.Ipc.Exceptions;
|
|||
using Dalamud.Plugin.Ipc.Internal;
|
||||
using Dalamud.Utility;
|
||||
|
||||
using static Dalamud.Interface.Internal.Windows.PluginInstaller.PluginInstallerWindow;
|
||||
|
||||
namespace Dalamud.Plugin;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -220,7 +222,19 @@ public sealed class DalamudPluginInterface : IDisposable
|
|||
/// Opens the <see cref="PluginInstallerWindow"/> with the plugin name set as search target.
|
||||
/// </summary>
|
||||
/// <returns>Returns false if the DalamudInterface was null.</returns>
|
||||
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
|
||||
public bool OpenPluginInstaller()
|
||||
{
|
||||
return this.OpenPluginInstallerTo(PluginInstallerOpenKind.InstalledPlugins, this.plugin.InternalName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the <see cref="PluginInstallerWindow"/>, with an optional search term.
|
||||
/// </summary>
|
||||
/// <param name="openTo">The page to open the installer to. Defaults to the "All Plugins" page.</param>
|
||||
/// <param name="searchText">An optional search text to input in the search box.</param>
|
||||
/// <returns>Returns false if the DalamudInterface was null.</returns>
|
||||
public bool OpenPluginInstallerTo(PluginInstallerOpenKind openTo = PluginInstallerOpenKind.AllPlugins, string searchText = null)
|
||||
{
|
||||
var dalamudInterface = Service<DalamudInterface>.GetNullable(); // Can be null during boot
|
||||
if (dalamudInterface == null)
|
||||
|
|
@ -228,12 +242,48 @@ public sealed class DalamudPluginInterface : IDisposable
|
|||
return false;
|
||||
}
|
||||
|
||||
dalamudInterface.OpenPluginInstallerTo(PluginInstallerWindow.PluginInstallerOpenKind.InstalledPlugins);
|
||||
dalamudInterface.SetPluginInstallerSearchText(this.plugin.InternalName);
|
||||
dalamudInterface.OpenPluginInstallerTo(openTo);
|
||||
dalamudInterface.SetPluginInstallerSearchText(searchText);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the <see cref="SettingsWindow"/>, with an optional search term.
|
||||
/// </summary>
|
||||
/// <param name="openTo">The tab to open the settings to. Defaults to the "General" tab.</param>
|
||||
/// <param name="searchText">An optional search text to input in the search box.</param>
|
||||
/// <returns>Returns false if the DalamudInterface was null.</returns>
|
||||
public bool OpenDalamudSettingsTo(SettingsOpenKind openTo = SettingsOpenKind.General, string searchText = null)
|
||||
{
|
||||
var dalamudInterface = Service<DalamudInterface>.GetNullable(); // Can be null during boot
|
||||
if (dalamudInterface == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dalamudInterface.OpenSettingsTo(openTo);
|
||||
dalamudInterface.SetSettingsSearchText(searchText);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the dev menu bar.
|
||||
/// </summary>
|
||||
/// <returns>Returns false if the DalamudInterface was null.</returns>
|
||||
public bool OpenDeveloperMenu()
|
||||
{
|
||||
var dalamudInterface = Service<DalamudInterface>.GetNullable(); // Can be null during boot
|
||||
if (dalamudInterface == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dalamudInterface.OpenDevMenu();
|
||||
return true;
|
||||
}
|
||||
|
||||
#region IPC
|
||||
|
||||
/// <inheritdoc cref="DataShare.GetOrCreateData{T}"/>
|
||||
|
|
@ -348,7 +398,7 @@ public sealed class DalamudPluginInterface : IDisposable
|
|||
if (currentConfig == null)
|
||||
return;
|
||||
|
||||
this.configs.Save(currentConfig, this.plugin.InternalName, this.plugin.Manifest.WorkingPluginId);
|
||||
this.configs.Save(currentConfig, this.plugin.InternalName, this.plugin.EffectiveWorkingPluginId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -375,7 +425,7 @@ public sealed class DalamudPluginInterface : IDisposable
|
|||
}
|
||||
|
||||
// this shouldn't be a thing, I think, but just in case
|
||||
return this.configs.Load(this.plugin.InternalName, this.plugin.Manifest.WorkingPluginId);
|
||||
return this.configs.Load(this.plugin.InternalName, this.plugin.EffectiveWorkingPluginId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Plugin;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using Dalamud.Utility;
|
||||
|
||||
namespace Dalamud.Plugin;
|
||||
|
||||
[Api10ToDo("Refactor into an interface, add wrappers for OpenMainUI and OpenConfigUI")]
|
||||
public record InstalledPluginState(string Name, string InternalName, bool IsLoaded, Version Version);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Plugin.Internal.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright (c) Nate McMaster, Dalamud contributors.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the Loader root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright (c) Nate McMaster, Dalamud contributors.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the Loader root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright (c) Nate McMaster, Dalamud contributors.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the Loader root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright (c) Nate McMaster, Dalamud contributors.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the Loader root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright (c) Nate McMaster, Dalamud contributors.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the Loader root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright (c) Nate McMaster, Dalamud team.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the Loader root for license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Loader;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ using Dalamud.Game.Gui.Dtr;
|
|||
using Dalamud.Game.Text;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Internal;
|
||||
using Dalamud.Interface.Internal.Windows.PluginInstaller;
|
||||
using Dalamud.IoC;
|
||||
using Dalamud.IoC.Internal;
|
||||
using Dalamud.Logging.Internal;
|
||||
using Dalamud.Networking.Http;
|
||||
using Dalamud.Plugin.Internal.Exceptions;
|
||||
|
|
@ -42,8 +42,8 @@ namespace Dalamud.Plugin.Internal;
|
|||
/// NOTE: ALL plugin exposed services are marked as dependencies for <see cref="PluginManager"/>
|
||||
/// from <see cref="ResolvePossiblePluginDependencyServices"/>.
|
||||
/// </summary>
|
||||
[ServiceManager.BlockingEarlyLoadedService("Accomodation of plugins that blocks the game startup.")]
|
||||
internal partial class PluginManager : IInternalDisposableService
|
||||
[ServiceManager.BlockingEarlyLoadedService("Accommodation of plugins that blocks the game startup.")]
|
||||
internal class PluginManager : IInternalDisposableService
|
||||
{
|
||||
/// <summary>
|
||||
/// Default time to wait between plugin unload and plugin assembly unload.
|
||||
|
|
@ -130,7 +130,7 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
(_, _) =>
|
||||
{
|
||||
Service<DalamudInterface>.GetNullable()?.OpenPluginInstallerTo(
|
||||
PluginInstallerWindow.PluginInstallerOpenKind.Changelogs);
|
||||
PluginInstallerOpenKind.Changelogs);
|
||||
}));
|
||||
|
||||
this.configuration.PluginTestingOptIns ??= new();
|
||||
|
|
@ -245,6 +245,11 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
/// Gets or sets a value indicating whether banned plugins will be loaded.
|
||||
/// </summary>
|
||||
public bool LoadBannedPlugins { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a tracker for plugins that are loading at startup, used to display information to the user.
|
||||
/// </summary>
|
||||
public StartupLoadTracker? StartupLoadTracking { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the given repo manifest should be visible to the user.
|
||||
|
|
@ -632,6 +637,15 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
Log.Information($"============= LoadPluginsAsync({logPrefix}) END =============");
|
||||
}
|
||||
|
||||
// Initialize the startup load tracker for all LoadSync plugins
|
||||
{
|
||||
this.StartupLoadTracking = new();
|
||||
foreach (var pluginDef in pluginDefs.Where(x => x.Manifest.LoadSync))
|
||||
{
|
||||
this.StartupLoadTracking.Add(pluginDef.Manifest!.InternalName, pluginDef.Manifest.Name);
|
||||
}
|
||||
}
|
||||
|
||||
var syncPlugins = pluginDefs.Where(def => def.Manifest?.LoadSync == true).ToList();
|
||||
var asyncPlugins = pluginDefs.Where(def => def.Manifest?.LoadSync != true).ToList();
|
||||
var loadTasks = new List<Task>();
|
||||
|
|
@ -702,6 +716,8 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
{
|
||||
Log.Error(ex, "Plugin and profile validation failed!");
|
||||
}
|
||||
|
||||
this.StartupLoadTracking = null;
|
||||
},
|
||||
tokenSource.Token);
|
||||
}
|
||||
|
|
@ -1013,7 +1029,7 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
{
|
||||
var plugin = metadata.InstalledPlugin;
|
||||
|
||||
var workingPluginId = metadata.InstalledPlugin.Manifest.WorkingPluginId;
|
||||
var workingPluginId = metadata.InstalledPlugin.EffectiveWorkingPluginId;
|
||||
if (workingPluginId == Guid.Empty)
|
||||
throw new Exception("Existing plugin had no WorkingPluginId");
|
||||
|
||||
|
|
@ -1163,7 +1179,8 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
}
|
||||
|
||||
// API level - we keep the API before this in the installer to show as "outdated"
|
||||
if (manifest.DalamudApiLevel < DalamudApiLevel - 1 && !this.LoadAllApiLevels)
|
||||
var effectiveApiLevel = this.UseTesting(manifest) && manifest.TestingDalamudApiLevel != null ? manifest.TestingDalamudApiLevel.Value : manifest.DalamudApiLevel;
|
||||
if (effectiveApiLevel < DalamudApiLevel - 1 && !this.LoadAllApiLevels)
|
||||
{
|
||||
Log.Verbose($"API Level: {manifest.InternalName} - {manifest.AssemblyVersion} - {manifest.TestingAssemblyVersion}");
|
||||
return false;
|
||||
|
|
@ -1314,16 +1331,16 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
|
||||
foreach (var installedPlugin in this.InstalledPlugins)
|
||||
{
|
||||
if (installedPlugin.Manifest.WorkingPluginId == Guid.Empty)
|
||||
if (installedPlugin.EffectiveWorkingPluginId == Guid.Empty)
|
||||
throw new Exception($"{(installedPlugin is LocalDevPlugin ? "DevPlugin" : "Plugin")} '{installedPlugin.Manifest.InternalName}' has an empty WorkingPluginId.");
|
||||
|
||||
if (seenIds.Contains(installedPlugin.Manifest.WorkingPluginId))
|
||||
if (seenIds.Contains(installedPlugin.EffectiveWorkingPluginId))
|
||||
{
|
||||
throw new Exception(
|
||||
$"{(installedPlugin is LocalDevPlugin ? "DevPlugin" : "Plugin")} '{installedPlugin.Manifest.InternalName}' has a duplicate WorkingPluginId '{installedPlugin.Manifest.WorkingPluginId}'");
|
||||
$"{(installedPlugin is LocalDevPlugin ? "DevPlugin" : "Plugin")} '{installedPlugin.Manifest.InternalName}' has a duplicate WorkingPluginId '{installedPlugin.EffectiveWorkingPluginId}'");
|
||||
}
|
||||
|
||||
seenIds.Add(installedPlugin.Manifest.WorkingPluginId);
|
||||
seenIds.Add(installedPlugin.EffectiveWorkingPluginId);
|
||||
}
|
||||
|
||||
this.profileManager.ParanoiaValidateProfiles();
|
||||
|
|
@ -1371,7 +1388,7 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
{
|
||||
// Only remove entries from the default profile that are NOT currently tied to an active LocalPlugin
|
||||
var guidsToRemove = this.profileManager.DefaultProfile.Plugins
|
||||
.Where(x => this.InstalledPlugins.All(y => y.Manifest.WorkingPluginId != x.WorkingPluginId))
|
||||
.Where(x => this.InstalledPlugins.All(y => y.EffectiveWorkingPluginId != x.WorkingPluginId))
|
||||
.Select(x => x.WorkingPluginId)
|
||||
.ToArray();
|
||||
|
||||
|
|
@ -1543,9 +1560,9 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
// This will also happen if you are installing a plugin with the installer, and that's intended!
|
||||
// It means that, if you have a profile which has unsatisfied plugins, installing a matching plugin will
|
||||
// enter it into the profiles it can match.
|
||||
if (plugin.Manifest.WorkingPluginId == Guid.Empty)
|
||||
if (plugin.EffectiveWorkingPluginId == Guid.Empty)
|
||||
throw new Exception("Plugin should have a WorkingPluginId at this point");
|
||||
this.profileManager.MigrateProfilesToGuidsForPlugin(plugin.Manifest.InternalName, plugin.Manifest.WorkingPluginId);
|
||||
this.profileManager.MigrateProfilesToGuidsForPlugin(plugin.Manifest.InternalName, plugin.EffectiveWorkingPluginId);
|
||||
|
||||
var wantedByAnyProfile = false;
|
||||
|
||||
|
|
@ -1556,7 +1573,7 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
loadPlugin &= !isBoot;
|
||||
|
||||
var wantsInDefaultProfile =
|
||||
this.profileManager.DefaultProfile.WantsPlugin(plugin.Manifest.WorkingPluginId);
|
||||
this.profileManager.DefaultProfile.WantsPlugin(plugin.EffectiveWorkingPluginId);
|
||||
if (wantsInDefaultProfile == null)
|
||||
{
|
||||
// We don't know about this plugin, so we don't want to do anything here.
|
||||
|
|
@ -1565,7 +1582,7 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
|
||||
// Check if any profile wants this plugin. We need to do this here, since we want to allow loading a dev plugin if a non-default profile wants it active.
|
||||
// Note that this will not add the plugin to the default profile. That's done below in any other case.
|
||||
wantedByAnyProfile = await this.profileManager.GetWantStateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, false, false);
|
||||
wantedByAnyProfile = await this.profileManager.GetWantStateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, false, false);
|
||||
|
||||
// If it is wanted by any other profile, we do want to load it.
|
||||
if (wantedByAnyProfile)
|
||||
|
|
@ -1575,28 +1592,28 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
{
|
||||
// We didn't want this plugin, and StartOnBoot is on. That means we don't want it and it should stay off until manually enabled.
|
||||
Log.Verbose("DevPlugin {Name} disabled and StartOnBoot => disable", plugin.Manifest.InternalName);
|
||||
await this.profileManager.DefaultProfile.AddOrUpdateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, false, false);
|
||||
await this.profileManager.DefaultProfile.AddOrUpdateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, false, false);
|
||||
loadPlugin = false;
|
||||
}
|
||||
else if (wantsInDefaultProfile == true && devPlugin.StartOnBoot)
|
||||
{
|
||||
// We wanted this plugin, and StartOnBoot is on. That means we actually do want it.
|
||||
Log.Verbose("DevPlugin {Name} enabled and StartOnBoot => enable", plugin.Manifest.InternalName);
|
||||
await this.profileManager.DefaultProfile.AddOrUpdateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, true, false);
|
||||
await this.profileManager.DefaultProfile.AddOrUpdateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, true, false);
|
||||
loadPlugin = !doNotLoad;
|
||||
}
|
||||
else if (wantsInDefaultProfile == true && !devPlugin.StartOnBoot)
|
||||
{
|
||||
// We wanted this plugin, but StartOnBoot is off. This means we don't want it anymore.
|
||||
Log.Verbose("DevPlugin {Name} enabled and !StartOnBoot => disable", plugin.Manifest.InternalName);
|
||||
await this.profileManager.DefaultProfile.AddOrUpdateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, false, false);
|
||||
await this.profileManager.DefaultProfile.AddOrUpdateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, false, false);
|
||||
loadPlugin = false;
|
||||
}
|
||||
else if (wantsInDefaultProfile == false && !devPlugin.StartOnBoot)
|
||||
{
|
||||
// We didn't want this plugin, and StartOnBoot is off. We don't want it.
|
||||
Log.Verbose("DevPlugin {Name} disabled and !StartOnBoot => disable", plugin.Manifest.InternalName);
|
||||
await this.profileManager.DefaultProfile.AddOrUpdateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, false, false);
|
||||
await this.profileManager.DefaultProfile.AddOrUpdateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, false, false);
|
||||
loadPlugin = false;
|
||||
}
|
||||
|
||||
|
|
@ -1609,7 +1626,7 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
|
||||
// Plugins that aren't in any profile will be added to the default profile with this call.
|
||||
// We are skipping a double-lookup for dev plugins that are wanted by non-default profiles, as noted above.
|
||||
wantedByAnyProfile = wantedByAnyProfile || await this.profileManager.GetWantStateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, defaultState);
|
||||
wantedByAnyProfile = wantedByAnyProfile || await this.profileManager.GetWantStateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, defaultState);
|
||||
Log.Information("{Name} defaultState: {State} wantedByAnyProfile: {WantedByAny} loadPlugin: {LoadPlugin}", plugin.Manifest.InternalName, defaultState, wantedByAnyProfile, loadPlugin);
|
||||
|
||||
if (loadPlugin)
|
||||
|
|
@ -1683,12 +1700,16 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
|
||||
if (plugin == null)
|
||||
throw new Exception("Plugin was null when adding to list");
|
||||
|
||||
|
||||
lock (this.pluginListLock)
|
||||
{
|
||||
this.installedPluginsList.Add(plugin);
|
||||
}
|
||||
|
||||
// Mark as finished loading
|
||||
if (manifest.LoadSync)
|
||||
this.StartupLoadTracking?.Finish(manifest.InternalName);
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
|
|
@ -1709,7 +1730,15 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
var updates = this.AvailablePlugins
|
||||
.Where(remoteManifest => plugin.Manifest.InternalName == remoteManifest.InternalName)
|
||||
.Where(remoteManifest => plugin.Manifest.InstalledFromUrl == remoteManifest.SourceRepo.PluginMasterUrl || !remoteManifest.SourceRepo.IsThirdParty)
|
||||
.Where(remoteManifest => remoteManifest.DalamudApiLevel == DalamudApiLevel)
|
||||
.Where(remoteManifest =>
|
||||
{
|
||||
var useTesting = this.UseTesting(remoteManifest);
|
||||
var candidateApiLevel = useTesting && remoteManifest.TestingDalamudApiLevel != null
|
||||
? remoteManifest.TestingDalamudApiLevel.Value
|
||||
: remoteManifest.DalamudApiLevel;
|
||||
|
||||
return candidateApiLevel == DalamudApiLevel;
|
||||
})
|
||||
.Select(remoteManifest =>
|
||||
{
|
||||
var useTesting = this.UseTesting(remoteManifest);
|
||||
|
|
@ -1782,7 +1811,16 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
|
||||
using (Timings.Start("PM Load Sync Plugins"))
|
||||
{
|
||||
this.LoadAllPlugins().Wait();
|
||||
var loadAllPlugins = Task.Run(this.LoadAllPlugins);
|
||||
|
||||
// We wait for all blocking services and tasks to finish before kicking off the main thread in any mode.
|
||||
// This means that we don't want to block here if this stupid thing isn't enabled.
|
||||
if (this.configuration.IsResumeGameAfterPluginLoad)
|
||||
{
|
||||
Log.Verbose("Waiting for all plugins to load before resuming game");
|
||||
loadAllPlugins.Wait();
|
||||
}
|
||||
|
||||
Log.Information("[T3] PML OK!");
|
||||
}
|
||||
|
||||
|
|
@ -1793,6 +1831,63 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
Log.Error(ex, "Plugin load failed");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple class that tracks the internal names and public names of plugins that we are planning to load at startup,
|
||||
/// and are still actively loading.
|
||||
/// </summary>
|
||||
public class StartupLoadTracker
|
||||
{
|
||||
private readonly Dictionary<string, string> internalToPublic = new();
|
||||
private readonly ConcurrentBag<string> allInternalNames = new();
|
||||
private readonly ConcurrentBag<string> finishedInternalNames = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating the total load progress.
|
||||
/// </summary>
|
||||
public float Progress => (float)this.finishedInternalNames.Count / this.allInternalNames.Count;
|
||||
|
||||
/// <summary>
|
||||
/// Calculate a set of internal names that are still pending.
|
||||
/// </summary>
|
||||
/// <returns>Set of pending InternalNames.</returns>
|
||||
public IReadOnlySet<string> GetPendingInternalNames()
|
||||
{
|
||||
var pending = new HashSet<string>(this.allInternalNames);
|
||||
pending.ExceptWith(this.finishedInternalNames);
|
||||
return pending;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Track a new plugin.
|
||||
/// </summary>
|
||||
/// <param name="internalName">The plugin's internal name.</param>
|
||||
/// <param name="publicName">The plugin's public name.</param>
|
||||
public void Add(string internalName, string publicName)
|
||||
{
|
||||
this.internalToPublic[internalName] = publicName;
|
||||
this.allInternalNames.Add(internalName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mark a plugin as finished loading.
|
||||
/// </summary>
|
||||
/// <param name="internalName">The internal name of the plugin.</param>
|
||||
public void Finish(string internalName)
|
||||
{
|
||||
this.finishedInternalNames.Add(internalName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the public name for a given internal name.
|
||||
/// </summary>
|
||||
/// <param name="internalName">The internal name to look up.</param>
|
||||
/// <returns>The public name.</returns>
|
||||
public string? GetPublicName(string internalName)
|
||||
{
|
||||
return this.internalToPublic.TryGetValue(internalName, out var publicName) ? publicName : null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Locs
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
|
@ -184,8 +183,8 @@ internal class ProfileManager : IServiceType
|
|||
var installedPlugin = pm.InstalledPlugins.FirstOrDefault(x => x.Manifest.InternalName == plugin.InternalName);
|
||||
if (installedPlugin != null)
|
||||
{
|
||||
Log.Information("Satisfying plugin {InternalName} for profile {Name} with {Guid}", plugin.InternalName, newModel.Name, installedPlugin.Manifest.WorkingPluginId);
|
||||
plugin.WorkingPluginId = installedPlugin.Manifest.WorkingPluginId;
|
||||
Log.Information("Satisfying plugin {InternalName} for profile {Name} with {Guid}", plugin.InternalName, newModel.Name, installedPlugin.EffectiveWorkingPluginId);
|
||||
plugin.WorkingPluginId = installedPlugin.EffectiveWorkingPluginId;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -238,7 +237,7 @@ internal class ProfileManager : IServiceType
|
|||
var pm = Service<PluginManager>.Get();
|
||||
foreach (var installedPlugin in pm.InstalledPlugins)
|
||||
{
|
||||
var wantThis = wantActive.Any(x => x.WorkingPluginId == installedPlugin.Manifest.WorkingPluginId);
|
||||
var wantThis = wantActive.Any(x => x.WorkingPluginId == installedPlugin.EffectiveWorkingPluginId);
|
||||
switch (wantThis)
|
||||
{
|
||||
case true when !installedPlugin.IsLoaded:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using System;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dalamud.Plugin.Internal.Types;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
|
@ -51,14 +50,6 @@ internal class LocalDevPlugin : LocalPlugin, IDisposable
|
|||
Log.Verbose("{InternalName} was assigned new devPlugin GUID {Guid}", this.InternalName, this.devSettings.WorkingPluginId);
|
||||
configuration.QueueSave();
|
||||
}
|
||||
|
||||
// If the ID in the manifest is wrong, force the good one
|
||||
if (this.DevImposedWorkingPluginId != this.manifest.WorkingPluginId)
|
||||
{
|
||||
Debug.Assert(this.DevImposedWorkingPluginId != Guid.Empty, "Empty guid for devPlugin");
|
||||
this.manifest.WorkingPluginId = this.DevImposedWorkingPluginId;
|
||||
this.SaveManifest("dev imposed working plugin id");
|
||||
}
|
||||
|
||||
if (this.AutomaticReload)
|
||||
{
|
||||
|
|
@ -100,7 +91,10 @@ internal class LocalDevPlugin : LocalPlugin, IDisposable
|
|||
/// Gets an ID uniquely identifying this specific instance of a devPlugin.
|
||||
/// </summary>
|
||||
public Guid DevImposedWorkingPluginId => this.devSettings.WorkingPluginId;
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Guid EffectiveWorkingPluginId => this.DevImposedWorkingPluginId;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of validation problems that have been dismissed by the user.
|
||||
/// </summary>
|
||||
|
|
@ -149,6 +143,23 @@ internal class LocalDevPlugin : LocalPlugin, IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reload the manifest if it exists, to update possible changes.
|
||||
/// </summary>
|
||||
/// <exception cref="Exception">Thrown if the manifest could not be loaded.</exception>
|
||||
public void ReloadManifest()
|
||||
{
|
||||
var manifestPath = LocalPluginManifest.GetManifestFile(this.DllFile);
|
||||
if (manifestPath.Exists)
|
||||
this.manifest = LocalPluginManifest.Load(manifestPath) ?? throw new Exception("Could not reload manifest.");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnPreReload()
|
||||
{
|
||||
this.ReloadManifest();
|
||||
}
|
||||
|
||||
private void OnFileChanged(object sender, FileSystemEventArgs args)
|
||||
{
|
||||
var current = Interlocked.Increment(ref this.reloadCounter);
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ internal class LocalPlugin : IDisposable
|
|||
}
|
||||
|
||||
// Create an installation instance ID for this plugin, if it doesn't have one yet
|
||||
if (this.manifest.WorkingPluginId == Guid.Empty)
|
||||
if (this.manifest.WorkingPluginId == Guid.Empty && !this.IsDev)
|
||||
{
|
||||
this.manifest.WorkingPluginId = Guid.NewGuid();
|
||||
|
||||
|
|
@ -162,12 +162,12 @@ internal class LocalPlugin : IDisposable
|
|||
/// INCLUDES the default profile.
|
||||
/// </summary>
|
||||
public bool IsWantedByAnyProfile =>
|
||||
Service<ProfileManager>.Get().GetWantStateAsync(this.manifest.WorkingPluginId, this.Manifest.InternalName, false, false).GetAwaiter().GetResult();
|
||||
Service<ProfileManager>.Get().GetWantStateAsync(this.EffectiveWorkingPluginId, this.Manifest.InternalName, false, false).GetAwaiter().GetResult();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this plugin's API level is out of date.
|
||||
/// </summary>
|
||||
public bool IsOutdated => this.manifest.DalamudApiLevel < PluginManager.DalamudApiLevel;
|
||||
public bool IsOutdated => this.manifest.EffectiveApiLevel < PluginManager.DalamudApiLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the plugin is for testing use only.
|
||||
|
|
@ -215,6 +215,11 @@ internal class LocalPlugin : IDisposable
|
|||
/// </summary>
|
||||
public Version EffectiveVersion => this.manifest.EffectiveVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the effective working plugin ID for this plugin.
|
||||
/// </summary>
|
||||
public virtual Guid EffectiveWorkingPluginId => this.manifest.WorkingPluginId;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the service scope for this plugin.
|
||||
/// </summary>
|
||||
|
|
@ -271,11 +276,8 @@ internal class LocalPlugin : IDisposable
|
|||
await this.pluginLoadStateLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
if (reloading && this.IsDev)
|
||||
{
|
||||
// Reload the manifest in-case there were changes here too.
|
||||
this.ReloadManifest();
|
||||
}
|
||||
if (reloading)
|
||||
this.OnPreReload();
|
||||
|
||||
// If we reload a plugin we don't want to delete it. Makes sense, right?
|
||||
if (this.manifest.ScheduledForDeletion)
|
||||
|
|
@ -318,8 +320,8 @@ internal class LocalPlugin : IDisposable
|
|||
if (this.manifest.ApplicableVersion < dalamud.StartInfo.GameVersion)
|
||||
throw new PluginPreconditionFailedException($"Unable to load {this.Name}, game is newer than applicable version {this.manifest.ApplicableVersion}");
|
||||
|
||||
if (this.manifest.DalamudApiLevel < PluginManager.DalamudApiLevel && !pluginManager.LoadAllApiLevels)
|
||||
throw new PluginPreconditionFailedException($"Unable to load {this.Name}, incompatible API level {this.manifest.DalamudApiLevel}");
|
||||
if (this.manifest.EffectiveApiLevel < PluginManager.DalamudApiLevel && !pluginManager.LoadAllApiLevels)
|
||||
throw new PluginPreconditionFailedException($"Unable to load {this.Name}, incompatible API level {this.manifest.EffectiveApiLevel}");
|
||||
|
||||
// We might want to throw here?
|
||||
if (!this.IsWantedByAnyProfile)
|
||||
|
|
@ -578,24 +580,6 @@ internal class LocalPlugin : IDisposable
|
|||
this.SaveManifest("scheduling for deletion");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reload the manifest if it exists, preserve the internal Disabled state.
|
||||
/// </summary>
|
||||
public void ReloadManifest()
|
||||
{
|
||||
var manifestPath = LocalPluginManifest.GetManifestFile(this.DllFile);
|
||||
if (manifestPath.Exists)
|
||||
{
|
||||
// Save some state that we do actually want to carry over
|
||||
var guid = this.manifest.WorkingPluginId;
|
||||
|
||||
this.manifest = LocalPluginManifest.Load(manifestPath) ?? throw new Exception("Could not reload manifest.");
|
||||
this.manifest.WorkingPluginId = guid;
|
||||
|
||||
this.SaveManifest("dev reload");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the repository this plugin was installed from.
|
||||
/// </summary>
|
||||
|
|
@ -620,6 +604,13 @@ internal class LocalPlugin : IDisposable
|
|||
/// </summary>
|
||||
/// <param name="reason">Why it should be saved.</param>
|
||||
protected void SaveManifest(string reason) => this.manifest.Save(this.manifestFile, reason);
|
||||
|
||||
/// <summary>
|
||||
/// Called before a plugin is reloaded.
|
||||
/// </summary>
|
||||
protected virtual void OnPreReload()
|
||||
{
|
||||
}
|
||||
|
||||
private static void SetupLoaderConfig(LoaderConfig config)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Plugin.Internal.Types.Manifest;
|
||||
namespace Dalamud.Plugin.Internal.Types.Manifest;
|
||||
|
||||
/// <summary>
|
||||
/// Public interface for the local plugin manifest.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Dalamud.Plugin.Internal.Types.Manifest;
|
||||
|
||||
|
|
@ -64,11 +63,17 @@ public interface IPluginManifest
|
|||
public List<string>? Tags { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the API level of this plugin. For the current API level, please see <see cref="PluginManager.DalamudApiLevel"/>
|
||||
/// for the currently used API level.
|
||||
/// Gets the API level of this plugin.
|
||||
/// For the current API level, please see <see cref="PluginManager.DalamudApiLevel"/> for the currently used API level.
|
||||
/// </summary>
|
||||
public int DalamudApiLevel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the API level of the plugin's testing variant.
|
||||
/// For the current API level, please see <see cref="PluginManager.DalamudApiLevel"/> for the currently used API level.
|
||||
/// </summary>
|
||||
public int? TestingDalamudApiLevel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of downloads this plugin has.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
using Dalamud.Utility;
|
||||
|
|
@ -46,6 +45,11 @@ internal record LocalPluginManifest : PluginManifest, ILocalPluginManifest
|
|||
/// </summary>
|
||||
public Version EffectiveVersion => this.Testing && this.TestingAssemblyVersion != null ? this.TestingAssemblyVersion : this.AssemblyVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the effective API level of this plugin.
|
||||
/// </summary>
|
||||
public int EffectiveApiLevel => this.Testing && this.TestingDalamudApiLevel != null ? this.TestingDalamudApiLevel.Value : this.DalamudApiLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Save a plugin manifest to file.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -79,6 +79,10 @@ internal record PluginManifest : IPluginManifest
|
|||
[JsonProperty]
|
||||
public int DalamudApiLevel { get; init; } = PluginManager.DalamudApiLevel;
|
||||
|
||||
/// <inheritdoc/>
|
||||
[JsonProperty]
|
||||
public int? TestingDalamudApiLevel { get; init; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
[JsonProperty]
|
||||
public long DownloadCount { get; init; }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Dalamud.Plugin.Internal.Types;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Plugin.Ipc.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Plugin.Ipc.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Plugin.Ipc.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Plugin.Ipc.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Plugin.Ipc.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Plugin.Ipc.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using System;
|
||||
|
||||
using Dalamud.Plugin.Ipc.Internal;
|
||||
|
||||
#pragma warning disable SA1402 // File may only contain a single type
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using System;
|
||||
|
||||
using Dalamud.Plugin.Ipc.Internal;
|
||||
|
||||
#pragma warning disable SA1402 // File may only contain a single type
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis;
|
|||
using System.Linq;
|
||||
|
||||
using Dalamud.Plugin.Ipc.Exceptions;
|
||||
|
||||
using Serilog;
|
||||
|
||||
namespace Dalamud.Plugin.Ipc.Internal;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using Dalamud.Game.Addon;
|
||||
using Dalamud.Game.Addon.Events;
|
||||
using Dalamud.Game.Addon.Events;
|
||||
|
||||
namespace Dalamud.Plugin.Services;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Dalamud.Game.Addon;
|
||||
using Dalamud.Game.Addon.Lifecycle;
|
||||
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
using Dalamud.Game.ClientState.Buddy;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Dalamud.Game.Gui;
|
||||
using Dalamud.Game.Text;
|
||||
|
|
@ -15,39 +15,39 @@ public interface IChatGui
|
|||
/// A delegate type used with the <see cref="ChatGui.ChatMessage"/> event.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of chat.</param>
|
||||
/// <param name="senderId">The sender ID.</param>
|
||||
/// <param name="timestamp">The timestamp of when the message was sent.</param>
|
||||
/// <param name="sender">The sender name.</param>
|
||||
/// <param name="message">The message sent.</param>
|
||||
/// <param name="isHandled">A value indicating whether the message was handled or should be propagated.</param>
|
||||
public delegate void OnMessageDelegate(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled);
|
||||
public delegate void OnMessageDelegate(XivChatType type, int timestamp, ref SeString sender, ref SeString message, ref bool isHandled);
|
||||
|
||||
/// <summary>
|
||||
/// A delegate type used with the <see cref="ChatGui.CheckMessageHandled"/> event.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of chat.</param>
|
||||
/// <param name="senderId">The sender ID.</param>
|
||||
/// <param name="timestamp">The timestamp of when the message was sent.</param>
|
||||
/// <param name="sender">The sender name.</param>
|
||||
/// <param name="message">The message sent.</param>
|
||||
/// <param name="isHandled">A value indicating whether the message was handled or should be propagated.</param>
|
||||
public delegate void OnCheckMessageHandledDelegate(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled);
|
||||
public delegate void OnCheckMessageHandledDelegate(XivChatType type, int timestamp, ref SeString sender, ref SeString message, ref bool isHandled);
|
||||
|
||||
/// <summary>
|
||||
/// A delegate type used with the <see cref="ChatGui.ChatMessageHandled"/> event.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of chat.</param>
|
||||
/// <param name="senderId">The sender ID.</param>
|
||||
/// <param name="timestamp">The timestamp of when the message was sent.</param>
|
||||
/// <param name="sender">The sender name.</param>
|
||||
/// <param name="message">The message sent.</param>
|
||||
public delegate void OnMessageHandledDelegate(XivChatType type, uint senderId, SeString sender, SeString message);
|
||||
public delegate void OnMessageHandledDelegate(XivChatType type, int timestamp, SeString sender, SeString message);
|
||||
|
||||
/// <summary>
|
||||
/// A delegate type used with the <see cref="ChatGui.ChatMessageUnhandled"/> event.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of chat.</param>
|
||||
/// <param name="senderId">The sender ID.</param>
|
||||
/// <param name="timestamp">The timestamp of when the message was sent.</param>
|
||||
/// <param name="sender">The sender name.</param>
|
||||
/// <param name="message">The message sent.</param>
|
||||
public delegate void OnMessageUnhandledDelegate(XivChatType type, uint senderId, SeString sender, SeString message);
|
||||
public delegate void OnMessageUnhandledDelegate(XivChatType type, int timestamp, SeString sender, SeString message);
|
||||
|
||||
/// <summary>
|
||||
/// Event that will be fired when a chat message is sent to chat by the game.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using System;
|
||||
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
|
||||
namespace Dalamud.Plugin.Services;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Dalamud.Game.Gui.Dtr;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Utility;
|
||||
|
||||
namespace Dalamud.Plugin.Services;
|
||||
|
||||
|
|
@ -10,6 +11,11 @@ namespace Dalamud.Plugin.Services;
|
|||
/// </summary>
|
||||
public interface IDtrBar
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a read-only list of all DTR bar entries.
|
||||
/// </summary>
|
||||
public IReadOnlyList<IReadOnlyDtrBarEntry> Entries { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get a DTR bar entry.
|
||||
/// This allows you to add your own text, and users to sort it.
|
||||
|
|
@ -18,6 +24,7 @@ public interface IDtrBar
|
|||
/// <param name="text">The text the entry shows.</param>
|
||||
/// <returns>The entry object used to update, hide and remove the entry.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown when an entry with the specified title exists.</exception>
|
||||
[Api10ToDo("Return IDtrBarEntry instead of DtrBarEntry")]
|
||||
public DtrBarEntry Get(string title, SeString? text = null);
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Dalamud.Game.Config;
|
||||
using Dalamud.Plugin.Internal.Types;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using System.Numerics;
|
||||
|
||||
using Dalamud.Game.Gui;
|
||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ public interface IGameInteropProvider
|
|||
/// <param name="detour">Callback function. Delegate must have a same original function prototype.</param>
|
||||
/// <returns>The hook with the supplied parameters.</returns>
|
||||
/// <typeparam name="T">Delegate of detour.</typeparam>
|
||||
public Hook<T> HookFromFunctionPointerVariable<T>(IntPtr address, T detour) where T : Delegate;
|
||||
public Hook<T> HookFromFunctionPointerVariable<T>(nint address, T detour) where T : Delegate;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a hook by rewriting import table address.
|
||||
|
|
@ -85,7 +85,31 @@ public interface IGameInteropProvider
|
|||
/// <param name="backend">Hooking library to use.</param>
|
||||
/// <returns>The hook with the supplied parameters.</returns>
|
||||
/// <typeparam name="T">Delegate of detour.</typeparam>
|
||||
Hook<T> HookFromAddress<T>(IntPtr procAddress, T detour, HookBackend backend = HookBackend.Automatic) where T : Delegate;
|
||||
Hook<T> HookFromAddress<T>(nint procAddress, T detour, HookBackend backend = HookBackend.Automatic) where T : Delegate;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a hook. Hooking address is inferred by calling to GetProcAddress() function.
|
||||
/// The hook is not activated until Enable() method is called.
|
||||
/// Please do not use MinHook unless you have thoroughly troubleshot why Reloaded does not work.
|
||||
/// </summary>
|
||||
/// <param name="procAddress">A memory address to install a hook.</param>
|
||||
/// <param name="detour">Callback function. Delegate must have a same original function prototype.</param>
|
||||
/// <param name="backend">Hooking library to use.</param>
|
||||
/// <returns>The hook with the supplied parameters.</returns>
|
||||
/// <typeparam name="T">Delegate of detour.</typeparam>
|
||||
Hook<T> HookFromAddress<T>(nuint procAddress, T detour, HookBackend backend = HookBackend.Automatic) where T : Delegate;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a hook. Hooking address is inferred by calling to GetProcAddress() function.
|
||||
/// The hook is not activated until Enable() method is called.
|
||||
/// Please do not use MinHook unless you have thoroughly troubleshot why Reloaded does not work.
|
||||
/// </summary>
|
||||
/// <param name="procAddress">A memory address to install a hook.</param>
|
||||
/// <param name="detour">Callback function. Delegate must have a same original function prototype.</param>
|
||||
/// <param name="backend">Hooking library to use.</param>
|
||||
/// <returns>The hook with the supplied parameters.</returns>
|
||||
/// <typeparam name="T">Delegate of detour.</typeparam>
|
||||
unsafe Hook<T> HookFromAddress<T>(void* procAddress, T detour, HookBackend backend = HookBackend.Automatic) where T : Delegate;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a hook from a signature into the Dalamud target module.
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ public interface IObjectTable : IEnumerable<GameObject>
|
|||
/// <summary>
|
||||
/// Search for a game object by their Object ID.
|
||||
/// </summary>
|
||||
/// <param name="objectId">Object ID to find.</param>
|
||||
/// <param name="gameObjectId">Object ID to find.</param>
|
||||
/// <returns>A game object or null.</returns>
|
||||
public GameObject? SearchById(ulong objectId);
|
||||
public GameObject? SearchById(ulong gameObjectId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of the game object at the specified index of the object table.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using Serilog;
|
||||
using Serilog.Events;
|
||||
using Serilog.Events;
|
||||
|
||||
#pragma warning disable CS1573 // See https://github.com/dotnet/roslyn/issues/40325
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Dalamud.Game;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Internal;
|
||||
using ImGuiScene;
|
||||
|
||||
namespace Dalamud.Plugin.Services;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue