1 ///
2 /// Defines an architecture to manage systems.
3 /// Systems must implement the System interface.
4 ///
5 /// Copyright: Copyright (c) 2014 James Zhu.
6 ///
7 /// License: MIT License (Expat). See accompanying file LICENSE.
8 ///
9 /// Authors: James Zhu <github.com/jzhu98>
10 ///
11 
12 module star.system;
13 
14 import star.entity;
15 import star.event;
16 
17 /// A generic system, encapsulating game logic.
18 interface System
19 {
20     /// Used to register events.
21     void configure(EventManager events);
22 
23     /// Used to update entities.
24     void update(EntityManager entities, EventManager events, double dt);
25 }
26 
27 /// Manages systems and their execution.
28 class SystemManager
29 {
30 public:
31     /// Constructor taking events and entities.
32     this(EntityManager entityManager, EventManager eventManager) pure nothrow @safe
33     {
34         _entityManager = entityManager;
35         _eventManager = eventManager;
36     }
37 
38     /// Add a system to the manager.
39     void add(System system) pure nothrow @trusted
40     in
41     {
42         assert(!(system.classinfo.name in _systems));
43     }
44     body
45     {
46         _systems[system.classinfo.name] = system;
47         _systems.rehash();
48     }
49 
50     /// Remove a system from the manager.
51     void remove(System system) pure nothrow @safe
52     {
53         _systems.remove(system.classinfo.name);
54     }
55 
56     /// Return the specified system.
57     S system(S)() pure nothrow @safe
58     {
59         auto sys = (S.classinfo.name in _systems);
60         if (sys)
61         {
62             return *sys;
63         }
64         else
65         {
66             return null;
67         }
68     }
69 
70     /// Configure every system added to the manager.
71     void configure()
72     {
73         foreach(system; _systems)
74         {
75             system.configure(_eventManager);
76         }
77         _configured = true;
78     }
79 
80     /// Update entities with the specified system.
81     void update(S)(double dt)
82     in
83     {
84         assert(_configured);
85     }
86     body
87     {
88         _systems[S.classinfo.name].update(_entitySystem, dt);
89     }
90 
91 private:
92     EntityManager _entityManager;
93     EventManager _eventManager;
94     System[string] _systems;
95     bool _configured = false;
96 }