summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <thorbjorn@lindeijer.nl>2012-05-27 23:26:19 +0200
committerThorbjørn Lindeijer <thorbjorn@lindeijer.nl>2013-01-09 17:12:15 +0100
commit0b339e547b77f80d6e81313bfb38249ce8995553 (patch)
treef22fee0142f72042430ace070a6e6ef4493e7c39 /src
parent16074a7c2c8197a061281a6880ddbc3967d8ea0c (diff)
downloadmanaserv-0b339e547b77f80d6e81313bfb38249ce8995553.tar.gz
manaserv-0b339e547b77f80d6e81313bfb38249ce8995553.tar.xz
manaserv-0b339e547b77f80d6e81313bfb38249ce8995553.zip
Replaced EventListener with signals based on libsigc++
This replaces the rather hard to understand event dispatcher with a probably even harder to understand templated library, but fortunately we can rely on the available documentation. Hopefully it will also help with the readability of our code and with adding additional signals to other classes. Added libsigc++ to README and Travis CI configuration. Reviewed-by: Erik Schilling
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt5
-rw-r--r--src/game-server/being.cpp27
-rw-r--r--src/game-server/being.h10
-rw-r--r--src/game-server/character.cpp10
-rw-r--r--src/game-server/character.h2
-rw-r--r--src/game-server/entity.cpp47
-rw-r--r--src/game-server/entity.h37
-rw-r--r--src/game-server/eventlistener.h102
-rw-r--r--src/game-server/monster.cpp83
-rw-r--r--src/game-server/monster.h23
-rw-r--r--src/game-server/quest.cpp78
-rw-r--r--src/game-server/spawnarea.cpp20
-rw-r--r--src/game-server/spawnarea.h2
-rw-r--r--src/game-server/state.cpp6
-rw-r--r--src/scripting/lua.cpp6
-rw-r--r--src/scripting/luascript.cpp2
-rw-r--r--src/scripting/luascript.h2
-rw-r--r--src/scripting/script.cpp3
-rw-r--r--src/scripting/script.h22
19 files changed, 150 insertions, 337 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5a4b38f..73f969f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,6 +1,7 @@
FIND_PACKAGE(LibXml2 REQUIRED)
FIND_PACKAGE(PhysFS REQUIRED)
FIND_PACKAGE(ZLIB REQUIRED)
+FIND_PACKAGE(SigC++ REQUIRED)
IF (CMAKE_COMPILER_IS_GNUCXX)
# Help getting compilation warnings
@@ -93,6 +94,8 @@ INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}
${PHYSFS_INCLUDE_DIR}
${LIBXML2_INCLUDE_DIR}
+ ${SigC++_INCLUDE_DIR}
+ ${SigC++Config_INCLUDE_DIR}
)
# Fix some stuff that gets not hidden by mainline modules
@@ -214,7 +217,6 @@ SET(SRCS_MANASERVGAME
game-server/effect.cpp
game-server/entity.h
game-server/entity.cpp
- game-server/eventlistener.h
game-server/gamehandler.h
game-server/gamehandler.cpp
game-server/inventory.h
@@ -315,6 +317,7 @@ FOREACH(program ${PROGRAMS})
${PHYSFS_LIBRARY}
${LIBXML2_LIBRARIES}
${ZLIB_LIBRARIES}
+ ${SigC++_LIBRARIES}
${OPTIONAL_LIBRARIES}
${EXTRA_LIBRARIES})
INSTALL(TARGETS ${program} RUNTIME DESTINATION ${PKG_BINDIR})
diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp
index ea7540c..9ce19d7 100644
--- a/src/game-server/being.cpp
+++ b/src/game-server/being.cpp
@@ -27,7 +27,6 @@
#include "game-server/attributemanager.h"
#include "game-server/character.h"
#include "game-server/collisiondetection.h"
-#include "game-server/eventlistener.h"
#include "game-server/mapcomposite.h"
#include "game-server/effect.h"
#include "game-server/skillmanager.h"
@@ -58,6 +57,9 @@ Being::Being(EntityType type):
Attribute(*it1->second)));
}
+
+ signal_inserted.connect(sigc::mem_fun(this, &Being::inserted));
+
// TODO: Way to define default base values?
// Should this be handled by the virtual modifiedAttribute?
// URGENT either way
@@ -177,14 +179,7 @@ void Being::died()
// reset target
mTarget = NULL;
- for (Listeners::iterator i = mListeners.begin(),
- i_end = mListeners.end(); i != i_end;)
- {
- const EventListener &l = **i;
- ++i; // In case the listener removes itself from the list on the fly.
- if (l.dispatch->died)
- l.dispatch->died(&l, this);
- }
+ signal_died.emit(this);
}
void Being::processAttacks()
@@ -512,6 +507,11 @@ bool Being::removeModifier(unsigned attr, double value, unsigned layer,
return ret;
}
+void Being::setGender(BeingGender gender)
+{
+ mGender = gender;
+}
+
void Being::setAttribute(unsigned id, double value)
{
AttributeMap::iterator ret = mAttributes.find(id);
@@ -743,20 +743,13 @@ void Being::update()
processAttacks();
}
-void Being::inserted()
+void Being::inserted(Entity *)
{
- Actor::inserted();
-
// Reset the old position, since after insertion it is important that it is
// in sync with the zone that we're currently present in.
mOld = getPosition();
}
-void Being::setGender(BeingGender gender)
-{
- mGender = gender;
-}
-
void Being::processAttack(Attack &attack)
{
performAttack(mTarget, attack.getAttackInfo()->getDamage());
diff --git a/src/game-server/being.h b/src/game-server/being.h
index 0083be1..a08df01 100644
--- a/src/game-server/being.h
+++ b/src/game-server/being.h
@@ -297,10 +297,7 @@ class Being : public Actor
void setTarget(Being *target)
{ mTarget = target; }
- /**
- * Overridden in order to reset the old position upon insertion.
- */
- virtual void inserted();
+ sigc::signal<void, Being *> signal_died;
protected:
/**
@@ -332,6 +329,11 @@ class Being : public Actor
Being(const Being &rhs);
Being &operator=(const Being &rhs);
+ /**
+ * Connected to signal_inserted to reset the old position.
+ */
+ void inserted(Entity *);
+
Path mPath;
BeingDirection mDirection; /**< Facing direction. */
diff --git a/src/game-server/character.cpp b/src/game-server/character.cpp
index 15ba940..a977799 100644
--- a/src/game-server/character.cpp
+++ b/src/game-server/character.cpp
@@ -24,7 +24,6 @@
#include "game-server/accountconnection.h"
#include "game-server/attributemanager.h"
#include "game-server/buysell.h"
-#include "game-server/eventlistener.h"
#include "game-server/inventory.h"
#include "game-server/item.h"
#include "game-server/itemmanager.h"
@@ -792,14 +791,7 @@ void Character::disconnected()
else
GameState::remove(this);
- for (Listeners::iterator i = mListeners.begin(),
- i_end = mListeners.end(); i != i_end;)
- {
- const EventListener &l = **i;
- ++i; // In case the listener removes itself from the list on the fly.
- if (l.dispatch->disconnected)
- l.dispatch->disconnected(&l, this);
- }
+ signal_disconnected.emit(this);
}
bool Character::takeSpecial(int id)
diff --git a/src/game-server/character.h b/src/game-server/character.h
index 5f3d3a6..d225081 100644
--- a/src/game-server/character.h
+++ b/src/game-server/character.h
@@ -428,6 +428,8 @@ class Character : public Being
virtual void removeAttack(AttackInfo *attackInfo);
+ sigc::signal<void, Character *> signal_disconnected;
+
protected:
/**
* Gets the way the actor blocks pathfinding for other objects
diff --git a/src/game-server/entity.cpp b/src/game-server/entity.cpp
index 671ef5e..6cb61e5 100644
--- a/src/game-server/entity.cpp
+++ b/src/game-server/entity.cpp
@@ -18,51 +18,4 @@
* along with The Mana Server. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <cassert>
-
#include "game-server/entity.h"
-
-#include "game-server/eventlistener.h"
-
-Entity::~Entity()
-{
- /* As another object will stop listening and call removeListener when it is
- deleted, the following assertion ensures that all the calls to
- removeListener have been performed will this object was still alive. It
- is not strictly necessary, as there are cases where no removal is
- performed (e.g. ~SpawnArea). But this is rather exceptional, so keep the
- assertion to catch all the other forgotten calls to removeListener. */
- assert(mListeners.empty());
-}
-
-void Entity::addListener(const EventListener *l)
-{
- mListeners.insert(l);
-}
-
-void Entity::removeListener(const EventListener *l)
-{
- mListeners.erase(l);
-}
-
-void Entity::inserted()
-{
- for (Listeners::iterator i = mListeners.begin(),
- i_end = mListeners.end(); i != i_end;)
- {
- const EventListener &l = **i;
- ++i; // In case the listener removes itself from the list on the fly.
- if (l.dispatch->inserted) l.dispatch->inserted(&l, this);
- }
-}
-
-void Entity::removed()
-{
- for (Listeners::iterator i = mListeners.begin(),
- i_end = mListeners.end(); i != i_end;)
- {
- const EventListener &l = **i;
- ++i; // In case the listener removes itself from the list on the fly.
- if (l.dispatch->removed) l.dispatch->removed(&l, this);
- }
-}
diff --git a/src/game-server/entity.h b/src/game-server/entity.h
index 652db7c..91f1369 100644
--- a/src/game-server/entity.h
+++ b/src/game-server/entity.h
@@ -23,18 +23,20 @@
#include "common/manaserv_protocol.h"
-using namespace ManaServ;
-
#include <set>
-class EventListener;
+#include <sigc++/signal.h>
+#include <sigc++/trackable.h>
+
+using namespace ManaServ;
+
class MapComposite;
/**
* Base class for in-game objects. Knows only its type and the map it resides
* on. Provides listeners.
*/
-class Entity
+class Entity : public sigc::trackable
{
public:
Entity(EntityType type, MapComposite *map = 0)
@@ -42,7 +44,7 @@ class Entity
mType(type)
{}
- virtual ~Entity();
+ virtual ~Entity() {}
/**
* Gets type of this entity.
@@ -88,29 +90,8 @@ class Entity
virtual void setMap(MapComposite *map)
{ mMap = map; }
- /**
- * Adds a new listener.
- */
- void addListener(const EventListener *);
-
- /**
- * Removes an existing listener.
- */
- void removeListener(const EventListener *);
-
- /**
- * Calls all the "inserted" listeners.
- */
- virtual void inserted();
-
- /**
- * Calls all the "removed" listeners.
- */
- virtual void removed();
-
- protected:
- typedef std::set< const EventListener * > Listeners;
- Listeners mListeners; /**< List of event listeners. */
+ sigc::signal<void, Entity *> signal_inserted;
+ sigc::signal<void, Entity *> signal_removed;
private:
MapComposite *mMap; /**< Map the entity is on */
diff --git a/src/game-server/eventlistener.h b/src/game-server/eventlistener.h
deleted file mode 100644
index 53d9207..0000000
--- a/src/game-server/eventlistener.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-#ifndef GAMESERVER_EVENTLISTENER_H
-#define GAMESERVER_EVENTLISTENER_H
-
-class Entity;
-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 *, Entity *);
-
- /**
- * Called just before something is removed from a map.
- */
- void (*removed)(const EventListener *, Entity *);
-
- /**
- * 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:
- * <code>&amp;EventListenerFactory&lt; _, DispatchPointerName &gt;::create&lt; _, MemberFunctionName &gt;::function</code>
- * 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
diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp
index cdfe063..330e3f4 100644
--- a/src/game-server/monster.cpp
+++ b/src/game-server/monster.cpp
@@ -35,18 +35,6 @@
#include <cmath>
-struct MonsterTargetEventDispatch: EventDispatch
-{
- MonsterTargetEventDispatch()
- {
- typedef EventListenerFactory<Monster, &Monster::mTargetListener> Factory;
- removed = &Factory::create< Entity, &Monster::forgetTarget >::function;
- died = &Factory::create<Entity, &Monster::forgetTarget, Being>::function;
- }
-};
-
-static MonsterTargetEventDispatch monsterTargetEventDispatch;
-
MonsterClass::~MonsterClass()
{
for (std::vector<AttackInfo *>::iterator it = mAttacks.begin(),
@@ -67,7 +55,6 @@ double MonsterClass::getVulnerability(Element element) const
Monster::Monster(MonsterClass *specy):
Being(OBJECT_MONSTER),
mSpecy(specy),
- mTargetListener(&monsterTargetEventDispatch),
mOwner(NULL)
{
LOG_DEBUG("Monster spawned! (id: " << mSpecy->getId() << ").");
@@ -137,12 +124,6 @@ Monster::Monster(MonsterClass *specy):
Monster::~Monster()
{
- // Remove death listeners.
- for (std::map<Being *, int>::iterator i = mAnger.begin(),
- i_end = mAnger.end(); i != i_end; ++i)
- {
- i->first->removeListener(&mTargetListener);
- }
}
void Monster::update()
@@ -229,11 +210,11 @@ void Monster::refreshTarget()
// Determine how much we hate the target
int targetPriority = 0;
- std::map<Being *, int, std::greater<Being *> >::iterator angerIterator;
- angerIterator = mAnger.find(target);
+ std::map<Being *, AggressionInfo>::iterator angerIterator = mAnger.find(target);
if (angerIterator != mAnger.end())
{
- targetPriority = angerIterator->second;
+ const AggressionInfo &aggressionInfo = angerIterator->second;
+ targetPriority = aggressionInfo.anger;
}
else if (mSpecy->isAggressive())
{
@@ -359,11 +340,15 @@ int Monster::calculatePositionPriority(Point position, int targetPriority)
}
}
-void Monster::forgetTarget(Entity *t)
+void Monster::forgetTarget(Entity *entity)
{
- Being *b = static_cast< Being * >(t);
+ Being *b = static_cast< Being * >(entity);
+ {
+ AggressionInfo &aggressionInfo = mAnger[b];
+ aggressionInfo.removedConnection.disconnect();
+ aggressionInfo.diedConnection.disconnect();
+ }
mAnger.erase(b);
- b->removeListener(&mTargetListener);
if (b->getType() == OBJECT_CHARACTER)
{
@@ -375,20 +360,42 @@ void Monster::forgetTarget(Entity *t)
void Monster::changeAnger(Actor *target, int amount)
{
- if (target && (target->getType() == OBJECT_MONSTER
- || target->getType() == OBJECT_CHARACTER))
+ const EntityType type = target->getType();
+ if (type != OBJECT_MONSTER && type != OBJECT_CHARACTER)
+ return;
+
+ Being *being = static_cast< Being * >(target);
+
+ if (mAnger.find(being) != mAnger.end())
{
- Being *t = static_cast< Being * >(target);
- if (mAnger.find(t) != mAnger.end())
- {
- mAnger[t] += amount;
- }
- else
- {
- mAnger[t] = amount;
- t->addListener(&mTargetListener);
- }
+ mAnger[being].anger += amount;
+ }
+ else
+ {
+ AggressionInfo &aggressionInfo = mAnger[being];
+ aggressionInfo.anger = amount;
+
+ // Forget target either when it's removed or died, whichever
+ // happens first.
+ aggressionInfo.removedConnection =
+ being->signal_removed.connect(sigc::mem_fun(this, &Monster::forgetTarget));
+ aggressionInfo.diedConnection =
+ being->signal_died.connect(sigc::mem_fun(this, &Monster::forgetTarget));
+ }
+}
+
+std::map<Being *, int> Monster::getAngerList() const
+{
+ std::map<Being *, int> result;
+ std::map<Being *, AggressionInfo>::const_iterator i, i_end;
+
+ for (i = mAnger.begin(), i_end = mAnger.end(); i != i_end; ++i)
+ {
+ const AggressionInfo &aggressionInfo = i->second;
+ result.insert(std::make_pair(i->first, aggressionInfo.anger));
}
+
+ return result;
}
int Monster::damage(Actor *source, const Damage &damage)
@@ -399,9 +406,7 @@ int Monster::damage(Actor *source, const Damage &damage)
newDamage.delta = newDamage.delta * factor;
int HPLoss = Being::damage(source, newDamage);
if (source)
- {
changeAnger(source, HPLoss);
- }
if (HPLoss && source && source->getType() == OBJECT_CHARACTER)
{
diff --git a/src/game-server/monster.h b/src/game-server/monster.h
index 73fec6a..3313345 100644
--- a/src/game-server/monster.h
+++ b/src/game-server/monster.h
@@ -22,7 +22,6 @@
#define MONSTER_H
#include "game-server/being.h"
-#include "game-server/eventlistener.h"
#include "common/defines.h"
#include "scripting/script.h"
#include "utils/string.h"
@@ -31,6 +30,9 @@
#include <vector>
#include <string>
+#include <sigc++/connection.h>
+
+class Character;
class ItemClass;
class Script;
@@ -315,8 +317,7 @@ class Monster : public Being
*/
void changeAnger(Actor *target, int amount);
- const std::map<Being *, int> &getAngerList() const
- { return mAnger; }
+ std::map<Being *, int> getAngerList() const;
/**
* Calls the damage function in Being and updates the aggro list
@@ -326,7 +327,7 @@ class Monster : public Being
/**
* Removes a being from the anger list.
*/
- void forgetTarget(Entity *being);
+ void forgetTarget(Entity *entity);
/**
* Called when an attribute modifier is changed.
@@ -351,10 +352,16 @@ class Monster : public Being
MonsterClass *mSpecy;
/** Aggression towards other beings. */
- std::map<Being *, int> mAnger;
-
- /** Listener for updating the anger list. */
- EventListener mTargetListener;
+ struct AggressionInfo {
+ AggressionInfo()
+ : anger(0)
+ {}
+
+ int anger;
+ sigc::connection removedConnection;
+ sigc::connection diedConnection;
+ };
+ std::map<Being *, AggressionInfo> mAnger;
/**
* Character who currently owns this monster (killsteal protection).
diff --git a/src/game-server/quest.cpp b/src/game-server/quest.cpp
index 4d65922..c28a421 100644
--- a/src/game-server/quest.cpp
+++ b/src/game-server/quest.cpp
@@ -18,24 +18,27 @@
* along with The Mana Server. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <cassert>
-#include <list>
-#include <map>
-#include <string>
-
#include "game-server/quest.h"
#include "game-server/accountconnection.h"
#include "game-server/character.h"
-#include "game-server/eventlistener.h"
#include "utils/logger.h"
+#include <cassert>
+#include <list>
+#include <map>
+#include <string>
+
+#include <sigc++/connection.h>
+
typedef std::list< QuestCallback * > QuestCallbacks;
typedef std::map< std::string, QuestCallbacks > PendingVariables;
struct PendingQuest
{
Character *character;
+ sigc::connection removedConnection;
+ sigc::connection disconnectedConnection;
PendingVariables variables;
};
@@ -72,22 +75,6 @@ void setQuestVar(Character *ch, const std::string &name,
accountHandler->updateCharacterVar(ch, name, value);
}
-/**
- * Listener for deleting related quests when a character disappears.
- */
-struct QuestDeathListener: EventDispatch
-{
- static void partialRemove(const EventListener *, Entity *);
-
- static void fullRemove(const EventListener *, Character *);
-
- QuestDeathListener()
- {
- removed = &partialRemove;
- disconnected = &fullRemove;
- }
-};
-
void QuestRefCallback::triggerCallback(Character *ch,
const std::string &value) const
{
@@ -103,10 +90,7 @@ void QuestRefCallback::triggerCallback(Character *ch,
s->execute();
}
-static QuestDeathListener questDeathDummy;
-static EventListener questDeathListener(&questDeathDummy);
-
-void QuestDeathListener::partialRemove(const EventListener *, Entity *t)
+static void partialRemove(Entity *t)
{
int id = static_cast< Character * >(t)->getDatabaseID();
PendingVariables &variables = pendingQuests[id].variables;
@@ -119,11 +103,18 @@ void QuestDeathListener::partialRemove(const EventListener *, Entity *t)
// The listener is kept in case a fullRemove is needed later.
}
-void QuestDeathListener::fullRemove(const EventListener *, Character *ch)
+static void fullRemove(Character *ch)
{
- ch->removeListener(&questDeathListener);
+ int id = ch->getDatabaseID();
+
+ {
+ PendingQuest &pendingQuest = pendingQuests[id];
+ pendingQuest.removedConnection.disconnect();
+ pendingQuest.disconnectedConnection.disconnect();
+ }
+
// Remove anything related to this character.
- pendingQuests.erase(ch->getDatabaseID());
+ pendingQuests.erase(id);
}
void recoverQuestVar(Character *ch, const std::string &name,
@@ -134,11 +125,19 @@ void recoverQuestVar(Character *ch, const std::string &name,
PendingQuests::iterator i = pendingQuests.lower_bound(id);
if (i == pendingQuests.end() || i->first != id)
{
- i = pendingQuests.insert(i, std::make_pair(id, PendingQuest()));
- i->second.character = ch;
- /* Register a listener, because we cannot afford to get invalid
- pointers, when we finally recover the variable. */
- ch->addListener(&questDeathListener);
+ PendingQuest pendingQuest;
+ pendingQuest.character = ch;
+
+ /* Connect to removed and disconnected signals, because we cannot
+ * afford to get invalid pointers, when we finally recover the
+ * variable.
+ */
+ pendingQuest.removedConnection =
+ ch->signal_removed.connect(sigc::ptr_fun(partialRemove));
+ pendingQuest.disconnectedConnection =
+ ch->signal_disconnected.connect(sigc::ptr_fun(fullRemove));
+
+ i = pendingQuests.insert(i, std::make_pair(id, pendingQuest));
}
i->second.variables[name].push_back(f);
accountHandler->requestCharacterVar(ch, name);
@@ -149,12 +148,14 @@ void recoveredQuestVar(int id,
const std::string &value)
{
PendingQuests::iterator i = pendingQuests.find(id);
- if (i == pendingQuests.end()) return;
+ if (i == pendingQuests.end())
+ return;
- Character *ch = i->second.character;
- ch->removeListener(&questDeathListener);
+ PendingQuest &pendingQuest = i->second;
+ pendingQuest.removedConnection.disconnect();
+ pendingQuest.disconnectedConnection.disconnect();
- PendingVariables &variables = i->second.variables;
+ PendingVariables &variables = pendingQuest.variables;
PendingVariables::iterator j = variables.find(name);
if (j == variables.end())
{
@@ -162,6 +163,7 @@ void recoveredQuestVar(int id,
return;
}
+ Character *ch = pendingQuest.character;
ch->questCache[name] = value;
// Call the registered callbacks.
diff --git a/src/game-server/spawnarea.cpp b/src/game-server/spawnarea.cpp
index 155d4c0..73dca6b 100644
--- a/src/game-server/spawnarea.cpp
+++ b/src/game-server/spawnarea.cpp
@@ -25,18 +25,6 @@
#include "game-server/state.h"
#include "utils/logger.h"
-struct SpawnAreaEventDispatch : EventDispatch
-{
- SpawnAreaEventDispatch()
- {
- typedef EventListenerFactory< SpawnArea, &SpawnArea::mSpawnedListener >
- Factory;
- removed = &Factory::create< Entity, &SpawnArea::decrease >::function;
- }
-};
-
-static SpawnAreaEventDispatch spawnAreaEventDispatch;
-
SpawnArea::SpawnArea(MapComposite *map,
MonsterClass *specy,
const Rectangle &zone,
@@ -44,7 +32,6 @@ SpawnArea::SpawnArea(MapComposite *map,
int spawnRate):
Entity(OBJECT_OTHER, map),
mSpecy(specy),
- mSpawnedListener(&spawnAreaEventDispatch),
mZone(zone),
mMaxBeings(maxBeings),
mSpawnRate(spawnRate),
@@ -102,7 +89,9 @@ void SpawnArea::update()
if (c)
{
- being->addListener(&mSpawnedListener);
+ being->signal_removed.connect(
+ sigc::mem_fun(this, &SpawnArea::decrease));
+
being->setMap(map);
being->setPosition(position);
being->clearDestination();
@@ -125,8 +114,7 @@ void SpawnArea::update()
}
}
-void SpawnArea::decrease(Entity *t)
+void SpawnArea::decrease(Entity *)
{
--mNumBeings;
- t->removeListener(&mSpawnedListener);
}
diff --git a/src/game-server/spawnarea.h b/src/game-server/spawnarea.h
index cc0642f..628c072 100644
--- a/src/game-server/spawnarea.h
+++ b/src/game-server/spawnarea.h
@@ -21,7 +21,6 @@
#ifndef SPAWNAREA_H
#define SPAWNAREA_H
-#include "game-server/eventlistener.h"
#include "game-server/entity.h"
#include "utils/point.h"
@@ -47,7 +46,6 @@ class SpawnArea : public Entity
private:
MonsterClass *mSpecy; /**< Specy of monster that spawns in this area. */
- EventListener mSpawnedListener; /**< Tracking of spawned monsters. */
Rectangle mZone;
int mMaxBeings; /**< Maximum population of this area. */
int mSpawnRate; /**< Number of beings spawning per minute. */
diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp
index ede94f8..a688cac 100644
--- a/src/game-server/state.cpp
+++ b/src/game-server/state.cpp
@@ -498,7 +498,7 @@ bool GameState::insert(Entity *ptr)
if (!ptr->isVisible())
{
map->insert(ptr);
- ptr->inserted();
+ ptr->signal_inserted.emit(ptr);
return true;
}
@@ -523,7 +523,7 @@ bool GameState::insert(Entity *ptr)
return false;
}
- obj->inserted();
+ obj->signal_inserted.emit(obj);
// DEBUG INFO
switch (obj->getType())
@@ -596,7 +596,7 @@ void GameState::remove(Entity *ptr)
MapComposite *map = ptr->getMap();
int visualRange = Configuration::getValue("game_visualRange", 448);
- ptr->removed();
+ ptr->signal_removed.emit(ptr);
// DEBUG INFO
switch (ptr->getType())
diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp
index 545e365..880216d 100644
--- a/src/scripting/lua.cpp
+++ b/src/scripting/lua.cpp
@@ -1709,7 +1709,11 @@ static int chr_get_post(lua_State *s)
static int being_register(lua_State *s)
{
Being *being = checkBeing(s, 1);
- being->addListener(getScript(s)->getScriptListener());
+ Script *script = getScript(s);
+
+ being->signal_died.connect(sigc::mem_fun(script, &Script::processDeathEvent));
+ being->signal_removed.connect(sigc::mem_fun(script, &Script::processRemoveEvent));
+
return 0;
}
diff --git a/src/scripting/luascript.cpp b/src/scripting/luascript.cpp
index 4104bc8..f4ea39a 100644
--- a/src/scripting/luascript.cpp
+++ b/src/scripting/luascript.cpp
@@ -265,8 +265,6 @@ void LuaScript::processRemoveEvent(Entity *entity)
// being. This might be very interesting for scripting quests.
execute();
}
-
- entity->removeListener(getScriptListener());
}
/**
diff --git a/src/scripting/luascript.h b/src/scripting/luascript.h
index 7631d98..9515bf0 100644
--- a/src/scripting/luascript.h
+++ b/src/scripting/luascript.h
@@ -28,6 +28,8 @@ extern "C" {
#include "scripting/script.h"
+class Character;
+
/**
* Implementation of the Script class for Lua.
*/
diff --git a/src/scripting/script.cpp b/src/scripting/script.cpp
index 3e29946..63ab7ff 100644
--- a/src/scripting/script.cpp
+++ b/src/scripting/script.cpp
@@ -40,8 +40,7 @@ Script::Ref Script::mUpdateCallback;
Script::Script():
mCurrentThread(0),
- mMap(0),
- mEventListener(&scriptEventDispatch)
+ mMap(0)
{}
Script::~Script()
diff --git a/src/scripting/script.h b/src/scripting/script.h
index 238bc34..8dee23a 100644
--- a/src/scripting/script.h
+++ b/src/scripting/script.h
@@ -23,19 +23,21 @@
#include "common/inventorydata.h"
#include "common/manaserv_protocol.h"
-#include "game-server/eventlistener.h"
#include <list>
#include <string>
#include <vector>
+#include <sigc++/trackable.h>
+
+class Being;
class MapComposite;
class Entity;
/**
* Abstract interface for calling functions written in an external language.
*/
-class Script
+class Script : public sigc::trackable
{
public:
/**
@@ -216,9 +218,6 @@ class Script
MapComposite *getMap() const
{ return mMap; }
- EventListener *getScriptListener()
- { return &mEventListener; }
-
virtual void processDeathEvent(Being *entity) = 0;
virtual void processRemoveEvent(Entity *entity) = 0;
@@ -235,7 +234,6 @@ class Script
private:
MapComposite *mMap;
- EventListener mEventListener; /**< Tracking of being deaths. */
std::vector<Thread*> mThreads;
static Ref mCreateNpcDelayedCallback;
@@ -245,16 +243,4 @@ class Script
friend class Thread;
};
-struct ScriptEventDispatch: EventDispatch
-{
- ScriptEventDispatch()
- {
- typedef EventListenerFactory< Script, &Script::mEventListener > Factory;
- died = &Factory::create< Being, &Script::processDeathEvent >::function;
- removed = &Factory::create< Entity, &Script::processRemoveEvent >::function;
- }
-};
-
-static ScriptEventDispatch scriptEventDispatch;
-
#endif // SCRIPTING_SCRIPT_H