mirror of
https://github.com/luanti-org/luanti.git
synced 2025-10-28 22:25:20 +01:00
Turn item metadata into a key-value store while keeping compatibility to the old interface via the empty string field
This commit is contained in:
@@ -424,6 +424,7 @@ set(common_SRCS
|
||||
version.cpp
|
||||
voxel.cpp
|
||||
voxelalgorithms.cpp
|
||||
itemstackmetadata.cpp
|
||||
${common_network_SRCS}
|
||||
${JTHREAD_SRCS}
|
||||
${common_SCRIPT_SRCS}
|
||||
|
||||
@@ -948,7 +948,7 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr,
|
||||
if(m_prop.textures.size() >= 1){
|
||||
infostream<<"textures[0]: "<<m_prop.textures[0]<<std::endl;
|
||||
IItemDefManager *idef = m_gamedef->idef();
|
||||
ItemStack item(m_prop.textures[0], 1, 0, "", idef);
|
||||
ItemStack item(m_prop.textures[0], 1, 0, idef);
|
||||
|
||||
m_wield_meshnode = new WieldMeshSceneNode(
|
||||
smgr->getRootSceneNode(), smgr, -1);
|
||||
|
||||
@@ -139,7 +139,7 @@ static std::vector<ItemStack> craftGetItems(
|
||||
for (std::vector<std::string>::size_type i = 0;
|
||||
i < items.size(); i++) {
|
||||
result.push_back(ItemStack(std::string(items[i]), (u16)1,
|
||||
(u16)0, "", gamedef->getItemDefManager()));
|
||||
(u16)0, gamedef->getItemDefManager()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "nameidmapping.h" // For loading legacy MaterialItems
|
||||
#include "util/serialize.h"
|
||||
#include "util/string.h"
|
||||
#include "itemstackmetadata.h"
|
||||
|
||||
/*
|
||||
ItemStack
|
||||
@@ -110,7 +111,7 @@ static std::string deSerializeJsonStringIfNeeded(std::istream &is)
|
||||
|
||||
|
||||
ItemStack::ItemStack(std::string name_, u16 count_,
|
||||
u16 wear_, std::string metadata_,
|
||||
u16 wear_, ItemStackMetadata metadata_,
|
||||
IItemDefManager *itemdef)
|
||||
{
|
||||
name = itemdef->getAlias(name_);
|
||||
@@ -123,6 +124,19 @@ ItemStack::ItemStack(std::string name_, u16 count_,
|
||||
else if(itemdef->get(name).type == ITEM_TOOL)
|
||||
count = 1;
|
||||
}
|
||||
ItemStack::ItemStack(std::string name_, u16 count_,
|
||||
u16 wear_,
|
||||
IItemDefManager *itemdef)
|
||||
{
|
||||
name = itemdef->getAlias(name_);
|
||||
count = count_;
|
||||
wear = wear_;
|
||||
|
||||
if(name.empty() || count == 0)
|
||||
clear();
|
||||
else if(itemdef->get(name).type == ITEM_TOOL)
|
||||
count = 1;
|
||||
}
|
||||
|
||||
void ItemStack::serialize(std::ostream &os) const
|
||||
{
|
||||
@@ -137,7 +151,7 @@ void ItemStack::serialize(std::ostream &os) const
|
||||
parts = 2;
|
||||
if(wear != 0)
|
||||
parts = 3;
|
||||
if(metadata != "")
|
||||
if(!metadata.isEmpty())
|
||||
parts = 4;
|
||||
|
||||
os<<serializeJsonStringIfNeeded(name);
|
||||
@@ -145,8 +159,9 @@ void ItemStack::serialize(std::ostream &os) const
|
||||
os<<" "<<count;
|
||||
if(parts >= 3)
|
||||
os<<" "<<wear;
|
||||
if(parts >= 4)
|
||||
os<<" "<<serializeJsonStringIfNeeded(metadata);
|
||||
if(parts >= 4) {
|
||||
os<<" "<<serializeJsonStringIfNeeded(metadata.serialize());
|
||||
}
|
||||
}
|
||||
|
||||
void ItemStack::deSerialize(std::istream &is, IItemDefManager *itemdef)
|
||||
@@ -289,8 +304,8 @@ void ItemStack::deSerialize(std::istream &is, IItemDefManager *itemdef)
|
||||
wear = stoi(wear_str);
|
||||
|
||||
// Read metadata
|
||||
metadata = deSerializeJsonStringIfNeeded(is);
|
||||
|
||||
std::string readMeta=deSerializeJsonStringIfNeeded(is);
|
||||
metadata.deSerialize(readMeta);
|
||||
// In case fields are added after metadata, skip space here:
|
||||
//std::getline(is, tmp, ' ');
|
||||
//if(!tmp.empty())
|
||||
@@ -579,8 +594,8 @@ bool InventoryList::operator == (const InventoryList &other) const
|
||||
{
|
||||
ItemStack s1 = m_items[i];
|
||||
ItemStack s2 = other.m_items[i];
|
||||
if(s1.name != s2.name || s1.wear!= s2.wear || s1.count != s2.count ||
|
||||
s1.metadata != s2.metadata)
|
||||
//TODO possible error source: stack metadata are not compared!
|
||||
if(s1.name != s2.name || s1.wear!= s2.wear || s1.count != s2.count)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,15 +27,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "itemstackmetadata.h"
|
||||
|
||||
struct ToolCapabilities;
|
||||
|
||||
struct ItemStack
|
||||
{
|
||||
ItemStack(): name(""), count(0), wear(0), metadata("") {}
|
||||
ItemStack(): name(""), count(0), wear(0), metadata() {}
|
||||
ItemStack(std::string name_, u16 count_,
|
||||
u16 wear, std::string metadata_,
|
||||
u16 wear, ItemStackMetadata metadata_,
|
||||
IItemDefManager *itemdef);
|
||||
//constructor for empty metadata. before the item meta k-v-store was implemented, functions used to call above constructor with an empty string.
|
||||
ItemStack(std::string name_, u16 count_,
|
||||
u16 wear,
|
||||
IItemDefManager *itemdef);
|
||||
~ItemStack() {}
|
||||
|
||||
// Serialization
|
||||
@@ -61,7 +66,7 @@ struct ItemStack
|
||||
name = "";
|
||||
count = 0;
|
||||
wear = 0;
|
||||
metadata = "";
|
||||
metadata.clear();
|
||||
}
|
||||
|
||||
void add(u16 n)
|
||||
@@ -167,7 +172,7 @@ struct ItemStack
|
||||
std::string name;
|
||||
u16 count;
|
||||
u16 wear;
|
||||
std::string metadata;
|
||||
ItemStackMetadata metadata;
|
||||
};
|
||||
|
||||
class InventoryList
|
||||
|
||||
106
src/itemstackmetadata.cpp
Normal file
106
src/itemstackmetadata.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2010-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 "itemstackmetadata.h"
|
||||
#include "exceptions.h"
|
||||
#include "gamedef.h"
|
||||
#include "inventory.h"
|
||||
#include "log.h"
|
||||
#include "util/serialize.h"
|
||||
#include "util/strfnd.h"
|
||||
#include "constants.h" // MAP_BLOCKSIZE
|
||||
#include <sstream>
|
||||
|
||||
/*
|
||||
ItemStackMetadata
|
||||
*/
|
||||
|
||||
std::string ItemStackMetadata::serialize() const
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "$";
|
||||
for (StringMap::const_iterator
|
||||
it = m_stringvars.begin();
|
||||
it != m_stringvars.end(); ++it) {
|
||||
os << it->first << "=";
|
||||
os << serializeJsonString(it->second) << "\n";
|
||||
}
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void ItemStackMetadata::deSerialize(std::string &in)
|
||||
{
|
||||
m_stringvars.clear();
|
||||
//to indicate new serialisation version, a dollar sign has to be the first char in the serialized string. if not, apply legacy deserialization
|
||||
if (in[0] == '$') {
|
||||
Strfnd fnd(in);
|
||||
fnd.to(1);
|
||||
while ( !fnd.at_end() ) {
|
||||
std::string name = fnd.next("=");
|
||||
std::string var_json=fnd.next("\n");
|
||||
std::istringstream var_stream(var_json);
|
||||
std::string var = deSerializeJsonString(var_stream);
|
||||
m_stringvars[name] = var;
|
||||
}
|
||||
}else{
|
||||
//legacy: store value in empty field ("")
|
||||
m_stringvars[""]=in;
|
||||
}
|
||||
}
|
||||
|
||||
void ItemStackMetadata::clear()
|
||||
{
|
||||
m_stringvars.clear();
|
||||
}
|
||||
bool ItemStackMetadata::isEmpty() const
|
||||
{
|
||||
return m_stringvars.empty();
|
||||
}
|
||||
|
||||
std::string ItemStackMetadata::getString(const std::string &name,
|
||||
unsigned short recursion) const
|
||||
{
|
||||
StringMap::const_iterator it = m_stringvars.find(name);
|
||||
if (it == m_stringvars.end())
|
||||
return "";
|
||||
|
||||
return resolveString(it->second, recursion);
|
||||
}
|
||||
|
||||
void ItemStackMetadata::setString(const std::string &name, const std::string &var)
|
||||
{
|
||||
if (var.empty()) {
|
||||
m_stringvars.erase(name);
|
||||
} else {
|
||||
m_stringvars[name] = var;
|
||||
}
|
||||
}
|
||||
|
||||
std::string ItemStackMetadata::resolveString(const std::string &str,
|
||||
unsigned short recursion) const
|
||||
{
|
||||
if (recursion > 1) {
|
||||
return str;
|
||||
}
|
||||
if (str.substr(0, 2) == "${" && str[str.length() - 1] == '}') {
|
||||
return getString(str.substr(2, str.length() - 3), recursion + 1);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
62
src/itemstackmetadata.h
Normal file
62
src/itemstackmetadata.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2010-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 ITEMSTACKMETADATA_HEADER
|
||||
#define ITEMSTACKMETADATA_HEADER
|
||||
|
||||
#include "irr_v3d.h"
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "util/string.h"
|
||||
|
||||
/*
|
||||
ItemStackMetadata stores arbitary amounts of data for items as a key-value store.
|
||||
*/
|
||||
|
||||
class Inventory;
|
||||
class IItemDefManager;
|
||||
|
||||
class ItemStackMetadata
|
||||
{
|
||||
public:
|
||||
ItemStackMetadata():
|
||||
m_stringvars()
|
||||
{
|
||||
};
|
||||
~ItemStackMetadata(){};
|
||||
|
||||
std::string serialize() const;
|
||||
void deSerialize(std::string &in);
|
||||
|
||||
void clear();
|
||||
bool isEmpty() const;
|
||||
// Generic key/value store
|
||||
std::string getString(const std::string &name, unsigned short recursion = 0) const;
|
||||
void setString(const std::string &name, const std::string &var);
|
||||
// Support variable names in values
|
||||
std::string resolveString(const std::string &str, unsigned short recursion = 0) const;
|
||||
StringMap getStrings(){
|
||||
return m_stringvars;
|
||||
};
|
||||
private:
|
||||
StringMap m_stringvars;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -811,8 +811,7 @@ 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);
|
||||
return ItemStack(name, count, wear, idef);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ set(common_SCRIPT_LUA_API_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_item.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_mapgen.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_nodemeta.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_itemstackmeta.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_nodetimer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_noise.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_object.cpp
|
||||
|
||||
@@ -280,7 +280,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;
|
||||
|
||||
@@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "content_sao.h"
|
||||
#include "inventory.h"
|
||||
#include "log.h"
|
||||
#include "lua_api/l_itemstackmeta.h"
|
||||
|
||||
|
||||
// garbage collector
|
||||
@@ -137,13 +138,24 @@ int LuaItemStack::l_set_wear(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_meta(self) -> userdata //note get_metadata and set_metadata mimic old behavior
|
||||
int LuaItemStack::l_get_meta(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
ItemStackMetaRef::create(L, &item);
|
||||
return 1;
|
||||
}
|
||||
//LEGACY metadata access
|
||||
// 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());
|
||||
std::string metastr=item.metadata.getString("");
|
||||
lua_pushlstring(L, metastr.c_str(), metastr.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -156,7 +168,9 @@ 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);
|
||||
std::string metastr;
|
||||
metastr.assign(ptr, len);
|
||||
item.metadata.setString("", metastr);
|
||||
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
@@ -211,8 +225,6 @@ 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");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -443,8 +455,9 @@ const luaL_reg LuaItemStack::methods[] = {
|
||||
luamethod(LuaItemStack, set_count),
|
||||
luamethod(LuaItemStack, get_wear),
|
||||
luamethod(LuaItemStack, set_wear),
|
||||
luamethod(LuaItemStack, get_metadata),
|
||||
luamethod(LuaItemStack, set_metadata),
|
||||
luamethod(LuaItemStack, get_meta),
|
||||
luamethod(LuaItemStack, get_metadata),//legacy
|
||||
luamethod(LuaItemStack, set_metadata),//legacy
|
||||
luamethod(LuaItemStack, clear),
|
||||
luamethod(LuaItemStack, replace),
|
||||
luamethod(LuaItemStack, to_string),
|
||||
|
||||
@@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
#include "inventory.h" // ItemStack
|
||||
#include "lua_api/l_itemstackmeta.h"
|
||||
#include "itemstackmetadata.h"
|
||||
|
||||
class LuaItemStack : public ModApiBase {
|
||||
private:
|
||||
@@ -56,10 +58,13 @@ private:
|
||||
// set_wear(self, number)
|
||||
static int l_set_wear(lua_State *L);
|
||||
|
||||
// get_metadata(self) -> string
|
||||
// get_meta(self) -> userdata(ItemStackMetaRef)
|
||||
static int l_get_meta(lua_State *L);
|
||||
|
||||
// get_metadata(self) -> string (legacy)
|
||||
static int l_get_metadata(lua_State *L);
|
||||
|
||||
// set_metadata(self, string)
|
||||
// set_metadata(self, string) (legacy)
|
||||
static int l_set_metadata(lua_State *L);
|
||||
|
||||
// clear(self) -> true
|
||||
|
||||
304
src/script/lua_api/l_itemstackmeta.cpp
Normal file
304
src/script/lua_api/l_itemstackmeta.cpp
Normal file
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
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 "lua_api/l_inventory.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "common/c_content.h"
|
||||
#include "gamedef.h"
|
||||
#include "inventory.h"
|
||||
#include "itemstackmetadata.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
ItemStackMetaRef
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
||||
ItemStackMetadata* ItemStackMetaRef::getmeta(ItemStackMetaRef *ref)
|
||||
{
|
||||
ItemStackMetadata *meta = &(ref->m_istack->metadata);
|
||||
return meta;
|
||||
}
|
||||
|
||||
|
||||
void ItemStackMetaRef::reportMetadataChange(ItemStackMetaRef *ref)
|
||||
{
|
||||
//At the moment, it does not seem to be neccessary to notify anything about changed metadata.
|
||||
//Reserved for future use.
|
||||
}
|
||||
|
||||
|
||||
// Exported functions
|
||||
|
||||
// garbage collector
|
||||
int ItemStackMetaRef::gc_object(lua_State *L) {
|
||||
ItemStackMetaRef *o = *(ItemStackMetaRef **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_string(self, name)
|
||||
int ItemStackMetaRef::l_get_string(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
ItemStackMetaRef *ref = checkobject(L, 1);
|
||||
std::string name = luaL_checkstring(L, 2);
|
||||
|
||||
ItemStackMetadata *meta = getmeta(ref);
|
||||
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 ItemStackMetaRef::l_set_string(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
ItemStackMetaRef *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);
|
||||
|
||||
ItemStackMetadata *meta = getmeta(ref);
|
||||
if(meta == NULL || str == meta->getString(name))
|
||||
return 0;
|
||||
meta->setString(name, str);
|
||||
reportMetadataChange(ref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_int(self, name)
|
||||
int ItemStackMetaRef::l_get_int(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
ItemStackMetaRef *ref = checkobject(L, 1);
|
||||
std::string name = lua_tostring(L, 2);
|
||||
|
||||
ItemStackMetadata *meta = getmeta(ref);
|
||||
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 ItemStackMetaRef::l_set_int(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
ItemStackMetaRef *ref = checkobject(L, 1);
|
||||
std::string name = lua_tostring(L, 2);
|
||||
int a = lua_tointeger(L, 3);
|
||||
std::string str = itos(a);
|
||||
|
||||
ItemStackMetadata *meta = getmeta(ref);
|
||||
if(meta == NULL || str == meta->getString(name))
|
||||
return 0;
|
||||
meta->setString(name, str);
|
||||
reportMetadataChange(ref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_float(self, name)
|
||||
int ItemStackMetaRef::l_get_float(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
ItemStackMetaRef *ref = checkobject(L, 1);
|
||||
std::string name = lua_tostring(L, 2);
|
||||
|
||||
ItemStackMetadata *meta = getmeta(ref);
|
||||
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 ItemStackMetaRef::l_set_float(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
ItemStackMetaRef *ref = checkobject(L, 1);
|
||||
std::string name = lua_tostring(L, 2);
|
||||
float a = lua_tonumber(L, 3);
|
||||
std::string str = ftos(a);
|
||||
|
||||
ItemStackMetadata *meta = getmeta(ref);
|
||||
if(meta == NULL || str == meta->getString(name))
|
||||
return 0;
|
||||
meta->setString(name, str);
|
||||
reportMetadataChange(ref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// to_table(self)
|
||||
int ItemStackMetaRef::l_to_table(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
ItemStackMetaRef *ref = checkobject(L, 1);
|
||||
|
||||
ItemStackMetadata *meta = getmeta(ref);
|
||||
if (meta == NULL) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// from_table(self, table)
|
||||
int ItemStackMetaRef::l_from_table(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
ItemStackMetaRef *ref = checkobject(L, 1);
|
||||
int base = 2;
|
||||
|
||||
ItemStackMetadata *meta = getmeta(ref);
|
||||
|
||||
if(meta == NULL){
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
meta->clear();
|
||||
|
||||
if(lua_isnil(L, base)){
|
||||
// No metadata
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set fields
|
||||
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);
|
||||
std::string value(cs, cl);
|
||||
meta->setString(name, value);
|
||||
lua_pop(L, 1); // removes value, keeps key for next iteration
|
||||
}
|
||||
|
||||
reportMetadataChange(ref);
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
ItemStackMetaRef::ItemStackMetaRef(ItemStack *istack):
|
||||
m_istack(istack)
|
||||
{
|
||||
}
|
||||
|
||||
ItemStackMetaRef::~ItemStackMetaRef()
|
||||
{
|
||||
}
|
||||
|
||||
// Creates an ItemStackMetaRef 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<<"ItemStackMetaRef::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, "__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(ItemStackMetaRef, get_string),
|
||||
luamethod(ItemStackMetaRef, set_string),
|
||||
luamethod(ItemStackMetaRef, get_int),
|
||||
luamethod(ItemStackMetaRef, set_int),
|
||||
luamethod(ItemStackMetaRef, get_float),
|
||||
luamethod(ItemStackMetaRef, set_float),
|
||||
luamethod(ItemStackMetaRef, to_table),
|
||||
luamethod(ItemStackMetaRef, from_table),
|
||||
{0,0}
|
||||
};
|
||||
94
src/script/lua_api/l_itemstackmeta.h
Normal file
94
src/script/lua_api/l_itemstackmeta.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
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 "irrlichttypes_bloated.h"
|
||||
#include "inventory.h"
|
||||
|
||||
class ServerEnvironment;
|
||||
class ItemStackMetadata;
|
||||
|
||||
/*
|
||||
ItemStackMetaRef
|
||||
*/
|
||||
|
||||
class ItemStackMetaRef : public ModApiBase {
|
||||
private:
|
||||
ItemStack *m_istack;
|
||||
|
||||
static const char className[];
|
||||
static const luaL_reg methods[];
|
||||
|
||||
static ItemStackMetaRef *checkobject(lua_State *L, int narg);
|
||||
|
||||
/**
|
||||
* Retrieve metadata for an itemstack (the one given as pointer as member variable).
|
||||
* @return pointer to a @c ItemStackMetadata object.
|
||||
*/
|
||||
static ItemStackMetadata* getmeta(ItemStackMetaRef *ref);
|
||||
|
||||
static void reportMetadataChange(ItemStackMetaRef *ref);
|
||||
|
||||
// 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:
|
||||
ItemStackMetaRef(ItemStack *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 /* L_NODEMETA_H_ */
|
||||
@@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "lua_api/l_item.h"
|
||||
#include "lua_api/l_mapgen.h"
|
||||
#include "lua_api/l_nodemeta.h"
|
||||
#include "lua_api/l_itemstackmeta.h"
|
||||
#include "lua_api/l_nodetimer.h"
|
||||
#include "lua_api/l_noise.h"
|
||||
#include "lua_api/l_object.h"
|
||||
@@ -103,6 +104,7 @@ void GameScripting::InitializeModApi(lua_State *L, int top)
|
||||
LuaSecureRandom::Register(L);
|
||||
LuaVoxelManip::Register(L);
|
||||
NodeMetaRef::Register(L);
|
||||
ItemStackMetaRef::Register(L);
|
||||
NodeTimerRef::Register(L);
|
||||
ObjectRef::Register(L);
|
||||
LuaSettings::Register(L);
|
||||
|
||||
Reference in New Issue
Block a user