|     |   | 
| Line 1: | Line 1: | 
|  | <pre>
 |  | 
|  | using System;
 |  | 
|  | using System.Diagnostics;
 |  | 
|  | using System.IO;
 |  | 
|  | using System.Threading;
 |  | 
|  | using Celeste.Pico8;
 |  | 
|  | using Microsoft.Xna.Framework;
 |  | 
|  | using Monocle;
 |  | 
|  | using SDL2;
 |  | 
|  | 
 |  | 
 | 
|  | namespace Celeste;
 |  | 
|  | 
 |  | 
|  | public class Celeste : Engine
 |  | 
|  | {
 |  | 
|  | 	public enum PlayModes
 |  | 
|  | 	{
 |  | 
|  | 		Normal,
 |  | 
|  | 		Debug,
 |  | 
|  | 		Event,
 |  | 
|  | 		Demo
 |  | 
|  | 	}
 |  | 
|  | 
 |  | 
|  | 	public const int GameWidth = 320;
 |  | 
|  | 
 |  | 
|  | 	public const int GameHeight = 180;
 |  | 
|  | 
 |  | 
|  | 	public const int TargetWidth = 1920;
 |  | 
|  | 
 |  | 
|  | 	public const int TargetHeight = 1080;
 |  | 
|  | 
 |  | 
|  | 	public static PlayModes PlayMode = PlayModes.Normal;
 |  | 
|  | 
 |  | 
|  | 	public const string EventName = "";
 |  | 
|  | 
 |  | 
|  | 	public const bool Beta = false;
 |  | 
|  | 
 |  | 
|  | 	public const string PLATFORM = "PC";
 |  | 
|  | 
 |  | 
|  | 	public static bool IsGGP = SDL.SDL_GetPlatform().Equals("Stadia");
 |  | 
|  | 
 |  | 
|  | 	public new static Celeste Instance;
 |  | 
|  | 
 |  | 
|  | 	public static VirtualRenderTarget HudTarget;
 |  | 
|  | 
 |  | 
|  | 	public static VirtualRenderTarget WipeTarget;
 |  | 
|  | 
 |  | 
|  | 	public static DisconnectedControllerUI DisconnectUI;
 |  | 
|  | 
 |  | 
|  | 	private bool firstLoad = true;
 |  | 
|  | 
 |  | 
|  | 	public AutoSplitterInfo AutoSplitterInfo = new AutoSplitterInfo();
 |  | 
|  | 
 |  | 
|  | 	public static Coroutine SaveRoutine;
 |  | 
|  | 
 |  | 
|  | 	public static Stopwatch LoadTimer;
 |  | 
|  | 
 |  | 
|  | 	private static int _mainThreadId;
 |  | 
|  | 
 |  | 
|  | 	public static Vector2 TargetCenter => new Vector2(1920f, 1080f) / 2f;
 |  | 
|  | 
 |  | 
|  | 	public static bool IsMainThread => Thread.CurrentThread.ManagedThreadId == _mainThreadId;
 |  | 
|  | 
 |  | 
|  | 	public Celeste()
 |  | 
|  | 		: base(1920, 1080, 960, 540, "Celeste", Settings.Instance.Fullscreen, Settings.Instance.VSync)
 |  | 
|  | 	{
 |  | 
|  | 		Version = new Version(1, 4, 0, 0);
 |  | 
|  | 		Instance = this;
 |  | 
|  | 		Engine.ExitOnEscapeKeypress = false;
 |  | 
|  | 		base.IsFixedTimeStep = true;
 |  | 
|  | 		Stats.MakeRequest();
 |  | 
|  | 		StatsForStadia.MakeRequest();
 |  | 
|  | 		Console.WriteLine("CELESTE : " + Version);
 |  | 
|  | 	}
 |  | 
|  | 
 |  | 
|  | 	protected override void Initialize()
 |  | 
|  | 	{
 |  | 
|  | 		base.Initialize();
 |  | 
|  | 		Settings.Instance.AfterLoad();
 |  | 
|  | 		if (Settings.Instance.Fullscreen)
 |  | 
|  | 		{
 |  | 
|  | 			Engine.ViewPadding = Settings.Instance.ViewportPadding;
 |  | 
|  | 		}
 |  | 
|  | 		Settings.Instance.ApplyScreen();
 |  | 
|  | 		SFX.Initialize();
 |  | 
|  | 		Tags.Initialize();
 |  | 
|  | 		Input.Initialize();
 |  | 
|  | 		Engine.Commands.Enabled = PlayMode == PlayModes.Debug;
 |  | 
|  | 		Engine.Scene = new GameLoader();
 |  | 
|  | 	}
 |  | 
|  | 
 |  | 
|  | 	protected override void LoadContent()
 |  | 
|  | 	{
 |  | 
|  | 		base.LoadContent();
 |  | 
|  | 		Console.WriteLine("BEGIN LOAD");
 |  | 
|  | 		LoadTimer = Stopwatch.StartNew();
 |  | 
|  | 		PlaybackData.Load();
 |  | 
|  | 		if (firstLoad)
 |  | 
|  | 		{
 |  | 
|  | 			firstLoad = false;
 |  | 
|  | 			HudTarget = VirtualContent.CreateRenderTarget("hud-target", 1922, 1082);
 |  | 
|  | 			WipeTarget = VirtualContent.CreateRenderTarget("wipe-target", 1922, 1082);
 |  | 
|  | 			OVR.Load();
 |  | 
|  | 			if (!IsGGP)
 |  | 
|  | 			{
 |  | 
|  | 				GFX.Load();
 |  | 
|  | 				MTN.Load();
 |  | 
|  | 			}
 |  | 
|  | 		}
 |  | 
|  | 		if (GFX.Game != null)
 |  | 
|  | 		{
 |  | 
|  | 			Monocle.Draw.Particle = GFX.Game["util/particle"];
 |  | 
|  | 			Monocle.Draw.Pixel = new MTexture(GFX.Game["util/pixel"], 1, 1, 1, 1);
 |  | 
|  | 		}
 |  | 
|  | 		GFX.LoadEffects();
 |  | 
|  | 	}
 |  | 
|  | 
 |  | 
|  | 	protected override void Update(GameTime gameTime)
 |  | 
|  | 	{
 |  | 
|  | 		StatsForStadia.BeginFrame(base.Window.Handle);
 |  | 
|  | 		if (SaveRoutine != null)
 |  | 
|  | 		{
 |  | 
|  | 			SaveRoutine.Update();
 |  | 
|  | 		}
 |  | 
|  | 		AutoSplitterInfo.Update();
 |  | 
|  | 		Audio.Update();
 |  | 
|  | 		base.Update(gameTime);
 |  | 
|  | 		Input.UpdateGrab();
 |  | 
|  | 	}
 |  | 
|  | 
 |  | 
|  | 	protected override void OnSceneTransition(Scene last, Scene next)
 |  | 
|  | 	{
 |  | 
|  | 		if (!(last is OverworldLoader) || !(next is Overworld))
 |  | 
|  | 		{
 |  | 
|  | 			base.OnSceneTransition(last, next);
 |  | 
|  | 		}
 |  | 
|  | 		Engine.TimeRate = 1f;
 |  | 
|  | 		Audio.PauseGameplaySfx = false;
 |  | 
|  | 		Audio.SetMusicParam("fade", 1f);
 |  | 
|  | 		Distort.Anxiety = 0f;
 |  | 
|  | 		Distort.GameRate = 1f;
 |  | 
|  | 		Glitch.Value = 0f;
 |  | 
|  | 	}
 |  | 
|  | 
 |  | 
|  | 	protected override void RenderCore()
 |  | 
|  | 	{
 |  | 
|  | 		base.RenderCore();
 |  | 
|  | 		if (DisconnectUI != null)
 |  | 
|  | 		{
 |  | 
|  | 			DisconnectUI.Render();
 |  | 
|  | 		}
 |  | 
|  | 	}
 |  | 
|  | 
 |  | 
|  | 	public static void Freeze(float time)
 |  | 
|  | 	{
 |  | 
|  | 		if (Engine.FreezeTimer < time)
 |  | 
|  | 		{
 |  | 
|  | 			Engine.FreezeTimer = time;
 |  | 
|  | 			if (Engine.Scene != null)
 |  | 
|  | 			{
 |  | 
|  | 				Engine.Scene.Tracker.GetEntity<CassetteBlockManager>()?.AdvanceMusic(time);
 |  | 
|  | 			}
 |  | 
|  | 		}
 |  | 
|  | 	}
 |  | 
|  | 
 |  | 
|  | 	private static void Main(string[] args)
 |  | 
|  | 	{
 |  | 
|  | 		Celeste game;
 |  | 
|  | 		try
 |  | 
|  | 		{
 |  | 
|  | 			Environment.SetEnvironmentVariable("FNA_AUDIO_DISABLE_SOUND", "1");
 |  | 
|  | 			for (int i = 0; i < args.Length; i++)
 |  | 
|  | 			{
 |  | 
|  | 				if (args[i] == "--graphics" && i < args.Length - 1)
 |  | 
|  | 				{
 |  | 
|  | 					Environment.SetEnvironmentVariable("FNA3D_FORCE_DRIVER", args[i + 1]);
 |  | 
|  | 					i++;
 |  | 
|  | 				}
 |  | 
|  | 				else if (args[i] == "--disable-lateswaptear")
 |  | 
|  | 				{
 |  | 
|  | 					Environment.SetEnvironmentVariable("FNA3D_DISABLE_LATESWAPTEAR", "1");
 |  | 
|  | 				}
 |  | 
|  | 			}
 |  | 
|  | 			_mainThreadId = Thread.CurrentThread.ManagedThreadId;
 |  | 
|  | 			Settings.Initialize();
 |  | 
|  | 			_ = Settings.Existed;
 |  | 
|  | 			for (int j = 0; j < args.Length - 1; j++)
 |  | 
|  | 			{
 |  | 
|  | 				if (args[j] == "--language" || args[j] == "-l")
 |  | 
|  | 				{
 |  | 
|  | 					Settings.Instance.Language = args[++j];
 |  | 
|  | 				}
 |  | 
|  | 				else if (args[j] == "--default-language" || args[j] == "-dl")
 |  | 
|  | 				{
 |  | 
|  | 					if (!Settings.Existed)
 |  | 
|  | 					{
 |  | 
|  | 						Settings.Instance.Language = args[++j];
 |  | 
|  | 					}
 |  | 
|  | 				}
 |  | 
|  | 				else if (args[j] == "--gui" || args[j] == "-g")
 |  | 
|  | 				{
 |  | 
|  | 					Input.OverrideInputPrefix = args[++j];
 |  | 
|  | 				}
 |  | 
|  | 			}
 |  | 
|  | 			game = new Celeste();
 |  | 
|  | 		}
 |  | 
|  | 		catch (Exception ex)
 |  | 
|  | 		{
 |  | 
|  | 			Console.WriteLine(ex.ToString());
 |  | 
|  | 			ErrorLog.Write(ex);
 |  | 
|  | 			try
 |  | 
|  | 			{
 |  | 
|  | 				ErrorLog.Open();
 |  | 
|  | 				return;
 |  | 
|  | 			}
 |  | 
|  | 			catch
 |  | 
|  | 			{
 |  | 
|  | 				Console.WriteLine("Failed to open the log!");
 |  | 
|  | 				return;
 |  | 
|  | 			}
 |  | 
|  | 		}
 |  | 
|  | 		game.RunWithLogging();
 |  | 
|  | 		RunThread.WaitAll();
 |  | 
|  | 		game.Dispose();
 |  | 
|  | 		Audio.Unload();
 |  | 
|  | 	}
 |  | 
|  | 
 |  | 
|  | 	public static void ReloadAssets(bool levels, bool graphics, bool hires, AreaKey? area = null)
 |  | 
|  | 	{
 |  | 
|  | 		if (levels)
 |  | 
|  | 		{
 |  | 
|  | 			ReloadLevels(area);
 |  | 
|  | 		}
 |  | 
|  | 		if (graphics)
 |  | 
|  | 		{
 |  | 
|  | 			ReloadGraphics(hires);
 |  | 
|  | 		}
 |  | 
|  | 	}
 |  | 
|  | 
 |  | 
|  | 	public static void ReloadLevels(AreaKey? area = null)
 |  | 
|  | 	{
 |  | 
|  | 	}
 |  | 
|  | 
 |  | 
|  | 	public static void ReloadGraphics(bool hires)
 |  | 
|  | 	{
 |  | 
|  | 	}
 |  | 
|  | 
 |  | 
|  | 	public static void ReloadPortraits()
 |  | 
|  | 	{
 |  | 
|  | 	}
 |  | 
|  | 
 |  | 
|  | 	public static void ReloadDialog()
 |  | 
|  | 	{
 |  | 
|  | 	}
 |  | 
|  | 
 |  | 
|  | 	private static void CallProcess(string path, string args = "", bool createWindow = false)
 |  | 
|  | 	{
 |  | 
|  | 		Process process = new Process();
 |  | 
|  | 		process.StartInfo = new ProcessStartInfo
 |  | 
|  | 		{
 |  | 
|  | 			FileName = path,
 |  | 
|  | 			WorkingDirectory = Path.GetDirectoryName(path),
 |  | 
|  | 			RedirectStandardOutput = false,
 |  | 
|  | 			CreateNoWindow = !createWindow,
 |  | 
|  | 			UseShellExecute = false,
 |  | 
|  | 			Arguments = args
 |  | 
|  | 		};
 |  | 
|  | 		process.Start();
 |  | 
|  | 		process.WaitForExit();
 |  | 
|  | 	}
 |  | 
|  | 
 |  | 
|  | 	public static bool PauseAnywhere()
 |  | 
|  | 	{
 |  | 
|  | 		if (Engine.Scene is Level)
 |  | 
|  | 		{
 |  | 
|  | 			Level level = Engine.Scene as Level;
 |  | 
|  | 			if (level.CanPause)
 |  | 
|  | 			{
 |  | 
|  | 				level.Pause();
 |  | 
|  | 				return true;
 |  | 
|  | 			}
 |  | 
|  | 		}
 |  | 
|  | 		else if (Engine.Scene is Emulator)
 |  | 
|  | 		{
 |  | 
|  | 			Emulator pico = Engine.Scene as Emulator;
 |  | 
|  | 			if (pico.CanPause)
 |  | 
|  | 			{
 |  | 
|  | 				pico.CreatePauseMenu();
 |  | 
|  | 				return true;
 |  | 
|  | 			}
 |  | 
|  | 		}
 |  | 
|  | 		else if (Engine.Scene is IntroVignette)
 |  | 
|  | 		{
 |  | 
|  | 			IntroVignette intro = Engine.Scene as IntroVignette;
 |  | 
|  | 			if (intro.CanPause)
 |  | 
|  | 			{
 |  | 
|  | 				intro.OpenMenu();
 |  | 
|  | 				return true;
 |  | 
|  | 			}
 |  | 
|  | 		}
 |  | 
|  | 		else if (Engine.Scene is CoreVignette)
 |  | 
|  | 		{
 |  | 
|  | 			CoreVignette core = Engine.Scene as CoreVignette;
 |  | 
|  | 			if (core.CanPause)
 |  | 
|  | 			{
 |  | 
|  | 				core.OpenMenu();
 |  | 
|  | 				return true;
 |  | 
|  | 			}
 |  | 
|  | 		}
 |  | 
|  | 		return false;
 |  | 
|  | 	}
 |  | 
|  | }
 |  | 
|  | </pre>
 |  |