diff --git a/rsc/scripts/setup_server.lua b/rsc/scripts/setup_server.lua index 8e498a3..9f30182 100644 --- a/rsc/scripts/setup_server.lua +++ b/rsc/scripts/setup_server.lua @@ -11,6 +11,14 @@ local function dumpTable(t) end end +--test the room hooks +roomSystem.RoomManager.SetOnCreate(function(room, index) + print("", "Creating room: ", roomSystem.Room.GetName(room), index) +end) +roomSystem.RoomManager.SetOnUnload(function(room, index) + print("", "Unloading room: ", roomSystem.Room.GetName(room), index) +end) + --NOTE: room 0 is the first that the client asks for, therefore it must exist local overworld, uid = roomSystem.RoomManager.CreateRoom("overworld", "overworld.bmp") roomSystem.Room.Initialize(overworld, mapSaver.Load, mapSaver.Save, mapMaker.DebugIsland, mapSaver.Save) diff --git a/server/rooms/room_manager.cpp b/server/rooms/room_manager.cpp index 1ba26ca..78916a8 100644 --- a/server/rooms/room_manager.cpp +++ b/server/rooms/room_manager.cpp @@ -40,24 +40,76 @@ int RoomManager::Create(std::string roomName, std::string tileset) { newRoom->monsterMgr.SetDatabase(database); newRoom->waypointMgr.SetLuaState(lua); + //get the hook + lua_rawgeti(lua, LUA_REGISTRYINDEX, createRef); + + if(!lua_isnil(lua, -1)) { + lua_pushlightuserdata(lua, newRoom); + lua_pushinteger(lua, counter); + //call the function, 2 arg, 0 return + if (lua_pcall(lua, 2, 0, 0) != LUA_OK) { + throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) )); + } + } + //finish the routine return counter++; } void RoomManager::UnloadAll() { + //get the hook + lua_rawgeti(lua, LUA_REGISTRYINDEX, unloadRef); + + if(!lua_isnil(lua, -1)) { + //pass each room to the hook + for (auto& it : elementMap) { + lua_pushvalue(lua, -1); //copy the hook + lua_pushlightuserdata(lua, &it.second); + lua_pushinteger(lua, it.first); + //call the function, 2 arg, 0 return + if (lua_pcall(lua, 2, 0, 0) != LUA_OK) { + throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) )); + } + } + } + + //pop the hook or nil + lua_pop(lua, 1); + elementMap.clear(); } void RoomManager::UnloadIf(std::function)> fn) { + //get the hook + lua_rawgeti(lua, LUA_REGISTRYINDEX, unloadRef); + + //get the element std::map::iterator it = elementMap.begin(); + + //jenky pattern while (it != elementMap.end()) { if (fn(*it)) { + + if(!lua_isnil(lua, -1)) { + lua_pushvalue(lua, -1); //copy the hook + lua_pushlightuserdata(lua, &it->second); + lua_pushinteger(lua, it->first); + + //call the function, 2 arg, 0 return + if (lua_pcall(lua, 2, 0, 0) != LUA_OK) { + throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) )); + } + } + it = elementMap.erase(it); } else { ++it; } } + + //pop the hook or nil + lua_pop(lua, 1); } void RoomManager::PushCharacter(CharacterData* character) { @@ -133,3 +185,19 @@ sqlite3* RoomManager::SetDatabase(sqlite3* db) { sqlite3* RoomManager::GetDatabase() { return database; } + +int RoomManager::SetCreateReference(int i) { + return createRef = i; +} + +int RoomManager::SetUnloadReference(int i) { + return unloadRef = i; +} + +int RoomManager::GetCreateReference() { + return createRef; +} + +int RoomManager::GetUnloadReference() { + return unloadRef; +} diff --git a/server/rooms/room_manager.hpp b/server/rooms/room_manager.hpp index 6e21382..00b44de 100644 --- a/server/rooms/room_manager.hpp +++ b/server/rooms/room_manager.hpp @@ -49,12 +49,19 @@ public: int GetLoadedCount(); std::map* GetContainer(); - //hooks + //API interfaces lua_State* SetLuaState(lua_State* L); lua_State* GetLuaState(); sqlite3* SetDatabase(sqlite3* db); sqlite3* GetDatabase(); + //hooks + int SetCreateReference(int i); + int SetUnloadReference(int i); + + int GetCreateReference(); + int GetUnloadReference(); + private: friend Singleton; @@ -66,6 +73,10 @@ private: lua_State* lua = nullptr; sqlite3* database = nullptr; int counter = 0; + + //hooks + int createRef = LUA_NOREF; + int unloadRef = LUA_NOREF; }; #endif diff --git a/server/rooms/room_manager_api.cpp b/server/rooms/room_manager_api.cpp index 1d4ba15..9269de4 100644 --- a/server/rooms/room_manager_api.cpp +++ b/server/rooms/room_manager_api.cpp @@ -96,10 +96,27 @@ int getRoom(lua_State* L) { return 1; } +static int setOnCreate(lua_State* L) { + RoomManager& roomMgr = RoomManager::GetSingleton(); + luaL_unref(L, LUA_REGISTRYINDEX, roomMgr.GetCreateReference()); + roomMgr.SetCreateReference(luaL_ref(L, LUA_REGISTRYINDEX)); + return 0; +} + +static int setOnUnload(lua_State* L) { + RoomManager& roomMgr = RoomManager::GetSingleton(); + luaL_unref(L, LUA_REGISTRYINDEX, roomMgr.GetUnloadReference()); + roomMgr.SetUnloadReference(luaL_ref(L, LUA_REGISTRYINDEX)); + return 0; +} + + static const luaL_Reg roomManagerLib[] = { {"CreateRoom", createRoom}, {"UnloadRoom", unloadRoom}, {"GetRoom", getRoom}, + {"SetOnCreate", setOnCreate}, + {"SetOnUnload", setOnUnload}, {nullptr, nullptr} };