75 lines
3 KiB
C#
75 lines
3 KiB
C#
using System.Collections.Immutable;
|
|
using System.Linq.Expressions;
|
|
using System.Reflection;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging;
|
|
using RPG.Network.Proto;
|
|
using RPG.Services.Gameserver.Modules.Attributes;
|
|
using RPG.Services.Gameserver.Session;
|
|
|
|
namespace RPG.Services.Gameserver.Modules;
|
|
internal class ModuleManager
|
|
{
|
|
private delegate Task ReqHandler(PlayerSession session, IServiceProvider serviceProvider, ReadOnlyMemory<byte> body);
|
|
private static readonly ImmutableDictionary<CmdType, ReqHandler> s_handlers;
|
|
|
|
private readonly IServiceProvider _serviceProvider;
|
|
private readonly ILogger _logger;
|
|
|
|
static ModuleManager()
|
|
{
|
|
s_handlers = MapHandlers();
|
|
}
|
|
|
|
public ModuleManager(IServiceProvider serviceProvider, ILogger<ModuleManager> logger)
|
|
{
|
|
_serviceProvider = serviceProvider;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task HandleAsync(PlayerSession session, CmdType cmdType, ReadOnlyMemory<byte> body)
|
|
{
|
|
if (s_handlers.TryGetValue(cmdType, out var handler))
|
|
{
|
|
await handler(session, _serviceProvider, body);
|
|
_logger.LogInformation("Successfully handled command of type {cmdType}", cmdType);
|
|
}
|
|
else
|
|
{
|
|
_logger.LogWarning("Handler for command of type {cmdType} not defined!", cmdType);
|
|
}
|
|
}
|
|
|
|
private static ImmutableDictionary<CmdType, ReqHandler> MapHandlers()
|
|
{
|
|
var builder = ImmutableDictionary.CreateBuilder<CmdType, ReqHandler>();
|
|
|
|
IEnumerable<Type> types = Assembly.GetExecutingAssembly().GetTypes()
|
|
.Where(type => type.IsAssignableTo(typeof(BaseModule)) && !type.IsAbstract);
|
|
|
|
MethodInfo getServiceMethod = typeof(ServiceProviderServiceExtensions).GetMethod("GetRequiredService", [typeof(IServiceProvider)])!;
|
|
|
|
foreach (Type type in types)
|
|
{
|
|
IEnumerable<MethodInfo> methods = type.GetMethods()
|
|
.Where(method => method.GetCustomAttribute<OnCommandAttribute>() != null);
|
|
|
|
foreach (MethodInfo method in methods)
|
|
{
|
|
OnCommandAttribute attribute = method.GetCustomAttribute<OnCommandAttribute>()!;
|
|
|
|
ParameterExpression sessionParam = Expression.Parameter(typeof(PlayerSession));
|
|
ParameterExpression serviceProviderParam = Expression.Parameter(typeof(IServiceProvider));
|
|
ParameterExpression bodyParam = Expression.Parameter(typeof(ReadOnlyMemory<byte>));
|
|
|
|
MethodCallExpression getServiceCall = Expression.Call(getServiceMethod.MakeGenericMethod(type), serviceProviderParam);
|
|
MethodCallExpression handlerCall = Expression.Call(getServiceCall, method, sessionParam, bodyParam);
|
|
|
|
Expression<ReqHandler> lambda = Expression.Lambda<ReqHandler>(handlerCall, sessionParam, serviceProviderParam, bodyParam);
|
|
builder.Add(attribute.CmdType, lambda.Compile());
|
|
}
|
|
}
|
|
|
|
return builder.ToImmutable();
|
|
}
|
|
}
|