Skip to content

Commit

Permalink
Add player:get_meta(), deprecate player attributes (#7202)
Browse files Browse the repository at this point in the history
* Add player:get_meta(), deprecate player attributes
  • Loading branch information
rubenwardy authored and nerzhul committed Apr 6, 2018
1 parent 7e3f88f commit 91615f9
Show file tree
Hide file tree
Showing 22 changed files with 314 additions and 70 deletions.
1 change: 1 addition & 0 deletions build/android/jni/Android.mk
Expand Up @@ -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 \
Expand Down
16 changes: 13 additions & 3 deletions doc/lua_api.txt
Expand Up @@ -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)`
Expand Down Expand Up @@ -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)`.
Expand Down Expand Up @@ -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`
Expand Down
34 changes: 31 additions & 3 deletions games/minimal/mods/test/init.lua
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
49 changes: 3 additions & 46 deletions src/content_sao.h
Expand Up @@ -197,7 +197,6 @@ class LagPool
} }
}; };


typedef std::unordered_map<std::string, std::string> PlayerAttributes;
class RemotePlayer; class RemotePlayer;


class PlayerSAO : public UnitSAO class PlayerSAO : public UnitSAO
Expand Down Expand Up @@ -269,49 +268,6 @@ class PlayerSAO : public UnitSAO
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
*/ */
Expand Down Expand Up @@ -375,6 +331,8 @@ class PlayerSAO : public UnitSAO
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();
Expand Down Expand Up @@ -410,8 +368,7 @@ class PlayerSAO : public UnitSAO
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;
Expand Down
6 changes: 4 additions & 2 deletions src/database/database-postgresql.cpp
Expand Up @@ -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(),
Expand All @@ -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();
} }


Expand Down Expand Up @@ -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);


Expand Down
6 changes: 4 additions & 2 deletions src/database/database-sqlite3.cpp
Expand Up @@ -520,14 +520,15 @@ 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);
str_to_sqlite(m_stmt_player_metadata_add, 3, attr.second); str_to_sqlite(m_stmt_player_metadata_add, 3, attr.second);
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();
} }
Expand Down Expand Up @@ -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;
} }
Expand Down
20 changes: 20 additions & 0 deletions src/itemstackmetadata.cpp
@@ -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"
Expand Down
2 changes: 1 addition & 1 deletion src/itemstackmetadata.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
Expand Down
14 changes: 14 additions & 0 deletions src/metadata.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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
* *
Expand All @@ -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;
} }


Expand Down
7 changes: 6 additions & 1 deletion src/metadata.h
Expand Up @@ -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;


Expand All @@ -45,14 +46,18 @@ class Metadata
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;

}; };
8 changes: 5 additions & 3 deletions src/remoteplayer.cpp
Expand Up @@ -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);
} }




Expand Down Expand Up @@ -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) {}
} }


Expand Down
1 change: 1 addition & 0 deletions src/script/lua_api/CMakeLists.txt
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/script/lua_api/l_itemstackmeta.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
Expand Down
2 changes: 2 additions & 0 deletions src/script/lua_api/l_itemstackmeta.h
@@ -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
Expand Down
1 change: 1 addition & 0 deletions src/script/lua_api/l_metadata.cpp
@@ -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
Expand Down

0 comments on commit 91615f9

Please sign in to comment.