File size: 3,660 Bytes
5a7e716
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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;

/// <summary>
/// Central service container and orchestrator for the bot framework.
/// Manages DI, service registration, and bot instance lifecycle.
/// </summary>
public class BotEngine : IDisposable
{
    private readonly IServiceProvider _services;
    private readonly ILogger<BotEngine> _logger;
    private readonly Dictionary<string, BotContext> _activeBots = new();
    private readonly ProtocolAdapterRegistry _adapterRegistry;
    private readonly PluginManager _pluginManager;
    
    public IReadOnlyDictionary<string, BotContext> ActiveBots => _activeBots;
    public ProtocolAdapterRegistry AdapterRegistry => _adapterRegistry;
    public PluginManager PluginManager => _pluginManager;
    public IEventDispatcher EventDispatcher { get; }

    public BotEngine(IServiceProvider services)
    {
        _services = services;
        _logger = services.GetRequiredService<ILogger<BotEngine>>();
        _adapterRegistry = services.GetRequiredService<ProtocolAdapterRegistry>();
        _pluginManager = services.GetRequiredService<PluginManager>();
        EventDispatcher = services.GetRequiredService<IEventDispatcher>();
    }

    /// <summary>
    /// Create a new bot instance for a profile.
    /// </summary>
    public BotContext CreateBot(string profileId, Domain.Enums.GameClientType clientType)
    {
        var adapter = _adapterRegistry.GetAdapter(clientType);
        var eventDispatcher = new EventDispatcher();
        var logger = _services.GetRequiredService<ILoggerFactory>().CreateLogger<BotContext>();
        
        var bot = new BotContext(profileId, adapter, eventDispatcher, logger);
        _activeBots[profileId] = bot;
        
        _logger.LogInformation("Created bot for profile {ProfileId} with {ClientType}", profileId, clientType);
        return bot;
    }

    /// <summary>
    /// Remove and dispose a bot instance.
    /// </summary>
    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);
        }
    }

    /// <summary>
    /// Initialize the plugin system and load all available plugins.
    /// </summary>
    public async Task InitializePluginsAsync(IPluginContext context)
    {
        await _pluginManager.DiscoverAndLoadAsync(context);
    }

    /// <summary>
    /// Configure services for the bot engine via DI.
    /// </summary>
    public static IServiceCollection ConfigureServices(IServiceCollection services, string pluginDir)
    {
        services.AddSingleton<ProtocolAdapterRegistry>();
        services.AddSingleton<IEventDispatcher, EventDispatcher>();
        services.AddSingleton(sp => new PluginManager(
            pluginDir,
            sp,
            sp.GetRequiredService<ILogger<PluginManager>>()
        ));
        services.AddSingleton<BotEngine>();
        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();
    }
}