+bool WorldSave::Exists(const Player &player) const {
+ return is_file(PlayerPath(player));
+}
+
+void WorldSave::Read(Player &player) const {
+ ifstream is(PlayerPath(player));
+ TokenStreamReader in(is);
+ string name;
+ EntityState state;
+ while (in.HasMore()) {
+ in.ReadIdentifier(name);
+ in.Skip(Token::EQUALS);
+ if (name == "chunk") {
+ in.ReadVec(state.chunk_pos);
+ } else if (name == "position") {
+ in.ReadVec(state.block_pos);
+ } else if (name == "orientation") {
+ in.ReadQuat(state.orient);
+ } else if (name == "slot") {
+ int slot;
+ in.ReadNumber(slot);
+ player.SetInventorySlot(slot);
+ }
+ if (in.HasMore() && in.Peek().type == Token::SEMICOLON) {
+ in.Skip(Token::SEMICOLON);
+ }
+ }
+ player.GetEntity().SetState(state);
+}
+
+void WorldSave::Write(const Player &player) const {
+ if (!make_dirs(player_path)) {
+ throw runtime_error("failed to create player save directory");
+ }
+ const EntityState &state = player.GetEntity().GetState();
+ ofstream out(PlayerPath(player));
+ out << "chunk = " << state.chunk_pos << ';' << endl;
+ out << "position = " << state.block_pos << ';' << endl;
+ out << "orientation = " << state.orient << ';' << endl;
+ out << "slot = " << player.GetInventorySlot() << ';' << endl;
+}
+
+string WorldSave::PlayerPath(const Player &player) const {
+ // TODO: this is potentially dangerous, server and client should
+ // provide a sanitized name for storage
+ return player_path + player.Name();
+}
+
+