[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; } }
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(); } }
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(); }
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"); } }
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; } }
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); }
protected override void Initialize() { // Note: You may instinctually call base.Initialize(); // DON'T! The original method is orig_Initialize orig_Initialize(); Everest.Invoke("Initialize"); }
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); })); }
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; } }
/// <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}"); } }
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 }; }
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(); }
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); }
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); }
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(); }
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; }
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 }; }
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; } } }
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); }
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); } }
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; } }
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; }
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; }; }
[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; } }
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(); }
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); })); }
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; } } } }
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); }