/*
* 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