mirror of
https://github.com/goatcorp/Dalamud.git
synced 2026-01-01 05:13:40 +01:00
Add "loading dialog" for service init, unify blocking logic (#1779)
* wip * hacky fix for overlapping event text in profiler * move IsResumeGameAfterPluginLoad logic to PluginManager * fix some warnings * handle exceptions properly * remove ability to cancel, rename button to "hide" instead * undo Dalamud.Service refactor for now * warnings * add explainer, show which plugins are still loading * add some text if loading takes more than 3 minutes * undo wrong CS merge
This commit is contained in:
parent
93adea0ac9
commit
448b0d16ea
294 changed files with 560 additions and 506 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Plugin;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
using System;
|
||||
|
||||
using Dalamud.Utility;
|
||||
using Dalamud.Utility;
|
||||
|
||||
namespace Dalamud.Plugin;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -1689,6 +1704,10 @@ internal partial class PluginManager : IInternalDisposableService
|
|||
this.installedPluginsList.Add(plugin);
|
||||
}
|
||||
|
||||
// Mark as finished loading
|
||||
if (manifest.LoadSync)
|
||||
this.StartupLoadTracking?.Finish(manifest.InternalName);
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
|
|
@ -1782,7 +1801,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 +1821,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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -4,11 +4,9 @@ using System.Reflection;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Dalamud.Common.Game;
|
||||
using Dalamud.Configuration.Internal;
|
||||
using Dalamud.Game;
|
||||
using Dalamud.Game.Gui.Dtr;
|
||||
using Dalamud.Interface.GameFonts;
|
||||
using Dalamud.Interface.Internal;
|
||||
using Dalamud.IoC.Internal;
|
||||
using Dalamud.Logging.Internal;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
using Dalamud.Utility;
|
||||
|
|
|
|||
|
|
@ -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,5 +1,3 @@
|
|||
using System;
|
||||
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
|
||||
namespace Dalamud.Plugin.Services;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Dalamud.Game.Gui.Dtr;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,5 +1,4 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
|
||||
using Dalamud.Interface.Internal;
|
||||
using Lumina.Data.Files;
|
||||
|
|
|
|||
|
|
@ -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