From 6efedcdd33b512875641068c92a5eebc0c3c9381 Mon Sep 17 00:00:00 2001 From: jacob1 Date: Sat, 15 Jul 2017 16:21:16 -0400 Subject: [PATCH] undo authors changes on ctrl+z, prevent excessive nesting --- src/client/Client.h | 4 +- src/client/GameSave.cpp | 114 +++++++++++++++++++--------- src/client/GameSave.h | 2 +- src/gui/game/GameController.cpp | 5 ++ src/gui/game/GameModel.cpp | 2 +- src/gui/game/GameView.cpp | 2 +- src/gui/save/ServerSaveActivity.cpp | 2 +- src/simulation/Snapshot.h | 3 + 8 files changed, 91 insertions(+), 43 deletions(-) diff --git a/src/client/Client.h b/src/client/Client.h index 47928b86f6..2f3a0b0ed3 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -97,12 +97,10 @@ class Client: public Singleton { void MergeStampAuthorInfo(Json::Value linksToAdd); void MergeAuthorInfo(Json::Value linksToAdd); void OverwriteAuthorInfo(Json::Value overwrite) { authors = overwrite; } + Json::Value GetAuthorInfo() { return authors; } void SaveAuthorInfo(Json::Value *saveInto); void ClearAuthorInfo() { authors.clear(); } bool IsAuthorsEmpty() { return authors.size() == 0; } -#if defined(DEBUG) || defined(SNAPSHOT) - std::string GetAuthorString() { return authors.toStyledString(); } -#endif UpdateInfo GetUpdateInfo(); diff --git a/src/client/GameSave.cpp b/src/client/GameSave.cpp index 4100c5666e..e2253dd096 100644 --- a/src/client/GameSave.cpp +++ b/src/client/GameSave.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "Config.h" #include "Format.h" @@ -1136,38 +1137,6 @@ void GameSave::readOPS(char * data, int dataLength) free(partsSimIndex); } -void GameSave::ConvertBsonToJson(bson_iterator *iter, Json::Value *j) -{ - bson_iterator subiter; - bson_iterator_subiterator(iter, &subiter); - while (bson_iterator_next(&subiter)) - { - std::string key = bson_iterator_key(&subiter); - if (bson_iterator_type(&subiter) == BSON_STRING) - (*j)[key] = bson_iterator_string(&subiter); - else if (bson_iterator_type(&subiter) == BSON_BOOL) - (*j)[key] = bson_iterator_bool(&subiter); - else if (bson_iterator_type(&subiter) == BSON_INT) - (*j)[key] = bson_iterator_int(&subiter); - else if (bson_iterator_type(&subiter) == BSON_LONG) - (*j)[key] = (Json::Value::Int64)bson_iterator_long(&subiter); - else if (bson_iterator_type(&subiter) == BSON_ARRAY) - { - bson_iterator arrayiter; - bson_iterator_subiterator(&subiter, &arrayiter); - while (bson_iterator_next(&arrayiter)) - { - if (bson_iterator_type(&arrayiter) == BSON_OBJECT && !strcmp(bson_iterator_key(&arrayiter), "part")) - { - Json::Value tempPart; - ConvertBsonToJson(&arrayiter, &tempPart); - (*j)["links"].append(tempPart); - } - } - } - } -} - void GameSave::readPSv(char * data, int dataLength) { unsigned char * d = NULL, * c = (unsigned char *)data; @@ -2377,8 +2346,68 @@ char * GameSave::serialiseOPS(unsigned int & dataLength) return (char*)outputData; } +void GameSave::ConvertBsonToJson(bson_iterator *iter, Json::Value *j) +{ + bson_iterator subiter; + bson_iterator_subiterator(iter, &subiter); + while (bson_iterator_next(&subiter)) + { + std::string key = bson_iterator_key(&subiter); + if (bson_iterator_type(&subiter) == BSON_STRING) + (*j)[key] = bson_iterator_string(&subiter); + else if (bson_iterator_type(&subiter) == BSON_BOOL) + (*j)[key] = bson_iterator_bool(&subiter); + else if (bson_iterator_type(&subiter) == BSON_INT) + (*j)[key] = bson_iterator_int(&subiter); + else if (bson_iterator_type(&subiter) == BSON_LONG) + (*j)[key] = (Json::Value::Int64)bson_iterator_long(&subiter); + else if (bson_iterator_type(&subiter) == BSON_ARRAY) + { + bson_iterator arrayiter; + bson_iterator_subiterator(&subiter, &arrayiter); + while (bson_iterator_next(&arrayiter)) + { + if (bson_iterator_type(&arrayiter) == BSON_OBJECT && !strcmp(bson_iterator_key(&arrayiter), "part")) + { + Json::Value tempPart; + ConvertBsonToJson(&arrayiter, &tempPart); + (*j)["links"].append(tempPart); + } + else if (bson_iterator_type(&arrayiter) == BSON_INT && !strcmp(bson_iterator_key(&arrayiter), "saveID")) + { + (*j)["links"].append(bson_iterator_int(&arrayiter)); + } + } + } + } +} + +std::set GetNestedSaveIDs(Json::Value j) +{ + Json::Value::Members members = j.getMemberNames(); + std::set saveIDs = std::set(); + for (Json::Value::Members::iterator iter = members.begin(), end = members.end(); iter != end; ++iter) + { + std::string member = *iter; + if (member == "id") + saveIDs.insert(j[member].asInt()); + else if (j[member].isArray()) + { + for (Json::Value::ArrayIndex i = 0; i < j[member].size(); i++) + { + // only supports objects here because that is all we need + if (!j[member][i].isObject()) + continue; + std::set nestedSaveIDs = GetNestedSaveIDs(j[member][i]); + saveIDs.insert(nestedSaveIDs.begin(), nestedSaveIDs.end()); + } + } + } + return saveIDs; +} + // converts a json object to bson -void GameSave::ConvertJsonToBson(bson *b, Json::Value j) +void GameSave::ConvertJsonToBson(bson *b, Json::Value j, int depth) { Json::Value::Members members = j.getMemberNames(); for (Json::Value::Members::iterator iter = members.begin(), end = members.end(); iter != end; ++iter) @@ -2395,14 +2424,27 @@ void GameSave::ConvertJsonToBson(bson *b, Json::Value j) else if (j[member].isArray()) { bson_append_start_array(b, member.c_str()); + std::set saveIDs = std::set(); for (Json::Value::ArrayIndex i = 0; i < j[member].size(); i++) { // only supports objects here because that is all we need if (!j[member][i].isObject()) continue; - bson_append_start_object(b, "part"); - ConvertJsonToBson(b, j[member][i]); - bson_append_finish_object(b); + if (depth > 4) + { + std::set nestedSaveIDs = GetNestedSaveIDs(j[member][i]); + saveIDs.insert(nestedSaveIDs.begin(), nestedSaveIDs.end()); + } + else + { + bson_append_start_object(b, "part"); + ConvertJsonToBson(b, j[member][i], depth+1); + bson_append_finish_object(b); + } + } + for (std::set::iterator iter = saveIDs.begin(), end = saveIDs.end(); iter != end; ++iter) + { + bson_append_int(b, "saveID", *iter); } bson_append_finish_array(b); } diff --git a/src/client/GameSave.h b/src/client/GameSave.h index be1fa23e44..670aa9fa04 100644 --- a/src/client/GameSave.h +++ b/src/client/GameSave.h @@ -116,7 +116,7 @@ class GameSave void readOPS(char * data, int dataLength); void readPSv(char * data, int dataLength); char * serialiseOPS(unsigned int & dataSize); - void ConvertJsonToBson(bson *b, Json::Value j); + void ConvertJsonToBson(bson *b, Json::Value j, int depth = 0); void ConvertBsonToJson(bson_iterator *b, Json::Value *j); }; diff --git a/src/gui/game/GameController.cpp b/src/gui/game/GameController.cpp index 29d9205266..fe1e91c54a 100644 --- a/src/gui/game/GameController.cpp +++ b/src/gui/game/GameController.cpp @@ -242,11 +242,14 @@ void GameController::HistoryRestore() if (historyPosition == history.size()) { Snapshot * newSnap = gameModel->GetSimulation()->CreateSnapshot(); + if (newSnap) + newSnap->Authors = Client::Ref().GetAuthorInfo(); delete gameModel->GetRedoHistory(); gameModel->SetRedoHistory(newSnap); } Snapshot * snap = history[newHistoryPosition]; gameModel->GetSimulation()->Restore(*snap); + Client::Ref().OverwriteAuthorInfo(snap->Authors); gameModel->SetHistory(history); gameModel->SetHistoryPosition(newHistoryPosition); } @@ -258,6 +261,7 @@ void GameController::HistorySnapshot() Snapshot * newSnap = gameModel->GetSimulation()->CreateSnapshot(); if (newSnap) { + newSnap->Authors = Client::Ref().GetAuthorInfo(); while (historyPosition < history.size()) { Snapshot * snap = history.back(); @@ -295,6 +299,7 @@ void GameController::HistoryForward() if (!snap) return; gameModel->GetSimulation()->Restore(*snap); + Client::Ref().OverwriteAuthorInfo(snap->Authors); gameModel->SetHistoryPosition(newHistoryPosition); } diff --git a/src/gui/game/GameModel.cpp b/src/gui/game/GameModel.cpp index b7b7f06468..8d3fa5c3bb 100644 --- a/src/gui/game/GameModel.cpp +++ b/src/gui/game/GameModel.cpp @@ -659,7 +659,7 @@ void GameModel::SetSave(SaveInfo * newSave) saveData->authors["username"] = newSave->userName; saveData->authors["title"] = newSave->name; saveData->authors["description"] = newSave->Description; - saveData->authors["published"] = newSave->Published; + saveData->authors["published"] = (int)newSave->Published; saveData->authors["date"] = newSave->updatedDate; } // This save was probably just created, and we didn't know the ID when creating it diff --git a/src/gui/game/GameView.cpp b/src/gui/game/GameView.cpp index c2fe1e4b44..81e62c64ae 100644 --- a/src/gui/game/GameView.cpp +++ b/src/gui/game/GameView.cpp @@ -1492,7 +1492,7 @@ void GameView::OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool case 'a': if (ctrl) { - std::string authorString = Client::Ref().GetAuthorString(); + std::string authorString = Client::Ref().GetAuthorInfo().toStyledString(); new InformationMessage("Save authorship info", authorString, true); } break; diff --git a/src/gui/save/ServerSaveActivity.cpp b/src/gui/save/ServerSaveActivity.cpp index 50a6dc8244..49d1ffbe36 100644 --- a/src/gui/save/ServerSaveActivity.cpp +++ b/src/gui/save/ServerSaveActivity.cpp @@ -266,7 +266,7 @@ void ServerSaveActivity::AddAuthorInfo() serverSaveInfo["username"] = Client::Ref().GetAuthUser().Username; serverSaveInfo["title"] = save.GetName(); serverSaveInfo["description"] = save.GetDescription(); - serverSaveInfo["published"] = save.GetPublished(); + serverSaveInfo["published"] = (int)save.GetPublished(); serverSaveInfo["date"] = (Json::Value::UInt64)time(NULL); Client::Ref().SaveAuthorInfo(&serverSaveInfo); save.GetGameSave()->authors = serverSaveInfo; diff --git a/src/simulation/Snapshot.h b/src/simulation/Snapshot.h index 468b21a9be..b40e43ce0e 100644 --- a/src/simulation/Snapshot.h +++ b/src/simulation/Snapshot.h @@ -3,6 +3,7 @@ #include #include "Particle.h" +#include "json/json.h" class Snapshot { @@ -30,6 +31,8 @@ class Snapshot std::vector WirelessData; std::vector stickmen; std::vector signs; + + Json::Value Authors; Snapshot() : AirPressure(),