/* * The Mana Server * Copyright (C) 2007-2010 The Mana World Development Team * Copyright (C) 2010 The Mana Developers * * 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 . */ #include "luautil.h" #include #include "game-server/actorcomponent.h" #include "game-server/being.h" #include "game-server/entity.h" #include "game-server/itemmanager.h" #include "game-server/monster.h" #include "game-server/monstermanager.h" #include "utils/logger.h" #include "scripting/luascript.h" void raiseWarning(lua_State *, const char *format, ...) { va_list args; va_start(args, format); char message[1024]; vsprintf(message, format, args); va_end( args ); LOG_WARN("Lua script error: " << message); } bool UserDataCache::retrieve(lua_State *s) { // Retrieve the cache table lua_pushlightuserdata(s, &mRegistryKey); // object_key, key lua_rawget(s, LUA_REGISTRYINDEX); // object_key, Cache? if (lua_isnil(s, -1)) { lua_pop(s, 1); return false; } lua_pushvalue(s, -2); // object_key, Cache, object_key lua_rawget(s, -2); // object_key, Cache, UD? if (lua_isnil(s, -1)) { lua_pop(s, 2); // object_key return false; } lua_replace(s, -3); // UD, Cache lua_pop(s, 1); // UD return true; } void UserDataCache::insert(lua_State *s) { // Retrieve the cache table lua_pushlightuserdata(s, &mRegistryKey); // object_key, UD, key lua_rawget(s, LUA_REGISTRYINDEX); // object_key, UD, Cache? // Create the cache when it doesn't exist yet if (lua_isnil(s, -1)) { lua_pop(s, 1); // object_key, UD lua_newtable(s); // object_key, UD, Cache // The metatable that makes the values in the table above weak lua_createtable(s, 0, 1); // object_key, UD, Cache, {} lua_pushliteral(s, "__mode"); lua_pushliteral(s, "v"); lua_rawset(s, -3); // object_key, UD, Cache, { __mode = "v" } lua_setmetatable(s, -2); // object_key, UD, Cache lua_pushlightuserdata(s, &mRegistryKey);// object_key, UD, Cache, key lua_pushvalue(s, -2); // object_key, UD, Cache, key, Cache lua_rawset(s, LUA_REGISTRYINDEX); // object_key, UD, Cache } lua_pushvalue(s, -3); // object_key, UD, Cache, object_key lua_pushvalue(s, -3); // object_key, UD, Cache, object_key, UD lua_rawset(s, -3); // object_key, UD, Cache { object_key = UD } lua_pop(s, 1); // object_key, UD lua_replace(s, -2); // UD } UserDataCache LuaUserData::mUserDataCache; void LuaUserData::registerType(lua_State *s, const luaL_Reg *members) { luaL_newmetatable(s, "Entity"); // metatable lua_pushliteral(s, "__index"); // metatable, "__index" lua_createtable(s, 0, 0); // metatable, "__index", {} #if LUA_VERSION_NUM < 502 luaL_register(s, nullptr, members); #else luaL_setfuncs(s, members, 0); #endif // Make the functions table available as a global lua_pushvalue(s, -1); // metatable, "__index", {}, {} lua_setglobal(s, "Entity"); // metatable, "__index", {} lua_rawset(s, -3); // metatable lua_pop(s, 1); // -empty- } void LuaUserData::push(lua_State *s, Entity *entity) { if (!entity) { lua_pushnil(s); } else { #if LUA_VERSION_NUM < 502 lua_pushnumber(s, entity->getId()); #else lua_pushunsigned(s, entity->getId()); #endif if (!mUserDataCache.retrieve(s)) { void *userData = lua_newuserdata(s, sizeof(unsigned)); * static_cast(userData) = entity->getId(); #if LUA_VERSION_NUM < 502 luaL_newmetatable(s, "Entity"); lua_setmetatable(s, -2); #else luaL_setmetatable(s, "Entity"); #endif mUserDataCache.insert(s); } } } Entity *LuaUserData::check(lua_State *L, int narg) { void *userData = luaL_checkudata(L, narg, "Entity"); Entity *entity = findEntity(*(static_cast(userData))); luaL_argcheck(L, entity, narg, "invalid entity"); return entity; } Script *getScript(lua_State *s) { lua_pushlightuserdata(s, (void *)&LuaScript::registryKey); lua_gettable(s, LUA_REGISTRYINDEX); auto script = static_cast