diff --git a/osu.Android.props b/osu.Android.props
index 7b22b76e0e..5ee0573c58 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -11,7 +11,7 @@
Off
True
Xamarin.Android.Net.AndroidClientHandler
- v8.1
+ v9.0
false
diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml
index 326d32f7ab..acd21f9587 100644
--- a/osu.Android/Properties/AndroidManifest.xml
+++ b/osu.Android/Properties/AndroidManifest.xml
@@ -1,6 +1,6 @@
-
-
+
+
diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj
index 42a3185cd1..ac3905a372 100644
--- a/osu.Android/osu.Android.csproj
+++ b/osu.Android/osu.Android.csproj
@@ -14,6 +14,11 @@
Properties\AndroidManifest.xml
armeabi-v7a;x86;arm64-v8a
+
+ cjk;mideast;other;rare;west
+ d8
+ r8
+
diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml
index b04b0718f5..db95e18f13 100644
--- a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml
+++ b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml
index c315581606..e6728c801d 100644
--- a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml
+++ b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml
index dac9c19477..aad907b241 100644
--- a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml
+++ b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml
index f731042a4c..cd4b74aa16 100644
--- a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml
+++ b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/osu.Game.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Tests.Android/Properties/AndroidManifest.xml
index 146f96c2a3..bb996dc5ca 100644
--- a/osu.Game.Tests.Android/Properties/AndroidManifest.xml
+++ b/osu.Game.Tests.Android/Properties/AndroidManifest.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs
index 860c7fc0fa..7ef50da7d3 100644
--- a/osu.Game/Beatmaps/BeatmapManager.cs
+++ b/osu.Game/Beatmaps/BeatmapManager.cs
@@ -82,6 +82,8 @@ namespace osu.Game.Beatmaps
protected override ArchiveDownloadRequest CreateDownloadRequest(BeatmapSetInfo set, bool minimiseDownloadSize) =>
new DownloadBeatmapSetRequest(set, minimiseDownloadSize);
+ protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == ".osz";
+
protected override Task Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive, CancellationToken cancellationToken = default)
{
if (archive != null)
@@ -176,20 +178,23 @@ namespace osu.Game.Beatmaps
if (beatmapInfo?.BeatmapSet == null || beatmapInfo == DefaultBeatmap?.BeatmapInfo)
return DefaultBeatmap;
- var cached = workingCache.FirstOrDefault(w => w.BeatmapInfo?.ID == beatmapInfo.ID);
+ lock (workingCache)
+ {
+ var cached = workingCache.FirstOrDefault(w => w.BeatmapInfo?.ID == beatmapInfo.ID);
- if (cached != null)
- return cached;
+ if (cached != null)
+ return cached;
- if (beatmapInfo.Metadata == null)
- beatmapInfo.Metadata = beatmapInfo.BeatmapSet.Metadata;
+ if (beatmapInfo.Metadata == null)
+ beatmapInfo.Metadata = beatmapInfo.BeatmapSet.Metadata;
- WorkingBeatmap working = new BeatmapManagerWorkingBeatmap(Files.Store, new LargeTextureStore(host?.CreateTextureLoaderStore(Files.Store)), beatmapInfo, audioManager);
+ WorkingBeatmap working = new BeatmapManagerWorkingBeatmap(Files.Store, new LargeTextureStore(host?.CreateTextureLoaderStore(Files.Store)), beatmapInfo, audioManager);
- previous?.TransferTo(working);
- workingCache.Add(working);
+ previous?.TransferTo(working);
+ workingCache.Add(working);
- return working;
+ return working;
+ }
}
///
diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs
index 01455e7d50..ed65bdc069 100644
--- a/osu.Game/Database/ArchiveModelManager.cs
+++ b/osu.Game/Database/ArchiveModelManager.cs
@@ -1,4 +1,4 @@
-// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
@@ -114,7 +114,8 @@ namespace osu.Game.Database
lock (imported)
{
- imported.Add(model);
+ if (model != null)
+ imported.Add(model);
current++;
notification.Text = $"Imported {current} of {paths.Length} {HumanisedModelName}s";
@@ -140,7 +141,7 @@ namespace osu.Game.Database
{
notification.CompletionText = imported.Count == 1
? $"Imported {imported.First()}!"
- : $"Imported {current} {HumanisedModelName}s!";
+ : $"Imported {imported.Count} {HumanisedModelName}s!";
if (imported.Count > 0 && PresentImport != null)
{
@@ -176,7 +177,7 @@ namespace osu.Game.Database
// TODO: Add a check to prevent files from storage to be deleted.
try
{
- if (import != null && File.Exists(path))
+ if (import != null && File.Exists(path) && ShouldDeleteArchive(path))
File.Delete(path);
}
catch (Exception e)
@@ -207,7 +208,7 @@ namespace osu.Game.Database
{
model = CreateModel(archive);
- if (model == null) return null;
+ if (model == null) return Task.FromResult(null);
model.Hash = computeHash(archive);
}
@@ -498,6 +499,18 @@ namespace osu.Game.Database
///
protected virtual string ImportFromStablePath => null;
+ ///
+ /// Select paths to import from stable. Default implementation iterates all directories in .
+ ///
+ protected virtual IEnumerable GetStableImportPaths(Storage stableStoage) => stableStoage.GetDirectories(ImportFromStablePath);
+
+ ///
+ /// Whether this specified path should be removed after successful import.
+ ///
+ /// The path for consideration. May be a file or a directory.
+ /// Whether to perform deletion.
+ protected virtual bool ShouldDeleteArchive(string path) => false;
+
///
/// This is a temporary method and will likely be replaced by a full-fledged (and more correctly placed) migration process in the future.
///
@@ -518,7 +531,7 @@ namespace osu.Game.Database
return Task.CompletedTask;
}
- return Task.Run(async () => await Import(stable.GetDirectories(ImportFromStablePath).Select(f => stable.GetFullPath(f)).ToArray()));
+ return Task.Run(async () => await Import(GetStableImportPaths(GetStableStorage()).Select(f => stable.GetFullPath(f)).ToArray()));
}
#endregion
diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs
index 869005d05c..8134cfb42d 100644
--- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs
+++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs
@@ -37,6 +37,8 @@ namespace osu.Game.Graphics.UserInterface
text.Colour = AccentColour;
icon.Colour = AccentColour;
}
+
+ updateFade();
}
}
@@ -48,39 +50,6 @@ namespace osu.Game.Graphics.UserInterface
private const float transition_length = 500;
- private void fadeIn()
- {
- box.FadeIn(transition_length, Easing.OutQuint);
- text.FadeColour(Color4.White, transition_length, Easing.OutQuint);
- }
-
- private void fadeOut()
- {
- box.FadeOut(transition_length, Easing.OutQuint);
- text.FadeColour(AccentColour, transition_length, Easing.OutQuint);
- }
-
- protected override bool OnHover(HoverEvent e)
- {
- fadeIn();
- return base.OnHover(e);
- }
-
- protected override void OnHoverLost(HoverLostEvent e)
- {
- if (!Current.Value)
- fadeOut();
-
- base.OnHoverLost(e);
- }
-
- [BackgroundDependencyLoader]
- private void load(OsuColour colours)
- {
- if (accentColour == null)
- AccentColour = colours.Blue;
- }
-
public OsuTabControlCheckbox()
{
AutoSizeAxes = Axes.Both;
@@ -115,19 +84,34 @@ namespace osu.Game.Graphics.UserInterface
}
};
- Current.ValueChanged += selected =>
- {
- if (selected.NewValue)
- {
- fadeIn();
- icon.Icon = FontAwesome.Regular.CheckCircle;
- }
- else
- {
- fadeOut();
- icon.Icon = FontAwesome.Regular.Circle;
- }
- };
+ Current.ValueChanged += selected => { icon.Icon = selected.NewValue ? FontAwesome.Regular.CheckCircle : FontAwesome.Regular.Circle; };
+ }
+
+ [BackgroundDependencyLoader]
+ private void load(OsuColour colours)
+ {
+ if (accentColour == null)
+ AccentColour = colours.Blue;
+ }
+
+ protected override bool OnHover(HoverEvent e)
+ {
+ updateFade();
+ return base.OnHover(e);
+ }
+
+ protected override void OnHoverLost(HoverLostEvent e)
+ {
+ if (!Current.Value)
+ updateFade();
+
+ base.OnHoverLost(e);
+ }
+
+ private void updateFade()
+ {
+ box.FadeTo(IsHovered ? 1 : 0, transition_length, Easing.OutQuint);
+ text.FadeColour(IsHovered ? Color4.White : AccentColour, transition_length, Easing.OutQuint);
}
}
}
diff --git a/osu.Game/Online/DownloadTrackingComposite.cs b/osu.Game/Online/DownloadTrackingComposite.cs
index 786afdf450..62d6efcb6f 100644
--- a/osu.Game/Online/DownloadTrackingComposite.cs
+++ b/osu.Game/Online/DownloadTrackingComposite.cs
@@ -11,7 +11,7 @@ using osu.Game.Online.API;
namespace osu.Game.Online
{
///
- /// A component which tracks a beatmap through potential download/import/deletion.
+ /// A component which tracks a through potential download/import/deletion.
///
public abstract class DownloadTrackingComposite : CompositeDrawable
where TModel : class, IEquatable
@@ -22,7 +22,7 @@ namespace osu.Game.Online
private TModelManager manager;
///
- /// Holds the current download state of the beatmap, whether is has already been downloaded, is in progress, or is not downloaded.
+ /// Holds the current download state of the , whether is has already been downloaded, is in progress, or is not downloaded.
///
protected readonly Bindable State = new Bindable();
diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs
index b91de93a4a..dea2ff1a21 100644
--- a/osu.Game/Online/Leaderboards/Leaderboard.cs
+++ b/osu.Game/Online/Leaderboards/Leaderboard.cs
@@ -231,12 +231,6 @@ namespace osu.Game.Online.Leaderboards
if (getScoresRequest == null)
return;
- if (api?.IsLoggedIn != true)
- {
- PlaceholderState = PlaceholderState.NotLoggedIn;
- return;
- }
-
getScoresRequest.Failure += e => Schedule(() =>
{
if (e is OperationCanceledException)
diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs
index 7087df83d7..0a472d4dc1 100644
--- a/osu.Game/OsuGame.cs
+++ b/osu.Game/OsuGame.cs
@@ -387,6 +387,7 @@ namespace osu.Game
BeatmapManager.PresentImport = items => PresentBeatmap(items.First());
ScoreManager.PostNotification = n => notifications?.Post(n);
+ ScoreManager.GetStableStorage = GetStorageForStableInstall;
ScoreManager.PresentImport = items => PresentScore(items.First());
Container logoContainer;
diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs
index 398a091486..832673703b 100644
--- a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs
+++ b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs
@@ -7,6 +7,7 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Game.Graphics.UserInterface;
+using osu.Game.Scoring;
using osu.Game.Skinning;
namespace osu.Game.Overlays.Settings.Sections.Maintenance
@@ -16,14 +17,16 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
protected override string Header => "General";
private TriangleButton importBeatmapsButton;
+ private TriangleButton importScoresButton;
private TriangleButton importSkinsButton;
- private TriangleButton deleteSkinsButton;
private TriangleButton deleteBeatmapsButton;
+ private TriangleButton deleteScoresButton;
+ private TriangleButton deleteSkinsButton;
private TriangleButton restoreButton;
private TriangleButton undeleteButton;
[BackgroundDependencyLoader]
- private void load(BeatmapManager beatmaps, SkinManager skins, DialogOverlay dialogOverlay)
+ private void load(BeatmapManager beatmaps, ScoreManager scores, SkinManager skins, DialogOverlay dialogOverlay)
{
if (beatmaps.SupportsImportFromStable)
{
@@ -51,6 +54,32 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
}
});
+ if (scores.SupportsImportFromStable)
+ {
+ Add(importScoresButton = new SettingsButton
+ {
+ Text = "Import scores from stable",
+ Action = () =>
+ {
+ importScoresButton.Enabled.Value = false;
+ scores.ImportFromStableAsync().ContinueWith(t => Schedule(() => importScoresButton.Enabled.Value = true));
+ }
+ });
+ }
+
+ Add(deleteScoresButton = new DangerousSettingsButton
+ {
+ Text = "Delete ALL scores",
+ Action = () =>
+ {
+ dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() =>
+ {
+ deleteScoresButton.Enabled.Value = false;
+ Task.Run(() => scores.Delete(scores.GetAllUsableScores())).ContinueWith(t => Schedule(() => deleteScoresButton.Enabled.Value = true));
+ }));
+ }
+ });
+
if (skins.SupportsImportFromStable)
{
Add(importSkinsButton = new SettingsButton
diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs
index 2d82987da0..8475158c78 100644
--- a/osu.Game/Scoring/ScoreManager.cs
+++ b/osu.Game/Scoring/ScoreManager.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
@@ -24,7 +25,7 @@ namespace osu.Game.Scoring
protected override string[] HashableFileTypes => new[] { ".osr" };
- protected override string ImportFromStablePath => "Replays";
+ protected override string ImportFromStablePath => Path.Combine("Data", "r");
private readonly RulesetStore rulesets;
private readonly Func beatmaps;
@@ -55,6 +56,9 @@ namespace osu.Game.Scoring
}
}
+ protected override IEnumerable GetStableImportPaths(Storage stableStorage)
+ => stableStorage.GetFiles(ImportFromStablePath).Where(p => HandledExtensions.Any(ext => Path.GetExtension(p)?.Equals(ext, StringComparison.InvariantCultureIgnoreCase) ?? false));
+
public Score GetScore(ScoreInfo score) => new LegacyDatabasedScore(score, rulesets, beatmaps(), Files.Store);
public List GetAllUsableScores() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList();
@@ -65,6 +69,6 @@ namespace osu.Game.Scoring
protected override ArchiveDownloadRequest CreateDownloadRequest(ScoreInfo score, bool minimiseDownload) => new DownloadReplayRequest(score);
- protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable items) => items.Any(s => s.OnlineScoreID == model.OnlineScoreID);
+ protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable items) => items.Any(s => s.OnlineScoreID == model.OnlineScoreID && s.Files.Any());
}
}
diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs
index dab5066c52..f6fbcf6498 100644
--- a/osu.Game/Screens/Menu/Intro.cs
+++ b/osu.Game/Screens/Menu/Intro.cs
@@ -33,13 +33,18 @@ namespace osu.Game.Screens.Menu
protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack();
+ private readonly BindableDouble exitingVolumeFade = new BindableDouble(1);
+
+ [Resolved]
+ private AudioManager audio { get; set; }
+
private Bindable menuVoice;
private Bindable menuMusic;
private Track track;
private WorkingBeatmap introBeatmap;
[BackgroundDependencyLoader]
- private void load(AudioManager audio, OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game)
+ private void load(OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game)
{
menuVoice = config.GetBindable(OsuSetting.MenuVoice);
menuMusic = config.GetBindable(OsuSetting.MenuMusic);
@@ -161,7 +166,8 @@ namespace osu.Game.Screens.Menu
else
fadeOutTime = 500;
- Scheduler.AddDelayed(this.Exit, fadeOutTime);
+ audio.AddAdjustment(AdjustableProperty.Volume, exitingVolumeFade);
+ this.TransformBindableTo(exitingVolumeFade, 0, fadeOutTime).OnComplete(_ => this.Exit());
//don't want to fade out completely else we will stop running updates.
Game.FadeTo(0.01f, fadeOutTime);
diff --git a/osu.Game/Screens/Play/ReplayDownloadButton.cs b/osu.Game/Screens/Play/ReplayDownloadButton.cs
index 748fe8cc90..290e00f287 100644
--- a/osu.Game/Screens/Play/ReplayDownloadButton.cs
+++ b/osu.Game/Screens/Play/ReplayDownloadButton.cs
@@ -86,11 +86,7 @@ namespace osu.Game.Screens.Play
}
}, true);
- if (replayAvailability == ReplayAvailability.NotAvailable)
- {
- button.Enabled.Value = false;
- button.Alpha = 0.6f;
- }
+ button.Enabled.Value = replayAvailability != ReplayAvailability.NotAvailable;
}
private enum ReplayAvailability
diff --git a/osu.Game/Screens/Select/EditSongSelect.cs b/osu.Game/Screens/Select/EditSongSelect.cs
deleted file mode 100644
index bdf5f905fe..0000000000
--- a/osu.Game/Screens/Select/EditSongSelect.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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.Screens;
-
-namespace osu.Game.Screens.Select
-{
- public class EditSongSelect : SongSelect
- {
- protected override bool ShowFooter => false;
-
- protected override bool OnStart()
- {
- this.Exit();
- return true;
- }
- }
-}
diff --git a/osu.Game/Screens/Select/ImportFromStablePopup.cs b/osu.Game/Screens/Select/ImportFromStablePopup.cs
index 54e4c096f6..20494829ae 100644
--- a/osu.Game/Screens/Select/ImportFromStablePopup.cs
+++ b/osu.Game/Screens/Select/ImportFromStablePopup.cs
@@ -12,7 +12,7 @@ namespace osu.Game.Screens.Select
public ImportFromStablePopup(Action importFromStable)
{
HeaderText = @"You have no beatmaps!";
- BodyText = "An existing copy of osu! was found, though.\nWould you like to import your beatmaps (and skins)?";
+ BodyText = "An existing copy of osu! was found, though.\nWould you like to import your beatmaps, skins and scores?";
Icon = FontAwesome.Solid.Plane;
diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs
index 62f93afbbb..68f153a97d 100644
--- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs
+++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs
@@ -62,6 +62,12 @@ namespace osu.Game.Screens.Select.Leaderboards
return null;
}
+ if (api?.IsLoggedIn != true)
+ {
+ PlaceholderState = PlaceholderState.NotLoggedIn;
+ return null;
+ }
+
if (Beatmap?.OnlineBeatmapID == null)
{
PlaceholderState = PlaceholderState.Unavailable;
diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs
index 3581ed5534..bf5857f725 100644
--- a/osu.Game/Screens/Select/SongSelect.cs
+++ b/osu.Game/Screens/Select/SongSelect.cs
@@ -35,6 +35,7 @@ using System.Linq;
using System.Threading.Tasks;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Bindings;
+using osu.Game.Scoring;
namespace osu.Game.Screens.Select
{
@@ -215,7 +216,7 @@ namespace osu.Game.Screens.Select
}
[BackgroundDependencyLoader(true)]
- private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins)
+ private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores)
{
mods.BindTo(Mods);
@@ -252,7 +253,7 @@ namespace osu.Game.Screens.Select
if (!beatmaps.GetAllUsableBeatmapSets().Any() && beatmaps.StableInstallationAvailable)
dialogOverlay.Push(new ImportFromStablePopup(() =>
{
- Task.Run(beatmaps.ImportFromStableAsync);
+ Task.Run(beatmaps.ImportFromStableAsync).ContinueWith(_ => scores.ImportFromStableAsync(), TaskContinuationOptions.OnlyOnRanToCompletion);
Task.Run(skins.ImportFromStableAsync);
}));
});
diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs
index 73cc47ea47..70abfac501 100644
--- a/osu.Game/Skinning/SkinManager.cs
+++ b/osu.Game/Skinning/SkinManager.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
@@ -54,6 +55,8 @@ namespace osu.Game.Skinning
};
}
+ protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == ".osk";
+
///
/// Returns a list of all usable s. Includes the special default skin plus all skins from .
///