From 5419f51942bdba7f1ed5bc8238cd5458ec7697c3 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Fri, 17 Feb 2023 19:12:44 +0100 Subject: [PATCH] DI: Only initialize one renderer at once --- Pal.Client/DependencyInjectionContext.cs | 15 ++++-- Pal.Client/Plugin.cs | 20 ++++---- Pal.Client/Rendering/ELayer.cs | 1 + Pal.Client/Rendering/IRenderer.cs | 10 ++-- Pal.Client/Rendering/RenderAdapter.cs | 53 ++++++++++++++++++---- Pal.Client/Rendering/SimpleRenderer.cs | 3 ++ Pal.Client/Rendering/SplatoonRenderer.cs | 11 ++++- Pal.Client/Scheduled/QueuedConfigUpdate.cs | 13 +++++- 8 files changed, 94 insertions(+), 32 deletions(-) diff --git a/Pal.Client/DependencyInjectionContext.cs b/Pal.Client/DependencyInjectionContext.cs index feaf1a8..ea2f1ce 100644 --- a/Pal.Client/DependencyInjectionContext.cs +++ b/Pal.Client/DependencyInjectionContext.cs @@ -48,6 +48,7 @@ namespace Pal.Client private readonly string _sqliteConnectionString; private readonly CancellationTokenSource _initCts = new(); private ServiceProvider? _serviceProvider; + private Plugin? _plugin; public string Name => Localization.Palace_Pal; @@ -122,8 +123,8 @@ namespace Pal.Client services.AddSingleton(); // these should maybe be scoped - services.AddSingleton(); - services.AddSingleton(); + services.AddScoped(); + services.AddScoped(); services.AddSingleton(); // queue handling @@ -199,7 +200,7 @@ namespace Pal.Client _serviceProvider.GetRequiredService(); token.ThrowIfCancellationRequested(); - _serviceProvider.GetRequiredService(); + _plugin = new Plugin(pluginInterface, _serviceProvider); _logger.LogInformation("Async init complete"); } @@ -226,15 +227,23 @@ namespace Pal.Client // ensure we're not calling dispose recursively on ourselves if (_serviceProvider != null) { + _logger.LogInformation("Disposing DI Context"); + ServiceProvider serviceProvider = _serviceProvider; _serviceProvider = null; + _plugin?.Dispose(); + _plugin = null; serviceProvider.Dispose(); // ensure we're not keeping the file open longer than the plugin is loaded using (SqliteConnection sqliteConnection = new(_sqliteConnectionString)) SqliteConnection.ClearPool(sqliteConnection); } + else + { + _logger.LogDebug("DI context is already disposed"); + } } } } diff --git a/Pal.Client/Plugin.cs b/Pal.Client/Plugin.cs index f30ff6b..f8fc54b 100644 --- a/Pal.Client/Plugin.cs +++ b/Pal.Client/Plugin.cs @@ -8,6 +8,7 @@ using System.Linq; using Pal.Client.Properties; using ECommons; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Pal.Client.Configuration; namespace Pal.Client @@ -19,24 +20,23 @@ namespace Pal.Client /// internal sealed class Plugin : IDisposable { - private readonly IServiceProvider _serviceProvider; private readonly DalamudPluginInterface _pluginInterface; + private readonly IServiceProvider _serviceProvider; + private readonly ILogger _logger; private readonly IPalacePalConfiguration _configuration; private readonly RenderAdapter _renderAdapter; private readonly WindowSystem _windowSystem; public Plugin( - IServiceProvider serviceProvider, DalamudPluginInterface pluginInterface, - IPalacePalConfiguration configuration, - RenderAdapter renderAdapter, - WindowSystem windowSystem) + IServiceProvider serviceProvider) { - _serviceProvider = serviceProvider; _pluginInterface = pluginInterface; - _configuration = configuration; - _renderAdapter = renderAdapter; - _windowSystem = windowSystem; + _serviceProvider = serviceProvider; + _logger = _serviceProvider.GetRequiredService>(); + _configuration = serviceProvider.GetRequiredService(); + _renderAdapter = serviceProvider.GetRequiredService(); + _windowSystem = serviceProvider.GetRequiredService(); LanguageChanged(pluginInterface.UiLanguage); @@ -65,6 +65,8 @@ namespace Pal.Client private void LanguageChanged(string languageCode) { + _logger.LogInformation("Language set to '{Language}'", languageCode); + Localization.Culture = new CultureInfo(languageCode); _windowSystem.Windows.OfType() .Each(w => w.LanguageChanged()); diff --git a/Pal.Client/Rendering/ELayer.cs b/Pal.Client/Rendering/ELayer.cs index be7881e..1027f27 100644 --- a/Pal.Client/Rendering/ELayer.cs +++ b/Pal.Client/Rendering/ELayer.cs @@ -4,5 +4,6 @@ { TrapHoard, RegularCoffers, + Test, } } diff --git a/Pal.Client/Rendering/IRenderer.cs b/Pal.Client/Rendering/IRenderer.cs index 9ecf7d2..68ecf00 100644 --- a/Pal.Client/Rendering/IRenderer.cs +++ b/Pal.Client/Rendering/IRenderer.cs @@ -1,15 +1,13 @@ -using ImGuiNET; -using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; using System.Numerics; -using System.Text; -using System.Threading.Tasks; +using Pal.Client.Configuration; namespace Pal.Client.Rendering { internal interface IRenderer { + ERenderer GetConfigValue(); + void SetLayer(ELayer layer, IReadOnlyList elements); void ResetLayer(ELayer layer); diff --git a/Pal.Client/Rendering/RenderAdapter.cs b/Pal.Client/Rendering/RenderAdapter.cs index 4afca66..338bb51 100644 --- a/Pal.Client/Rendering/RenderAdapter.cs +++ b/Pal.Client/Rendering/RenderAdapter.cs @@ -1,25 +1,55 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Numerics; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Pal.Client.Configuration; namespace Pal.Client.Rendering { - internal sealed class RenderAdapter : IRenderer + internal sealed class RenderAdapter : IRenderer, IDisposable { - private readonly SimpleRenderer _simpleRenderer; - private readonly SplatoonRenderer _splatoonRenderer; + private readonly IServiceScopeFactory _serviceScopeFactory; + private readonly ILogger _logger; private readonly IPalacePalConfiguration _configuration; - public RenderAdapter(SimpleRenderer simpleRenderer, SplatoonRenderer splatoonRenderer, IPalacePalConfiguration configuration) + private IServiceScope? _renderScope; + + public RenderAdapter(IServiceScopeFactory serviceScopeFactory, ILogger logger, + IPalacePalConfiguration configuration) { - _simpleRenderer = simpleRenderer; - _splatoonRenderer = splatoonRenderer; + _serviceScopeFactory = serviceScopeFactory; + _logger = logger; _configuration = configuration; + + Implementation = Recreate(null); } - public IRenderer Implementation => _configuration.Renderer.SelectedRenderer == ERenderer.Splatoon - ? _splatoonRenderer - : _simpleRenderer; + private IRenderer Recreate(ERenderer? currentRenderer) + { + ERenderer targetRenderer = _configuration.Renderer.SelectedRenderer; + if (targetRenderer == currentRenderer) + return Implementation; + + _renderScope?.Dispose(); + + _logger.LogInformation("Selected new renderer: {Renderer}", _configuration.Renderer.SelectedRenderer); + _renderScope = _serviceScopeFactory.CreateScope(); + if (targetRenderer == ERenderer.Splatoon) + return _renderScope.ServiceProvider.GetRequiredService(); + else + return _renderScope.ServiceProvider.GetRequiredService(); + } + + public void ConfigUpdated() + { + Implementation = Recreate(Implementation.GetConfigValue()); + } + + public void Dispose() + => _renderScope?.Dispose(); + + public IRenderer Implementation { get; private set; } public void SetLayer(ELayer layer, IReadOnlyList elements) => Implementation.SetLayer(layer, elements); @@ -35,5 +65,8 @@ namespace Pal.Client.Rendering if (Implementation is SimpleRenderer sr) sr.DrawLayers(); } + + public ERenderer GetConfigValue() + => throw new NotImplementedException(); } } diff --git a/Pal.Client/Rendering/SimpleRenderer.cs b/Pal.Client/Rendering/SimpleRenderer.cs index 675426a..14fd0bc 100644 --- a/Pal.Client/Rendering/SimpleRenderer.cs +++ b/Pal.Client/Rendering/SimpleRenderer.cs @@ -146,6 +146,9 @@ namespace Pal.Client.Rendering ImGui.GetWindowDrawList().PathClear(); } + public ERenderer GetConfigValue() + => ERenderer.Simple; + public void Dispose() { foreach (var l in _layers.Values) diff --git a/Pal.Client/Rendering/SplatoonRenderer.cs b/Pal.Client/Rendering/SplatoonRenderer.cs index 5595b52..a07d2f5 100644 --- a/Pal.Client/Rendering/SplatoonRenderer.cs +++ b/Pal.Client/Rendering/SplatoonRenderer.cs @@ -14,6 +14,7 @@ using System.Reflection; using Dalamud.Game.ClientState; using Dalamud.Game.Gui; using Microsoft.Extensions.Logging; +using Pal.Client.Configuration; using Pal.Client.DependencyInjection; using Pal.Client.Extensions; @@ -41,7 +42,7 @@ namespace Pal.Client.Rendering _clientState = clientState; _chat = chat; - _logger.LogInformation("Initializing splatoon..."); + _logger.LogInformation("Initializing splatoon"); ECommonsMain.Init(pluginInterface, dalamudPlugin, ECommons.Module.SplatoonAPI); } @@ -117,7 +118,7 @@ namespace Pal.Client.Rendering CreateElement(Marker.EType.Hoard, pos.Value, ImGui.ColorConvertFloat4ToU32(hoardColor)), }; - if (!Splatoon.AddDynamicElements("PalacePal.Test", + if (!Splatoon.AddDynamicElements(ToLayerName(ELayer.Test), elements.Cast().Select(x => x.Delegate).ToArray(), new[] { Environment.TickCount64 + 10000 })) { @@ -158,12 +159,18 @@ namespace Pal.Client.Rendering } } + public ERenderer GetConfigValue() + => ERenderer.Splatoon; + public void Dispose() { + _logger.LogInformation("Disposing splatoon"); + IsDisposed = true; ResetLayer(ELayer.TrapHoard); ResetLayer(ELayer.RegularCoffers); + ResetLayer(ELayer.Test); ECommonsMain.Dispose(); } diff --git a/Pal.Client/Scheduled/QueuedConfigUpdate.cs b/Pal.Client/Scheduled/QueuedConfigUpdate.cs index 3a3e802..d0e71ca 100644 --- a/Pal.Client/Scheduled/QueuedConfigUpdate.cs +++ b/Pal.Client/Scheduled/QueuedConfigUpdate.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.Logging; using Pal.Client.Configuration; using Pal.Client.DependencyInjection; +using Pal.Client.Rendering; namespace Pal.Client.Scheduled { @@ -11,14 +12,20 @@ namespace Pal.Client.Scheduled private readonly IPalacePalConfiguration _configuration; private readonly FloorService _floorService; private readonly TerritoryState _territoryState; + private readonly RenderAdapter _renderAdapter; - public Handler(ILogger logger, IPalacePalConfiguration configuration, FloorService floorService, - TerritoryState territoryState) + public Handler( + ILogger logger, + IPalacePalConfiguration configuration, + FloorService floorService, + TerritoryState territoryState, + RenderAdapter renderAdapter) : base(logger) { _configuration = configuration; _floorService = floorService; _territoryState = territoryState; + _renderAdapter = renderAdapter; } protected override void Run(QueuedConfigUpdate queued, ref bool recreateLayout, ref bool saveMarkers) @@ -33,6 +40,8 @@ namespace Pal.Client.Scheduled recreateLayout = true; saveMarkers = true; } + + _renderAdapter.ConfigUpdated(); } } }