diff options
Diffstat (limited to 'src/database')
-rw-r--r-- | src/database/database-files.cpp | 125 | ||||
-rw-r--r-- | src/database/database-files.h | 9 |
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; }; |