forked from Mirrorlandia_minetest/minetest
Add ItemStack key-value meta storage
This commit is contained in:
parent
c2e7b1f579
commit
f2aa2c6a98
@ -164,6 +164,7 @@ LOCAL_SRC_FILES := \
|
|||||||
jni/src/inventory.cpp \
|
jni/src/inventory.cpp \
|
||||||
jni/src/inventorymanager.cpp \
|
jni/src/inventorymanager.cpp \
|
||||||
jni/src/itemdef.cpp \
|
jni/src/itemdef.cpp \
|
||||||
|
jni/src/itemstackmetadata.cpp \
|
||||||
jni/src/keycode.cpp \
|
jni/src/keycode.cpp \
|
||||||
jni/src/light.cpp \
|
jni/src/light.cpp \
|
||||||
jni/src/localplayer.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_env.cpp \
|
||||||
jni/src/script/lua_api/l_inventory.cpp \
|
jni/src/script/lua_api/l_inventory.cpp \
|
||||||
jni/src/script/lua_api/l_item.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_mainmenu.cpp \
|
||||||
jni/src/script/lua_api/l_mapgen.cpp \
|
jni/src/script/lua_api/l_mapgen.cpp \
|
||||||
jni/src/script/lua_api/l_metadata.cpp \
|
jni/src/script/lua_api/l_metadata.cpp \
|
||||||
|
@ -1427,9 +1427,9 @@ Node Metadata
|
|||||||
-------------
|
-------------
|
||||||
The instance of a node in the world normally only contains the three values
|
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
|
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
|
* A key-value store
|
||||||
* An inventory
|
* 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
|
||||||
--------
|
--------
|
||||||
Formspec defines a menu. Currently not much else than inventories are
|
Formspec defines a menu. Currently not much else than inventories are
|
||||||
@ -2774,9 +2786,8 @@ These functions return the leftover itemstack.
|
|||||||
Class reference
|
Class reference
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
### `NodeMetaRef`
|
### `MetaDataRef`
|
||||||
Node metadata: reference extra data and functionality stored in a node.
|
See `NodeMetaRef` and `ItemStackMetaRef`.
|
||||||
Can be gotten via `minetest.get_meta(pos)`.
|
|
||||||
|
|
||||||
#### Methods
|
#### Methods
|
||||||
* `set_string(name, value)`
|
* `set_string(name, value)`
|
||||||
@ -2785,13 +2796,29 @@ Can be gotten via `minetest.get_meta(pos)`.
|
|||||||
* `get_int(name)`
|
* `get_int(name)`
|
||||||
* `set_float(name, value)`
|
* `set_float(name, value)`
|
||||||
* `get_float(name)`
|
* `get_float(name)`
|
||||||
* `get_inventory()`: returns `InvRef`
|
* `to_table()`: returns `nil` or a table with keys:
|
||||||
* `to_table()`: returns `nil` or `{fields = {...}, inventory = {list1 = {}, ...}}`
|
* `fields`: key-value storage
|
||||||
|
* `inventory`: `{list1 = {}, ...}}` (NodeMetaRef only)
|
||||||
* `from_table(nil or {})`
|
* `from_table(nil or {})`
|
||||||
* Any non-table value will clear the metadata
|
* Any non-table value will clear the metadata
|
||||||
* See "Node Metadata"
|
* See "Node Metadata" for an example
|
||||||
* returns `true` on success
|
* 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`
|
### `NodeTimerRef`
|
||||||
Node Timers: a high resolution persistent per-node timer.
|
Node Timers: a high resolution persistent per-node timer.
|
||||||
Can be gotten via `minetest.get_node_timer(pos)`.
|
Can be gotten via `minetest.get_node_timer(pos)`.
|
||||||
|
@ -415,6 +415,7 @@ set(common_SRCS
|
|||||||
inventory.cpp
|
inventory.cpp
|
||||||
inventorymanager.cpp
|
inventorymanager.cpp
|
||||||
itemdef.cpp
|
itemdef.cpp
|
||||||
|
itemstackmetadata.cpp
|
||||||
light.cpp
|
light.cpp
|
||||||
log.cpp
|
log.cpp
|
||||||
map.cpp
|
map.cpp
|
||||||
|
@ -938,7 +938,7 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr,
|
|||||||
if(m_prop.textures.size() >= 1){
|
if(m_prop.textures.size() >= 1){
|
||||||
infostream<<"textures[0]: "<<m_prop.textures[0]<<std::endl;
|
infostream<<"textures[0]: "<<m_prop.textures[0]<<std::endl;
|
||||||
IItemDefManager *idef = m_client->idef();
|
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(
|
m_wield_meshnode = new WieldMeshSceneNode(
|
||||||
smgr->getRootSceneNode(), smgr, -1);
|
smgr->getRootSceneNode(), smgr, -1);
|
||||||
|
@ -139,7 +139,7 @@ static std::vector<ItemStack> craftGetItems(
|
|||||||
for (std::vector<std::string>::size_type i = 0;
|
for (std::vector<std::string>::size_type i = 0;
|
||||||
i < items.size(); i++) {
|
i < items.size(); i++) {
|
||||||
result.push_back(ItemStack(std::string(items[i]), (u16)1,
|
result.push_back(ItemStack(std::string(items[i]), (u16)1,
|
||||||
(u16)0, "", gamedef->getItemDefManager()));
|
(u16)0, gamedef->getItemDefManager()));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1126,4 +1126,3 @@ IWritableCraftDefManager* createCraftDefManager()
|
|||||||
{
|
{
|
||||||
return new CCraftDefManager();
|
return new CCraftDefManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,78 +45,12 @@ static content_t content_translate_from_19_to_internal(content_t c_from)
|
|||||||
return c_from;
|
return c_from;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the string contains spaces, quotes or control characters, encodes as JSON.
|
ItemStack::ItemStack(const std::string &name_, u16 count_,
|
||||||
// Else returns the string unmodified.
|
u16 wear_, IItemDefManager *itemdef)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
name = itemdef->getAlias(name_);
|
name = itemdef->getAlias(name_);
|
||||||
count = count_;
|
count = count_;
|
||||||
wear = wear_;
|
wear = wear_;
|
||||||
metadata = metadata_;
|
|
||||||
|
|
||||||
if (name.empty() || count == 0)
|
if (name.empty() || count == 0)
|
||||||
clear();
|
clear();
|
||||||
@ -137,7 +71,7 @@ void ItemStack::serialize(std::ostream &os) const
|
|||||||
parts = 2;
|
parts = 2;
|
||||||
if(wear != 0)
|
if(wear != 0)
|
||||||
parts = 3;
|
parts = 3;
|
||||||
if(metadata != "")
|
if (!metadata.empty())
|
||||||
parts = 4;
|
parts = 4;
|
||||||
|
|
||||||
os<<serializeJsonStringIfNeeded(name);
|
os<<serializeJsonStringIfNeeded(name);
|
||||||
@ -145,8 +79,10 @@ void ItemStack::serialize(std::ostream &os) const
|
|||||||
os<<" "<<count;
|
os<<" "<<count;
|
||||||
if(parts >= 3)
|
if(parts >= 3)
|
||||||
os<<" "<<wear;
|
os<<" "<<wear;
|
||||||
if(parts >= 4)
|
if (parts >= 4) {
|
||||||
os<<" "<<serializeJsonStringIfNeeded(metadata);
|
os << " ";
|
||||||
|
metadata.serialize(os);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemStack::deSerialize(std::istream &is, IItemDefManager *itemdef)
|
void ItemStack::deSerialize(std::istream &is, IItemDefManager *itemdef)
|
||||||
@ -289,7 +225,7 @@ void ItemStack::deSerialize(std::istream &is, IItemDefManager *itemdef)
|
|||||||
wear = stoi(wear_str);
|
wear = stoi(wear_str);
|
||||||
|
|
||||||
// Read metadata
|
// Read metadata
|
||||||
metadata = deSerializeJsonStringIfNeeded(is);
|
metadata.deSerialize(is);
|
||||||
|
|
||||||
// In case fields are added after metadata, skip space here:
|
// In case fields are added after metadata, skip space here:
|
||||||
//std::getline(is, tmp, ' ');
|
//std::getline(is, tmp, ' ');
|
||||||
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "itemdef.h"
|
#include "itemdef.h"
|
||||||
#include "irrlichttypes.h"
|
#include "irrlichttypes.h"
|
||||||
|
#include "itemstackmetadata.h"
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -32,10 +33,10 @@ struct ToolCapabilities;
|
|||||||
|
|
||||||
struct ItemStack
|
struct ItemStack
|
||||||
{
|
{
|
||||||
ItemStack(): name(""), count(0), wear(0), metadata("") {}
|
ItemStack(): name(""), count(0), wear(0) {}
|
||||||
ItemStack(std::string name_, u16 count_,
|
ItemStack(const std::string &name_, u16 count_,
|
||||||
u16 wear, std::string metadata_,
|
u16 wear, IItemDefManager *itemdef);
|
||||||
IItemDefManager *itemdef);
|
|
||||||
~ItemStack() {}
|
~ItemStack() {}
|
||||||
|
|
||||||
// Serialization
|
// Serialization
|
||||||
@ -61,7 +62,7 @@ struct ItemStack
|
|||||||
name = "";
|
name = "";
|
||||||
count = 0;
|
count = 0;
|
||||||
wear = 0;
|
wear = 0;
|
||||||
metadata = "";
|
metadata.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(u16 n)
|
void add(u16 n)
|
||||||
@ -166,7 +167,7 @@ struct ItemStack
|
|||||||
std::string name;
|
std::string name;
|
||||||
u16 count;
|
u16 count;
|
||||||
u16 wear;
|
u16 wear;
|
||||||
std::string metadata;
|
ItemStackMetadata metadata;
|
||||||
};
|
};
|
||||||
|
|
||||||
class InventoryList
|
class InventoryList
|
||||||
@ -313,4 +314,3 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
43
src/itemstackmetadata.cpp
Normal file
43
src/itemstackmetadata.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
35
src/itemstackmetadata.h
Normal file
35
src/itemstackmetadata.h
Normal file
@ -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
|
@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "gamedef.h"
|
#include "gamedef.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include "constants.h" // MAP_BLOCKSIZE
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Metadata
|
Metadata
|
||||||
|
@ -25,35 +25,37 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
|
||||||
/*
|
|
||||||
NodeMetadata stores arbitary amounts of data for special blocks.
|
|
||||||
Used for furnaces, chests and signs.
|
|
||||||
|
|
||||||
There are two interaction methods: inventory menu and text input.
|
|
||||||
Only one can be used for a single metadata, thus only inventory OR
|
|
||||||
text input should exist in a metadata.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Inventory;
|
|
||||||
class IItemDefManager;
|
|
||||||
|
|
||||||
class Metadata
|
class Metadata
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void clear();
|
virtual ~Metadata() {}
|
||||||
bool empty() const;
|
|
||||||
|
|
||||||
// Generic key/value store
|
virtual void clear();
|
||||||
|
virtual bool empty() const;
|
||||||
|
|
||||||
|
bool operator==(const Metadata &other) const;
|
||||||
|
inline bool operator!=(const Metadata &other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Key-value related
|
||||||
|
//
|
||||||
|
|
||||||
|
size_t size() const;
|
||||||
|
bool contains(const std::string &name) const;
|
||||||
const std::string &getString(const std::string &name, u16 recursion = 0) const;
|
const std::string &getString(const std::string &name, u16 recursion = 0) const;
|
||||||
void setString(const std::string &name, const std::string &var);
|
void setString(const std::string &name, const std::string &var);
|
||||||
// Support variable names in values
|
|
||||||
const std::string &resolveString(const std::string &str, u16 recursion = 0) const;
|
|
||||||
const StringMap &getStrings() const
|
const StringMap &getStrings() const
|
||||||
{
|
{
|
||||||
return m_stringvars;
|
return m_stringvars;
|
||||||
}
|
}
|
||||||
private:
|
// Add support for variable names in values
|
||||||
|
const std::string &resolveString(const std::string &str, u16 recursion = 0) const;
|
||||||
|
protected:
|
||||||
StringMap m_stringvars;
|
StringMap m_stringvars;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -824,11 +824,32 @@ ItemStack read_item(lua_State* L, int index,Server* srv)
|
|||||||
std::string name = getstringfield_default(L, index, "name", "");
|
std::string name = getstringfield_default(L, index, "name", "");
|
||||||
int count = getintfield_default(L, index, "count", 1);
|
int count = getintfield_default(L, index, "count", 1);
|
||||||
int wear = getintfield_default(L, index, "wear", 0);
|
int wear = getintfield_default(L, index, "wear", 0);
|
||||||
std::string metadata = getstringfield_default(L, index, "metadata", "");
|
|
||||||
return ItemStack(name, count, wear, metadata, idef);
|
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
|
} 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");
|
throw LuaError("Expecting itemstack, itemstring, table or nil");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ set(common_SCRIPT_LUA_API_SRCS
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/l_env.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/l_env.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/l_inventory.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/l_inventory.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/l_item.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_mapgen.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/l_metadata.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/l_metadata.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/l_nodemeta.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/l_nodemeta.cpp
|
||||||
|
@ -284,7 +284,7 @@ int ModApiEnvMod::l_place_node(lua_State *L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
// Create item to place
|
// 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
|
// Make pointed position
|
||||||
PointedThing pointed;
|
PointedThing pointed;
|
||||||
pointed.type = POINTEDTHING_NODE;
|
pointed.type = POINTEDTHING_NODE;
|
||||||
|
@ -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_item.h"
|
||||||
|
#include "lua_api/l_itemstackmeta.h"
|
||||||
#include "lua_api/l_internal.h"
|
#include "lua_api/l_internal.h"
|
||||||
#include "common/c_converter.h"
|
#include "common/c_converter.h"
|
||||||
#include "common/c_content.h"
|
#include "common/c_content.h"
|
||||||
@ -137,16 +138,28 @@ int LuaItemStack::l_set_wear(lua_State *L)
|
|||||||
return 1;
|
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
|
// get_metadata(self) -> string
|
||||||
int LuaItemStack::l_get_metadata(lua_State *L)
|
int LuaItemStack::l_get_metadata(lua_State *L)
|
||||||
{
|
{
|
||||||
NO_MAP_LOCK_REQUIRED;
|
NO_MAP_LOCK_REQUIRED;
|
||||||
LuaItemStack *o = checkobject(L, 1);
|
LuaItemStack *o = checkobject(L, 1);
|
||||||
ItemStack &item = o->m_stack;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DEPRECATED
|
||||||
// set_metadata(self, string)
|
// set_metadata(self, string)
|
||||||
int LuaItemStack::l_set_metadata(lua_State *L)
|
int LuaItemStack::l_set_metadata(lua_State *L)
|
||||||
{
|
{
|
||||||
@ -156,7 +169,7 @@ int LuaItemStack::l_set_metadata(lua_State *L)
|
|||||||
|
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
const char *ptr = luaL_checklstring(L, 2, &len);
|
const char *ptr = luaL_checklstring(L, 2, &len);
|
||||||
item.metadata.assign(ptr, len);
|
item.metadata.setString("", std::string(ptr, len));
|
||||||
|
|
||||||
lua_pushboolean(L, true);
|
lua_pushboolean(L, true);
|
||||||
return 1;
|
return 1;
|
||||||
@ -211,8 +224,24 @@ int LuaItemStack::l_to_table(lua_State *L)
|
|||||||
lua_setfield(L, -2, "count");
|
lua_setfield(L, -2, "count");
|
||||||
lua_pushinteger(L, item.wear);
|
lua_pushinteger(L, item.wear);
|
||||||
lua_setfield(L, -2, "wear");
|
lua_setfield(L, -2, "wear");
|
||||||
lua_pushlstring(L, item.metadata.c_str(), item.metadata.size());
|
|
||||||
|
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");
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -443,6 +472,7 @@ const luaL_reg LuaItemStack::methods[] = {
|
|||||||
luamethod(LuaItemStack, set_count),
|
luamethod(LuaItemStack, set_count),
|
||||||
luamethod(LuaItemStack, get_wear),
|
luamethod(LuaItemStack, get_wear),
|
||||||
luamethod(LuaItemStack, set_wear),
|
luamethod(LuaItemStack, set_wear),
|
||||||
|
luamethod(LuaItemStack, get_meta),
|
||||||
luamethod(LuaItemStack, get_metadata),
|
luamethod(LuaItemStack, get_metadata),
|
||||||
luamethod(LuaItemStack, set_metadata),
|
luamethod(LuaItemStack, set_metadata),
|
||||||
luamethod(LuaItemStack, clear),
|
luamethod(LuaItemStack, clear),
|
||||||
|
@ -56,9 +56,14 @@ private:
|
|||||||
// set_wear(self, number)
|
// set_wear(self, number)
|
||||||
static int l_set_wear(lua_State *L);
|
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
|
// get_metadata(self) -> string
|
||||||
static int l_get_metadata(lua_State *L);
|
static int l_get_metadata(lua_State *L);
|
||||||
|
|
||||||
|
// DEPRECATED
|
||||||
// set_metadata(self, string)
|
// set_metadata(self, string)
|
||||||
static int l_set_metadata(lua_State *L);
|
static int l_set_metadata(lua_State *L);
|
||||||
|
|
||||||
|
115
src/script/lua_api/l_itemstackmeta.cpp
Normal file
115
src/script/lua_api/l_itemstackmeta.cpp
Normal file
@ -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}
|
||||||
|
};
|
59
src/script/lua_api/l_itemstackmeta.h
Normal file
59
src/script/lua_api/l_itemstackmeta.h
Normal file
@ -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
|
@ -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_env.h"
|
||||||
#include "lua_api/l_inventory.h"
|
#include "lua_api/l_inventory.h"
|
||||||
#include "lua_api/l_item.h"
|
#include "lua_api/l_item.h"
|
||||||
|
#include "lua_api/l_itemstackmeta.h"
|
||||||
#include "lua_api/l_mapgen.h"
|
#include "lua_api/l_mapgen.h"
|
||||||
#include "lua_api/l_nodemeta.h"
|
#include "lua_api/l_nodemeta.h"
|
||||||
#include "lua_api/l_nodetimer.h"
|
#include "lua_api/l_nodetimer.h"
|
||||||
@ -94,6 +95,7 @@ void GameScripting::InitializeModApi(lua_State *L, int top)
|
|||||||
|
|
||||||
// Register reference classes (userdata)
|
// Register reference classes (userdata)
|
||||||
InvRef::Register(L);
|
InvRef::Register(L);
|
||||||
|
ItemStackMetaRef::Register(L);
|
||||||
LuaAreaStore::Register(L);
|
LuaAreaStore::Register(L);
|
||||||
LuaItemStack::Register(L);
|
LuaItemStack::Register(L);
|
||||||
LuaPerlinNoise::Register(L);
|
LuaPerlinNoise::Register(L);
|
||||||
|
@ -354,6 +354,55 @@ std::string deSerializeJsonString(std::istream &is)
|
|||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
////
|
////
|
||||||
//// String/Struct conversions
|
//// String/Struct conversions
|
||||||
////
|
////
|
||||||
|
@ -405,6 +405,13 @@ std::string serializeJsonString(const std::string &plain);
|
|||||||
// Reads a string encoded in JSON format
|
// Reads a string encoded in JSON format
|
||||||
std::string deSerializeJsonString(std::istream &is);
|
std::string deSerializeJsonString(std::istream &is);
|
||||||
|
|
||||||
|
// If the string contains spaces, quotes or control characters, encodes as JSON.
|
||||||
|
// Else returns the string unmodified.
|
||||||
|
std::string serializeJsonStringIfNeeded(const std::string &s);
|
||||||
|
|
||||||
|
// Parses a string serialized by serializeJsonStringIfNeeded.
|
||||||
|
std::string deSerializeJsonStringIfNeeded(std::istream &is);
|
||||||
|
|
||||||
// Creates a string consisting of the hexadecimal representation of `data`
|
// Creates a string consisting of the hexadecimal representation of `data`
|
||||||
std::string serializeHexString(const std::string &data, bool insert_spaces=false);
|
std::string serializeHexString(const std::string &data, bool insert_spaces=false);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user