Beispiel #1
0
        [MonoModOriginalName("orig_ctor_Celeste")] // For Everest.Installer
        public void ctor()
        {
            // Everest.Flags aren't initialized this early.
            if (Environment.GetEnvironmentVariable("EVEREST_HEADLESS") == "1")
            {
                Instance = this;
                Version  = new Version(0, 0, 0, 0);
                Console.WriteLine("CELESTE HEADLESS VIA EVEREST");
            }
            else
            {
                orig_ctor_Celeste();
            }
            try {
                Everest.Boot();
            } catch (Exception e) {
                e.LogDetailed();

                /*
                 * ErrorLog.Write(e);
                 * ErrorLog.Open();
                 */
                throw;
            }
        }
Beispiel #2
0
        private void onBackPressed(Overworld overworld)
        {
            if (blacklistedModsOriginal.SetEquals(blacklistedMods))
            {
                // nothing changed, go back to Mod Options
                overworld.Goto <OuiModOptions>();
            }
            else
            {
                // save the blacklist
                using (StreamWriter blacklistTxt = File.CreateText(Everest.Loader.PathBlacklist)) {
                    // header
                    blacklistTxt.WriteLine("# This is the blacklist. Lines starting with # are ignored.");
                    blacklistTxt.WriteLine("# File generated through the \"Toggle Mods\" menu in Mod Options");
                    blacklistTxt.WriteLine("");

                    // write all mods, commenting out the ones we want unblacklisted.
                    foreach (string mod in allMods)
                    {
                        blacklistTxt.WriteLine(blacklistedMods.Contains(mod) ? mod : $"# {mod}");
                    }
                }

                // restart the game
                Everest.QuickFullRestart();
            }
        }
Beispiel #3
0
        public override void Update()
        {
            // handle pressing Confirm to install a new Everest version
            if (everestVersionToInstall != null)
            {
                if (Input.MenuConfirm.Pressed && Focused)
                {
                    Everest.Updater.Update(OuiModOptions.Instance.Overworld.Goto <OuiLoggedProgress>(), everestVersionToInstall);
                }
            }
            // handle pressing the Back key
            else if (task != null && !shouldAutoExit && (task.IsCompleted || task.IsCanceled || task.IsFaulted) && Input.MenuCancel.Pressed && Focused)
            {
                if (shouldRestart)
                {
                    Everest.QuickFullRestart();
                }
                else
                {
                    Exit();
                }
            }

            base.Update();
        }
Beispiel #4
0
        public override void Update()
        {
            base.Update();

            // check if Confirm is pressed to restart or proceed to the title screen.
            if (Input.MenuConfirm.Pressed)
            {
                if (confirmToRestart)
                {
                    Everest.QuickFullRestart();
                    confirmToRestart = false; // better safe than sorry
                }

                if (confirmToContinue)
                {
                    shouldContinue = true;
                }
            }

            // if Back is pressed, we should cancel the update.
            if (Input.MenuCancel.Pressed && showCancel)
            {
                skipUpdate         = true;
                modUpdatingMessage = Dialog.Clean("AUTOUPDATECHECKER_SKIPPING");
            }
        }
Beispiel #5
0
        public void ctor()
        {
            if (Environment.GetEnvironmentVariable("EVEREST_HEADLESS") == "1")
            {
                Instance = this;
                Version  = new Version(0, 0, 0, 0);
                Console.WriteLine("CELESTE HEADLESS VIA EVEREST");
            }
            else
            {
                orig_ctor();
            }
            try {
                Everest.Boot();
            } catch (Exception e) {
                if (e is OutOfMemoryException && CoreModule.Instance?._Settings != null)
                {
                    CoreModule.Settings.LazyLoading = true;
                    CoreModule.Instance.SaveSettings();
                }

                e.LogDetailed();

                /*
                 * ErrorLog.Write(e);
                 * ErrorLog.Open();
                 */
                throw;
            }
        }
Beispiel #6
0
        public static TextMenu CreateMenu(bool inGame, EventInstance snapshot)
        {
            TextMenu menu = new TextMenu();

            menu.Add(new TextMenuExt.HeaderImage("menu/everest")
            {
                ImageColor   = Color.White,
                ImageOutline = true,
                ImageScale   = 0.5f
            });
            menu.Add(new TextMenu.SubHeader($"v.{Everest.VersionString}"));

            Everest.InvokeTyped(
                "CreateModMenuSection",
                new Type[] { typeof(TextMenu), typeof(bool), typeof(EventInstance) },
                menu, inGame, snapshot
                );

            if (menu.Height > menu.ScrollableMinSize)
            {
                menu.Position.Y = menu.ScrollTargetY;
            }

            return(menu);
        }
