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},
|
{"__gc", gc_object},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
registerClass(L, className, methods, metamethods);
|
registerClass<LuaAreaStore>(L, methods, metamethods);
|
||||||
|
|
||||||
// Can be created from Lua (AreaStore())
|
// Can be created from Lua (AreaStore())
|
||||||
lua_register(L, className, create_object);
|
lua_register(L, className, create_object);
|
||||||
|
|
|
@ -90,29 +90,6 @@ bool ModApiBase::registerFunction(lua_State *L, const char *name,
|
||||||
return true;
|
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)
|
int ModApiBase::l_deprecated_function(lua_State *L, const char *good, const char *bad, lua_CFunction func)
|
||||||
{
|
{
|
||||||
thread_local std::vector<u64> deprecated_logged;
|
thread_local std::vector<u64> deprecated_logged;
|
||||||
|
|
|
@ -60,9 +60,37 @@ public:
|
||||||
lua_CFunction func,
|
lua_CFunction func,
|
||||||
int top);
|
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 *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>
|
template<typename T>
|
||||||
static inline T *checkObject(lua_State *L, int narg)
|
static inline T *checkObject(lua_State *L, int narg)
|
||||||
|
@ -84,4 +112,14 @@ public:
|
||||||
* @return value from `func`
|
* @return value from `func`
|
||||||
*/
|
*/
|
||||||
static int l_deprecated_function(lua_State *L, const char *good, const char *bad, lua_CFunction 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},
|
{"__gc", gc_object},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
registerClass(L, className, methods, metamethods);
|
registerClass<LuaCamera>(L, methods, metamethods);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char LuaCamera::className[] = "Camera";
|
const char LuaCamera::className[] = "Camera";
|
||||||
|
|
|
@ -124,7 +124,7 @@ void LuaRaycast::Register(lua_State *L)
|
||||||
{"__gc", gc_object},
|
{"__gc", gc_object},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
registerClass(L, className, methods, metamethods);
|
registerClass<LuaRaycast>(L, methods, metamethods);
|
||||||
|
|
||||||
lua_register(L, className, create_object);
|
lua_register(L, className, create_object);
|
||||||
}
|
}
|
||||||
|
|
|
@ -410,7 +410,7 @@ void InvRef::Register(lua_State *L)
|
||||||
{"__gc", gc_object},
|
{"__gc", gc_object},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
registerClass(L, className, methods, metamethods);
|
registerClass<InvRef>(L, methods, metamethods);
|
||||||
|
|
||||||
// Cannot be created from Lua
|
// Cannot be created from Lua
|
||||||
//lua_register(L, className, create_object);
|
//lua_register(L, className, create_object);
|
||||||
|
|
|
@ -524,7 +524,7 @@ void LuaItemStack::Register(lua_State *L)
|
||||||
{"__eq", l_equals},
|
{"__eq", l_equals},
|
||||||
{0, 0}
|
{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))
|
// Can be created from Lua (ItemStack(itemstack or itemstring or table or nil))
|
||||||
lua_register(L, className, create_object);
|
lua_register(L, className, create_object);
|
||||||
|
|
|
@ -81,7 +81,7 @@ void ItemStackMetaRef::create(lua_State *L, LuaItemStack *istack)
|
||||||
|
|
||||||
void ItemStackMetaRef::Register(lua_State *L)
|
void ItemStackMetaRef::Register(lua_State *L)
|
||||||
{
|
{
|
||||||
registerMetadataClass(L, className, methods);
|
registerMetadataClass<ItemStackMetaRef>(L, methods);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char ItemStackMetaRef::className[] = "ItemStackMetaRef";
|
const char ItemStackMetaRef::className[] = "ItemStackMetaRef";
|
||||||
|
|
|
@ -464,7 +464,7 @@ void LuaLocalPlayer::Register(lua_State *L)
|
||||||
{"__gc", gc_object},
|
{"__gc", gc_object},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
registerClass(L, className, methods, metamethods);
|
registerClass<LuaLocalPlayer>(L, methods, metamethods);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char LuaLocalPlayer::className[] = "LocalPlayer";
|
const char LuaLocalPlayer::className[] = "LocalPlayer";
|
||||||
|
|
|
@ -315,20 +315,3 @@ int MetaDataRef::l_equals(lua_State *L)
|
||||||
lua_pushboolean(L, *data1 == *data2);
|
lua_pushboolean(L, *data1 == *data2);
|
||||||
return 1;
|
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 void handleToTable(lua_State *L, IMetadata *meta);
|
||||||
virtual bool handleFromTable(lua_State *L, int table, 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
|
// Exported functions
|
||||||
|
|
||||||
|
|
|
@ -160,7 +160,7 @@ void LuaMinimap::Register(lua_State *L)
|
||||||
{"__gc", gc_object},
|
{"__gc", gc_object},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
registerClass(L, className, methods, metamethods);
|
registerClass<LuaMinimap>(L, methods, metamethods);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char LuaMinimap::className[] = "Minimap";
|
const char LuaMinimap::className[] = "Minimap";
|
||||||
|
|
|
@ -77,7 +77,7 @@ void ModChannelRef::Register(lua_State *L)
|
||||||
{"__gc", gc_object},
|
{"__gc", gc_object},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
registerClass(L, className, methods, metamethods);
|
registerClass<ModChannelRef>(L, methods, metamethods);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModChannelRef::create(lua_State *L, const std::string &channel)
|
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)
|
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)
|
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},
|
{"__gc", gc_object},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
registerClass(L, className, methods, metamethods);
|
registerClass<NodeTimerRef>(L, methods, metamethods);
|
||||||
|
|
||||||
// Cannot be created from Lua
|
// Cannot be created from Lua
|
||||||
//lua_register(L, className, create_object);
|
//lua_register(L, className, create_object);
|
||||||
|
|
|
@ -101,7 +101,7 @@ void LuaValueNoise::Register(lua_State *L)
|
||||||
{"__gc", gc_object},
|
{"__gc", gc_object},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
registerClass(L, className, methods, metamethods);
|
registerClass<LuaValueNoise>(L, methods, metamethods);
|
||||||
|
|
||||||
lua_register(L, className, create_object);
|
lua_register(L, className, create_object);
|
||||||
|
|
||||||
|
@ -360,7 +360,7 @@ void LuaValueNoiseMap::Register(lua_State *L)
|
||||||
{"__gc", gc_object},
|
{"__gc", gc_object},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
registerClass(L, className, methods, metamethods);
|
registerClass<LuaValueNoiseMap>(L, methods, metamethods);
|
||||||
|
|
||||||
lua_register(L, className, create_object);
|
lua_register(L, className, create_object);
|
||||||
|
|
||||||
|
@ -449,7 +449,7 @@ void LuaPseudoRandom::Register(lua_State *L)
|
||||||
{"__gc", gc_object},
|
{"__gc", gc_object},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
registerClass(L, className, methods, metamethods);
|
registerClass<LuaPseudoRandom>(L, methods, metamethods);
|
||||||
|
|
||||||
lua_register(L, className, create_object);
|
lua_register(L, className, create_object);
|
||||||
}
|
}
|
||||||
|
@ -562,7 +562,7 @@ void LuaPcgRandom::Register(lua_State *L)
|
||||||
{"__gc", gc_object},
|
{"__gc", gc_object},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
registerClass(L, className, methods, metamethods);
|
registerClass<LuaPcgRandom>(L, methods, metamethods);
|
||||||
|
|
||||||
lua_register(L, className, create_object);
|
lua_register(L, className, create_object);
|
||||||
}
|
}
|
||||||
|
@ -652,7 +652,7 @@ void LuaSecureRandom::Register(lua_State *L)
|
||||||
{"__gc", gc_object},
|
{"__gc", gc_object},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
registerClass(L, className, methods, metamethods);
|
registerClass<LuaSecureRandom>(L, methods, metamethods);
|
||||||
|
|
||||||
lua_register(L, className, create_object);
|
lua_register(L, className, create_object);
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,8 +69,27 @@ RemotePlayer *ObjectRef::getplayer(ObjectRef *ref)
|
||||||
|
|
||||||
// Exported functions
|
// 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
|
// garbage collector
|
||||||
int ObjectRef::gc_object(lua_State *L) {
|
int ObjectRef::gc_object(lua_State *L)
|
||||||
|
{
|
||||||
ObjectRef *obj = *(ObjectRef **)(lua_touserdata(L, 1));
|
ObjectRef *obj = *(ObjectRef **)(lua_touserdata(L, 1));
|
||||||
delete obj;
|
delete obj;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2806,9 +2825,10 @@ void ObjectRef::Register(lua_State *L)
|
||||||
{
|
{
|
||||||
static const luaL_Reg metamethods[] = {
|
static const luaL_Reg metamethods[] = {
|
||||||
{"__gc", gc_object},
|
{"__gc", gc_object},
|
||||||
|
{"__tostring", mt_tostring},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
registerClass(L, className, methods, metamethods);
|
registerClass<ObjectRef>(L, methods, metamethods);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char ObjectRef::className[] = "ObjectRef";
|
const char ObjectRef::className[] = "ObjectRef";
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "lua_api/l_base.h"
|
#include "lua_api/l_base.h"
|
||||||
#include "irrlichttypes.h"
|
#include "irrlichttypes.h"
|
||||||
|
#include <lua.h>
|
||||||
|
|
||||||
class ServerActiveObject;
|
class ServerActiveObject;
|
||||||
class LuaEntitySAO;
|
class LuaEntitySAO;
|
||||||
|
@ -48,6 +49,9 @@ private:
|
||||||
|
|
||||||
// Exported functions
|
// Exported functions
|
||||||
|
|
||||||
|
// __tostring metamethod
|
||||||
|
static int mt_tostring(lua_State *L);
|
||||||
|
|
||||||
// garbage collector
|
// garbage collector
|
||||||
static int gc_object(lua_State *L);
|
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)
|
void PlayerMetaRef::Register(lua_State *L)
|
||||||
{
|
{
|
||||||
registerMetadataClass(L, className, methods);
|
registerMetadataClass<PlayerMetaRef>(L, methods);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char PlayerMetaRef::className[] = "PlayerMetaRef";
|
const char PlayerMetaRef::className[] = "PlayerMetaRef";
|
||||||
|
|
|
@ -362,7 +362,7 @@ void LuaSettings::Register(lua_State* L)
|
||||||
{"__gc", gc_object},
|
{"__gc", gc_object},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
registerClass(L, className, methods, metamethods);
|
registerClass<LuaSettings>(L, methods, metamethods);
|
||||||
|
|
||||||
// Can be created from Lua (Settings(filename))
|
// Can be created from Lua (Settings(filename))
|
||||||
lua_register(L, className, create_object);
|
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)
|
void StorageRef::Register(lua_State *L)
|
||||||
{
|
{
|
||||||
registerMetadataClass(L, className, methods);
|
registerMetadataClass<StorageRef>(L, methods);
|
||||||
}
|
}
|
||||||
|
|
||||||
IMetadata* StorageRef::getmeta(bool auto_create)
|
IMetadata* StorageRef::getmeta(bool auto_create)
|
||||||
|
|
|
@ -425,7 +425,7 @@ void LuaVoxelManip::Register(lua_State *L)
|
||||||
{"__gc", gc_object},
|
{"__gc", gc_object},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
registerClass(L, className, methods, metamethods);
|
registerClass<LuaVoxelManip>(L, methods, metamethods);
|
||||||
|
|
||||||
// Can be created from Lua (VoxelManip())
|
// Can be created from Lua (VoxelManip())
|
||||||
lua_register(L, className, create_object);
|
lua_register(L, className, create_object);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue