aboutsummaryrefslogtreecommitdiff
path: root/src/database
diff options
context:
space:
mode:
Diffstat (limited to 'src/database')
-rw-r--r--src/database/database-files.cpp125
-rw-r--r--src/database/database-files.h9
2 files changed, 115 insertions, 19 deletions
diff --git a/src/database/database-files.cpp b/src/database/database-files.cpp
index d2b0b1543..529fb8763 100644
--- a/src/database/database-files.cpp
+++ b/src/database/database-files.cpp
@@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <cassert>
#include <json/json.h>
+#include "convert_json.h"
#include "database-files.h"
#include "remoteplayer.h"
#include "settings.h"
@@ -36,29 +37,117 @@ PlayerDatabaseFiles::PlayerDatabaseFiles(const std::string &savedir) : m_savedir
fs::CreateDir(m_savedir);
}
-void PlayerDatabaseFiles::serialize(std::ostringstream &os, RemotePlayer *player)
+void PlayerDatabaseFiles::deSerialize(RemotePlayer *p, std::istream &is,
+ const std::string &playername, PlayerSAO *sao)
+{
+ Settings args("PlayerArgsEnd");
+
+ if (!args.parseConfigLines(is)) {
+ throw SerializationError("PlayerArgsEnd of player " + playername + " not found!");
+ }
+
+ p->m_dirty = true;
+ //args.getS32("version"); // Version field value not used
+ const std::string &name = args.get("name");
+ strlcpy(p->m_name, name.c_str(), PLAYERNAME_SIZE);
+
+ if (sao) {
+ try {
+ sao->setHPRaw(args.getU16("hp"));
+ } catch(SettingNotFoundException &e) {
+ sao->setHPRaw(PLAYER_MAX_HP_DEFAULT);
+ }
+
+ try {
+ sao->setBasePosition(args.getV3F("position"));
+ } catch (SettingNotFoundException &e) {}
+
+ try {
+ sao->setLookPitch(args.getFloat("pitch"));
+ } catch (SettingNotFoundException &e) {}
+ try {
+ sao->setPlayerYaw(args.getFloat("yaw"));
+ } catch (SettingNotFoundException &e) {}
+
+ try {
+ sao->setBreath(args.getU16("breath"), false);
+ } catch (SettingNotFoundException &e) {}
+
+ try {
+ const std::string &extended_attributes = args.get("extended_attributes");
+ std::istringstream iss(extended_attributes);
+ Json::CharReaderBuilder builder;
+ builder.settings_["collectComments"] = false;
+ std::string errs;
+
+ Json::Value attr_root;
+ Json::parseFromStream(builder, iss, &attr_root, &errs);
+
+ const Json::Value::Members attr_list = attr_root.getMemberNames();
+ for (const auto &it : attr_list) {
+ Json::Value attr_value = attr_root[it];
+ sao->getMeta().setString(it, attr_value.asString());
+ }
+ sao->getMeta().setModified(false);
+ } catch (SettingNotFoundException &e) {}
+ }
+
+ try {
+ p->inventory.deSerialize(is);
+ } catch (SerializationError &e) {
+ errorstream << "Failed to deserialize player inventory. player_name="
+ << name << " " << e.what() << std::endl;
+ }
+
+ if (!p->inventory.getList("craftpreview") && p->inventory.getList("craftresult")) {
+ // Convert players without craftpreview
+ p->inventory.addList("craftpreview", 1);
+
+ bool craftresult_is_preview = true;
+ if(args.exists("craftresult_is_preview"))
+ craftresult_is_preview = args.getBool("craftresult_is_preview");
+ if(craftresult_is_preview)
+ {
+ // Clear craftresult
+ p->inventory.getList("craftresult")->changeItem(0, ItemStack());
+ }
+ }
+}
+
+void PlayerDatabaseFiles::serialize(RemotePlayer *p, std::ostream &os)
{
// Utilize a Settings object for storing values
- Settings args;
+ Settings args("PlayerArgsEnd");
args.setS32("version", 1);
- args.set("name", player->getName());
+ args.set("name", p->m_name);
- sanity_check(player->getPlayerSAO());
- args.setU16("hp", player->getPlayerSAO()->getHP());
- args.setV3F("position", player->getPlayerSAO()->getBasePosition());
- args.setFloat("pitch", player->getPlayerSAO()->getLookPitch());
- args.setFloat("yaw", player->getPlayerSAO()->getRotation().Y);
- args.setU16("breath", player->getPlayerSAO()->getBreath());
+ // This should not happen
+ assert(m_sao);
+ args.setU16("hp", p->m_sao->getHP());
+ args.setV3F("position", p->m_sao->getBasePosition());
+ args.setFloat("pitch", p->m_sao->getLookPitch());
+ args.setFloat("yaw", p->m_sao->getRotation().Y);
+ args.setU16("breath", p->m_sao->getBreath());
std::string extended_attrs;
- player->serializeExtraAttributes(extended_attrs);
+ {
+ // serializeExtraAttributes
+ PlayerSAO *sao = p->getPlayerSAO();
+ assert(sao);
+ Json::Value json_root;
+
+ const StringMap &attrs = sao->getMeta().getStrings();
+ for (const auto &attr : attrs) {
+ json_root[attr.first] = attr.second;
+ }
+
+ extended_attrs = fastWriteJson(json_root);
+ }
args.set("extended_attributes", extended_attrs);
args.writeLines(os);
- os << "PlayerArgsEnd\n";
-
- player->inventory.serialize(os);
+ p->inventory.serialize(os);
}
void PlayerDatabaseFiles::savePlayer(RemotePlayer *player)
@@ -83,7 +172,7 @@ void PlayerDatabaseFiles::savePlayer(RemotePlayer *player)
return;
}
- testplayer.deSerialize(is, path, NULL);
+ deSerialize(&testplayer, is, path, NULL);
is.close();
if (strcmp(testplayer.getName(), player->getName()) == 0) {
path_found = true;
@@ -101,7 +190,7 @@ void PlayerDatabaseFiles::savePlayer(RemotePlayer *player)
// Open and serialize file
std::ostringstream ss(std::ios_base::binary);
- serialize(ss, player);
+ serialize(&testplayer, ss);
if (!fs::safeWriteToFile(path, ss.str())) {
infostream << "Failed to write " << path << std::endl;
}
@@ -121,7 +210,7 @@ bool PlayerDatabaseFiles::removePlayer(const std::string &name)
if (!is.good())
continue;
- temp_player.deSerialize(is, path, NULL);
+ deSerialize(&temp_player, is, path, NULL);
is.close();
if (temp_player.getName() == name) {
@@ -147,7 +236,7 @@ bool PlayerDatabaseFiles::loadPlayer(RemotePlayer *player, PlayerSAO *sao)
if (!is.good())
continue;
- player->deSerialize(is, path, sao);
+ deSerialize(player, is, path, sao);
is.close();
if (player->getName() == player_to_load)
@@ -180,7 +269,7 @@ void PlayerDatabaseFiles::listPlayers(std::vector<std::string> &res)
// Null env & dummy peer_id
PlayerSAO playerSAO(NULL, &player, 15789, false);
- player.deSerialize(is, "", &playerSAO);
+ deSerialize(&player, is, "", &playerSAO);
is.close();
res.emplace_back(player.getName());
diff --git a/src/database/database-files.h b/src/database/database-files.h
index cb830a3ed..a041cb1ff 100644
--- a/src/database/database-files.h
+++ b/src/database/database-files.h
@@ -38,7 +38,14 @@ public:
void listPlayers(std::vector<std::string> &res);
private:
- void serialize(std::ostringstream &os, RemotePlayer *player);
+ void deSerialize(RemotePlayer *p, std::istream &is,
+ const std::string &playername, PlayerSAO *sao);
+ /*
+ serialize() writes a bunch of text that can contain
+ any characters except a '\0', and such an ending that
+ deSerialize stops reading exactly at the right point.
+ */
+ void serialize(RemotePlayer *p, std::ostream &os);
std::string m_savedir;
};