Updated KD and ModulLoader
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Firebird2D.Datatypes;
|
||||
using Firebird2D.DataypesAndInterfaces.Interfaces;
|
||||
using Firebird2D.Interfaces;
|
||||
using Firebird2D.Logger;
|
||||
using Firebird2D.Requirement;
|
||||
@@ -25,66 +26,122 @@ namespace Firebird2D.ModulLoading
|
||||
|
||||
public class ModulLoader
|
||||
{
|
||||
private readonly IGame gameInstance;
|
||||
|
||||
private static readonly Dictionary<ExtensionDependencyInjection, (Type type, Func<IGame, object> resolver)> providers = new()
|
||||
{
|
||||
[ExtensionDependencyInjection.game] = (typeof(IGame), game => game),
|
||||
[ExtensionDependencyInjection.eventsystem] = (typeof(IEventBus), game => game.EventBus),
|
||||
[ExtensionDependencyInjection.keymapper] = (typeof(IKeyMapper), game => game.KeyMapper),
|
||||
};
|
||||
|
||||
|
||||
private ModulList? modulList = null;
|
||||
|
||||
|
||||
public ModulLoader(IGame gameInstance)
|
||||
{
|
||||
this.gameInstance = gameInstance;
|
||||
DeserialiseModulList();
|
||||
}
|
||||
|
||||
public void LoadModules()
|
||||
public T? LoadSystemComponent<T>(ModuleType moduleType, IGame gameInstance) where T : class
|
||||
{
|
||||
DeserialiseModulList();
|
||||
if (modulList == null) return;
|
||||
List<Modul> eventModul = modulList.mods.Where(m => m.ModuleType == ModuleType.EventSystem).ToList();
|
||||
if(modulList?.mods == null || modulList.mods.Count == 0) return null;
|
||||
|
||||
if (eventModul.Count > 1) GameLogger.GetInstance(0).Log("ModuleLoader", LogType.Warning, $"More then one EventModul defined first modul ist loaded");
|
||||
List<Modul> systemModules = modulList.mods.Where(m => m.ModuleType == moduleType).ToList();
|
||||
if (systemModules.Count > 1) GameLogger.GetInstance(0).Log("ModuleLoader", LogType.Warning, $"More then one {moduleType.ToString()} defined, first loadable modul ist loaded");
|
||||
if (systemModules.Count < 1) { GameLogger.GetInstance(0).Log("ModuleLoader", LogType.Info, $"No {moduleType.ToString()} is Defined Basic Modul is Loaded"); return null; };
|
||||
|
||||
if (eventModul.Count != 0)
|
||||
for(int i = 0; i < systemModules.Count; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Assembly eventAssembly = Assembly.Load(eventModul[0].RelativePath);
|
||||
if (string.IsNullOrWhiteSpace(systemModules[i].RelativePath)) continue;
|
||||
T? modul = LoadModule<T>(moduleType, gameInstance, systemModules[i].RelativePath);
|
||||
if (modul == null) continue;
|
||||
GameLogger.GetInstance(0).Log("ModuleLoader", LogType.Info, $"{systemModules[i].RelativePath} is loeaded for {moduleType}.");
|
||||
return modul;
|
||||
}
|
||||
|
||||
GameLogger.GetInstance(0).Log("ModuleLoader", LogType.Info, $"F{eventModul[0].Name} loaded.");
|
||||
GameLogger.GetInstance(0).Log("ModuleLoader", LogType.Error, $"None of the defined {moduleType} modules could be loaded.");
|
||||
|
||||
LinkEventAssembly(eventAssembly);
|
||||
}
|
||||
catch(Exception ex)
|
||||
return null;
|
||||
}
|
||||
|
||||
public void LoadExtensions(IGame gameInstance)
|
||||
{
|
||||
if (modulList?.mods == null || modulList.mods.Count == 0) return;
|
||||
|
||||
List<Modul> eventModul = modulList.mods.Where(m => m.ModuleType == ModuleType.Extension).ToList();
|
||||
|
||||
foreach (Modul modul in eventModul) {
|
||||
if (string.IsNullOrWhiteSpace(modul.RelativePath)) continue;
|
||||
|
||||
IExtensionBase? extensionBase = LoadModule<IExtensionBase>(ModuleType.Extension, gameInstance, modul.RelativePath);
|
||||
if (extensionBase != null)
|
||||
{
|
||||
GameLogger.GetInstance(0).Log("ModuleLoader", LogType.Warning, $"Failed to load {eventModul[0].Name}, with exception {ex.Message}");
|
||||
extensionBase.Startup();
|
||||
}
|
||||
}
|
||||
else
|
||||
GameLogger.GetInstance(0).Log("ModuleLoader", LogType.Warning, $"More then one EventModul defined first modul ist loaded");
|
||||
|
||||
|
||||
|
||||
|
||||
if (modulList.mods.Count == 0) return;
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void LinkEventAssembly(Assembly assembly)
|
||||
{
|
||||
Type? type = assembly.GetTypes().FirstOrDefault(t => typeof(IEventBus).IsAssignableFrom(t) && !t.IsInterface);
|
||||
Require.NotNull(type,"type",0);
|
||||
|
||||
IEventBus? eventBus = Activator.CreateInstance(type) as IEventBus;
|
||||
|
||||
Require.NotNull(eventBus,"eventBus",0);
|
||||
gameInstance.EventBus = eventBus;
|
||||
}
|
||||
|
||||
private void DeserialiseModulList()
|
||||
private T? LoadModule<T>(ModuleType moduleType, IGame gameInstance, string modulePath) where T : class
|
||||
{
|
||||
try
|
||||
{
|
||||
using (FileStream file = new FileStream("Modules/Moduls.xml", FileMode.Open))
|
||||
string basePath = AppContext.BaseDirectory;
|
||||
string dllPath = Path.Combine(basePath, modulePath);
|
||||
|
||||
Assembly assembly = Assembly.LoadFrom(dllPath);
|
||||
Type moduleClassType = assembly.GetTypes().First(t => typeof(T).IsAssignableFrom(t));
|
||||
|
||||
List<Type> dependencyInjectionTypes = [];
|
||||
List<Object> dependencyInjections = [];
|
||||
|
||||
foreach (var neededParam in moduleType.getNeededDependencyInjection())
|
||||
{
|
||||
if (providers.TryGetValue(neededParam, out var entry))
|
||||
{
|
||||
dependencyInjectionTypes.Add(entry.type);
|
||||
dependencyInjections.Add(entry.resolver(gameInstance));
|
||||
}
|
||||
else
|
||||
{
|
||||
GameLogger.GetInstance(0).Log("ModuleLoader", LogType.Warning, $"No provider found for dependency: {neededParam}");
|
||||
}
|
||||
}
|
||||
|
||||
ConstructorInfo? ctor = moduleClassType.GetConstructor(dependencyInjectionTypes.ToArray());
|
||||
|
||||
if (ctor == null)
|
||||
{
|
||||
string signature = string.Join(", ", dependencyInjectionTypes.Select(t => t.Name));
|
||||
GameLogger.GetInstance(0).Log("ModuleLoader", LogType.Error, $"No constructor found matching: ({signature})");
|
||||
return null;
|
||||
};
|
||||
|
||||
T instance = (T)ctor.Invoke(dependencyInjections.ToArray());
|
||||
Type expectedType = moduleType.getBasicModuleInterfaceType();
|
||||
|
||||
if (!expectedType.IsInstanceOfType(instance))
|
||||
{
|
||||
GameLogger.GetInstance(0).Log("ModuleLoader", LogType.Error, $"Instance does not implement {expectedType.Name}");
|
||||
return null;
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GameLogger.GetInstance(0).Log("ModuleLoader", LogType.Error, $"Error while loading event module {ex.ToString()}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void DeserialiseModulList()
|
||||
{
|
||||
try
|
||||
{
|
||||
string path = Path.Combine(AppContext.BaseDirectory, "Modules", "Moduls.xml");
|
||||
using (FileStream file = new FileStream(path, FileMode.Open))
|
||||
{
|
||||
XmlSerializer xmlSerializer = new XmlSerializer(typeof(ModulList));
|
||||
modulList = (ModulList?)xmlSerializer.Deserialize(file);
|
||||
@@ -92,7 +149,7 @@ namespace Firebird2D.ModulLoading
|
||||
}
|
||||
catch(Exception ex) {
|
||||
modulList = null;
|
||||
GameLogger.GetInstance(0).Log("ModulLoader",LogType.Warning, $"Modul file not existing or invalid: {ex.Message}");
|
||||
GameLogger.GetInstance(0).Log("ModulLoader",LogType.Warning, $"Modul file not existing or invalid: {ex.ToString()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
using Firebird2D.DataypesAndInterfaces.Interfaces;
|
||||
using Firebird2D.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Firebird2D.ModulLoading
|
||||
{
|
||||
public enum ModuleType
|
||||
{
|
||||
Extension = 0,
|
||||
EventSystem = 1,
|
||||
KeyMapper = 2
|
||||
}
|
||||
|
||||
public enum ExtensionDependencyInjection
|
||||
{
|
||||
game,
|
||||
eventsystem,
|
||||
keymapper
|
||||
}
|
||||
|
||||
public static class ModuleTypeExtensions
|
||||
{
|
||||
public static Type getBasicModuleInterfaceType(this ModuleType moduleType)
|
||||
{
|
||||
return moduleType switch
|
||||
{
|
||||
ModuleType.Extension => typeof(IExtensionBase),
|
||||
ModuleType.EventSystem => typeof(IEventBus),
|
||||
ModuleType.KeyMapper => typeof(IKeyMapper)
|
||||
};
|
||||
}
|
||||
|
||||
public static ExtensionDependencyInjection[] getNeededDependencyInjection(this ModuleType moduleType)
|
||||
{
|
||||
return moduleType switch
|
||||
{
|
||||
ModuleType.Extension => [ExtensionDependencyInjection.game],
|
||||
ModuleType.EventSystem => [ ],
|
||||
ModuleType.KeyMapper => [ExtensionDependencyInjection.eventsystem]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,9 @@
|
||||
<Moduls>
|
||||
<!--
|
||||
<Modul>
|
||||
<ModuleType>Plugin</ModuleType>
|
||||
<ModuleType>Extension |
|
||||
EventSystem |
|
||||
KeyMapper</ModuleType>
|
||||
<Name>Logger</Name>
|
||||
<RelativePath>Modules/Logger</RelativePath>
|
||||
</Modul>
|
||||
|
||||
Reference in New Issue
Block a user