mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 01:53:45 +01:00
Add player:get_meta(), deprecate player attributes (#7202)
* Add player:get_meta(), deprecate player attributes
This commit is contained in:
parent
7e3f88f539
commit
91615f9588
@ -347,6 +347,7 @@ LOCAL_SRC_FILES += \
|
|||||||
jni/src/script/lua_api/l_nodetimer.cpp \
|
jni/src/script/lua_api/l_nodetimer.cpp \
|
||||||
jni/src/script/lua_api/l_noise.cpp \
|
jni/src/script/lua_api/l_noise.cpp \
|
||||||
jni/src/script/lua_api/l_object.cpp \
|
jni/src/script/lua_api/l_object.cpp \
|
||||||
|
jni/src/script/lua_api/l_playermeta.cpp \
|
||||||
jni/src/script/lua_api/l_particles.cpp \
|
jni/src/script/lua_api/l_particles.cpp \
|
||||||
jni/src/script/lua_api/l_particles_local.cpp\
|
jni/src/script/lua_api/l_particles_local.cpp\
|
||||||
jni/src/script/lua_api/l_rollback.cpp \
|
jni/src/script/lua_api/l_rollback.cpp \
|
||||||
|
@ -3902,7 +3902,7 @@ An interface to use mod channels on client and server
|
|||||||
* Message size is limited to 65535 characters by protocol.
|
* Message size is limited to 65535 characters by protocol.
|
||||||
|
|
||||||
### `MetaDataRef`
|
### `MetaDataRef`
|
||||||
See `StorageRef`, `NodeMetaRef` and `ItemStackMetaRef`.
|
See `StorageRef`, `NodeMetaRef`, `ItemStackMetaRef`, and `PlayerMetaRef`.
|
||||||
|
|
||||||
#### Methods
|
#### Methods
|
||||||
* `set_string(name, value)`
|
* `set_string(name, value)`
|
||||||
@ -3952,6 +3952,15 @@ Can be obtained via `minetest.get_mod_storage()` during load time.
|
|||||||
#### Methods
|
#### Methods
|
||||||
* All methods in MetaDataRef
|
* All methods in MetaDataRef
|
||||||
|
|
||||||
|
### `PlayerMetaRef`
|
||||||
|
Player metadata.
|
||||||
|
Uses the same method of storage as the deprecated player attribute API, so
|
||||||
|
data there will also be in player meta.
|
||||||
|
Can be obtained using `player: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)`.
|
||||||
@ -4101,14 +4110,15 @@ This is basically a reference to a C++ `ServerActiveObject`
|
|||||||
* `0`: player is drowning
|
* `0`: player is drowning
|
||||||
* max: bubbles bar is not shown
|
* max: bubbles bar is not shown
|
||||||
* See Object Properties for more information
|
* See Object Properties for more information
|
||||||
* `set_attribute(attribute, value)`:
|
* `set_attribute(attribute, value)`: DEPRECATED, use get_meta() instead
|
||||||
* Sets an extra attribute with value on player.
|
* Sets an extra attribute with value on player.
|
||||||
* `value` must be a string, or a number which will be converted to a
|
* `value` must be a string, or a number which will be converted to a
|
||||||
string.
|
string.
|
||||||
* If `value` is `nil`, remove attribute from player.
|
* If `value` is `nil`, remove attribute from player.
|
||||||
* `get_attribute(attribute)`:
|
* `get_attribute(attribute)`: DEPRECATED, use get_meta() instead
|
||||||
* Returns value (a string) for extra attribute.
|
* Returns value (a string) for extra attribute.
|
||||||
* Returns `nil` if no attribute found.
|
* Returns `nil` if no attribute found.
|
||||||
|
* `get_meta()`: Returns a PlayerMetaRef.
|
||||||
* `set_inventory_formspec(formspec)`
|
* `set_inventory_formspec(formspec)`
|
||||||
* Redefine player's inventory form
|
* Redefine player's inventory form
|
||||||
* Should usually be called in `on_joinplayer`
|
* Should usually be called in `on_joinplayer`
|
||||||
|
@ -13,7 +13,7 @@ assert(pseudo:next() == 13854)
|
|||||||
-- HP Change Reasons
|
-- HP Change Reasons
|
||||||
--
|
--
|
||||||
local expect = nil
|
local expect = nil
|
||||||
minetest.register_on_joinplayer(function(player)
|
local function run_hpchangereason_tests(player)
|
||||||
expect = { type = "set_hp", from = "mod" }
|
expect = { type = "set_hp", from = "mod" }
|
||||||
player:set_hp(3)
|
player:set_hp(3)
|
||||||
assert(expect == nil)
|
assert(expect == nil)
|
||||||
@ -25,8 +25,7 @@ minetest.register_on_joinplayer(function(player)
|
|||||||
expect = { df = 3458973454, type = "fall", from = "mod" }
|
expect = { df = 3458973454, type = "fall", from = "mod" }
|
||||||
player:set_hp(10, { type = "fall", df = 3458973454 })
|
player:set_hp(10, { type = "fall", df = 3458973454 })
|
||||||
assert(expect == nil)
|
assert(expect == nil)
|
||||||
end)
|
end
|
||||||
|
|
||||||
minetest.register_on_player_hpchange(function(player, hp, reason)
|
minetest.register_on_player_hpchange(function(player, hp, reason)
|
||||||
for key, value in pairs(reason) do
|
for key, value in pairs(reason) do
|
||||||
assert(expect[key] == value)
|
assert(expect[key] == value)
|
||||||
@ -38,3 +37,32 @@ minetest.register_on_player_hpchange(function(player, hp, reason)
|
|||||||
|
|
||||||
expect = nil
|
expect = nil
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
local function run_player_meta_tests(player)
|
||||||
|
local meta = player:get_meta()
|
||||||
|
meta:set_string("foo", "bar")
|
||||||
|
assert(meta:get_string("foo") == "bar")
|
||||||
|
|
||||||
|
local meta2 = player:get_meta()
|
||||||
|
assert(meta2:get_string("foo") == "bar")
|
||||||
|
assert(meta:equals(meta2))
|
||||||
|
assert(player:get_attribute("foo") == "bar")
|
||||||
|
|
||||||
|
meta:set_string("bob", "dillan")
|
||||||
|
assert(meta:get_string("foo") == "bar")
|
||||||
|
assert(meta:get_string("bob") == "dillan")
|
||||||
|
assert(meta2:get_string("foo") == "bar")
|
||||||
|
assert(meta2:get_string("bob") == "dillan")
|
||||||
|
assert(meta:equals(meta2))
|
||||||
|
assert(player:get_attribute("foo") == "bar")
|
||||||
|
assert(player:get_attribute("bob") == "dillan")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function run_player_tests(player)
|
||||||
|
run_hpchangereason_tests(player)
|
||||||
|
run_player_meta_tests(player)
|
||||||
|
minetest.chat_send_all("All tests pass!")
|
||||||
|
end
|
||||||
|
minetest.register_on_joinplayer(run_player_tests)
|
||||||
|
@ -197,7 +197,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::unordered_map<std::string, std::string> PlayerAttributes;
|
|
||||||
class RemotePlayer;
|
class RemotePlayer;
|
||||||
|
|
||||||
class PlayerSAO : public UnitSAO
|
class PlayerSAO : public UnitSAO
|
||||||
@ -269,49 +268,6 @@ public:
|
|||||||
int getWieldIndex() const;
|
int getWieldIndex() const;
|
||||||
void setWieldIndex(int i);
|
void setWieldIndex(int i);
|
||||||
|
|
||||||
/*
|
|
||||||
Modding interface
|
|
||||||
*/
|
|
||||||
inline void setExtendedAttribute(const std::string &attr, const std::string &value)
|
|
||||||
{
|
|
||||||
m_extra_attributes[attr] = value;
|
|
||||||
m_extended_attributes_modified = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool getExtendedAttribute(const std::string &attr, std::string *value)
|
|
||||||
{
|
|
||||||
if (m_extra_attributes.find(attr) == m_extra_attributes.end())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
*value = m_extra_attributes[attr];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void removeExtendedAttribute(const std::string &attr)
|
|
||||||
{
|
|
||||||
PlayerAttributes::iterator it = m_extra_attributes.find(attr);
|
|
||||||
if (it == m_extra_attributes.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_extra_attributes.erase(it);
|
|
||||||
m_extended_attributes_modified = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const PlayerAttributes &getExtendedAttributes()
|
|
||||||
{
|
|
||||||
return m_extra_attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool extendedAttributesModified() const
|
|
||||||
{
|
|
||||||
return m_extended_attributes_modified;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void setExtendedAttributeModified(bool v)
|
|
||||||
{
|
|
||||||
m_extended_attributes_modified = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
PlayerSAO-specific
|
PlayerSAO-specific
|
||||||
*/
|
*/
|
||||||
@ -375,6 +331,8 @@ public:
|
|||||||
v3f getEyePosition() const { return m_base_position + getEyeOffset(); }
|
v3f getEyePosition() const { return m_base_position + getEyeOffset(); }
|
||||||
v3f getEyeOffset() const;
|
v3f getEyeOffset() const;
|
||||||
|
|
||||||
|
inline Metadata &getMeta() { return m_meta; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string getPropertyPacket();
|
std::string getPropertyPacket();
|
||||||
void unlinkPlayerSessionAndSave();
|
void unlinkPlayerSessionAndSave();
|
||||||
@ -410,8 +368,7 @@ private:
|
|||||||
f32 m_fov = 0.0f;
|
f32 m_fov = 0.0f;
|
||||||
s16 m_wanted_range = 0.0f;
|
s16 m_wanted_range = 0.0f;
|
||||||
|
|
||||||
PlayerAttributes m_extra_attributes;
|
Metadata m_meta;
|
||||||
bool m_extended_attributes_modified = false;
|
|
||||||
public:
|
public:
|
||||||
float m_physics_override_speed = 1.0f;
|
float m_physics_override_speed = 1.0f;
|
||||||
float m_physics_override_jump = 1.0f;
|
float m_physics_override_jump = 1.0f;
|
||||||
|
@ -518,7 +518,7 @@ void PlayerDatabasePostgreSQL::savePlayer(RemotePlayer *player)
|
|||||||
}
|
}
|
||||||
|
|
||||||
execPrepared("remove_player_metadata", 1, rmvalues);
|
execPrepared("remove_player_metadata", 1, rmvalues);
|
||||||
const PlayerAttributes &attrs = sao->getExtendedAttributes();
|
const StringMap &attrs = sao->getMeta().getStrings();
|
||||||
for (const auto &attr : attrs) {
|
for (const auto &attr : attrs) {
|
||||||
const char *meta_values[] = {
|
const char *meta_values[] = {
|
||||||
player->getName(),
|
player->getName(),
|
||||||
@ -527,6 +527,7 @@ void PlayerDatabasePostgreSQL::savePlayer(RemotePlayer *player)
|
|||||||
};
|
};
|
||||||
execPrepared("save_player_metadata", 3, meta_values);
|
execPrepared("save_player_metadata", 3, meta_values);
|
||||||
}
|
}
|
||||||
|
sao->getMeta().setModified(false);
|
||||||
endSave();
|
endSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,8 +595,9 @@ bool PlayerDatabasePostgreSQL::loadPlayer(RemotePlayer *player, PlayerSAO *sao)
|
|||||||
|
|
||||||
int numrows = PQntuples(results);
|
int numrows = PQntuples(results);
|
||||||
for (int row = 0; row < numrows; row++) {
|
for (int row = 0; row < numrows; row++) {
|
||||||
sao->setExtendedAttribute(PQgetvalue(results, row, 0),PQgetvalue(results, row, 1));
|
sao->getMeta().setString(PQgetvalue(results, row, 0), PQgetvalue(results, row, 1));
|
||||||
}
|
}
|
||||||
|
sao->getMeta().setModified(false);
|
||||||
|
|
||||||
PQclear(results);
|
PQclear(results);
|
||||||
|
|
||||||
|
@ -520,7 +520,7 @@ void PlayerDatabaseSQLite3::savePlayer(RemotePlayer *player)
|
|||||||
sqlite3_vrfy(sqlite3_step(m_stmt_player_metadata_remove), SQLITE_DONE);
|
sqlite3_vrfy(sqlite3_step(m_stmt_player_metadata_remove), SQLITE_DONE);
|
||||||
sqlite3_reset(m_stmt_player_metadata_remove);
|
sqlite3_reset(m_stmt_player_metadata_remove);
|
||||||
|
|
||||||
const PlayerAttributes &attrs = sao->getExtendedAttributes();
|
const StringMap &attrs = sao->getMeta().getStrings();
|
||||||
for (const auto &attr : attrs) {
|
for (const auto &attr : attrs) {
|
||||||
str_to_sqlite(m_stmt_player_metadata_add, 1, player->getName());
|
str_to_sqlite(m_stmt_player_metadata_add, 1, player->getName());
|
||||||
str_to_sqlite(m_stmt_player_metadata_add, 2, attr.first);
|
str_to_sqlite(m_stmt_player_metadata_add, 2, attr.first);
|
||||||
@ -528,6 +528,7 @@ void PlayerDatabaseSQLite3::savePlayer(RemotePlayer *player)
|
|||||||
sqlite3_vrfy(sqlite3_step(m_stmt_player_metadata_add), SQLITE_DONE);
|
sqlite3_vrfy(sqlite3_step(m_stmt_player_metadata_add), SQLITE_DONE);
|
||||||
sqlite3_reset(m_stmt_player_metadata_add);
|
sqlite3_reset(m_stmt_player_metadata_add);
|
||||||
}
|
}
|
||||||
|
sao->getMeta().setModified(false);
|
||||||
|
|
||||||
endSave();
|
endSave();
|
||||||
}
|
}
|
||||||
@ -578,8 +579,9 @@ bool PlayerDatabaseSQLite3::loadPlayer(RemotePlayer *player, PlayerSAO *sao)
|
|||||||
std::string attr = sqlite_to_string(m_stmt_player_metadata_load, 0);
|
std::string attr = sqlite_to_string(m_stmt_player_metadata_load, 0);
|
||||||
std::string value = sqlite_to_string(m_stmt_player_metadata_load, 1);
|
std::string value = sqlite_to_string(m_stmt_player_metadata_load, 1);
|
||||||
|
|
||||||
sao->setExtendedAttribute(attr, value);
|
sao->getMeta().setString(attr, value);
|
||||||
}
|
}
|
||||||
|
sao->getMeta().setModified(false);
|
||||||
sqlite3_reset(m_stmt_player_metadata_load);
|
sqlite3_reset(m_stmt_player_metadata_load);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,23 @@
|
|||||||
|
/*
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2017-8 rubenwardy <rw@rubenwardy.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 "itemstackmetadata.h"
|
||||||
#include "util/serialize.h"
|
#include "util/serialize.h"
|
||||||
#include "util/strfnd.h"
|
#include "util/strfnd.h"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Minetest
|
Minetest
|
||||||
Copyright (C) 2010-2013 rubenwardy <rubenwardy@gmail.com>
|
Copyright (C) 2017-8 rubenwardy <rw@rubenwardy.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
void Metadata::clear()
|
void Metadata::clear()
|
||||||
{
|
{
|
||||||
m_stringvars.clear();
|
m_stringvars.clear();
|
||||||
|
m_modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Metadata::empty() const
|
bool Metadata::empty() const
|
||||||
@ -68,6 +69,18 @@ const std::string &Metadata::getString(const std::string &name, u16 recursion) c
|
|||||||
return resolveString(it->second, recursion);
|
return resolveString(it->second, recursion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Metadata::getStringToRef(
|
||||||
|
const std::string &name, std::string &str, u16 recursion) const
|
||||||
|
{
|
||||||
|
StringMap::const_iterator it = m_stringvars.find(name);
|
||||||
|
if (it == m_stringvars.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
str = resolveString(it->second, recursion);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets var to name key in the metadata storage
|
* Sets var to name key in the metadata storage
|
||||||
*
|
*
|
||||||
@ -88,6 +101,7 @@ bool Metadata::setString(const std::string &name, const std::string &var)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_stringvars[name] = var;
|
m_stringvars[name] = var;
|
||||||
|
m_modified = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
class Metadata
|
class Metadata
|
||||||
{
|
{
|
||||||
|
bool m_modified = false;
|
||||||
public:
|
public:
|
||||||
virtual ~Metadata() = default;
|
virtual ~Metadata() = default;
|
||||||
|
|
||||||
@ -45,14 +46,18 @@ public:
|
|||||||
size_t size() const;
|
size_t size() const;
|
||||||
bool contains(const std::string &name) 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;
|
||||||
|
bool getStringToRef(const std::string &name, std::string &str, u16 recursion = 0) const;
|
||||||
virtual bool setString(const std::string &name, const std::string &var);
|
virtual bool setString(const std::string &name, const std::string &var);
|
||||||
|
inline bool removeString(const std::string &name) { return setString(name, ""); }
|
||||||
const StringMap &getStrings() const
|
const StringMap &getStrings() const
|
||||||
{
|
{
|
||||||
return m_stringvars;
|
return m_stringvars;
|
||||||
}
|
}
|
||||||
// Add support for variable names in values
|
// Add support for variable names in values
|
||||||
const std::string &resolveString(const std::string &str, u16 recursion = 0) const;
|
const std::string &resolveString(const std::string &str, u16 recursion = 0) const;
|
||||||
|
|
||||||
|
inline bool isModified() const { return m_modified; }
|
||||||
|
inline void setModified(bool v) { m_modified = v; }
|
||||||
protected:
|
protected:
|
||||||
StringMap m_stringvars;
|
StringMap m_stringvars;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -72,14 +72,15 @@ void RemotePlayer::serializeExtraAttributes(std::string &output)
|
|||||||
{
|
{
|
||||||
assert(m_sao);
|
assert(m_sao);
|
||||||
Json::Value json_root;
|
Json::Value json_root;
|
||||||
const PlayerAttributes &attrs = m_sao->getExtendedAttributes();
|
|
||||||
|
const StringMap &attrs = m_sao->getMeta().getStrings();
|
||||||
for (const auto &attr : attrs) {
|
for (const auto &attr : attrs) {
|
||||||
json_root[attr.first] = attr.second;
|
json_root[attr.first] = attr.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
output = fastWriteJson(json_root);
|
output = fastWriteJson(json_root);
|
||||||
|
|
||||||
m_sao->setExtendedAttributeModified(false);
|
m_sao->getMeta().setModified(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -132,8 +133,9 @@ void RemotePlayer::deSerialize(std::istream &is, const std::string &playername,
|
|||||||
const Json::Value::Members attr_list = attr_root.getMemberNames();
|
const Json::Value::Members attr_list = attr_root.getMemberNames();
|
||||||
for (const auto &it : attr_list) {
|
for (const auto &it : attr_list) {
|
||||||
Json::Value attr_value = attr_root[it];
|
Json::Value attr_value = attr_root[it];
|
||||||
sao->setExtendedAttribute(it, attr_value.asString());
|
sao->getMeta().setString(it, attr_value.asString());
|
||||||
}
|
}
|
||||||
|
sao->getMeta().setModified(false);
|
||||||
} catch (SettingNotFoundException &e) {}
|
} catch (SettingNotFoundException &e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ set(common_SCRIPT_LUA_API_SRCS
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/l_noise.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/l_noise.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/l_object.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/l_object.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/l_particles.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/l_particles.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/l_playermeta.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/l_rollback.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/l_rollback.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/l_server.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/l_server.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/l_settings.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/l_settings.cpp
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
Minetest
|
Minetest
|
||||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
Copyright (C) 2017-8 rubenwardy <rw@rubenwardy.com>
|
||||||
|
Copyright (C) 2017 raymoo
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
Minetest
|
Minetest
|
||||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
Copyright (C) 2017-8 rubenwardy <rw@rubenwardy.com>
|
||||||
|
Copyright (C) 2017 raymoo
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
Minetest
|
Minetest
|
||||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
Copyright (C) 2017-8 rubenwardy <rw@rubenwardy.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
Minetest
|
Minetest
|
||||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2013-8 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
Copyright (C) 2017-8 rubenwardy <rw@rubenwardy.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "lua_api/l_internal.h"
|
#include "lua_api/l_internal.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_playermeta.h"
|
||||||
#include "common/c_converter.h"
|
#include "common/c_converter.h"
|
||||||
#include "common/c_content.h"
|
#include "common/c_content.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
@ -1218,16 +1219,15 @@ int ObjectRef::l_set_attribute(lua_State *L)
|
|||||||
{
|
{
|
||||||
ObjectRef *ref = checkobject(L, 1);
|
ObjectRef *ref = checkobject(L, 1);
|
||||||
PlayerSAO* co = getplayersao(ref);
|
PlayerSAO* co = getplayersao(ref);
|
||||||
if (co == NULL) {
|
if (co == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
std::string attr = luaL_checkstring(L, 2);
|
std::string attr = luaL_checkstring(L, 2);
|
||||||
if (lua_isnil(L, 3)) {
|
if (lua_isnil(L, 3)) {
|
||||||
co->removeExtendedAttribute(attr);
|
co->getMeta().removeString(attr);
|
||||||
} else {
|
} else {
|
||||||
std::string value = luaL_checkstring(L, 3);
|
std::string value = luaL_checkstring(L, 3);
|
||||||
co->setExtendedAttribute(attr, value);
|
co->getMeta().setString(attr, value);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1237,14 +1237,13 @@ int ObjectRef::l_get_attribute(lua_State *L)
|
|||||||
{
|
{
|
||||||
ObjectRef *ref = checkobject(L, 1);
|
ObjectRef *ref = checkobject(L, 1);
|
||||||
PlayerSAO* co = getplayersao(ref);
|
PlayerSAO* co = getplayersao(ref);
|
||||||
if (co == NULL) {
|
if (co == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
std::string attr = luaL_checkstring(L, 2);
|
std::string attr = luaL_checkstring(L, 2);
|
||||||
|
|
||||||
std::string value;
|
std::string value;
|
||||||
if (co->getExtendedAttribute(attr, &value)) {
|
if (co->getMeta().getStringToRef(attr, value)) {
|
||||||
lua_pushstring(L, value.c_str());
|
lua_pushstring(L, value.c_str());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1253,6 +1252,19 @@ int ObjectRef::l_get_attribute(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// get_meta(self, attribute)
|
||||||
|
int ObjectRef::l_get_meta(lua_State *L)
|
||||||
|
{
|
||||||
|
ObjectRef *ref = checkobject(L, 1);
|
||||||
|
PlayerSAO *co = getplayersao(ref);
|
||||||
|
if (co == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
PlayerMetaRef::create(L, &co->getMeta());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// set_inventory_formspec(self, formspec)
|
// set_inventory_formspec(self, formspec)
|
||||||
int ObjectRef::l_set_inventory_formspec(lua_State *L)
|
int ObjectRef::l_set_inventory_formspec(lua_State *L)
|
||||||
{
|
{
|
||||||
@ -1884,6 +1896,7 @@ const luaL_Reg ObjectRef::methods[] = {
|
|||||||
luamethod(ObjectRef, set_breath),
|
luamethod(ObjectRef, set_breath),
|
||||||
luamethod(ObjectRef, get_attribute),
|
luamethod(ObjectRef, get_attribute),
|
||||||
luamethod(ObjectRef, set_attribute),
|
luamethod(ObjectRef, set_attribute),
|
||||||
|
luamethod(ObjectRef, get_meta),
|
||||||
luamethod(ObjectRef, set_inventory_formspec),
|
luamethod(ObjectRef, set_inventory_formspec),
|
||||||
luamethod(ObjectRef, get_inventory_formspec),
|
luamethod(ObjectRef, get_inventory_formspec),
|
||||||
luamethod(ObjectRef, set_formspec_prepend),
|
luamethod(ObjectRef, set_formspec_prepend),
|
||||||
|
@ -250,6 +250,9 @@ private:
|
|||||||
// get_attribute(self, attribute)
|
// get_attribute(self, attribute)
|
||||||
static int l_get_attribute(lua_State *L);
|
static int l_get_attribute(lua_State *L);
|
||||||
|
|
||||||
|
// get_meta(self)
|
||||||
|
static int l_get_meta(lua_State *L);
|
||||||
|
|
||||||
// set_inventory_formspec(self, formspec)
|
// set_inventory_formspec(self, formspec)
|
||||||
static int l_set_inventory_formspec(lua_State *L);
|
static int l_set_inventory_formspec(lua_State *L);
|
||||||
|
|
||||||
|
121
src/script/lua_api/l_playermeta.cpp
Normal file
121
src/script/lua_api/l_playermeta.cpp
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
Copyright (C) 2017-8 rubenwardy <rw@rubenwardy.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_playermeta.h"
|
||||||
|
#include "lua_api/l_internal.h"
|
||||||
|
#include "common/c_content.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
PlayerMetaRef
|
||||||
|
*/
|
||||||
|
PlayerMetaRef *PlayerMetaRef::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 *(PlayerMetaRef **)ud; // unbox pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
Metadata *PlayerMetaRef::getmeta(bool auto_create)
|
||||||
|
{
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerMetaRef::clearMeta()
|
||||||
|
{
|
||||||
|
metadata->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerMetaRef::reportMetadataChange()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// garbage collector
|
||||||
|
int PlayerMetaRef::gc_object(lua_State *L)
|
||||||
|
{
|
||||||
|
PlayerMetaRef *o = *(PlayerMetaRef **)(lua_touserdata(L, 1));
|
||||||
|
delete o;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates an PlayerMetaRef and leaves it on top of stack
|
||||||
|
// Not callable from Lua; all references are created on the C side.
|
||||||
|
void PlayerMetaRef::create(lua_State *L, Metadata *metadata)
|
||||||
|
{
|
||||||
|
PlayerMetaRef *o = new PlayerMetaRef(metadata);
|
||||||
|
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||||
|
luaL_getmetatable(L, className);
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerMetaRef::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_pushliteral(L, "__eq");
|
||||||
|
lua_pushcfunction(L, l_equals);
|
||||||
|
lua_settable(L, metatable);
|
||||||
|
|
||||||
|
lua_pop(L, 1); // drop metatable
|
||||||
|
|
||||||
|
luaL_openlib(L, 0, methods, 0);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
// Cannot be created from Lua
|
||||||
|
// lua_register(L, className, create_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
const char PlayerMetaRef::className[] = "PlayerMetaRef";
|
||||||
|
const luaL_Reg PlayerMetaRef::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),
|
||||||
|
luamethod(MetaDataRef, equals),
|
||||||
|
{0,0}
|
||||||
|
};
|
||||||
|
// clang-format on
|
57
src/script/lua_api/l_playermeta.h
Normal file
57
src/script/lua_api/l_playermeta.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
Copyright (C) 2017-8 rubenwardy <rw@rubenwardy.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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "lua_api/l_base.h"
|
||||||
|
#include "lua_api/l_metadata.h"
|
||||||
|
#include "irrlichttypes_bloated.h"
|
||||||
|
#include "inventory.h"
|
||||||
|
#include "metadata.h"
|
||||||
|
|
||||||
|
class PlayerMetaRef : public MetaDataRef
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Metadata *metadata = nullptr;
|
||||||
|
|
||||||
|
static const char className[];
|
||||||
|
static const luaL_Reg methods[];
|
||||||
|
|
||||||
|
static PlayerMetaRef *checkobject(lua_State *L, int narg);
|
||||||
|
|
||||||
|
virtual Metadata *getmeta(bool auto_create);
|
||||||
|
|
||||||
|
virtual void clearMeta();
|
||||||
|
|
||||||
|
virtual void reportMetadataChange();
|
||||||
|
|
||||||
|
// garbage collector
|
||||||
|
static int gc_object(lua_State *L);
|
||||||
|
|
||||||
|
public:
|
||||||
|
PlayerMetaRef(Metadata *metadata) : metadata(metadata) {}
|
||||||
|
~PlayerMetaRef() = default;
|
||||||
|
|
||||||
|
// 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, Metadata *metadata);
|
||||||
|
|
||||||
|
static void Register(lua_State *L);
|
||||||
|
};
|
@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "lua_api/l_nodetimer.h"
|
#include "lua_api/l_nodetimer.h"
|
||||||
#include "lua_api/l_noise.h"
|
#include "lua_api/l_noise.h"
|
||||||
#include "lua_api/l_object.h"
|
#include "lua_api/l_object.h"
|
||||||
|
#include "lua_api/l_playermeta.h"
|
||||||
#include "lua_api/l_particles.h"
|
#include "lua_api/l_particles.h"
|
||||||
#include "lua_api/l_rollback.h"
|
#include "lua_api/l_rollback.h"
|
||||||
#include "lua_api/l_server.h"
|
#include "lua_api/l_server.h"
|
||||||
@ -99,6 +100,7 @@ void ServerScripting::InitializeModApi(lua_State *L, int top)
|
|||||||
NodeMetaRef::Register(L);
|
NodeMetaRef::Register(L);
|
||||||
NodeTimerRef::Register(L);
|
NodeTimerRef::Register(L);
|
||||||
ObjectRef::Register(L);
|
ObjectRef::Register(L);
|
||||||
|
PlayerMetaRef::Register(L);
|
||||||
LuaSettings::Register(L);
|
LuaSettings::Register(L);
|
||||||
StorageRef::Register(L);
|
StorageRef::Register(L);
|
||||||
ModChannelRef::Register(L);
|
ModChannelRef::Register(L);
|
||||||
|
@ -535,7 +535,7 @@ void ServerEnvironment::saveLoadedPlayers()
|
|||||||
|
|
||||||
for (RemotePlayer *player : m_players) {
|
for (RemotePlayer *player : m_players) {
|
||||||
if (player->checkModified() || (player->getPlayerSAO() &&
|
if (player->checkModified() || (player->getPlayerSAO() &&
|
||||||
player->getPlayerSAO()->extendedAttributesModified())) {
|
player->getPlayerSAO()->getMeta().isModified())) {
|
||||||
try {
|
try {
|
||||||
m_player_database->savePlayer(player);
|
m_player_database->savePlayer(player);
|
||||||
} catch (DatabaseException &e) {
|
} catch (DatabaseException &e) {
|
||||||
|
Loading…
Reference in New Issue
Block a user