From 5f8ac3c36c88c4f6bf98a9877340b11e2bdd95e3 Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Thu, 16 Aug 2012 22:21:46 +0200 Subject: Set the current map when executing being callbacks The on_death and on_remove callbacks where not being executed in the context of any map. Now they execute in the context of the map of the being. Reviewed-by: Erik Schilling --- src/scripting/luascript.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/scripting/luascript.cpp') diff --git a/src/scripting/luascript.cpp b/src/scripting/luascript.cpp index e2b127f7..97b03e1d 100644 --- a/src/scripting/luascript.cpp +++ b/src/scripting/luascript.cpp @@ -241,6 +241,7 @@ void LuaScript::processDeathEvent(Being *entity) { if (mDeathNotificationCallback.isValid()) { + setMap(entity->getMap()); prepare(mDeathNotificationCallback); push(entity); //TODO: get and push a list of creatures who contributed to killing the @@ -253,6 +254,7 @@ void LuaScript::processRemoveEvent(Entity *entity) { if (mRemoveNotificationCallback.isValid()) { + setMap(entity->getMap()); prepare(mRemoveNotificationCallback); push(entity); //TODO: get and push a list of creatures who contributed to killing the -- cgit v1.2.3-70-g09d2 From 2594084de6e163f15a1516d64cf413de5b0d899f Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Tue, 8 Jan 2013 18:03:02 +0100 Subject: Added support for Lua 5.2 Should still work against Lua 5.1 as well. --- src/scripting/lua.cpp | 9 +++++++++ src/scripting/luascript.cpp | 4 ++++ src/scripting/luautil.h | 11 ++++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) (limited to 'src/scripting/luascript.cpp') diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index 6285f382..c0aedfdd 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -2575,7 +2575,11 @@ LuaScript::LuaScript(): // Register package loader that goes through the resource manager // table.insert(package.loaders, 2, require_loader) lua_getglobal(mRootState, "package"); +#if LUA_VERSION_NUM < 502 lua_getfield(mRootState, -1, "loaders"); +#else + lua_getfield(mRootState, -1, "searchers"); +#endif lua_pushcfunction(mRootState, require_loader); lua_rawseti(mRootState, -2, 2); lua_pop(mRootState, 2); @@ -2699,8 +2703,13 @@ LuaScript::LuaScript(): { "get_special_info", &get_special_info }, { NULL, NULL } }; +#if LUA_VERSION_NUM < 502 lua_pushvalue(mRootState, LUA_GLOBALSINDEX); luaL_register(mRootState, NULL, callbacks); +#else + lua_pushglobaltable(mRootState); + luaL_setfuncs(mRootState, callbacks, 0); +#endif lua_pop(mRootState, 1); // pop the globals table static luaL_Reg const members_AttackInfo[] = { diff --git a/src/scripting/luascript.cpp b/src/scripting/luascript.cpp index 97b03e1d..a3dcb1d4 100644 --- a/src/scripting/luascript.cpp +++ b/src/scripting/luascript.cpp @@ -151,7 +151,11 @@ bool LuaScript::resume() setMap(mCurrentThread->mMap); const int tmpNbArgs = nbArgs; nbArgs = -1; +#if LUA_VERSION_NUM < 502 int result = lua_resume(mCurrentState, tmpNbArgs); +#else + int result = lua_resume(mCurrentState, NULL, tmpNbArgs); +#endif setMap(0); if (result == 0) // Thread is done diff --git a/src/scripting/luautil.h b/src/scripting/luautil.h index 1ff2ab8d..0d2a981d 100644 --- a/src/scripting/luautil.h +++ b/src/scripting/luautil.h @@ -103,7 +103,12 @@ public: luaL_newmetatable(s, mTypeName); // metatable lua_pushstring(s, "__index"); // metatable, "__index" - luaL_register(s, typeName, members); // metatable, "__index", {} + lua_createtable(s, 0, 0); // metatable, "__index", {} +#if LUA_VERSION_NUM < 502 + luaL_register(s, NULL, members); +#else + luaL_setfuncs(s, members, 0); +#endif lua_rawset(s, -3); // metatable lua_pop(s, 1); // -empty- } @@ -125,8 +130,12 @@ public: void *userData = lua_newuserdata(s, sizeof(T*)); * static_cast(userData) = object; +#if LUA_VERSION_NUM < 502 luaL_newmetatable(s, mTypeName); lua_setmetatable(s, -2); +#else + luaL_setmetatable(s, mTypeName); +#endif UserDataCache::insert(s, object); } -- cgit v1.2.3-70-g09d2 From 562b403a66a6a96d883620b27455564d50e3d49b Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Wed, 9 Jan 2013 11:47:16 +0100 Subject: Micro-optimizations for pushing strings to Lua Use lua_pushliteral and lua_pushlstring instead of lua_pushstring, which avoids Lua having to determine the length of the string. --- src/scripting/lua.cpp | 56 +++++++++++++++++++-------------------------- src/scripting/luascript.cpp | 2 +- src/scripting/luautil.cpp | 4 ++-- src/scripting/luautil.h | 4 ++-- 4 files changed, 29 insertions(+), 37 deletions(-) (limited to 'src/scripting/luascript.cpp') diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index c0aedfdd..545e365e 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -458,8 +458,6 @@ static int chr_get_inventory(lua_State *s) int firstTableStackPosition = lua_gettop(s); int tableIndex = 1; - std::string itemName = ""; - for (InventoryData::const_iterator it = invData.begin(), it_end = invData.end(); it != it_end; ++it) { @@ -470,20 +468,19 @@ static int chr_get_inventory(lua_State *s) lua_createtable(s, 0, 4); int subTableStackPosition = lua_gettop(s); // Stores the item info in it. - lua_pushstring(s, "slot"); + lua_pushliteral(s, "slot"); lua_pushinteger(s, it->first); // The slot id lua_settable(s, subTableStackPosition); - lua_pushstring(s, "id"); + lua_pushliteral(s, "id"); lua_pushinteger(s, it->second.itemId); lua_settable(s, subTableStackPosition); - lua_pushstring(s, "name"); - itemName = itemManager->getItem(it->second.itemId)->getName(); - lua_pushstring(s, itemName.c_str()); + lua_pushliteral(s, "name"); + push(s, itemManager->getItem(it->second.itemId)->getName()); lua_settable(s, subTableStackPosition); - lua_pushstring(s, "amount"); + lua_pushliteral(s, "amount"); lua_pushinteger(s, it->second.amount); lua_settable(s, subTableStackPosition); @@ -517,7 +514,6 @@ static int chr_get_equipment(lua_State *s) int firstTableStackPosition = lua_gettop(s); int tableIndex = 1; - std::string itemName; std::set itemInstances; for (EquipData::const_iterator it = equipData.begin(), @@ -534,17 +530,16 @@ static int chr_get_equipment(lua_State *s) lua_createtable(s, 0, 3); int subTableStackPosition = lua_gettop(s); // Stores the item info in it. - lua_pushstring(s, "slot"); + lua_pushliteral(s, "slot"); lua_pushinteger(s, it->first); // The slot id lua_settable(s, subTableStackPosition); - lua_pushstring(s, "id"); + lua_pushliteral(s, "id"); lua_pushinteger(s, it->second.itemId); lua_settable(s, subTableStackPosition); - lua_pushstring(s, "name"); - itemName = itemManager->getItem(it->second.itemId)->getName(); - lua_pushstring(s, itemName.c_str()); + lua_pushliteral(s, "name"); + push(s, itemManager->getItem(it->second.itemId)->getName()); lua_settable(s, subTableStackPosition); // Add the sub-table as value of the main one. @@ -1127,7 +1122,7 @@ static int being_remove_attribute_modifier(lua_State *s) static int being_get_name(lua_State *s) { Being *being = checkBeing(s, 1); - lua_pushstring(s, being->getName().c_str()); + push(s, being->getName()); return 1; } @@ -1309,7 +1304,7 @@ static int monster_get_name(lua_State *s) luaL_error(s, "monster_get_name called with unknown monster id."); return 0; } - lua_pushstring(s, spec->getName().c_str()); + push(s, spec->getName()); return 1; } @@ -1386,7 +1381,7 @@ static int chr_get_quest(lua_State *s) bool res = getQuestVar(q, name, value); if (res) { - lua_pushstring(s, value.c_str()); + push(s, value); return 1; } QuestCallback *f = new QuestThreadCallback(&LuaScript::getQuestCallback, @@ -1453,7 +1448,7 @@ static int chr_try_get_quest(lua_State *s) std::string value; bool res = getQuestVar(q, name, value); if (res) - lua_pushstring(s, value.c_str()); + push(s, value); else lua_pushnil(s); return 1; @@ -1469,9 +1464,8 @@ static int getvar_map(lua_State *s) luaL_argcheck(s, name[0] != 0, 1, "empty variable name"); MapComposite *map = checkCurrentMap(s); - std::string value = map->getVariable(name); - lua_pushstring(s, value.c_str()); + push(s, map->getVariable(name)); return 1; } @@ -1500,8 +1494,7 @@ static int getvar_world(lua_State *s) const char *name = luaL_checkstring(s, 1); luaL_argcheck(s, name[0] != 0, 1, "empty variable name"); - std::string value = GameState::getVariable(name); - lua_pushstring(s, value.c_str()); + push(s, GameState::getVariable(name)); return 1; } @@ -2128,8 +2121,7 @@ static int get_map_property(lua_State *s) const char *property = luaL_checkstring(s, 1); Map *map = checkCurrentMap(s)->getMap(); - std::string value = map->getProperty(property); - lua_pushstring(s, value.c_str()); + push(s, map->getProperty(property)); return 1; } @@ -2210,7 +2202,7 @@ static int item_get_name(lua_State *s) luaL_error(s, "item_get_name called with unknown item id."); return 0; } - lua_pushstring(s, it->getName().c_str()); + push(s, it->getName()); return 1; } @@ -2314,7 +2306,7 @@ static int map_object_get_property(lua_State *s) std::string property = obj->getProperty(key); if (!property.empty()) { - lua_pushstring(s, property.c_str()); + push(s, property); return 1; } else @@ -2346,7 +2338,7 @@ static int map_object_get_bounds(lua_State *s) static int map_object_get_name(lua_State *s) { MapObject *obj = LuaMapObject::check(s, 1); - lua_pushstring(s, obj->getName().c_str()); + push(s, obj->getName()); return 1; } @@ -2357,7 +2349,7 @@ static int map_object_get_name(lua_State *s) static int map_object_get_type(lua_State *s) { MapObject *obj = LuaMapObject::check(s, 1); - lua_pushstring(s, obj->getType().c_str()); + push(s, obj->getType()); return 1; } @@ -2398,7 +2390,7 @@ static int get_special_info(lua_State *s) static int specialinfo_get_name(lua_State *s) { SpecialManager::SpecialInfo *info = LuaSpecialInfo::check(s, 1); - lua_pushstring(s, info->name.c_str()); + push(s, info->name); return 1; } @@ -2419,7 +2411,7 @@ static int specialinfo_is_rechargeable(lua_State *s) static int specialinfo_get_category(lua_State *s) { SpecialManager::SpecialInfo *info = LuaSpecialInfo::check(s, 1); - lua_pushstring(s, info->setName.c_str()); + push(s, info->setName); return 1; } @@ -2559,7 +2551,7 @@ static int require_loader(lua_State *s) if (!path.empty()) luaL_loadfile(s, path.c_str()); else - lua_pushstring(s, "File not found"); + lua_pushliteral(s, "File not found"); return 1; } @@ -2573,7 +2565,7 @@ LuaScript::LuaScript(): luaL_openlibs(mRootState); // Register package loader that goes through the resource manager - // table.insert(package.loaders, 2, require_loader) + // package.loaders[2] = require_loader lua_getglobal(mRootState, "package"); #if LUA_VERSION_NUM < 502 lua_getfield(mRootState, -1, "loaders"); diff --git a/src/scripting/luascript.cpp b/src/scripting/luascript.cpp index a3dcb1d4..4104bc89 100644 --- a/src/scripting/luascript.cpp +++ b/src/scripting/luascript.cpp @@ -82,7 +82,7 @@ void LuaScript::push(int v) void LuaScript::push(const std::string &v) { assert(nbArgs >= 0); - lua_pushstring(mCurrentState, v.c_str()); + lua_pushlstring(mCurrentState, v.c_str(), v.length()); ++nbArgs; } diff --git a/src/scripting/luautil.cpp b/src/scripting/luautil.cpp index 3de23c77..f7b39e29 100644 --- a/src/scripting/luautil.cpp +++ b/src/scripting/luautil.cpp @@ -86,8 +86,8 @@ void UserDataCache::insert(lua_State *s, void *object) // The metatable that makes the values in the table above weak lua_newtable(s); // UD, Cache, {} - lua_pushstring(s, "__mode"); - lua_pushstring(s, "v"); + lua_pushliteral(s, "__mode"); + lua_pushliteral(s, "v"); lua_rawset(s, -3); // UD, Cache, { __mode = "v" } lua_setmetatable(s, -2); // UD, Cache diff --git a/src/scripting/luautil.h b/src/scripting/luautil.h index 0d2a981d..8e380d4e 100644 --- a/src/scripting/luautil.h +++ b/src/scripting/luautil.h @@ -102,7 +102,7 @@ public: mTypeName = typeName; luaL_newmetatable(s, mTypeName); // metatable - lua_pushstring(s, "__index"); // metatable, "__index" + lua_pushliteral(s, "__index"); // metatable, "__index" lua_createtable(s, 0, 0); // metatable, "__index", {} #if LUA_VERSION_NUM < 502 luaL_register(s, NULL, members); @@ -197,7 +197,7 @@ inline void push(lua_State *s, int val) inline void push(lua_State *s, const std::string &val) { - lua_pushstring(s, val.c_str()); + lua_pushlstring(s, val.c_str(), val.length()); } inline void push(lua_State *s, Entity *val) -- cgit v1.2.3-70-g09d2 From 0b339e547b77f80d6e81313bfb38249ce8995553 Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Sun, 27 May 2012 23:26:19 +0200 Subject: 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 --- .travis.yml | 2 +- CMake/Modules/FindSigC++.cmake | 34 +++++++++++++ CMake/Modules/LibFindMacros.cmake | 99 ++++++++++++++++++++++++++++++++++++ README | 13 ++--- src/CMakeLists.txt | 5 +- src/game-server/being.cpp | 27 ++++------ src/game-server/being.h | 10 ++-- src/game-server/character.cpp | 10 +--- src/game-server/character.h | 2 + src/game-server/entity.cpp | 47 ------------------ src/game-server/entity.h | 37 ++++---------- src/game-server/eventlistener.h | 102 -------------------------------------- src/game-server/monster.cpp | 83 ++++++++++++++++--------------- src/game-server/monster.h | 23 ++++++--- src/game-server/quest.cpp | 78 +++++++++++++++-------------- src/game-server/spawnarea.cpp | 20 ++------ src/game-server/spawnarea.h | 2 - src/game-server/state.cpp | 6 +-- src/scripting/lua.cpp | 6 ++- src/scripting/luascript.cpp | 2 - src/scripting/luascript.h | 2 + src/scripting/script.cpp | 3 +- src/scripting/script.h | 22 ++------ 23 files changed, 291 insertions(+), 344 deletions(-) create mode 100644 CMake/Modules/FindSigC++.cmake create mode 100644 CMake/Modules/LibFindMacros.cmake delete mode 100644 src/game-server/eventlistener.h (limited to 'src/scripting/luascript.cpp') diff --git a/.travis.yml b/.travis.yml index bbebefd2..b56d187b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,5 +4,5 @@ compiler: - clang before_install: - sudo apt-get update -qq - - sudo apt-get install -qq sqlite3 cmake make gcc libxml2-dev liblua5.1-0-dev libphysfs-dev libsqlite3-dev libsdl-gfx1.2-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-net1.2-dev libsdl-pango-dev libsdl-ttf2.0-dev libsdl1.2-dev libguichan-dev libphysfs-dev libenet1a libcurl4-openssl-dev libcurl3 zlib1g-dev libmysqlclient-dev + - sudo apt-get install -qq sqlite3 cmake make gcc libxml2-dev liblua5.1-0-dev libphysfs-dev libsqlite3-dev libsdl-gfx1.2-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-net1.2-dev libsdl-pango-dev libsdl-ttf2.0-dev libsdl1.2-dev libguichan-dev libphysfs-dev libenet1a libcurl4-openssl-dev libcurl3 zlib1g-dev libmysqlclient-dev libsigc++-2.0-dev script: cmake . -DWITH_MYSQL=ON && make diff --git a/CMake/Modules/FindSigC++.cmake b/CMake/Modules/FindSigC++.cmake new file mode 100644 index 00000000..35687d5b --- /dev/null +++ b/CMake/Modules/FindSigC++.cmake @@ -0,0 +1,34 @@ +# - Try to find SigC++-2.0 +# Once done, this will define +# +# SigC++_FOUND - system has SigC++ +# SigC++_INCLUDE_DIRS - the SigC++ include directories +# SigC++_LIBRARIES - link these to use SigC++ + +include(LibFindMacros) + +# Use pkg-config to get hints about paths +libfind_pkg_check_modules(SigC++_PKGCONF sigc++-2.0) + +# Main include dir +find_path(SigC++_INCLUDE_DIR + NAMES sigc++/sigc++.h + PATHS ${SigC++_PKGCONF_INCLUDE_DIRS} + PATH_SUFFIXES sigc++-2.0 +) + +# Glib-related libraries also use a separate config header, which is in lib dir +find_path(SigC++Config_INCLUDE_DIR + NAMES sigc++config.h + PATHS ${SigC++_PKGCONF_INCLUDE_DIRS} /usr + PATH_SUFFIXES lib/sigc++-2.0/include +) + +libfind_library(SigC++ sigc 2.0) + +# Set the include dir variables and the libraries and let libfind_process do +# the rest. NOTE: Singular variables for this library, plural for libraries +# this this lib depends on. +set(SigC++_PROCESS_INCLUDES SigC++_INCLUDE_DIR SigC++Config_INCLUDE_DIR) +set(SigC++_PROCESS_LIBS SigC++_LIBRARY) +libfind_process(SigC++) diff --git a/CMake/Modules/LibFindMacros.cmake b/CMake/Modules/LibFindMacros.cmake new file mode 100644 index 00000000..69975c51 --- /dev/null +++ b/CMake/Modules/LibFindMacros.cmake @@ -0,0 +1,99 @@ +# Works the same as find_package, but forwards the "REQUIRED" and "QUIET" arguments +# used for the current package. For this to work, the first parameter must be the +# prefix of the current package, then the prefix of the new package etc, which are +# passed to find_package. +macro (libfind_package PREFIX) + set (LIBFIND_PACKAGE_ARGS ${ARGN}) + if (${PREFIX}_FIND_QUIETLY) + set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} QUIET) + endif (${PREFIX}_FIND_QUIETLY) + if (${PREFIX}_FIND_REQUIRED) + set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} REQUIRED) + endif (${PREFIX}_FIND_REQUIRED) + find_package(${LIBFIND_PACKAGE_ARGS}) +endmacro (libfind_package) + +# CMake developers made the UsePkgConfig system deprecated in the same release (2.6) +# where they added pkg_check_modules. Consequently I need to support both in my scripts +# to avoid those deprecated warnings. Here's a helper that does just that. +# Works identically to pkg_check_modules, except that no checks are needed prior to use. +macro (libfind_pkg_check_modules PREFIX PKGNAME) + if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4) + include(UsePkgConfig) + pkgconfig(${PKGNAME} ${PREFIX}_INCLUDE_DIRS ${PREFIX}_LIBRARY_DIRS ${PREFIX}_LDFLAGS ${PREFIX}_CFLAGS) + else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(${PREFIX} ${PKGNAME}) + endif (PKG_CONFIG_FOUND) + endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4) +endmacro (libfind_pkg_check_modules) + +# Do the final processing once the paths have been detected. +# If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain +# all the variables, each of which contain one include directory. +# Ditto for ${PREFIX}_PROCESS_LIBS and library files. +# Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES. +# Also handles errors in case library detection was required, etc. +macro (libfind_process PREFIX) + # Skip processing if already processed during this run + if (NOT ${PREFIX}_FOUND) + # Start with the assumption that the library was found + set (${PREFIX}_FOUND TRUE) + + # Process all includes and set _FOUND to false if any are missing + foreach (i ${${PREFIX}_PROCESS_INCLUDES}) + if (${i}) + set (${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIRS} ${${i}}) + mark_as_advanced(${i}) + else (${i}) + set (${PREFIX}_FOUND FALSE) + endif (${i}) + endforeach (i) + + # Process all libraries and set _FOUND to false if any are missing + foreach (i ${${PREFIX}_PROCESS_LIBS}) + if (${i}) + set (${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARIES} ${${i}}) + mark_as_advanced(${i}) + else (${i}) + set (${PREFIX}_FOUND FALSE) + endif (${i}) + endforeach (i) + + # Print message and/or exit on fatal error + if (${PREFIX}_FOUND) + if (NOT ${PREFIX}_FIND_QUIETLY) + message (STATUS "Found ${PREFIX} ${${PREFIX}_VERSION}") + endif (NOT ${PREFIX}_FIND_QUIETLY) + else (${PREFIX}_FOUND) + if (${PREFIX}_FIND_REQUIRED) + foreach (i ${${PREFIX}_PROCESS_INCLUDES} ${${PREFIX}_PROCESS_LIBS}) + message("${i}=${${i}}") + endforeach (i) + message (FATAL_ERROR "Required library ${PREFIX} NOT FOUND.\nInstall the library (dev version) and try again. If the library is already installed, use ccmake to set the missing variables manually.") + endif (${PREFIX}_FIND_REQUIRED) + endif (${PREFIX}_FOUND) + endif (NOT ${PREFIX}_FOUND) +endmacro (libfind_process) + +macro(libfind_library PREFIX basename) + set(TMP "") + if(MSVC80) + set(TMP -vc80) + endif(MSVC80) + if(MSVC90) + set(TMP -vc90) + endif(MSVC90) + set(${PREFIX}_LIBNAMES ${basename}${TMP}) + if(${ARGC} GREATER 2) + set(${PREFIX}_LIBNAMES ${basename}${TMP}-${ARGV2}) + string(REGEX REPLACE "\\." "_" TMP ${${PREFIX}_LIBNAMES}) + set(${PREFIX}_LIBNAMES ${${PREFIX}_LIBNAMES} ${TMP}) + endif(${ARGC} GREATER 2) + find_library(${PREFIX}_LIBRARY + NAMES ${${PREFIX}_LIBNAMES} + PATHS ${${PREFIX}_PKGCONF_LIBRARY_DIRS} + ) +endmacro(libfind_library) + diff --git a/README b/README index 06e56ce6..34faafcf 100644 --- a/README +++ b/README @@ -6,15 +6,16 @@ COMPILATION Before trying to compile, make sure all the dependencies are installed. For each dependency the Ubuntu package name is listed as well as the website. - * libxml2 (libxml2-dev) - http://xmlsoft.org/ - * Lua (liblua5.1-0-dev) - http://lua.org/ - * PhysFS (libphysfs-dev) - http://icculus.org/physfs/ - * SQLite 3 (libsqlite3-dev) - http://sqlite.org/ - * zlib (zlib1g-dev) - http://zlib.net/ + * libsigc++ 2.0 (libsigc++-2.0-dev) - http://libsigc.sourceforge.net/ + * libxml2 (libxml2-dev) - http://xmlsoft.org/ + * Lua (liblua5.1-0-dev) - http://lua.org/ + * PhysFS (libphysfs-dev) - http://icculus.org/physfs/ + * SQLite 3 (libsqlite3-dev) - http://sqlite.org/ + * zlib (zlib1g-dev) - http://zlib.net/ Optional dependencies: - * MySQL (libmysqlclient-dev) - http://dev.mysql.com/ + * MySQL (libmysqlclient-dev) - http://dev.mysql.com/ (replaces the SQLite 3 depency) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5a4b38fc..73f969f7 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 ea7540ca..9ce19d76 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 0083be1f..a08df018 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 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 15ba940a..a9777991 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 5f3d3a64..d225081b 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 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 671ef5e6..6cb61e58 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 . */ -#include - #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 652db7c7..91f13699 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 -class EventListener; +#include +#include + +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 signal_inserted; + sigc::signal 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 53d92077..00000000 --- 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 . - */ - -#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: - * &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 diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp index cdfe063a..330e3f4f 100644 --- a/src/game-server/monster.cpp +++ b/src/game-server/monster.cpp @@ -35,18 +35,6 @@ #include -struct MonsterTargetEventDispatch: EventDispatch -{ - MonsterTargetEventDispatch() - { - typedef EventListenerFactory Factory; - removed = &Factory::create< Entity, &Monster::forgetTarget >::function; - died = &Factory::create::function; - } -}; - -static MonsterTargetEventDispatch monsterTargetEventDispatch; - MonsterClass::~MonsterClass() { for (std::vector::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::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 >::iterator angerIterator; - angerIterator = mAnger.find(target); + std::map::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 Monster::getAngerList() const +{ + std::map result; + std::map::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 73fec6aa..3313345c 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 #include +#include + +class Character; class ItemClass; class Script; @@ -315,8 +317,7 @@ class Monster : public Being */ void changeAnger(Actor *target, int amount); - const std::map &getAngerList() const - { return mAnger; } + std::map 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 mAnger; - - /** Listener for updating the anger list. */ - EventListener mTargetListener; + struct AggressionInfo { + AggressionInfo() + : anger(0) + {} + + int anger; + sigc::connection removedConnection; + sigc::connection diedConnection; + }; + std::map mAnger; /** * Character who currently owns this monster (killsteal protection). diff --git a/src/game-server/quest.cpp b/src/game-server/quest.cpp index 4d659227..c28a4213 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 . */ -#include -#include -#include -#include - #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 +#include +#include +#include + +#include + 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 155d4c0d..73dca6b2 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 cc0642f1..628c072e 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 ede94f86..a688caca 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 545e365e..880216d2 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 4104bc89..f4ea39ac 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 7631d982..9515bf0e 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 3e299461..63ab7ff4 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 238bc34c..8dee23a9 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 #include #include +#include + +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 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 -- cgit v1.2.3-70-g09d2