Beispiel #7
0
 protected override void Initialize()
 {
     // Note: You may instinctually call base.Initialize();
     // DON'T! The original method is orig_Initialize
     orig_Initialize();
     Everest.Invoke("Initialize");
 }
Beispiel #8
0
        public void CreatePauseMenuButtons(Level level, TextMenu menu, bool minimal)
        {
            if (Everest.Flags.IsDisabled || !Settings.ShowModOptionsInGame)
            {
                return;
            }

            List <TextMenu.Item> items = menu.GetItems();
            int index;

            // Find the options button and place our button below it.
            string cleanedOptions = Dialog.Clean("menu_pause_options");

            index = items.FindIndex(_ => {
                TextMenu.Button other = (_ as TextMenu.Button);
                if (other == null)
                {
                    return(false);
                }
                return(other.Label == cleanedOptions);
            });
            if (index != -1)
            {
                index++;
            }
            // Otherwise, place it below the last button.
            else
            {
                index = items.Count;
            }

            TextMenu.Item itemModOptions = null;
            menu.Insert(index, itemModOptions = new TextMenu.Button(Dialog.Clean("menu_pause_modoptions")).Pressed(() => {
                int returnIndex = menu.IndexOf(itemModOptions);
                menu.RemoveSelf();

                level.PauseMainMenuOpen = false;
                level.Paused            = true;

                TextMenu options = OuiModOptions.CreateMenu(true, LevelExt.PauseSnapshot);

                options.OnESC = options.OnCancel = () => {
                    Audio.Play(Sfxs.ui_main_button_back);
                    options.CloseAndRun(Everest.SaveSettings(), () => level.Pause(returnIndex, minimal, false));
                };

                options.OnPause = () => {
                    Audio.Play(Sfxs.ui_main_button_back);
                    options.CloseAndRun(Everest.SaveSettings(), () => {
                        level.Paused       = false;
                        Engine.FreezeTimer = 0.15f;
                    });
                };

                level.Add(options);
            }));
        }
Beispiel #9
0
        protected override void LoadContent()
        {
            // Note: You may instinctually call base.LoadContent();
            // DON'T! The original method is orig_LoadContent
            bool firstLoad = this.firstLoad;

            orig_LoadContent();

            Everest.Invoke("LoadContent", firstLoad);
        }
 public void ctor_Celeste()
 {
     orig_ctor_Celeste();
     try {
         Everest.Boot();
     } catch (Exception e) {
         e.LogDetailed();
         throw;
     }
 }
Beispiel #11
0
        /// <summary>
        /// Verifies the downloaded mod's checksum, and throws an IOException if it doesn't match the database one.
        /// </summary>
        /// <param name="update">The mod info from the database</param>
        /// <param name="filePath">The path to the file to check</param>
        public static void VerifyChecksum(ModUpdateInfo update, string filePath)
        {
            string actualHash   = BitConverter.ToString(Everest.GetChecksum(filePath)).Replace("-", "").ToLowerInvariant();
            string expectedHash = update.xxHash[0];

            Logger.Log("ModUpdaterHelper", $"Verifying checksum: actual hash is {actualHash}, expected hash is {expectedHash}");
            if (expectedHash != actualHash)
            {
                throw new IOException($"Checksum error: expected {expectedHash}, got {actualHash}");
            }
        }
