mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-09-02 12:32:40 +02:00
Fix crash when navigating away from a save while voting on it
By tying the lifetimes of the vote request and the queued vote to the online save info. Broken since c73fa1bcdd
, where the vote request was made non-blocking. TODO: Let the user know that their vote may not have gone through if the vote request gets destroyed abnormally.
This commit is contained in:
@@ -556,33 +556,33 @@ void GameModel::SetUndoHistoryLimit(unsigned int undoHistoryLimit_)
|
|||||||
|
|
||||||
void GameModel::SetVote(int direction)
|
void GameModel::SetVote(int direction)
|
||||||
{
|
{
|
||||||
queuedVote = direction;
|
currentSave.queuedVote = direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameModel::Tick()
|
void GameModel::Tick()
|
||||||
{
|
{
|
||||||
if (execVoteRequest && execVoteRequest->CheckDone())
|
if (currentSave.execVoteRequest && currentSave.execVoteRequest->CheckDone())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
execVoteRequest->Finish();
|
currentSave.execVoteRequest->Finish();
|
||||||
currentSave->vote = execVoteRequest->Direction();
|
currentSave.saveInfo->vote = currentSave.execVoteRequest->Direction();
|
||||||
notifySaveChanged();
|
notifySaveChanged();
|
||||||
}
|
}
|
||||||
catch (const http::RequestError &ex)
|
catch (const http::RequestError &ex)
|
||||||
{
|
{
|
||||||
new ErrorMessage("Error while voting", ByteString(ex.what()).FromUtf8());
|
new ErrorMessage("Error while voting", ByteString(ex.what()).FromUtf8());
|
||||||
}
|
}
|
||||||
execVoteRequest.reset();
|
currentSave.execVoteRequest.reset();
|
||||||
}
|
}
|
||||||
if (!execVoteRequest && queuedVote)
|
if (!currentSave.execVoteRequest && currentSave.queuedVote)
|
||||||
{
|
{
|
||||||
if (currentSave)
|
if (currentSave.saveInfo)
|
||||||
{
|
{
|
||||||
execVoteRequest = std::make_unique<http::ExecVoteRequest>(currentSave->GetID(), *queuedVote);
|
currentSave.execVoteRequest = std::make_unique<http::ExecVoteRequest>(currentSave.saveInfo->GetID(), *currentSave.queuedVote);
|
||||||
execVoteRequest->Start();
|
currentSave.execVoteRequest->Start();
|
||||||
}
|
}
|
||||||
queuedVote.reset();
|
currentSave.queuedVote.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -717,13 +717,15 @@ std::vector<Menu *> GameModel::GetMenuList()
|
|||||||
|
|
||||||
SaveInfo *GameModel::GetSave() // non-owning
|
SaveInfo *GameModel::GetSave() // non-owning
|
||||||
{
|
{
|
||||||
return currentSave.get();
|
return currentSave.saveInfo.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<SaveInfo> GameModel::TakeSave()
|
std::unique_ptr<SaveInfo> GameModel::TakeSave()
|
||||||
{
|
{
|
||||||
// we don't notify listeners because we'll get a new save soon anyway
|
// we don't notify listeners because we'll get a new save soon anyway
|
||||||
return std::move(currentSave);
|
SaveInfoWrapper empty;
|
||||||
|
std::swap(empty, currentSave);
|
||||||
|
return std::move(empty.saveInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameModel::SaveToSimParameters(const GameSave &saveData)
|
void GameModel::SaveToSimParameters(const GameSave &saveData)
|
||||||
@@ -753,12 +755,12 @@ void GameModel::SaveToSimParameters(const GameSave &saveData)
|
|||||||
|
|
||||||
void GameModel::SetSave(std::unique_ptr<SaveInfo> newSave, bool invertIncludePressure)
|
void GameModel::SetSave(std::unique_ptr<SaveInfo> newSave, bool invertIncludePressure)
|
||||||
{
|
{
|
||||||
currentSave = std::move(newSave);
|
currentSave = { std::move(newSave) };
|
||||||
currentFile.reset();
|
currentFile.reset();
|
||||||
|
|
||||||
if (currentSave && currentSave->GetGameSave())
|
if (currentSave.saveInfo && currentSave.saveInfo->GetGameSave())
|
||||||
{
|
{
|
||||||
auto *saveData = currentSave->GetGameSave();
|
auto *saveData = currentSave.saveInfo->GetGameSave();
|
||||||
SaveToSimParameters(*saveData);
|
SaveToSimParameters(*saveData);
|
||||||
sim->clear_sim();
|
sim->clear_sim();
|
||||||
view->PauseRendererThread();
|
view->PauseRendererThread();
|
||||||
@@ -768,23 +770,23 @@ void GameModel::SetSave(std::unique_ptr<SaveInfo> newSave, bool invertIncludePre
|
|||||||
// Add in the correct info
|
// Add in the correct info
|
||||||
if (saveData->authors.size() == 0)
|
if (saveData->authors.size() == 0)
|
||||||
{
|
{
|
||||||
auto gameSave = currentSave->TakeGameSave();
|
auto gameSave = currentSave.saveInfo->TakeGameSave();
|
||||||
gameSave->authors["type"] = "save";
|
gameSave->authors["type"] = "save";
|
||||||
gameSave->authors["id"] = currentSave->id;
|
gameSave->authors["id"] = currentSave.saveInfo->id;
|
||||||
gameSave->authors["username"] = currentSave->userName;
|
gameSave->authors["username"] = currentSave.saveInfo->userName;
|
||||||
gameSave->authors["title"] = currentSave->name.ToUtf8();
|
gameSave->authors["title"] = currentSave.saveInfo->name.ToUtf8();
|
||||||
gameSave->authors["description"] = currentSave->Description.ToUtf8();
|
gameSave->authors["description"] = currentSave.saveInfo->Description.ToUtf8();
|
||||||
gameSave->authors["published"] = (int)currentSave->Published;
|
gameSave->authors["published"] = (int)currentSave.saveInfo->Published;
|
||||||
gameSave->authors["date"] = (Json::Value::UInt64)currentSave->updatedDate;
|
gameSave->authors["date"] = (Json::Value::UInt64)currentSave.saveInfo->updatedDate;
|
||||||
currentSave->SetGameSave(std::move(gameSave));
|
currentSave.saveInfo->SetGameSave(std::move(gameSave));
|
||||||
}
|
}
|
||||||
// This save was probably just created, and we didn't know the ID when creating it
|
// This save was probably just created, and we didn't know the ID when creating it
|
||||||
// Update with the proper ID
|
// Update with the proper ID
|
||||||
else if (saveData->authors.get("id", -1) == 0 || saveData->authors.get("id", -1) == -1)
|
else if (saveData->authors.get("id", -1) == 0 || saveData->authors.get("id", -1) == -1)
|
||||||
{
|
{
|
||||||
auto gameSave = currentSave->TakeGameSave();
|
auto gameSave = currentSave.saveInfo->TakeGameSave();
|
||||||
gameSave->authors["id"] = currentSave->id;
|
gameSave->authors["id"] = currentSave.saveInfo->id;
|
||||||
currentSave->SetGameSave(std::move(gameSave));
|
currentSave.saveInfo->SetGameSave(std::move(gameSave));
|
||||||
}
|
}
|
||||||
Client::Ref().OverwriteAuthorInfo(saveData->authors);
|
Client::Ref().OverwriteAuthorInfo(saveData->authors);
|
||||||
}
|
}
|
||||||
@@ -806,7 +808,7 @@ std::unique_ptr<SaveFile> GameModel::TakeSaveFile()
|
|||||||
void GameModel::SetSaveFile(std::unique_ptr<SaveFile> newSave, bool invertIncludePressure)
|
void GameModel::SetSaveFile(std::unique_ptr<SaveFile> newSave, bool invertIncludePressure)
|
||||||
{
|
{
|
||||||
currentFile = std::move(newSave);
|
currentFile = std::move(newSave);
|
||||||
currentSave.reset();
|
currentSave = {};
|
||||||
|
|
||||||
if (currentFile && currentFile->GetGameSave())
|
if (currentFile && currentFile->GetGameSave())
|
||||||
{
|
{
|
||||||
|
@@ -51,7 +51,6 @@ struct HistoryEntry
|
|||||||
|
|
||||||
class GameModel
|
class GameModel
|
||||||
{
|
{
|
||||||
std::unique_ptr<http::ExecVoteRequest> execVoteRequest;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Notification*> notifications;
|
std::vector<Notification*> notifications;
|
||||||
@@ -74,7 +73,13 @@ private:
|
|||||||
int activeMenu;
|
int activeMenu;
|
||||||
int currentBrush;
|
int currentBrush;
|
||||||
std::vector<std::unique_ptr<Brush>> brushList;
|
std::vector<std::unique_ptr<Brush>> brushList;
|
||||||
std::unique_ptr<SaveInfo> currentSave;
|
struct SaveInfoWrapper
|
||||||
|
{
|
||||||
|
std::unique_ptr<SaveInfo> saveInfo;
|
||||||
|
std::optional<int> queuedVote;
|
||||||
|
std::unique_ptr<http::ExecVoteRequest> execVoteRequest;
|
||||||
|
};
|
||||||
|
SaveInfoWrapper currentSave;
|
||||||
std::unique_ptr<SaveFile> currentFile;
|
std::unique_ptr<SaveFile> currentFile;
|
||||||
Tool *lastTool = nullptr;
|
Tool *lastTool = nullptr;
|
||||||
Tool **activeTools = nullptr;
|
Tool **activeTools = nullptr;
|
||||||
@@ -130,7 +135,6 @@ private:
|
|||||||
|
|
||||||
void SaveToSimParameters(const GameSave &saveData);
|
void SaveToSimParameters(const GameSave &saveData);
|
||||||
|
|
||||||
std::optional<int> queuedVote;
|
|
||||||
bool threadedRendering = false;
|
bool threadedRendering = false;
|
||||||
|
|
||||||
GameView *view;
|
GameView *view;
|
||||||
|
Reference in New Issue
Block a user