/// <summary> /// Initializes the database, and either inserts/updates /// </summary> public static void Initialize() { CreateTable(); using (var conn = new SQLiteConnection(DatabasePath)) { var settings = conn.Find <QuaverSettings>(x => x.Id == 1); // Settings need to be updated if (settings == null) { Logger.Important($"QuaverSettings could not be found previously in the database.", LogType.Runtime); settings = new QuaverSettings { VersionDifficultyProcessorKeys = DifficultyProcessorKeys.Version, VersionScoreProcessorKeys = ScoreProcessorKeys.Version, VersionRatingProcessorKeys = RatingProcessorKeys.Version }; conn.Insert(settings); } OutdatedMaps = MapDatabaseCache.FetchAll().FindAll(x => x.DifficultyProcessorVersion != DifficultyProcessorKeys.Version); Logger.Important($"Found {OutdatedMaps.Count} maps that have outdated difficulty ratings. Scheduling recalculation upon entering" + $"select.", LogType.Runtime); } }
/// <summary> /// Performs any initial setup the game needs to run. /// </summary> private void PerformGameSetup() { ConfigManager.Initialize(); DeleteTemporaryFiles(); ScoreDatabaseCache.CreateTable(); MapDatabaseCache.Load(false); QuaverSettingsDatabaseCache.Initialize(); // Force garabge collection. GC.Collect(); // Start watching for mapset changes in the folder. MapsetImporter.WatchForChanges(); // Initially set the global volume. AudioTrack.GlobalVolume = ConfigManager.VolumeGlobal.Value; AudioSample.GlobalVolume = ConfigManager.VolumeEffect.Value; ConfigManager.VolumeGlobal.ValueChanged += (sender, e) => { AudioTrack.GlobalVolume = e.Value; AudioSample.GlobalVolume = e.Value; };; ConfigManager.VolumeMusic.ValueChanged += (sender, e) => { if (AudioEngine.Track != null) { AudioEngine.Track.Volume = e.Value; } }; ConfigManager.VolumeEffect.ValueChanged += (sender, e) => AudioSample.GlobalVolume = e.Value; ConfigManager.Pitched.ValueChanged += (sender, e) => AudioEngine.Track.ToggleRatePitching(e.Value); ConfigManager.FpsLimiterType.ValueChanged += (sender, e) => InitializeFpsLimiting(); ConfigManager.WindowFullScreen.ValueChanged += (sender, e) => Graphics.IsFullScreen = e.Value; // Handle discord rich presence. DiscordHelper.Initialize("376180410490552320"); DiscordHelper.Presence = new DiscordRpc.RichPresence() { LargeImageKey = "quaver", LargeImageText = ConfigManager.Username.Value, EndTimestamp = 0 }; DiscordRpc.UpdatePresence(ref DiscordHelper.Presence); // Create bindable for selected map. if (MapManager.Mapsets.Count != 0) { MapManager.Selected = new Bindable <Map>(MapManager.Mapsets.First().Maps.First()); } }
/// <summary> /// Asks the user if they'd like to create a new difficulty for the mapset, /// and does so. /// </summary> public void CreateNewDifficulty() => ThreadScheduler.Run(() => { if (MapManager.Selected.Value.Game != MapGame.Quaver) { NotificationManager.Show(NotificationLevel.Error, "You cannot create new difficulties for maps from other games. Create a new set!"); return; } // Save the already existing map. if (Ruleset.ActionManager.HasUnsavedChanges) { DialogManager.Show(new EditorUnsavedChangesDialog(this)); return; } Button.IsGloballyClickable = false; var qua = ObjectHelper.DeepClone(WorkingMap); qua.DifficultyName = ""; qua.MapId = -1; qua.Description = $"Created at {TimeHelper.GetUnixTimestampMilliseconds()}"; var dir = $"{ConfigManager.SongDirectory.Value}/{MapManager.Selected.Value.Directory}"; var path = $"{dir}/{StringHelper.FileNameSafeString($"{qua.Artist} - {qua.Title} [{qua.DifficultyName}] - {TimeHelper.GetUnixTimestampMilliseconds()}")}.qua"; qua.Save(path); // Add the new map to the db. var map = Map.FromQua(qua, path); map.DateAdded = DateTime.Now; map.Id = MapDatabaseCache.InsertMap(map, path); // Reload the mapsets MapDatabaseCache.OrderAndSetMapsets(); // Set the selected one to the new one. MapManager.Selected.Value = map; MapManager.Selected.Value.Qua = qua; // Find the mapset and get the *new* object w/ the selected map. var selectedMapset = MapManager.Mapsets.Find(x => x.Maps.Any(y => y.Id == MapManager.Selected.Value.Id)); MapManager.Selected.Value = selectedMapset.Maps.Find(x => x.Id == MapManager.Selected.Value.Id); MapManager.Selected.Value.Qua = qua; MapManager.Selected.Value.NewlyCreated = true; MapManager.Selected.Value.AskToRemoveHitObjects = true; // Reload editor w/ new one. Exit(() => new EditorScreen(qua)); });
/// <summary> /// Handles the input of the game + individual game modes. /// </summary> /// <param name="gameTime"></param> private void HandleInput(GameTime gameTime) { var dt = gameTime.ElapsedGameTime.TotalMilliseconds; // Handle pausing if (!Failed && !IsPlayComplete) HandlePauseInput(gameTime); // Show/hide scoreboard. if (KeyboardManager.IsUniqueKeyPress(ConfigManager.KeyScoreboardVisible.Value)) ConfigManager.ScoreboardVisible.Value = !ConfigManager.ScoreboardVisible.Value; // Everything after this point is applicable to gameplay ONLY. if (IsPaused || Failed) return; if (!IsPlayComplete) { // Handle the restarting of the map. HandlePlayRestart(dt); if (KeyboardManager.IsUniqueKeyPress(ConfigManager.KeySkipIntro.Value)) SkipToNextObject(); // Only allow offset changes if the map hasn't started or if we're on a break if (Ruleset.Screen.Timing.Time <= 5000 || Ruleset.Screen.EligibleToSkip) { // Handle offset + if (KeyboardManager.IsUniqueKeyPress(Keys.OemPlus)) { MapManager.Selected.Value.LocalOffset += 5; NotificationManager.Show(NotificationLevel.Success, $"Local map offset is now: {MapManager.Selected.Value.LocalOffset}ms"); MapDatabaseCache.UpdateMap(MapManager.Selected.Value); } // Handle offset - if (KeyboardManager.IsUniqueKeyPress(Keys.OemMinus)) { MapManager.Selected.Value.LocalOffset -= 5; NotificationManager.Show(NotificationLevel.Success, $"Local map offset is now: {MapManager.Selected.Value.LocalOffset}ms"); MapDatabaseCache.UpdateMap(MapManager.Selected.Value); } } } // Handle input per game mode. Ruleset.HandleInput(gameTime); }
/// <summary> /// Does a recalculation for the difficulties on outdated maps. /// </summary> public static void RecalculateDifficultiesForOutdatedMaps() { foreach (var map in OutdatedMaps) { map.DifficultyProcessorVersion = DifficultyProcessorKeys.Version; try { map.CalculateDifficulties(); MapDatabaseCache.UpdateMap(map); } catch (Exception e) { new SQLiteConnection(DatabasePath).Delete(map); } } OutdatedMaps.Clear(); }
/// <inheritdoc /> /// <summary> /// </summary> public override void OnFirstUpdate() { ThreadScheduler.Run(() => { MapsetImporter.ImportMapsetsInQueue(); if (MapDatabaseCache.MapsToUpdate.Count != 0) { MapDatabaseCache.ForceUpdateMaps(); } if (QuaverSettingsDatabaseCache.OutdatedMaps.Count != 0) { var view = View as ImportingScreenView; view.Header.Text = "Please wait. Calculating difficulties for maps."; QuaverSettingsDatabaseCache.RecalculateDifficultiesForOutdatedMaps();; } OnImportCompletion(); }); base.OnFirstUpdate(); }
/// <summary> /// Creates a new mapset with an audio file. /// </summary> /// <param name="audioFile"></param> public static void HandleNewMapsetCreation(string audioFile) { try { var game = GameBase.Game as QuaverGame; // Add a fade effect and make butotns not clickable // so the user can't perform any actions during this time. Transitioner.FadeIn(); Button.IsGloballyClickable = false; var tagFile = TagLib.File.Create(audioFile); // Create a fresh .qua with the available metadata from the file var qua = new Qua() { AudioFile = Path.GetFileName(audioFile), Artist = tagFile.Tag.FirstPerformer ?? "", Title = tagFile.Tag.Title ?? "", Source = tagFile.Tag.Album ?? "", Tags = string.Join(" ", tagFile.Tag.Genres) ?? "", Creator = ConfigManager.Username.Value, DifficultyName = "", // Makes the file different to prevent exception thrown in the DB for same md5 checksum Description = $"Created at {TimeHelper.GetUnixTimestampMilliseconds()}", BackgroundFile = "", Mode = GameMode.Keys4 }; // Create a new directory to house the map. var dir = $"{ConfigManager.SongDirectory.Value}/{TimeHelper.GetUnixTimestampMilliseconds()}"; Directory.CreateDirectory(dir); // Copy over the audio file into the directory File.Copy(audioFile, $"{dir}/{Path.GetFileName(audioFile)}"); // Save the new .qua file into the directory var path = $"{dir}/{StringHelper.FileNameSafeString($"{qua.Artist} - {qua.Title} [{qua.DifficultyName}] - {TimeHelper.GetUnixTimestampMilliseconds()}")}.qua"; qua.Save(path); // Place the new map inside of the database and make sure all the loaded maps are correct var map = Map.FromQua(qua, path); map.Id = MapDatabaseCache.InsertMap(map, path); MapDatabaseCache.OrderAndSetMapsets(); MapManager.Selected.Value = map; MapManager.Selected.Value.Qua = qua; var selectedMapset = MapManager.Mapsets.Find(x => x.Maps.Any(y => y.Id == MapManager.Selected.Value.Id)); // Find the new object from the loaded maps that contains the same id. MapManager.Selected.Value = selectedMapset.Maps.Find(x => x.Id == MapManager.Selected.Value.Id); MapManager.Selected.Value.Qua = qua; MapManager.Selected.Value.NewlyCreated = true; game?.CurrentScreen.Exit(() => new EditorScreen(qua)); } catch (Exception e) { Logger.Error(e, LogType.Runtime); var game = GameBase.Game as QuaverGame; game?.CurrentScreen.Exit(() => { NotificationManager.Show(NotificationLevel.Error, "Could not create new mapset with that audio file."); return(new SelectScreen()); }); } }
/// <inheritdoc /> /// <summary> /// </summary> public DownloadableMapset(DownloadScrollContainer container, JToken mapset) { Container = container; Mapset = mapset; MapsetId = (int)Mapset["id"]; Size = new ScalableVector2(container.Width - 2, HEIGHT); Image = UserInterface.DownloadItem; Banner = new Sprite { Parent = this, X = 0, Size = new ScalableVector2(900 / 3.6f, Height), Alignment = Alignment.MidLeft, Alpha = 0 }; AlreadyOwned = new SpriteTextBitmap(FontsBitmap.GothamRegular, "Already Owned") { Parent = Banner, Alignment = Alignment.MidCenter, UsePreviousSpriteBatchOptions = true, FontSize = 14 }; // Check if the mapset is already owned. var set = MapDatabaseCache.FindSet(MapsetId); IsAlreadyOwned = set != null; AlreadyOwned.Alpha = IsAlreadyOwned ? 1 : 0; Title = new SpriteTextBitmap(FontsBitmap.GothamRegular, $"{Mapset["title"]}") { Parent = this, X = Banner.X + Banner.Width + 15, Y = 10, Alpha = IsAlreadyOwned ? 0.65f : 1, FontSize = 16 }; Artist = new SpriteTextBitmap(FontsBitmap.GothamRegular, $"{Mapset["artist"]}") { Parent = this, X = Title.X, Y = Title.Y + Title.Height + 5, Alpha = IsAlreadyOwned ? 0.65f : 1, FontSize = 14 }; var gameModes = Mapset["game_modes"].ToList(); var modes = new List <string>(); if (gameModes.Contains(1)) { modes.Add("4K"); } if (gameModes.Contains(2)) { modes.Add("7K"); } Modes = new SpriteTextBitmap(FontsBitmap.GothamRegular, string.Join(" & ", modes) + " | ") { Parent = this, X = Artist.X, Y = Artist.Y + Artist.Height + 5, Alpha = IsAlreadyOwned ? 0.65f : 1, FontSize = 14 }; Creator = new SpriteTextBitmap(FontsBitmap.GothamRegular, $"Created By: {Mapset["creator_username"]}") { Parent = this, Alignment = Alignment.BotRight, Position = new ScalableVector2(-10, -5), Alpha = IsAlreadyOwned ? 0.65f : 1, FontSize = 14 }; var lowestDiff = Mapset["difficulty_range"].ToList().Min(); var highestDiff = Mapset["difficulty_range"].ToList().Max(); // ReSharper disable once ObjectCreationAsStatement var low = new SpriteTextBitmap(FontsBitmap.GothamRegular, $"{lowestDiff:0.00}") { Parent = this, X = Modes.X + Modes.Width + 2, Y = Modes.Y, Alpha = IsAlreadyOwned ? 0.65f : 1, FontSize = 14, Tint = ColorHelper.DifficultyToColor((float)lowestDiff) }; if (lowestDiff != highestDiff) { var high = new SpriteTextBitmap(FontsBitmap.GothamRegular, $" - {highestDiff:0.00}") { Parent = this, X = low.X + low.Width + 2, Y = Modes.Y, Alpha = IsAlreadyOwned ? 0.65f : 1, FontSize = 14, Tint = ColorHelper.DifficultyToColor((float)highestDiff) }; } var badge = new BannerRankedStatus { Parent = this, Alignment = Alignment.TopRight, Position = new ScalableVector2(-10, 5), Alpha = IsAlreadyOwned ? 0.65f : 1, }; var screen = (DownloadScreen)container.View.Screen; badge.UpdateMap(new Map { RankedStatus = screen.CurrentRankedStatus }); FetchMapsetBanner(); // ReSharper disable once ObjectCreationAsStatement new Sprite() { Parent = this, Alignment = Alignment.BotLeft, Size = new ScalableVector2(Width, 1), Alpha = 0.65f }; Progress = new ProgressBar(new Vector2(Width - Banner.Width, Height), 0, 100, 0, Color.Transparent, Colors.MainAccent) { Parent = this, X = Banner.X + Banner.Width, ActiveBar = { UsePreviousSpriteBatchOptions = true, Alpha = 0.60f }, }; Clicked += (sender, args) => OnClicked(); }
/// <summary> /// Starts the deleting process. /// </summary> public void DeleteSelected() { // Externally loaded map check. if (MapManager.Selected.Value.Game != MapGame.Quaver) { // Display error message. NotificationManager.Show(NotificationLevel.Error, "This map was loaded from another game, and it cannot be deleted."); return; } var view = View as SelectScreenView; var type = view.ActiveContainer; var selectedMapsetIndex = view.MapsetScrollContainer.SelectedMapsetIndex; var selectedDifficultyIndex = view.DifficultyScrollContainer.SelectedMapIndex; var selectedMapset = AvailableMapsets[selectedMapsetIndex]; var selectedDifficulty = selectedMapset.Maps[selectedDifficultyIndex]; var mapsetPath = Path.Combine(ConfigManager.SongDirectory.Value, selectedMapset.Directory); var difficultyPath = Path.Combine(mapsetPath, selectedDifficulty.Path); // Commence deleting and reloading. var confirmDelete = new ConfirmCancelDialog($"Are you sure you want to delete this {( type == SelectContainerStatus.Mapsets ? "mapset" : "difficulty" )}?", (sender, confirm) => { var mapTitle = selectedMapset.Maps.First().Title; var deleteMapset = type == SelectContainerStatus.Mapsets || type == SelectContainerStatus.Difficulty && selectedMapset.Maps.Count == 1; // Dispose of the background for the currently selected map. BackgroundHelper.Background?.Dispose(); // Dispose of the currently playing track. AudioEngine.Track?.Dispose(); // Run path deletion in the background. ThreadScheduler.Run(() => DeletePath(deleteMapset ? mapsetPath : difficultyPath)); // Remove mapset/difficulty from cache and AvailableMapsets list. if (deleteMapset) { selectedMapset.Maps.ForEach(MapDatabaseCache.RemoveMap); AvailableMapsets.RemoveAt(selectedMapsetIndex); MapManager.Mapsets.RemoveAll(x => x.Directory == selectedMapset.Directory); view.MapsetScrollContainer.InitializeWithNewSets(); view.MapsetScrollContainer.SelectMapset(Math.Min(selectedMapsetIndex, AvailableMapsets.Count - 1)); } else { MapDatabaseCache.RemoveMap(selectedDifficulty); selectedMapset.Maps.RemoveAt(selectedDifficultyIndex); MapManager.Mapsets.Find(x => x.Directory == selectedMapset.Directory).Maps.RemoveAll(x => x.Md5Checksum == selectedDifficulty.Md5Checksum); view.DifficultyScrollContainer.ReInitializeDifficulties(); view.MapsetScrollContainer.SelectMap(selectedMapsetIndex, selectedMapset.Maps[Math.Min(selectedDifficultyIndex, selectedMapset.Maps.Count - 1)], true); } // Finally show confirmation notification. NotificationManager.Show(NotificationLevel.Success, $"Successfully deleted {mapTitle} from Quaver!"); // If the deleted mapset was the last one, then exit back to menu. if (MapManager.Mapsets.Count != 0) { return; } view.Destroy(); AudioEngine.Track = null; MapManager.Selected.Value = null; ExitToMenu(); }); // Finally show the confirmation dialog that orchestrates the deleting process. DialogManager.Show(confirmDelete); }
/// <summary> /// Creates the local and global offset fix buttons. /// </summary> private void CreateOffsetFixButtons() { // Don't draw the buttons if we don't have the hit stats (and therefore don't know the // values to adjust the offset by). if (Processor.Stats == null) { return; } var availableWidth = Width - VerticalDividerLine.X; var buttonPadding = 15; var buttonWidth = (availableWidth - buttonPadding * 3) / 2; var localOffsetButton = new BorderedTextButton("Fix Local Offset", Colors.MainAccent, (o, e) => { // Local offset is scaled with rate, so the adjustment depends on the rate the // score was played on. var change = HitStatistics.Mean * ModHelper.GetRateFromMods(Processor.Mods); var newOffset = (int)Math.Round(ResultScreen.Map.LocalOffset - change); DialogManager.Show(new ConfirmCancelDialog($"Local offset will be changed from {ResultScreen.Map.LocalOffset} ms to {newOffset} ms.", (o_, e_) => { ResultScreen.Map.LocalOffset = newOffset; MapDatabaseCache.UpdateMap(ResultScreen.Map); NotificationManager.Show(NotificationLevel.Success, $"Local offset was set to {ResultScreen.Map.LocalOffset} ms."); })); }) { Parent = this, X = VerticalDividerLine.X + buttonPadding, Y = BottomHorizontalDividerLine.Y - 15 - 25, Height = 30, Width = buttonWidth, Text = { Font = Fonts.SourceSansProSemiBold, FontSize = 13 } }; var globalOffsetButton = new BorderedTextButton("Fix Global Offset", Colors.MainAccent, (o, e) => { var newOffset = (int)Math.Round(ConfigManager.GlobalAudioOffset.Value + HitStatistics.Mean); DialogManager.Show(new ConfirmCancelDialog($"Global offset will be changed from {ConfigManager.GlobalAudioOffset.Value} ms to {newOffset} ms.", (o_, e_) => { ConfigManager.GlobalAudioOffset.Value = newOffset; NotificationManager.Show(NotificationLevel.Success, $"Global offset was set to {ConfigManager.GlobalAudioOffset.Value} ms."); })); }) { Parent = this, X = localOffsetButton.X + localOffsetButton.Width + buttonPadding, Y = BottomHorizontalDividerLine.Y - 15 - 25, Height = 30, Width = buttonWidth, Text = { Font = Fonts.SourceSansProSemiBold, FontSize = 13 } }; }
/// <inheritdoc /> /// <summary> /// </summary> public DownloadableMapset(DownloadScrollContainer container, JToken mapset) { Container = container; Mapset = mapset; MapsetId = (int)Mapset["id"]; Size = new ScalableVector2(container.Width, HEIGHT); Tint = Color.Black; Alpha = IsAlreadyOwned ? 0.25f : 0.45f; Banner = new Sprite { Parent = this, X = 0, Size = new ScalableVector2(900 / 3.6f, Height), Alignment = Alignment.MidLeft, Alpha = 0 }; AlreadyOwned = new SpriteText(Fonts.SourceSansProBold, "Already Owned", 13) { Parent = Banner, Alignment = Alignment.MidCenter, UsePreviousSpriteBatchOptions = true }; // Check if the mapset is already owned. var set = MapDatabaseCache.FindSet(MapsetId); IsAlreadyOwned = set != null; AlreadyOwned.Alpha = IsAlreadyOwned ? 1 : 0; Progress = new ProgressBar(new Vector2(Width - Banner.Width, Height), 0, 100, 0, Color.Transparent, Colors.MainAccent) { Parent = this, X = Banner.X + Banner.Width, ActiveBar = { UsePreviousSpriteBatchOptions = true, Alpha = 0.60f }, }; Title = new SpriteText(Fonts.SourceSansProBold, $"{Mapset["title"]}", 13) { Parent = this, X = Banner.X + Banner.Width + 15, Y = 6, Alpha = IsAlreadyOwned ? 0.65f : 1, }; Artist = new SpriteText(Fonts.SourceSansProBold, $"{Mapset["artist"]}", 12) { Parent = this, X = Title.X, Y = Title.Y + Title.Height, Alpha = IsAlreadyOwned ? 0.65f : 1, }; var gameModes = Mapset["game_modes"].ToList(); var modes = new List <string>(); if (gameModes.Contains(1)) { modes.Add("4K"); } if (gameModes.Contains(2)) { modes.Add("7K"); } Modes = new SpriteText(Fonts.SourceSansProBold, string.Join(" & ", modes), 11) { Parent = this, X = Artist.X, Y = Artist.Y + Artist.Height + 2, Alpha = IsAlreadyOwned ? 0.65f : 1, }; Creator = new SpriteText(Fonts.SourceSansProSemiBold, $"Created By: {Mapset["creator_username"]}", 11) { Parent = this, Alignment = Alignment.BotRight, Position = new ScalableVector2(-10, -5), Alpha = IsAlreadyOwned ? 0.65f : 1, }; var badge = new BannerRankedStatus { Parent = this, Alignment = Alignment.TopRight, Position = new ScalableVector2(-10, 5), Alpha = IsAlreadyOwned ? 0.65f : 1, }; var screen = (DownloadScreen)container.View.Screen; badge.UpdateMap(new Map { RankedStatus = screen.CurrentRankedStatus }); FetchMapsetBanner(); Clicked += (sender, args) => OnClicked(); }
/// <summary> /// Uploads the mapset to the server /// </summary> private void UploadMapset() => ThreadScheduler.Run(() => { try { Logger.Important($"Starting to upload mapset...", LogType.Network); var path = MapManager.Selected.Value.Mapset.ExportToZip(false); Response = OnlineManager.Client.UploadMapset(path); Logger.Important($"Uploaded mapset with response: {Response}", LogType.Network); File.Delete(path); // ReSharper disable once SwitchStatementMissingSomeCases switch (Response.Code) { case MapsetSubmissionStatusCode.SuccessUpdated: case MapsetSubmissionStatusCode.SuccessUploaded: // Get all files in the directory and delete them, so we can get the updated ones foreach (var f in Directory.GetFiles($"{ConfigManager.SongDirectory.Value}/{MapManager.Selected.Value.Directory}", "*.qua")) { File.Delete(f); } using (var conn = new SQLiteConnection(MapDatabaseCache.DatabasePath)) MapManager.Selected.Value.Mapset.Maps.ForEach(x => conn.Delete(x)); foreach (var map in Response.Maps) { if (map == null) { continue; } var filePath = $"{ConfigManager.SongDirectory.Value}/{MapManager.Selected.Value.Directory}/{map.Id}.qua"; Logger.Important($"Commencing download for map: {map.Id}", LogType.Runtime); try { OnlineManager.Client.DownloadMap(filePath, map.Id); Logger.Important($"Successfully downloaded map: {map.Id}", LogType.Network); } catch (Exception) { continue; } MapDatabaseCache.MapsToUpdate.Add(Map.FromQua(Qua.Parse(filePath), filePath)); Thread.Sleep(1000); } DividerLine.Tint = Color.LimeGreen; TopLine.Tint = Color.LimeGreen; MapDatabaseCache.ForceUpdateMaps(); break; default: DividerLine.Tint = Color.Crimson; TopLine.Tint = Color.Crimson; break; } Header.Text = StatusCodeMessages[Response.Code]; } catch (Exception e) { Logger.Error(e, LogType.Network); DividerLine.Tint = Color.Crimson; TopLine.Tint = Color.Crimson; Header.Text = "An unknown error has occurred while uploading. Please check your log files!"; } finally { LoadingWheel.Visible = false; CreateCloseButton(); if (Response != null && (Response.Code == MapsetSubmissionStatusCode.SuccessUpdated || Response.Code == MapsetSubmissionStatusCode.SuccessUploaded)) { CloseButton.Border.Tint = Color.LimeGreen; CloseButton.Text.Tint = Color.LimeGreen; CreateVisitMapsetPageButton(); VisitMapsetPageButton.X = -VisitMapsetPageButton.Width / 2f - 10; CloseButton.X = CloseButton.Width / 2f + 10; } } });
/// <summary> /// Handles the input of the game + individual game modes. /// </summary> /// <param name="gameTime"></param> private void HandleInput(GameTime gameTime) { if (Exiting) { return; } var dt = gameTime.ElapsedGameTime.TotalMilliseconds; // Handle pausing if (!Failed && !IsPlayComplete) { HandlePauseInput(gameTime); } // Show/hide scoreboard. if (KeyboardManager.IsUniqueKeyPress(ConfigManager.KeyScoreboardVisible.Value)) { ConfigManager.ScoreboardVisible.Value = !ConfigManager.ScoreboardVisible.Value; } // CTRL+ input while play testing if (IsPlayTesting && (KeyboardManager.CurrentState.IsKeyDown(Keys.LeftControl) || KeyboardManager.CurrentState.IsKeyDown(Keys.RightControl))) { if (KeyboardManager.IsUniqueKeyPress(Keys.P)) { if (!AudioEngine.Track.IsDisposed) { if (AudioEngine.Track.IsPlaying) { AudioEngine.Track.Pause(); IsPaused = true; } else { AudioEngine.Track.Play(); IsPaused = false; } } } } // Handle the restarting of the map. HandlePlayRestart(dt); // Everything after this point is applicable to gameplay ONLY. if (IsPaused || Failed) { return; } if (!IsPlayComplete && !IsCalibratingOffset || IsMultiplayerGame) { if (KeyboardManager.IsUniqueKeyPress(ConfigManager.KeyQuickExit.Value)) { HandleQuickExit(); } } if (!IsPlayComplete && !IsCalibratingOffset) { if (KeyboardManager.IsUniqueKeyPress(ConfigManager.KeySkipIntro.Value)) { SkipToNextObject(); } // Go back to editor at the same time if (IsPlayTesting && KeyboardManager.IsUniqueKeyPress(Keys.F2)) { if (AudioEngine.Track.IsPlaying) { AudioEngine.Track.Pause(); } Exit(() => new EditorScreen(OriginalEditorMap)); } // Handle play test autoplay input. if (IsPlayTesting && KeyboardManager.IsUniqueKeyPress(Keys.Tab)) { var inputManager = (KeysInputManager)Ruleset.InputManager; if (LoadedReplay == null) { LoadedReplay = ReplayHelper.GeneratePerfectReplay(Map, MapHash); inputManager.ReplayInputManager = new ReplayInputManagerKeys(this); inputManager.ReplayInputManager.HandleSkip(); inputManager.ReplayInputManager.CurrentFrame++; } InReplayMode = !InReplayMode; inputManager.ReplayInputManager.HandleSkip(); inputManager.ReplayInputManager.CurrentFrame++; if (!InReplayMode) { for (var i = 0; i < Map.GetKeyCount(); i++) { inputManager.ReplayInputManager.UniquePresses[i] = false; inputManager.ReplayInputManager.UniqueReleases[i] = true; inputManager.BindingStore[i].Pressed = false; var playfield = (GameplayPlayfieldKeys)Ruleset.Playfield; playfield.Stage.HitLightingObjects[i].StopHolding(); playfield.Stage.SetReceptorAndLightingActivity(i, inputManager.BindingStore[i].Pressed); } inputManager.HandleInput(gameTime.ElapsedGameTime.TotalMilliseconds); } NotificationManager.Show(NotificationLevel.Info, $"Autoplay has been turned {(InReplayMode ? "on" : "off")}"); } // Only allow offset changes if the map hasn't started or if we're on a break if (Ruleset.Screen.Timing.Time <= 5000 || Ruleset.Screen.EligibleToSkip) { var change = 5; if (KeyboardManager.CurrentState.IsKeyDown(Keys.LeftControl) || KeyboardManager.CurrentState.IsKeyDown(Keys.RightControl)) { change = 1; } // Handle offset + if (KeyboardManager.IsUniqueKeyPress(ConfigManager.KeyIncreaseMapOffset.Value)) { MapManager.Selected.Value.LocalOffset += change; NotificationManager.Show(NotificationLevel.Success, $"Local map offset is now: {MapManager.Selected.Value.LocalOffset} ms"); MapDatabaseCache.UpdateMap(MapManager.Selected.Value); } // Handle offset - if (KeyboardManager.IsUniqueKeyPress(ConfigManager.KeyDecreaseMapOffset.Value)) { MapManager.Selected.Value.LocalOffset -= change; NotificationManager.Show(NotificationLevel.Success, $"Local map offset is now: {MapManager.Selected.Value.LocalOffset} ms"); MapDatabaseCache.UpdateMap(MapManager.Selected.Value); } } } // Handle input per game mode. Ruleset.HandleInput(gameTime); }