diff options
Diffstat (limited to 'src/script')
-rw-r--r-- | src/script/lua_api/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/script/lua_api/l_metadata.cpp | 252 | ||||
-rw-r--r-- | src/script/lua_api/l_metadata.h | 71 | ||||
-rw-r--r-- | src/script/lua_api/l_nodemeta.cpp | 224 | ||||
-rw-r--r-- | src/script/lua_api/l_nodemeta.h | 35 |
5 files changed, 366 insertions, 218 deletions
diff --git a/src/script/lua_api/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt index d507dcf70..efccce515 100644 --- a/src/script/lua_api/CMakeLists.txt +++ b/src/script/lua_api/CMakeLists.txt @@ -6,6 +6,7 @@ set(common_SCRIPT_LUA_API_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/l_inventory.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_item.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_mapgen.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/l_metadata.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_nodemeta.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_nodetimer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_noise.cpp @@ -22,4 +23,3 @@ set(common_SCRIPT_LUA_API_SRCS set(client_SCRIPT_LUA_API_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/l_mainmenu.cpp PARENT_SCOPE) - diff --git a/src/script/lua_api/l_metadata.cpp b/src/script/lua_api/l_metadata.cpp new file mode 100644 index 000000000..b54005bac --- /dev/null +++ b/src/script/lua_api/l_metadata.cpp @@ -0,0 +1,252 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "lua_api/l_metadata.h" +#include "lua_api/l_internal.h" +#include "common/c_content.h" +#include "serverenvironment.h" +#include "map.h" +#include "server.h" + +// LUALIB_API +void *luaL_checkudata_is_metadataref(lua_State *L, int ud) { + void *p = lua_touserdata(L, ud); + if (p != NULL && // value is a userdata? + lua_getmetatable(L, ud)) { // does it have a metatable? + lua_getfield(L, -1, "metadata_class"); + if (lua_type(L, -1) == LUA_TSTRING) { // does it have a metadata_class field? + return p; + } + } + luaL_typerror(L, ud, "MetaDataRef"); + return NULL; +} + +MetaDataRef* MetaDataRef::checkobject(lua_State *L, int narg) +{ + luaL_checktype(L, narg, LUA_TUSERDATA); + void *ud = luaL_checkudata_is_metadataref(L, narg); + if (!ud) + luaL_typerror(L, narg, "MetaDataRef"); + + return *(MetaDataRef**)ud; // unbox pointer +} + +// Exported functions + +// get_string(self, name) +int MetaDataRef::l_get_string(lua_State *L) +{ + MAP_LOCK_REQUIRED; + + MetaDataRef *ref = checkobject(L, 1); + std::string name = luaL_checkstring(L, 2); + + Metadata *meta = ref->getmeta(false); + if (meta == NULL) { + lua_pushlstring(L, "", 0); + return 1; + } + + const std::string &str = meta->getString(name); + lua_pushlstring(L, str.c_str(), str.size()); + return 1; +} + +// set_string(self, name, var) +int MetaDataRef::l_set_string(lua_State *L) +{ + MAP_LOCK_REQUIRED; + + MetaDataRef *ref = checkobject(L, 1); + std::string name = luaL_checkstring(L, 2); + size_t len = 0; + 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(); + return 0; +} + +// get_int(self, name) +int MetaDataRef::l_get_int(lua_State *L) +{ + MAP_LOCK_REQUIRED; + + MetaDataRef *ref = checkobject(L, 1); + std::string name = lua_tostring(L, 2); + + Metadata *meta = ref->getmeta(false); + if (meta == NULL) { + lua_pushnumber(L, 0); + return 1; + } + + const std::string &str = meta->getString(name); + lua_pushnumber(L, stoi(str)); + return 1; +} + +// set_int(self, name, var) +int MetaDataRef::l_set_int(lua_State *L) +{ + MAP_LOCK_REQUIRED; + + MetaDataRef *ref = checkobject(L, 1); + std::string name = lua_tostring(L, 2); + int a = lua_tointeger(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(); + return 0; +} + +// get_float(self, name) +int MetaDataRef::l_get_float(lua_State *L) +{ + MAP_LOCK_REQUIRED; + + MetaDataRef *ref = checkobject(L, 1); + std::string name = lua_tostring(L, 2); + + Metadata *meta = ref->getmeta(false); + if (meta == NULL) { + lua_pushnumber(L, 0); + return 1; + } + + const std::string &str = meta->getString(name); + lua_pushnumber(L, stof(str)); + return 1; +} + +// set_float(self, name, var) +int MetaDataRef::l_set_float(lua_State *L) +{ + MAP_LOCK_REQUIRED; + + MetaDataRef *ref = checkobject(L, 1); + std::string name = lua_tostring(L, 2); + float a = lua_tonumber(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(); + return 0; +} + +// to_table(self) +int MetaDataRef::l_to_table(lua_State *L) +{ + MAP_LOCK_REQUIRED; + + MetaDataRef *ref = checkobject(L, 1); + + Metadata *meta = ref->getmeta(true); + if (meta == NULL) { + lua_pushnil(L); + return 1; + } + lua_newtable(L); + + ref->handleToTable(L, meta); + + return 1; +} + +// from_table(self, table) +int MetaDataRef::l_from_table(lua_State *L) +{ + MAP_LOCK_REQUIRED; + + MetaDataRef *ref = checkobject(L, 1); + int base = 2; + + ref->clearMeta(); + + if (!lua_istable(L, base)) { + // No metadata + lua_pushboolean(L, true); + return 1; + } + + // Create new metadata + Metadata *meta = ref->getmeta(true); + if (meta == NULL) { + lua_pushboolean(L, false); + return 1; + } + + bool was_successful = ref->handleFromTable(L, base, meta); + ref->reportMetadataChange(); + lua_pushboolean(L, was_successful); + return 1; +} + +void MetaDataRef::handleToTable(lua_State *L, Metadata *meta) +{ + lua_newtable(L); + { + const StringMap &fields = meta->getStrings(); + for (StringMap::const_iterator + it = fields.begin(); it != fields.end(); ++it) { + const std::string &name = it->first; + const std::string &value = it->second; + lua_pushlstring(L, name.c_str(), name.size()); + lua_pushlstring(L, value.c_str(), value.size()); + lua_settable(L, -3); + } + } + lua_setfield(L, -2, "fields"); +} + +bool MetaDataRef::handleFromTable(lua_State *L, int table, Metadata *meta) +{ + // Set fields + lua_getfield(L, table, "fields"); + if (lua_istable(L, -1)) { + int fieldstable = lua_gettop(L); + lua_pushnil(L); + while (lua_next(L, fieldstable) != 0) { + // key at index -2 and value at index -1 + std::string name = lua_tostring(L, -2); + size_t cl; + const char *cs = lua_tolstring(L, -1, &cl); + meta->setString(name, std::string(cs, cl)); + lua_pop(L, 1); // Remove value, keep key for next iteration + } + lua_pop(L, 1); + } + + return true; +} diff --git a/src/script/lua_api/l_metadata.h b/src/script/lua_api/l_metadata.h new file mode 100644 index 000000000..561be6adf --- /dev/null +++ b/src/script/lua_api/l_metadata.h @@ -0,0 +1,71 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#ifndef L_METADATA_H_ +#define L_METADATA_H_ + +#include "lua_api/l_base.h" +#include "irrlichttypes_bloated.h" + +class Metadata; + +/* + NodeMetaRef +*/ + +class MetaDataRef : public ModApiBase { +public: + virtual ~MetaDataRef() {} +protected: + static MetaDataRef *checkobject(lua_State *L, int narg); + + virtual void reportMetadataChange() {} + virtual Metadata* 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); + + // Exported functions + + // get_string(self, name) + static int l_get_string(lua_State *L); + + // set_string(self, name, var) + static int l_set_string(lua_State *L); + + // get_int(self, name) + static int l_get_int(lua_State *L); + + // set_int(self, name, var) + static int l_set_int(lua_State *L); + + // get_float(self, name) + static int l_get_float(lua_State *L); + + // set_float(self, name, var) + static int l_set_float(lua_State *L); + + // to_table(self) + static int l_to_table(lua_State *L); + + // from_table(self, table) + static int l_from_table(lua_State *L); +}; + +#endif /* L_NODEMETA_H_ */ diff --git a/src/script/lua_api/l_nodemeta.cpp b/src/script/lua_api/l_nodemeta.cpp index 8391de03c..4b2b392da 100644 --- a/src/script/lua_api/l_nodemeta.cpp +++ b/src/script/lua_api/l_nodemeta.cpp @@ -36,7 +36,7 @@ NodeMetaRef* NodeMetaRef::checkobject(lua_State *L, int narg) return *(NodeMetaRef**)ud; // unbox pointer } -NodeMetadata* NodeMetaRef::getmeta(bool auto_create) +Metadata* NodeMetaRef::getmeta(bool auto_create) { NodeMetadata *meta = m_env->getMap().getNodeMetadata(m_p); if (meta == NULL && auto_create) { @@ -49,17 +49,22 @@ NodeMetadata* NodeMetaRef::getmeta(bool auto_create) return meta; } -void NodeMetaRef::reportMetadataChange(NodeMetaRef *ref) +void NodeMetaRef::clearMeta() +{ + m_env->getMap().removeNodeMetadata(m_p); +} + +void NodeMetaRef::reportMetadataChange() { // NOTE: This same code is in rollback_interface.cpp // Inform other things that the metadata has changed - v3s16 blockpos = getNodeBlockPos(ref->m_p); + v3s16 blockpos = getNodeBlockPos(m_p); MapEditEvent event; event.type = MEET_BLOCK_NODE_METADATA_CHANGED; event.p = blockpos; - ref->m_env->getMap().dispatchEvent(&event); + m_env->getMap().dispatchEvent(&event); // Set the block to be saved - MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos); + MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos); if (block) { block->raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_REPORT_META_CHANGE); @@ -75,115 +80,6 @@ int NodeMetaRef::gc_object(lua_State *L) { return 0; } -// get_string(self, name) -int NodeMetaRef::l_get_string(lua_State *L) -{ - MAP_LOCK_REQUIRED; - - NodeMetaRef *ref = checkobject(L, 1); - std::string name = luaL_checkstring(L, 2); - - NodeMetadata *meta = ref->getmeta(false); - if(meta == NULL){ - lua_pushlstring(L, "", 0); - return 1; - } - std::string str = meta->getString(name); - lua_pushlstring(L, str.c_str(), str.size()); - return 1; -} - -// set_string(self, name, var) -int NodeMetaRef::l_set_string(lua_State *L) -{ - MAP_LOCK_REQUIRED; - - NodeMetaRef *ref = checkobject(L, 1); - std::string name = luaL_checkstring(L, 2); - size_t len = 0; - const char *s = lua_tolstring(L, 3, &len); - std::string str(s, len); - - NodeMetadata *meta = ref->getmeta(!str.empty()); - if(meta == NULL || str == meta->getString(name)) - return 0; - meta->setString(name, str); - reportMetadataChange(ref); - return 0; -} - -// get_int(self, name) -int NodeMetaRef::l_get_int(lua_State *L) -{ - MAP_LOCK_REQUIRED; - - NodeMetaRef *ref = checkobject(L, 1); - std::string name = lua_tostring(L, 2); - - NodeMetadata *meta = ref->getmeta(false); - if(meta == NULL){ - lua_pushnumber(L, 0); - return 1; - } - std::string str = meta->getString(name); - lua_pushnumber(L, stoi(str)); - return 1; -} - -// set_int(self, name, var) -int NodeMetaRef::l_set_int(lua_State *L) -{ - MAP_LOCK_REQUIRED; - - NodeMetaRef *ref = checkobject(L, 1); - std::string name = lua_tostring(L, 2); - int a = lua_tointeger(L, 3); - std::string str = itos(a); - - NodeMetadata *meta = ref->getmeta(true); - if(meta == NULL || str == meta->getString(name)) - return 0; - meta->setString(name, str); - reportMetadataChange(ref); - return 0; -} - -// get_float(self, name) -int NodeMetaRef::l_get_float(lua_State *L) -{ - MAP_LOCK_REQUIRED; - - NodeMetaRef *ref = checkobject(L, 1); - std::string name = lua_tostring(L, 2); - - NodeMetadata *meta = ref->getmeta(false); - if(meta == NULL){ - lua_pushnumber(L, 0); - return 1; - } - std::string str = meta->getString(name); - lua_pushnumber(L, stof(str)); - return 1; -} - -// set_float(self, name, var) -int NodeMetaRef::l_set_float(lua_State *L) -{ - MAP_LOCK_REQUIRED; - - NodeMetaRef *ref = checkobject(L, 1); - std::string name = lua_tostring(L, 2); - float a = lua_tonumber(L, 3); - std::string str = ftos(a); - - NodeMetadata *meta = ref->getmeta(true); - if(meta == NULL || str == meta->getString(name)) - return 0; - meta->setString(name, str); - reportMetadataChange(ref); - return 0; -} - // get_inventory(self) int NodeMetaRef::l_get_inventory(lua_State *L) { @@ -195,34 +91,12 @@ int NodeMetaRef::l_get_inventory(lua_State *L) return 1; } -// to_table(self) -int NodeMetaRef::l_to_table(lua_State *L) +void NodeMetaRef::handleToTable(lua_State *L, Metadata *_meta) { - MAP_LOCK_REQUIRED; - - NodeMetaRef *ref = checkobject(L, 1); - - NodeMetadata *meta = ref->getmeta(true); - if (meta == NULL) { - lua_pushnil(L); - return 1; - } - lua_newtable(L); - // fields - lua_newtable(L); - { - StringMap fields = meta->getStrings(); - for (StringMap::const_iterator - it = fields.begin(); it != fields.end(); ++it) { - const std::string &name = it->first; - const std::string &value = it->second; - lua_pushlstring(L, name.c_str(), name.size()); - lua_pushlstring(L, value.c_str(), value.size()); - lua_settable(L, -3); - } - } - lua_setfield(L, -2, "fields"); + MetaDataRef::handleToTable(L, _meta); + + NodeMetadata *meta = (NodeMetadata*) _meta; // inventory lua_newtable(L); @@ -236,52 +110,20 @@ int NodeMetaRef::l_to_table(lua_State *L) } } lua_setfield(L, -2, "inventory"); - return 1; } // from_table(self, table) -int NodeMetaRef::l_from_table(lua_State *L) +bool NodeMetaRef::handleFromTable(lua_State *L, int table, Metadata *_meta) { - MAP_LOCK_REQUIRED; - - NodeMetaRef *ref = checkobject(L, 1); - int base = 2; - - // clear old metadata first - ref->m_env->getMap().removeNodeMetadata(ref->m_p); - - if (!lua_istable(L, base)) { - // No metadata - lua_pushboolean(L, true); - return 1; - } + // fields + if (!MetaDataRef::handleFromTable(L, table, _meta)) + return false; - // Create new metadata - NodeMetadata *meta = ref->getmeta(true); - if (meta == NULL) { - lua_pushboolean(L, false); - return 1; - } + NodeMetadata *meta = (NodeMetadata*) _meta; - // Set fields - lua_getfield(L, base, "fields"); - if (lua_istable(L, -1)) { - int fieldstable = lua_gettop(L); - lua_pushnil(L); - while (lua_next(L, fieldstable) != 0) { - // key at index -2 and value at index -1 - std::string name = lua_tostring(L, -2); - size_t cl; - const char *cs = lua_tolstring(L, -1, &cl); - meta->setString(name, std::string(cs, cl)); - lua_pop(L, 1); // Remove value, keep key for next iteration - } - lua_pop(L, 1); - } - - // Set inventory + // inventory Inventory *inv = meta->getInventory(); - lua_getfield(L, base, "inventory"); + lua_getfield(L, table, "inventory"); if (lua_istable(L, -1)) { int inventorytable = lua_gettop(L); lua_pushnil(L); @@ -294,9 +136,7 @@ int NodeMetaRef::l_from_table(lua_State *L) lua_pop(L, 1); } - reportMetadataChange(ref); - lua_pushboolean(L, true); - return 1; + return true; } @@ -332,6 +172,10 @@ void NodeMetaRef::Register(lua_State *L) lua_pushvalue(L, methodtable); lua_settable(L, metatable); // hide metatable from Lua getmetatable() + lua_pushliteral(L, "metadata_class"); + lua_pushlstring(L, className, strlen(className)); + lua_settable(L, metatable); + lua_pushliteral(L, "__index"); lua_pushvalue(L, methodtable); lua_settable(L, metatable); @@ -351,14 +195,14 @@ void NodeMetaRef::Register(lua_State *L) const char NodeMetaRef::className[] = "NodeMetaRef"; const luaL_reg NodeMetaRef::methods[] = { - luamethod(NodeMetaRef, get_string), - luamethod(NodeMetaRef, set_string), - luamethod(NodeMetaRef, get_int), - luamethod(NodeMetaRef, set_int), - luamethod(NodeMetaRef, get_float), - luamethod(NodeMetaRef, set_float), + luamethod(MetaDataRef, get_string), + luamethod(MetaDataRef, set_string), + luamethod(MetaDataRef, get_int), + luamethod(MetaDataRef, set_int), + luamethod(MetaDataRef, get_float), + luamethod(MetaDataRef, set_float), + luamethod(MetaDataRef, to_table), + luamethod(MetaDataRef, from_table), luamethod(NodeMetaRef, get_inventory), - luamethod(NodeMetaRef, to_table), - luamethod(NodeMetaRef, from_table), {0,0} }; diff --git a/src/script/lua_api/l_nodemeta.h b/src/script/lua_api/l_nodemeta.h index 4ce338b18..d03f086c9 100644 --- a/src/script/lua_api/l_nodemeta.h +++ b/src/script/lua_api/l_nodemeta.h @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define L_NODEMETA_H_ #include "lua_api/l_base.h" +#include "lua_api/l_metadata.h" #include "irrlichttypes_bloated.h" class ServerEnvironment; @@ -29,7 +30,7 @@ class NodeMetadata; NodeMetaRef */ -class NodeMetaRef : public ModApiBase { +class NodeMetaRef : public MetaDataRef { private: v3s16 m_p; ServerEnvironment *m_env; @@ -52,42 +53,22 @@ 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 NodeMetadata* getmeta(bool auto_create); + virtual Metadata* getmeta(bool auto_create); + virtual void clearMeta(); - static void reportMetadataChange(NodeMetaRef *ref); + virtual void reportMetadataChange(); + + virtual void handleToTable(lua_State *L, Metadata *_meta); + virtual bool handleFromTable(lua_State *L, int table, Metadata *_meta); // Exported functions // garbage collector static int gc_object(lua_State *L); - // get_string(self, name) - static int l_get_string(lua_State *L); - - // set_string(self, name, var) - static int l_set_string(lua_State *L); - - // get_int(self, name) - static int l_get_int(lua_State *L); - - // set_int(self, name, var) - static int l_set_int(lua_State *L); - - // get_float(self, name) - static int l_get_float(lua_State *L); - - // set_float(self, name, var) - static int l_set_float(lua_State *L); - // get_inventory(self) static int l_get_inventory(lua_State *L); - // to_table(self) - static int l_to_table(lua_State *L); - - // from_table(self, table) - static int l_from_table(lua_State *L); - public: NodeMetaRef(v3s16 p, ServerEnvironment *env); |