using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using SilkroadBot.Core.Configuration; using SilkroadBot.Core.Events; using SilkroadBot.Core.Plugins; using SilkroadBot.Core.State; using SilkroadBot.Plugins.SDK.Interfaces; namespace SilkroadBot.Core.Services; /// /// Central service container and orchestrator for the bot framework. /// Manages DI, service registration, and bot instance lifecycle. /// public class BotEngine : IDisposable { private readonly IServiceProvider _services; private readonly ILogger _logger; private readonly Dictionary _activeBots = new(); private readonly ProtocolAdapterRegistry _adapterRegistry; private readonly PluginManager _pluginManager; public IReadOnlyDictionary ActiveBots => _activeBots; public ProtocolAdapterRegistry AdapterRegistry => _adapterRegistry; public PluginManager PluginManager => _pluginManager; public IEventDispatcher EventDispatcher { get; } public BotEngine(IServiceProvider services) { _services = services; _logger = services.GetRequiredService>(); _adapterRegistry = services.GetRequiredService(); _pluginManager = services.GetRequiredService(); EventDispatcher = services.GetRequiredService(); } /// /// Create a new bot instance for a profile. /// public BotContext CreateBot(string profileId, Domain.Enums.GameClientType clientType) { var adapter = _adapterRegistry.GetAdapter(clientType); var eventDispatcher = new EventDispatcher(); var logger = _services.GetRequiredService().CreateLogger(); var bot = new BotContext(profileId, adapter, eventDispatcher, logger); _activeBots[profileId] = bot; _logger.LogInformation("Created bot for profile {ProfileId} with {ClientType}", profileId, clientType); return bot; } /// /// Remove and dispose a bot instance. /// public async Task RemoveBotAsync(string profileId) { if (_activeBots.TryGetValue(profileId, out var bot)) { await bot.DisconnectAsync(); bot.Dispose(); _activeBots.Remove(profileId); _logger.LogInformation("Removed bot for profile {ProfileId}", profileId); } } /// /// Initialize the plugin system and load all available plugins. /// public async Task InitializePluginsAsync(IPluginContext context) { await _pluginManager.DiscoverAndLoadAsync(context); } /// /// Configure services for the bot engine via DI. /// public static IServiceCollection ConfigureServices(IServiceCollection services, string pluginDir) { services.AddSingleton(); services.AddSingleton(); services.AddSingleton(sp => new PluginManager( pluginDir, sp, sp.GetRequiredService>() )); services.AddSingleton(); services.AddLogging(builder => builder.AddConsole().SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Debug)); return services; } public void Dispose() { foreach (var bot in _activeBots.Values) bot.Dispose(); _activeBots.Clear(); _pluginManager.Dispose(); } }