riversong code showcase
This commit is contained in:
155
Source/Engine/Core/EngineRunner.cs
Normal file
155
Source/Engine/Core/EngineRunner.cs
Normal file
@@ -0,0 +1,155 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user