Exemple #1
0
    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 T PerformWithSettings <T>(Func <JsonSerializerSettings, T> func)
    {
        JsonSerializerSettings settings;

        bool recursive = false;

        if (currentJsonSettings.Value != null)
        {
            // This is a recursive call
            recursive = true;
            settings  = currentJsonSettings.Value;

            settings.TraceWriter?.Trace(TraceLevel.Info, "Entering recursive object", null);
        }
        else
        {
            settings = CreateSettings();
            currentJsonSettings.Value = settings;
        }

        try
        {
            return(func(settings));
        }
        catch (Exception e)
        {
            // Don't do our special automatic debug enabling if debug writing is already on
            if (JSONDebug.ErrorHasOccurred || settings.TraceWriter != null)
            {
                throw;
            }

            JSONDebug.ErrorHasOccurred = true;

            if (Settings.Instance.JSONDebugMode == JSONDebug.DebugMode.Automatic)
            {
                GD.Print("JSON error happened, retrying with debug printing (mode is automatic), first exception: ",
                         e);

                currentJsonSettings.Value = null;
                PerformWithSettings(func);

                // If we get here, we didn't get another exception...
                // So we could maybe re-throw the first exception so that we fail like we should
                GD.PrintErr(
                    "Expected an exception for the second try at JSON operation, but it succeeded, " +
                    "re-throwing the original exception");
                throw;
            }
            else
            {
                throw;
            }
        }
        finally
        {
            if (!recursive)
            {
                currentJsonSettings.Value = null;

                if (settings.TraceWriter != null)
                {
                    JSONDebug.OnTraceFinished(settings.TraceWriter);

                    // This shouldn't get reused so no point in creating a new instance here
                    settings.TraceWriter = null;
                }
            }
            else
            {
                settings.TraceWriter?.Trace(TraceLevel.Info, "Exited recursive object", null);
            }
        }
    }
Exemple #3
0
    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);
    }