diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 8c97a65c3a..86c97df191 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; +using osu.Framework; using osu.Framework.Extensions; using osu.Framework.IO.File; using osu.Framework.Logging; @@ -53,6 +54,8 @@ namespace osu.Game.Database public virtual string[] HandledExtensions => new[] { ".zip" }; + public virtual bool SupportsImportFromStable => RuntimeInfo.IsDesktop; + protected readonly FileStore Files; protected readonly IDatabaseContextFactory ContextFactory; diff --git a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs index 4d889856f6..188c9c05ef 100644 --- a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs @@ -1,8 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework; using osu.Framework.Allocation; -using osu.Framework.Graphics; using osu.Framework.Platform; using osu.Game.Configuration; @@ -15,19 +15,20 @@ namespace osu.Game.Overlays.Settings.Sections.General [BackgroundDependencyLoader] private void load(Storage storage, OsuConfigManager config) { - Children = new Drawable[] + Add(new SettingsEnumDropdown { - new SettingsEnumDropdown - { - LabelText = "Release stream", - Bindable = config.GetBindable(OsuSetting.ReleaseStream), - }, - new SettingsButton + LabelText = "Release stream", + Bindable = config.GetBindable(OsuSetting.ReleaseStream), + }); + + if (RuntimeInfo.IsDesktop) + { + Add(new SettingsButton { Text = "Open osu! folder", Action = storage.OpenInNativeExplorer, - } - }; + }); + } } } } diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs index d512652938..398a091486 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs @@ -25,9 +25,9 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance [BackgroundDependencyLoader] private void load(BeatmapManager beatmaps, SkinManager skins, DialogOverlay dialogOverlay) { - Children = new Drawable[] + if (beatmaps.SupportsImportFromStable) { - importBeatmapsButton = new SettingsButton + Add(importBeatmapsButton = new SettingsButton { Text = "Import beatmaps from stable", Action = () => @@ -35,20 +35,25 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance importBeatmapsButton.Enabled.Value = false; beatmaps.ImportFromStableAsync().ContinueWith(t => Schedule(() => importBeatmapsButton.Enabled.Value = true)); } - }, - deleteBeatmapsButton = new DangerousSettingsButton + }); + } + + Add(deleteBeatmapsButton = new DangerousSettingsButton + { + Text = "Delete ALL beatmaps", + Action = () => { - Text = "Delete ALL beatmaps", - Action = () => + dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() => { - dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() => - { - deleteBeatmapsButton.Enabled.Value = false; - Task.Run(() => beatmaps.Delete(beatmaps.GetAllUsableBeatmapSets())).ContinueWith(t => Schedule(() => deleteBeatmapsButton.Enabled.Value = true)); - })); - } - }, - importSkinsButton = new SettingsButton + deleteBeatmapsButton.Enabled.Value = false; + Task.Run(() => beatmaps.Delete(beatmaps.GetAllUsableBeatmapSets())).ContinueWith(t => Schedule(() => deleteBeatmapsButton.Enabled.Value = true)); + })); + } + }); + + if (skins.SupportsImportFromStable) + { + Add(importSkinsButton = new SettingsButton { Text = "Import skins from stable", Action = () => @@ -56,7 +61,11 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance importSkinsButton.Enabled.Value = false; skins.ImportFromStableAsync().ContinueWith(t => Schedule(() => importSkinsButton.Enabled.Value = true)); } - }, + }); + } + + AddRange(new Drawable[] + { deleteSkinsButton = new DangerousSettingsButton { Text = "Delete ALL skins", @@ -91,7 +100,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Task.Run(() => beatmaps.Undelete(beatmaps.QueryBeatmapSets(b => b.DeletePending).ToList())).ContinueWith(t => Schedule(() => undeleteButton.Enabled.Value = true)); } }, - }; + }); } } } diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index c922e4ef4a..f2d2381d20 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -22,6 +22,8 @@ using osu.Game.Screens.Edit.Components.Menus; using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Design; using osuTK.Input; +using System.Collections.Generic; +using osu.Framework; namespace osu.Game.Screens.Edit { @@ -67,6 +69,15 @@ namespace osu.Game.Screens.Edit SummaryTimeline timeline; PlaybackControl playback; + var fileMenuItems = new List(); + if (RuntimeInfo.IsDesktop) + { + fileMenuItems.Add(new EditorMenuItem("Export", MenuItemType.Standard, exportBeatmap)); + fileMenuItems.Add(new EditorMenuItemSpacer()); + } + + fileMenuItems.Add(new EditorMenuItem("Exit", MenuItemType.Standard, this.Exit)); + InternalChildren = new[] { new Container @@ -94,12 +105,7 @@ namespace osu.Game.Screens.Edit { new MenuItem("File") { - Items = new[] - { - new EditorMenuItem("Export", MenuItemType.Standard, exportBeatmap), - new EditorMenuItemSpacer(), - new EditorMenuItem("Exit", MenuItemType.Standard, this.Exit) - } + Items = fileMenuItems } } } diff --git a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs index 3e4694e232..b299e70962 100644 --- a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs @@ -39,6 +39,7 @@ namespace osu.Game.Screens.Multi.Match.Components private void load() { beatmaps.ItemAdded += beatmapAdded; + beatmaps.ItemRemoved += beatmapRemoved; Beatmap.BindValueChanged(b => updateBeatmap(b.NewValue), true); } @@ -62,6 +63,15 @@ namespace osu.Game.Screens.Multi.Match.Components Schedule(() => hasBeatmap = true); } + private void beatmapRemoved(BeatmapSetInfo model) + { + if (Beatmap.Value == null) + return; + + if (model.OnlineBeatmapSetID == Beatmap.Value.BeatmapSet.OnlineBeatmapSetID) + Schedule(() => hasBeatmap = false); + } + protected override void Update() { base.Update(); diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index c3f7cea43e..229b9bde6a 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Multi.Match protected Bindable CurrentItem { get; private set; } [Resolved] - protected Bindable> CurrentMods { get; private set; } + protected Bindable> SelectedMods { get; private set; } [Resolved] private BeatmapManager beatmapManager { get; set; } @@ -194,7 +194,7 @@ namespace osu.Game.Screens.Multi.Match var localBeatmap = e.NewValue?.Beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == e.NewValue.Beatmap.OnlineBeatmapID); Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); - CurrentMods.Value = e.NewValue?.RequiredMods ?? Enumerable.Empty(); + SelectedMods.Value = e.NewValue?.RequiredMods ?? Enumerable.Empty(); if (e.NewValue?.Ruleset != null) Ruleset.Value = e.NewValue.Ruleset; } @@ -222,7 +222,7 @@ namespace osu.Game.Screens.Multi.Match private void onStart() { - Beatmap.Value.Mods.Value = CurrentMods.Value.ToArray(); + Beatmap.Value.Mods.Value = SelectedMods.Value.ToArray(); switch (type.Value) { diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs index d127bdc0ea..6b88403b9e 100644 --- a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs +++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs @@ -2,7 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Threading; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -11,6 +13,8 @@ using osu.Framework.Screens; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Scoring; using osu.Game.Screens.Multi.Ranking; using osu.Game.Screens.Play; @@ -30,6 +34,12 @@ namespace osu.Game.Screens.Multi.Play [Resolved] private APIAccess api { get; set; } + [Resolved] + private IBindable ruleset { get; set; } + + [Resolved] + private Bindable> selectedMods { get; set; } + public TimeshiftPlayer(PlaylistItem playlistItem) { this.playlistItem = playlistItem; @@ -44,6 +54,16 @@ namespace osu.Game.Screens.Multi.Play bool failed = false; + // Sanity checks to ensure that TimeshiftPlayer matches the settings for the current PlaylistItem + if (Beatmap.Value.BeatmapInfo.OnlineBeatmapID != playlistItem.Beatmap.OnlineBeatmapID) + throw new InvalidOperationException("Current Beatmap does not match PlaylistItem's Beatmap"); + + if (ruleset.Value.ID != playlistItem.Ruleset.ID) + throw new InvalidOperationException("Current Ruleset does not match PlaylistItem's Ruleset"); + + if (!playlistItem.RequiredMods.All(m => selectedMods.Value.Contains(m))) + throw new InvalidOperationException("Current Mods do not match PlaylistItem's RequiredMods"); + var req = new CreateRoomScoreRequest(roomId.Value ?? 0, playlistItem.ID); req.Success += r => token = r.ID; req.Failure += e => diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index cfeaa1785e..f6d758df29 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -2,10 +2,15 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using Humanizer; +using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Screens; +using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.Multi; namespace osu.Game.Screens.Select @@ -17,6 +22,15 @@ namespace osu.Game.Screens.Select public string ShortTitle => "song selection"; public override string Title => ShortTitle.Humanize(); + [Resolved(typeof(Room))] + protected Bindable CurrentItem { get; private set; } + + [Resolved] + private Bindable> selectedMods { get; set; } + + [Resolved] + private BeatmapManager beatmaps { get; set; } + public MatchSongSelect() { Padding = new MarginPadding { Horizontal = HORIZONTAL_OVERFLOW_PADDING }; @@ -43,10 +57,17 @@ namespace osu.Game.Screens.Select public override bool OnExiting(IScreen next) { + if (base.OnExiting(next)) + return true; + + Beatmap.Value = beatmaps.GetWorkingBeatmap(CurrentItem.Value?.Beatmap); + Beatmap.Value.Mods.Value = selectedMods.Value = CurrentItem.Value?.RequiredMods; + Ruleset.Value = CurrentItem.Value?.Ruleset; + Beatmap.Disabled = true; Ruleset.Disabled = true; - return base.OnExiting(next); + return false; } public override void OnEntering(IScreen last) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 82c23fc491..f8d89ec8a5 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index f95f42d933..16eeb46683 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + +