using System.Collections.Generic; using System.Linq; using EcsRx.Collections; using EcsRx.Collections.Database; using EcsRx.Events; using EcsRx.Executor; using EcsRx.Extensions; using EcsRx.Infrastructure.Dependencies; using EcsRx.Infrastructure.Extensions; using EcsRx.Infrastructure.Modules; using EcsRx.Infrastructure.Plugins; using EcsRx.Systems; namespace EcsRx.Infrastructure { public abstract class EcsRxApplication : IEcsRxApplication { public ISystemExecutor SystemExecutor { get; private set; } public IEventSystem EventSystem { get; private set; } public IEntityDatabase EntityDatabase { get; private set; } public IObservableGroupManager ObservableGroupManager { get; private set; } public IEnumerable Plugins => _plugins; private readonly List _plugins; public abstract IDependencyContainer Container { get; } protected EcsRxApplication() { _plugins = new List(); } /// /// This starts the process of initializing the application /// public virtual void StartApplication() { LoadModules(); LoadPlugins(); SetupPlugins(); ResolveApplicationDependencies(); BindSystems(); StartPluginSystems(); StartSystems(); ApplicationStarted(); } public virtual void StopApplication() { StopAndUnbindAllSystems(); } /// /// Load any modules that your application needs /// /// /// If you wish to use the default setup call through to base, if you wish to stop the default framework /// modules loading then do not call base and register your own internal framework module. /// protected virtual void LoadModules() { Container.LoadModule(new FrameworkModule()); } /// /// Load any plugins that your application needs /// /// It is recommended you just call RegisterPlugin method in here for each plugin you need protected virtual void LoadPlugins(){} /// /// Resolve any dependencies the application needs /// /// By default it will setup SystemExecutor, EventSystem, EntityCollectionManager protected virtual void ResolveApplicationDependencies() { SystemExecutor = Container.Resolve(); EventSystem = Container.Resolve(); EntityDatabase = Container.Resolve(); ObservableGroupManager = Container.Resolve(); } /// /// Bind any systems that the application will need /// /// By default will auto bind any systems within application scope protected virtual void BindSystems() { this.BindAllSystemsWithinApplicationScope(); } protected virtual void StopAndUnbindAllSystems() { var allSystems = SystemExecutor.Systems.ToList(); allSystems.ForEachRun(SystemExecutor.RemoveSystem); Container.Unbind(); } /// /// Start any systems that the application will need /// /// By default it will auto start any systems which have been bound protected virtual void StartSystems() { this.StartAllBoundSystems(); } protected abstract void ApplicationStarted(); protected void SetupPlugins() { Plugins.ForEachRun(x => x.SetupDependencies(Container)); } protected void StartPluginSystems() { Plugins.SelectMany(x => x.GetSystemsForRegistration(Container)) .ForEachRun(SystemExecutor.AddSystem); } /// /// Register a given plugin within the application /// /// The plugin to register protected void RegisterPlugin(IEcsRxPlugin plugin) { _plugins.Add(plugin); } } }