1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Avoid duplication of mod metadata in memory (#12562)

Co-authored-by: sfan5 <sfan5@live.de>
This commit is contained in:
Jude Melton-Houghton 2022-09-26 17:03:43 -04:00 committed by GitHub
parent 03428d9825
commit f4a01f3a5d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 527 additions and 272 deletions

View file

@ -36,7 +36,7 @@ ItemStackMetaRef* ItemStackMetaRef::checkobject(lua_State *L, int narg)
return *(ItemStackMetaRef**)ud; // unbox pointer
}
Metadata* ItemStackMetaRef::getmeta(bool auto_create)
IMetadata* ItemStackMetaRef::getmeta(bool auto_create)
{
return &istack->getItem().metadata;
}

View file

@ -36,7 +36,7 @@ private:
static ItemStackMetaRef *checkobject(lua_State *L, int narg);
virtual Metadata* getmeta(bool auto_create);
virtual IMetadata* getmeta(bool auto_create);
virtual void clearMeta();

View file

@ -59,7 +59,7 @@ int MetaDataRef::l_contains(lua_State *L)
MetaDataRef *ref = checkobject(L, 1);
std::string name = luaL_checkstring(L, 2);
Metadata *meta = ref->getmeta(false);
IMetadata *meta = ref->getmeta(false);
if (meta == NULL)
return 0;
@ -75,7 +75,7 @@ int MetaDataRef::l_get(lua_State *L)
MetaDataRef *ref = checkobject(L, 1);
std::string name = luaL_checkstring(L, 2);
Metadata *meta = ref->getmeta(false);
IMetadata *meta = ref->getmeta(false);
if (meta == NULL)
return 0;
@ -96,13 +96,14 @@ int MetaDataRef::l_get_string(lua_State *L)
MetaDataRef *ref = checkobject(L, 1);
std::string name = luaL_checkstring(L, 2);
Metadata *meta = ref->getmeta(false);
IMetadata *meta = ref->getmeta(false);
if (meta == NULL) {
lua_pushlstring(L, "", 0);
return 1;
}
const std::string &str = meta->getString(name);
std::string str_;
const std::string &str = meta->getString(name, &str_);
lua_pushlstring(L, str.c_str(), str.size());
return 1;
}
@ -118,12 +119,9 @@ int MetaDataRef::l_set_string(lua_State *L)
const char *s = lua_tolstring(L, 3, &len);
std::string str(s, len);
Metadata *meta = ref->getmeta(!str.empty());
if (meta == NULL || str == meta->getString(name))
return 0;
meta->setString(name, str);
ref->reportMetadataChange(&name);
IMetadata *meta = ref->getmeta(!str.empty());
if (meta != NULL && meta->setString(name, str))
ref->reportMetadataChange(&name);
return 0;
}
@ -135,13 +133,14 @@ int MetaDataRef::l_get_int(lua_State *L)
MetaDataRef *ref = checkobject(L, 1);
std::string name = luaL_checkstring(L, 2);
Metadata *meta = ref->getmeta(false);
IMetadata *meta = ref->getmeta(false);
if (meta == NULL) {
lua_pushnumber(L, 0);
return 1;
}
const std::string &str = meta->getString(name);
std::string str_;
const std::string &str = meta->getString(name, &str_);
lua_pushnumber(L, stoi(str));
return 1;
}
@ -156,12 +155,9 @@ int MetaDataRef::l_set_int(lua_State *L)
int a = luaL_checkint(L, 3);
std::string str = itos(a);
Metadata *meta = ref->getmeta(true);
if (meta == NULL || str == meta->getString(name))
return 0;
meta->setString(name, str);
ref->reportMetadataChange(&name);
IMetadata *meta = ref->getmeta(true);
if (meta != NULL && meta->setString(name, str))
ref->reportMetadataChange(&name);
return 0;
}
@ -173,13 +169,14 @@ int MetaDataRef::l_get_float(lua_State *L)
MetaDataRef *ref = checkobject(L, 1);
std::string name = luaL_checkstring(L, 2);
Metadata *meta = ref->getmeta(false);
IMetadata *meta = ref->getmeta(false);
if (meta == NULL) {
lua_pushnumber(L, 0);
return 1;
}
const std::string &str = meta->getString(name);
std::string str_;
const std::string &str = meta->getString(name, &str_);
lua_pushnumber(L, stof(str));
return 1;
}
@ -194,12 +191,9 @@ int MetaDataRef::l_set_float(lua_State *L)
float a = readParam<float>(L, 3);
std::string str = ftos(a);
Metadata *meta = ref->getmeta(true);
if (meta == NULL || str == meta->getString(name))
return 0;
meta->setString(name, str);
ref->reportMetadataChange(&name);
IMetadata *meta = ref->getmeta(true);
if (meta != NULL && meta->setString(name, str))
ref->reportMetadataChange(&name);
return 0;
}
@ -210,7 +204,7 @@ int MetaDataRef::l_to_table(lua_State *L)
MetaDataRef *ref = checkobject(L, 1);
Metadata *meta = ref->getmeta(true);
IMetadata *meta = ref->getmeta(true);
if (meta == NULL) {
lua_pushnil(L);
return 1;
@ -239,7 +233,7 @@ int MetaDataRef::l_from_table(lua_State *L)
}
// Create new metadata
Metadata *meta = ref->getmeta(true);
IMetadata *meta = ref->getmeta(true);
if (meta == NULL) {
lua_pushboolean(L, false);
return 1;
@ -251,11 +245,12 @@ int MetaDataRef::l_from_table(lua_State *L)
return 1;
}
void MetaDataRef::handleToTable(lua_State *L, Metadata *meta)
void MetaDataRef::handleToTable(lua_State *L, IMetadata *meta)
{
lua_newtable(L);
{
const StringMap &fields = meta->getStrings();
StringMap fields_;
const StringMap &fields = meta->getStrings(&fields_);
for (const auto &field : fields) {
const std::string &name = field.first;
const std::string &value = field.second;
@ -267,7 +262,7 @@ void MetaDataRef::handleToTable(lua_State *L, Metadata *meta)
lua_setfield(L, -2, "fields");
}
bool MetaDataRef::handleFromTable(lua_State *L, int table, Metadata *meta)
bool MetaDataRef::handleFromTable(lua_State *L, int table, IMetadata *meta)
{
// Set fields
lua_getfield(L, table, "fields");
@ -292,9 +287,9 @@ bool MetaDataRef::handleFromTable(lua_State *L, int table, Metadata *meta)
int MetaDataRef::l_equals(lua_State *L)
{
MetaDataRef *ref1 = checkobject(L, 1);
Metadata *data1 = ref1->getmeta(false);
IMetadata *data1 = ref1->getmeta(false);
MetaDataRef *ref2 = checkobject(L, 2);
Metadata *data2 = ref2->getmeta(false);
IMetadata *data2 = ref2->getmeta(false);
if (data1 == NULL || data2 == NULL)
lua_pushboolean(L, data1 == data2);
else

View file

@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes_bloated.h"
#include "lua_api/l_base.h"
class Metadata;
class IMetadata;
/*
NodeMetaRef
@ -38,11 +38,11 @@ protected:
static MetaDataRef *checkobject(lua_State *L, int narg);
virtual void reportMetadataChange(const std::string *name = nullptr) {}
virtual Metadata *getmeta(bool auto_create) = 0;
virtual IMetadata *getmeta(bool auto_create) = 0;
virtual void clearMeta() = 0;
virtual void handleToTable(lua_State *L, Metadata *meta);
virtual bool handleFromTable(lua_State *L, int table, Metadata *meta);
virtual void handleToTable(lua_State *L, IMetadata *meta);
virtual bool handleFromTable(lua_State *L, int table, IMetadata *meta);
// Exported functions

View file

@ -37,7 +37,7 @@ NodeMetaRef* NodeMetaRef::checkobject(lua_State *L, int narg)
return *(NodeMetaRef**)ud; // unbox pointer
}
Metadata* NodeMetaRef::getmeta(bool auto_create)
IMetadata* NodeMetaRef::getmeta(bool auto_create)
{
if (m_is_local)
return m_local_meta;
@ -127,12 +127,13 @@ int NodeMetaRef::l_mark_as_private(lua_State *L)
return 0;
}
void NodeMetaRef::handleToTable(lua_State *L, Metadata *_meta)
void NodeMetaRef::handleToTable(lua_State *L, IMetadata *_meta)
{
// fields
MetaDataRef::handleToTable(L, _meta);
NodeMetadata *meta = (NodeMetadata *) _meta;
NodeMetadata *meta = dynamic_cast<NodeMetadata*>(_meta);
assert(meta);
// inventory
Inventory *inv = meta->getInventory();
@ -145,13 +146,14 @@ void NodeMetaRef::handleToTable(lua_State *L, Metadata *_meta)
}
// from_table(self, table)
bool NodeMetaRef::handleFromTable(lua_State *L, int table, Metadata *_meta)
bool NodeMetaRef::handleFromTable(lua_State *L, int table, IMetadata *_meta)
{
// fields
if (!MetaDataRef::handleFromTable(L, table, _meta))
return false;
NodeMetadata *meta = (NodeMetadata*) _meta;
NodeMetadata *meta = dynamic_cast<NodeMetadata*>(_meta);
assert(meta);
// inventory
Inventory *inv = meta->getInventory();
@ -178,7 +180,7 @@ NodeMetaRef::NodeMetaRef(v3s16 p, ServerEnvironment *env):
{
}
NodeMetaRef::NodeMetaRef(Metadata *meta):
NodeMetaRef::NodeMetaRef(IMetadata *meta):
m_is_local(true),
m_local_meta(meta)
{
@ -196,7 +198,7 @@ void NodeMetaRef::create(lua_State *L, v3s16 p, ServerEnvironment *env)
}
// Client-sided version of the above
void NodeMetaRef::createClient(lua_State *L, Metadata *meta)
void NodeMetaRef::createClient(lua_State *L, IMetadata *meta)
{
NodeMetaRef *o = new NodeMetaRef(meta);
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;

View file

@ -38,7 +38,7 @@ private:
v3s16 m_p;
ServerEnvironment *m_env = nullptr;
// Set for client metadata
Metadata *m_local_meta = nullptr;
IMetadata *m_local_meta = nullptr;
static const char className[];
static const luaL_Reg methodsServer[];
@ -59,13 +59,13 @@ private:
* @param auto_create when true, try to create metadata information for the node if it has none.
* @return pointer to a @c NodeMetadata object or @c NULL in case of error.
*/
virtual Metadata* getmeta(bool auto_create);
virtual IMetadata* getmeta(bool auto_create);
virtual void clearMeta();
virtual void reportMetadataChange(const std::string *name = nullptr);
virtual void handleToTable(lua_State *L, Metadata *_meta);
virtual bool handleFromTable(lua_State *L, int table, Metadata *_meta);
virtual void handleToTable(lua_State *L, IMetadata *_meta);
virtual bool handleFromTable(lua_State *L, int table, IMetadata *_meta);
// Exported functions
@ -80,7 +80,7 @@ private:
public:
NodeMetaRef(v3s16 p, ServerEnvironment *env);
NodeMetaRef(Metadata *meta);
NodeMetaRef(IMetadata *meta);
~NodeMetaRef() = default;
@ -89,7 +89,7 @@ public:
static void create(lua_State *L, v3s16 p, ServerEnvironment *env);
// Client-sided version of the above
static void createClient(lua_State *L, Metadata *meta);
static void createClient(lua_State *L, IMetadata *meta);
static void RegisterCommon(lua_State *L);
static void Register(lua_State *L);

View file

@ -35,7 +35,7 @@ PlayerMetaRef *PlayerMetaRef::checkobject(lua_State *L, int narg)
return *(PlayerMetaRef **)ud; // unbox pointer
}
Metadata *PlayerMetaRef::getmeta(bool auto_create)
IMetadata *PlayerMetaRef::getmeta(bool auto_create)
{
return metadata;
}
@ -60,7 +60,7 @@ int PlayerMetaRef::gc_object(lua_State *L)
// Creates an PlayerMetaRef and leaves it on top of stack
// Not callable from Lua; all references are created on the C side.
void PlayerMetaRef::create(lua_State *L, Metadata *metadata)
void PlayerMetaRef::create(lua_State *L, IMetadata *metadata)
{
PlayerMetaRef *o = new PlayerMetaRef(metadata);
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;

View file

@ -29,14 +29,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class PlayerMetaRef : public MetaDataRef
{
private:
Metadata *metadata = nullptr;
IMetadata *metadata = nullptr;
static const char className[];
static const luaL_Reg methods[];
static PlayerMetaRef *checkobject(lua_State *L, int narg);
virtual Metadata *getmeta(bool auto_create);
virtual IMetadata *getmeta(bool auto_create);
virtual void clearMeta();
@ -46,12 +46,12 @@ private:
static int gc_object(lua_State *L);
public:
PlayerMetaRef(Metadata *metadata) : metadata(metadata) {}
PlayerMetaRef(IMetadata *metadata) : metadata(metadata) {}
~PlayerMetaRef() = default;
// Creates an ItemStackMetaRef and leaves it on top of stack
// Not callable from Lua; all references are created on the C side.
static void create(lua_State *L, Metadata *metadata);
static void create(lua_State *L, IMetadata *metadata);
static void Register(lua_State *L);
};

View file

@ -20,7 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_storage.h"
#include "l_internal.h"
#include "content/mods.h"
#include "server.h"
int ModApiStorage::l_get_mod_storage(lua_State *L)
@ -28,23 +27,12 @@ int ModApiStorage::l_get_mod_storage(lua_State *L)
// Note that this is wrapped in Lua, see builtin/common/mod_storage.lua
std::string mod_name = readParam<std::string>(L, 1);
ModMetadata *store = nullptr;
if (IGameDef *gamedef = getGameDef(L)) {
store = new ModMetadata(mod_name, gamedef->getModStorageDatabase());
if (gamedef->registerModStorage(store)) {
StorageRef::create(L, store);
int object = lua_gettop(L);
lua_pushvalue(L, object);
return 1;
}
StorageRef::create(L, mod_name, gamedef->getModStorageDatabase());
} else {
assert(false); // this should not happen
lua_pushnil(L);
}
delete store;
lua_pushnil(L);
return 1;
}
@ -53,19 +41,9 @@ void ModApiStorage::Initialize(lua_State *L, int top)
API_FCT(get_mod_storage);
}
StorageRef::StorageRef(ModMetadata *object):
m_object(object)
void StorageRef::create(lua_State *L, const std::string &mod_name, ModMetadataDatabase *db)
{
}
StorageRef::~StorageRef()
{
delete m_object;
}
void StorageRef::create(lua_State *L, ModMetadata *object)
{
StorageRef *o = new StorageRef(object);
StorageRef *o = new StorageRef(mod_name, db);
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
luaL_getmetatable(L, className);
lua_setmetatable(L, -2);
@ -74,9 +52,6 @@ void StorageRef::create(lua_State *L, ModMetadata *object)
int StorageRef::gc_object(lua_State *L)
{
StorageRef *o = *(StorageRef **)(lua_touserdata(L, 1));
// Server side
if (IGameDef *gamedef = getGameDef(L))
gamedef->unregisterModStorage(getobject(o)->getModName());
delete o;
return 0;
}
@ -122,20 +97,14 @@ StorageRef* StorageRef::checkobject(lua_State *L, int narg)
return *(StorageRef**)ud; // unbox pointer
}
ModMetadata* StorageRef::getobject(StorageRef *ref)
IMetadata* StorageRef::getmeta(bool auto_create)
{
ModMetadata *co = ref->m_object;
return co;
}
Metadata* StorageRef::getmeta(bool auto_create)
{
return m_object;
return &m_object;
}
void StorageRef::clearMeta()
{
m_object->clear();
m_object.clear();
}
const char StorageRef::className[] = "StorageRef";

View file

@ -22,8 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "l_metadata.h"
#include "lua_api/l_base.h"
class ModMetadata;
#include "content/mods.h"
class ModApiStorage : public ModApiBase
{
@ -37,24 +36,23 @@ public:
class StorageRef : public MetaDataRef
{
private:
ModMetadata *m_object = nullptr;
ModMetadata m_object;
static const char className[];
static const luaL_Reg methods[];
virtual Metadata *getmeta(bool auto_create);
virtual IMetadata *getmeta(bool auto_create);
virtual void clearMeta();
// garbage collector
static int gc_object(lua_State *L);
public:
StorageRef(ModMetadata *object);
~StorageRef();
StorageRef(const std::string &mod_name, ModMetadataDatabase *db): m_object(mod_name, db) {}
~StorageRef() = default;
static void Register(lua_State *L);
static void create(lua_State *L, ModMetadata *object);
static void create(lua_State *L, const std::string &mod_name, ModMetadataDatabase *db);
static StorageRef *checkobject(lua_State *L, int narg);
static ModMetadata *getobject(StorageRef *ref);
};