mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
Implement helpful __tostring
for all userdata-based classes
This commit is contained in:
parent
9ad23e4384
commit
747857bffa
22 changed files with 103 additions and 66 deletions
|
@ -330,7 +330,7 @@ void LuaAreaStore::Register(lua_State *L)
|
|||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<LuaAreaStore>(L, methods, metamethods);
|
||||
|
||||
// Can be created from Lua (AreaStore())
|
||||
lua_register(L, className, create_object);
|
||||
|
|
|
@ -90,29 +90,6 @@ bool ModApiBase::registerFunction(lua_State *L, const char *name,
|
|||
return true;
|
||||
}
|
||||
|
||||
void ModApiBase::registerClass(lua_State *L, const char *name,
|
||||
const luaL_Reg *methods,
|
||||
const luaL_Reg *metamethods)
|
||||
{
|
||||
luaL_newmetatable(L, name);
|
||||
luaL_register(L, NULL, metamethods);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_newtable(L);
|
||||
luaL_register(L, NULL, methods);
|
||||
int methodtable = lua_gettop(L);
|
||||
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_setfield(L, metatable, "__index");
|
||||
|
||||
// Protect the real metatable.
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_setfield(L, metatable, "__metatable");
|
||||
|
||||
// Pop methodtable and metatable.
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
int ModApiBase::l_deprecated_function(lua_State *L, const char *good, const char *bad, lua_CFunction func)
|
||||
{
|
||||
thread_local std::vector<u64> deprecated_logged;
|
||||
|
|
|
@ -60,9 +60,37 @@ public:
|
|||
lua_CFunction func,
|
||||
int top);
|
||||
|
||||
static void registerClass(lua_State *L, const char *name,
|
||||
template<typename T>
|
||||
static void registerClass(lua_State *L,
|
||||
const luaL_Reg *methods,
|
||||
const luaL_Reg *metamethods);
|
||||
const luaL_Reg *metamethods)
|
||||
{
|
||||
luaL_newmetatable(L, T::className);
|
||||
luaL_register(L, NULL, metamethods);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_newtable(L);
|
||||
luaL_register(L, NULL, methods);
|
||||
int methodtable = lua_gettop(L);
|
||||
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_setfield(L, metatable, "__index");
|
||||
|
||||
lua_getfield(L, metatable, "__tostring");
|
||||
bool default_tostring = lua_isnil(L, -1);
|
||||
lua_pop(L, 1);
|
||||
if (default_tostring) {
|
||||
lua_pushcfunction(L, ModApiBase::defaultToString<T>);
|
||||
lua_setfield(L, metatable, "__tostring");
|
||||
}
|
||||
|
||||
// Protect the real metatable.
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_setfield(L, metatable, "__metatable");
|
||||
|
||||
// Pop methodtable and metatable.
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline T *checkObject(lua_State *L, int narg)
|
||||
|
@ -84,4 +112,14 @@ public:
|
|||
* @return value from `func`
|
||||
*/
|
||||
static int l_deprecated_function(lua_State *L, const char *good, const char *bad, lua_CFunction func);
|
||||
|
||||
private:
|
||||
|
||||
template<typename T>
|
||||
static int defaultToString(lua_State *L)
|
||||
{
|
||||
auto *t = checkObject<T>(L, 1);
|
||||
lua_pushfstring(L, "%s: %p", T::className, t);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -175,7 +175,7 @@ void LuaCamera::Register(lua_State *L)
|
|||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<LuaCamera>(L, methods, metamethods);
|
||||
}
|
||||
|
||||
const char LuaCamera::className[] = "Camera";
|
||||
|
|
|
@ -124,7 +124,7 @@ void LuaRaycast::Register(lua_State *L)
|
|||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<LuaRaycast>(L, methods, metamethods);
|
||||
|
||||
lua_register(L, className, create_object);
|
||||
}
|
||||
|
|
|
@ -410,7 +410,7 @@ void InvRef::Register(lua_State *L)
|
|||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<InvRef>(L, methods, metamethods);
|
||||
|
||||
// Cannot be created from Lua
|
||||
//lua_register(L, className, create_object);
|
||||
|
|
|
@ -524,7 +524,7 @@ void LuaItemStack::Register(lua_State *L)
|
|||
{"__eq", l_equals},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<LuaItemStack>(L, methods, metamethods);
|
||||
|
||||
// Can be created from Lua (ItemStack(itemstack or itemstring or table or nil))
|
||||
lua_register(L, className, create_object);
|
||||
|
|
|
@ -81,7 +81,7 @@ void ItemStackMetaRef::create(lua_State *L, LuaItemStack *istack)
|
|||
|
||||
void ItemStackMetaRef::Register(lua_State *L)
|
||||
{
|
||||
registerMetadataClass(L, className, methods);
|
||||
registerMetadataClass<ItemStackMetaRef>(L, methods);
|
||||
}
|
||||
|
||||
const char ItemStackMetaRef::className[] = "ItemStackMetaRef";
|
||||
|
|
|
@ -464,7 +464,7 @@ void LuaLocalPlayer::Register(lua_State *L)
|
|||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<LuaLocalPlayer>(L, methods, metamethods);
|
||||
}
|
||||
|
||||
const char LuaLocalPlayer::className[] = "LocalPlayer";
|
||||
|
|
|
@ -315,20 +315,3 @@ int MetaDataRef::l_equals(lua_State *L)
|
|||
lua_pushboolean(L, *data1 == *data2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void MetaDataRef::registerMetadataClass(lua_State *L, const char *name,
|
||||
const luaL_Reg *methods)
|
||||
{
|
||||
const luaL_Reg metamethods[] = {
|
||||
{"__eq", l_equals},
|
||||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, name, methods, metamethods);
|
||||
|
||||
// Set metadata_class in the metatable for MetaDataRef::checkAnyMetadata.
|
||||
luaL_getmetatable(L, name);
|
||||
lua_pushstring(L, name);
|
||||
lua_setfield(L, -2, "metadata_class");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,22 @@ protected:
|
|||
virtual void handleToTable(lua_State *L, IMetadata *meta);
|
||||
virtual bool handleFromTable(lua_State *L, int table, IMetadata *meta);
|
||||
|
||||
static void registerMetadataClass(lua_State *L, const char *name, const luaL_Reg *methods);
|
||||
template<class T>
|
||||
static void registerMetadataClass(lua_State *L, const luaL_Reg *methods)
|
||||
{
|
||||
const luaL_Reg metamethods[] = {
|
||||
{"__eq", l_equals},
|
||||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass<T>(L, methods, metamethods);
|
||||
|
||||
// Set metadata_class in the metatable for MetaDataRef::checkAnyMetadata.
|
||||
luaL_getmetatable(L, T::className);
|
||||
lua_pushstring(L, T::className);
|
||||
lua_setfield(L, -2, "metadata_class");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
// Exported functions
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ void LuaMinimap::Register(lua_State *L)
|
|||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<LuaMinimap>(L, methods, metamethods);
|
||||
}
|
||||
|
||||
const char LuaMinimap::className[] = "Minimap";
|
||||
|
|
|
@ -77,7 +77,7 @@ void ModChannelRef::Register(lua_State *L)
|
|||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<ModChannelRef>(L, methods, metamethods);
|
||||
}
|
||||
|
||||
void ModChannelRef::create(lua_State *L, const std::string &channel)
|
||||
|
|
|
@ -186,7 +186,7 @@ const char NodeMetaRef::className[] = "NodeMetaRef";
|
|||
|
||||
void NodeMetaRef::Register(lua_State *L)
|
||||
{
|
||||
registerMetadataClass(L, className, methodsServer);
|
||||
registerMetadataClass<NodeMetaRef>(L, methodsServer);
|
||||
}
|
||||
|
||||
|
||||
|
@ -211,7 +211,7 @@ const luaL_Reg NodeMetaRef::methodsServer[] = {
|
|||
|
||||
void NodeMetaRef::RegisterClient(lua_State *L)
|
||||
{
|
||||
registerMetadataClass(L, className, methodsClient);
|
||||
registerMetadataClass<NodeMetaRef>(L, methodsClient);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ void NodeTimerRef::Register(lua_State *L)
|
|||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<NodeTimerRef>(L, methods, metamethods);
|
||||
|
||||
// Cannot be created from Lua
|
||||
//lua_register(L, className, create_object);
|
||||
|
|
|
@ -101,7 +101,7 @@ void LuaValueNoise::Register(lua_State *L)
|
|||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<LuaValueNoise>(L, methods, metamethods);
|
||||
|
||||
lua_register(L, className, create_object);
|
||||
|
||||
|
@ -360,7 +360,7 @@ void LuaValueNoiseMap::Register(lua_State *L)
|
|||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<LuaValueNoiseMap>(L, methods, metamethods);
|
||||
|
||||
lua_register(L, className, create_object);
|
||||
|
||||
|
@ -449,7 +449,7 @@ void LuaPseudoRandom::Register(lua_State *L)
|
|||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<LuaPseudoRandom>(L, methods, metamethods);
|
||||
|
||||
lua_register(L, className, create_object);
|
||||
}
|
||||
|
@ -562,7 +562,7 @@ void LuaPcgRandom::Register(lua_State *L)
|
|||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<LuaPcgRandom>(L, methods, metamethods);
|
||||
|
||||
lua_register(L, className, create_object);
|
||||
}
|
||||
|
@ -652,7 +652,7 @@ void LuaSecureRandom::Register(lua_State *L)
|
|||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<LuaSecureRandom>(L, methods, metamethods);
|
||||
|
||||
lua_register(L, className, create_object);
|
||||
}
|
||||
|
|
|
@ -69,8 +69,27 @@ RemotePlayer *ObjectRef::getplayer(ObjectRef *ref)
|
|||
|
||||
// Exported functions
|
||||
|
||||
int ObjectRef::mt_tostring(lua_State *L)
|
||||
{
|
||||
auto *ref = checkObject<ObjectRef>(L, 1);
|
||||
if (getobject(ref)) {
|
||||
if (auto *player = getplayer(ref)) {
|
||||
lua_pushfstring(L, "ObjectRef (player): %s", player->getName().c_str());
|
||||
} else if (auto *entitysao = getluaobject(ref)) {
|
||||
lua_pushfstring(L, "ObjectRef (entity): %s (id: %d)",
|
||||
entitysao->getName().c_str(), entitysao->getId());
|
||||
} else {
|
||||
lua_pushfstring(L, "ObjectRef (?): %p", ref);
|
||||
}
|
||||
} else {
|
||||
lua_pushfstring(L, "ObjectRef (invalid): %p", ref);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// garbage collector
|
||||
int ObjectRef::gc_object(lua_State *L) {
|
||||
int ObjectRef::gc_object(lua_State *L)
|
||||
{
|
||||
ObjectRef *obj = *(ObjectRef **)(lua_touserdata(L, 1));
|
||||
delete obj;
|
||||
return 0;
|
||||
|
@ -2806,9 +2825,10 @@ void ObjectRef::Register(lua_State *L)
|
|||
{
|
||||
static const luaL_Reg metamethods[] = {
|
||||
{"__gc", gc_object},
|
||||
{"__tostring", mt_tostring},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<ObjectRef>(L, methods, metamethods);
|
||||
}
|
||||
|
||||
const char ObjectRef::className[] = "ObjectRef";
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "lua_api/l_base.h"
|
||||
#include "irrlichttypes.h"
|
||||
#include <lua.h>
|
||||
|
||||
class ServerActiveObject;
|
||||
class LuaEntitySAO;
|
||||
|
@ -48,6 +49,9 @@ private:
|
|||
|
||||
// Exported functions
|
||||
|
||||
// __tostring metamethod
|
||||
static int mt_tostring(lua_State *L);
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ void PlayerMetaRef::create(lua_State *L, ServerEnvironment *env, std::string_vie
|
|||
|
||||
void PlayerMetaRef::Register(lua_State *L)
|
||||
{
|
||||
registerMetadataClass(L, className, methods);
|
||||
registerMetadataClass<PlayerMetaRef>(L, methods);
|
||||
}
|
||||
|
||||
const char PlayerMetaRef::className[] = "PlayerMetaRef";
|
||||
|
|
|
@ -362,7 +362,7 @@ void LuaSettings::Register(lua_State* L)
|
|||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<LuaSettings>(L, methods, metamethods);
|
||||
|
||||
// Can be created from Lua (Settings(filename))
|
||||
lua_register(L, className, create_object);
|
||||
|
|
|
@ -36,7 +36,7 @@ void StorageRef::create(lua_State *L, const std::string &mod_name, ModStorageDat
|
|||
|
||||
void StorageRef::Register(lua_State *L)
|
||||
{
|
||||
registerMetadataClass(L, className, methods);
|
||||
registerMetadataClass<StorageRef>(L, methods);
|
||||
}
|
||||
|
||||
IMetadata* StorageRef::getmeta(bool auto_create)
|
||||
|
|
|
@ -425,7 +425,7 @@ void LuaVoxelManip::Register(lua_State *L)
|
|||
{"__gc", gc_object},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass(L, className, methods, metamethods);
|
||||
registerClass<LuaVoxelManip>(L, methods, metamethods);
|
||||
|
||||
// Can be created from Lua (VoxelManip())
|
||||
lua_register(L, className, create_object);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue