aboutsummaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
authorrubenwardy <rubenwardy@gmail.com>2017-01-31 19:49:01 +0000
committerrubenwardy <rubenwardy@gmail.com>2017-02-04 22:07:55 +0000
commitf2aa2c6a986dec47856c49ae5f54fbf3c688e027 (patch)
treed12fbb3e62776efaafe059a7fdbfa9938e7298cd /src/script
parentc2e7b1f57941cb34cb7e3d71dc040fad53a64e3e (diff)
downloadminetest-f2aa2c6a986dec47856c49ae5f54fbf3c688e027.tar.gz
minetest-f2aa2c6a986dec47856c49ae5f54fbf3c688e027.tar.bz2
minetest-f2aa2c6a986dec47856c49ae5f54fbf3c688e027.zip
Add ItemStack key-value meta storage
Diffstat (limited to 'src/script')
-rw-r--r--src/script/common/c_content.cpp31
-rw-r--r--src/script/lua_api/CMakeLists.txt1
-rw-r--r--src/script/lua_api/l_env.cpp2
-rw-r--r--src/script/lua_api/l_item.cpp38
-rw-r--r--src/script/lua_api/l_item.h5
-rw-r--r--src/script/lua_api/l_itemstackmeta.cpp115
-rw-r--r--src/script/lua_api/l_itemstackmeta.h59
-rw-r--r--src/script/scripting_game.cpp2
8 files changed, 243 insertions, 10 deletions
diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp
index ebc951295..8925b51f4 100644
--- a/src/script/common/c_content.cpp
+++ b/src/script/common/c_content.cpp
@@ -824,11 +824,32 @@ ItemStack read_item(lua_State* L, int index,Server* srv)
std::string name = getstringfield_default(L, index, "name", "");
int count = getintfield_default(L, index, "count", 1);
int wear = getintfield_default(L, index, "wear", 0);
- std::string metadata = getstringfield_default(L, index, "metadata", "");
- return ItemStack(name, count, wear, metadata, idef);
- }
- else
- {
+
+ ItemStack istack(name, count, wear, idef);
+
+ lua_getfield(L, index, "metadata");
+
+ // Support old metadata format by checking type
+ int fieldstable = lua_gettop(L);
+ if (lua_istable(L, fieldstable)) {
+ lua_pushnil(L);
+ while (lua_next(L, fieldstable) != 0) {
+ // key at index -2 and value at index -1
+ std::string key = lua_tostring(L, -2);
+ size_t value_len;
+ const char *value_cs = lua_tolstring(L, -1, &value_len);
+ std::string value(value_cs, value_len);
+ istack.metadata.setString(name, value);
+ lua_pop(L, 1); // removes value, keeps key for next iteration
+ }
+ } else {
+ // BACKWARDS COMPATIBLITY
+ std::string value = getstringfield_default(L, index, "metadata", "");
+ istack.metadata.setString("", value);
+ }
+
+ return istack;
+ } else {
throw LuaError("Expecting itemstack, itemstring, table or nil");
}
}
diff --git a/src/script/lua_api/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt
index efccce515..070234eba 100644
--- a/src/script/lua_api/CMakeLists.txt
+++ b/src/script/lua_api/CMakeLists.txt
@@ -5,6 +5,7 @@ set(common_SCRIPT_LUA_API_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/l_env.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_inventory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_item.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/l_itemstackmeta.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_mapgen.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_metadata.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_nodemeta.cpp
diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp
index 3d9db7917..2722e35a4 100644
--- a/src/script/lua_api/l_env.cpp
+++ b/src/script/lua_api/l_env.cpp
@@ -284,7 +284,7 @@ int ModApiEnvMod::l_place_node(lua_State *L)
return 1;
}
// Create item to place
- ItemStack item(ndef->get(n).name, 1, 0, "", idef);
+ ItemStack item(ndef->get(n).name, 1, 0, idef);
// Make pointed position
PointedThing pointed;
pointed.type = POINTEDTHING_NODE;
diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp
index ff0baea14..f0293bed8 100644
--- a/src/script/lua_api/l_item.cpp
+++ b/src/script/lua_api/l_item.cpp
@@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include "lua_api/l_item.h"
+#include "lua_api/l_itemstackmeta.h"
#include "lua_api/l_internal.h"
#include "common/c_converter.h"
#include "common/c_content.h"
@@ -137,16 +138,28 @@ int LuaItemStack::l_set_wear(lua_State *L)
return 1;
}
+// get_meta(self) -> string
+int LuaItemStack::l_get_meta(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ LuaItemStack *o = checkobject(L, 1);
+ ItemStackMetaRef::create(L, &o->m_stack);
+ return 1;
+}
+
+// DEPRECATED
// get_metadata(self) -> string
int LuaItemStack::l_get_metadata(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
LuaItemStack *o = checkobject(L, 1);
ItemStack &item = o->m_stack;
- lua_pushlstring(L, item.metadata.c_str(), item.metadata.size());
+ const std::string &value = item.metadata.getString("");
+ lua_pushlstring(L, value.c_str(), value.size());
return 1;
}
+// DEPRECATED
// set_metadata(self, string)
int LuaItemStack::l_set_metadata(lua_State *L)
{
@@ -156,7 +169,7 @@ int LuaItemStack::l_set_metadata(lua_State *L)
size_t len = 0;
const char *ptr = luaL_checklstring(L, 2, &len);
- item.metadata.assign(ptr, len);
+ item.metadata.setString("", std::string(ptr, len));
lua_pushboolean(L, true);
return 1;
@@ -211,8 +224,24 @@ int LuaItemStack::l_to_table(lua_State *L)
lua_setfield(L, -2, "count");
lua_pushinteger(L, item.wear);
lua_setfield(L, -2, "wear");
- lua_pushlstring(L, item.metadata.c_str(), item.metadata.size());
- lua_setfield(L, -2, "metadata");
+
+ if (item.metadata.size() == 1 && item.metadata.contains("")) {
+ const std::string &value = item.metadata.getString("");
+ lua_pushlstring(L, value.c_str(), value.size());
+ lua_setfield(L, -2, "metadata");
+ } else {
+ lua_newtable(L);
+ const StringMap &fields = item.metadata.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, "metadata");
+ }
}
return 1;
}
@@ -443,6 +472,7 @@ const luaL_reg LuaItemStack::methods[] = {
luamethod(LuaItemStack, set_count),
luamethod(LuaItemStack, get_wear),
luamethod(LuaItemStack, set_wear),
+ luamethod(LuaItemStack, get_meta),
luamethod(LuaItemStack, get_metadata),
luamethod(LuaItemStack, set_metadata),
luamethod(LuaItemStack, clear),
diff --git a/src/script/lua_api/l_item.h b/src/script/lua_api/l_item.h
index be919b701..1ba5d79e0 100644
--- a/src/script/lua_api/l_item.h
+++ b/src/script/lua_api/l_item.h
@@ -56,9 +56,14 @@ private:
// set_wear(self, number)
static int l_set_wear(lua_State *L);
+ // get_meta(self) -> string
+ static int l_get_meta(lua_State *L);
+
+ // DEPRECATED
// get_metadata(self) -> string
static int l_get_metadata(lua_State *L);
+ // DEPRECATED
// set_metadata(self, string)
static int l_set_metadata(lua_State *L);
diff --git a/src/script/lua_api/l_itemstackmeta.cpp b/src/script/lua_api/l_itemstackmeta.cpp
new file mode 100644
index 000000000..304a7cdf3
--- /dev/null
+++ b/src/script/lua_api/l_itemstackmeta.cpp
@@ -0,0 +1,115 @@
+/*
+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_itemstackmeta.h"
+#include "lua_api/l_internal.h"
+#include "common/c_content.h"
+
+/*
+ NodeMetaRef
+*/
+ItemStackMetaRef* ItemStackMetaRef::checkobject(lua_State *L, int narg)
+{
+ luaL_checktype(L, narg, LUA_TUSERDATA);
+ void *ud = luaL_checkudata(L, narg, className);
+ if (!ud)
+ luaL_typerror(L, narg, className);
+
+ return *(ItemStackMetaRef**)ud; // unbox pointer
+}
+
+Metadata* ItemStackMetaRef::getmeta(bool auto_create)
+{
+ return &istack->metadata;
+}
+
+void ItemStackMetaRef::clearMeta()
+{
+ istack->metadata.clear();
+}
+
+void ItemStackMetaRef::reportMetadataChange()
+{
+ // TODO
+}
+
+// Exported functions
+
+// garbage collector
+int ItemStackMetaRef::gc_object(lua_State *L) {
+ ItemStackMetaRef *o = *(ItemStackMetaRef **)(lua_touserdata(L, 1));
+ delete o;
+ return 0;
+}
+
+// Creates an NodeMetaRef and leaves it on top of stack
+// Not callable from Lua; all references are created on the C side.
+void ItemStackMetaRef::create(lua_State *L, ItemStack *istack)
+{
+ ItemStackMetaRef *o = new ItemStackMetaRef(istack);
+ //infostream<<"NodeMetaRef::create: o="<<o<<std::endl;
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+}
+
+void ItemStackMetaRef::Register(lua_State *L)
+{
+ lua_newtable(L);
+ int methodtable = lua_gettop(L);
+ luaL_newmetatable(L, className);
+ int metatable = lua_gettop(L);
+
+ lua_pushliteral(L, "__metatable");
+ 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);
+
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, gc_object);
+ lua_settable(L, metatable);
+
+ lua_pop(L, 1); // drop metatable
+
+ luaL_openlib(L, 0, methods, 0); // fill methodtable
+ lua_pop(L, 1); // drop methodtable
+
+ // Cannot be created from Lua
+ //lua_register(L, className, create_object);
+}
+
+const char ItemStackMetaRef::className[] = "ItemStackMetaRef";
+const luaL_reg ItemStackMetaRef::methods[] = {
+ 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),
+ {0,0}
+};
diff --git a/src/script/lua_api/l_itemstackmeta.h b/src/script/lua_api/l_itemstackmeta.h
new file mode 100644
index 000000000..6f9b2016c
--- /dev/null
+++ b/src/script/lua_api/l_itemstackmeta.h
@@ -0,0 +1,59 @@
+/*
+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_ITEMSTACKMETA_H_
+#define L_ITEMSTACKMETA_H_
+
+#include "lua_api/l_base.h"
+#include "lua_api/l_metadata.h"
+#include "irrlichttypes_bloated.h"
+#include "inventory.h"
+
+class ItemStackMetaRef : public MetaDataRef
+{
+private:
+ ItemStack *istack;
+
+ static const char className[];
+ static const luaL_reg methods[];
+
+ static ItemStackMetaRef *checkobject(lua_State *L, int narg);
+
+ virtual Metadata* getmeta(bool auto_create);
+
+ virtual void clearMeta();
+
+ virtual void reportMetadataChange();
+
+ // Exported functions
+
+ // garbage collector
+ static int gc_object(lua_State *L);
+public:
+ ItemStackMetaRef(ItemStack *istack): istack(istack) {}
+ ~ItemStackMetaRef() {}
+
+ // 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, ItemStack *istack);
+
+ static void Register(lua_State *L);
+};
+
+#endif
diff --git a/src/script/scripting_game.cpp b/src/script/scripting_game.cpp
index e313d55f8..7becef6dc 100644
--- a/src/script/scripting_game.cpp
+++ b/src/script/scripting_game.cpp
@@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_env.h"
#include "lua_api/l_inventory.h"
#include "lua_api/l_item.h"
+#include "lua_api/l_itemstackmeta.h"
#include "lua_api/l_mapgen.h"
#include "lua_api/l_nodemeta.h"
#include "lua_api/l_nodetimer.h"
@@ -94,6 +95,7 @@ void GameScripting::InitializeModApi(lua_State *L, int top)
// Register reference classes (userdata)
InvRef::Register(L);
+ ItemStackMetaRef::Register(L);
LuaAreaStore::Register(L);
LuaItemStack::Register(L);
LuaPerlinNoise::Register(L);