90803bcd3c
The plugin is now loadable. Dalamud injects five services into the Plugin constructor (Lightless pattern), the constructor builds the generic-host container synchronously, and PluginLifecycle drives StartAsync from LoadAsync. Module 02+ extends PluginHostFactory; this file set stays put. - PluginHostDependencies (record): bundles the five Dalamud services v0.1.0 needs (IDalamudPluginInterface, IPluginLog, IDataManager, IFramework, ISelfTestRegistry). - PluginHostFactory.Build: HostBuilder + AddDalamudLogging + the four service blocks (Dalamud services, Anvil singletons, ISelfTestStep collection, IHostedService init chain). Every registration uses an explicit factory lambda - the default activator only sees public ctors and Anvil follows the internal-sealed convention. - PluginLifecycle (IAsyncDisposable): owns Host.StartAsync, marshals the Host.Dispose call onto the framework thread, idempotency guard via Interlocked, ExceptionDispatchInfo.Capture preserves the original load-throw stack when a failure cascades. - Plugin (IAsyncDalamudPlugin): constructor injection of the five Dalamud services, builds the dependencies record, kicks off the host build, hands DisposeAsync to the lifecycle. - Hosting/RecipeDataLoadHostedService: dispatches LuminaRecipeAdapter .LoadInternal onto the framework thread on StartAsync. Lumina sheet reads have no documented thread safety; conservative default. - Hosting/SelfTestRegistrationHostedService: collects every ISelfTestStep registration from DI and hands them to ISelfTestRegistry.RegisterTestSteps once the host is up. - SelfTest/RecipeDataAdapterLoadStep: nine pass criteria per spec §4.1 (IsLoaded, RecipeCount > 0, ActionCount in 30..80, BuffsByKind.Count == 14, ConditionsByKind.Count == 11, Foods >= 30, Medicines >= 5, BasicSynthesis.RowIdByClassJob[8] == 100001, Cosmic-surface silent-degradation warning). Returns Waiting while the catalog is still loading. - Infrastructure/Logging trio: DalamudLogger maps Microsoft.Extensions.Logging levels to IPluginLog, the provider emits an Anvil bootstrap banner with a Forge-Bronze fingerprint on ctor, the extension wires the provider into the ILoggingBuilder via TryAddEnumerable.
102 lines
4.1 KiB
C#
102 lines
4.1 KiB
C#
// Builds the generic-host DI container for Anvil. v0.1.0 is intentionally
|
|
// thin - module 01 (RecipeData) plus the bootstrap glue. Module 02+ will
|
|
// extend the Block B / Block C sections, not replace them.
|
|
//
|
|
// Every service registration goes through a factory lambda. The default
|
|
// AddSingleton<T>() overload reflects public constructors, and Anvil
|
|
// follows the Goatcorp / Dalamud convention of internal-sealed types -
|
|
// the activator would throw on the first resolve otherwise (HellionChat
|
|
// v1.5.0 C0 smoke documented this). The lambda compiles inside Anvil's
|
|
// namespace where internal access works.
|
|
|
|
using System.Collections.Generic;
|
|
using Anvil.Hosting;
|
|
using Anvil.Infrastructure.Logging;
|
|
using Anvil.RecipeData;
|
|
using Anvil.RecipeData.Internal;
|
|
using Anvil.SelfTest;
|
|
using Dalamud.Plugin;
|
|
using Dalamud.Plugin.SelfTest;
|
|
using Dalamud.Plugin.Services;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace Anvil;
|
|
|
|
internal static class PluginHostFactory
|
|
{
|
|
public static IHost Build(Plugin plugin, PluginHostDependencies dependencies)
|
|
{
|
|
return new HostBuilder()
|
|
.UseContentRoot(dependencies.PluginInterface.ConfigDirectory.FullName)
|
|
.ConfigureLogging(logging =>
|
|
{
|
|
logging.ClearProviders();
|
|
logging.AddDalamudLogging(dependencies.PluginLog);
|
|
logging.SetMinimumLevel(LogLevel.Trace);
|
|
})
|
|
.ConfigureServices(services => ConfigureServices(services, plugin, dependencies))
|
|
.Build();
|
|
}
|
|
|
|
private static void ConfigureServices(
|
|
IServiceCollection services,
|
|
Plugin plugin,
|
|
PluginHostDependencies dependencies
|
|
)
|
|
{
|
|
// ---- Block A: Dalamud services ----
|
|
services.AddSingleton(dependencies);
|
|
services.AddSingleton(dependencies.PluginInterface);
|
|
services.AddSingleton(dependencies.PluginLog);
|
|
services.AddSingleton(dependencies.DataManager);
|
|
services.AddSingleton(dependencies.Framework);
|
|
services.AddSingleton(dependencies.SelfTestRegistry);
|
|
|
|
// Self-reference. Lets services that genuinely need the plugin
|
|
// back-ref (later modules; v0.1.0 has none) reach it without a
|
|
// Plugin.Instance static.
|
|
services.AddSingleton(plugin);
|
|
|
|
services.AddSingleton<PluginLifecycle>(sp => new PluginLifecycle(
|
|
sp.GetRequiredService<IFramework>(),
|
|
sp.GetRequiredService<Plugin>()
|
|
));
|
|
|
|
// ---- Block B: Anvil singletons ----
|
|
services.AddSingleton<RecipeDataCatalog>(_ => new RecipeDataCatalog());
|
|
services.AddSingleton<LuminaRecipeAdapter>(sp => new LuminaRecipeAdapter(
|
|
sp.GetRequiredService<IDataManager>(),
|
|
sp.GetRequiredService<ILogger<LuminaRecipeAdapter>>(),
|
|
sp.GetRequiredService<RecipeDataCatalog>()
|
|
));
|
|
|
|
// ---- Block C: SelfTest steps (collected as IEnumerable<ISelfTestStep>) ----
|
|
services.AddSingleton<ISelfTestStep, RecipeDataAdapterLoadStep>(
|
|
sp => new RecipeDataAdapterLoadStep(
|
|
sp.GetRequiredService<RecipeDataCatalog>(),
|
|
sp.GetRequiredService<ILogger<RecipeDataAdapterLoadStep>>()
|
|
)
|
|
);
|
|
|
|
// ---- Block D: Hosted services (init order is registration order) ----
|
|
// RecipeData adapter runs first so the catalog is populated before
|
|
// the self-test registry sees its steps.
|
|
services.AddHostedService<RecipeDataLoadHostedService>(
|
|
sp => new RecipeDataLoadHostedService(
|
|
sp.GetRequiredService<IFramework>(),
|
|
sp.GetRequiredService<LuminaRecipeAdapter>(),
|
|
sp.GetRequiredService<ILogger<RecipeDataLoadHostedService>>()
|
|
)
|
|
);
|
|
services.AddHostedService<SelfTestRegistrationHostedService>(
|
|
sp => new SelfTestRegistrationHostedService(
|
|
sp.GetRequiredService<ISelfTestRegistry>(),
|
|
sp.GetRequiredService<IEnumerable<ISelfTestStep>>(),
|
|
sp.GetRequiredService<ILogger<SelfTestRegistrationHostedService>>()
|
|
)
|
|
);
|
|
}
|
|
}
|