PalacePal/Pal.Client/DependencyInjectionContext.cs

195 lines
7.9 KiB
C#
Raw Normal View History

using System;
2023-02-16 18:51:54 +00:00
using System.IO;
2023-02-15 22:17:19 +00:00
using Dalamud.Data;
2023-02-25 14:32:26 +00:00
using Dalamud.Extensions.MicrosoftLogging;
2023-02-15 13:35:11 +00:00
using Dalamud.Game;
using Dalamud.Game.ClientState;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.Command;
using Dalamud.Game.Gui;
2023-02-15 22:17:19 +00:00
using Dalamud.Interface.Windowing;
2023-02-15 13:35:11 +00:00
using Dalamud.Plugin;
2023-10-03 09:08:38 +00:00
using Dalamud.Plugin.Services;
2023-02-16 18:51:54 +00:00
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
2023-02-15 13:35:11 +00:00
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
2023-02-15 22:17:19 +00:00
using Pal.Client.Commands;
using Pal.Client.Configuration;
using Pal.Client.Configuration.Legacy;
2023-02-16 18:51:54 +00:00
using Pal.Client.Database;
using Pal.Client.DependencyInjection;
2023-02-18 20:12:36 +00:00
using Pal.Client.Floors;
2023-02-15 22:17:19 +00:00
using Pal.Client.Net;
using Pal.Client.Rendering;
using Pal.Client.Scheduled;
using Pal.Client.Windows;
2023-02-15 13:35:11 +00:00
2023-03-30 20:01:43 +00:00
namespace Pal.Client;
/// <summary>
/// DI-aware Plugin.
/// </summary>
internal sealed class DependencyInjectionContext : IDisposable
2023-02-15 13:35:11 +00:00
{
2023-03-30 20:01:43 +00:00
public const string DatabaseFileName = "palace-pal.data.sqlite3";
2023-02-15 13:35:11 +00:00
/// <summary>
2023-03-30 20:01:43 +00:00
/// Initialized as temporary logger, will be overriden once context is ready with a logger that supports scopes.
2023-02-15 13:35:11 +00:00
/// </summary>
2023-10-03 09:08:38 +00:00
private ILogger _logger;
2023-03-30 20:01:43 +00:00
private readonly string _sqliteConnectionString;
private readonly ServiceCollection _serviceCollection = new();
private ServiceProvider? _serviceProvider;
public DependencyInjectionContext(
DalamudPluginInterface pluginInterface,
2023-10-03 09:08:38 +00:00
IClientState clientState,
IGameGui gameGui,
IChatGui chatGui,
IObjectTable objectTable,
IFramework framework,
ICondition condition,
ICommandManager commandManager,
IDataManager dataManager,
IGameInteropProvider gameInteropProvider,
IPluginLog pluginLog,
2023-03-30 20:01:43 +00:00
Plugin plugin)
2023-02-15 13:35:11 +00:00
{
2023-10-03 20:05:19 +00:00
var loggerProvider = new DalamudLoggerProvider(pluginLog);
_logger = loggerProvider.CreateLogger<DependencyInjectionContext>();
2023-03-30 20:01:43 +00:00
_logger.LogInformation("Building dalamud service container for {Assembly}",
typeof(DependencyInjectionContext).Assembly.FullName);
2023-02-16 18:51:54 +00:00
2023-03-30 20:01:43 +00:00
// set up legacy services
#pragma warning disable CS0612
2023-03-30 20:01:43 +00:00
JsonFloorState.SetContextProperties(pluginInterface.GetPluginConfigDirectory());
#pragma warning restore CS0612
2023-03-30 20:01:43 +00:00
// set up logging
_serviceCollection.AddLogging(builder =>
builder.AddFilter("Pal", LogLevel.Trace)
.AddFilter("Microsoft.EntityFrameworkCore.Database", LogLevel.Warning)
.AddFilter("Grpc", LogLevel.Debug)
.ClearProviders()
2023-10-03 09:08:38 +00:00
.AddDalamudLogger(pluginLog));
2023-03-30 20:01:43 +00:00
// dalamud
_serviceCollection.AddSingleton<IDalamudPlugin>(plugin);
_serviceCollection.AddSingleton(pluginInterface);
_serviceCollection.AddSingleton(clientState);
_serviceCollection.AddSingleton(gameGui);
_serviceCollection.AddSingleton(chatGui);
_serviceCollection.AddSingleton<Chat>();
_serviceCollection.AddSingleton(objectTable);
_serviceCollection.AddSingleton(framework);
_serviceCollection.AddSingleton(condition);
_serviceCollection.AddSingleton(commandManager);
_serviceCollection.AddSingleton(dataManager);
2023-10-03 09:08:38 +00:00
_serviceCollection.AddSingleton(gameInteropProvider);
2023-03-30 20:01:43 +00:00
_serviceCollection.AddSingleton(new WindowSystem(typeof(DependencyInjectionContext).AssemblyQualifiedName));
_sqliteConnectionString =
$"Data Source={Path.Join(pluginInterface.GetPluginConfigDirectory(), DatabaseFileName)}";
}
public IServiceProvider BuildServiceContainer()
{
_logger.LogInformation("Building async service container for {Assembly}",
typeof(DependencyInjectionContext).Assembly.FullName);
// EF core
_serviceCollection.AddDbContext<PalClientContext>(o => o
.UseSqlite(_sqliteConnectionString)
.UseModel(Database.Compiled.PalClientContextModel.Instance));
_serviceCollection.AddTransient<JsonMigration>();
_serviceCollection.AddScoped<Cleanup>();
// plugin-specific
_serviceCollection.AddScoped<DependencyContextInitializer>();
_serviceCollection.AddScoped<DebugState>();
_serviceCollection.AddScoped<GameHooks>();
_serviceCollection.AddScoped<RemoteApi>();
_serviceCollection.AddScoped<ConfigurationManager>();
_serviceCollection.AddScoped<IPalacePalConfiguration>(sp =>
sp.GetRequiredService<ConfigurationManager>().Load());
_serviceCollection.AddTransient<RepoVerification>();
// commands
_serviceCollection.AddScoped<PalConfigCommand>();
_serviceCollection.AddScoped<ISubCommand, PalConfigCommand>();
_serviceCollection.AddScoped<ISubCommand, PalNearCommand>();
_serviceCollection.AddScoped<ISubCommand, PalStatsCommand>();
_serviceCollection.AddScoped<ISubCommand, PalTestConnectionCommand>();
// territory & marker related services
_serviceCollection.AddScoped<TerritoryState>();
_serviceCollection.AddScoped<FrameworkService>();
_serviceCollection.AddScoped<ChatService>();
_serviceCollection.AddScoped<FloorService>();
_serviceCollection.AddScoped<ImportService>();
_serviceCollection.AddScoped<ObjectTableDebug>();
// windows & related services
_serviceCollection.AddScoped<AgreementWindow>();
_serviceCollection.AddScoped<ConfigWindow>();
_serviceCollection.AddScoped<StatisticsService>();
_serviceCollection.AddScoped<StatisticsWindow>();
// rendering
_serviceCollection.AddScoped<SimpleRenderer>();
_serviceCollection.AddScoped<SplatoonRenderer>();
_serviceCollection.AddScoped<RenderAdapter>();
// queue handling
_serviceCollection.AddTransient<IQueueOnFrameworkThread.Handler<QueuedImport>, QueuedImport.Handler>();
_serviceCollection
.AddTransient<IQueueOnFrameworkThread.Handler<QueuedUndoImport>, QueuedUndoImport.Handler>();
_serviceCollection
.AddTransient<IQueueOnFrameworkThread.Handler<QueuedConfigUpdate>, QueuedConfigUpdate.Handler>();
_serviceCollection
.AddTransient<IQueueOnFrameworkThread.Handler<QueuedSyncResponse>, QueuedSyncResponse.Handler>();
// build
_serviceProvider = _serviceCollection.BuildServiceProvider(new ServiceProviderOptions
{
2023-03-30 20:01:43 +00:00
ValidateOnBuild = true,
ValidateScopes = true,
});
2023-02-15 13:35:11 +00:00
2023-02-16 18:51:54 +00:00
2023-02-15 22:17:19 +00:00
#if RELEASE
2023-03-30 20:01:43 +00:00
// You're welcome to remove this code in your fork, but please make sure that:
// - none of the links accessible within FFXIV open the original repo (e.g. in the plugin installer), and
// - you host your own server instance
//
// This is mainly to avoid this plugin being included in 'mega-repos' that, for whatever reason, decide
// that collecting all plugins is a good idea (and break half in the process).
_serviceProvider.GetService<RepoVerification>();
2023-02-15 22:17:19 +00:00
#endif
2023-03-30 20:01:43 +00:00
// This is not ideal as far as loading the plugin goes, because there's no way to check for errors and
// tell Dalamud that no, the plugin isn't ready -- so the plugin will count as properly initialized,
// even if it's not.
//
// There's 2-3 seconds of slowdown primarily caused by the sqlite init, but that needs to happen for
// config stuff.
_logger = _serviceProvider.GetRequiredService<ILogger<DependencyInjectionContext>>();
_logger.LogInformation("Service container built");
2023-03-30 20:01:43 +00:00
return _serviceProvider;
}
2023-02-15 13:35:11 +00:00
2023-03-30 20:01:43 +00:00
public void Dispose()
{
_logger.LogInformation("Disposing DI Context");
_serviceProvider?.Dispose();
2023-03-30 20:01:43 +00:00
// ensure we're not keeping the file open longer than the plugin is loaded
using (SqliteConnection sqliteConnection = new(_sqliteConnectionString))
SqliteConnection.ClearPool(sqliteConnection);
2023-02-15 13:35:11 +00:00
}
}