acdream/src/AcDream.App/Program.cs

170 lines
4.7 KiB
C#

using AcDream.App;
using AcDream.App.Plugins;
using AcDream.App.Platform;
using AcDream.App.Rendering;
using AcDream.Core.Plugins;
using AcDream.Runtime.Platform;
using Serilog;
GraphicalHostPlatformServices graphicalPlatform =
GraphicalHostPlatformServices.Resolve();
graphicalPlatform.ConfigureWindowBackend();
ApplicationPathSet applicationPaths = graphicalPlatform.Paths;
IReadOnlyList<string> migratedConfigurationFiles =
GraphicalLegacyConfigurationMigrator.Migrate(applicationPaths);
if (args.Length >= 1 && args[0] == "ui-studio")
{
var so = AcDream.App.Studio.StudioOptions.Parse(args[1..]);
using var sw = new AcDream.App.Studio.StudioWindow(
so,
applicationPaths);
try
{
sw.Run();
return 0;
}
catch (NotSupportedException error)
{
Console.Error.WriteLine(error.Message);
return 4;
}
}
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.CreateLogger();
foreach (string migratedConfigurationFile in migratedConfigurationFiles)
{
Log.Information(
"migrated legacy graphical configuration to {Path}",
migratedConfigurationFile);
}
Log.Information(
"graphical platform {RuntimeIdentifier}; native closure: {NativeDependencies}",
graphicalPlatform.RuntimeIdentifier,
string.Join(
", ",
graphicalPlatform.NativeDependencies.Select(
dependency =>
$"{dependency.Feature}={dependency.PublishedFileName}")));
var datDir = args.FirstOrDefault() ?? Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR");
if (string.IsNullOrWhiteSpace(datDir))
{
Log.Error("usage: AcDream.App <dat-directory> (or set ACDREAM_DAT_DIR)");
return 2;
}
// Single read of the startup-time process environment. Every downstream
// consumer (GameWindow + collaborators) reads the typed bundle, not the
// raw env vars. See docs/architecture/code-structure.md §2 Rule 4.
var runtimeOptions = RuntimeOptions.FromEnvironment(datDir);
var worldGameState = new AcDream.Core.Plugins.WorldGameState();
var worldEvents = new AcDream.Core.Plugins.WorldEvents();
var uiRegistry = new AcDream.App.Plugins.BufferedUiRegistry();
using var window = new GameWindow(
runtimeOptions,
worldGameState,
worldEvents,
uiRegistry,
graphicalPlatform);
var host = new AppPluginHost(
new SerilogAdapter(Log.Logger),
worldGameState,
worldEvents,
window.Selection,
uiRegistry);
var loaded = new List<LoadedPlugin>();
var loadedPluginIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
StringComparer pathComparer =
graphicalPlatform.OperatingSystem
== GraphicalHostOperatingSystem.Windows
? StringComparer.OrdinalIgnoreCase
: StringComparer.Ordinal;
string[] pluginRoots =
[
.. new[]
{
Path.Combine(AppContext.BaseDirectory, "plugins"),
applicationPaths.PluginsDirectory,
}.Distinct(pathComparer),
];
foreach (string pluginsDir in pluginRoots)
{
Log.Information("scanning plugins in {PluginsDir}", pluginsDir);
foreach (var result in PluginDiscovery.Scan(pluginsDir))
{
if (!result.Success)
{
Log.Warning(
"plugin discovery failed for {Dir}: {Error}",
result.PluginDirectory,
result.Error);
continue;
}
if (loadedPluginIds.Contains(result.Manifest!.Id))
{
Log.Warning(
"skipping duplicate plugin id {Id} from {Dir}",
result.Manifest.Id,
result.PluginDirectory);
continue;
}
var loadResult = PluginLoader.Load(
result.PluginDirectory,
result.Manifest,
host);
if (!loadResult.Success)
{
Log.Warning(
"plugin load failed for {Id}: {Error}",
result.Manifest.Id,
loadResult.Error);
continue;
}
loadedPluginIds.Add(result.Manifest.Id);
loaded.Add(loadResult);
Log.Information(
"loaded plugin {Id} ({DisplayName})",
result.Manifest.Id,
result.Manifest.DisplayName);
}
}
try
{
foreach (var plugin in loaded)
{
try { plugin.Plugin!.Enable(); }
catch (Exception ex) { Log.Error(ex, "plugin enable failed: {Id}", plugin.Manifest.Id); }
}
try
{
window.Run();
}
catch (NotSupportedException error)
{
Log.Error("{GraphicalStartupFailure}", error.Message);
return 4;
}
}
finally
{
foreach (var plugin in loaded)
{
try { plugin.Plugin!.Disable(); }
catch (Exception ex) { Log.Error(ex, "plugin disable failed: {Id}", plugin.Manifest.Id); }
}
Log.CloseAndFlush();
}
return 0;