/* * The Mana Server * Copyright (C) 2007-2010 The Mana World Development Team * * This file is part of The Mana Server. * * The Mana Server is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * any later version. * * The Mana Server is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with The Mana Server. If not, see . */ #ifndef GAMESERVER_EVENTLISTENER_H #define GAMESERVER_EVENTLISTENER_H class Thing; class Being; class Character; struct EventDispatch; /** * Pointer to a dispatch table. */ struct EventListener { const EventDispatch *dispatch; EventListener(const EventDispatch *d): dispatch(d) {} }; /** * Dispatch table for event notification. */ struct EventDispatch { /** * Called just after something is inserted in a map. */ void (*inserted)(const EventListener *, Thing *); /** * Called just before something is removed from a map. */ void (*removed)(const EventListener *, Thing *); /** * Called just after a being has died. */ void (*died)(const EventListener *, Being *); /** * Called just before a character is deleted. */ void (*disconnected)(const EventListener *, Character *); /** * Initializes dispatch methods as missing. */ EventDispatch(): inserted(0), removed(0), died(0), disconnected(0) {} }; /** * Helper for using member functions as dispatch methods. The 3-level structure * is due to default template parameter not being allowed on functions yet. * Conceptually, this helper takes two parameters: the name of the member * variable pointing to the dispatch table and the name of the member function * to call on dispatch. With these two parameters, it creates a dispatch * method. When called, this free function forwards the call to the member * function. * Pseudo-syntax for getting a dispatch method: * &EventListenerFactory< _, DispatchPointerName >::create< _, MemberFunctionName >::function * See the start of the spawnarea.cpp file for a complete example. */ template< class T, EventListener T::*D > struct EventListenerFactory { template< class U, void (T::*F)(U *), class V = U > struct create { static void function(const EventListener *d, V *u) { /* Get the address of the T object by substracting the offset of D from the pointer d. */ T *t = (T *)((char *)d - ((char *)&(((T *)42)->*D) - (char *)&(*(T *)42))); // Then call the method F of this T object. (t->*F)(u); } }; }; #endif