mirror of
https://github.com/minetest/minetest.git
synced 2024-12-23 14:42:24 +01:00
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/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,7 +71,7 @@ void ItemStack::serialize(std::ostream &os) const
|
||||
parts = 2;
|
||||
if(wear != 0)
|
||||
parts = 3;
|
||||
if(metadata != "")
|
||||
if (!metadata.empty())
|
||||
parts = 4;
|
||||
|
||||
os<<serializeJsonStringIfNeeded(name);
|
||||
@ -145,8 +79,10 @@ void ItemStack::serialize(std::ostream &os) const
|
||||
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 @@ private:
|
||||
};
|
||||
|
||||
#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 "log.h"
|
||||
#include <sstream>
|
||||
#include "constants.h" // MAP_BLOCKSIZE
|
||||
#include <sstream>
|
||||
|
||||
/*
|
||||
Metadata
|
||||
|
@ -25,35 +25,37 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <vector>
|
||||
#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
|
||||
{
|
||||
public:
|
||||
void clear();
|
||||
bool empty() const;
|
||||
virtual ~Metadata() {}
|
||||
|
||||
// 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;
|
||||
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
|
||||
{
|
||||
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;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
||||
|
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_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);
|
||||
|
@ -354,6 +354,55 @@ std::string deSerializeJsonString(std::istream &is)
|
||||
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
|
||||
////
|
||||
|
@ -405,6 +405,13 @@ std::string serializeJsonString(const std::string &plain);
|
||||
// Reads a string encoded in JSON format
|
||||
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`
|
||||
std::string serializeHexString(const std::string &data, bool insert_spaces=false);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user