1 module voxelman.eventdispatcher.plugin;
2 
3 import pluginlib;
4 import voxelman.core.config;
5 import tharsis.prof : Profiler;
6 
7 abstract class GameEvent {
8 	Profiler profiler;
9 	bool continuePropagation = true;
10 }
11 
12 template isGameEvent(T)
13 {
14 	enum bool isGameEvent = is(typeof(
15     (inout int = 0)
16     {
17     	T t;
18     	t.profiler = new Profiler(null);
19     	t.continuePropagation = true;
20     }));
21 }
22 
23 private class ValidGameEventClass : GameEvent {
24 
25 }
26 private struct ValidGameEvent {
27 	Profiler profiler;
28 	bool continuePropagation = true;
29 }
30 private struct InvalidEvent1 {}
31 private struct InvalidEvent2 {Profiler profiler;}
32 private struct InvalidEvent3 {bool continuePropagation;}
33 static assert(isGameEvent!ValidGameEvent);
34 static assert(isGameEvent!ValidGameEventClass);
35 static assert(!isGameEvent!InvalidEvent1);
36 static assert(!isGameEvent!InvalidEvent2);
37 static assert(!isGameEvent!InvalidEvent3);
38 
39 private alias EventHandler = void delegate(ref GameEvent event);
40 
41 shared static this()
42 {
43 	pluginRegistry.regClientPlugin(new EventDispatcherPlugin);
44 	pluginRegistry.regServerPlugin(new EventDispatcherPlugin);
45 }
46 
47 class EventDispatcherPlugin : IPlugin
48 {
49 	mixin IdAndSemverFrom!(voxelman.eventdispatcher.plugininfo);
50 
51 	Profiler profiler;
52 
53 	void subscribeToEvent(Event)(void delegate(ref Event event) handler)
54 	{
55 		static assert(isGameEvent!Event, Event.stringof ~ " must contain Profiler profiler; and bool continuePropagation;");
56 		_eventHandlers[typeid(Event)] ~= cast(EventHandler)handler;
57 	}
58 
59 	void postEvent(Event)(auto ref Event event)
60 	{
61 		static assert(isGameEvent!Event, stringof(Event) ~ " must contain Profiler profiler; and bool continuePropagation;");
62 		auto handlers = typeid(Event) in _eventHandlers;
63 		if (!handlers) return;
64 
65 		event.profiler = profiler;
66 		foreach(handler; *handlers)
67 		{
68 			(cast(void delegate(ref Event))handler)(event);
69 			if (!event.continuePropagation) break;
70 		}
71 	}
72 
73 private:
74 
75 	EventHandler[][TypeInfo] _eventHandlers;
76 }