Merge branch 'refs/heads/master' into apiX

# Conflicts:
#	Dalamud/Game/Libc/LibcFunction.cs
#	Dalamud/Game/Libc/LibcFunctionAddressResolver.cs
#	Dalamud/Game/Libc/OwnedStdString.cs
#	Dalamud/Game/Libc/StdString.cs
#	Dalamud/Interface/UiBuilder.cs
This commit is contained in:
Kaz Wolfe 2024-04-28 11:54:54 -07:00
commit b32ed39826
No known key found for this signature in database
GPG key ID: 258813F53A16EBB4
297 changed files with 768 additions and 543 deletions

View file

@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
@ -25,7 +24,6 @@ using Dalamud.Plugin.Internal.Types.Manifest;
using Dalamud.Plugin.Ipc;
using Dalamud.Plugin.Ipc.Exceptions;
using Dalamud.Plugin.Ipc.Internal;
using Dalamud.Utility;
namespace Dalamud.Plugin;

View file

@ -1,5 +1,3 @@
using System;
namespace Dalamud.Plugin;
/// <summary>

View file

@ -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);

View file

@ -1,5 +1,3 @@
using System;
namespace Dalamud.Plugin.Internal.Exceptions;
/// <summary>

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -22,7 +22,6 @@ using Dalamud.Game.Text.SeStringHandling.Payloads;
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 +41,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.
@ -245,6 +244,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 +636,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 +715,8 @@ internal partial class PluginManager : IInternalDisposableService
{
Log.Error(ex, "Plugin and profile validation failed!");
}
this.StartupLoadTracking = null;
},
tokenSource.Token);
}
@ -1163,7 +1178,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;
@ -1683,12 +1699,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 +1729,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 +1810,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 +1830,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
{

View file

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

View file

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;

View file

@ -1,5 +1,3 @@
using System;
using Newtonsoft.Json;
namespace Dalamud.Plugin.Internal.Types;

View file

@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

View file

@ -167,7 +167,7 @@ internal class LocalPlugin : IDisposable
/// <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.
@ -318,8 +318,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)

View file

@ -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.

View file

@ -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>

View file

@ -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>

View file

@ -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; }

View file

@ -1,4 +1,3 @@
using System;
using System.IO;
namespace Dalamud.Plugin.Internal.Types;

View file

@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;

View file

@ -1,5 +1,3 @@
using System;
namespace Dalamud.Plugin.Ipc.Exceptions;
/// <summary>

View file

@ -1,5 +1,3 @@
using System;
namespace Dalamud.Plugin.Ipc.Exceptions;
/// <summary>

View file

@ -1,5 +1,3 @@
using System;
namespace Dalamud.Plugin.Ipc.Exceptions;
/// <summary>

View file

@ -1,5 +1,3 @@
using System;
namespace Dalamud.Plugin.Ipc.Exceptions;
/// <summary>

View file

@ -1,5 +1,3 @@
using System;
namespace Dalamud.Plugin.Ipc.Exceptions;
/// <summary>

View file

@ -1,5 +1,3 @@
using System;
namespace Dalamud.Plugin.Ipc.Exceptions;
/// <summary>

View file

@ -1,5 +1,3 @@
using System;
using Dalamud.Plugin.Ipc.Internal;
#pragma warning disable SA1402 // File may only contain a single type

View file

@ -1,5 +1,3 @@
using System;
using Dalamud.Plugin.Ipc.Internal;
#pragma warning disable SA1402 // File may only contain a single type

View file

@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Dalamud.Plugin.Ipc.Exceptions;
using Serilog;
namespace Dalamud.Plugin.Ipc.Internal;

View file

@ -1,5 +1,4 @@
using Dalamud.Game.Addon;
using Dalamud.Game.Addon.Events;
using Dalamud.Game.Addon.Events;
namespace Dalamud.Plugin.Services;

View file

@ -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;

View file

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Dalamud.Game.ClientState.Buddy;

View file

@ -1,5 +1,3 @@
using System;
using Dalamud.Game.ClientState.Objects.SubKinds;
namespace Dalamud.Plugin.Services;

View file

@ -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>

View file

@ -1,5 +1,4 @@
using System.Diagnostics;
using System.Threading.Tasks;
using Dalamud.Game.Config;
using Dalamud.Plugin.Internal.Types;

View file

@ -1,5 +1,4 @@
using System;
using System.Numerics;
using System.Numerics;
using Dalamud.Game.Gui;
using Dalamud.Game.Text.SeStringHandling.Payloads;

View file

@ -1,5 +1,4 @@
using Serilog;
using Serilog.Events;
using Serilog.Events;
#pragma warning disable CS1573 // See https://github.com/dotnet/roslyn/issues/40325

View file

@ -1,5 +1,4 @@
using System;
using System.Diagnostics;
using System.Diagnostics;
namespace Dalamud.Game;

View file

@ -1,5 +1,4 @@
using System;
using System.IO;
using System.IO;
using Dalamud.Interface.Internal;
using Lumina.Data.Files;

View file

@ -2,7 +2,6 @@
using Dalamud.Interface;
using Dalamud.Interface.Internal;
using ImGuiScene;
namespace Dalamud.Plugin.Services;