|
|
|
@ -29,42 +29,44 @@ public class ModuleManager |
|
|
|
|
|
|
|
|
|
public EntityRef Register<T>() |
|
|
|
|
where T : class => Register(typeof(T)); |
|
|
|
|
public EntityRef Register(Type type) |
|
|
|
|
public EntityRef Register(Type moduleType) |
|
|
|
|
{ |
|
|
|
|
if (!type.IsClass || type.IsGenericType || type.IsGenericTypeDefinition) throw new Exception( |
|
|
|
|
$"Module {type} must be a non-generic class"); |
|
|
|
|
if (type.Get<ModuleAttribute>() is not ModuleAttribute attr) throw new Exception( |
|
|
|
|
$"Module {type} must be marked with ModuleAttribute"); |
|
|
|
|
if (!moduleType.IsClass || moduleType.IsGenericType || moduleType.IsGenericTypeDefinition) throw new Exception( |
|
|
|
|
$"Module {moduleType} must be a non-generic class"); |
|
|
|
|
if (moduleType.Get<ModuleAttribute>() is not ModuleAttribute attr) throw new Exception( |
|
|
|
|
$"Module {moduleType} must be marked with ModuleAttribute"); |
|
|
|
|
|
|
|
|
|
// Check if module type is static. |
|
|
|
|
if (type.IsAbstract && type.IsSealed) { |
|
|
|
|
if (moduleType.IsAbstract && moduleType.IsSealed) { |
|
|
|
|
|
|
|
|
|
// Static modules represent existing modules, as such they don't |
|
|
|
|
// create entities, only look up existing ones to add type lookups |
|
|
|
|
// for use with the Lookup(Type) method. |
|
|
|
|
|
|
|
|
|
if (attr.Path == null) throw new Exception( |
|
|
|
|
$"Existing module {type} must have ModuleAttribute.Name set"); |
|
|
|
|
$"Existing module {moduleType} must have ModuleAttribute.Name set"); |
|
|
|
|
var path = new EntityPath(true, attr.Path); |
|
|
|
|
var entity = Universe.Lookup(path) ?? throw new Exception( |
|
|
|
|
$"Existing module {type} with name '{path}' not found"); |
|
|
|
|
var module = Universe.Lookup(path) ?? throw new Exception( |
|
|
|
|
$"Existing module {moduleType} with name '{path}' not found"); |
|
|
|
|
|
|
|
|
|
// This implementation is pretty naive. It simply gets all nested |
|
|
|
|
// types which are tagged with an ICreateEntityAttribute base |
|
|
|
|
// attribute and creates a lookup mapping. No sanity checking. |
|
|
|
|
|
|
|
|
|
foreach (var nested in type.GetNestedTypes()) { |
|
|
|
|
if (!nested.GetCustomAttributes(true).OfType<ICreateEntityAttribute>().Any()) continue; |
|
|
|
|
var name = nested.Get<EntityAttribute>()?.Path?.Single() ?? nested.Name; |
|
|
|
|
Universe.LookupOrThrow(entity, name).CreateLookup(nested); |
|
|
|
|
foreach (var type in moduleType.GetNestedTypes()) { |
|
|
|
|
if (!type.GetCustomAttributes(true).OfType<ICreateEntityAttribute>().Any()) continue; |
|
|
|
|
var name = type.Get<EntityAttribute>()?.Path?.Single() ?? type.Name; |
|
|
|
|
var entity = Universe.LookupOrThrow(module, name); |
|
|
|
|
entity.CreateLookup(type); |
|
|
|
|
if (type.Has<RelationAttribute>()) entity.Add<Relation>(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return entity; |
|
|
|
|
return module; |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
|
|
var path = GetModulePath(type); |
|
|
|
|
var module = new ModuleInfo(Universe, type, path); |
|
|
|
|
var path = GetModulePath(moduleType); |
|
|
|
|
var module = new ModuleInfo(Universe, moduleType, path); |
|
|
|
|
_modules.Add(module.Entity, module); |
|
|
|
|
TryEnableModule(module); |
|
|
|
|
return module.Entity; |
|
|
|
@ -194,6 +196,8 @@ internal class ModuleInfo |
|
|
|
|
var builder = path.IsAbsolute ? Universe.New(path) : Entity.NewChild(path); |
|
|
|
|
if (!type.IsPublic) builder.Symbol(path.Name); |
|
|
|
|
|
|
|
|
|
if (type.Has<RelationAttribute>()) builder.Add<Relation>(); |
|
|
|
|
|
|
|
|
|
var entity = builder.Build(); |
|
|
|
|
|
|
|
|
|
EntityRef Lookup(Type toLookup) |
|
|
|
|