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.entity.system;
13 
14 import std.traits : fullyQualifiedName;
15 
16 import star.entity.entity;
17 import star.entity.event;
18 
19 /// A generic system, encapsulating game logic.
20 interface System
21 {
22     /// Used to register events.
23     void configure(EventManager events);
24 
25     /// Used to update entities.
26     void update(EntityManager entities, EventManager events, double dt);
27 }
28 
29 /// Manages systems and their execution.
30 class SystemManager
31 {
32 public:
33     /// Constructor taking events and entities.
34     this(EntityManager entityManager, EventManager eventManager) pure nothrow @safe
35     {
36         _entityManager = entityManager;
37         _eventManager = eventManager;
38     }
39 
40     /// Add a system to the manager.
41     void add(S)(S system) pure nothrow @trusted if (is (S : System))
42     in
43     {
44         assert(!(system.classinfo.name in _systems));
45     }
46     body
47     {
48         _systems[system.classinfo.name] = system;
49         _systems.rehash();
50     }
51 
52     /// Remove a system from the manager.
53     void remove(S)(S system) pure nothrow @safe
54     {
55         _systems.remove(system.classinfo.name);
56     }
57 
58     /// Return the specified system.
59     inout(S) system(S)() inout pure nothrow @safe
60     {
61         if (S.classinfo.name in _systems)
62         {
63             return cast(inout(S)) _systems[S.classinfo.name];
64         }
65         else
66         {
67             return null;
68         }
69     }
70 
71     /// Configure every system added to the manager.
72     void configure()
73     {
74         foreach(system; _systems)
75         {
76             system.configure(_eventManager);
77         }
78         _configured = true;
79     }
80 
81     /// Update entities with the specified system.
82     void update(S)(double dt)
83     in
84     {
85         assert(_configured);
86     }
87     body
88     {
89         _systems[S.classinfo.name].update(_entityManager, _eventManager, dt);
90     }
91 
92 private:
93     EntityManager _entityManager;
94     EventManager _eventManager;
95     System[string] _systems;
96     bool _configured = false;
97 }