Beispiel #12
0
        public override void Initialize()
        {
            // F5: Reload and restart the current screen.
            Engine.Commands.FunctionKeyActions[4] = () => {
                // CTRL + F5: Quick-restart the entire game.
                if (MInput.Keyboard.Check(Keys.LeftControl) ||
                    MInput.Keyboard.Check(Keys.RightControl))
                {
                    // block restarting while the game is starting up. this might lead to crashes
                    if (!(Engine.Scene is GameLoader))
                    {
                        Everest.QuickFullRestart();
                    }

                    return;
                }

                Level level = Engine.Scene as Level;
                if (level == null)
                {
                    return;
                }

                AssetReloadHelper.Do(Dialog.Clean("ASSETRELOADHELPER_RELOADINGMAP"), () => {
                    AreaData.Areas[level.Session.Area.ID].Mode[(int)level.Session.Area.Mode].MapData.Reload();
                });
                AssetReloadHelper.ReloadLevel();
            };

            // F6: Open map editor for current level.
            Engine.Commands.FunctionKeyActions[5] = () => {
                Level level = Engine.Scene as Level;
                if (level == null)
                {
                    return;
                }
                Engine.Scene         = new MapEditor(level.Session.Area);
                Engine.Commands.Open = false;
            };

            // Set up the touch input regions.
            TouchRegion touchTitleScreen = new TouchRegion {
                Position  = new Vector2(1920f, 1080f) * 0.5f,
                Size      = new Vector2(1920f, 1080f),
                Condition = _ =>
                            ((Engine.Scene as Overworld)?.IsCurrent <OuiTitleScreen>() ?? false) ||
                            (Engine.Scene is GameLoader)
                ,
                Button = Input.MenuConfirm
            };
        }
Beispiel #13
0
        private static void MainInner(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;

            try {
                Everest.ParseArgs(args);
                orig_Main(args);
            } catch (Exception e) {
                CriticalFailureHandler(e);
                return;
            } finally {
                Instance?.Dispose();
            }

            Everest.Shutdown();
        }
Beispiel #14
0
        protected override void LoadContent()
        {
            // Note: You may instinctually call base.LoadContent();
            // DON'T! The original method is orig_LoadContent
            bool firstLoad = this.firstLoad;

            orig_LoadContent();

            if (firstLoad)
            {
                SubHudRenderer.Buffer = VirtualContent.CreateRenderTarget("subhud-target", 1922, 1082);
            }

            Everest.Invoke("LoadContent");
            Everest.Invoke("LoadContent", firstLoad);
        }
Beispiel #15
0
        public new void BeforeSave()
        {
            // If we're in a Vanilla-compatible area, copy from _Safe (new) to _Unsafe (legacy).
            if (LastArea_Safe.GetLevelSet() == "Celeste")
            {
                LastArea_Unsafe = LastArea_Safe;
            }
            if (CurrentSession_Safe != null && CurrentSession_Safe.Area.GetLevelSet() == "Celeste")
            {
                CurrentSession_Unsafe = CurrentSession_Safe;
            }

            orig_BeforeSave();

            Everest.Invoke("SaveSaveData", FileSlot);
        }
Beispiel #16
0
        public override void Update()
        {
            // handle pressing the Back key
            if (task != null && !shouldAutoExit && (task.IsCompleted || task.IsCanceled || task.IsFaulted) && Input.MenuCancel.Pressed)
            {
                if (shouldRestart)
                {
                    Everest.QuickFullRestart();
                }
                else
                {
                    Exit();
                }
            }

            base.Update();
        }
Beispiel #17
0
        public override IEnumerator Leave(Oui next)
        {
            Audio.Play("event:/ui/main/whoosh_large_out");
            menu.Focused = false;

            yield return(Everest.SaveSettings());

            for (float p = 0f; p < 1f; p += Engine.DeltaTime * 4f)
            {
                menu.X = onScreenX + 1920f * Ease.CubeIn(p);
                alpha  = 1f - Ease.CubeIn(p);
                yield return(null);
            }

            menu.Visible = Visible = false;
            menu.RemoveSelf();
            menu = null;
        }
Beispiel #18
0
        public override void Initialize()
        {
            // F5: Reload and restart the current screen.
            Engine.Commands.FunctionKeyActions[4] = () => {
                // CTRL + F5: Quick-restart the entire game.
                if (MInput.Keyboard.Check(Keys.LeftControl) ||
                    MInput.Keyboard.Check(Keys.RightControl))
                {
                    Everest.QuickFullRestart();
                    return;
                }

                Level level = Engine.Scene as Level;
                if (level == null)
                {
                    return;
                }

                AreaData.Areas[level.Session.Area.ID].Mode[(int)level.Session.Area.Mode].MapData.Reload();
                Engine.Scene = new LevelLoader(level.Session, level.Session.RespawnPoint);
            };

            // F6: Open map editor for current level.
            Engine.Commands.FunctionKeyActions[5] = () => {
                Level level = Engine.Scene as Level;
                if (level == null)
                {
                    return;
                }
                Engine.Scene         = new MapEditor(level.Session.Area);
                Engine.Commands.Open = false;
            };

            // Set up the touch input regions.
            TouchRegion touchTitleScreen = new TouchRegion {
                Position  = new Vector2(1920f, 1080f) * 0.5f,
                Size      = new Vector2(1920f, 1080f),
                Condition = _ =>
                            ((Engine.Scene as Overworld)?.IsCurrent <OuiTitleScreen>() ?? false) ||
                            (Engine.Scene is GameLoader)
                ,
                Button = Input.MenuConfirm
            };
        }
