Advertisement
Guest User

Untitled

a guest
Jun 27th, 2016
242
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 125.23 KB | None | 0 0
  1. #region Using Statements
  2.  
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Drawing;
  7. using System.Globalization;
  8. using System.IO;
  9. using System.Runtime.InteropServices;
  10. using System.Threading;
  11. using System.Windows.Forms;
  12. using Microsoft.Win32;
  13. using Microsoft.Xna.Framework;
  14. using Microsoft.Xna.Framework.Graphics;
  15. using Microsoft.Xna.Framework.Input;
  16. using osu.Audio;
  17. using osu.Configuration;
  18. using osu.GameModes.Edit;
  19. using osu.GameModes.Edit.Forms;
  20. using osu.GameModes.Menus;
  21. using osu.GameModes.Online;
  22. using osu.GameModes.Options;
  23. using osu.GameModes.Play;
  24. using osu.GameModes.Ranking;
  25. using osu.GameModes.Select;
  26. using osu.GameplayElements;
  27. using osu.GameplayElements.Beatmaps;
  28. using osu.GameplayElements.Scoring;
  29. using osu.Graphics;
  30. using osu.Graphics.Notifications;
  31. using osu.Graphics.OpenGl;
  32. using OpenTK.Graphics.ES20;
  33. using osu.Graphics.Primitives;
  34. using osu.Graphics.Renderers;
  35. using osu.Graphics.Skinning;
  36. using osu.Graphics.Sprites;
  37. using osu.Graphics.UserInterface;
  38. using osu.Helpers;
  39. using osu.Helpers.Forms;
  40. using osu.Input;
  41. using osu.Input.Handlers;
  42. using osu.Online;
  43. using osu.Online.Drawable;
  44. using osu_common;
  45. using osu_common.Helpers;
  46. using osudata;
  47. using Un4seen.Bass;
  48. using Color = Microsoft.Xna.Framework.Graphics.Color;
  49. using Keys = Microsoft.Xna.Framework.Input.Keys;
  50. using Menu = osu.GameModes.Menus.Menu;
  51. using Point = Microsoft.Xna.Framework.Point;
  52. using Rectangle = Microsoft.Xna.Framework.Rectangle;
  53. using System.Security;
  54. using ICSharpCode.SharpZipLib.Zip;
  55. using System.Net.NetworkInformation;
  56. using System.Security.Principal;
  57. using System.Security.AccessControl;
  58. using osu.GameModes.Play.Rulesets.Mania;
  59. using System.Drawing.Imaging;
  60. using osu.Framework;
  61. using osu.GameModes.Play.Components;
  62. using osu_common.Updater;
  63. using osu.Graphics.Tips;
  64. using osu.Online.Social;
  65. using osu.GameModes;
  66. using PixelFormat = System.Drawing.Imaging.PixelFormat;
  67. using osu.GameModes.Other.Drawings;
  68. using osu.Graphics.Shaders;
  69. using OpenTK.Graphics;
  70. using osu.GameModes.Other.Tournament;
  71. using Amib.Threading;
  72. using osu.Framework.GLControl;
  73.  
  74. #endregion
  75.  
  76. namespace osu
  77. {
  78.     public partial class GameBase : Game
  79.     {
  80.         #region General
  81.  
  82.         private static ChatEngine chatEngine;
  83.         private static List<pDialog> DialogQueue = new List<pDialog>();
  84.         internal static EditorControl EditorControl;
  85.         internal static WindowsGameForm Form => (Instance?.Window as WindowsGameWindow)?.Form;
  86.         private static NotifyIcon notifyIcon;
  87.         private const double FrameAimTime = (double)1000 / 60;
  88.  
  89.         /// <summary>
  90.         /// The time a frame took to draw compared to 60fps standard.
  91.         /// </summary>
  92.         internal static double FrameRatio;
  93.  
  94.         internal static GameBase Instance;
  95.         internal static bool IsMinimized;
  96.         internal static LineManager LineManager;
  97.         internal static bool MenuVisible;
  98.  
  99.         internal BackgroundAppDetector BackgroundAppDetector;
  100.  
  101.         internal DataStoreUpdater DataStoreUpdater;
  102.  
  103.         internal static int MenuHeight
  104.         {
  105.             get
  106.             {
  107.                 return MenuVisible ? EditorControl.Height : 0;
  108.             }
  109.         }
  110.  
  111.         internal static readonly NumberFormatInfo nfi = new CultureInfo(@"en-US", false).NumberFormat;
  112.         internal static int PixelShaderVersion;
  113.         internal static PrimitiveBatch LineBatch;
  114.         internal static pSprite s_fadeScreen;
  115.         internal const double SIXTY_FRAME_TIME = (double)1000 / 60;
  116.  
  117.         internal double FrameLimitMillisecondsPerFrame
  118.         {
  119.             get
  120.             {
  121.                 return 1000d / TargetFrameRate;
  122.             }
  123.         }
  124.  
  125.         internal static double TargetFrameRate
  126.         {
  127.             get
  128.             {
  129.                 double result = 60;
  130.  
  131.                 switch (ConfigManager.sFrameSync.Value)
  132.                 {
  133.                     case FrameSync.Custom:
  134.                         result = ConfigManager.sCustomFrameLimit.Value;
  135.                         break;
  136.                     case FrameSync.Unlimited:
  137.                     case FrameSync.CompletelyUnlimited:
  138.                         // With gameplay unlimited we want to have at _least_ the user-specified CustomFrameLimit outside of gameplay, or the monitor refresh (whichever is higher).
  139.                         result = Mode == OsuModes.Play && !Player.Paused ? Double.PositiveInfinity : Math.Max(RefreshRate, ConfigManager.sCustomFrameLimit.Value);
  140.  
  141. #if !Public
  142.                         if (KeyboardHandler.AltPressed)
  143.                             result = Double.PositiveInfinity;
  144. #endif
  145.                         break;
  146.  
  147.                     case FrameSync.Limit120:
  148.                         result = 120;
  149.                         break;
  150.  
  151.                     // With VSync on the refresh rate is controlled by the graphics API, so this member variable shouldn't limit the frame rate in any way
  152.                     case FrameSync.VSync:
  153.                         result = Double.PositiveInfinity;
  154.                         break;
  155.                 }
  156.  
  157.                 if (CanRunSlowly)
  158.                 {
  159.                     if (IsMinimized)
  160.                         result = Math.Min(15, result);
  161.                     else if (!Instance.IsActive)
  162.                         result = Math.Min(30, result);
  163.                     else
  164.                         result = Math.Min(RefreshRate, result);
  165.                 }
  166.  
  167.                 Debug.Assert(result > 0);
  168.                 return result;
  169.             }
  170.         }
  171.  
  172.         internal static bool SixtyFramesPerSecondFrame;
  173.         internal static double SixtyFramesPerSecondLength;
  174.         internal static SpriteManager spriteManager;
  175.         internal static SpriteManager spriteManagerCursor;
  176.         internal static CursorTrailRenderer cursorTrailRenderer;
  177.         internal static SpriteManager spriteManagerOverlay;
  178.         internal static SpriteManager spriteManagerOverlayHighest;
  179.         internal static SpriteManager spriteManagerTransition;
  180.         internal static SpriteManager spriteManagerHighest;
  181.         internal static Stopwatch stopWatch = new Stopwatch();
  182.         internal static int Time;
  183.         internal static pTexture WhitePixel;
  184.         internal static bool PendingModeChange = true;
  185.         internal static double TimeAccurateLastUpdate;
  186.         private static double SixtyFrameLast;
  187.         internal static double TimeAccurate;
  188.         private static double AccumulatedSleepError;
  189.  
  190.         internal FpsDisplay FpsDisplay;
  191.  
  192.         internal static OnScreenDisplay OnScreenDisplay;
  193.         internal static FrameTimeDisplay FrameTimeDisplay;
  194.  
  195.         internal static PerformanceMonitor PerformanceMonitor;
  196.  
  197.         internal static PhysicsManager PhysicsManager = new PhysicsManager();
  198.         internal static BanchoStatusOverlay BanchoStatus;
  199.  
  200.         internal static VolumeControlSet Volume;
  201.  
  202.         /// <summary>
  203.         /// This client is in Tournament mode.
  204.         /// </summary>
  205.         internal static bool Tournament;
  206.         /// <summary>
  207.         /// Special client for managing other tournament clients.
  208.         /// </summary>
  209.         internal static bool TournamentManager;
  210.         /// <summary>
  211.         /// Special tournament client for team drawings.
  212.         /// </summary>
  213.         internal static bool TournamentDrawings;
  214.         internal static short TournamentClientId;
  215.         internal static pText TourneySpectatorName;
  216.         internal static bool TournamentBuffering;
  217.         internal static bool TournamentSkipCalculations;
  218.  
  219.         internal static CoinsOverlay Coins;
  220.  
  221.         internal static TransitionManager TransitionManager;
  222.  
  223.         internal static double ModeTime;
  224.  
  225.         internal static string EXPORT_FOLDER => Path.Combine(OsuMain.UserPath, @"Exports");
  226.  
  227.         internal GameBase(string startupFile)
  228.             : base(ConfigManager.sCompatibilityContext ? GraphicsContextFlags.Angle : GraphicsContextFlags.Default)
  229.         {
  230.             Instance = this;
  231.  
  232.             StartupNewFiles = startupFile;
  233.  
  234.             Application.EnableVisualStyles();
  235.  
  236.             Mouse.WindowHandle = Window.Handle;
  237.             OpenTK.NativeWindow.OsuWindowHandle = Window.Handle;
  238.  
  239.             string exeName = Environment.CurrentDirectory + @"\" + Process.GetCurrentProcess().ProcessName.Replace(@".vshost", string.Empty) + @".exe";
  240.  
  241.             try
  242.             {
  243.                 Form.Icon = Icon.ExtractAssociatedIcon(exeName);
  244.             }
  245.             catch
  246.             {
  247.             }
  248.  
  249.             Form.AllowDrop = true;
  250.  
  251.             Form.FormClosing += Form_FormClosing;
  252.             Form.DragEnter += Form_DragEnter;
  253.             Form.DragDrop += Form_DragDrop;
  254.             Deactivated += Form_Deactivate;
  255.             Activated += Form_Activated;
  256.  
  257.             FadeOutComplete += delegate { loadQueuedMode(0); };
  258.  
  259.             MainThread = Thread.CurrentThread;
  260.  
  261.             //If we have failed to update more than five times in a row, let's force an update.
  262.             if (ConfigManager.sUpdateFailCount >= 5)
  263.             {
  264.                 SplashScreen.CloseAll();
  265.  
  266.                 ConfigManager.sUpdateFailCount.Value = 0;
  267.                 ConfigManager.SaveConfig();
  268.  
  269.                 OsuMain.Repair();
  270.             }
  271.  
  272.             LocalisationManager.SetLanguage(ConfigManager.sLanguage, ConfigManager.sLastVersion != General.BUILD_NAME, delegate
  273.             {
  274.                 if (GameBase.Time > 0)
  275.                 {
  276.                     Scheduler.AddDelayed(delegate
  277.                     {
  278.                         ConfigManager.sLanguage.Value = LocalisationManager.CurrentLanguage;
  279.                     }, Math.Max(0, (Menu.IntroLength + 500) - GameBase.Time));
  280.  
  281.                     return;
  282.                 }
  283.  
  284.                 ConfigManager.sLanguage.Value = LocalisationManager.CurrentLanguage;
  285.  
  286.             }, osu.Properties.Resources.en);
  287.  
  288.             InitialDesktopResolution = ResolutionHelper.GetDesktopResolution();
  289.             InitialDesktopLocation = ResolutionHelper.GetDesktopPosition();
  290.             InitialRefreshRate = ResolutionHelper.GetCurrentRefreshRate();
  291.  
  292.             WindowManager = new WindowManager();
  293.  
  294.             KeyboardState keyState = Keyboard.GetState();
  295.             if (keyState.IsKeyDown(Keys.LeftShift) || keyState.IsKeyDown(Keys.RightShift) || (OsuMain.Args.Length > 1 && OsuMain.Args[1] == @"-config"))
  296.             {
  297.                 Helpers.Forms.Configuration configForm = new Helpers.Forms.Configuration();
  298.                 configForm.ShowDialog();
  299.             }
  300.  
  301.             GameField = new GameField(WindowManager);
  302.  
  303.             InitializeSound();
  304.  
  305.             Native.SetThreadExecutionState(Native.ExecutionState.Continuous | Native.ExecutionState.SystemRequired | Native.ExecutionState.DisplayRequired);
  306.         }
  307.  
  308.  
  309.         internal delegate string DllRegisterServerInvoker();
  310.  
  311.         internal static void InitializeSound()
  312.         {
  313.             AudioEngine.SetAudioDevice(ConfigManager.sAudioDevice.Value);
  314.  
  315.             if (Tournament)
  316.                 AudioEngine.VolumeMaster.Value = 0;
  317.         }
  318.  
  319.  
  320.         internal static bool TopMost
  321.         {
  322.             get
  323.             {
  324.                 return
  325.                     // We can only be topmost if we are active and not in the editor showing the menu. Otherwise osu! shouldn't steal the show from other programs
  326.                     (GameBase.Instance.IsActive && !GameBase.MenuVisible && GameBase.IsFullscreen)
  327.                     //Tournament clients should always be topmost
  328.                     || (Tournament && !TournamentManager);
  329.             }
  330.         }
  331.  
  332.  
  333.         internal static bool MenuActive
  334.         {
  335.             get { return localMenuActive; }
  336.             set
  337.             {
  338.                 if (localMenuActive == value) return;
  339.  
  340.                 localMenuActive = value;
  341.                 MouseManager.UpdateMouseCursorVisibility();
  342.                 MouseManager.ResetStatus();
  343.             }
  344.         }
  345.  
  346.         private static int bossKeyRestoreVolume = 0;
  347.         internal static bool OnKeyPressed(object sender, Keys k)
  348.         {
  349.             Bindings bind = BindingManager.CheckKey(k);
  350.  
  351. #if DEBUG
  352.             if (SpriteManager.Placement && SpriteManager.ClickHandledSprite != null)
  353.             {
  354.                 float increment = 1;
  355.                 if (KeyboardHandler.ShiftPressed)
  356.                     increment /= 5f;
  357.                 else if (KeyboardHandler.ControlPressed)
  358.                     increment *= 5f;
  359.  
  360.                 pSprite p = SpriteManager.ClickHandledSprite;
  361.                 pText pt = p as pText;
  362.  
  363.                 switch (k)
  364.                 {
  365.                     case Keys.Left:
  366.                         p.Position.X -= increment;
  367.                         break;
  368.                     case Keys.Right:
  369.                         p.Position.X += increment;
  370.                         break;
  371.                     case Keys.Up:
  372.                         p.Position.Y -= increment;
  373.                         break;
  374.                     case Keys.Down:
  375.                         p.Position.Y += increment;
  376.                         break;
  377.                     case Keys.Z:
  378.                         if (pt != null)
  379.                             pt.TextSize -= increment;
  380.                         else
  381.                             p.Scale -= increment / 100f;
  382.                         break;
  383.                     case Keys.X:
  384.                         if (pt != null)
  385.                             pt.TextSize += increment;
  386.                         else
  387.                             p.Scale += increment / 100f;
  388.                         break;
  389.                     case Keys.H:
  390.                         p.Bypass = !p.Bypass;
  391.                         break;
  392.                 }
  393.             }
  394. #endif
  395.  
  396.             switch (bind)
  397.             {
  398.                 case Bindings.Screenshot:
  399.                     Screenshot.TakeScreenshot(KeyboardHandler.ShiftPressed);
  400.                     return true;
  401.                 case Bindings.DisableMouseButtons:
  402.                     ConfigManager.sMouseDisableButtons.Toggle();
  403.                     NotificationManager.ShowMessageMassive("Mouse buttons are " + (ConfigManager.sMouseDisableButtons ? "disabled" : "enabled") + @".", 1000);
  404.                     return true;
  405.                 case Bindings.ToggleFrameLimiter:
  406.                     switch (ConfigManager.sFrameSync.Value)
  407.                     {
  408.                         case FrameSync.VSync:
  409.                             ConfigManager.sFrameSync.Value = FrameSync.Limit120;
  410.                             break;
  411.                         case FrameSync.Limit120:
  412.                             ConfigManager.sFrameSync.Value = FrameSync.Custom;
  413.                             break;
  414.                         case FrameSync.Custom:
  415.                             ConfigManager.sFrameSync.Value = FrameSync.Unlimited;
  416.                             break;
  417.                         case FrameSync.Unlimited:
  418.                         default:
  419.                             ConfigManager.sFrameSync.Value = FrameSync.Limit120;
  420.                             break;
  421.                     }
  422.                     return true;
  423.                 case Bindings.BossKey:
  424.                     MinimizedToTray = true;
  425.                     return true;
  426.             }
  427.  
  428.             switch (k)
  429.             {
  430.                 case Keys.O:
  431.                     if (KeyboardHandler.ControlPressed && !KeyboardHandler.AltPressed && Options.CanExpand)
  432.                     {
  433.                         Options.LoginOnly = false;
  434.                         Options.Expanded = true;
  435.                         return true;
  436.                     }
  437.  
  438.                     break;
  439.                 case Keys.Enter:
  440.                     if (KeyboardHandler.AltPressed)
  441.                     {
  442.                         switch (Mode)
  443.                         {
  444.                             case OsuModes.Menu:
  445.                             case OsuModes.SelectPlay:
  446.                             case OsuModes.Lobby:
  447.                                 ConfigManager.sFullscreen.Toggle();
  448.                                 return true;
  449.                         }
  450.  
  451.                         return false;
  452.                     }
  453.  
  454.                     break;
  455.                 case Keys.S:
  456.                     if (KeyboardHandler.ShiftPressed && KeyboardHandler.AltPressed && KeyboardHandler.ControlPressed)
  457.                     {
  458.                         GameBase.OnNextModeChange += delegate {
  459.                             NotificationManager.ShowMessageMassive("Skin reloaded!", 2000);
  460.                             SkinManager.LoadSkin(null, true);
  461.                             TextureManager.Reload();
  462.                         };
  463.  
  464.                         if (ModeCanReload)
  465.                             GameBase.ChangeMode(GameBase.Mode, true);
  466.                         else
  467.                             NotificationManager.ShowMessageMassive("Skin reload queued.", 2000);
  468.  
  469.                         return true;
  470.                     }
  471.                     break;
  472.  
  473.                 case Keys.R:
  474.                     if (KeyboardHandler.ControlPressed && Tournament)
  475.                     {
  476.                         User u = StreamingManager.CurrentlySpectating;
  477.  
  478.                         if (u == null)
  479.                             u = BanchoClient.GetUserByName(TourneySpectatorName.Text);
  480.  
  481.                         if (u != null)
  482.                         {
  483.                             StreamingManager.StopSpectating(true);
  484.                             StreamingManager.StartSpectating(u);
  485.                         }
  486.                     }
  487.  
  488.                     break;
  489.                 case Keys.F11:
  490.                     if (KeyboardHandler.ControlPressed)
  491.                     {
  492.                         ConfigManager.sFrameTimeDisplay.Value = !ConfigManager.sFrameTimeDisplay.Value;
  493.                         NotificationManager.ShowMessage("Frame times are now " + (ConfigManager.sFrameTimeDisplay.Value ? "visible" : "hidden") + ". Press Ctrl+F11 to toggle.");
  494.                         return true;
  495.                     }
  496.                     else if (OnScreenDisplay != null)
  497.                     {
  498.                         OnScreenDisplay.ToggleShow();
  499.                         return true;
  500.                     }
  501.  
  502.                     break;
  503. #if DEBUG
  504.                 case Keys.D0:
  505.                     if (KeyboardHandler.ControlPressed)
  506.                     {
  507.                         BanchoClient.SwitchServer();
  508.                         return true;
  509.                     }
  510.                     break;
  511.                 case Keys.G:
  512.                     if (KeyboardHandler.ControlPressed)
  513.                         GC.Collect();
  514.                     break;
  515. #endif
  516.             }
  517.  
  518.             return false;
  519.         }
  520.  
  521.         static int owcCount = 0;
  522.  
  523.         private static void Form_DragDrop(object sender, DragEventArgs e)
  524.         {
  525.             try
  526.             {
  527.                 Array a = (Array)e.Data.GetData(DataFormats.FileDrop);
  528.  
  529.                 OsuModes gs = OsuModes.Unknown;
  530.                 if (a != null)
  531.                 {
  532.                     string[] files = new string[a.Length];
  533.                     for (int i = 0; i < a.Length; i++)
  534.                         files[i] = a.GetValue(i).ToString();
  535.  
  536.                     gs = ReceiveFile(files);
  537.                 }
  538.                 else
  539.                 {
  540.                     string text = e.Data.GetData(DataFormats.Text) as string;
  541.                     if (text.StartsWith(@"http"))
  542.                         ChatEngine.HandleLink(text);
  543.                     else
  544.                         gs = ReceiveFile(text);
  545.                 }
  546.  
  547.                 if (gs != OsuModes.Unknown)
  548.                     ChangeMode(gs, true);
  549.             }
  550.             catch (Exception)
  551.             {
  552.             }
  553.         }
  554.  
  555.         private static void Form_DragEnter(object sender, DragEventArgs e)
  556.         {
  557.             bool isFile = e.Data.GetDataPresent(DataFormats.FileDrop);
  558.             bool isUrl = e.Data.GetDataPresent(DataFormats.Text);
  559.             e.Effect = isFile || isUrl ? DragDropEffects.Copy : DragDropEffects.None;
  560.         }
  561.  
  562.         private void Form_Deactivate(object sender, EventArgs e)
  563.         {
  564.             Native.SetThreadExecutionState(Native.ExecutionState.Continuous);
  565.  
  566.             if (Tournament) return;
  567.  
  568.             if (Player.Playing && !InputManager.ReplayMode)
  569.             {
  570.                 Form.BringToFront();
  571.                 Form.Focus();
  572.             }
  573.         }
  574.  
  575.         void Form_Activated(object sender, EventArgs e)
  576.         {
  577.             Native.SetThreadExecutionState(Native.ExecutionState.Continuous | Native.ExecutionState.SystemRequired | Native.ExecutionState.DisplayRequired);
  578.             InputManager.LastActionTime = GameBase.Time;
  579.         }
  580.  
  581.         private void Form_FormClosing(object sender, FormClosingEventArgs e)
  582.         {
  583.             if (ChatEngine.Visibility == ChatVisibility.Full)
  584.             {
  585.                 ChatEngine.HideChat();
  586.                 e.Cancel = true;
  587.                 return;
  588.             }
  589.  
  590.             switch (Mode)
  591.             {
  592.                 case OsuModes.Rank:
  593.                     ChangeMode(OsuModes.SelectPlay);
  594.                     e.Cancel = true;
  595.                     return;
  596.                 case OsuModes.RankingVs:
  597.                 case OsuModes.RankingTeam:
  598.                 case OsuModes.RankingTagCoop:
  599.                     ChangeMode(OsuModes.MatchSetup);
  600.                     e.Cancel = true;
  601.                     return;
  602.                 case OsuModes.Edit:
  603.                     Editor editor = RunningGameMode as Editor;
  604.                     if (editor != null)
  605.                         editor.Exit();
  606.                     e.Cancel = true;
  607.                     return;
  608.                 case OsuModes.Play:
  609.                     StreamingManager.StopSpectating();
  610.  
  611.                     if (RunningGameMode is PlayerVs)
  612.                         MatchSetup.LeaveGame();
  613.                     else if (TestMode)
  614.                         ChangeMode(OsuModes.Edit);
  615.                     else
  616.                         ChangeMode(OsuModes.SelectPlay);
  617.                     e.Cancel = true;
  618.                     return;
  619.                 case OsuModes.Lobby:
  620.                 case OsuModes.OnlineSelection:
  621.                 case OsuModes.OptionsOffsetWizard:
  622.                     ChangeMode(OsuModes.Menu);
  623.                     e.Cancel = true;
  624.                     return;
  625.                 case OsuModes.MatchSetup:
  626.                     ChangeMode(OsuModes.Lobby);
  627.                     e.Cancel = true;
  628.                     return;
  629.             }
  630.  
  631.             if (Mode != OsuModes.Exit && Mode != OsuModes.Update)
  632.             {
  633.                 BeginExit(false);
  634.                 //Sleepable = false;
  635.                 e.Cancel = true;
  636.             }
  637.         }
  638.  
  639.         internal static event VoidDelegate OnNextModeChange;
  640.         internal static event VoidDelegate OnModeChange;
  641.  
  642.         internal static event VoidDelegate OnExitFade;
  643.  
  644.         private static event VoidDelegate exitAction;
  645.         protected override void OnExiting(object sender, EventArgs args)
  646.         {
  647.             if (exitAction != null) exitAction();
  648.  
  649.             BanchoClient.Exit();
  650.  
  651.             ImHelper.SetAllMusic(false, string.Empty, string.Empty, string.Empty, string.Empty);
  652.  
  653.             if (Mode == OsuModes.Edit)
  654.             {
  655.                 try
  656.                 {
  657.                     ((Editor)RunningGameMode).Exit();
  658.                 }
  659.                 catch (Exception)
  660.                 {
  661.                 }
  662.             }
  663.  
  664.             DataStoreUpdater.Save();
  665.  
  666.             try
  667.             {
  668.                 if (Mode == OsuModes.Play && !InputManager.ReplayMode)
  669.                     Player.Instance.HandleScoreSubmission();
  670.             }
  671.             catch { }
  672.  
  673.  
  674.  
  675.             Screensaver.Restore();
  676.  
  677.             spriteManager.Dispose();
  678.             spriteManagerOverlay.Dispose();
  679.             spriteManagerOverlayHighest.Dispose();
  680.  
  681.             if (ConfigManager.sWiimote)
  682.                 WiimoteManager.Disconnect();
  683.  
  684.             Cursor.Show();
  685.             Cursor.Clip = InputManager.CursorOriginalBounds;
  686.  
  687.             try
  688.             {
  689.                 Directory.Delete(User.AvatarFilePath, true);
  690.             }
  691.             catch
  692.             {
  693.             }
  694. #if P2P
  695.             Osup2pManager.Shutdown();
  696. #endif
  697.  
  698.             try
  699.             {
  700.                 Bass.BASS_Free();
  701.             }
  702.             catch { }
  703.  
  704.             InputManager.Dispose();
  705.  
  706.             base.OnExiting(sender, args);
  707.         }
  708.  
  709.         internal static event VoidDelegate OnResolutionChange;
  710.  
  711.         /// <summary>
  712.         /// Uses a sledgehammer method to leave exclusive full screen mode forcibly. This messed up window borders and position and should only be used when absolutely necessary.
  713.         /// </summary>
  714.         private static void ForcefullyLeaveExclusiveFullscreen()
  715.         {
  716.             if (OsuGlControl.UsesAngle)
  717.                 GLControl.ToggleWindowed();
  718.             else
  719.             {
  720.                 System.Drawing.Point p = Form.Location;
  721.                 Form.Location = new System.Drawing.Point(p.X - 1, p.Y - 1);
  722.                 Form.FormBorderStyle = FormBorderStyle.FixedSingle;
  723.             }
  724.         }
  725.  
  726.         static VoidDelegate pendingScreenModeChange;
  727.         internal static void SetScreenSize(int? width = null, int? height = null, bool saveToConfig = false, bool force = false)
  728.         {
  729.             try
  730.             {
  731.                 if (width == WindowManager.Width && height == WindowManager.Height && !force) return;
  732.  
  733.                 Instance.GlControl.VSync = ConfigManager.sFrameSync == FrameSync.VSync;
  734.  
  735.                 UpdateDesktopProperties();
  736.  
  737.                 if (pendingScreenModeChange == null && !PendingModeChange)
  738.                 {
  739.                     pendingScreenModeChange = delegate { SetScreenSize(width, height, saveToConfig, true); };
  740.                     ChangeMode(Mode, true);
  741.                     return;
  742.                 }
  743.  
  744.                 bool wasFullscreen = IsFullscreen;
  745.                 IsFullscreen = ConfigManager.sFullscreen && !ForceNonExclusive;
  746.  
  747.                 if (wasFullscreen && !IsFullscreen)
  748.                     ForcefullyLeaveExclusiveFullscreen();
  749.  
  750.                 bool wasHighRes = UseHighResolutionSprites;
  751.  
  752.                 if (width > 0 && height > 0)
  753.                 {
  754.                     //if width and height are specified, we should use them.
  755.                     WindowManager.Width = width.Value;
  756.                     WindowManager.Height = height.Value;
  757.  
  758.                     if (saveToConfig)
  759.                     {
  760.                         if (ConfigManager.sFullscreen)
  761.                         {
  762.                             ConfigManager.sWidthFullscreen.Value = WindowManager.Width;
  763.                             ConfigManager.sHeightFullscreen.Value = WindowManager.Height;
  764.                         }
  765.                         else
  766.                         {
  767.                             ConfigManager.sWidth.Value = WindowManager.Width;
  768.                             ConfigManager.sHeight.Value = WindowManager.Height;
  769.                         }
  770.                     }
  771.                 }
  772.                 else
  773.                 {
  774.                     if (ConfigManager.sFullscreen)
  775.                     {
  776.                         WindowManager.Width = ConfigManager.sWidthFullscreen;
  777.                         WindowManager.Height = ConfigManager.sHeightFullscreen;
  778.                     }
  779.                     else
  780.                     {
  781.                         WindowManager.Width = ConfigManager.sWidth;
  782.                         WindowManager.Height = ConfigManager.sHeight;
  783.                     }
  784.  
  785.                     if (WindowManager.Width == 9999 || WindowManager.Height == 9999)
  786.                     {
  787.                         //A fresh config file. Set some sane defaults based on the environment.
  788.                         if (ConfigManager.sFullscreen)
  789.                         {
  790.                             Size s = ResolutionHelper.FindNativeResolution();
  791.                             WindowManager.Width = ConfigManager.sWidthFullscreen.Value = s.Width;
  792.                             WindowManager.Height = ConfigManager.sHeightFullscreen.Value = s.Height;
  793.                         }
  794.                         else
  795.                         {
  796.                             WindowManager.Width = ConfigManager.sWidth.Value = InitialDesktopResolution.Width;
  797.                             WindowManager.Height = ConfigManager.sHeight.Value = InitialDesktopResolution.Height;
  798.                         }
  799.                     }
  800.                 }
  801.  
  802.                 if (ConfigManager.sLetterboxing && (WindowManager.Width > InitialDesktopResolution.Width || WindowManager.Height > InitialDesktopResolution.Height))
  803.                 {
  804.                     ConfigManager.sLetterboxing.Value = false;
  805.                     return; // Changing the letterboxing setting will invoke SetScreenSize again, thus we can abort here.
  806.                 }
  807.  
  808.                 if (ConfigManager.sFullscreen && !ConfigManager.sLetterboxing)
  809.                 {
  810.                     //check whether the full screen resolution we are about to enter is supported
  811.                     if (!ResolutionHelper.ChangeResolution(WindowManager.Width, WindowManager.Height, CustomRefreshRate, true))
  812.                     {
  813.                         NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.GameBase_ResolutionChangeFailed));
  814.                         ConfigManager.sOverrideRefreshRate.Value = false;
  815.  
  816.                         if (!ResolutionHelper.ChangeResolution(WindowManager.Width, WindowManager.Height, null, true))
  817.                         {
  818.                             ConfigManager.sWidthFullscreen.Value = WindowManager.Width = InitialDesktopResolution.Width;
  819.                             ConfigManager.sHeightFullscreen.Value = WindowManager.Height = InitialDesktopResolution.Height;
  820.                         }
  821.                     }
  822.                 }
  823.  
  824.                 WindowManager.Height -= MenuHeight;
  825.  
  826.                 //limit the aspect ratio from being too square (just causes breaking).
  827.                 if (WindowManager.Height > WindowManager.Width * 0.8f) WindowManager.Height = (int)(WindowManager.Width * 0.8f);
  828.  
  829.                 if (!IsFullscreen && AeroGlassHelper.DesktopCompositionEnabled)
  830.                 {
  831.                     Scheduler.AddDelayed(delegate
  832.                     {
  833.                         AeroGlassHelper.DisableGlass(Form);
  834.                         AeroGlassHelper.EnableGlass(Form);
  835.                     }, 250);
  836.                 }
  837.  
  838.                 NativeText.ClearFontCache();
  839.  
  840.                 InputManager.TextInput.Location = new System.Drawing.Point((int)(WindowManager.Width * 0.015), WindowManager.Height - (int)(WindowManager.Height * 0.052) + 2000);
  841.                 foreach (TextInputControl c in InputManager.TextInputControls)
  842.                     c.SetLocation();
  843.  
  844.                 SkinManager.PrepareSliderRenderer();
  845.  
  846.                 if (LastMode != OsuModes.Unknown && UseHighResolutionSprites != wasHighRes)
  847.                     TextureManager.Reload();
  848.  
  849.                 if (EditorControl != null)
  850.                     EditorControl.Width = GameBase.InitialDesktopResolution.Width;
  851.  
  852.                 if (s_fadeScreen != null)
  853.                     s_fadeScreen.VectorScale = new Vector2(WindowManager.Width, WindowManager.Height);
  854.  
  855.                 GameField.Resize(GameBase.GameField.ScaleFactor, true);
  856.  
  857.                 WindowRectangle = new Rectangle(-1 + WindowManager.NonWidescreenOffsetX, -1, WindowManager.Width - WindowManager.NonWidescreenOffsetX * 2 + 1, WindowManager.Height + 1);
  858.                 WindowRectangleWidescreen = new Rectangle(-1, -1, WindowManager.Width + 1, WindowManager.Height + 1);
  859.  
  860.                 SpriteManager.ViewRectangleCurrent.Width = (int)Math.Ceiling(WindowManager.Width / WindowManager.Ratio);
  861.  
  862. #if !Public
  863.                 if (testBuildOverlay != null)
  864.                     testBuildOverlay.VectorScale.X = Math.Max(1, (GameBase.WindowManager.Width / GameBase.WindowManager.RatioInverse) / testBuildOverlay.DrawWidth);
  865. #endif
  866.  
  867.                 UpdateDesktopResolution();
  868.  
  869.                 if (chatEngine != null) ChatEngine.OnResolutionChange();
  870.  
  871.                 ResizeGL(ForceNonExclusive);
  872.  
  873.                 if (OnResolutionChange != null)
  874.                     OnResolutionChange();
  875.             }
  876.             catch
  877.             {
  878.                 ResizeGL(ForceNonExclusive);
  879.                 throw;
  880.             }
  881.         }
  882.  
  883.  
  884.         private static int? CustomRefreshRate
  885.         {
  886.             get
  887.             {
  888.                 if (ConfigManager.sOverrideRefreshRate.Value)
  889.                     return ConfigManager.sRefreshRate.Value;
  890.                 else
  891.                     return null;
  892.             }
  893.         }
  894.  
  895.  
  896.         internal static void LetterboxPosition_ValueChanged(object sender, EventArgs e)
  897.         {
  898.             if (ConfigManager.sLetterboxing)
  899.             {
  900.                 OsuGlControl.ResetViewport();
  901.                 UpdateClientBounds();
  902.             }
  903.         }
  904.  
  905.         private static void ResizeGL(bool forceNonExclusive)
  906.         {
  907.             //temporary hack to avoid running fullscreen when in editor
  908.             int adjust = forceNonExclusive && !OsuGlControl.UsesAngle ? 1 : 0;
  909.  
  910.             if (ConfigManager.sLetterboxing)
  911.                 clientSize = new Size(InitialDesktopResolution.Width, InitialDesktopResolution.Height);
  912.             else
  913.                 clientSize = new Size(WindowManager.Width, WindowManager.Height + MenuHeight);
  914.  
  915.             // This prevents exclusive fullscreen when we want to set a resolution equal to the current desktop resolution.
  916.             Size currentResolution = ResolutionHelper.GetDesktopResolution();
  917.             if (clientSize.Width == currentResolution.Width && clientSize.Height == currentResolution.Height)
  918.             {
  919.                 clientSize.Height += adjust;
  920.                 ClientSizeAdjustment = adjust;
  921.             }
  922.             else
  923.             {
  924.                 ClientSizeAdjustment = 0;
  925.             }
  926.  
  927.             UpdateWindowBorders();
  928.  
  929.             OsuGlControl.ResetViewport();
  930.  
  931.             UpdateClientBounds();
  932.  
  933.             Form.ClientSize = clientSize;
  934.  
  935.             if (!GameBase.Tournament)
  936.             {
  937.                 if (IsFillingScreen)
  938.                     Form.Location = InitialDesktopLocation;
  939.                 else if (Time == 0 || pendingScreenModeChange != null)
  940.                     //Center if this is the first initialized screen change, or a screen mode change is pending
  941.                     Form.CentreToScreen();
  942.             }
  943.  
  944.             Form.Invalidate();
  945.         }
  946.  
  947.  
  948.         private static void UpdateWindowBorders()
  949.         {
  950.             if (IsFillingScreen)
  951.                 Form.FormBorderStyle = FormBorderStyle.None;
  952.             else if (!Tournament)
  953.                 Form.FormBorderStyle = FormBorderStyle.FixedSingle;
  954.         }
  955.  
  956.         private static void UpdateDesktopResolution()
  957.         {
  958.             if (ConfigManager.sFullscreen && !ConfigManager.sLetterboxing)
  959.                 ResolutionHelper.ChangeResolution(WindowManager.Width, WindowManager.Height + MenuHeight, CustomRefreshRate);
  960.             else
  961.                 ResolutionHelper.ResetResolution();
  962.  
  963.             RefreshRate = ResolutionHelper.GetCurrentRefreshRate();
  964.         }
  965.  
  966.         internal static int GetTime(Clocks clock)
  967.         {
  968.             switch (clock)
  969.             {
  970.                 case Clocks.Audio:
  971.                 case Clocks.AudioOnce:
  972.                     return AudioEngine.Time;
  973.                 case Clocks.Game:
  974.                     return Time;
  975.             }
  976.  
  977.             return 0;
  978.         }
  979.  
  980.         internal static string ClientHash;
  981.  
  982.         protected override void Initialize()
  983.         {
  984.             if (!string.IsNullOrEmpty(ConfigManager.sUsername.Value))
  985.                 Logger.UserIdentifier = ConfigManager.sUsername.Value;
  986.             Logger.VersionIdentifier = General.BUILD_NAME;
  987.  
  988.             OsuGlControl.InitializedEvent.WaitOne(5000);
  989.  
  990.             InitializeGl();
  991.  
  992.             LineBatch = new PrimitiveBatch(BeginMode.Lines);
  993.             WhitePixel = pTexture.FromRawBytes(new byte[] { 255, 255, 255, 255 }, 1, 1);
  994.             LineManager = new LineManager();
  995.  
  996. #if DEBUG
  997.             if (!Tournament || TournamentManager)
  998.             {
  999.                 OnScreenDisplay = new OnScreenDisplay();
  1000.             }
  1001.             Debug.Print(@"Running on " + Environment.OSVersion);
  1002.             Debug.Print(@"Graphics mode: " + GlControl.GraphicsMode);
  1003. #endif
  1004.  
  1005.             //Tourney Initialisation
  1006.             if (Tournament)
  1007.             {
  1008.                 General.SUBVERSION = @"tourney";
  1009.  
  1010.                 AudioEngine.VolumeMaster.Value = 35;
  1011.                 AudioEngine.VolumeMusic.Value = TournamentManager ? 100 : 0;
  1012.                 AudioEngine.VolumeEffect.Value = TournamentClientId == 0 ? 100 : 0;
  1013.  
  1014.                 Form.FormBorderStyle = FormBorderStyle.None;
  1015.                 string tourneyServer = GameModes.Other.Tournament.Tournament.Config.GetValue(@"privateserver", string.Empty);
  1016.                 if (!string.IsNullOrEmpty(tourneyServer))
  1017.                     BanchoClient.SetServer(new[] { tourneyServer });
  1018.  
  1019.                 Scheduler.Add(delegate
  1020.                 {
  1021.                     Form.StartPosition = FormStartPosition.Manual;
  1022.                     if (TournamentManager)
  1023.                     {
  1024.                         Form.Location = new System.Drawing.Point(0, 0);
  1025.                     }
  1026.                     else
  1027.                     {
  1028.                         Vector2 pos = TournamentLayout.ClientPositions[TournamentClientId];
  1029.                         Form.Location = new System.Drawing.Point((int)pos.X, (int)pos.Y);
  1030.                     }
  1031.                 }, true);
  1032.             }
  1033.  
  1034.             startupThreadOperation = RunBackgroundThread(delegate
  1035.             {
  1036.                 if (!Tournament)
  1037.                 {
  1038.                     CheckFilePermissions();
  1039.                     HandleRegistryAssociations(false);
  1040.                     Screensaver.Disable();
  1041.                 }
  1042.  
  1043.                 IPC.AcceptConnections(IpcChannelName);
  1044.             });
  1045.  
  1046.             BackgroundAppDetector = new BackgroundAppDetector();
  1047.             BackgroundAppDetector.AllowBackgroundExecution = ConfigManager.sDetectPerformanceIssues;
  1048.             BackgroundAppDetector.OnNewAppDetection += delegate (BackgroundAppDetector.AppDetection app)
  1049.             {
  1050.                 NotificationManager.ShowMessage(string.Format(LocalisationManager.GetString(OsuString.GameBase_DetectedBackgroundApp), app.AppName), Color.Orange, 10000);
  1051.             };
  1052.             BackgroundAppDetector.Start();
  1053.  
  1054.             DataStoreUpdater = new DataStoreUpdater();
  1055.  
  1056.             NewGraphicsAvailable = File.Exists(@"osu!gameplay.dll") && File.Exists(@"osu!ui.dll");
  1057.  
  1058.             NativeText.Initialize();
  1059.  
  1060.             Player.Mode = SongSelection.LastSelectMode;
  1061.  
  1062.             UpdateScreenDevice();
  1063.  
  1064.             Window.ScreenDeviceNameChanged += Window_ScreenDeviceNameChanged;
  1065.             Form.LocationChanged += OnLocationChanged;
  1066.             Form.SizeChanged += OnLocationChanged;
  1067.             Form.ResizeEnd += OnLocationChanged;
  1068.             Form.Activated += OnLocationChanged;
  1069.             Form.ClientSizeChanged += OnLocationChanged;
  1070.  
  1071.  
  1072.             SystemResolutionWidth = Screen.PrimaryScreen.Bounds.Width;
  1073.             SystemResolutionHeight = Screen.PrimaryScreen.Bounds.Height;
  1074.  
  1075.             List<string> checkFiles = new List<string>()
  1076.             {
  1077.                 @"1812a3605d6a596a67b5f2250f82307d",
  1078.                 @"83d489cce95f15b275e480de15bafa88",
  1079.                 @"f3bf7a5f31a97c2e01dbfd88d49fdcb0",
  1080.                 @"80ea471ed63c89c4b7db3c3b70ee20a3"
  1081.             };
  1082.  
  1083.             try
  1084.             {
  1085.                 Directory.CreateDirectory(BeatmapManager.SongsDirectory);
  1086.  
  1087.                 string dataPath = Path.Combine(OsuMain.UserPath, @"Data");
  1088.                 Directory.CreateDirectory(dataPath);
  1089.                 Directory.CreateDirectory(Path.Combine(dataPath, @"r"));
  1090.                 Directory.CreateDirectory(Path.Combine(dataPath, @"a"));
  1091.  
  1092.                 GeneralHelper.FileDelete(@"error_update.txt");
  1093.                 GeneralHelper.FileDelete(@"update_log.txt");
  1094.                 GeneralHelper.FileDelete(@"update_log_success.txt");
  1095.                 GeneralHelper.FileDelete(@".gl_compatible");
  1096.  
  1097.                 if (!OsuMain.IsWine)
  1098.                 {
  1099.                     if (!File.Exists(Path.Combine(OsuMain.UserPath, @"osu!.exe")))
  1100.                     {
  1101.                         //user's UserPath is in a different location from the osu! executable install.
  1102.                         //make sure we have a shortcut to osu!
  1103.  
  1104.                         string runShortcut = Path.Combine(OsuMain.UserPath, @"start osu!.lnk");
  1105.                         if (!File.Exists(runShortcut)) ShellLinkHelper.Create(runShortcut, Path.Combine(Environment.CurrentDirectory, @"osu!.exe"), @"osu!");
  1106.                     }
  1107.  
  1108.                     string repairShortcut = Path.Combine(OsuMain.UserPath, @"repair osu!.lnk");
  1109.                     if (!File.Exists(repairShortcut)) ShellLinkHelper.Create(repairShortcut, Path.Combine(Environment.CurrentDirectory, @"osu!.exe"), @"repair osu!", @"-config");
  1110.                 }
  1111.  
  1112.                 try
  1113.                 {
  1114.                     List<string> files = new List<string>();
  1115.  
  1116.                     files.AddRange(Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)));
  1117.                     files.AddRange(Directory.GetDirectories(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)));
  1118.  
  1119.                     foreach (string s in files)
  1120.                     {
  1121.                         if (checkFiles.Contains(CryptoHelper.GetMd5String(@"osu!" + Path.GetFileName(s).ToLower())))
  1122.                             checkFilesMatched = true;
  1123.                     }
  1124.                 }
  1125.                 catch { }
  1126.             }
  1127.             catch { }
  1128.  
  1129.             PerformanceMonitor = new PerformanceMonitor();
  1130.  
  1131.             BeatmapManager.Initialize();
  1132.             InputManager.Initialize();
  1133.  
  1134.             spriteManagerOverlay = new SpriteManager(true);
  1135.             spriteManagerOverlay.HandleOverlayInput = true;
  1136.  
  1137.             spriteManagerOverlayHighest = new SpriteManager(true);
  1138.             spriteManagerOverlayHighest.HandleOverlayInput = true;
  1139.  
  1140.             spriteManagerTransition = new SpriteManager(true);
  1141.  
  1142.             spriteManager = new SpriteManager();
  1143.             spriteManagerCursor = new SpriteManager(true) { HandleInput = false };
  1144.             cursorTrailRenderer = new CursorTrailRenderer();
  1145.             spriteManagerHighest = new SpriteManager(true);
  1146.  
  1147.             if (Tournament)
  1148.             {
  1149.                 TourneySpectatorName = new pText(string.Empty, TournamentClientManager.ClientNameSize * TournamentLayout.ClientSizeRatio, new Vector2(3, 3), 1, true, Color.Yellow);
  1150.                 TourneySpectatorName.FontFace = FontFace.ExoMedium;
  1151.                 TourneySpectatorName.Field = Fields.TopLeft;
  1152.                 TourneySpectatorName.Origin = Origins.TopLeft;
  1153.                 TourneySpectatorName.TextShadow = true;
  1154.                 TourneySpectatorName.TextBold = true;
  1155.                 TourneySpectatorName.OnRefreshTexture += delegate { TourneySpectatorName.Alpha = 1; };
  1156.                 spriteManagerOverlayHighest.Add(TourneySpectatorName);
  1157.             }
  1158.  
  1159.             s_fadeScreen = new pSprite(WhitePixel, Fields.Native, Origins.TopLeft, Clocks.Game, Vector2.Zero, 0, true, Color.Black);
  1160.  
  1161. #if !Public
  1162.             if (!Tournament)
  1163.             {
  1164.                 testBuildOverlay = new pSprite(TextureManager.Load(@"test-build-overlay", SkinSource.Osu), Fields.BottomRight, Origins.BottomRight, Clocks.Game, Vector2.Zero, 1, true, Color.White);
  1165.  
  1166.                 spriteManagerOverlayHighest.Add(testBuildOverlay);
  1167.  
  1168.                 testBuildVersion = new pText(General.BUILD_NAME, 14, new Vector2(0, 0), 0.99f, true, Color.White);
  1169.                 testBuildVersion.TextShadow = true;
  1170.                 testBuildVersion.Alpha = 0.4f;
  1171.                 testBuildVersion.Field = Fields.BottomCentre;
  1172.                 testBuildVersion.Origin = Origins.BottomCentre;
  1173.                 testBuildVersion.TextRenderSpecific = false;
  1174.                 spriteManagerOverlayHighest.Add(testBuildVersion);
  1175.             }
  1176. #endif
  1177.  
  1178.             SetScreenSize();
  1179.  
  1180.             SkinManager.Initialize();
  1181.             AudioEngine.Initialize();
  1182.  
  1183.             TransitionManager = new TransitionManager();
  1184.  
  1185.             BanchoStatus = new BanchoStatusOverlay();
  1186.  
  1187.             spriteManagerTransition.Add(s_fadeScreen);
  1188.  
  1189.             float scale = DpiHelper.DPI(GameBase.Form) / 96.0f;
  1190.             ToolTip = new pTooltip(string.Empty, 11, Vector2.Zero, Vector2.Zero, 1, true, Color.White, false);
  1191.             spriteManagerHighest.Add(ToolTip);
  1192.  
  1193.             Options = new Options(this);
  1194.  
  1195.             FpsDisplay = new FpsDisplay(PerformanceMonitor);
  1196.  
  1197.             osuDirect = new OsuDirect(this);
  1198.             osuDirect.Initialize();
  1199.  
  1200.             chatEngine = new ChatEngine(this);
  1201.             chatEngine.Initialize();
  1202.  
  1203.             Volume = new VolumeControlSet();
  1204.  
  1205.             //Coins = new CoinsOverlay();
  1206.  
  1207.             MusicControl = new MusicControl(this);
  1208.             MusicControl.Initialize();
  1209.  
  1210. #if Local
  1211.             if (!IsFirstInstance)
  1212.                 ConfigManager.sUsername.Value = "General Pepper";
  1213.             else
  1214.                 ConfigManager.sUsername.Value = "peppy";
  1215. #endif
  1216.  
  1217.             User = new User(ConfigManager.sUsername);
  1218.             User.DrawAt(new Vector2(0, 0), false, 0);
  1219.  
  1220. #if !ARCADE
  1221.             //For the time being let's make this not clickable for arcade.  Not sure whether this is required, though.
  1222.             User.Clickable = true;
  1223.             User.Sprites[0].KeepEventsBound = true;
  1224.             User.Sprites[0].OnClick += ShowLocalUserOptions;
  1225. #endif
  1226.  
  1227.             BanchoClient.Start();
  1228.  
  1229.             OsuModes gs = ReceiveFile(StartupNewFiles);
  1230.  
  1231.             QueuedMode = gs != OsuModes.Unknown ? gs : QueuedMode;
  1232.  
  1233.             if (BenchmarkMode)
  1234.             {
  1235.                 BeatmapManager.Current = BeatmapManager.Beatmaps.Find(b => b.PlayMode == PlayModes.Osu);
  1236.                 ModManager.ModStatus |= Mods.Autoplay;
  1237.                 //ModManager.ModDoubleTime = true;
  1238.                 QueuedMode = OsuModes.Play;
  1239.             }
  1240.  
  1241. #if DEBUG
  1242.             InitializeTester();
  1243. #endif
  1244.  
  1245.             FadeState = FadeStates.WaitingLoad;
  1246.             loadQueuedMode();
  1247.  
  1248.             IdleHandler.Initialize();
  1249.  
  1250. #if P2P
  1251.             //activate P2P system
  1252.             Osup2pManager.Initialize(new P2PSettings());
  1253.             Osup2pManager.Activate();
  1254.             //Osup2pManager.LoadMagnet("3oh!3 - I Can't Do It Alone.osz2.osuMagnet");
  1255. #endif
  1256.  
  1257.             BringToFront();
  1258.  
  1259.             base.Initialize();
  1260.  
  1261.             if (!string.IsNullOrEmpty(ConfigManager.sLastVersion))
  1262.             {
  1263.                 ConfigManager.sUpdateFailCount.Value = 0;
  1264.  
  1265.                 if (ConfigManager.sLastVersion != General.BUILD_NAME)
  1266.                 {
  1267.                     SetUpdateState(UpdateStates.Completed);
  1268.                 }
  1269.                 else if (ConfigManager.sUpdatePending)
  1270.                 {
  1271.                     SetUpdateState(UpdateStates.Completed);
  1272.                 }
  1273.             }
  1274.  
  1275.             ConfigManager.sLastVersion.Value = General.BUILD_NAME;
  1276.  
  1277.             ConfigManager.dDisableFBO?.TriggerChange();
  1278.             ConfigManager.dDisableVBO?.TriggerChange();
  1279.  
  1280.             stopWatch.Start();
  1281.  
  1282.             BeatmapImport.Start();
  1283.         }
  1284.  
  1285.         private static void UpdateScreenDevice()
  1286.         {
  1287.             Screen currentScreen = Screen.FromHandle(Instance.Window.Handle);
  1288.             string displayName = currentScreen.DeviceName;
  1289.  
  1290.             try
  1291.             {
  1292.                 ConfigManager.sDisplay.Value = Int32.Parse(displayName[displayName.Length - 1].ToString());
  1293.                 Debug.Print("Changed to monitor #" + ConfigManager.sDisplay.Value + " ( " + displayName + " )");
  1294.             }
  1295.             catch
  1296.             {
  1297.             }
  1298.  
  1299.             UpdateDesktopProperties();
  1300.         }
  1301.  
  1302.  
  1303.         internal static void UpdateDesktopProperties(bool force = false)
  1304.         {
  1305.             RefreshRate = ResolutionHelper.GetCurrentRefreshRate();
  1306.  
  1307.             //Find the current desktop parameters. If we are fullscreen, then we might have changed the desktop resolution, so we may not change these parameters under any circumstances.
  1308.             if ((!ConfigManager.sFullscreen && !IsFullscreen) || force)
  1309.             {
  1310.                 InitialDesktopResolution = ResolutionHelper.GetDesktopResolution();
  1311.                 InitialDesktopLocation = ResolutionHelper.GetDesktopPosition();
  1312.                 InitialRefreshRate = RefreshRate;
  1313.  
  1314.                 if (Options != null)
  1315.                     Options.UpdateResolutions();
  1316.             }
  1317.         }
  1318.  
  1319.         private static string createUniqueCheck()
  1320.         {
  1321.             return CryptoHelper.GetMd5String(UniqueId + 0x08 + 0x200 + UniqueId2);
  1322.         }
  1323.  
  1324.         internal static string CreateUniqueId()
  1325.         {
  1326.             try
  1327.             {
  1328.                 string guid = Uninstaller.GetUninstallId().ToString();
  1329.                 UniqueId.Value = CryptoHelper.GetMd5String(guid);
  1330.             }
  1331.             catch { }
  1332.  
  1333.             try
  1334.             {
  1335.                 UniqueId2.Value = CryptoHelper.GetMd5String(identifier("Win32_DiskDrive", "Signature", "SerialNumber"));
  1336.             }
  1337.             catch { }
  1338.  
  1339.             UniqueId2.allowDestruction = false;
  1340.             UniqueId.allowDestruction = false;
  1341.  
  1342.             UniqueCheck.Value = createUniqueCheck();
  1343.  
  1344.             return UniqueId + @"|" + UniqueId2;
  1345.         }
  1346.  
  1347.         internal static bool CheckUniqueId()
  1348.         {
  1349.             if (GameBase.Time == 0) return true;
  1350.             return createUniqueCheck() == UniqueCheck.Value && UniqueId.c <= 3 + ChangeAllowance && UniqueId2.c <= 3 + ChangeAllowance;
  1351.         }
  1352.  
  1353.         internal static string identifier(string wmiClass, params string[] wmiProperty)
  1354.         //Return a hardware identifier
  1355.         {
  1356.             try
  1357.             {
  1358.                 System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass);
  1359.                 System.Management.ManagementObjectCollection moc = mc.GetInstances();
  1360.                 foreach (System.Management.ManagementObject mo in moc)
  1361.                 {
  1362.                     foreach (string w in wmiProperty)
  1363.                     {
  1364.                         try
  1365.                         {
  1366.                             object o = mo[w];
  1367.                             if (o == null)
  1368.                                 continue;
  1369.  
  1370.                             return mo[w].ToString();
  1371.                         }
  1372.                         catch
  1373.                         {
  1374.                         }
  1375.                     }
  1376.                 }
  1377.             }
  1378.             catch { }
  1379.  
  1380.             return string.Empty;
  1381.         }
  1382.  
  1383.         internal static void BringToFront()
  1384.         {
  1385.             Form.BringToFront();
  1386.             SetForegroundWindow(Form.Handle);
  1387.         }
  1388.  
  1389.         /// <summary> The RegisterHotKey function defines a system-wide hot key </summary>
  1390.         /// <param name="hwnd">Handle to the window that will receive WM_HOTKEY messages
  1391.         /// generated by the hot key.</param>
  1392.         /// <param name="id">Specifies the identifier of the hot key.</param>
  1393.         /// <param name="fsModifiers">Specifies keys that must be pressed in combination with the key
  1394.         /// specified by the 'vk' parameter in order to generate the WM_HOTKEY message.</param>
  1395.         /// <param name="vk">Specifies the virtual-key code of the hot key</param>
  1396.         /// <returns><c>true</c> if the function succeeds, otherwise <c>false</c></returns>
  1397.         /// <seealso cref="http://msdn.microsoft.com/en-us/library/ms646309(VS.85).aspx"/>
  1398.         [DllImport(@"user32.dll", SetLastError = true)]
  1399.         [return: MarshalAs(UnmanagedType.Bool)]
  1400.         static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
  1401.  
  1402.         #region fields
  1403.         private static int MOD_ALT = 0x1;
  1404.         private static int MOD_CONTROL = 0x2;
  1405.         private static int MOD_SHIFT = 0x4;
  1406.         private static int MOD_WIN = 0x8;
  1407.         private static int WM_HOTKEY = 0x312;
  1408.         #endregion
  1409.  
  1410.         private static void OnLocationChanged(object sender, EventArgs e)
  1411.         {
  1412.             UpdateClientBounds();
  1413.         }
  1414.  
  1415.         private static void UpdateClientBounds()
  1416.         {
  1417.             System.Drawing.Rectangle actualViewport = new System.Drawing.Rectangle(OsuGlControl.Viewport.Left, clientSize.Height - OsuGlControl.Viewport.Bottom, OsuGlControl.Viewport.Width, OsuGlControl.Viewport.Height);
  1418.             ClientBounds = Form.RectangleToScreen(actualViewport);
  1419.         }
  1420.  
  1421.         internal static Point ViewportOffset
  1422.         {
  1423.             get
  1424.             {
  1425.                 return new Point(OsuGlControl.Viewport.Left, clientSize.Height - OsuGlControl.Viewport.Bottom);
  1426.             }
  1427.         }
  1428.  
  1429.  
  1430.         internal static bool MouseVisible = true;
  1431.  
  1432.         internal static void HandleRegistryAssociations(bool runningElevated)
  1433.         {
  1434.             //ensure we only run this operation once before release (in the case it is actually run).
  1435.             if (!runningElevated && ConfigManager.sLastVersionPermissionsFailed.Value == General.BUILD_NAME)
  1436.                 return;
  1437.  
  1438.             bool success = true;
  1439.  
  1440.             //make sure we've initialised our uniqueId here.
  1441.             if (Uninstaller.GetUninstallId() == Guid.Empty)
  1442.                 success = false;
  1443.  
  1444.             if (!GeneralHelper.RegistryCheck("osu!", OsuMain.FullPath))
  1445.             {
  1446.                 success &= GeneralHelper.RegistryAdd("osz", "osu!", "osu! beatmap", OsuMain.FullPath);
  1447.                 if (success) success &= GeneralHelper.RegistryAdd("osz2", "osu!", "osu! beatmap v2", OsuMain.FullPath);
  1448.                 if (success) success &= GeneralHelper.RegistryAdd("osr", "osu!", "osu! replay", OsuMain.FullPath);
  1449.                 if (success) success &= GeneralHelper.RegistryAdd("osk", "osu!", "osu! skin", OsuMain.FullPath);
  1450.  
  1451.                 if (Registry.ClassesRoot.GetValue(string.Empty, string.Empty).ToString() == "osu") Registry.ClassesRoot.DeleteValue(string.Empty, false);
  1452.             }
  1453.  
  1454.             if (!GeneralHelper.RegistryCheck("osu", OsuMain.FullPath) && !GeneralHelper.RegistryAdd(string.Empty, "osu", "osu! url handler", OsuMain.FullPath, true))
  1455.                 success = false;
  1456.  
  1457.             if (!Uninstaller.CreateUninstaller())
  1458.                 success = false;
  1459.  
  1460.             if (!success && !runningElevated)
  1461.             {
  1462.                 GameBase.SetPermissions(true);
  1463.                 ConfigManager.sLastVersionPermissionsFailed.Value = General.BUILD_NAME;
  1464.             }
  1465.  
  1466.         }
  1467.  
  1468.         /// <summary>
  1469.         /// Permission test for vista crap shit fuck.
  1470.         /// </summary>
  1471.         private static void CheckFilePermissions()
  1472.         {
  1473.             OperatingSystem osInfo = Environment.OSVersion;
  1474.             if (osInfo.Platform != PlatformID.Win32NT || osInfo.Version.Major != 6)
  1475.                 return;
  1476.             try
  1477.             {
  1478.                 Directory.CreateDirectory(".test");
  1479.                 Directory.Delete(".test");
  1480.             }
  1481.             catch (Exception)
  1482.             {
  1483.                 SetPermissions(false);
  1484.                 try
  1485.                 {
  1486.                     Directory.Delete(".test");
  1487.                 }
  1488.                 catch { }
  1489.             }
  1490.         }
  1491.  
  1492.         internal static void SetPermissions(bool registryOnly)
  1493.         {
  1494.             if (!OsuMain.IsElevated)
  1495.             {
  1496.                 Scheduler.AddDelayed(() =>
  1497.                 {
  1498.                     bool didPause = AudioEngine.PauseAudioTrackIfPlaying();
  1499.                     RunNonExclusive(() => { OsuMain.Elevate(registryOnly ? "-setassociations" : "-setpermissions", true); });
  1500.                     if (didPause) AudioEngine.TogglePause();
  1501.                 }, Math.Max(500, (Menu.IntroLength + 500) - GameBase.Time));
  1502.  
  1503.                 return;
  1504.             }
  1505.  
  1506.             GameBase.HandleRegistryAssociations(true);
  1507.  
  1508.             if (registryOnly) return;
  1509.  
  1510.             OsuMain.SetDirectoryPermissions();
  1511.         }
  1512.  
  1513.         private void InitializeGl()
  1514.         {
  1515.             GlControl.InitializeGl();
  1516.             TextureGlSingle.Initialize();
  1517.  
  1518.             clientSize = Form.ClientSize;
  1519.  
  1520.             if (ConfigManager.sShaders && !ShaderManager.CanUseShaders)
  1521.                 ConfigManager.sShaders.Value = false;
  1522.         }
  1523.  
  1524.         private void Window_ScreenDeviceNameChanged(object sender, EventArgs e)
  1525.         {
  1526.             UpdateScreenDevice();
  1527.         }
  1528.  
  1529.         //todo: this can be optimised
  1530.         internal static bool HasLogin { get { return !string.IsNullOrEmpty(ConfigManager.sPassword) && !string.IsNullOrEmpty(ConfigManager.sUsername); } }
  1531.  
  1532.         internal static void ShowLocalUserOptions(object sender, EventArgs e)
  1533.         {
  1534.             if (!GameBase.HasLogin)
  1535.                 ShowLogin();
  1536.             else
  1537.                 UserProfile.DisplayProfileFor(User, false);
  1538.         }
  1539.  
  1540.         /// <summary>
  1541.         /// We are running in the background or during a period where we should be favouring other threads.
  1542.         /// </summary>
  1543.         internal static bool CanRunSlowly
  1544.         {
  1545.             get
  1546.             {
  1547.                 return (IsMinimized || MenuActive || (!Instance.IsActive && !Tournament) || BackgroundLoading) && !Player.Playing && !InputManager.ReplayStreaming && !InputManager.ReplayMode;
  1548.             }
  1549.         }
  1550.  
  1551.         protected override void Update()
  1552.         {
  1553.             PerformanceMonitor.EndCollecting(FrameTimeType.BetweenFrames);
  1554.  
  1555. #if !DEBUG
  1556.             try
  1557.             {
  1558. #endif
  1559.  
  1560.             PerformanceMonitor.BeginCollecting(FrameTimeType.Update);
  1561.  
  1562.             IsMinimized = Window.IsMinimized || (Window.ClientBounds.X < -10000 && Window.ClientBounds.Y < -10000);
  1563.  
  1564.             if (OnScreenDisplay != null) OnScreenDisplay.Update();
  1565.  
  1566.             PerformanceMonitor.BeginCollecting(FrameTimeType.Scheduler);
  1567.             Scheduler.Update();
  1568.             PerformanceMonitor.EndCollecting(FrameTimeType.Scheduler);
  1569.  
  1570.             updateWindowState();
  1571.  
  1572.             FpsDisplay.Update();
  1573.  
  1574.             chatEngine.Update();
  1575.             osuDirect.Update();
  1576.             MusicControl.Update();
  1577.  
  1578.             UpdateDialogQueue();
  1579.  
  1580.             bool oldBloomPass = BloomRenderer.ExtraPass;
  1581.             ChildrenUpdated = false;
  1582.             BloomRenderer.ExtraPass = false;
  1583.  
  1584.             UpdateFadeState();
  1585.  
  1586.             PhysicsManager.Update();
  1587.  
  1588.             BanchoStatus.Update();
  1589.  
  1590.             TransitionManager.Update();
  1591.  
  1592.             Options.Update();
  1593.  
  1594.             Volume.Update();
  1595.  
  1596.             if (Coins != null) Coins.Update();
  1597.  
  1598.             InputManager.UpdateFrame(() =>
  1599.             {
  1600.                 Components.ForEach(c => c.Update());
  1601.  
  1602.                 base.Update();
  1603.                 ChildrenUpdated = true;
  1604.             });
  1605.  
  1606.             cursorTrailRenderer.Update();
  1607.  
  1608.             if (!ChildrenUpdated)
  1609.                 //In the case children are not updated, we need to remember the bloom pass state.
  1610.                 //This happens when replays/auto are skipping frames (but we don't want the bloom pass to flicker during this).
  1611.                 BloomRenderer.ExtraPass = oldBloomPass;
  1612.  
  1613.  
  1614.             NotificationManager.Update();
  1615.             OsuTipManager.Update();
  1616.  
  1617.             SkinManager.Cleanup();
  1618.  
  1619.             InputManager.CheckTextInputFocus(false);
  1620.             UpdateSystemWideDisables();
  1621.  
  1622. #if !Release
  1623.             if (GameBase.BenchmarkMode && GameBase.Time > 120000)
  1624.                 BeginExit(false);
  1625. #endif
  1626.  
  1627. #if !DEBUG
  1628.             }
  1629.             catch (Exception e)
  1630.             {
  1631.                 if (ExceptionCount++ > 1 || Mode == OsuModes.Exit || QueuedMode == OsuModes.Exit)
  1632.                     throw;
  1633.                 softHandle(e);
  1634.             }
  1635. #endif
  1636.  
  1637. #if !Public
  1638.             if (testBuildOverlay != null && testBuildOverlay.Transformations.Count == 0)
  1639.             {
  1640.                 bool hide = Player.Playing || ChatEngine.IsVisible || InputManager.ReplayMode || ConfigManager.sFrameTimeDisplay;
  1641.                 bool hideText = hide || (Mode == OsuModes.Menu && Menu.titleImageUrl != null);
  1642.                 testBuildOverlay.MoveTo(new Vector2(0, hide ? -5 : 0), 500);
  1643.                 testBuildVersion.FadeTo(hideText ? 0 : 0.4f, 500);
  1644.             }
  1645. #endif
  1646.  
  1647.             if (Tournament && !TournamentManager)
  1648.             {
  1649.                 User u = StreamingManager.CurrentlySpectating;
  1650.  
  1651.                 TourneySpectatorName.Text = u == null ? string.Empty : u.Name;
  1652.  
  1653.                 if (GameBase.Time > 40000 && GameBase.Time - IPC.LastContact > 10000)
  1654.                     BeginExit();
  1655.             }
  1656.  
  1657.             if (Form.WindowState == FormWindowState.Maximized)
  1658.             {
  1659.                 //switch to borderless fullscreen.
  1660.                 Form.WindowState = FormWindowState.Normal;
  1661.                 SetScreenSize(InitialDesktopResolution.Width, InitialDesktopResolution.Height, true);
  1662.             }
  1663.  
  1664.             bool shallBeTopMost = TopMost;
  1665.             if (Form.TopMost != shallBeTopMost)
  1666.             {
  1667.                 Form.TopMost = shallBeTopMost;
  1668.             }
  1669.  
  1670.             SpriteManager handler = null;
  1671.             if (InputManager.HandleInput)
  1672.                 handler = SpriteManager.CheckInputGlobal();
  1673.  
  1674.             //update tooltip
  1675.             if (handler != null && handler.CurrentHoverSprite != null)
  1676.                 ToolTip.Text = handler.CurrentHoverSprite.ToolTip;
  1677.             else
  1678.                 ToolTip.Text = null;
  1679.  
  1680.             PerformanceMonitor.EndCollecting(FrameTimeType.Update);
  1681.         }
  1682.  
  1683.         private bool handleWindowedToggle = true;
  1684.         private void updateWindowState()
  1685.         {
  1686.             if (!IsFullscreen)
  1687.                 return;
  1688.  
  1689.             if (Time < 1000 || handleWindowedToggle)
  1690.             {
  1691.                 // The window should be active, let's keep forcing focus until it activates
  1692.                 if (IsActive)
  1693.                     handleWindowedToggle = false;
  1694.                 else if (!GLControl.ForcedWindowed)
  1695.                     Form.Focus();
  1696.                 return;
  1697.             }
  1698.  
  1699.             if (IsActive && GLControl.ForcedWindowed)
  1700.             {
  1701.                 // Enter fullscreen
  1702.                 GLControl.ToggleWindowed();
  1703.  
  1704.                 UpdateDesktopResolution();
  1705.  
  1706.                 bool forceNonExclusive = ForceNonExclusive;
  1707.                 ResizeGL(forceNonExclusive);
  1708.  
  1709.                 if (!forceNonExclusive)
  1710.                 {
  1711.                     // TopMost is already true at this point from the main loop, we however need to touch it again after changing the resolution so that windows understands.
  1712.                     Form.TopMost = true;
  1713.                 }
  1714.  
  1715.                 if (OsuGlControl.UsesAngle)
  1716.                 {
  1717.                     // D3D window will be unfocused upon device reset causing us to immediately fall through the !IsActive branch below. We don't want this so let's make sure the window
  1718.                     // is properly focused before that branch can be executed.
  1719.                     handleWindowedToggle = true;
  1720.                 }
  1721.             }
  1722.             else if (!IsActive && !GLControl.ForcedWindowed)
  1723.             {
  1724.                 // We need to enter the windowed state, but this is also handled inside ForcefullyLeaveExclusiveFullscreen() for Angle.
  1725.                 if (!OsuGlControl.UsesAngle)
  1726.                     GLControl.ToggleWindowed();
  1727.  
  1728.                 // We forcefully leave exclusive fullscreen mode, both when we want to minimize and when we don't want to. On some graphics hardware otherwise exclusive fullscreen
  1729.                 // won't be left on minimize, resulting in a frozen screen.
  1730.                 ForcefullyLeaveExclusiveFullscreen();
  1731.                 ResizeGL(true);
  1732.  
  1733.                 // We need to perform the minimization and resolution change delayed due to some hardware failing to leave exclusive fullscreen mode otherwise
  1734.                 GameBase.Scheduler.Add(() =>
  1735.                 {
  1736.                     if (OsuGlControl.UsesAngle || ConfigManager.sConfineMouse.Value > ConfineMouseMode.Never ||
  1737.                         clientSize.Width < InitialDesktopResolution.Width || clientSize.Height < InitialDesktopResolution.Height || RefreshRate != InitialRefreshRate)
  1738.                     {
  1739.                         Form.WindowState = FormWindowState.Minimized;
  1740.                     }
  1741.  
  1742.                     // This condition catches minimization via the boss key, too.
  1743.                     if (Form.WindowState == FormWindowState.Minimized)
  1744.                         ResolutionHelper.ResetResolution();
  1745.                 }, true);
  1746.             }
  1747.         }
  1748.  
  1749.         private static void UpdateDialogQueue()
  1750.         {
  1751.             if (DialogQueue.Count > 0 && ActiveDialog == null && (!Player.Playing || ChatEngine.Visibility == ChatVisibility.Full))
  1752.             {
  1753.                 TextInputControl tic = InputManager.GetActiveTextInputControl();
  1754.                 if (tic != null && tic.AcceptText)
  1755.                 {
  1756.                     ActiveDialogMutedTextControl = tic;
  1757.                     ActiveDialogMutedTextControl.AcceptText = false;
  1758.                 }
  1759.  
  1760.                 ActiveDialog = DialogQueue[0];
  1761.                 ActiveDialog.Display();
  1762.                 ActiveDialog.DisplayAfter();
  1763.                 ActiveDialog.Closed += dialog_Closed;
  1764.             }
  1765.  
  1766.             if (ActiveDialog != null)
  1767.                 ActiveDialog.Update();
  1768.         }
  1769.  
  1770.         /// <summary>
  1771.         /// Main time-keeping function. Handles different kinds of frame limiters and ensures constant velocity where required.
  1772.         /// </summary>
  1773.         private void UpdateTiming()
  1774.         {
  1775.             PerformanceMonitor.BeginCollecting(FrameTimeType.Sleep);
  1776.             double stopwatchTime = stopWatch.GetElapsedMillisecondsPrecise();
  1777.  
  1778.             double targetMilliseconds = FrameLimitMillisecondsPerFrame;
  1779.  
  1780.             int timeToSleepFloored = 0;
  1781.  
  1782.             //If we are limiting to a specific rate, and not enough time has passed for the next frame to be accepted we should pause here.
  1783.             if (targetMilliseconds > 0)
  1784.             {
  1785.                 if (stopwatchTime - TimeAccurate < targetMilliseconds)
  1786.                 {
  1787.                     // Using ticks for sleeping is pointless due to them being rounded to milliseconds internally anyways (in windows at least).
  1788.                     double timeToSleep = targetMilliseconds - (stopwatchTime - TimeAccurate);
  1789.                     timeToSleepFloored = (int)Math.Floor(timeToSleep);
  1790.  
  1791.                     Debug.Assert(timeToSleepFloored >= 0);
  1792.  
  1793.                     AccumulatedSleepError += timeToSleep - (double)timeToSleepFloored;
  1794.                     int accumulatedSleepErrorCompensation = (int)Math.Round(AccumulatedSleepError);
  1795.  
  1796.                     // Can't sleep a negative amount of time
  1797.                     accumulatedSleepErrorCompensation = Math.Max(accumulatedSleepErrorCompensation, -timeToSleepFloored);
  1798.  
  1799.                     AccumulatedSleepError -= accumulatedSleepErrorCompensation;
  1800.                     timeToSleepFloored += accumulatedSleepErrorCompensation;
  1801.  
  1802.                     // We don't want re-schedules with Thread.Sleep(0). We already have that case down below.
  1803.                     if (timeToSleepFloored > 0)
  1804.                         Thread.Sleep(timeToSleepFloored);
  1805.  
  1806.                     // Sleep is not guaranteed to be an exact time. It only guaranteed to sleep AT LEAST the specified time. We also used some time to compute the above things, so this is also factored in here.
  1807.                     double afterSleepTime = stopWatch.GetElapsedMillisecondsPrecise();
  1808.                     AccumulatedSleepError += (double)timeToSleepFloored - (afterSleepTime - stopwatchTime);
  1809.                     stopwatchTime = afterSleepTime;
  1810.                 }
  1811.                 else
  1812.                 {
  1813.                     // We use the negative spareTime to compensate for framerate jitter slightly.
  1814.                     double spareTime = (stopwatchTime - TimeAccurate) - targetMilliseconds;
  1815.                     AccumulatedSleepError = -spareTime;
  1816.                 }
  1817.             }
  1818.  
  1819.             // Call the scheduler to give lower-priority background processes a chance to do stuff.
  1820.             if (timeToSleepFloored == 0)
  1821.                 Thread.Sleep(0);
  1822.  
  1823.             TimeAccurateLastUpdate = TimeAccurate;
  1824.             TimeAccurate = stopwatchTime;
  1825.  
  1826.             Time = (int)Math.Round(TimeAccurate, 0);
  1827.  
  1828.             if (TimeAccurate - SixtyFrameLast >= SIXTY_FRAME_TIME || PendingModeChange)
  1829.             {
  1830.                 if (PendingModeChange || (!Player.IsSpinning && !Player.IsSliding && !InputManager.ReplayMode && (IsMinimized || !IsActive || Time - SixtyFrameLast > 500)))
  1831.                 {
  1832.                     //This is a kind of catch-up mode, where we ignore the fact 60fps frames haven't been handled
  1833.                     //and force the game back into sync. 500ms is arbitrary, but seems to work well.
  1834.  
  1835.                     SixtyFramesPerSecondLength = TimeAccurate - SixtyFrameLast;
  1836.                     SixtyFrameLast = TimeAccurate - SIXTY_FRAME_TIME;
  1837.                 }
  1838.                 else
  1839.                 {
  1840.                     SixtyFramesPerSecondLength = TimeAccurate - SixtyFrameLast;
  1841.                     SixtyFrameLast = TimeAccurate - (SixtyFramesPerSecondLength - SIXTY_FRAME_TIME);
  1842.                 }
  1843.  
  1844.                 SixtyFramesPerSecondFrame = true;
  1845.                 PendingModeChange = false;
  1846.             }
  1847.             else
  1848.                 SixtyFramesPerSecondFrame = false;
  1849.  
  1850.             ElapsedMilliseconds = TimeAccurate - TimeAccurateLastUpdate;
  1851.             FrameRatio = ElapsedMilliseconds / FrameAimTime;
  1852.             ModeTime += ElapsedMilliseconds;
  1853.             PerformanceMonitor.EndCollecting(FrameTimeType.Sleep);
  1854.         }
  1855.  
  1856.         private static void UpdateSystemWideDisables()
  1857.         {
  1858.             //Handle whether the screensaver should be disabled or not.
  1859.             //todo: run less frequently
  1860.             if (Instance.IsActive)
  1861.                 Screensaver.Disable();
  1862.             else
  1863.                 Screensaver.Restore();
  1864.  
  1865.             if (Instance.IsActive && Player.Playing && !InputManager.ReplayMode)
  1866.                 WindowsKey.Disable();
  1867.             else
  1868.                 WindowsKey.Enable();
  1869.         }
  1870.  
  1871. #if DEBUG
  1872.         internal static int AmountVBO = 0;
  1873.         internal static int AmountTextures = 0;
  1874. #endif
  1875.  
  1876.         private void UpdateFadeState()
  1877.         {
  1878.             if (FadeState != FadeStates.Idle || fadeLevel > 0)
  1879.             {
  1880.                 if (ConfigManager.sShaders && !s_fadeScreen.Bypass)
  1881.                 {
  1882.                     BloomRenderer.ExtraPass = true;
  1883.                     BloomRenderer.Magnitude = 0.004f;
  1884.                     BloomRenderer.Additive = false;
  1885.                     BloomRenderer.HiRange = false;
  1886.                     BloomRenderer.Alpha = OsuMathHelper.Clamp((float)fadeLevel, 0, 100) / 100;
  1887.                 }
  1888.  
  1889.                 if (FadeState == FadeStates.FadeIn)
  1890.                 {
  1891.                     if (fadeLevel <= 0)
  1892.                     {
  1893.                         FadeState = FadeStates.Idle;
  1894.                         if (FadeInComplete != null)
  1895.                             FadeInComplete(this, null);
  1896.                     }
  1897.                     else
  1898.                         fadeLevel = Math.Max(-1, fadeLevel - fadeInRate * FrameRatio);
  1899.                 }
  1900.                 else if (FadeState == FadeStates.FadeOut)
  1901.                 {
  1902.                     if (fadeLevel >= 100)
  1903.                     {
  1904.                         FadeState = FadeStates.WaitingLoad;
  1905.                         if (FadeOutComplete != null)
  1906.                             FadeOutComplete(this, null);
  1907.                     }
  1908.                     else
  1909.                     {
  1910.                         fadeLevel = Math.Min(100, fadeLevel + fadeOutRate * FrameRatio);
  1911.  
  1912.                         if (QueuedMode == OsuModes.Exit || QueuedMode == OsuModes.Update)
  1913.                         {
  1914.                             AudioEngine.SetVolumeMusicFade((int)(100 * Math.Pow(1 - fadeLevel / 100, 3)), true);
  1915.                             Form.Opacity = Math.Min(1, 3 - 3 * fadeLevel / 100);
  1916.                         }
  1917.                         else if (Mode == OsuModes.Play)
  1918.                         {
  1919.                             if (AudioEngine.volumeMusicFade > 50)
  1920.                                 AudioEngine.SetVolumeMusicFade(AudioEngine.volumeMusicFade - 1);
  1921.                         }
  1922.                         else
  1923.                             AudioEngine.SetVolumeMusicFade(AudioEngine.volumeMusicFade - 5);
  1924.                     }
  1925.                 }
  1926.             }
  1927.  
  1928. #if TRIANGLES
  1929.             spriteManagerTransition.Alpha = OsuMathHelper.Clamp((float)fadeLevel, 0, 100) / 200;
  1930. #else
  1931.             spriteManagerTransition.Alpha = OsuMathHelper.Clamp((float)fadeLevel, 0, 100) / 100;
  1932. #endif
  1933.         }
  1934.  
  1935.         internal static void ShowDialog(pDialog dialog)
  1936.         {
  1937.             DialogQueue.Add(dialog);
  1938.         }
  1939.  
  1940.         private static void dialog_Closed(object sender, EventArgs e)
  1941.         {
  1942.             if (ActiveDialog == null)
  1943.                 return;
  1944.  
  1945.             ActiveDialog.spriteManager.SpriteList.ForEach(s => { s.FadeOut(180); s.AlwaysDraw = false; });
  1946.  
  1947.             pDialog disposedDialog = ActiveDialog;
  1948.  
  1949.             Scheduler.AddDelayed(delegate { disposedDialog.spriteManager.Dispose(); }, 180);
  1950.  
  1951.             spriteManagerOverlay.Add(ActiveDialog.spriteManager.SpriteList);
  1952.  
  1953.             ActiveDialog = null;
  1954.  
  1955.             if (ActiveDialogMutedTextControl != null)
  1956.             {
  1957.                 ActiveDialogMutedTextControl.AcceptText = true;
  1958.                 ActiveDialogMutedTextControl = null;
  1959.             }
  1960.  
  1961.             DialogQueue.Remove((pDialog)sender);
  1962.             Instance.Components.Remove((GameComponent)sender);
  1963.         }
  1964.  
  1965.  
  1966.         static int ExceptionCount;
  1967.  
  1968.         protected override void Draw()
  1969.         {
  1970. #if !DEBUG
  1971.             try
  1972.             {
  1973. #endif
  1974.             PerformanceMonitor.BeginCollecting(FrameTimeType.Draw);
  1975.  
  1976.             OsuGlControl.ResetState();
  1977.  
  1978.             GraphicsScheduler.Update();
  1979.             TextureGl.UploadNext();
  1980.  
  1981.             if (IsMinimized && CanRunSlowly && TotalFramesRendered % 4 != 0)
  1982.             {
  1983.                 //We don't need to draw much when minimised.
  1984.                 //We do need to draw occasionally though, else there can be cases where, for example,
  1985.                 //Update creates many sprites which are never cleaned up by SpriteManager's Draw call.
  1986.                 //Once every 4 frames sounds like a fair compromise (once every second, as we run 15fps when minimised).
  1987.                 PerformanceMonitor.EndCollecting(FrameTimeType.Draw);
  1988.                 return;
  1989.             }
  1990.  
  1991.             SpriteManager.NewFrame();
  1992.             Shader.SetGlobalProperty(@"g_Time", Time);
  1993.  
  1994.             OsuGlControl.TextureShader2D.Begin();
  1995.  
  1996.             HitObjectManager.DrawTargets();
  1997.  
  1998.             GL.Clear(ClearBufferMask.ColorBufferBit);
  1999.  
  2000.             bool replayCursor = InputManager.ReplayMode && Mode == OsuModes.Play;
  2001.  
  2002.             //Begin bloom virtual renderer.
  2003.             if (ConfigManager.sShaders) BloomRenderer.BloomStart();
  2004.  
  2005.             TransitionManager.Draw();
  2006.  
  2007.             base.Draw();
  2008.  
  2009.             Components.ForEach(c => (c as DrawableGameComponent)?.Draw());
  2010.  
  2011.  
  2012.             spriteManager.Draw();
  2013.  
  2014.             //if ((BanchoClient.Permission & Permissions.Supporter) > 0)
  2015.             if (replayCursor)
  2016.             {
  2017.                 cursorTrailRenderer.Draw();
  2018.                 spriteManagerCursor.Draw();
  2019.             }
  2020.  
  2021.             Options.Draw();
  2022.  
  2023.             osuDirect.Draw();
  2024.  
  2025.             spriteManagerOverlay.Draw();
  2026.             chatEngine.Draw();
  2027.  
  2028.             MusicControl.Draw();
  2029.  
  2030.             if (Coins != null) Coins.Draw();
  2031.  
  2032.             if (ActiveDialog != null)
  2033.                 ActiveDialog.Draw();
  2034.  
  2035.             Volume.Draw();
  2036.  
  2037.             if (FrameTimeDisplay != null && ConfigManager.sFrameTimeDisplay.Value) FrameTimeDisplay.Draw();
  2038.  
  2039.             spriteManagerOverlayHighest.Draw();
  2040.  
  2041.             FpsDisplay.Draw();
  2042.  
  2043.             BanchoStatus.Draw();
  2044.  
  2045.             if (OnScreenDisplay != null) OnScreenDisplay.Draw();
  2046.  
  2047.             if (!replayCursor)
  2048.             {
  2049.                 cursorTrailRenderer.Draw();
  2050.                 spriteManagerCursor.Draw();
  2051.             }
  2052.  
  2053.             spriteManagerHighest.Draw();
  2054.  
  2055.             if (FadeState != FadeStates.Idle || spriteManagerTransition.Alpha > 0)
  2056.                 spriteManagerTransition.Draw();
  2057.  
  2058.             TransitionManager.DrawHigh();
  2059.  
  2060.             //Draw bloom overlay.
  2061.             if (ConfigManager.sShaders) BloomRenderer.BloomEnd();
  2062.  
  2063.             OsuGlControl.TextureShader2D.End();
  2064.  
  2065.             PerformanceMonitor.EndCollecting(FrameTimeType.Draw);
  2066.  
  2067.             PerformanceMonitor.BeginCollecting(FrameTimeType.Sleep);
  2068.             Thread.Sleep(0);
  2069.             PerformanceMonitor.EndCollecting(FrameTimeType.Sleep);
  2070.  
  2071.             PerformanceMonitor.BeginCollecting(FrameTimeType.SwapBuffer);
  2072.             GlControl.SwapBuffers();
  2073.             PerformanceMonitor.EndCollecting(FrameTimeType.SwapBuffer);
  2074.  
  2075. #if !DEBUG
  2076.             }
  2077.             catch (Exception e)
  2078.             {
  2079.                 if (ExceptionCount++ > 1 || Mode == OsuModes.Exit || QueuedMode == OsuModes.Exit)
  2080.                     throw;
  2081.                 softHandle(e);
  2082.             }
  2083. #endif
  2084.  
  2085.             TotalFramesRendered++;
  2086.         }
  2087.  
  2088.         protected override void PostFrame()
  2089.         {
  2090.             PerformanceMonitor.BeginCollecting(FrameTimeType.Update);
  2091.  
  2092.             base.PostFrame();
  2093.  
  2094.             UpdateTiming();
  2095.  
  2096.             PerformanceMonitor.EndCollecting(FrameTimeType.Update);
  2097.  
  2098.             if (ConfigManager.sFrameTimeDisplay)
  2099.             {
  2100.                 if (FrameTimeDisplay == null) FrameTimeDisplay = new FrameTimeDisplay(PerformanceMonitor);
  2101.                 FrameTimeDisplay.Update();
  2102.             }
  2103.  
  2104.             PerformanceMonitor.NewFrame();
  2105.  
  2106.             PerformanceMonitor.BeginCollecting(FrameTimeType.BetweenFrames);
  2107.         }
  2108.  
  2109.         private static void softHandle(Exception e)
  2110.         {
  2111.             Logger.Log($@"Soft handled: {e}", LoggingTarget.Runtime, LogLevel.Error);
  2112.  
  2113.             if (ExceptionCount == 1) //report error the first time
  2114.             {
  2115.                 ErrorSubmission.Submit(new OsuError(e) { Feedback = "soft handle" });
  2116.                 NotificationManager.ShowMessage("An error occurred somewhere in osu! and has been reported. osu! will attempt to keep running.", Color.Red, 5000);
  2117.             }
  2118.  
  2119.             if (e is MissingFieldException || e is MissingMethodException || e is MissingMemberException)
  2120.                 GameBase.ChangeMode(OsuModes.Update);
  2121.  
  2122.             GameBase.Scheduler.AddDelayed(delegate { ExceptionCount--; }, 1000);
  2123.         }
  2124.  
  2125.         //used for flashlight cheat detecting
  2126.         internal static Color[] PixelColorAt(Vector2 pos, int count)
  2127.         {
  2128.             try
  2129.             {
  2130.                 {
  2131.                     Color[] c = new Color[count];
  2132.                     using (Bitmap b = new Bitmap(WindowManager.Width, WindowManager.Height, PixelFormat.Format32bppArgb))
  2133.                     {
  2134.                         BitmapData bd = b.LockBits(new System.Drawing.Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadOnly, b.PixelFormat);
  2135.                         GL.ReadPixels(0, 0, WindowManager.Width, WindowManager.Height, OpenTK.Graphics.ES20.PixelFormat.Rgba, PixelType.UnsignedByte, bd.Scan0);
  2136.                         b.UnlockBits(bd);
  2137.                         for (int i = 0; i < count; i++)
  2138.                         {
  2139.                             System.Drawing.Color sc = b.GetPixel((int)pos.X, (int)pos.Y + i);
  2140.                             c[i] = new Color(sc.R, sc.G, sc.B);
  2141.                         }
  2142.                     }
  2143.                     return c;
  2144.                 }
  2145.             }
  2146.             catch
  2147.             {
  2148.                 return null;
  2149.             }
  2150.         }
  2151.  
  2152.         internal static MemoryStream GetScreenShotStream()
  2153.         {
  2154.             try
  2155.             {
  2156.                 MemoryStream image = new MemoryStream();
  2157.                 {
  2158.                     using (Bitmap b = new Bitmap(WindowManager.Width, WindowManager.Height, PixelFormat.Format32bppArgb))
  2159.                     {
  2160.                         BitmapData bd = b.LockBits(new System.Drawing.Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadOnly, b.PixelFormat);
  2161.                         GL.ReadPixels(0, 0, WindowManager.Width, WindowManager.Height, OpenTK.Graphics.ES20.PixelFormat.Rgba, PixelType.UnsignedByte, bd.Scan0);
  2162.                         b.UnlockBits(bd);
  2163.                         b.RotateFlip(RotateFlipType.RotateNoneFlipY);
  2164.                         b.Save(image, ImageFormat.Jpeg);
  2165.                     }
  2166.                     return image;
  2167.                 }
  2168.             }
  2169.             catch
  2170.             {
  2171.                 return null;
  2172.             }
  2173.         }
  2174.  
  2175.         #endregion
  2176.  
  2177.         #region Gamefield/Window Manipulation
  2178.  
  2179.         internal static GameField GameField;
  2180.         internal static WindowManager WindowManager;
  2181.  
  2182.         internal static bool IsBorderlessWindow
  2183.         {
  2184.             get
  2185.             {
  2186.                 return !ConfigManager.sFullscreen.Value && WindowManager.Width == InitialDesktopResolution.Width && WindowManager.Height == InitialDesktopResolution.Height;
  2187.             }
  2188.         }
  2189.  
  2190.         private static int InitialRefreshRate = 0;
  2191.         internal static int RefreshRate = 0;
  2192.  
  2193.         #endregion
  2194.  
  2195.         #region Sprites
  2196.  
  2197.         internal static Rectangle WindowRectangle;
  2198.         internal static Rectangle WindowRectangleWidescreen;
  2199.         #endregion
  2200.  
  2201.         #region State Management
  2202.  
  2203.         internal static double fadeLevel;
  2204.  
  2205.         internal static FadeStates FadeState = FadeStates.Idle;
  2206.         internal static OsuModes QueuedMode = OsuModes.Menu;
  2207.         internal static OsuModes Mode = OsuModes.Unknown;
  2208.         internal static pGameMode RunningGameMode;
  2209.  
  2210.         /// <summary>
  2211.         /// Track whether the exit dialog box is displaying (so we don't display more than one).
  2212.         /// </summary>
  2213.         static bool exitDialogDisplaying;
  2214.  
  2215.         /// <summary>
  2216.         /// Handle exit confirmation when required.
  2217.         /// </summary>
  2218.         internal static void BeginExit(bool forceConfirm = false)
  2219.         {
  2220.             bool downloadsActive = OsuDirect.ActiveDownloads.Count > 0;
  2221.             bool waitingPrivateMessages = ChatEngine.channelTabs.Tabs.FindAll(t => t.Alerting && t.tabText.Text != null && !t.tabText.Text.StartsWith(@"#")).Count > 0;
  2222.  
  2223.             if (Tournament)
  2224.             {
  2225.                 ChangeMode(OsuModes.Exit);
  2226.                 return;
  2227.             }
  2228.  
  2229.             if (!downloadsActive && !waitingPrivateMessages && !ConfigManager.sConfirmExit && !forceConfirm)
  2230.             {
  2231.                 ChangeMode(OsuModes.Exit);
  2232.                 return;
  2233.             }
  2234.  
  2235.             if (exitDialogDisplaying) return;
  2236.  
  2237.             exitDialogDisplaying = true;
  2238.  
  2239.             string confirmMessage = "Are you sure you want to exit osu!?";
  2240.  
  2241.             if (downloadsActive)
  2242.                 confirmMessage = "Exiting will cancel all active downloads!\n" + confirmMessage;
  2243.             else if (waitingPrivateMessages)
  2244.                 confirmMessage = "You have unread chat messages.\n" + confirmMessage;
  2245.  
  2246.             pDialogConfirmation pd = new pDialogConfirmation(confirmMessage,
  2247.                 delegate { ChangeMode(OsuModes.Exit); },
  2248.                 delegate { exitDialogDisplaying = false; }
  2249.                 );
  2250.             pd.Closed += delegate { exitDialogDisplaying = false; };
  2251.  
  2252.             ShowDialog(pd);
  2253.         }
  2254.  
  2255.         internal static void ChangeMode(OsuModes newMode = OsuModes.Unknown, bool force = false)
  2256.         {
  2257.             if (newMode == OsuModes.Unknown)
  2258.             {
  2259.                 newMode = Mode;
  2260.                 force = true;
  2261.             }
  2262.  
  2263.             if (newMode != OsuModes.Menu && Time < Menu.IntroLength)
  2264.             {
  2265.                 //170ms delay = 120ms transition fade out + 50ms transition scheduling
  2266.                 Scheduler.AddDelayed(delegate { ChangeMode(newMode, force); }, Menu.IntroLength - Time + 170);
  2267.                 return;
  2268.             }
  2269.  
  2270.             //If we are in the editor and not yet prompted for confirmation, do so now.
  2271.             if (Mode == OsuModes.Edit && !((Editor)RunningGameMode).ExitedProperly && !((Editor)RunningGameMode).Exit())
  2272.                 return;
  2273.  
  2274.             if ((newMode != OsuModes.Exit && newMode != OsuModes.Update) && (!BanchoClient.CheckAuth(false) || !AudioEngine.CheckAudioDevice()))
  2275.             {
  2276.                 newMode = OsuModes.Menu;
  2277.                 force = true;
  2278.             }
  2279.  
  2280.             if (Tournament)
  2281.             {
  2282.                 switch (newMode)
  2283.                 {
  2284.                     case OsuModes.Rank:
  2285.                     case OsuModes.Exit:
  2286.                     case OsuModes.Busy:
  2287.                         break;
  2288.                     case OsuModes.SelectPlay:
  2289.                         newMode = OsuModes.Menu;
  2290.                         break;
  2291.                     default:
  2292.                         if (Mode == OsuModes.Play && !AudioEngine.Paused &&
  2293.                             (InputManager.ReplayToEnd || (Player.Instance != null && Player.Instance.Status == PlayerStatus.Outro)))
  2294.                             return;
  2295.                         break;
  2296.                 }
  2297.  
  2298.                 //todo: figure a proper fix for this.
  2299.                 if (Mode == OsuModes.Rank && newMode == OsuModes.Play && ModeTime < 10000)
  2300.                     return;
  2301.             }
  2302.  
  2303.             NotificationManager.ClearMessageMassive();
  2304.  
  2305.             if (newMode == Mode && !force)
  2306.                 return;
  2307.  
  2308.             if (newMode == QueuedMode && !force)
  2309.                 return;
  2310.  
  2311.             if (QueuedMode == OsuModes.Exit)
  2312.                 return;
  2313.  
  2314.             Debug.Print("Queued mode change to {0}", newMode.ToString());
  2315.  
  2316.             //Close dialogs which are specific to the old game mode.
  2317.             List<pDialog> closeUs = new List<pDialog>();
  2318.             foreach (pDialog p in DialogQueue)
  2319.                 if (p.GameModeSpecific)
  2320.                     closeUs.Add(p);
  2321.  
  2322.             foreach (pDialog p in closeUs)
  2323.                 p.Close();
  2324.  
  2325.             QueuedMode = newMode;
  2326.  
  2327.             s_fadeScreen.Bypass = false;
  2328.             fadeOutRate = 10;
  2329.  
  2330.             spriteManagerTransition.Clear();
  2331.             spriteManagerTransition.Add(s_fadeScreen);
  2332.  
  2333.             switch (newMode)
  2334.             {
  2335.                 case OsuModes.Exit:
  2336.                     if (OnExitFade != null) OnExitFade();
  2337.  
  2338.                     if (!ConfigManager.sMenuVoice || (UpdateState == UpdateStates.NeedsRestart && OsuMain.Restart) || Tournament)
  2339.                         fadeOutRate = 5;
  2340.                     else
  2341.                     {
  2342.                         fadeOutRate = 0.6;
  2343.                         AudioEngine.PlaySample(@"seeya", 100, (BanchoClient.Permission & Permissions.Supporter) > 0 ? SkinSource.ExceptBeatmap : SkinSource.Osu);
  2344.                     }
  2345.  
  2346.                     InputManager.HandleInput = false;
  2347.                     break;
  2348.             }
  2349.  
  2350.             FadeState = FadeStates.FadeOut;
  2351.         }
  2352.  
  2353.         internal static void ChangeModeInstant(OsuModes newMode, bool force = false, int disposalDelay = 0)
  2354.         {
  2355.             if (newMode != OsuModes.Menu && Time < Menu.IntroLength)
  2356.             {
  2357.                 //170ms delay = 120ms transition fade out + 50ms transition scheduling
  2358.                 Scheduler.AddDelayed(delegate { ChangeModeInstant(newMode, force, disposalDelay); }, Menu.IntroLength - Time + 170);
  2359.                 return;
  2360.             }
  2361.  
  2362.             Scheduler.Add(delegate
  2363.             {
  2364.                 if (newMode == Mode && !force)
  2365.                     return;
  2366.  
  2367.                 FadeState = FadeStates.Idle;
  2368.  
  2369.                 //Close dialogs which are specific to the old game mode.
  2370.                 List<pDialog> closeUs = new List<pDialog>();
  2371.                 foreach (pDialog p in DialogQueue)
  2372.                     if (p.GameModeSpecific)
  2373.                         closeUs.Add(p);
  2374.  
  2375.                 foreach (pDialog p in closeUs)
  2376.                     p.Close();
  2377.  
  2378.                 QueuedMode = newMode;
  2379.  
  2380.                 loadQueuedMode(disposalDelay);
  2381.  
  2382.                 if (FadeInComplete != null)
  2383.                     FadeInComplete(null, null);
  2384.             });
  2385.         }
  2386.  
  2387.         internal static OsuModes LastMode = OsuModes.Unknown;
  2388.  
  2389.         /// <summary>
  2390.         /// Returns the LastMode entered if it's not the current mode and it has been set, otherwise returns a fallback mode.
  2391.         /// </summary>
  2392.         internal static OsuModes CallbackMode => LastMode != Mode && LastMode != OsuModes.Unknown ? LastMode : OsuModes.Menu;
  2393.  
  2394.         private static void loadQueuedMode(int disposalDelay = 0)
  2395.         {
  2396.             if (QueuedMode == OsuModes.Unknown) return;
  2397.  
  2398.             Debug.Print("Mode change in progress.");
  2399.  
  2400.             if (QueuedMode != OsuModes.Play || LastMode != OsuModes.Play)
  2401.                 SetTitle();
  2402.  
  2403.             if (Mode != QueuedMode)
  2404.                 Options.Expanded = false;
  2405.  
  2406.             IdleHandler.ForceActivity();
  2407.  
  2408.             switch (QueuedMode)
  2409.             {
  2410.                 case OsuModes.Rank:
  2411.                 case OsuModes.RankingTagCoop:
  2412.                 case OsuModes.RankingTeam:
  2413.                 case OsuModes.RankingVs:
  2414.                     break;
  2415.                 default:
  2416.                     //Only clear this cache if we aren't entering the ranking screen.  We want these samples to keep playing otherwise.
  2417.                     AudioEngine.ClearSampleEvents();
  2418.                     break;
  2419.             }
  2420.  
  2421.             PendingModeChange = true; //Allows skipping of sync frames after load.
  2422.  
  2423.             bool previousForceNonExclusive = ForceNonExclusive;
  2424.  
  2425.             LastMode = Mode;
  2426.             Mode = QueuedMode;
  2427.  
  2428.             if (RunningGameMode != null)
  2429.             {
  2430.                 pGameMode gamemodeToDispose = RunningGameMode;
  2431.  
  2432.                 if (disposalDelay > 0)
  2433.                 {
  2434.                     Scheduler.AddDelayed(delegate
  2435.                     {
  2436.                         Instance.Components.Remove(gamemodeToDispose);
  2437.                         ((GameComponent)gamemodeToDispose).Dispose();
  2438.                     }, disposalDelay);
  2439.                 }
  2440.                 else
  2441.                 {
  2442.                     Instance.Components.Remove(gamemodeToDispose);
  2443.                     ((GameComponent)gamemodeToDispose).Dispose();
  2444.                 }
  2445.  
  2446.                 RunningGameMode = null;
  2447.             }
  2448.  
  2449.             OnNextModeChange?.Invoke();
  2450.             OnModeChange?.Invoke();
  2451.  
  2452.             OnNextModeChange = null;
  2453.  
  2454.             if (!Options.CanExpand)
  2455.                 Options.PoppedOut = false;
  2456.  
  2457.             //This is after QueuedMode is assigned to Mode
  2458.             Debug.Assert(Mode == QueuedMode);
  2459.  
  2460.             if (Mode == OsuModes.Exit)
  2461.             {
  2462.                 Instance.Exit();
  2463.                 goto Finish;
  2464.             }
  2465.  
  2466.             if (LastMode != OsuModes.Unknown)
  2467.             {
  2468.                 if (LastMode != Mode)
  2469.                     SkinManager.LoadSkin();
  2470.                 else
  2471.                     SkinManager.LoadCursor(false);
  2472.             }
  2473.  
  2474.             BloomRenderer.RedTint = 0;
  2475.             ModeTime = 0;
  2476.  
  2477.             bool forceScreenSize = false;
  2478.             if (Mode == OsuModes.Edit)
  2479.             {
  2480.                 if (EditorControl == null) EditorControl = new EditorControl();
  2481.  
  2482.                 if (!MenuVisible)
  2483.                 {
  2484.                     MenuVisible = true;
  2485.                     EditorControl.Parent = Form;
  2486.                     forceScreenSize = true;
  2487.                 }
  2488.             }
  2489.             else
  2490.             {
  2491.                 if (EditorControl != null)
  2492.                 {
  2493.                     EditorControl.Dispose();
  2494.                     EditorControl = null;
  2495.                 }
  2496.  
  2497.                 if (MenuVisible)
  2498.                 {
  2499.                     MenuVisible = false;
  2500.                     forceScreenSize = true;
  2501.                 }
  2502.             }
  2503.  
  2504.             forceScreenSize |= previousForceNonExclusive != ForceNonExclusive;
  2505.  
  2506.             if (!Tournament)
  2507.             {
  2508.                 if (pendingScreenModeChange != null)
  2509.                     pendingScreenModeChange();
  2510.                 else if (forceScreenSize)
  2511.                     SetScreenSize();
  2512.                 pendingScreenModeChange = null;
  2513.             }
  2514.  
  2515.             GameField.Resize(GameBase.GameField.ScaleFactor, true);
  2516.  
  2517.             InputManager.FullTextEnabled = ChatEngine.IsVisible;
  2518.             InputManager.fullTextGameBuffer = string.Empty;
  2519.  
  2520.             AudioEngine.cachedSeekPending = false;
  2521.  
  2522.             bool showMusicControls = false;
  2523.  
  2524.             ForceGC(true);
  2525.  
  2526.             bool allowMaximize = false;
  2527.  
  2528.             switch (Mode)
  2529.             {
  2530.                 case OsuModes.Edit:
  2531.                     AudioEngine.ResetAudioTrack();
  2532.                     AudioEngine.Stop();
  2533.                     RunningGameMode = new Editor(Instance);
  2534.                     break;
  2535.                 case OsuModes.Play:
  2536.                     if (LastMode == OsuModes.MatchSetup || PlayerVs.Match != null)
  2537.                         RunningGameMode = new PlayerVs(MatchSetup.Match);
  2538.                     else if (TestMode)
  2539.                         RunningGameMode = new PlayerTest();
  2540.                     else if (InputManager.ReplayMode || InputManager.ReplayStreaming || ModManager.CheckActive(Mods.Autoplay))
  2541.                         RunningGameMode = new ReplayWatcher();
  2542.                     else
  2543.                         RunningGameMode = new Player();
  2544.                     break;
  2545.                 case OsuModes.SelectPlay:
  2546.                 case OsuModes.SelectEdit:
  2547.                 case OsuModes.SelectMulti:
  2548.                     allowMaximize = true;
  2549.  
  2550.                     //check for new beatmaps once after starting osu!
  2551.                     if (BeatmapImport.DoNewBeatmapCheck ||
  2552.                         (LastMode != OsuModes.BeatmapImport && BeatmapManager.Beatmaps.Count == 0))
  2553.                     {
  2554.                         LastMode = Mode;
  2555.                         RunningGameMode = new BeatmapImport(Instance);
  2556.                         Mode = OsuModes.BeatmapImport;
  2557.                     }
  2558.                     else
  2559.                         RunningGameMode = new SongSelection(Instance);
  2560.                     break;
  2561.                 case OsuModes.SelectDrawings:
  2562.                     allowMaximize = true;
  2563.                     RunningGameMode = new Drawings(Instance);
  2564.                     break;
  2565.                 case OsuModes.OptionsOffsetWizard:
  2566.                     allowMaximize = true;
  2567.                     showMusicControls = true;
  2568.                     RunningGameMode = new OptionsOffsetWizard(Instance);
  2569.                     break;
  2570.                 case OsuModes.Menu:
  2571.                     allowMaximize = true;
  2572.                     if (LastMode != OsuModes.Unknown) Menu.FirstLoad = false;
  2573.                     showMusicControls = true;
  2574.                     RunningGameMode = new Menu(Instance);
  2575.                     break;
  2576.                 case OsuModes.Lobby:
  2577.                     allowMaximize = true;
  2578.                     showMusicControls = true;
  2579.                     RunningGameMode = new Lobby(Instance);
  2580.                     break;
  2581.                 case OsuModes.MatchSetup:
  2582.                     //check for new beatmaps once after starting osu!
  2583.                     if (BeatmapImport.DoNewBeatmapCheck)
  2584.                     {
  2585.                         LastMode = Mode;
  2586.                         RunningGameMode = new BeatmapImport(Instance);
  2587.                         Mode = OsuModes.BeatmapImport;
  2588.                     }
  2589.                     else
  2590.                         RunningGameMode = new MatchSetup(Instance);
  2591.                     break;
  2592.                 case OsuModes.OnlineSelection:
  2593.                     allowMaximize = true;
  2594.                     RunningGameMode = new OnlineSelection(Instance);
  2595.                     break;
  2596.                 case OsuModes.RankingVs:
  2597.                     RunningGameMode = new RankingVs(Instance);
  2598.                     break;
  2599.                 case OsuModes.RankingTagCoop:
  2600.                     RunningGameMode = new RankingTagCoop(Instance);
  2601.                     break;
  2602.                 case OsuModes.RankingTeam:
  2603.                     RunningGameMode = new RankingTeamVs(Instance);
  2604.                     break;
  2605.                 case OsuModes.Rank:
  2606.                     RunningGameMode = new Ranking(Instance);
  2607.                     break;
  2608.                 case OsuModes.BeatmapImport:
  2609.                     RunningGameMode = new BeatmapImport(Instance);
  2610.                     break;
  2611.                 case OsuModes.PackageUpdater:
  2612.                     RunningGameMode = new PackageUpdater(Instance);
  2613.                     break;
  2614.                 case OsuModes.Benchmark:
  2615.                     RunningGameMode = new Benchmark(Instance);
  2616.                     break;
  2617.                 case OsuModes.Tourney:
  2618.                     RunningGameMode = new osu.GameModes.Other.Tournament.Tournament(Instance);
  2619.                     break;
  2620.                 case OsuModes.Charts:
  2621.                     RunningGameMode = new Charts();
  2622.                     break;
  2623.                 case OsuModes.Update:
  2624.                     OsuMain.ForceUpdate();
  2625.                     Instance.Exit();
  2626.                     goto Finish;
  2627.                 case OsuModes.Busy:
  2628.                     goto Finish;
  2629.             }
  2630.  
  2631.             if (Form.FormBorderStyle != FormBorderStyle.None)
  2632.                 Form.MaximizeBox = allowMaximize;
  2633.  
  2634.             MusicControl.ShowControls = showMusicControls;
  2635.  
  2636.             UpdateClientBounds();
  2637.  
  2638.             Instance.Components.Add(RunningGameMode);
  2639.             RunningGameMode.Initialize();
  2640.  
  2641.             Debug.Print("RunningGameMode is now {0} (was {1})", RunningGameMode, LastMode);
  2642.  
  2643.             Finish:
  2644.  
  2645.             if (QueuedMode == Mode)
  2646.                 QueuedMode = OsuModes.Unknown;
  2647.         }
  2648.  
  2649.         internal static void LoadComplete()
  2650.         {
  2651.             BanchoClient.UpdateStatus();
  2652.  
  2653.             BeginFadeIn();
  2654.  
  2655.             ChatEngine.UpdateNowPlaying(false, false);
  2656.         }
  2657.  
  2658.         internal static void BeginFadeIn()
  2659.         {
  2660.             if (FadeState != FadeStates.Idle)
  2661.                 fadeLevel = 140;
  2662.  
  2663.             FadeState = FadeStates.FadeIn;
  2664.         }
  2665.  
  2666.         #endregion
  2667.  
  2668.         #region User Input Handling
  2669.  
  2670.         internal static double ElapsedMilliseconds;
  2671.  
  2672.         private static bool localMenuActive;
  2673.  
  2674.         internal static bool TestMode;
  2675.         internal static int TestTime;
  2676.         private readonly string StartupNewFiles;
  2677.  
  2678.         #endregion
  2679.  
  2680.         #region Events
  2681.  
  2682.         internal static event EventHandler FadeInComplete;
  2683.         internal static event EventHandler FadeOutComplete;
  2684.  
  2685.         #endregion
  2686.  
  2687.         //private static readonly Queue<VoidDelegate> schedulerQueue = new Queue<VoidDelegate>();
  2688.         internal static readonly Scheduler Scheduler = new Scheduler();
  2689.         internal static readonly ThreadedScheduler BackgroundScheduler = new ThreadedScheduler();
  2690.         internal static readonly Scheduler GraphicsScheduler = new Scheduler();
  2691.         internal static pDialog ActiveDialog;
  2692.         private static TextInputControl ActiveDialogMutedTextControl;
  2693.         internal static System.Drawing.Rectangle ClientBounds;
  2694.         private static double fadeOutRate = 8;
  2695.         private static double fadeInRate = 4;
  2696.  
  2697.         internal static int SystemResolutionHeight;
  2698.         internal static int SystemResolutionWidth;
  2699.         internal static pTooltip ToolTip;
  2700.  
  2701.         /// <summary>
  2702.         /// The local user's user/panel object.
  2703.         /// </summary>
  2704.         internal static User User;
  2705.  
  2706.         private OsuDirect osuDirect;
  2707.  
  2708.         internal static void SetTitle()
  2709.         {
  2710.             string titleAddition = string.Empty;
  2711.             User current = StreamingManager.CurrentlySpectating;
  2712.             if (current != null)
  2713.                 titleAddition += " (watching " + current.Name + ")";
  2714.             SetTitle(titleAddition);
  2715.         }
  2716.  
  2717.         internal static void SetTitle(string title)
  2718.         {
  2719.             Scheduler.Add(delegate
  2720.             {
  2721.                 string t = (string.Format(@"osu!{0} {1} {2}", General.SUBVERSION, General.PUBLIC_NAME, title.Length > 0 ? @"- " + title : string.Empty)).Trim();
  2722.                 if (Tournament && !TournamentManager)
  2723.                     t += string.Format(@" Tournament Client {0}", TournamentClientId);
  2724.                 if (TournamentManager)
  2725.                     t += @" Tournament Manager";
  2726.                 Instance.Window.Title = t;
  2727.             });
  2728.         }
  2729.  
  2730.         static bool isShowingLogin;
  2731.         internal static void ShowLogin(bool callback = false)
  2732.         {
  2733.             if (Tournament) return;
  2734.  
  2735.             if (isShowingLogin && !callback) return;
  2736.             isShowingLogin = true;
  2737.  
  2738.             if (!GameBase.Instance.IsActive || !startupThreadOperation.IsCompleted)
  2739.             {
  2740.                 GameBase.Scheduler.AddDelayed(delegate { ShowLogin(true); }, 100);
  2741.                 return;
  2742.             }
  2743.  
  2744.             MenuActive = true;
  2745.             Options.Expanded = true;
  2746.             Options.LoginOnly = true;
  2747.  
  2748.             MenuActive = false;
  2749.  
  2750.             isShowingLogin = false;
  2751.         }
  2752.  
  2753.         internal static OsuModes ReceiveFile(params string[] files)
  2754.         {
  2755.             if (BeatmapManager.Beatmaps == null)
  2756.             {
  2757.                 Scheduler.Add(delegate { ReceiveFile(files); }, true);
  2758.                 return OsuModes.Unknown;
  2759.             }
  2760.  
  2761.             if (files == null || files.Length == 0 || (files.Length == 1 && String.IsNullOrEmpty(files[0])))
  2762.                 return OsuModes.Unknown;
  2763.  
  2764.             string firstFile = files[0];
  2765.  
  2766.             //Base the extension on the first file dragged.
  2767.             //This could fail if there are multiple filetypes, but the user shouldn't be doing this.
  2768.             FileType ext = GeneralHelper.GetFileType(firstFile);
  2769.  
  2770.             try
  2771.             {
  2772.                 switch (ext)
  2773.                 {
  2774.                     case FileType.BeatmapPackage2:
  2775.                     //TODO: reimplement
  2776.                     //string newPath = Application.StartupPath + "/Songs/" + Path.GetFileName(files);
  2777.                     //BeatmapManager.ChangedPackages.Add(newPath);
  2778.                     //goto case "osz";
  2779.                     case FileType.BeatmapPackage:
  2780.                     case FileType.Zip:
  2781.                         string songs_fullpath = Path.GetFullPath(BeatmapManager.SongsDirectory);
  2782.  
  2783.                         foreach (string f in files)
  2784.                         {
  2785.                             string filename = Path.GetFileName(f);
  2786.  
  2787.                             int charsOver = (songs_fullpath.Length + filename.Length) - GeneralHelper.MAX_PATH_LENGTH;
  2788.  
  2789.                             if (charsOver > 0)
  2790.                             {
  2791.                                 int newLength = filename.Length - charsOver;
  2792.                                 //Leave enough room for file chars + extension
  2793.                                 if (newLength > (ext != FileType.BeatmapPackage2 ? 3 : 4) + 1)
  2794.                                 {
  2795.                                     filename = filename.Remove(newLength) + Path.GetExtension(filename);
  2796.                                 }
  2797.                                 else
  2798.                                 {
  2799.                                     NotificationManager.ShowMessage("Error moving " + filename + ". Path is too long.", Color.Red, 1000);
  2800.                                     continue;
  2801.                                 }
  2802.                             }
  2803.  
  2804.                             string newPath = Path.Combine(BeatmapManager.SongsDirectory, filename);
  2805.                             Beatmap beatmap = BeatmapManager.Beatmaps.Find(bm => bm.InOszContainer && bm.ContainingFolderAbsolute == newPath);
  2806.  
  2807.                             if (beatmap != null)
  2808.                                 //in the case a map is already loaded, select it as the current map rather than attempt import.
  2809.                                 BeatmapManager.Current = beatmap;
  2810.                             else if (GeneralHelper.FileMove(f, newPath))
  2811.                                 BeatmapImport.SignalBeatmapCheck(true);
  2812.                             else
  2813.                             {
  2814.                                 if (BeatmapManager.ChangedPackages.Contains(newPath))
  2815.                                     BeatmapManager.ChangedPackages.Remove(newPath);
  2816.                                 TopMostMessageBox.Show("Error moving file " + filename);
  2817.                                 return OsuModes.Unknown;
  2818.                             }
  2819.                         }
  2820.  
  2821.                         switch (Mode)
  2822.                         {
  2823.                             case OsuModes.MatchSetup:
  2824.                             case OsuModes.SelectEdit:
  2825.                             case OsuModes.SelectMulti:
  2826.                             case OsuModes.SelectDrawings:
  2827.                                 return Mode;
  2828.                             case OsuModes.Edit:
  2829.                             case OsuModes.Play:
  2830.                                 NotificationManager.ShowMessageMassive(
  2831.                                     "New beatmap available - visit song select to finish importing!", 1000);
  2832.                                 return OsuModes.Unknown;
  2833.                             default:
  2834.                                 return OsuModes.SelectPlay;
  2835.                         }
  2836. #if P2P
  2837.                     case FileType.OsuMagnet:
  2838.                         OsuDirect.StartDownload(new P2PDirectDownload(filename, true));
  2839.                         break;
  2840. #endif
  2841.                     case FileType.AudioTrack:
  2842.                         BeatmapImport.SignalBeatmapCheck(true);
  2843.  
  2844.                         foreach (string f in files)
  2845.                         {
  2846.                             string dest = Path.Combine(BeatmapManager.SongsDirectory, Path.GetFileName(f));
  2847.                             GeneralHelper.FileDelete(dest);
  2848.                             File.Copy(f, dest);
  2849.                         }
  2850.  
  2851.                         return OsuModes.SelectEdit;
  2852.                     case FileType.Replay:
  2853.                         {
  2854.                             Score score = ScoreManager.ReadReplayFromFile(firstFile);
  2855.  
  2856.                             switch (Mode)
  2857.                             {
  2858.                                 case OsuModes.MatchSetup:
  2859.                                 case OsuModes.Edit:
  2860.                                 case OsuModes.Play:
  2861.                                     NotificationManager.ShowMessageMassive("Replay has been loaded.", 1000);
  2862.                                     return OsuModes.Unknown;
  2863.                             }
  2864.  
  2865.                             if (MatchSetup.Match != null)
  2866.                             {
  2867.                                 NotificationManager.ShowMessageMassive("Replay has been loaded.", 1000);
  2868.                                 return OsuModes.Unknown;
  2869.                             }
  2870.  
  2871.                             if (score != null)
  2872.                             {
  2873.                                 Beatmap b = BeatmapManager.GetBeatmapByChecksum(score.FileChecksum);
  2874.                                 if (BeatmapManager.Current != b)
  2875.                                 {
  2876.                                     BeatmapManager.Current = b;
  2877.                                     AudioEngine.LoadAudioForPreview(b, true, false);
  2878.                                 }
  2879.                                 InputManager.ReplayScore = score;
  2880.                                 InputManager.ReplayMode = true;
  2881.                                 return OsuModes.Rank;
  2882.                             }
  2883.  
  2884.                             return OsuModes.Unknown;
  2885.                         }
  2886.                     case FileType.Skin:
  2887.                         foreach (string f in files)
  2888.                         {
  2889.                             string filename = Path.GetFileName(f);
  2890.                             string filenameNoExt = Path.GetFileNameWithoutExtension(filename);
  2891.                             try
  2892.                             {
  2893.                                 string basePath = Path.Combine(SkinManager.SKINS_FOLDER, filenameNoExt);
  2894.                                 string path = Path.Combine(SkinManager.SKINS_FOLDER, filename);
  2895.  
  2896.                                 GeneralHelper.FileMove(f, path);
  2897.                                 string tempFolder = GeneralHelper.GetTempPath(filenameNoExt);
  2898.  
  2899.                                 Directory.CreateDirectory(tempFolder);
  2900.  
  2901.                                 FastZip fz = new FastZip();
  2902.                                 fz.ExtractZip(path, tempFolder, ".*");
  2903.  
  2904.                                 //Force removal of readonly flag.
  2905.                                 FileInfo myFile = new FileInfo(path);
  2906.                                 if ((myFile.Attributes & FileAttributes.ReadOnly) > 0)
  2907.                                     myFile.Attributes &= ~FileAttributes.ReadOnly;
  2908.  
  2909.                                 GeneralHelper.RecursiveMove(tempFolder, basePath);
  2910.                                 GeneralHelper.FileDelete(path);
  2911.  
  2912.                                 // So now we have the skin extracted in Skins/SkinName/
  2913.                                 // but they may still be in a subdirectory depending on how the skin was packaged.
  2914.                                 int maximumTries = 5;
  2915.  
  2916.                                 while (Directory.GetFiles(basePath).Length < 1 && maximumTries-- > 0)
  2917.                                 {
  2918.                                     string[] dirs = Directory.GetDirectories(basePath);
  2919.                                     GeneralHelper.RecursiveMove(dirs[0], basePath);
  2920.                                 }
  2921.  
  2922.                                 SkinManager.RefreshAvailableSkins();
  2923.  
  2924.                                 ConfigManager.sSkin.Value = filenameNoExt;
  2925.                                 SkinManager.LoadSkin(null, true);
  2926.  
  2927.                                 InputManager.ReplayMode = false;
  2928.  
  2929.                                 Options.Expanded = true;
  2930.                                 Options.ScrollTo(GameBase.Options.SkinSection);
  2931.                                 return OsuModes.Menu;
  2932.                             }
  2933.                             catch
  2934.                             {
  2935.                                 NotificationManager.ShowMessage("Unable to import skin \"" + filename + "\".");
  2936.                             }
  2937.                         }
  2938.                         return OsuModes.Unknown;
  2939.                     case FileType.Image:
  2940.                     case FileType.Video:
  2941.                         if (Mode == OsuModes.Menu && (BanchoClient.Permission & Permissions.Supporter) > 0 && ext == FileType.Image)
  2942.                         {
  2943.                             SkinManager.CreateUserSkin();
  2944.  
  2945.                             string dest = GeneralHelper.PathSanitise(Path.Combine(SkinManager.Current.FullPath, @"menu-background.jpg"));
  2946.  
  2947.                             GeneralHelper.FileDelete(dest);
  2948.                             File.Copy(firstFile, dest);
  2949.                             SkinManager.LoadSkin(ConfigManager.sSkin, true);
  2950.                             return OsuModes.Menu;
  2951.                         }
  2952.  
  2953.                         if (Mode != OsuModes.Edit)
  2954.                         {
  2955.                             NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.General_File_EnterEditor));
  2956.                             return OsuModes.Unknown;
  2957.                         }
  2958.  
  2959.                         pDialogConfirmation d = new pDialogConfirmation("Would you like to use \"" + Path.GetFileName(firstFile) + "\" as your map's background?",
  2960.                             delegate { Editor.Instance.Design.InsertBackground(firstFile); }, null);
  2961.                         GameBase.ShowDialog(d);
  2962.  
  2963.                         return OsuModes.Unknown;
  2964.                     default:
  2965.                         if (firstFile.StartsWith(@"osu://"))
  2966.                         {
  2967.                             if (BanchoClient.Connected)
  2968.                                 ChatEngine.HandleLink(firstFile);
  2969.                             else
  2970.                             {
  2971.                                 VoidDelegate del = null;
  2972.                                 del = delegate
  2973.                                 {
  2974.                                     ChatEngine.HandleLink(firstFile);
  2975.                                     BanchoClient.OnPermissionChange -= del;
  2976.                                 };
  2977.  
  2978.                                 BanchoClient.OnPermissionChange += del;
  2979.                             }
  2980.  
  2981.                             return OsuModes.Unknown;
  2982.                         }
  2983.  
  2984.                         if (!firstFile.StartsWith(@"-") && firstFile.Contains(@"."))
  2985.                             NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.General_File_UnknownType) + @" (" + firstFile + @")");
  2986.                         return OsuModes.Unknown;
  2987.                 }
  2988.             }
  2989.             catch (Exception e)
  2990.             {
  2991.                 NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.GameBase_FileImportError));
  2992.                 ErrorSubmission.Submit(new OsuError(e) { Feedback = @"file handling" });
  2993.             }
  2994.  
  2995.             return OsuModes.Unknown;
  2996.         }
  2997.  
  2998.         internal static void PackageFile(string filename, string saveDirectory)
  2999.         {
  3000.             string exportFolder = EXPORT_FOLDER;
  3001.             Directory.CreateDirectory(exportFolder);
  3002.  
  3003.             string filepath = Path.Combine(exportFolder, GeneralHelper.WindowsFilenameStrip(filename));
  3004.             ZipConstants.DefaultCodePage = 932;
  3005.             FastZip fz = new FastZip();
  3006.             fz.CreateZip(filepath, saveDirectory, true, "[^z]+$");
  3007.  
  3008.             NotificationManager.ShowMessage(filename + " has been exported.  Opening the Exports folder...", Color.YellowGreen, 6000);
  3009.             OpenFolder(exportFolder);
  3010.         }
  3011.  
  3012.         internal static void OpenFolderToFile(string filePath)
  3013.         {
  3014.             if (OsuMain.IsWine)
  3015.                 OpenFolder(Path.GetDirectoryName(filePath));
  3016.             else
  3017.                 Process.Start(@"explorer.exe", string.Format(@"/select,""{0}""", Path.GetFullPath(filePath)));
  3018.         }
  3019.  
  3020.         internal static void OpenFolder(string folderPath)
  3021.         {
  3022.             if (String.IsNullOrEmpty(folderPath)) return;
  3023.  
  3024.             if (folderPath[folderPath.Length - 1] != Path.DirectorySeparatorChar)
  3025.                 folderPath += Path.DirectorySeparatorChar;
  3026.  
  3027.             GameBase.ProcessStart(folderPath);
  3028.         }
  3029.  
  3030.         [return: MarshalAs(UnmanagedType.Bool)]
  3031.         [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
  3032.         public static extern bool SetForegroundWindow(IntPtr hwnd);
  3033.  
  3034.         [SuppressUnmanagedCodeSecurityAttribute()]
  3035.         [DllImport(@"user32.dll")]
  3036.         internal static extern bool FlashWindow(IntPtr hwnd, bool bInvert);
  3037.  
  3038.         [DllImport(@"user32.dll")]
  3039.         public static extern bool GetLayeredWindowAttributes(IntPtr hwnd, out IntPtr pcrKey, out IntPtr pbAlpha, out IntPtr pdwFlags);
  3040.  
  3041.         internal static void FlashWindow()
  3042.         {
  3043.             if (GameBase.Tournament) return;
  3044.  
  3045.             try
  3046.             {
  3047.                 if (ConfigManager.sChatAudibleHighlight)
  3048.                     AudioEngine.PlaySample(@"match-start");
  3049.                 Form.Invoke(new VoidDelegate(delegate { FlashWindow(Form.Handle, true); }));
  3050.             }
  3051.             catch { }
  3052.         }
  3053.  
  3054.         internal static void Restart(VoidDelegate restartAction = null)
  3055.         {
  3056.             if (restartAction != null) exitAction += restartAction;
  3057.             OsuMain.Restart = true;
  3058.             ChangeMode(OsuModes.Exit);
  3059.         }
  3060.  
  3061.         internal static bool IsFormOpacityHacked()
  3062.         {
  3063.             try
  3064.             {
  3065.                 IntPtr pcr = IntPtr.Zero;
  3066.                 IntPtr alpha = IntPtr.Zero;
  3067.                 IntPtr flag = new IntPtr(0x00000002);//LWA_ALPHA
  3068.                 if (GetLayeredWindowAttributes(Form.Handle, out pcr, out alpha, out flag))
  3069.                     return alpha.ToInt32() < 255;
  3070.             }
  3071.             catch { }
  3072.             return false;
  3073.         }
  3074.  
  3075.  
  3076.         internal static MusicControl MusicControl;
  3077.         internal static Options Options;
  3078.         private static pSprite s_WidescreenLeft;
  3079.         private static pSprite s_WidescreenRight;
  3080.  
  3081.         private static SmartThreadPool mainThreadPool = new SmartThreadPool(new STPStartInfo()
  3082.         {
  3083.             AreThreadsBackground = true,
  3084.             IdleTimeout = 300000,
  3085.             MaxWorkerThreads = 32,
  3086.             MinWorkerThreads = 8
  3087.         });
  3088.  
  3089.         internal static IWorkItemResult RunBackgroundThread(VoidDelegate d)
  3090.         {
  3091.             return mainThreadPool.QueueWorkItem(delegate
  3092.             {
  3093.                 try
  3094.                 {
  3095.                     d();
  3096.                 }
  3097.                 catch (Exception e)
  3098.                 {
  3099.                     softHandle(e);
  3100.                 }
  3101.             });
  3102.         }
  3103.  
  3104.         /// <summary>
  3105.         /// Ensures the delegate function is run in non-exclusive display mode (for windows forms etc.)
  3106.         /// </summary>
  3107.         private static void RunNonExclusive(VoidDelegate run)
  3108.         {
  3109.             bool requireExclusiveExit = GameBase.IsFullscreen && !GameBase.ForceNonExclusive;
  3110.  
  3111.             if (requireExclusiveExit)
  3112.             {
  3113.                 GameBase.ForcefullyLeaveExclusiveFullscreen();
  3114.                 GameBase.ResizeGL(true);
  3115.             }
  3116.  
  3117.             run();
  3118.  
  3119.             if (requireExclusiveExit)
  3120.             {
  3121.                 GameBase.ResizeGL(false);
  3122.  
  3123.                 // TopMost is already true at this point from the main loop, we however need to touch it again so that windows understands.
  3124.                 GameBase.Form.TopMost = true;
  3125.             }
  3126.         }
  3127.  
  3128.         internal static Thread MainThread;
  3129.         private bool ChildrenUpdated;
  3130.  
  3131.         public static int LastForcedGC;
  3132.         internal static Obfuscated<string> UniqueCheck = "unknown";
  3133.         internal static Obfuscated<string> UniqueId = "unknown";
  3134.         internal static Obfuscated<string> UniqueId2 = "unknown";
  3135.  
  3136.         internal static bool BenchmarkMode;
  3137.         internal static string IpcChannelName = "osu!";
  3138.         public static bool BackgroundLoading;
  3139.         internal static void ForceGC(bool ignoreTime = false)
  3140.         {
  3141.             if (GameBase.Time - LastForcedGC < 5000 && !ignoreTime) return;
  3142.  
  3143.             LastForcedGC = GameBase.Time;
  3144.  
  3145.             GC.Collect();
  3146.             GC.WaitForPendingFinalizers();
  3147.         }
  3148.  
  3149.         internal static void ProcessStart(string process, string flags = null)
  3150.         {
  3151.             if (Tournament) return;
  3152.  
  3153. #if ARCADE
  3154.             //We don't want the user to be able to start any external processes.
  3155.             //This includes the ability to open URLs (which is handled through this method).
  3156.             return;
  3157. #endif
  3158.  
  3159.             RunBackgroundThread(delegate
  3160.             {
  3161.                 try
  3162.                 {
  3163.                     ProcessStartInfo psi = new ProcessStartInfo(process, flags);
  3164.                     Process.Start(psi);
  3165.                 }
  3166.                 catch (Exception)
  3167.                 { }
  3168.             });
  3169.         }
  3170.  
  3171.         public static int IdleTime
  3172.         {
  3173.             get
  3174.             {
  3175.                 return GameBase.Time - InputManager.LastActionTime;
  3176.             }
  3177.         }
  3178.  
  3179.         public static bool HasPendingDialog { get { return ActiveDialog != null || DialogQueue.Count > 0; } }
  3180.  
  3181.         public static bool UseHighResolutionSprites { get { return (WindowManager.Height >= 800 || ConfigManager.sHighResolution) && !ConfigManager.sLowResolution && OsuGlControl.MaxTextureSize > 2048; } }
  3182.  
  3183.         public static bool NewGraphicsAvailable;
  3184.         internal static Size InitialDesktopResolution;
  3185.         internal static System.Drawing.Point InitialDesktopLocation;
  3186.         public static long TotalFramesRendered;
  3187.  
  3188. #if !Public
  3189.         private static pSprite testBuildOverlay;
  3190.         private static pText testBuildVersion;
  3191. #endif
  3192.  
  3193.         internal static int ChangeAllowance;
  3194.         internal static Process[] Processes;
  3195.  
  3196.  
  3197.         public static bool IsWindows81
  3198.         {
  3199.             get
  3200.             {
  3201.                 OperatingSystem os = Environment.OSVersion;
  3202.                 return os.Platform == PlatformID.Win32NT && os.Version.Major >= 6 && os.Version.Minor >= 3;
  3203.             }
  3204.         }
  3205.  
  3206.  
  3207.         static bool minimizedToTray;
  3208.         internal static bool checkFilesMatched;
  3209.         internal static bool IsFullscreen;
  3210.  
  3211.         private static Size clientSize;
  3212.  
  3213.         internal static bool IsFillingScreen
  3214.         {
  3215.             get
  3216.             {
  3217.                 return ConfigManager.sFullscreen || ConfigManager.sLetterboxing || (clientSize.Width >= InitialDesktopResolution.Width && clientSize.Height >= InitialDesktopResolution.Height);
  3218.             }
  3219.         }
  3220.  
  3221.         internal static bool ForceNonExclusive
  3222.         {
  3223.             get
  3224.             {
  3225.                 switch (Mode)
  3226.                 {
  3227.                     case OsuModes.SelectEdit:
  3228.                     case OsuModes.Edit:
  3229.                         return true;
  3230.                     case OsuModes.Play:
  3231.                         if (TestMode)
  3232.                             return true;
  3233.                         break;
  3234.                 }
  3235.  
  3236.                 return MenuVisible || !ConfigManager.sFullscreen;
  3237.             }
  3238.         }
  3239.  
  3240.         internal static int ClientSizeAdjustment = 0;
  3241.         private List<GameComponent> Components = new List<GameComponent>();
  3242.         private static IWorkItemResult startupThreadOperation;
  3243.  
  3244.         public static bool MinimizedToTray
  3245.         {
  3246.             get
  3247.             {
  3248.                 return minimizedToTray;
  3249.             }
  3250.  
  3251.             set
  3252.             {
  3253.                 //don't allow boss mode when running under wine (reported failure https://osu.ppy.sh/forum/t/362773)
  3254.                 if (OsuMain.IsWine) return;
  3255.  
  3256.                 if (value == minimizedToTray) return;
  3257.                 minimizedToTray = value;
  3258.  
  3259.                 if (minimizedToTray)
  3260.                 {
  3261.                     if (notifyIcon == null)
  3262.                     {
  3263.                         notifyIcon = new NotifyIcon();
  3264.                         notifyIcon.Icon = Form.Icon;
  3265.                         notifyIcon.Click += (obj, e) => { MinimizedToTray = false; };
  3266.                     }
  3267.  
  3268.                     notifyIcon.Visible = true;
  3269.  
  3270.                     if (ConfigManager.sBossKeyFirstActivation)
  3271.                     {
  3272.                         notifyIcon.ShowBalloonTip(10000, LocalisationManager.GetString(OsuString.BossKeyActivated), LocalisationManager.GetString(OsuString.BossKeyActivated_Tooltip), ToolTipIcon.Info);
  3273.                         ConfigManager.sBossKeyFirstActivation.Value = false;
  3274.                     }
  3275.  
  3276.                     Form.WindowState = FormWindowState.Minimized;
  3277.                     Form.Visible = false;
  3278.  
  3279.                     Player p = Player.Instance;
  3280.                     if (p != null && !(p is PlayerVs && Player.Loaded) && !AudioEngine.Paused && !Player.Paused && !InputManager.ReplayMode)
  3281.                         p.TogglePause();
  3282.  
  3283.                     bossKeyRestoreVolume = AudioEngine.VolumeMaster.Value;
  3284.                     AudioEngine.VolumeMaster.Value = 0;
  3285.                 }
  3286.                 else
  3287.                 {
  3288.                     Form.Visible = true;
  3289.                     Form.WindowState = FormWindowState.Normal;
  3290.  
  3291.                     Form.ShowInTaskbar = true;
  3292.                     notifyIcon.Visible = false;
  3293.  
  3294.                     BringToFront();
  3295.                     AudioEngine.VolumeMaster.Value = bossKeyRestoreVolume;
  3296.                 }
  3297.             }
  3298.         }
  3299.  
  3300.         /// <summary>
  3301.         /// Are we able to (forcefully) reload the current game mode without having an adverse effect on the overall state of osu!?
  3302.         /// </summary>
  3303.         public static bool ModeCanReload
  3304.         {
  3305.             get
  3306.             {
  3307.                 switch (Mode)
  3308.                 {
  3309.                     case OsuModes.Play:
  3310.                         return ModManager.CheckActive(Mods.Autoplay);
  3311.                     case OsuModes.Rank:
  3312.                     case OsuModes.RankingVs:
  3313.                     case OsuModes.RankingTeam:
  3314.                     case OsuModes.RankingTagCoop:
  3315.                         return false;
  3316.                 }
  3317.  
  3318.                 return true;
  3319.             }
  3320.         }
  3321.     }
  3322.  
  3323.     public enum OsuModes
  3324.     {
  3325.         Menu,
  3326.         Edit,
  3327.         Play,
  3328.         Exit,
  3329.         SelectEdit,
  3330.         SelectPlay,
  3331.         SelectDrawings,
  3332.         Rank,
  3333.         Update,
  3334.         Busy,
  3335.         Unknown,
  3336.         Lobby,
  3337.         MatchSetup,
  3338.         SelectMulti,
  3339.         RankingVs,
  3340.         OnlineSelection,
  3341.         OptionsOffsetWizard,
  3342.         RankingTagCoop,
  3343.         RankingTeam,
  3344.         BeatmapImport,
  3345.         PackageUpdater,
  3346.         Benchmark,
  3347.         Tourney,
  3348.         Charts
  3349.     };
  3350.  
  3351.     internal enum FadeStates
  3352.     {
  3353.         FadeOut,
  3354.         FadeIn,
  3355.         Idle,
  3356.         WaitingLoad,
  3357.     };
  3358.  
  3359.     public enum FrameSync
  3360.     {
  3361.         VSync = 1,
  3362.         Limit120 = 0,
  3363.         Unlimited = 2,
  3364.         CompletelyUnlimited = 4,
  3365.         Custom = 5
  3366.     };
  3367.  
  3368.  
  3369. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement