Mineserver
A rewrite of Minecraft 1.8.9 in C++ !
Loading...
Searching...
No Matches
event.h
Go to the documentation of this file.
1
12#ifndef MINESERVER_EVENT_HPP
13#define MINESERVER_EVENT_HPP
14
15#include <functional>
16#include <type_traits>
17#include <plugins/luaheaders.h>
18
26template<class T>
27class IEvent
28{
29public:
39 static void loadLua(lua_State *state);
40};
41
42#ifndef DOXYGEN_IGNORE_THIS
43namespace logger
44{
45 void error(const char *format, ...);
46}
47#endif // DOXYGEN_IGNORE_THIS
48
55template <typename T>
56constexpr std::string_view type_name()
57{
58 std::string_view name, prefix, suffix;
59#ifdef __clang__
60 name = __PRETTY_FUNCTION__;
61 prefix = "auto type_name() [T = ";
62 suffix = "]";
63#elif defined(__GNUC__)
64 name = __PRETTY_FUNCTION__;
65 prefix = "constexpr auto type_name() [with T = ";
66 suffix = "]";
67#elif defined(_MSC_VER)
68 name = __FUNCSIG__;
69 prefix = "auto __cdecl type_name<";
70 suffix = ">(void)";
71#endif
72 name.remove_prefix(prefix.size());
73 name.remove_suffix(suffix.size());
74 return name;
75}
76
83template <class T>
85{
86public:
94 typedef std::function<void(T &)> callbackType;
100 typedef int subId;
101
102private:
103 struct subscription
104 {
105 callbackType callback;
106 subId id;
107 };
108
109 std::vector<subscription> subs;
110 subId nextId = 0;
111 const std::type_info *typeInfo;
112
119 subId getNextId()
120 {
121 return ++nextId;
122 }
123
124public:
131 EventHandler() : subs()
132 {
133 static_assert(std::is_base_of_v<IEvent<T>, T>, "Class doesn't derive from IEvent");
134 typeInfo = &typeid(T);
135 }
136
137 ~EventHandler() = default;
138
145 void fire(T &event)
146 {
147 for (auto &sub : subs)
148 {
149 try {
150 sub.callback(event);
151 }
152 catch (const std::exception &e)
153 {
154 logger::error("Could not launch event %s", std::string(type_name<T>()).c_str());
155 }
156 }
157 }
158
167 {
168 subscription s;
169 s.callback = static_cast<callbackType>(func);
170 s.id = getNextId();
171 subs.push_back(s);
172 return s.id;
173 }
174
183 {
184 subscription s;
185 s.callback = std::move(func);
186 s.id = getNextId();
187 subs.push_back(s);
188 return s.id;
189 }
190
198 {
199 subs.erase(
200 std::remove_if(
201 subs.begin(),
202 subs.end(),
203 [id](subscription el) -> bool
204 {
205 return el.id == id;
206 }),
207 subs.end());
208 }
209
216 const std::type_info *getTypeInfo() const { return typeInfo; }
217};
218
224{
225private:
226 std::vector<EventHandler<void *> *> handlers;
227 static EventsManager *INSTANCE;
228
229 template <class T>
230 EventHandler<T> *getOrNull()
231 {
232 auto loc = std::find_if(handlers.begin(), handlers.end(), [](const EventHandler<void *> *entry)
233 { return *entry->getTypeInfo() == typeid(T); });
234
235 if (loc == handlers.end())
236 return nullptr;
237
238 return reinterpret_cast<EventHandler<T> *>(*loc);
239 }
240
241 template <class T>
242 EventHandler<T> *getOrCreateHandler()
243 {
244 auto handler = getOrNull<T>();
245
246 if (!handler)
247 {
248 handler = new EventHandler<T>();
249 handlers.push_back(reinterpret_cast<EventHandler<void *> *>(handler));
250 }
251
252 return handler;
253 }
254
255public:
261
267 {
268 auto loc = handlers.begin();
269 while (loc != handlers.end())
270 {
271 delete *loc;
272 loc = handlers.erase(loc);
273 }
274 }
275
284 template <class T>
286 {
287 static_assert(std::is_base_of_v<IEvent<T>, T>, "Class doesn't derive from IEvent");
289 return handler->subscribe(callback);
290 }
291
300 template <class T>
302 {
303 static_assert(std::is_base_of_v<IEvent<T>, T>, "Class doesn't derive from IEvent");
305 return handler->subscribe(std::move(callback));
306 }
307
315 template <class T>
317 {
318 static_assert(std::is_base_of_v<IEvent<T>, T>, "Class doesn't derive from IEvent");
320 return handler->unsubscribe(subId);
321 }
322
330 template <class T>
331 void fire(T &event)
332 {
333 static_assert(std::is_base_of_v<IEvent<T>, T>, "Class doesn't derive from IEvent");
334 EventHandler<T> *handler = getOrNull<T>();
335
336 if (handler)
337 {
338 handler->fire(event);
339 }
340 }
341
347 static EventsManager *inst();
348};
349
350template<class T>
352 auto baseName = std::string(type_name<T>());
353 std::string cleanedEvent = baseName.substr(0, baseName.length() - std::string("Event").length());
354 static_assert(std::is_base_of_v<IEvent, T>, "Class doesn't derive from IEvent");
355 luabridge::getGlobalNamespace(state)
356 .beginNamespace("event")
357 .addFunction(("on"+cleanedEvent).c_str(), [](const luabridge::LuaRef& ref) {
358 if(!ref.isFunction())
359 return;
360
361 EventsManager::inst()->subscribe<T>(const_cast<luabridge::LuaRef&>(ref));
362 })
363 .template beginClass<T>(cleanedEvent.c_str())
364 .endClass()
365 .endNamespace();
366}
367
368#endif // MINESERVER_EVENT_HPP
Handler for a type of event.
Definition event.h:85
EventHandler()
Construct a new Event Handler object.
Definition event.h:131
void fire(T &event)
Fire an event.
Definition event.h:145
std::function< void(T &) callbackType)
The type of function that should be passed.
Definition event.h:94
int subId
The Subscription Id.
Definition event.h:100
void unsubscribe(subId id)
Unsubscribe from an event.
Definition event.h:197
const std::type_info * getTypeInfo() const
Get the Type Info of T.
Definition event.h:216
subId subscribe(callbackType &&func)
Subscribe to an event.
Definition event.h:182
subId subscribe(const callbackType &func)
Subscribe to an event.
Definition event.h:166
Manager for Events.
Definition event.h:224
~EventsManager()
Destroy the Events Manager object.
Definition event.h:266
EventsManager()
Construct a new Events Manager object.
Definition event.cpp:15
static EventsManager * inst()
Gets the instance of the events manager.
Definition event.cpp:20
void unsubscribe(typename EventHandler< T >::subId subId)
Unsubscribe to T event.
Definition event.h:316
EventHandler< T >::subId subscribe(typename EventHandler< T >::callbackType &&callback)
Subscribe to T event.
Definition event.h:301
void fire(T &event)
Fire T event.
Definition event.h:331
EventHandler< T >::subId subscribe(const typename EventHandler< T >::callbackType &callback)
Subscribe to T event.
Definition event.h:285
Event interface.
Definition event.h:28
static void loadLua(lua_State *state)
Loads the event to the lua state.
Definition event.h:351
constexpr std::string_view type_name()
Gets the name of the type paramater.
Definition event.h:56
Utility header file for lua things.
The logging namespace.
Definition logger.h:146
void error(const char *format,...)
Logs something at the ERROR level.
Definition logger.cpp:196