poe2-bot/src/Automata.Ui/App.axaml.cs
2026-03-02 16:23:23 -05:00

122 lines
4.7 KiB
C#

using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Microsoft.Extensions.DependencyInjection;
using Automata.Bot;
using Automata.Core;
using Automata.Game;
using Automata.GameLog;
using Automata.Inventory;
using Automata.Items;
using Automata.Screen;
using Automata.Screen.Ocr;
using Automata.Trade;
using Automata.Ui.Overlay;
using Automata.Ui.ViewModels;
using Automata.Ui.Views;
namespace Automata.Ui;
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
// Initialize Sidekick parser (fire-and-forget, non-blocking)
_ = Task.Run(async () =>
{
try { await SidekickBootstrapper.InitializeAsync(); }
catch (Exception ex) { Serilog.Log.Warning(ex, "Sidekick init failed"); }
});
var services = new ServiceCollection();
// Config
services.AddSingleton<ConfigStore>();
services.AddSingleton(sp => sp.GetRequiredService<ConfigStore>().Settings);
// Services
services.AddSingleton<IOcrEngine>(sp =>
{
var settings = sp.GetRequiredService<SavedSettings>();
return OcrEngineFactory.Create(settings.OcrEngine);
});
services.AddSingleton<IGameController, GameController>();
services.AddSingleton<IScreenReader, ScreenReader>();
services.AddSingleton<IClientLogWatcher>(sp =>
new ClientLogWatcher(sp.GetRequiredService<SavedSettings>().GameLogPath));
services.AddSingleton<ITradeMonitor, TradeDaemonBridge>();
services.AddSingleton<IInventoryManager, InventoryManager>();
// Bot
services.AddSingleton<FramePipelineService>();
services.AddSingleton<LinkManager>();
services.AddSingleton<TradeExecutor>();
services.AddSingleton<TradeQueue>();
services.AddSingleton<BotOrchestrator>();
services.AddSingleton<ModPoolService>();
// ViewModels
services.AddSingleton<MainWindowViewModel>();
services.AddSingleton<DebugViewModel>();
services.AddSingleton<SettingsViewModel>();
services.AddSingleton<MappingViewModel>();
services.AddSingleton<AtlasViewModel>();
services.AddSingleton<CraftingViewModel>();
services.AddSingleton<MemoryViewModel>();
services.AddSingleton<RobotoViewModel>();
services.AddSingleton<ObjectBrowserViewModel>();
var provider = services.BuildServiceProvider();
var store = provider.GetRequiredService<ConfigStore>();
var bot = provider.GetRequiredService<BotOrchestrator>();
var modPool = provider.GetRequiredService<ModPoolService>();
// Fire-and-forget: load RePoE data, then populate CraftingVM base items
_ = Task.Run(async () =>
{
await modPool.LoadAsync();
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
{
var craftVm = provider.GetRequiredService<CraftingViewModel>();
craftVm.LoadBaseItems();
});
});
var mainVm = provider.GetRequiredService<MainWindowViewModel>();
mainVm.DebugVm = provider.GetRequiredService<DebugViewModel>();
mainVm.SettingsVm = provider.GetRequiredService<SettingsViewModel>();
mainVm.MappingVm = provider.GetRequiredService<MappingViewModel>();
mainVm.AtlasVm = provider.GetRequiredService<AtlasViewModel>();
mainVm.CraftingVm = provider.GetRequiredService<CraftingViewModel>();
mainVm.MemoryVm = provider.GetRequiredService<MemoryViewModel>();
mainVm.RobotoVm = provider.GetRequiredService<RobotoViewModel>();
mainVm.BrowserVm = provider.GetRequiredService<ObjectBrowserViewModel>();
var window = new MainWindow { DataContext = mainVm };
window.SetConfigStore(store);
desktop.MainWindow = window;
desktop.ShutdownMode = Avalonia.Controls.ShutdownMode.OnMainWindowClose;
var overlay = new D2dOverlay(bot);
overlay.Start();
desktop.ShutdownRequested += async (_, _) =>
{
overlay.Shutdown();
mainVm.Shutdown();
mainVm.RobotoVm?.Shutdown();
await bot.DisposeAsync();
};
}
base.OnFrameworkInitializationCompleted();
}
}