Skip to content
Permalink
Browse files

Add ItemStack key-value meta storage

  • Loading branch information...
rubenwardy committed Jan 31, 2017
1 parent c2e7b1f commit f2aa2c6a986dec47856c49ae5f54fbf3c688e027
@@ -164,6 +164,7 @@ LOCAL_SRC_FILES := \
jni/src/inventory.cpp \
jni/src/inventorymanager.cpp \
jni/src/itemdef.cpp \
jni/src/itemstackmetadata.cpp \
jni/src/keycode.cpp \
jni/src/light.cpp \
jni/src/localplayer.cpp \
@@ -305,6 +306,7 @@ LOCAL_SRC_FILES += \
jni/src/script/lua_api/l_env.cpp \
jni/src/script/lua_api/l_inventory.cpp \
jni/src/script/lua_api/l_item.cpp \
jni/src/script/lua_api/l_itemstackmeta.cpp\
jni/src/script/lua_api/l_mainmenu.cpp \
jni/src/script/lua_api/l_mapgen.cpp \
jni/src/script/lua_api/l_metadata.cpp \
@@ -1411,7 +1411,7 @@ the entity itself.
* `direction` is a unit vector, pointing from the source of the punch to
the punched object.
* `damage` damage that will be done to entity
Return value of this function will determin if damage is done by this function
Return value of this function will determin if damage is done by this function
(retval true) or shall be done by engine (retval false)

To punch an entity/object in Lua, call:
@@ -1427,9 +1427,9 @@ Node Metadata
-------------
The instance of a node in the world normally only contains the three values
mentioned in "Nodes". However, it is possible to insert extra data into a
node. It is called "node metadata"; See "`NodeMetaRef`".
node. It is called "node metadata"; See `NodeMetaRef`.

Metadata contains two things:
Node metadata contains two things:

* A key-value store
* An inventory
@@ -1467,6 +1467,18 @@ Example stuff:
}
})

Item Metadata
-------------
Item stacks can store metadata too. See `ItemStackMetaRef`.

Item metadata only contains a key-value store.

Example stuff:

local meta = stack:get_meta()
meta:set_string("key", "value")
print(dump(meta:to_table()))

Formspec
--------
Formspec defines a menu. Currently not much else than inventories are
@@ -2774,9 +2786,8 @@ These functions return the leftover itemstack.
Class reference
---------------

### `NodeMetaRef`
Node metadata: reference extra data and functionality stored in a node.
Can be gotten via `minetest.get_meta(pos)`.
### `MetaDataRef`
See `NodeMetaRef` and `ItemStackMetaRef`.

#### Methods
* `set_string(name, value)`
@@ -2785,13 +2796,29 @@ Can be gotten via `minetest.get_meta(pos)`.
* `get_int(name)`
* `set_float(name, value)`
* `get_float(name)`
* `get_inventory()`: returns `InvRef`
* `to_table()`: returns `nil` or `{fields = {...}, inventory = {list1 = {}, ...}}`
* `to_table()`: returns `nil` or a table with keys:
* `fields`: key-value storage
* `inventory`: `{list1 = {}, ...}}` (NodeMetaRef only)
* `from_table(nil or {})`
* Any non-table value will clear the metadata
* See "Node Metadata"
* See "Node Metadata" for an example
* returns `true` on success

### `NodeMetaRef`
Node metadata: reference extra data and functionality stored in a node.
Can be gotten via `minetest.get_meta(pos)`.

#### Methods
* All methods in MetaDataRef
* `get_inventory()`: returns `InvRef`

### `ItemStackMetaRef`
ItemStack metadata: reference extra data and functionality stored in a stack.
Can be gotten via `item:get_meta()`.

#### Methods
* All methods in MetaDataRef

### `NodeTimerRef`
Node Timers: a high resolution persistent per-node timer.
Can be gotten via `minetest.get_node_timer(pos)`.
@@ -415,6 +415,7 @@ set(common_SRCS
inventory.cpp
inventorymanager.cpp
itemdef.cpp
itemstackmetadata.cpp
light.cpp
log.cpp
map.cpp
@@ -938,7 +938,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_client->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;
}
@@ -1126,4 +1126,3 @@ IWritableCraftDefManager* createCraftDefManager()
{
return new CCraftDefManager();
}

@@ -45,82 +45,16 @@ static content_t content_translate_from_19_to_internal(content_t c_from)
return c_from;
}

// If the string contains spaces, quotes or control characters, encodes as JSON.
// Else returns the string unmodified.
static std::string serializeJsonStringIfNeeded(const std::string &s)
{
for(size_t i = 0; i < s.size(); ++i)
{
if(s[i] <= 0x1f || s[i] >= 0x7f || s[i] == ' ' || s[i] == '\"')
return serializeJsonString(s);
}
return s;
}

// Parses a string serialized by serializeJsonStringIfNeeded.
static std::string deSerializeJsonStringIfNeeded(std::istream &is)
{
std::ostringstream tmp_os;
bool expect_initial_quote = true;
bool is_json = false;
bool was_backslash = false;
for(;;)
{
char c = is.get();
if(is.eof())
break;
if(expect_initial_quote && c == '"')
{
tmp_os << c;
is_json = true;
}
else if(is_json)
{
tmp_os << c;
if(was_backslash)
was_backslash = false;
else if(c == '\\')
was_backslash = true;
else if(c == '"')
break; // Found end of string
}
else
{
if(c == ' ')
{
// Found end of word
is.unget();
break;
}
else
{
tmp_os << c;
}
}
expect_initial_quote = false;
}
if(is_json)
{
std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
return deSerializeJsonString(tmp_is);
}
else
return tmp_os.str();
}


