155 lines
5.2 KiB
C#
155 lines
5.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using Cysharp.Threading.Tasks;
|
|
using UnityEngine;
|
|
|
|
namespace DanieleMarotta.RiversongCodeShowcase
|
|
{
|
|
public class EngineRunner : MonoBehaviour, IEngine
|
|
{
|
|
private ServiceLocator _serviceLocator;
|
|
|
|
private RootGameSystemGroup _rootSystemGroup;
|
|
|
|
private List<GameSystemGroup> _systemGroups = new();
|
|
|
|
private Dictionary<Type, GameSystemGroup> _systemGroupsByType = new();
|
|
|
|
private EngineUpdateFilter _updateFilter = new();
|
|
|
|
public bool IsInitialized { get; private set; }
|
|
|
|
public List<IGameSystem> Systems { get; } = new();
|
|
|
|
public void Start()
|
|
{
|
|
StartAsync().Forget(Debug.LogException);
|
|
}
|
|
|
|
private async UniTask StartAsync()
|
|
{
|
|
Debug.Log("Engine started");
|
|
|
|
_serviceLocator = new ServiceLocator();
|
|
|
|
_serviceLocator.RegisterService(typeof(IEngine), this);
|
|
|
|
var serviceProviders = GetComponentsInChildren<IServiceProvider>();
|
|
foreach (var serviceProvider in serviceProviders) serviceProvider.RegisterServices(_serviceLocator);
|
|
|
|
await UniTask.NextFrame();
|
|
|
|
_rootSystemGroup = new RootGameSystemGroup();
|
|
_systemGroups.Add(_rootSystemGroup);
|
|
_systemGroupsByType.Add(_rootSystemGroup.GetType(), _rootSystemGroup);
|
|
|
|
Debug.Log("Systems discovery started");
|
|
DiscoverSystems();
|
|
Debug.Log($"Systems discovery completed. Discovered {_rootSystemGroup.Systems.Count} system groups and {Systems.Count} systems");
|
|
|
|
await UniTask.NextFrame();
|
|
|
|
foreach (var systemGroup in _systemGroups) _serviceLocator.Inject(systemGroup);
|
|
foreach (var system in Systems) _serviceLocator.Inject(system);
|
|
|
|
await UniTask.NextFrame();
|
|
|
|
var types = Systems.Select(obj => obj.GetType()).Concat(_systemGroups.Select(obj => obj.GetType())).Distinct().ToList();
|
|
SystemSorter.InitializeSorters(types);
|
|
|
|
await UniTask.NextFrame();
|
|
|
|
Debug.Log("Systems initialization started");
|
|
await InitializeAsync();
|
|
Debug.Log("Systems initialization completed");
|
|
|
|
IsInitialized = true;
|
|
}
|
|
|
|
private void DiscoverSystems()
|
|
{
|
|
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
|
|
|
foreach (var assembly in assemblies)
|
|
foreach (var type in assembly.GetTypes())
|
|
{
|
|
if (type.IsAbstract || !type.IsSubclassOf(typeof(GameSystemGroup)) || type.GetCustomAttribute<DisableDiscoveryAttribute>() != null) continue;
|
|
|
|
var systemGroup = (GameSystemGroup)Activator.CreateInstance(type);
|
|
systemGroup.UpdateFilter = _updateFilter;
|
|
|
|
_systemGroups.Add(systemGroup);
|
|
_systemGroupsByType.Add(type, systemGroup);
|
|
}
|
|
|
|
foreach (var systemGroup in _systemGroups)
|
|
{
|
|
if (systemGroup == _rootSystemGroup) continue;
|
|
|
|
var parent = GetContainingSystemGroup(systemGroup.GetType(), typeof(RootGameSystemGroup));
|
|
parent.Add(systemGroup);
|
|
}
|
|
|
|
foreach (var assembly in assemblies)
|
|
foreach (var type in assembly.GetTypes())
|
|
{
|
|
if (type.IsAbstract || !type.IsSubclassOf(typeof(GameSystem)) || type.GetCustomAttribute<DisableDiscoveryAttribute>() != null) continue;
|
|
|
|
var system = CreateSystem(type);
|
|
Systems.Add(system);
|
|
|
|
var systemGroup = GetContainingSystemGroup(type, typeof(DefaultGameSystemGroup));
|
|
systemGroup.Add(system);
|
|
}
|
|
}
|
|
|
|
private GameSystem CreateSystem(Type systemType)
|
|
{
|
|
var system = (GameSystem)Activator.CreateInstance(systemType, _serviceLocator);
|
|
|
|
var serviceAttributes = systemType.GetCustomAttributes<ServiceAttribute>();
|
|
foreach (var serviceAttribute in serviceAttributes)
|
|
{
|
|
var serviceType = serviceAttribute?.ServiceType ?? systemType;
|
|
_serviceLocator.RegisterService(serviceType, system);
|
|
}
|
|
|
|
if (system is IServiceProvider serviceProvider) serviceProvider.RegisterServices(_serviceLocator);
|
|
|
|
return system;
|
|
}
|
|
|
|
private GameSystemGroup GetContainingSystemGroup(Type type, Type defaultGroup)
|
|
{
|
|
var systemGroupAttribute = type.GetCustomAttribute<GameSystemGroupAttribute>();
|
|
var systemGroupType = systemGroupAttribute?.SystemGroupType ?? defaultGroup;
|
|
return _systemGroupsByType[systemGroupType];
|
|
}
|
|
|
|
private async UniTask InitializeAsync()
|
|
{
|
|
await _rootSystemGroup.InitializeAsync();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!IsInitialized) return;
|
|
|
|
_rootSystemGroup.Update();
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
Debug.Log("Systems disposing started");
|
|
_rootSystemGroup.Dispose();
|
|
Debug.Log("Systems disposing completed");
|
|
}
|
|
|
|
public void RegisterUpdateFilter(IUpdateFilter filter)
|
|
{
|
|
_updateFilter.Filters.Add(filter);
|
|
}
|
|
}
|
|
} |