private void Step() { switch (state) { case State.Initial: state = State.ReadingData; // Invalid is given as the target state here, because it's unknown yet. // TODO: See #1847 LoadingScreen.Instance.Show(TranslationServer.Translate("LOADING_GAME"), MainGameState.Invalid, TranslationServer.Translate("READING_SAVE_DATA")); // Let all suppressed deletions happen TemporaryLoadedNodeDeleter.Instance.ReleaseAllHolds(); JSONDebug.FlushJSONTracesOut(); break; case State.ReadingData: { // Start suppressing loaded node deletion TemporaryLoadedNodeDeleter.Instance.AddDeletionHold(Constants.DELETION_HOLD_LOAD); // TODO: do this in a background thread if possible try { // Invalid is given as the target state here, because it's unknown yet. // TODO: See #1847 save = Save.LoadFromFile(saveName, () => Invoke.Instance.Perform(() => LoadingScreen.Instance.Show(TranslationServer.Translate("LOADING_GAME"), MainGameState.Invalid, TranslationServer.Translate("CREATING_OBJECTS_FROM_SAVE")))); state = State.CreatingScene; } catch (Exception e) { var extraProblem = TryFreeAlreadyLoadedData(); ReportStatus(false, TranslationServer.Translate("EXCEPTION_HAPPENED_WHILE_LOADING"), e + extraProblem); state = State.Finished; // ReSharper disable HeuristicUnreachableCode ConditionIsAlwaysTrueOrFalse if (!Constants.CATCH_SAVE_ERRORS) #pragma warning disable 162 { throw; } #pragma warning restore 162 // ReSharper restore HeuristicUnreachableCode ConditionIsAlwaysTrueOrFalse } break; } case State.CreatingScene: { try { loadedState = save !.TargetScene ?? throw new Exception("Save has no target scene"); } catch (Exception) { var extraProblem = TryFreeAlreadyLoadedData(); ReportStatus(false, TranslationServer.Translate("SAVE_IS_INVALID"), TranslationServer.Translate("SAVE_HAS_INVALID_GAME_STATE") + extraProblem); state = State.Finished; break; } state = State.ProcessingLoadedObjects; break; } case State.ProcessingLoadedObjects: { LoadingScreen.Instance.Show(TranslationServer.Translate("LOADING_GAME"), save !.GameState, TranslationServer.Translate("PROCESSING_LOADED_OBJECTS")); if (loadedState !.IsLoadedFromSave != true) { throw new Exception("Game load logic not working correctly, IsLoadedFromSave was not set"); } try { SceneManager.Instance.SwitchToScene(loadedState.GameStateRoot); loadedState.OnFinishLoading(save); } catch (Exception e) { var extraProblem = TryFreeAlreadyLoadedData(); ReportStatus(false, TranslationServer.Translate("EXCEPTION_HAPPENED_PROCESSING_SAVE"), e + extraProblem); state = State.Finished; break; } ReportStatus(true, TranslationServer.Translate("LOAD_FINISHED"), string.Empty); state = State.Finished; break; } case State.Finished: { stopwatch.Stop(); GD.Print("load finished, success: ", success, " message: ", message, " elapsed: ", stopwatch.Elapsed); // Stop suppressing loaded node deletion TemporaryLoadedNodeDeleter.Instance.RemoveDeletionHold(Constants.DELETION_HOLD_LOAD); JSONDebug.FlushJSONTracesOut(); if (success) { LoadingScreen.Instance.Hide(); SaveStatusOverlay.Instance.ShowMessage(message); // TODO: does this cause problems if the game was paused when saving? loadedState !.GameStateRoot.GetTree().Paused = false; } else { SaveStatusOverlay.Instance.ShowError(TranslationServer.Translate("ERROR_LOADING"), message, exception, true, () => LoadingScreen.Instance.Hide()); } IsLoading = false; SaveHelper.MarkLastSaveToCurrentTime(); return; } default: throw new InvalidOperationException(); } Invoke.Instance.Queue(Step); }
private void Step() { switch (state) { case State.Initial: // On this frame a pause menu might still be open, wait until next frame for it to close before // taking a screenshot wasColourblindScreenFilterVisible = ColourblindScreenFilter.Instance.Visible; if (wasColourblindScreenFilterVisible) { ColourblindScreenFilter.Instance.Hide(); } state = State.Screenshot; break; case State.Screenshot: { save = createSaveData.Invoke(this); if (wasColourblindScreenFilterVisible) { ColourblindScreenFilter.Instance.Show(); } SaveStatusOverlay.Instance.ShowMessage(TranslationServer.Translate("SAVING_DOT_DOT_DOT"), Mathf.Inf); state = State.SaveData; JSONDebug.FlushJSONTracesOut(); break; } case State.SaveData: { save!.Name = saveNameTask.Result; GD.Print("Creating a save with name: ", save.Name); performSave.Invoke(this, save); state = State.Finished; break; } case State.Finished: { stopwatch.Stop(); GD.Print("save finished, success: ", success, " message: ", message, " elapsed: ", stopwatch.Elapsed); JSONDebug.FlushJSONTracesOut(); if (success) { SaveStatusOverlay.Instance.ShowMessage(message); currentGameRoot.Invoke().GetTree().Paused = returnToPauseState; } else { SaveStatusOverlay.Instance.ShowMessage(TranslationServer.Translate("SAVE_FAILED")); SaveStatusOverlay.Instance.ShowError(TranslationServer.Translate("ERROR_SAVING"), message, exceptionOrFailureMessage, false, null, exceptionOrMessageIsException); } IsSaving = false; SaveHelper.MarkLastSaveToCurrentTime(); return; } default: throw new InvalidOperationException(); } Invoke.Instance.Queue(Step); }