ItemStack::ItemStack(std::string name_, u16 count_,
u16 wear_, std::string metadata_,
IItemDefManager *itemdef)
ItemStack::ItemStack(const std::string &name_, u16 count_,
u16 wear_, IItemDefManager *itemdef)
{
name = itemdef->getAlias(name_);
count = count_;
wear = wear_;
metadata = metadata_;

if(name.empty() || count == 0)
if (name.empty() || count == 0)
clear();
else if(itemdef->get(name).type == ITEM_TOOL)
else if (itemdef->get(name).type == ITEM_TOOL)
count = 1;
}

@@ -137,16 +71,18 @@ void ItemStack::serialize(std::ostream &os) const
parts = 2;
if(wear != 0)
parts = 3;
if(metadata != "")
if (!metadata.empty())
parts = 4;

os<<serializeJsonStringIfNeeded(name);
if(parts >= 2)
os<<" "<<count;
if(parts >= 3)
os<<" "<<wear;
if(parts >= 4)
os<<" "<<serializeJsonStringIfNeeded(metadata);
if (parts >= 4) {
os << " ";
metadata.serialize(os);
}
}

void ItemStack::deSerialize(std::istream &is, IItemDefManager *itemdef)
@@ -289,7 +225,7 @@ void ItemStack::deSerialize(std::istream &is, IItemDefManager *itemdef)
wear = stoi(wear_str);

// Read metadata
metadata = deSerializeJsonStringIfNeeded(is);
metadata.deSerialize(is);

// In case fields are added after metadata, skip space here:
//std::getline(is, tmp, ' ');
@@ -335,7 +271,7 @@ ItemStack ItemStack::addItem(const ItemStack &newitem_,
*this = newitem;
newitem.clear();
}
// If item name or metadata differs, bail out
// If item name or metadata differs, bail out
else if (name != newitem.name
|| metadata != newitem.metadata)
{
@@ -375,7 +311,7 @@ bool ItemStack::itemFits(const ItemStack &newitem_,
{
newitem.clear();
}
// If item name or metadata differs, bail out
// If item name or metadata differs, bail out
else if (name != newitem.name
|| metadata != newitem.metadata)
{
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "debug.h"
#include "itemdef.h"
#include "irrlichttypes.h"
#include "itemstackmetadata.h"
#include <istream>
#include <ostream>
#include <string>
@@ -32,10 +33,10 @@ struct ToolCapabilities;

struct ItemStack
{
ItemStack(): name(""), count(0), wear(0), metadata("") {}
ItemStack(std::string name_, u16 count_,
u16 wear, std::string metadata_,
IItemDefManager *itemdef);
ItemStack(): name(""), count(0), wear(0) {}
ItemStack(const std::string &name_, u16 count_,
u16 wear, IItemDefManager *itemdef);

~ItemStack() {}

// Serialization
@@ -61,7 +62,7 @@ struct ItemStack
name = "";
count = 0;
wear = 0;
metadata = "";
metadata.clear();
}

void add(u16 n)
@@ -166,7 +167,7 @@ struct ItemStack
std::string name;
u16 count;
u16 wear;
std::string metadata;
ItemStackMetadata metadata;
};

class InventoryList
@@ -313,4 +314,3 @@ class Inventory
};

#endif

@@ -0,0 +1,43 @@
#include "itemstackmetadata.h"
#include "util/serialize.h"
#include "util/strfnd.h"

#define DESERIALIZE_START '\x01'
#define DESERIALIZE_KV_DELIM '\x02'
#define DESERIALIZE_PAIR_DELIM '\x03'
#define DESERIALIZE_START_STR "\x01"
#define DESERIALIZE_KV_DELIM_STR "\x02"
#define DESERIALIZE_PAIR_DELIM_STR "\x03"

void ItemStackMetadata::serialize(std::ostream &os) const
{
std::ostringstream os2;
os2 << DESERIALIZE_START;
for (StringMap::const_iterator
it = m_stringvars.begin();
it != m_stringvars.end(); ++it) {
os2 << it->first << DESERIALIZE_KV_DELIM
<< it->second << DESERIALIZE_PAIR_DELIM;
}
os << serializeJsonStringIfNeeded(os2.str());
}

void ItemStackMetadata::deSerialize(std::istream &is)
{
std::string in = deSerializeJsonStringIfNeeded(is);

m_stringvars.clear();

if (!in.empty() && in[0] == DESERIALIZE_START) {
Strfnd fnd(in);
fnd.to(1);
while (!fnd.at_end()) {
std::string name = fnd.next(DESERIALIZE_KV_DELIM_STR);
std::string var = fnd.next(DESERIALIZE_PAIR_DELIM_STR);
m_stringvars[name] = var;
}
} else {
// BACKWARDS COMPATIBILITY
m_stringvars[""] = in;
}
}
@@ -0,0 +1,35 @@
/*
Minetest
Copyright (C) 2010-2013 rubenwardy <rubenwardy@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 "metadata.h"

class Inventory;
class IItemDefManager;

class ItemStackMetadata : public Metadata
{
public:
void serialize(std::ostream &os) const;
void deSerialize(std::istream &is);
};

#endif

0 comments on commit f2aa2c6

Please sign in to comment.
You can’t perform that action at this time.