diff --git a/client/scenes/world.cpp b/client/scenes/world.cpp index fd034d6..0a03516 100644 --- a/client/scenes/world.cpp +++ b/client/scenes/world.cpp @@ -947,6 +947,7 @@ void World::hCreatureMovement(CreaturePacket* const argPacket) { //------------------------- void World::hBarrierUpdate(BarrierPacket* const argPacket) { + std::cout << "Barrier Update" << std::endl; //Cull barriers that are too far away if ( (localCharacter->GetOrigin() - argPacket->origin).Length() > INFLUENCE_RADIUS) { //ignore beyond 1000 units @@ -967,7 +968,6 @@ void World::hBarrierUpdate(BarrierPacket* const argPacket) { } barrier->SetStatusArray(argPacket->status); barrier->CorrectSprite(); - } void World::hBarrierCreate(BarrierPacket* const argPacket) { diff --git a/rsc/scripts/setup_server.lua b/rsc/scripts/setup_server.lua index d11bc07..06d3967 100644 --- a/rsc/scripts/setup_server.lua +++ b/rsc/scripts/setup_server.lua @@ -43,6 +43,8 @@ doorUtility = require("door_utility") creatureAPI = require("creature") creatureManagerAPI = require("creature_manager") +barrierAPI = require("barrier") +barrierManagerAPI = require("barrier_manager") --testing creature tags local function bunnySquare(creature) @@ -60,8 +62,6 @@ local function bunnySquare(creature) creatureAPI.SetMotion(creature, 0, 1) end - - --is it time to change direction? if os.time() - tonumber(timestamp) >= 4 then -- print("changing directions") @@ -90,12 +90,51 @@ local function bunnySquare(creature) return ret end +local function barrierTick(barrier) + --load from the object + local statusTable = {} + for i = 1, 8 do + statusTable[i] = barrierAPI.GetStatus(barrier, i) + end + + --binary tick + for i = 1, 8, 0 do + if status[i] == 0 then + status[i] = 1 + break + else + status[i] = 0 + i = i + 1 + end + end + + --save to the object + for i = 1, 8 do + barrierAPI.GetStatus(barrier, i, statusTable[i]) + end +end + --test the room hooks roomManagerAPI.SetOnCreate(function(room, index) print("", "Creating room: ", roomAPI.GetName(room), index) + --TODO: (0) creatureManager with SetOnCreate + creatureManagerAPI.SetOnCreate(roomAPI.GetCreatureMgr(room), function(creature, index) + print ("making creature: ", index) + end) + print("Here it comes...") + creatureManagerAPI.Create(roomAPI.GetCreatureMgr(room), "anibunny.png", bunnySquare) + creatureManagerAPI.SetOnUnload(roomAPI.GetCreatureMgr(room), function(creature) + print("unloading creature...") + end) + + --TODO: (0) barrierManager with Create + barrierManagerAPI.SetOnCreate(roomAPI.GetBarrierMgr(room), function(barrier) + barrierAPI.SetScript(barrier, barrierTick) + end) + roomAPI.SetOnTick(room, function(room) roomAPI.ForEachCharacter(room, function(character) -- diff --git a/server/combat/barrier_manager.cpp b/server/combat/barrier_manager.cpp index 899d6fe..a174459 100644 --- a/server/combat/barrier_manager.cpp +++ b/server/combat/barrier_manager.cpp @@ -21,6 +21,8 @@ */ #include "barrier_manager.hpp" +#include "lua_utilities.hpp" + BarrierManager::BarrierManager() { //EMPTY } @@ -44,8 +46,7 @@ int BarrierManager::Create(int instanceIndex) { //implicitly create the new object elementMap.emplace( std::pair(counter, BarrierData(instanceIndex)) ); - //set the script - //TODO: (0) + runHook(lua, createRef, &elementMap.find(counter)->second, counter); //TODO: do various things like saving to the database return counter++; @@ -54,10 +55,14 @@ int BarrierManager::Create(int instanceIndex) { //TODO: (1) combat load, save void BarrierManager::Unload(int uid) { + runHook(lua, unloadRef, &elementMap.find(uid)->second, uid); elementMap.erase(uid); } void BarrierManager::UnloadAll() { + for (std::map::iterator it = elementMap.begin(); it != elementMap.end(); it++) { + runHook(lua, unloadRef, &it->second, it->first); + } elementMap.clear(); } @@ -65,6 +70,7 @@ void BarrierManager::UnloadIf(std::function::iterator it = elementMap.begin(); while (it != elementMap.end()) { if (fn(*it)) { + runHook(lua, unloadRef, &it->second, it->first); it = elementMap.erase(it); } else { @@ -122,4 +128,3 @@ int BarrierManager::GetCreateReference() { int BarrierManager::GetUnloadReference() { return unloadRef; } - diff --git a/server/combat/barrier_manager_api.cpp b/server/combat/barrier_manager_api.cpp index e926722..c684294 100644 --- a/server/combat/barrier_manager_api.cpp +++ b/server/combat/barrier_manager_api.cpp @@ -23,19 +23,96 @@ #include "barrier_manager.hpp" +//args: mgr, avatar, script +static int create(lua_State* L) { + //register the function at the top of the stack + lua_pushinteger(L, luaL_ref(L, LUA_REGISTRYINDEX)); + + //create the actual barrier + BarrierManager* mgr = static_cast(lua_touserdata(L, 1)); + int index = mgr->Create(-1); + BarrierData* barrier = mgr->Find(index); + lua_pushlightuserdata(L, static_cast(barrier)); + lua_pushinteger(L, index); + return 2; +} + +//TOOD: overload this to take the userdata as a parameter +static int unload(lua_State* L) { + BarrierManager* mgr = static_cast(lua_touserdata(L, 1)); + mgr->Unload(lua_tointeger(L, 2)); + return 0; +} + +static int unloadAll(lua_State* L) { + BarrierManager* mgr = static_cast(lua_touserdata(L, 1)); + mgr->UnloadAll(); + return 0; +} + +static int unloadIf(lua_State* L) { + BarrierManager* mgr = static_cast(lua_touserdata(L, 1)); + + //list of stuff to unload (don't invalidate iterators) + std::list unloadList; + + //unloadIf + for (auto it : *mgr->GetContainer()) { + //copy the function at the top + lua_pushvalue(L, -1); + + //index & object as function parameters + lua_pushinteger(L, it.first); + lua_pushlightuserdata(L, &it.second); + + //call + lua_pcall(L, 2, 1, 0); + + //unload-ish + if (lua_toboolean(L, -1)) { + unloadList.push_back(it.first); + } + } + + //actually unload + for (auto& it : unloadList) { + mgr->Unload(it); + } + return 0; +} + +static int find(lua_State* L) { + BarrierManager* mgr = static_cast(lua_touserdata(L, 1)); + BarrierData* barrier = mgr->Find(lua_tointeger(L, 2)); + lua_pushlightuserdata(L, static_cast(barrier)); + return 1; +} + +static int getLoadedCount(lua_State* L) { + BarrierManager* mgr = static_cast(lua_touserdata(L, 1)); + lua_pushinteger(L, mgr->GetLoadedCount()); + return 1; +} + static int setOnCreate(lua_State* L) { - BarrierManager* barrierMgr = static_cast(lua_touserdata(L, 1)); - barrierMgr->SetCreateReference(luaL_ref(L, LUA_REGISTRYINDEX)); + BarrierManager* mgr = static_cast(lua_touserdata(L, 1)); + mgr->SetCreateReference(luaL_ref(L, LUA_REGISTRYINDEX)); return 0; } static int setOnUnload(lua_State* L) { - BarrierManager* barrierMgr = static_cast(lua_touserdata(L, 1)); - barrierMgr->SetUnloadReference(luaL_ref(L, LUA_REGISTRYINDEX)); + BarrierManager* mgr = static_cast(lua_touserdata(L, 1)); + mgr->SetUnloadReference(luaL_ref(L, LUA_REGISTRYINDEX)); return 0; } static const luaL_Reg barrierManagerLib[] = { + {"Create", create}, + {"Unload", unload}, + {"UnloadAll", unloadAll}, + {"UnloadIf", unloadIf}, + {"Find", find}, + {"GetLoadedCount", getLoadedCount}, {"SetOnCreate", setOnCreate}, {"SetOnUnload", setOnUnload}, {nullptr, nullptr} diff --git a/server/creatures/creature_manager.cpp b/server/creatures/creature_manager.cpp index 75fb248..4b82eb3 100644 --- a/server/creatures/creature_manager.cpp +++ b/server/creatures/creature_manager.cpp @@ -21,6 +21,8 @@ */ #include "creature_manager.hpp" +#include "lua_utilities.hpp" + CreatureManager::CreatureManager() { //EMPTY } @@ -44,6 +46,8 @@ int CreatureManager::Create(std::string avatar, int scriptRef) { //implicitly create the new object elementMap.emplace( std::pair(counter, CreatureData(avatar, scriptRef)) ); + runHook(lua, createRef, &elementMap.find(counter)->second, counter); + //TODO: do various things like saving to the database return counter++; } @@ -51,10 +55,14 @@ int CreatureManager::Create(std::string avatar, int scriptRef) { //TODO: (1) creature load, save void CreatureManager::Unload(int uid) { + runHook(lua, unloadRef, &elementMap.find(uid)->second, uid); elementMap.erase(uid); } void CreatureManager::UnloadAll() { + for (std::map::iterator it = elementMap.begin(); it != elementMap.end(); it++) { + runHook(lua, unloadRef, &it->second, it->first); + } elementMap.clear(); } @@ -62,6 +70,7 @@ void CreatureManager::UnloadIf(std::function::iterator it = elementMap.begin(); while (it != elementMap.end()) { if (fn(*it)) { + runHook(lua, unloadRef, &it->second, it->first); it = elementMap.erase(it); } else { @@ -103,3 +112,19 @@ sqlite3* CreatureManager::SetDatabase(sqlite3* db) { sqlite3* CreatureManager::GetDatabase() { return database; } + +int CreatureManager::SetCreateReference(int i) { + return createRef = i; +} + +int CreatureManager::SetUnloadReference(int i) { + return unloadRef = i; +} + +int CreatureManager::GetCreateReference() { + return createRef; +} + +int CreatureManager::GetUnloadReference() { + return unloadRef; +} diff --git a/server/creatures/creature_manager.hpp b/server/creatures/creature_manager.hpp index 928f043..353abc1 100644 --- a/server/creatures/creature_manager.hpp +++ b/server/creatures/creature_manager.hpp @@ -56,10 +56,18 @@ public: sqlite3* SetDatabase(sqlite3* db); sqlite3* GetDatabase(); + int SetCreateReference(int i); + int SetUnloadReference(int i); + + int GetCreateReference(); + int GetUnloadReference(); + private: //members std::map elementMap; int counter = 0; lua_State* lua = nullptr; sqlite3* database = nullptr; + int createRef = LUA_NOREF; + int unloadRef = LUA_NOREF; }; diff --git a/server/creatures/creature_manager_api.cpp b/server/creatures/creature_manager_api.cpp index 982ed42..ea8f146 100644 --- a/server/creatures/creature_manager_api.cpp +++ b/server/creatures/creature_manager_api.cpp @@ -52,7 +52,32 @@ static int unloadAll(lua_State* L) { static int unloadIf(lua_State* L) { CreatureManager* mgr = static_cast(lua_touserdata(L, 1)); - //TODO: unloadIf + + //list of stuff to unload (don't invalidate iterators) + std::list unloadList; + + //unloadIf + for (auto it : *mgr->GetContainer()) { + //copy the function at the top + lua_pushvalue(L, -1); + + //index & object as function parameters + lua_pushinteger(L, it.first); + lua_pushlightuserdata(L, &it.second); + + //call + lua_pcall(L, 2, 1, 0); + + //unload-ish + if (lua_toboolean(L, -1)) { + unloadList.push_back(it.first); + } + } + + //actually unload + for (auto& it : unloadList) { + mgr->Unload(it); + } return 0; } @@ -69,13 +94,27 @@ static int getLoadedCount(lua_State* L) { return 1; } +static int setOnCreate(lua_State* L) { + CreatureManager* mgr = static_cast(lua_touserdata(L, 1)); + mgr->SetCreateReference(luaL_ref(L, LUA_REGISTRYINDEX)); + return 0; +} + +static int setOnUnload(lua_State* L) { + CreatureManager* mgr = static_cast(lua_touserdata(L, 1)); + mgr->SetUnloadReference(luaL_ref(L, LUA_REGISTRYINDEX)); + return 0; +} + static const luaL_Reg creatureManagerLib[] = { {"Create", create}, {"Unload", unload}, {"UnloadAll", unloadAll}, -// {"UnloadIf", unloadIf}, + {"UnloadIf", unloadIf}, {"Find", find}, {"GetLoadedCount", getLoadedCount}, + {"SetOnCreate", setOnCreate}, + {"SetOnUnload", setOnUnload}, {nullptr, nullptr} }; diff --git a/server/lua_utilities.cpp b/server/lua_utilities.cpp new file mode 100644 index 0000000..5695aa9 --- /dev/null +++ b/server/lua_utilities.cpp @@ -0,0 +1,47 @@ +/* Copyright: (c) Kayne Ruse 2013-2016 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "lua_utilities.hpp" + +#include +#include + +//this is for functions passed to SetOnCreate & SetOnUnload +int runHook(lua_State* L, int scriptRef, void* userdata, int index) { + //get the hook + lua_rawgeti(L, LUA_REGISTRYINDEX, scriptRef); + + if (lua_isnil(L, -1)) { + lua_pop(L, 1); + return -1; + } + + //push args + lua_pushlightuserdata(L, userdata); + lua_pushinteger(L, index); + + //call the function, 2 arg, 0 return + if (lua_pcall(L, 2, 0, 0) != LUA_OK) { + throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(L, -1) )); + } + + return 0; +} \ No newline at end of file diff --git a/server/lua_utilities.hpp b/server/lua_utilities.hpp new file mode 100644 index 0000000..4342492 --- /dev/null +++ b/server/lua_utilities.hpp @@ -0,0 +1,26 @@ +/* Copyright: (c) Kayne Ruse 2013-2016 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#pragma once + +#include "lua.hpp" + +int runHook(lua_State* L, int scriptRef, void* userdata, int index); \ No newline at end of file diff --git a/server/rooms/room_data.cpp b/server/rooms/room_data.cpp index 8819c74..37d8326 100644 --- a/server/rooms/room_data.cpp +++ b/server/rooms/room_data.cpp @@ -157,6 +157,7 @@ TriggerManager* RoomData::GetTriggerMgr() { lua_State* RoomData::SetLuaState(lua_State* L) { lua = L; + barrierMgr.SetLuaState(lua); creatureMgr.SetLuaState(lua); pager.SetLuaState(lua); triggerMgr.SetLuaState(lua); @@ -168,6 +169,7 @@ lua_State* RoomData::GetLuaState() { } sqlite3* RoomData::SetDatabase(sqlite3* db) { + //TODO: (1) set database here database = db; return database; } diff --git a/server/server_utilities.hpp b/server/server_utilities.hpp index eb49e25..900bec5 100644 --- a/server/server_utilities.hpp +++ b/server/server_utilities.hpp @@ -44,4 +44,4 @@ void copyBarrierToPacket(BarrierPacket* const packet, BarrierData* const barrier void pumpAndChangeRooms(int characterIndex, int newRoomIndex); void pumpAndChangeRooms(CharacterData* const characterData, int newRoomIndex, int characterIndex); -double distance(Vector2 lhs, Vector2 rhs); +double distance(Vector2 lhs, Vector2 rhs); \ No newline at end of file