Beispiel #19
0
        public override void Update()
        {
            base.Update();

            // check if Confirm is pressed to restart or proceed to the title screen.
            if (Input.MenuConfirm.Pressed)
            {
                if (confirmToRestart)
                {
                    Everest.QuickFullRestart();
                    confirmToRestart = false; // better safe than sorry
                }

                if (confirmToContinue)
                {
                    shouldContinue = true;
                }
            }
        }
Beispiel #20
0
        public static TextMenu CreateMenu(bool inGame, EventInstance snapshot)
        {
            TextMenu menu = new TextMenu();

            menu.Add(new TextMenu.Header(Dialog.Clean("modoptions_title")));
            menu.Add(new TextMenu.SubHeader($"v.{Everest.VersionString}"));

            Everest.InvokeTyped(
                "CreateModMenuSection",
                new Type[] { typeof(TextMenu), typeof(bool), typeof(EventInstance) },
                menu, inGame, snapshot
                );

            if (menu.Height > menu.ScrollableMinSize)
            {
                menu.Position.Y = menu.ScrollTargetY;
            }

            return(menu);
        }
Beispiel #21
0
        public static void CriticalFailureHandler(Exception e)
        {
            Everest.LogDetours();

            (e ?? new Exception("Unknown exception")).LogDetailed("CRITICAL");

            ErrorLog.Write(
                @"Yo, I heard you like Everest so I put Everest in your Everest so you can Ever Rest while you Ever Rest.

In other words: Celeste has encountered a catastrophic failure.

IF YOU WANT TO HELP US FIX THIS:
Please join the Celeste Discord server and drag and drop your log.txt into #modding_help.
https://discord.gg/6qjaePQ");

            ErrorLog.Open();
            if (!_CriticalFailureIsUnhandledException)
            {
                Environment.Exit(-1);
            }
        }
Beispiel #22
0
        public override void Update()
        {
            // handle pressing the Back key
            if (task != null && !shouldAutoRestart && (task.IsCompleted || task.IsCanceled || task.IsFaulted) && Input.MenuCancel.Pressed)
            {
                if (shouldRestart)
                {
                    Everest.QuickFullRestart();
                }
                else
                {
                    // go back to mod options instead
                    task = null;
                    Lines.Clear();
                    Audio.Play(SFX.ui_main_button_back);
                    Overworld.Goto <OuiModOptions>();
                }
            }

            base.Update();
        }
        public static void Main(string[] args)
        {
            if (File.Exists("log.txt"))
            {
                File.Delete("log.txt");
            }
            using (Stream fileStream = File.OpenWrite("log.txt"))
                using (StreamWriter fileWriter = new StreamWriter(fileStream, Console.OutputEncoding))
                    using (LogWriter logWriter = new LogWriter {
                        STDOUT = Console.Out,
                        File = fileWriter
                    }) {
                        Console.SetOut(logWriter);

                        Everest.ParseArgs(args);
                        orig_Main(args);

                        Console.SetOut(logWriter.STDOUT);
                        logWriter.STDOUT = null;
                    }
        }
Beispiel #24
0
        public override IEnumerator Leave(Oui next)
        {
            Audio.Play(SFX.ui_main_whoosh_large_out);
            menu.Focused = false;

            // save the menu position in case we want to restore it.
            savedMenuIndex = menu.Selection;

            yield return(Everest.SaveSettings());

            for (float p = 0f; p < 1f; p += Engine.DeltaTime * 4f)
            {
                menu.X = onScreenX + 1920f * Ease.CubeIn(p);
                alpha  = 1f - Ease.CubeIn(p);
                yield return(null);
            }

            menu.Visible = Visible = false;
            menu.RemoveSelf();
            menu = null;
        }
Beispiel #25
0
        public override void Initialize()
        {
            // F5: Reload and restart the current screen.
            Engine.Commands.FunctionKeyActions[4] = () => {
                // CTRL + F5: Quick-restart the entire game.
                if (MInput.Keyboard.Check(Keys.LeftControl) ||
                    MInput.Keyboard.Check(Keys.RightControl))
                {
                    // block restarting while the game is starting up. this might lead to crashes
                    if (!(Engine.Scene is GameLoader))
                    {
                        Everest.QuickFullRestart();
                    }

                    return;
                }

                if (!(Engine.Scene is Level level))
                {
                    return;
                }

                AssetReloadHelper.Do(Dialog.Clean("ASSETRELOADHELPER_RELOADINGMAP"), () => {
                    AreaData.Areas[level.Session.Area.ID].Mode[(int)level.Session.Area.Mode].MapData.Reload();
                });
                AssetReloadHelper.ReloadLevel();
            };

            // F6: Open map editor for current level.
            Engine.Commands.FunctionKeyActions[5] = () => {
                if (!(Engine.Scene is Level level))
                {
                    return;
                }
                Engine.Scene         = new MapEditor(level.Session.Area);
                Engine.Commands.Open = false;
            };
        }
Beispiel #26
0
        [MonoModOriginalName("orig_ctor_Celeste")] // For Everest.Installer
        public void ctor()
        {
            if (Everest.Flags.IsHeadless)
            {
                Instance = this;
                Version  = new Version(0, 0, 0, 0);
                Console.WriteLine("CELESTE HEADLESS VIA EVEREST");
            }
            else
            {
                orig_ctor_Celeste();
            }
            try {
                Everest.Boot();
            } catch (Exception e) {
                e.LogDetailed();

                /*
                 * ErrorLog.Write(e);
                 * ErrorLog.Open();
                 */
                throw;
            }
        }
Beispiel #27
0
        public override IEnumerator Leave(Oui next)
        {
            Audio.Play(SFX.ui_main_whoosh_large_out);
            menu.Focused = false;

            if (fromModOptions)
            {
                Add(new Coroutine(FadeBgTo(0f)));
            }

            yield return(Everest.SaveSettings());

            for (float p = 0f; p < 1f; p += Engine.DeltaTime * 4f)
            {
                menu.X = onScreenX - 1920f * Ease.CubeIn(p);
                yield return(null);
            }

            menu.Visible = Visible = false;
            menu.RemoveSelf();
            menu = null;

            Overworld.Maddy.Hide();
        }
Beispiel #28
0
        public void CreatePauseMenuButtons(Level level, TextMenu menu, bool minimal)
        {
            if (Everest.Flags.IsDisabled || !Settings.ShowModOptionsInGame)
            {
                return;
            }

            List <TextMenu.Item> items = menu.GetItems();
            int index;

            // Find the options button and place our button below it.
            string cleanedOptions = Dialog.Clean("menu_pause_options");

            index = items.FindIndex(_ => {
                TextMenu.Button other = (_ as TextMenu.Button);
                if (other == null)
                {
                    return(false);
                }
                return(other.Label == cleanedOptions);
            });
            if (index != -1)
            {
                index++;
            }
            // Otherwise, place it below the last button.
            else
            {
                index = items.Count;
            }

            TextMenu.Item itemModOptions = null;
            menu.Insert(index, itemModOptions = new TextMenu.Button(Dialog.Clean("menu_pause_modoptions")).Pressed(() => {
                int returnIndex = menu.IndexOf(itemModOptions);
                menu.RemoveSelf();

                level.PauseMainMenuOpen = false;
                level.Paused            = true;

                TextMenu options = OuiModOptions.CreateMenu(true, LevelExt.PauseSnapshot);

                options.OnESC = options.OnCancel = () => {
                    Audio.Play(SFX.ui_main_button_back);
                    options.CloseAndRun(Everest.SaveSettings(), () => {
                        level.Pause(returnIndex, minimal, false);

                        // adjust the Mod Options menu position, in case it moved (pause menu entries added/removed after changing mod options).
                        TextMenu textMenu = level.Entities.GetToAdd().FirstOrDefault((Entity e) => e is TextMenu) as TextMenu;
                        TextMenu.Button modOptionsButton = textMenu?.GetItems().OfType <TextMenu.Button>()
                                                           .FirstOrDefault(button => button.Label == Dialog.Clean("menu_pause_modoptions"));
                        if (modOptionsButton != null)
                        {
                            textMenu.Selection = textMenu.IndexOf(modOptionsButton);
                        }
                    });
                };

                options.OnPause = () => {
                    Audio.Play(SFX.ui_main_button_back);
                    options.CloseAndRun(Everest.SaveSettings(), () => {
                        level.Paused       = false;
                        Engine.FreezeTimer = 0.15f;
                    });
                };

                level.Add(options);
            }));
        }
Beispiel #29
0
        public static void Main(string[] args)
        {
            if (Thread.CurrentThread.Name != "Main Thread")
            {
                Thread.CurrentThread.Name = "Main Thread";
            }

            if (File.Exists("BuildIsXNA.txt"))
            {
                File.Delete("BuildIsXNA.txt");
            }
            if (File.Exists("BuildIsFNA.txt"))
            {
                File.Delete("BuildIsFNA.txt");
            }
            File.WriteAllText($"BuildIs{(typeof(Game).Assembly.FullName.Contains("FNA") ? "FNA" : "XNA")}.txt", "");

            if (File.Exists("launch.txt"))
            {
                args =
                    File.ReadAllLines("launch.txt")
                    .Select(l => l.Trim())
                    .Where(l => !l.StartsWith("#"))
                    .SelectMany(l => l.Split(' '))
                    .Concat(args)
                    .ToArray();
            }
            else
            {
                using (StreamWriter writer = File.CreateText("launch.txt")) {
                    writer.WriteLine("# Add any Everest launch flags here. Lines starting with # are ignored.");
                    writer.WriteLine();
                    writer.WriteLine("# If you're having graphics issues with the FNA version on Windows,");
                    writer.WriteLine("# remove the # from the following line to enable using Direct3D.");
                    writer.WriteLine("#--d3d");
                    writer.WriteLine();
                    writer.WriteLine("# If you've got an Intel GPU, are using the FNA version on Windows and");
                    writer.WriteLine("# are 100% sure that you want to use Intel's possibly broken OpenGL drivers,");
                    writer.WriteLine("# remove the # from the following line to revert to using OpenGL.");
                    writer.WriteLine("#--no-d3d");
                    writer.WriteLine();
                }
            }

            if (args.Contains("--console") && PlatformHelper.Is(MonoMod.Utils.Platform.Windows))
            {
                AllocConsole();
            }

            // PlatformHelper is part of MonoMod.
            // Environment.OSVersion.Platform is good enough as well, but Everest consistently uses PlatformHelper.
            // The following is based off of https://github.com/FNA-XNA/FNA/wiki/4:-FNA-and-Windows-API#direct3d-support
            if (PlatformHelper.Is(MonoMod.Utils.Platform.Windows))
            {
                bool useD3D = args.Contains("--d3d");

                try {
                    // Keep all usage of System.Management in a separate method.
                    // Member references are resolved as soon as a method is called.
                    // This means that if System.Management cannot be found due to
                    // f.e. the use of MonoKickstart, this method won't even get as
                    // far as checking the platform.
                    if (DoesGPUHaveBadOpenGLDrivers())
                    {
                        useD3D = true;
                    }
                } catch {
                    // Silently catch all exceptions: Method and type load errors,
                    // permission / access related exceptions and whatnot.
                }

                if (args.Contains("--no-d3d"))
                {
                    useD3D = false;
                }

                if (useD3D)
                {
                    Environment.SetEnvironmentVariable("FNA_OPENGL_FORCE_ES3", "1");
                    Environment.SetEnvironmentVariable("SDL_OPENGL_ES_DRIVER", "1");
                }
            }

            if (args.Contains("--nolog"))
            {
                MainInner(args);
                Everest.Shutdown();
                return;
            }

            if (File.Exists("log.txt"))
            {
                File.Delete("log.txt");
            }

            using (Stream fileStream = new FileStream("log.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete))
                using (StreamWriter fileWriter = new StreamWriter(fileStream, Console.OutputEncoding))
                    using (LogWriter logWriter = new LogWriter {
                        STDOUT = Console.Out,
                        File = fileWriter
                    }) {
                        try {
                            Console.SetOut(logWriter);

                            MainInner(args);
                        } finally {
                            if (logWriter.STDOUT != null)
                            {
                                Console.SetOut(logWriter.STDOUT);
                                logWriter.STDOUT = null;
                            }
                        }
                    }
        }
Beispiel #30
0
        public new void AfterInitialize()
        {
            // Vanilla / new saves don't have the LevelSets list.
            if (LevelSets == null)
            {
                LevelSets = new List <LevelSetStats>();
            }

            // Add missing LevelSetStats.
            foreach (AreaData area in AreaData.Areas)
            {
                string set = area.GetLevelSet();
                if (!LevelSets.Exists(other => other.Name == set))
                {
                    LevelSets.Add(new LevelSetStats {
                        Name          = set,
                        UnlockedAreas = set == "Celeste" ? UnlockedAreas_Unsafe : 0
                    });
                }
            }

            // Fill each LevelSetStats with its areas.
            for (int lsi = 0; lsi < LevelSets.Count; lsi++)
            {
                LevelSetStats set = LevelSets[lsi];
                set.SaveData = this;
                List <AreaStats> areas = set.Areas;
                if (set.Name == "Celeste")
                {
                    areas = Areas_Unsafe;
                }

                int offset = set.AreaOffset;
                if (offset == -1)
                {
                    // LevelSet gone - let's remove it to prevent any unwanted accesses.
                    // We previously kept the LevelSetStats around in case the levelset resurfaces later on, but as it turns out, this breaks some stuff.
                    LevelSets.RemoveAt(lsi);
                    lsi--;
                    continue;
                }

                int count = AreaData.Areas.Count(other => other.GetLevelSet() == set.Name);
                while (areas.Count < count)
                {
                    areas.Add(new AreaStats(offset + areas.Count));
                }
                while (areas.Count > count)
                {
                    areas.RemoveAt(areas.Count - 1);
                }
                for (int i = 0; i < count; i++)
                {
                    areas[i].ID = offset + i;
                    areas[i].SetSID(AreaData.Get(offset + i).GetSID());
                }

                int lastCompleted = -1;
                for (int i = 0; i < count; i++)
                {
                    if (areas[i].Modes[0].Completed)
                    {
                        lastCompleted = i;
                    }
                }

                if (set.Name == "Celeste")
                {
                    if (UnlockedAreas_Unsafe < lastCompleted + 1 && set.MaxArea >= lastCompleted + 1)
                    {
                        UnlockedAreas_Unsafe = lastCompleted + 1;
                    }
                    if (DebugMode)
                    {
                        UnlockedAreas_Unsafe = set.MaxArea;
                    }
                }
                else
                {
                    if (set.UnlockedAreas < lastCompleted + 1 && set.MaxArea >= lastCompleted + 1)
                    {
                        set.UnlockedAreas = lastCompleted + 1;
                    }
                    if (DebugMode)
                    {
                        set.UnlockedAreas = set.MaxArea;
                    }
                }

                foreach (AreaStats area in areas)
                {
                    area.CleanCheckpoints();
                }
            }

            // Order the levelsets to appear just as their areas appear in AreaData.Areas
            LevelSets.OrderBy(set => set.AreaOffset);

            // Carry over any progress from vanilla saves.
            if (LastArea_Unsafe.ID != 0)
            {
                LastArea_Safe = LastArea_Unsafe;
            }
            if (CurrentSession_Unsafe != null)
            {
                CurrentSession_Safe = CurrentSession_Unsafe;
            }

            // Trick unmodded instances of Celeste to thinking that we last selected prologue / played no level.
            LastArea_Unsafe       = AreaKey.Default;
            CurrentSession_Unsafe = null;

            // Fix out of bounds areas.
            if (LastArea.ID < 0 || LastArea.ID >= AreaData.Areas.Count)
            {
                LastArea = AreaKey.Default;
            }

            // Debug mode shouldn't auto-enter into a level.
            if (DebugMode)
            {
                CurrentSession = null;
            }

            if (string.IsNullOrEmpty(TheoSisterName))
            {
                TheoSisterName = Dialog.Clean("THEO_SISTER_NAME", null);
                if (Name.IndexOf(TheoSisterName, StringComparison.InvariantCultureIgnoreCase) >= 0)
                {
                    TheoSisterName = Dialog.Clean("THEO_SISTER_ALT_NAME", null);
                }
            }

            if (!AssistMode)
            {
                Assists = default(Assists);
            }

            // Disable the GameSpeed clamping - allow mods to "break" this.

            /*
             * if (Assists.GameSpeed < 5 || Assists.GameSpeed > 10) {
             *  Assists.GameSpeed = 10;
             * }
             */

            Everest.Invoke("LoadSaveData", FileSlot);
        }